<commit_before>package cete

import (
	"bytes"
	"log"
	"os"
	"strings"
	"sync/atomic"

	"github.com/1lann/badger"
	"github.com/1lann/msgpack"
)

// Bounds is the type for variables which represent a bound for Between.
type Bounds int

// Minimum and maximum values.
var (
	MinValue Bounds = (-1 << 63)
	MaxValue Bounds = (1 << 63) - 1
)

const prefetchSize = 2

// NewIndex creates a new index on the table, using the name as the Query.
// The index name must not be empty, and must be no more than 125 bytes
// long. ErrAlreadyExists will be returned if the index already exists.
//
// NewIndex may take a while if there are already values in the
// table, as it needs to index all the existing values in the table.
func (t *Table) NewIndex(name string) error {
	if name == "" || len(name) > 125 {
		return ErrBadIdentifier
	}

	t.db.configMutex.Lock()

	tableName := t.name()
	tableConfigKey := -1

	for key, table := range t.db.config.Tables {
		if table.TableName == tableName {
			tableConfigKey = key
			for _, index := range table.Indexes {
				if index.IndexName == name {
					t.db.configMutex.Unlock()
					return ErrAlreadyExists
				}
			}
		}
	}

	if tableConfigKey < 0 {
		t.db.configMutex.Unlock()
		return ErrNotFound
	}

	kv, err := t.db.newKV(Name(tableName), Name(name))
	if err != nil {
		t.db.configMutex.Unlock()
		return err
	}

	indexes := t.db.config.Tables[tableConfigKey].Indexes
	indexes = append(indexes, indexConfig{IndexName: name})
	t.db.config.Tables[tableConfigKey].Indexes = indexes
	if err = t.db.writeConfig(); err != nil {
		t.db.configMutex.Unlock()
		return err
	}

	t.db.configMutex.Unlock()

	idx := &Index{
		index: kv,
		table: t,
	}

	t.indexes[Name(name)] = idx

	if err = idx.indexValues(name); err != nil {
		log.Println("cete: error while indexing \""+
			idx.name()+"\", index likely corrupt:", err)
		return nil
	}

	return nil
}

func (i *Index) indexValues(name string) error {
	var total int64

	i.table.Between(MinValue, MaxValue).Do(func(key string, counter uint64, doc Document) error {
		last := atomic.AddInt64(&total, 1)
		if last%100000 == 0 {
			log.Println(last)
		}

		results, err := i.indexQuery(doc.data, name)
		if err != nil {
			return nil
		}

		for _, result := range results {
			err = i.addToIndex(valueToBytes(result), key)
			if err != nil {
				log.Println("cete: index error for index \""+name+"\":", err)
			}
		}

		return nil
	}, 20)

	return nil
}

func (i *Index) indexQuery(data []byte, query string) ([]interface{}, error) {
	rd := bytes.NewReader(data)
	dec := msgpack.NewDecoder(rd)

	compressed := i.table.keyToCompressed != nil

	queries := strings.Split(query, ",")
	if len(queries) > 1 {
		results := make([]interface{}, len(queries))

		var res []interface{}
		var err error
		for it, q := range queries {
			if compressed {
				res, err = dec.QueryCompressed(i.table.keyToC, q)
			} else {
				res, err = dec.Query(q)
			}
			if err != nil {
				return nil, err
			}

			rd.Reset(data)
			dec.Reset(rd)

			results[it] = res[0]
		}

		return []interface{}{results}, nil
	}

	if compressed {
		return dec.QueryCompressed(i.table.keyToC, query)
	}

	return dec.Query(query)
}

// One puts the first matching value with the index's key into dst. dst
// must either be a pointer or nil if you would like to only get the key/counter
// and check for existence. Note that indexes are non-unique, a single index key
// can map to multiple values. Use GetAll to get all such matching values.
func (i *Index) One(key interface{}, dst interface{}) (string, uint64, error) {
	r := i.GetAll(key)
	defer r.Close()

	if !r.Next() {
		if r.Error() == ErrEndOfRange {
			return "", 0, ErrNotFound
		}

		return "", 0, r.Error()
	}

	if dst == nil {
		return r.Key(), r.Counter(), nil
	}

	return r.Key(), r.Counter(), r.Decode(dst)
}

// GetAll returns all the matching values as a range for the provided index key.
func (i *Index) GetAll(key interface{}) *Range {
	var item badger.KVItem
	err := i.index.Get(valueToBytes(key), &item)
	if err != nil {
		return newRange(func() (string, []byte, uint64, error) {
			return "", nil, 0, err
		}, func() {}, nil)
	}

	itemValue := getItemValue(&item)
	if itemValue == nil {
		return newRange(func() (string, []byte, uint64, error) {
			return "", nil, 0, ErrEndOfRange
		}, func() {}, nil)
	}

	r, err := i.getAllValues(itemValue)
	if err != nil {
		return newRange(func() (string, []byte, uint64, error) {
			return "", nil, 0, err
		}, func() {}, nil)
	}
	return r
}

func (i *Index) getAllValues(indexValue []byte) (*Range, error) {
	var keys []string
	err := msgpack.Unmarshal(indexValue, &keys)
	if err != nil {
		log.Println("cete: corrupt index \""+i.name()+"\":", err)
		return nil, ErrIndexError
	}

	if len(keys) == 0 {
		log.Println("cete: corrupt index \""+i.name()+"\":", err)
		return nil, ErrIndexError
	}

	c := 0
	var value []byte
	var item badger.KVItem

	return newRange(func() (string, []byte, uint64, error) {
		for {
			if c >= len(keys) {
				return "", nil, 0, ErrEndOfRange
			}

			err = i.table.data.Get([]byte(keys[c]), &item)
			if err != nil {
				return "", nil, 0, err
			}

			itemValue := getItemValue(&item)
			if itemValue == nil {
				c++
				continue
			}

			value = make([]byte, len(itemValue))
			copy(value, itemValue)

			c++
			return keys[c-1], value, item.Counter(), nil
		}
	}, func() {}, i.table), nil
}

// Between returns a Range of documents between the lower and upper index values
// provided. The range will be sorted in ascending order by index value. You can
// reverse the sorting by specifying true to the optional reverse parameter.
// The bounds are inclusive on both ends. It is possible to have
// duplicate documents if the same document has multiple unique index values.
// To remove filter duplicate documents, use `Unique()` on the Range.
//
// You can use cete.MinValue and cete.MaxValue to specify minimum and maximum
// bound values.
func (i *Index) Between(lower, upper interface{}, reverse ...bool) *Range {
	if lower == MaxValue || upper == MinValue {
		return newRange(func() (string, []byte, uint64, error) {
			return "", nil, 0, ErrEndOfRange
		}, func() {}, nil)
	}

	shouldReverse := (len(reverse) > 0) && reverse[0]

	itOpts := badger.DefaultIteratorOptions
	itOpts.PrefetchSize = prefetchSize
	itOpts.Reverse = shouldReverse
	it := i.index.NewIterator(itOpts)

	upperBytes := valueToBytes(upper)
	lowerBytes := valueToBytes(lower)

	if !shouldReverse {
		if lower == MinValue {
			it.Rewind()
		} else {
			it.Seek(lowerBytes)
		}
	} else {
		if upper == MaxValue {
			it.Rewind()
		} else {
			it.Seek(upperBytes)
		}
	}

	var lastRange *Range

	return newRange(i.betweenNext(it, lastRange, shouldReverse, lower, upper),
		func() {
			if lastRange != nil {
				lastRange.Close()
			}
			it.Close()
		}, i.table)
}

// CountBetween returns the number of documents whose index values are
// within the given bounds. It is an optimized version of
// Between(lower, upper).Count(). Note that like with Between, double counting
// for documents is possible if the document has multiple unique index values.
func (i *Index) CountBetween(lower, upper interface{}) int64 {
	if lower == MaxValue || upper == MinValue {
		return 0
	}

	itOpts := badger.DefaultIteratorOptions
	itOpts.PrefetchSize = prefetchSize
	it := i.index.NewIterator(itOpts)

	upperBytes := valueToBytes(upper)
	lowerBytes := valueToBytes(lower)

	if lower == MinValue {
		it.Rewind()
	} else {
		it.Seek(lowerBytes)
	}

	var count int64

	for it.Valid() {
		if upper != MaxValue &&
			bytes.Compare(it.Item().Key(), upperBytes) > 0 {
			return count
		}

		itemValue := getItemValue(it.Item())
		if len(itemValue) < 5 {
			// Malformed index value my cause a panic here
			count += decodeArrayCount(itemValue)
		} else {
			count += decodeArrayCount(itemValue[:5])
		}

		it.Next()
	}

	return count
}

func decodeArrayCount(header []byte) int64 {
	if (header[0] >> 4) == 9 {
		return int64(header[0] & 0xf)
	} else if header[0] == 0xdc {
		return int64(header[1])<<8 + int64(header[2])
	} else if header[0] == 0xdd {
		return int64(header[1])<<24 + int64(header[2])<<16 +
			int64(header[3])<<8 + int64(header[4])
	}

	// not a valid array
	return 0
}

func (i *Index) betweenNext(it *badger.Iterator, lastRange *Range,
	shouldReverse bool, lower,
	upper interface{}) func() (string, []byte, uint64, error) {
	upperBytes := valueToBytes(upper)
	lowerBytes := valueToBytes(lower)

	var entry bufferEntry

	return func() (string, []byte, uint64, error) {
		if lastRange != nil {
			entry = <-lastRange.buffer
			if entry.err != ErrEndOfRange {
				return entry.key, entry.data, entry.counter, entry.err
			}

			lastRange.Close()
		}

		for it.Valid() {
			if !shouldReverse && upper != MaxValue &&
				bytes.Compare(it.Item().Key(), upperBytes) > 0 {
				return "", nil, 0, ErrEndOfRange
			} else if shouldReverse && lower != MinValue &&
				bytes.Compare(it.Item().Key(), lowerBytes) < 0 {
				return "", nil, 0, ErrEndOfRange
			}

			r, err := i.getAllValues(getItemValue(it.Item()))
			it.Next()
			if err != nil {
				continue
			}

			lastRange = r

			entry = <-lastRange.buffer
			if entry.err != ErrEndOfRange {
				return entry.key, entry.data, entry.counter, entry.err
			}

			lastRange.Close()
		}

		return "", nil, 0, ErrEndOfRange
	}
}

// All returns all the documents which have an index value. It is shorthand
// for Between(MinValue, MaxValue, reverse...)
func (i *Index) All(reverse ...bool) *Range {
	return i.Between(MinValue, MaxValue, reverse...)
}

// Drop drops the index from the table, deleting its folder from the disk.
// All further calls to the index will result in undefined behaviour.
// Note that table.Index("deleted index") will be nil.
func (i *Index) Drop() error {
	i.table.db.configMutex.Lock()
	defer i.table.db.configMutex.Unlock()

	tableName := i.table.name()

	var indexName string

	for idxName, index := range i.table.indexes {
		if index == i {
			indexName = string(idxName)
		}
	}

	if indexName == "" {
		return ErrNotFound
	}

tableLoop:
	for key, table := range i.table.db.config.Tables {
		if table.TableName == tableName {
			for indexKey, index := range table.Indexes {
				if index.IndexName == indexName {
					indexes := i.table.db.config.Tables[key].Indexes
					indexes = append(indexes[:indexKey], indexes[indexKey+1:]...)
					i.table.db.config.Tables[key].Indexes = indexes
					break tableLoop
				}
			}
		}
	}

	if err := i.table.db.writeConfig(); err != nil {
		return err
	}

	i.index.Close()

	delete(i.table.indexes, Name(indexName))

	return os.RemoveAll(i.table.db.path + "/" + Name(tableName).Hex() + "/" +
		Name(indexName).Hex())
}
<commit_msg>chore: remove debug message<commit_after>package cete

import (
	"bytes"
	"log"
	"os"
	"strings"

	"github.com/1lann/badger"
	"github.com/1lann/msgpack"
)

// Bounds is the type for variables which represent a bound for Between.
type Bounds int

// Minimum and maximum values.
var (
	MinValue Bounds = (-1 << 63)
	MaxValue Bounds = (1 << 63) - 1
)

const prefetchSize = 2

// NewIndex creates a new index on the table, using the name as the Query.
// The index name must not be empty, and must be no more than 125 bytes
// long. ErrAlreadyExists will be returned if the index already exists.
//
// NewIndex may take a while if there are already values in the
// table, as it needs to index all the existing values in the table.
func (t *Table) NewIndex(name string) error {
	if name == "" || len(name) > 125 {
		return ErrBadIdentifier
	}

	t.db.configMutex.Lock()

	tableName := t.name()
	tableConfigKey := -1

	for key, table := range t.db.config.Tables {
		if table.TableName == tableName {
			tableConfigKey = key
			for _, index := range table.Indexes {
				if index.IndexName == name {
					t.db.configMutex.Unlock()
					return ErrAlreadyExists
				}
			}
		}
	}

	if tableConfigKey < 0 {
		t.db.configMutex.Unlock()
		return ErrNotFound
	}

	kv, err := t.db.newKV(Name(tableName), Name(name))
	if err != nil {
		t.db.configMutex.Unlock()
		return err
	}

	indexes := t.db.config.Tables[tableConfigKey].Indexes
	indexes = append(indexes, indexConfig{IndexName: name})
	t.db.config.Tables[tableConfigKey].Indexes = indexes
	if err = t.db.writeConfig(); err != nil {
		t.db.configMutex.Unlock()
		return err
	}

	t.db.configMutex.Unlock()

	idx := &Index{
		index: kv,
		table: t,
	}

	t.indexes[Name(name)] = idx

	if err = idx.indexValues(name); err != nil {
		log.Println("cete: error while indexing \""+
			idx.name()+"\", index likely corrupt:", err)
		return nil
	}

	return nil
}

func (i *Index) indexValues(name string) error {
	i.table.Between(MinValue, MaxValue).Do(func(key string, counter uint64, doc Document) error {
		results, err := i.indexQuery(doc.data, name)
		if err != nil {
			return nil
		}

		for _, result := range results {
			err = i.addToIndex(valueToBytes(result), key)
			if err != nil {
				log.Println("cete: index error for index \""+name+"\":", err)
			}
		}

		return nil
	}, 20)

	return nil
}

func (i *Index) indexQuery(data []byte, query string) ([]interface{}, error) {
	rd := bytes.NewReader(data)
	dec := msgpack.NewDecoder(rd)

	compressed := i.table.keyToCompressed != nil

	queries := strings.Split(query, ",")
	if len(queries) > 1 {
		results := make([]interface{}, len(queries))

		var res []interface{}
		var err error
		for it, q := range queries {
			if compressed {
				res, err = dec.QueryCompressed(i.table.keyToC, q)
			} else {
				res, err = dec.Query(q)
			}
			if err != nil {
				return nil, err
			}

			rd.Reset(data)
			dec.Reset(rd)

			results[it] = res[0]
		}

		return []interface{}{results}, nil
	}

	if compressed {
		return dec.QueryCompressed(i.table.keyToC, query)
	}

	return dec.Query(query)
}

// One puts the first matching value with the index's key into dst. dst
// must either be a pointer or nil if you would like to only get the key/counter
// and check for existence. Note that indexes are non-unique, a single index key
// can map to multiple values. Use GetAll to get all such matching values.
func (i *Index) One(key interface{}, dst interface{}) (string, uint64, error) {
	r := i.GetAll(key)
	defer r.Close()

	if !r.Next() {
		if r.Error() == ErrEndOfRange {
			return "", 0, ErrNotFound
		}

		return "", 0, r.Error()
	}

	if dst == nil {
		return r.Key(), r.Counter(), nil
	}

	return r.Key(), r.Counter(), r.Decode(dst)
}

// GetAll returns all the matching values as a range for the provided index key.
func (i *Index) GetAll(key interface{}) *Range {
	var item badger.KVItem
	err := i.index.Get(valueToBytes(key), &item)
	if err != nil {
		return newRange(func() (string, []byte, uint64, error) {
			return "", nil, 0, err
		}, func() {}, nil)
	}

	itemValue := getItemValue(&item)
	if itemValue == nil {
		return newRange(func() (string, []byte, uint64, error) {
			return "", nil, 0, ErrEndOfRange
		}, func() {}, nil)
	}

	r, err := i.getAllValues(itemValue)
	if err != nil {
		return newRange(func() (string, []byte, uint64, error) {
			return "", nil, 0, err
		}, func() {}, nil)
	}
	return r
}

func (i *Index) getAllValues(indexValue []byte) (*Range, error) {
	var keys []string
	err := msgpack.Unmarshal(indexValue, &keys)
	if err != nil {
		log.Println("cete: corrupt index \""+i.name()+"\":", err)
		return nil, ErrIndexError
	}

	if len(keys) == 0 {
		log.Println("cete: corrupt index \""+i.name()+"\":", err)
		return nil, ErrIndexError
	}

	c := 0
	var value []byte
	var item badger.KVItem

	return newRange(func() (string, []byte, uint64, error) {
		for {
			if c >= len(keys) {
				return "", nil, 0, ErrEndOfRange
			}

			err = i.table.data.Get([]byte(keys[c]), &item)
			if err != nil {
				return "", nil, 0, err
			}

			itemValue := getItemValue(&item)
			if itemValue == nil {
				c++
				continue
			}

			value = make([]byte, len(itemValue))
			copy(value, itemValue)

			c++
			return keys[c-1], value, item.Counter(), nil
		}
	}, func() {}, i.table), nil
}

// Between returns a Range of documents between the lower and upper index values
// provided. The range will be sorted in ascending order by index value. You can
// reverse the sorting by specifying true to the optional reverse parameter.
// The bounds are inclusive on both ends. It is possible to have
// duplicate documents if the same document has multiple unique index values.
// To remove filter duplicate documents, use `Unique()` on the Range.
//
// You can use cete.MinValue and cete.MaxValue to specify minimum and maximum
// bound values.
func (i *Index) Between(lower, upper interface{}, reverse ...bool) *Range {
	if lower == MaxValue || upper == MinValue {
		return newRange(func() (string, []byte, uint64, error) {
			return "", nil, 0, ErrEndOfRange
		}, func() {}, nil)
	}

	shouldReverse := (len(reverse) > 0) && reverse[0]

	itOpts := badger.DefaultIteratorOptions
	itOpts.PrefetchSize = prefetchSize
	itOpts.Reverse = shouldReverse
	it := i.index.NewIterator(itOpts)

	upperBytes := valueToBytes(upper)
	lowerBytes := valueToBytes(lower)

	if !shouldReverse {
		if lower == MinValue {
			it.Rewind()
		} else {
			it.Seek(lowerBytes)
		}
	} else {
		if upper == MaxValue {
			it.Rewind()
		} else {
			it.Seek(upperBytes)
		}
	}

	var lastRange *Range

	return newRange(i.betweenNext(it, lastRange, shouldReverse, lower, upper),
		func() {
			if lastRange != nil {
				lastRange.Close()
			}
			it.Close()
		}, i.table)
}

// CountBetween returns the number of documents whose index values are
// within the given bounds. It is an optimized version of
// Between(lower, upper).Count(). Note that like with Between, double counting
// for documents is possible if the document has multiple unique index values.
func (i *Index) CountBetween(lower, upper interface{}) int64 {
	if lower == MaxValue || upper == MinValue {
		return 0
	}

	itOpts := badger.DefaultIteratorOptions
	itOpts.PrefetchSize = prefetchSize
	it := i.index.NewIterator(itOpts)

	upperBytes := valueToBytes(upper)
	lowerBytes := valueToBytes(lower)

	if lower == MinValue {
		it.Rewind()
	} else {
		it.Seek(lowerBytes)
	}

	var count int64

	for it.Valid() {
		if upper != MaxValue &&
			bytes.Compare(it.Item().Key(), upperBytes) > 0 {
			return count
		}

		itemValue := getItemValue(it.Item())
		if len(itemValue) < 5 {
			// Malformed index value my cause a panic here
			count += decodeArrayCount(itemValue)
		} else {
			count += decodeArrayCount(itemValue[:5])
		}

		it.Next()
	}

	return count
}

func decodeArrayCount(header []byte) int64 {
	if (header[0] >> 4) == 9 {
		return int64(header[0] & 0xf)
	} else if header[0] == 0xdc {
		return int64(header[1])<<8 + int64(header[2])
	} else if header[0] == 0xdd {
		return int64(header[1])<<24 + int64(header[2])<<16 +
			int64(header[3])<<8 + int64(header[4])
	}

	// not a valid array
	return 0
}

func (i *Index) betweenNext(it *badger.Iterator, lastRange *Range,
	shouldReverse bool, lower,
	upper interface{}) func() (string, []byte, uint64, error) {
	upperBytes := valueToBytes(upper)
	lowerBytes := valueToBytes(lower)

	var entry bufferEntry

	return func() (string, []byte, uint64, error) {
		if lastRange != nil {
			entry = <-lastRange.buffer
			if entry.err != ErrEndOfRange {
				return entry.key, entry.data, entry.counter, entry.err
			}

			lastRange.Close()
		}

		for it.Valid() {
			if !shouldReverse && upper != MaxValue &&
				bytes.Compare(it.Item().Key(), upperBytes) > 0 {
				return "", nil, 0, ErrEndOfRange
			} else if shouldReverse && lower != MinValue &&
				bytes.Compare(it.Item().Key(), lowerBytes) < 0 {
				return "", nil, 0, ErrEndOfRange
			}

			r, err := i.getAllValues(getItemValue(it.Item()))
			it.Next()
			if err != nil {
				continue
			}

			lastRange = r

			entry = <-lastRange.buffer
			if entry.err != ErrEndOfRange {
				return entry.key, entry.data, entry.counter, entry.err
			}

			lastRange.Close()
		}

		return "", nil, 0, ErrEndOfRange
	}
}

// All returns all the documents which have an index value. It is shorthand
// for Between(MinValue, MaxValue, reverse...)
func (i *Index) All(reverse ...bool) *Range {
	return i.Between(MinValue, MaxValue, reverse...)
}

// Drop drops the index from the table, deleting its folder from the disk.
// All further calls to the index will result in undefined behaviour.
// Note that table.Index("deleted index") will be nil.
func (i *Index) Drop() error {
	i.table.db.configMutex.Lock()
	defer i.table.db.configMutex.Unlock()

	tableName := i.table.name()

	var indexName string

	for idxName, index := range i.table.indexes {
		if index == i {
			indexName = string(idxName)
		}
	}

	if indexName == "" {
		return ErrNotFound
	}

tableLoop:
	for key, table := range i.table.db.config.Tables {
		if table.TableName == tableName {
			for indexKey, index := range table.Indexes {
				if index.IndexName == indexName {
					indexes := i.table.db.config.Tables[key].Indexes
					indexes = append(indexes[:indexKey], indexes[indexKey+1:]...)
					i.table.db.config.Tables[key].Indexes = indexes
					break tableLoop
				}
			}
		}
	}

	if err := i.table.db.writeConfig(); err != nil {
		return err
	}

	i.index.Close()

	delete(i.table.indexes, Name(indexName))

	return os.RemoveAll(i.table.db.path + "/" + Name(tableName).Hex() + "/" +
		Name(indexName).Hex())
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"net/url"
	"os"
	"strconv"
	"strings"
	"time"

	"code.google.com/p/go-uuid/uuid"
	"github.com/nlopes/slack"
	"gopkg.in/redis.v3"

	messages "github.com/foxelbox/foxbukkitslacklink/messages"
)

func (s *SlackLink) handleSlackMessage(msg *slack.MessageEvent) {
	info := s.slack.GetInfo()

	if msg.UserId == "" || msg.UserId == info.User.Id {
		return
	}

	if strings.HasPrefix(msg.Text, ".") {
		// Always handle commands, regardless of channel
		s.forwardSlackMessageToChatLink(msg)
		return
	}

	channel := info.GetChannelById(msg.ChannelId)

	if channel == nil {
		// We don't know about this channel.
		return
	}

	switch channel.Name {
	case "minecraft":
	case "minecraft-ops":
		msg.Text = "#" + msg.Text
	default:
		return
	}

	s.forwardSlackMessageToChatLink(msg)
}

func (s *SlackLink) forwardSlackMessageToChatLink(msg *slack.MessageEvent) {
	if strings.HasPrefix(msg.Text, ".") {
		msg.Text = "/" + msg.Text[1:]
	}

	minecraftAccount := s.getMinecraftFromSlack(msg.UserId)
	if minecraftAccount == nil {
		// They aren't associated with an account. Ignore.
		return
	}

	cmi := &ChatMessageIn{
		Server:  "Slack",
		Context: uuid.NewRandom(),
		Type:    messages.MessageType_TEXT,

		From: minecraftAccount,

		Timestamp: parseSlackTimestamp(msg.Timestamp),

		Contents: msg.Text,
	}

	s.addContextAssociation(cmi.Context, msg.ChannelId)

	s.chatLinkOut <- CMIToProtoCMI(cmi)
}

func (s *SlackLink) handlePresenceChange(ev *slack.PresenceChangeEvent) {
	mcID, err := s.redis.HGet("slacklinks:slack-to-mc", ev.UserId).Result()
	if err == redis.Nil {
		return
	} else if err != nil {
		panic(err)
	}

	if ev.Presence == "active" {
		s.redis.SAdd("playersOnline:Slack", mcID)
	} else {
		s.redis.SRem("playersOnline:Slack", mcID)
	}
}

func (s *SlackLink) handleSlackMessages() {
	defer s.wg.Done()

	for msg := range s.slackMessages {
		switch data := msg.Data.(type) {
		case *slack.MessageEvent:
			s.handleSlackMessage(data)
		case *slack.PresenceChangeEvent:
			s.handlePresenceChange(data)
		case slack.HelloEvent:
			s.refreshPresenceInfo()
		case *slack.SlackWSError:
			panic(data)
		default:
			//log.Printf("Unhandled message: %T", data)
		}
	}
}

func (s *SlackLink) refreshPresenceInfo() {
	users := s.slack.GetInfo().Users

	slackToMC, err := s.redis.HGetAllMap("slacklinks:slack-to-mc").Result()
	if err != nil {
		panic(err)
	}

	mcIDs := make([]string, 0, len(slackToMC))
	for _, user := range users {
		mcID, ok := slackToMC[user.Id]
		if !ok {
			continue
		}

		if user.Presence != "active" {
			continue
		}

		mcIDs = append(mcIDs, mcID)
	}

	s.redis.Del("playersOnline:Slack")
	s.redis.SAdd("playersOnline:Slack", mcIDs...)
}

func (s *SlackLink) receiveSlackMessages() {
	defer s.wg.Done()

	rtm, err := s.slack.StartRTM("", "https://slack.com")
	if err != nil {
		panic(err)
	}

	rtm.SetUserAsActive()

	go rtm.Keepalive(5 * time.Second)
	rtm.HandleIncomingEvents(s.slackMessages)

	log.Printf("WARNING: Slack WebSocket died.")
	os.Exit(2)
}

func (s *SlackLink) sendSlackMessages() {
	defer s.wg.Done()

	for msg := range s.slackOut {
		params := slack.NewPostMessageParameters()

		params.Markdown = !msg.DisableMarkdown

		if msg.As != nil {
			params.AsUser = false
			params.Username = msg.As.Name
			params.IconURL = "https://minotar.net/avatar/" + url.QueryEscape(strings.ToLower(msg.As.Name)) + "/48.png"
		} else {
			params.AsUser = true
		}

		s.slack.PostMessage(msg.To, msg.Message, params)
	}
}

type SlackMessage struct {
	To      string
	Message string

	As              *MinecraftPlayer
	DisableMarkdown bool
}

func parseSlackTimestamp(ts string) time.Time {
	f, _ := strconv.ParseFloat(ts, 64)

	tsInt := int64(f)
	leftover := f - float64(tsInt)
	leftoverNsec := int64((float64(time.Second) * leftover) / float64(time.Nanosecond))

	return time.Unix(tsInt, leftoverNsec)
}
<commit_msg>Fix encoding issues<commit_after>package main

import (
	"log"
	"net/url"
	"os"
	"strconv"
	"strings"
	"time"
	"html"

	"code.google.com/p/go-uuid/uuid"
	"github.com/nlopes/slack"
	"gopkg.in/redis.v3"

	messages "github.com/foxelbox/foxbukkitslacklink/messages"
)

func (s *SlackLink) handleSlackMessage(msg *slack.MessageEvent) {
	info := s.slack.GetInfo()

	if msg.UserId == "" || msg.UserId == info.User.Id {
		return
	}

	msg.Text = html.UnescapeString(msg.Text)

	if strings.HasPrefix(msg.Text, ".") {
		// Always handle commands, regardless of channel
		s.forwardSlackMessageToChatLink(msg)
		return
	}

	channel := info.GetChannelById(msg.ChannelId)

	if channel == nil {
		// We don't know about this channel.
		return
	}

	switch channel.Name {
	case "minecraft":
	case "minecraft-ops":
		msg.Text = "#" + msg.Text
	default:
		return
	}

	s.forwardSlackMessageToChatLink(msg)
}

func (s *SlackLink) forwardSlackMessageToChatLink(msg *slack.MessageEvent) {
	if strings.HasPrefix(msg.Text, ".") {
		msg.Text = "/" + msg.Text[1:]
	}

	minecraftAccount := s.getMinecraftFromSlack(msg.UserId)
	if minecraftAccount == nil {
		// They aren't associated with an account. Ignore.
		return
	}

	cmi := &ChatMessageIn{
		Server:  "Slack",
		Context: uuid.NewRandom(),
		Type:    messages.MessageType_TEXT,

		From: minecraftAccount,

		Timestamp: parseSlackTimestamp(msg.Timestamp),

		Contents: msg.Text,
	}

	s.addContextAssociation(cmi.Context, msg.ChannelId)

	s.chatLinkOut <- CMIToProtoCMI(cmi)
}

func (s *SlackLink) handlePresenceChange(ev *slack.PresenceChangeEvent) {
	mcID, err := s.redis.HGet("slacklinks:slack-to-mc", ev.UserId).Result()
	if err == redis.Nil {
		return
	} else if err != nil {
		panic(err)
	}

	if ev.Presence == "active" {
		s.redis.SAdd("playersOnline:Slack", mcID)
	} else {
		s.redis.SRem("playersOnline:Slack", mcID)
	}
}

func (s *SlackLink) handleSlackMessages() {
	defer s.wg.Done()

	for msg := range s.slackMessages {
		switch data := msg.Data.(type) {
		case *slack.MessageEvent:
			s.handleSlackMessage(data)
		case *slack.PresenceChangeEvent:
			s.handlePresenceChange(data)
		case slack.HelloEvent:
			s.refreshPresenceInfo()
		case *slack.SlackWSError:
			panic(data)
		default:
			//log.Printf("Unhandled message: %T", data)
		}
	}
}

func (s *SlackLink) refreshPresenceInfo() {
	users := s.slack.GetInfo().Users

	slackToMC, err := s.redis.HGetAllMap("slacklinks:slack-to-mc").Result()
	if err != nil {
		panic(err)
	}

	mcIDs := make([]string, 0, len(slackToMC))
	for _, user := range users {
		mcID, ok := slackToMC[user.Id]
		if !ok {
			continue
		}

		if user.Presence != "active" {
			continue
		}

		mcIDs = append(mcIDs, mcID)
	}

	s.redis.Del("playersOnline:Slack")
	s.redis.SAdd("playersOnline:Slack", mcIDs...)
}

func (s *SlackLink) receiveSlackMessages() {
	defer s.wg.Done()

	rtm, err := s.slack.StartRTM("", "https://slack.com")
	if err != nil {
		panic(err)
	}

	rtm.SetUserAsActive()

	go rtm.Keepalive(5 * time.Second)
	rtm.HandleIncomingEvents(s.slackMessages)

	log.Printf("WARNING: Slack WebSocket died.")
	os.Exit(2)
}

func (s *SlackLink) sendSlackMessages() {
	defer s.wg.Done()

	for msg := range s.slackOut {
		params := slack.NewPostMessageParameters()

		params.Markdown = !msg.DisableMarkdown

		if msg.As != nil {
			params.AsUser = false
			params.Username = msg.As.Name
			params.IconURL = "https://minotar.net/avatar/" + url.QueryEscape(strings.ToLower(msg.As.Name)) + "/48.png"
		} else {
			params.AsUser = true
		}

		s.slack.PostMessage(msg.To, msg.Message, params)
	}
}

type SlackMessage struct {
	To      string
	Message string

	As              *MinecraftPlayer
	DisableMarkdown bool
}

func parseSlackTimestamp(ts string) time.Time {
	f, _ := strconv.ParseFloat(ts, 64)

	tsInt := int64(f)
	leftover := f - float64(tsInt)
	leftoverNsec := int64((float64(time.Second) * leftover) / float64(time.Nanosecond))

	return time.Unix(tsInt, leftoverNsec)
}
<|endoftext|>


<commit_before>package sleapi

import (
	"fmt"
	//"io"
	"net/http"
	"os"
)

type Napper func(w ResponseWriter, req *http.Request)

type Sleep struct {
	Port   string
	Router *Router
	Naps   []Napper
}

func Sleeper() *Sleep {
	r := NewRouter()
	s := &Sleep{Port: "3030", Router: r}
	s.Naps = make([]Napper, 0)

	s.Naps = append(s.Naps, Static("/static/"))
	s.Naps = append(s.Naps, r.FindRoute)

	return s
}

// hello world, the web server
func (this *Sleep) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	//io.WriteString(w, "hello, world!\n")
	fmt.Println("Server: ", req.URL.Path)

	for _, h := range this.Naps {
		rw := NewResponseWriter(w)
		h(rw, req)
		if rw.Written() {
			break
		}
	}

	//this.Router.FindRoute(w, req)
}

func (this *Sleep) Run() {
	port := os.Getenv("PORT")
	if port == "" {
		port = "3030"
	}

	err := http.ListenAndServe(":"+port, this)
	if err != nil {
		fmt.Println("ListenAndServer Error: ", err.Error())
	}
}
<commit_msg>Printing raw query string<commit_after>package sleapi

import (
	"fmt"
	//"io"
	"net/http"
	"os"
)

type Napper func(w ResponseWriter, req *http.Request)

type Sleep struct {
	Port   string
	Router *Router
	Naps   []Napper
}

func Sleeper() *Sleep {
	r := NewRouter()
	s := &Sleep{Port: "3030", Router: r}
	s.Naps = make([]Napper, 0)

	s.Naps = append(s.Naps, Static("/static/"))
	s.Naps = append(s.Naps, r.FindRoute)

	return s
}

// hello world, the web server
func (this *Sleep) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	//io.WriteString(w, "hello, world!\n")
	fmt.Println("Server: ", req.URL.Path)
	fmt.Println("Server (raw): ", req.URL.RawQuery)

	for _, h := range this.Naps {
		rw := NewResponseWriter(w)
		h(rw, req)
		if rw.Written() {
			break
		}
	}

	//this.Router.FindRoute(w, req)
}

func (this *Sleep) Run() {
	port := os.Getenv("PORT")
	if port == "" {
		port = "3030"
	}

	err := http.ListenAndServe(":"+port, this)
	if err != nil {
		fmt.Println("ListenAndServer Error: ", err.Error())
	}
}
<|endoftext|>


<commit_before>package sloth

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
	"time"
)

// for mock in this package
var timeNow = time.Now

// Make sure Logger always implements io.Writer
var _ io.WriteCloser = (*File)(nil)

// Logger writes specific to Filename
type File struct {
	Filename string
	Every    time.Duration

	file      *os.File
	createdAt time.Time
}

func (f *File) Write(b []byte) (n int, err error) {
	if f.file == nil {
		f.file, err = openNew(f.Filename, false)
		f.createdAt = timeNow()
	}

	if now := timeNow(); f.Every > 0 && now.Sub(f.createdAt) >= f.Every {
		backup(f)
	}
	return f.file.Write(b)
}

func (f *File) Close() error {
	return f.file.Close()
}

func (f *File) Name() string { return f.file.Name() }

func backup(f *File) {
	name := f.Name()
	f.Close()

	backupfile, err := openNew(name, true)
	if err != nil {
		return
	}
	defer backupfile.Close()

	f.file, _ = openNew(name, false)
	f.createdAt = timeNow()
	if _, err := io.Copy(backupfile, f.file); err != nil {
		panic(err)
	}
}

func exist(filename string) bool {
	_, err := os.Stat(filename)
	return !os.IsNotExist(err)
}

func openNew(filename string, stamptime bool) (*os.File, error) {
	if !stamptime {
		return os.OpenFile(filename, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0644)
	}

	dir := filepath.Dir(filename)
	ext := filepath.Ext(filename)
	name := filepath.Base(filename)
	prefix := name[:len(name)-len(ext)]

	if !exist(dir) {
		os.MkdirAll(dir, 0744)
	}

	return os.OpenFile(filepath.Join(dir, fmt.Sprintf("%s_%s%s", prefix, timeNow().Format("20060102_1504"), ext)), os.O_CREATE|os.O_WRONLY, 0644)
}
<commit_msg>Add godoc comment<commit_after>package sloth

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
	"time"
)

// for mock in this package
var timeNow = time.Now

// Make sure Logger always implements io.Writer
var _ io.WriteCloser = (*File)(nil)

// File wrap os.File to manage rotate logic
type File struct {
	Filename string
	Every    time.Duration

	file      *os.File
	createdAt time.Time
}

// Write data to the file
func (f *File) Write(b []byte) (n int, err error) {
	if f.file == nil {
		f.file, err = openNew(f.Filename, false)
		f.createdAt = timeNow()
	}

	if now := timeNow(); f.Every > 0 && now.Sub(f.createdAt) >= f.Every {
		backup(f)
	}
	return f.file.Write(b)
}

// Close the file
func (f *File) Close() error {
	return f.file.Close()
}

// Name return file name
func (f *File) Name() string { return f.file.Name() }

func backup(f *File) {
	name := f.Name()
	f.Close()

	backupfile, err := openNew(name, true)
	if err != nil {
		return
	}
	defer backupfile.Close()

	f.file, _ = openNew(name, false)
	f.createdAt = timeNow()
	if _, err := io.Copy(backupfile, f.file); err != nil {
		panic(err)
	}
}

func exist(filename string) bool {
	_, err := os.Stat(filename)
	return !os.IsNotExist(err)
}

func openNew(filename string, stamptime bool) (*os.File, error) {
	if !stamptime {
		return os.OpenFile(filename, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0644)
	}

	dir := filepath.Dir(filename)
	ext := filepath.Ext(filename)
	name := filepath.Base(filename)
	prefix := name[:len(name)-len(ext)]

	if !exist(dir) {
		os.MkdirAll(dir, 0744)
	}

	return os.OpenFile(filepath.Join(dir, fmt.Sprintf("%s_%s%s", prefix, timeNow().Format("20060102_1504"), ext)), os.O_CREATE|os.O_WRONLY, 0644)
}
<|endoftext|>


<commit_before>// Copyright 2017 The go-daq 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 smbus provides access to the System Management bus, over i2c.
//
// http://www.smbus.org/.
package smbus

import (
	"fmt"
	"os"
	"syscall"
	"unsafe"
)

const (
	i2cSlave      = 0x0703
	i2cSlaveForce = 0x0706
	i2cFuncs      = 0x0705
	i2cSMBus      = 0x0720

	i2cSMBusWrite uint8 = 0
	i2cSMBusRead  uint8 = 1

	// size identifiers
	i2cSMBusByteData     uint32 = 2
	i2cSMBusWordData     uint32 = 3
	i2cSMBusBlockData    uint32 = 5
	i2cSMBusI2CBlockData uint32 = 8
	i2cSMBusBlockMax     uint32 = 32
)

// Conn is connection to a i2c device.
type Conn struct {
	f *os.File
}

// Open opens a connection to the i2c bus number at address addr.
func Open(bus int, addr uint8) (*Conn, error) {
	f, err := os.OpenFile(fmt.Sprintf("/dev/i2c-%d", bus), os.O_RDWR, 0600)
	if err != nil {
		return nil, err
	}
	if err := ioctl(f.Fd(), i2cSlave, uintptr(addr)); err != nil {
		return nil, err
	}
	return &Conn{f: f}, nil
}

// Write sends buf to the remote i2c device.
// The interpretation of the message is implementation dependant.
func (c *Conn) Write(buf []byte) (int, error) {
	return c.f.Write(buf)
}

// WriteByte sends a single byte to the remote i2c device.
// The interpretation of the message is implementation dependant.
func (c *Conn) WriteByte(b byte) (int, error) {
	var buf [1]byte
	buf[0] = b
	return c.f.Write(buf[:])
}

// Read reads data from the remote i2c device into p.
func (c *Conn) Read(p []byte) (int, error) {
	return c.f.Read(p)
}

// Close closes the connection to the remote i2c device.
func (c *Conn) Close() error {
	return c.f.Close()
}

// ReadReg reads a single byte from a designated register.
func (c *Conn) ReadReg(addr, reg uint8) (uint8, error) {
	if err := c.addr(addr); err != nil {
		return 0, err
	}

	var v uint8
	cmd := i2cCmd{
		rw:  i2cSMBusRead,
		cmd: reg,
		len: i2cSMBusByteData,
		ptr: unsafe.Pointer(&v),
	}
	ptr := unsafe.Pointer(&cmd)
	err := ioctl(c.f.Fd(), i2cSMBus, uintptr(ptr))
	return v, err
}

// WriteReg writes a single byte v to a designated register.
func (c *Conn) WriteReg(addr, reg, v uint8) error {
	if err := c.addr(addr); err != nil {
		return err
	}

	cmd := i2cCmd{
		rw:  i2cSMBusWrite,
		cmd: reg,
		len: i2cSMBusByteData,
		ptr: unsafe.Pointer(&v),
	}
	ptr := unsafe.Pointer(&cmd)
	return ioctl(c.f.Fd(), i2cSMBus, uintptr(ptr))
}

// ReadWord reads a 2-bytes word from a designated register.
func (c *Conn) ReadWord(addr, reg uint8) (uint16, error) {
	if err := c.addr(addr); err != nil {
		return 0, err
	}

	var v uint16
	cmd := i2cCmd{
		rw:  i2cSMBusRead,
		cmd: reg,
		len: i2cSMBusWordData,
		ptr: unsafe.Pointer(&v),
	}
	ptr := unsafe.Pointer(&cmd)
	err := ioctl(c.f.Fd(), i2cSMBus, uintptr(ptr))
	return v, err
}

// WriteWord writes a 2-bytes word v to a designated register.
func (c *Conn) WriteWord(addr, reg uint8, v uint16) error {
	if err := c.addr(addr); err != nil {
		return err
	}

	cmd := i2cCmd{
		rw:  i2cSMBusWrite,
		cmd: reg,
		len: i2cSMBusWordData,
		ptr: unsafe.Pointer(&v),
	}
	ptr := unsafe.Pointer(&cmd)
	return ioctl(c.f.Fd(), i2cSMBus, uintptr(ptr))
}

func (c *Conn) addr(addr uint8) error {
	return ioctl(c.f.Fd(), i2cSlave, uintptr(addr))
}

func ioctl(fd, cmd, arg uintptr) (err error) {
	_, _, e1 := syscall.Syscall6(syscall.SYS_IOCTL, fd, cmd, arg, 0, 0, 0)
	if e1 != 0 {
		err = e1
	}
	return
}

type i2cCmd struct {
	rw  uint8
	cmd uint8
	len uint32
	ptr unsafe.Pointer
}
<commit_msg>smbus: add R/W-I2C-block-data support<commit_after>// Copyright 2017 The go-daq 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 smbus provides access to the System Management bus, over i2c.
//
// http://www.smbus.org/.
package smbus

import (
	"errors"
	"fmt"
	"os"
	"syscall"
	"unsafe"
)

const (
	i2cSlave      = 0x0703
	i2cSlaveForce = 0x0706
	i2cFuncs      = 0x0705
	i2cSMBus      = 0x0720

	i2cSMBusWrite uint8 = 0
	i2cSMBusRead  uint8 = 1

	// size identifiers
	i2cSMBusByteData     uint32 = 2
	i2cSMBusWordData     uint32 = 3
	i2cSMBusBlockData    uint32 = 5
	i2cSMBusI2CBlockData uint32 = 8
	i2cSMBusBlockMax     uint32 = 32
)

var (
	errSMBusBlockDataMax = errors.New("smbus: buffer slice too big")
)

// Conn is connection to a i2c device.
type Conn struct {
	f *os.File
}

// Open opens a connection to the i2c bus number at address addr.
func Open(bus int, addr uint8) (*Conn, error) {
	f, err := os.OpenFile(fmt.Sprintf("/dev/i2c-%d", bus), os.O_RDWR, 0600)
	if err != nil {
		return nil, err
	}
	if err := ioctl(f.Fd(), i2cSlave, uintptr(addr)); err != nil {
		return nil, err
	}
	return &Conn{f: f}, nil
}

// Write sends buf to the remote i2c device.
// The interpretation of the message is implementation dependant.
func (c *Conn) Write(buf []byte) (int, error) {
	return c.f.Write(buf)
}

// WriteByte sends a single byte to the remote i2c device.
// The interpretation of the message is implementation dependant.
func (c *Conn) WriteByte(b byte) (int, error) {
	var buf [1]byte
	buf[0] = b
	return c.f.Write(buf[:])
}

// Read reads data from the remote i2c device into p.
func (c *Conn) Read(p []byte) (int, error) {
	return c.f.Read(p)
}

// Close closes the connection to the remote i2c device.
func (c *Conn) Close() error {
	return c.f.Close()
}

// ReadReg reads a single byte from a designated register.
func (c *Conn) ReadReg(addr, reg uint8) (uint8, error) {
	if err := c.addr(addr); err != nil {
		return 0, err
	}

	var v uint8
	cmd := i2cCmd{
		rw:  i2cSMBusRead,
		cmd: reg,
		len: i2cSMBusByteData,
		ptr: unsafe.Pointer(&v),
	}
	ptr := unsafe.Pointer(&cmd)
	err := ioctl(c.f.Fd(), i2cSMBus, uintptr(ptr))
	return v, err
}

// WriteReg writes a single byte v to a designated register.
func (c *Conn) WriteReg(addr, reg, v uint8) error {
	if err := c.addr(addr); err != nil {
		return err
	}

	cmd := i2cCmd{
		rw:  i2cSMBusWrite,
		cmd: reg,
		len: i2cSMBusByteData,
		ptr: unsafe.Pointer(&v),
	}
	ptr := unsafe.Pointer(&cmd)
	return ioctl(c.f.Fd(), i2cSMBus, uintptr(ptr))
}

// ReadWord reads a 2-bytes word from a designated register.
func (c *Conn) ReadWord(addr, reg uint8) (uint16, error) {
	if err := c.addr(addr); err != nil {
		return 0, err
	}

	var v uint16
	cmd := i2cCmd{
		rw:  i2cSMBusRead,
		cmd: reg,
		len: i2cSMBusWordData,
		ptr: unsafe.Pointer(&v),
	}
	ptr := unsafe.Pointer(&cmd)
	err := ioctl(c.f.Fd(), i2cSMBus, uintptr(ptr))
	return v, err
}

// WriteWord writes a 2-bytes word v to a designated register.
func (c *Conn) WriteWord(addr, reg uint8, v uint16) error {
	if err := c.addr(addr); err != nil {
		return err
	}

	cmd := i2cCmd{
		rw:  i2cSMBusWrite,
		cmd: reg,
		len: i2cSMBusWordData,
		ptr: unsafe.Pointer(&v),
	}
	ptr := unsafe.Pointer(&cmd)
	return ioctl(c.f.Fd(), i2cSMBus, uintptr(ptr))
}

// ReadBlockData reads len(buf) data into the byte slice, from the designated register.
func (c *Conn) ReadBlockData(addr, reg uint8, buf []byte) error {
	if len(buf) > int(i2cSMBusBlockMax) {
		return errSMBusBlockDataMax
	}

	if err := c.addr(addr); err != nil {
		return err
	}

	data := make([]byte, len(buf)+1, i2cSMBusBlockMax+2)
	data[0] = byte(len(buf))
	cmd := i2cCmd{
		rw:  i2cSMBusRead,
		cmd: reg,
		len: i2cSMBusI2CBlockData,
		ptr: unsafe.Pointer(&data[0]),
	}
	ptr := unsafe.Pointer(&cmd)
	err := ioctl(c.f.Fd(), i2cSMBus, uintptr(ptr))
	if err != nil {
		return err
	}

	copy(buf[:len(buf)], data[1:len(buf)+1])
	return nil
}

// WriteBlockData writes the buf byte slice to a designated register.
func (c *Conn) WriteBlockData(addr, reg uint8, buf []byte) error {
	if len(buf) > int(i2cSMBusBlockMax) {
		return errSMBusBlockDataMax
	}

	if err := c.addr(addr); err != nil {
		return err
	}

	data := make([]byte, 1+len(buf))
	data[0] = byte(len(buf))
	copy(data[1:], buf)

	cmd := i2cCmd{
		rw:  i2cSMBusWrite,
		cmd: reg,
		len: i2cSMBusI2CBlockData,
		ptr: unsafe.Pointer(&data[0]),
	}
	ptr := unsafe.Pointer(&cmd)
	return ioctl(c.f.Fd(), i2cSMBus, uintptr(ptr))
}

func (c *Conn) addr(addr uint8) error {
	return ioctl(c.f.Fd(), i2cSlave, uintptr(addr))
}

func ioctl(fd, cmd, arg uintptr) (err error) {
	_, _, e1 := syscall.Syscall6(syscall.SYS_IOCTL, fd, cmd, arg, 0, 0, 0)
	if e1 != 0 {
		err = e1
	}
	return
}

type i2cCmd struct {
	rw  uint8
	cmd uint8
	len uint32
	ptr unsafe.Pointer
}
<|endoftext|>


<commit_before>// Package smtpd implements a SMTP server with support for STARTTLS, authentication (PLAIN/LOGIN) and optional restrictions on the different stages of the SMTP session.
package smtpd

import (
	"bufio"
	"crypto/tls"
	"fmt"
	"log"
	"net"
	"os"
	"time"
)

// Server defines the parameters for running the SMTP server
type Server struct {
	Addr           string // Address to listen on when using ListenAndServe (default: "127.0.0.1:10025")
	WelcomeMessage string // Initial server banner (default: "<hostname> ESMTP ready.")

	ReadTimeout  time.Duration // Socket timeout for read operations (default: 60s)
	WriteTimeout time.Duration // Socket timeout for write operations (default: 60s)

	MaxMessageSize int // Max message size in bytes (default: 10240000)
	MaxConnections int // Max concurrent connections, use -1 to disable (default: 100)

	// New e-mails are handed off to this function.
	// Can be left empty for a NOOP server.
	// If an error is returned, it will be reported in the SMTP session.
	Handler func(peer Peer, env Envelope) error

	// Enable various checks during the SMTP session.
	// Can be left empty for no restrictions.
	// If an error is returned, it will be reported in the SMTP session.
	HeloChecker      func(peer Peer) error              // Called after HELO/EHLO.
	SenderChecker    func(peer Peer, addr string) error // Called after MAIL FROM.
	RecipientChecker func(peer Peer, addr string) error // Called after each RCPT TO.

	// Enable PLAIN/LOGIN authentication, only available after STARTTLS.
	// Can be left empty for no authentication support.
	Authenticator func(peer Peer, username, password string) error

	TLSConfig *tls.Config // Enable STARTTLS support
	ForceTLS  bool        // Force STARTTLS usage
}

// Peer represents the client connecting to the server
type Peer struct {
	HeloName string   // Server name used in HELO/EHLO command
	Username string   // Username from authentication, if authenticated
	Password string   // Password from authentication, if authenticated
	Addr     net.Addr // Network address
}

// Envelope holds a message
type Envelope struct {
	Sender     string
	Recipients []string
	Data       []byte
}

type session struct {
	server *Server

	peer     Peer
	envelope *Envelope

	conn net.Conn

	reader  *bufio.Reader
	writer  *bufio.Writer
	scanner *bufio.Scanner

	tls bool
}

func (srv *Server) newSession(c net.Conn) (s *session, err error) {

	s = &session{
		server: srv,
		conn:   c,
		reader: bufio.NewReader(c),
		writer: bufio.NewWriter(c),
		peer:   Peer{Addr: c.RemoteAddr()},
	}

	s.scanner = bufio.NewScanner(s.reader)

	return s, nil

}

// ListenAndServe starts the SMTP server and listens on the address provided in Server.Addr
func (srv *Server) ListenAndServe() error {

	srv.configureDefaults()

	l, err := net.Listen("tcp", srv.Addr)
	if err != nil {
		return err
	}

	return srv.Serve(l)
}

// Serve starts the SMTP server and listens on the Listener provided
func (srv *Server) Serve(l net.Listener) error {

	srv.configureDefaults()

	defer l.Close()

	var limiter chan struct{}

	if srv.MaxConnections > 0 {
		limiter = make(chan struct{}, srv.MaxConnections)
	} else {
		limiter = nil
	}

	for {

		conn, e := l.Accept()
		if e != nil {
			if ne, ok := e.(net.Error); ok && ne.Temporary() {
				time.Sleep(time.Second)
				continue
			}
			return e
		}

		session, err := srv.newSession(conn)
		if err != nil {
			continue
		}

		if limiter != nil {
			go func() {
				select {
				case limiter <- struct{}{}:
					session.serve()
					<-limiter
				default:
					session.reject()
				}
			}()
		} else {
			go session.serve()
		}

	}

}

func (srv *Server) configureDefaults() {

	if srv.MaxMessageSize == 0 {
		srv.MaxMessageSize = 10240000
	}

	if srv.MaxConnections == 0 {
		srv.MaxConnections = 100
	}

	if srv.ReadTimeout == 0 {
		srv.ReadTimeout = time.Second * 60
	}

	if srv.WriteTimeout == 0 {
		srv.WriteTimeout = time.Second * 60
	}

	if srv.ForceTLS && srv.TLSConfig == nil {
		log.Fatal("Cannot use ForceTLS with no TLSConfig")
	}

	if srv.Addr == "" {
		srv.Addr = "127.0.0.1:10025"
	}

	if srv.WelcomeMessage == "" {

		hostname, err := os.Hostname()

		if err != nil {
			log.Fatal("Couldn't determine hostname: %s", err)
		}

		srv.WelcomeMessage = fmt.Sprintf("%s ESMTP ready.", hostname)

	}

}

func (session *session) serve() {

	defer session.close()

	session.reply(220, session.server.WelcomeMessage)

	for session.scanner.Scan() {
		session.handle(session.scanner.Text())
	}

}

func (session *session) reject() {
	session.reply(450, "Too busy. Try again later.")
	session.close()
}

func (session *session) reply(code int, message string) {

	fmt.Fprintf(session.writer, "%d %s\r\n", code, message)

	session.conn.SetWriteDeadline(time.Now().Add(session.server.WriteTimeout))
	session.writer.Flush()

	session.conn.SetReadDeadline(time.Now().Add(session.server.ReadTimeout))

}

func (session *session) error(err error) {
	session.reply(502, fmt.Sprintf("%s", err))
}

func (session *session) extensions() []string {

	extensions := []string{
		fmt.Sprintf("SIZE %d", session.server.MaxMessageSize),
		"8BITMIME",
	}

	if session.server.TLSConfig != nil && !session.tls {
		extensions = append(extensions, "STARTTLS")
	}

	if session.server.Authenticator != nil && session.tls {
		extensions = append(extensions, "AUTH PLAIN LOGIN")
	}

	return extensions

}

func (session *session) deliver() error {
	if session.server.Handler != nil {
		return session.server.Handler(session.peer, *session.envelope)
	}
	return nil
}

func (session *session) close() {
	session.writer.Flush()
	session.conn.Close()
}
<commit_msg>newSession cannot fail.<commit_after>// Package smtpd implements a SMTP server with support for STARTTLS, authentication (PLAIN/LOGIN) and optional restrictions on the different stages of the SMTP session.
package smtpd

import (
	"bufio"
	"crypto/tls"
	"fmt"
	"log"
	"net"
	"os"
	"time"
)

// Server defines the parameters for running the SMTP server
type Server struct {
	Addr           string // Address to listen on when using ListenAndServe (default: "127.0.0.1:10025")
	WelcomeMessage string // Initial server banner (default: "<hostname> ESMTP ready.")

	ReadTimeout  time.Duration // Socket timeout for read operations (default: 60s)
	WriteTimeout time.Duration // Socket timeout for write operations (default: 60s)

	MaxMessageSize int // Max message size in bytes (default: 10240000)
	MaxConnections int // Max concurrent connections, use -1 to disable (default: 100)

	// New e-mails are handed off to this function.
	// Can be left empty for a NOOP server.
	// If an error is returned, it will be reported in the SMTP session.
	Handler func(peer Peer, env Envelope) error

	// Enable various checks during the SMTP session.
	// Can be left empty for no restrictions.
	// If an error is returned, it will be reported in the SMTP session.
	HeloChecker      func(peer Peer) error              // Called after HELO/EHLO.
	SenderChecker    func(peer Peer, addr string) error // Called after MAIL FROM.
	RecipientChecker func(peer Peer, addr string) error // Called after each RCPT TO.

	// Enable PLAIN/LOGIN authentication, only available after STARTTLS.
	// Can be left empty for no authentication support.
	Authenticator func(peer Peer, username, password string) error

	TLSConfig *tls.Config // Enable STARTTLS support
	ForceTLS  bool        // Force STARTTLS usage
}

// Peer represents the client connecting to the server
type Peer struct {
	HeloName string   // Server name used in HELO/EHLO command
	Username string   // Username from authentication, if authenticated
	Password string   // Password from authentication, if authenticated
	Addr     net.Addr // Network address
}

// Envelope holds a message
type Envelope struct {
	Sender     string
	Recipients []string
	Data       []byte
}

type session struct {
	server *Server

	peer     Peer
	envelope *Envelope

	conn net.Conn

	reader  *bufio.Reader
	writer  *bufio.Writer
	scanner *bufio.Scanner

	tls bool
}

func (srv *Server) newSession(c net.Conn) (s *session) {

	s = &session{
		server: srv,
		conn:   c,
		reader: bufio.NewReader(c),
		writer: bufio.NewWriter(c),
		peer:   Peer{Addr: c.RemoteAddr()},
	}

	s.scanner = bufio.NewScanner(s.reader)

	return

}

// ListenAndServe starts the SMTP server and listens on the address provided in Server.Addr
func (srv *Server) ListenAndServe() error {

	srv.configureDefaults()

	l, err := net.Listen("tcp", srv.Addr)
	if err != nil {
		return err
	}

	return srv.Serve(l)
}

// Serve starts the SMTP server and listens on the Listener provided
func (srv *Server) Serve(l net.Listener) error {

	srv.configureDefaults()

	defer l.Close()

	var limiter chan struct{}

	if srv.MaxConnections > 0 {
		limiter = make(chan struct{}, srv.MaxConnections)
	} else {
		limiter = nil
	}

	for {

		conn, e := l.Accept()
		if e != nil {
			if ne, ok := e.(net.Error); ok && ne.Temporary() {
				time.Sleep(time.Second)
				continue
			}
			return e
		}

		session := srv.newSession(conn)

		if limiter != nil {
			go func() {
				select {
				case limiter <- struct{}{}:
					session.serve()
					<-limiter
				default:
					session.reject()
				}
			}()
		} else {
			go session.serve()
		}

	}

}

func (srv *Server) configureDefaults() {

	if srv.MaxMessageSize == 0 {
		srv.MaxMessageSize = 10240000
	}

	if srv.MaxConnections == 0 {
		srv.MaxConnections = 100
	}

	if srv.ReadTimeout == 0 {
		srv.ReadTimeout = time.Second * 60
	}

	if srv.WriteTimeout == 0 {
		srv.WriteTimeout = time.Second * 60
	}

	if srv.ForceTLS && srv.TLSConfig == nil {
		log.Fatal("Cannot use ForceTLS with no TLSConfig")
	}

	if srv.Addr == "" {
		srv.Addr = "127.0.0.1:10025"
	}

	if srv.WelcomeMessage == "" {

		hostname, err := os.Hostname()

		if err != nil {
			log.Fatal("Couldn't determine hostname: %s", err)
		}

		srv.WelcomeMessage = fmt.Sprintf("%s ESMTP ready.", hostname)

	}

}

func (session *session) serve() {

	defer session.close()

	session.reply(220, session.server.WelcomeMessage)

	for session.scanner.Scan() {
		session.handle(session.scanner.Text())
	}

}

func (session *session) reject() {
	session.reply(450, "Too busy. Try again later.")
	session.close()
}

func (session *session) reply(code int, message string) {

	fmt.Fprintf(session.writer, "%d %s\r\n", code, message)

	session.conn.SetWriteDeadline(time.Now().Add(session.server.WriteTimeout))
	session.writer.Flush()

	session.conn.SetReadDeadline(time.Now().Add(session.server.ReadTimeout))

}

func (session *session) error(err error) {
	session.reply(502, fmt.Sprintf("%s", err))
}

func (session *session) extensions() []string {

	extensions := []string{
		fmt.Sprintf("SIZE %d", session.server.MaxMessageSize),
		"8BITMIME",
	}

	if session.server.TLSConfig != nil && !session.tls {
		extensions = append(extensions, "STARTTLS")
	}

	if session.server.Authenticator != nil && session.tls {
		extensions = append(extensions, "AUTH PLAIN LOGIN")
	}

	return extensions

}

func (session *session) deliver() error {
	if session.server.Handler != nil {
		return session.server.Handler(session.peer, *session.envelope)
	}
	return nil
}

func (session *session) close() {
	session.writer.Flush()
	session.conn.Close()
}
<|endoftext|>


<commit_before>package slice

type solid struct {
	exterior  []*segment   // exterior perimeter
	interiors [][]*segment // interior perimeters
	infill    []*segment   // infill lines
	debug     []*segment   // extra lines to draw for debugging purposes
}
<commit_msg>add min and max vertices to solid type<commit_after>package slice

type solid struct {
	min, max  Vertex2
	exterior  []*segment   // exterior perimeter
	interiors [][]*segment // interior perimeters
	infill    []*segment   // infill lines
	debug     []*segment   // extra lines to draw for debugging purposes
}
<|endoftext|>


<commit_before>package sudoku

import (
	"math/rand"
	"sync"
)

//Solve searches for a solution to the puzzle as it currently exists without
//unfilling any cells. If one exists, it will fill in all cells to fit that
//solution and return true. If there are no solutions the grid will remain
//untouched and it will return false. If multiple solutions exist, Solve will pick one at random.
func (self *Grid) Solve() bool {

	//Special case; check if it's already solved.
	//TODO: removing this causes Solve, when called on an already solved grid, to sometimes fail. Why is that?
	if self.Solved() {
		return true
	}

	//TODO: Optimization: we only need one, so we can bail as soon as we find a single one.
	solutions := self.Solutions()
	if len(solutions) == 0 {
		return false
	}
	self.Load(solutions[0].DataString())
	return true
}

//NumSolutions returns the total number of solutions found in the grid when it is solved forward
//from this point. A valid Sudoku puzzle has only one solution. Does not mutate the grid.
func (self *Grid) NumSolutions() int {
	return len(self.Solutions())
}

//HasSolution returns true if the grid has at least one solution. Does not mutate the grid.
func (self *Grid) HasSolution() bool {
	//TODO: optimize this to bail as soon as we find a single solution.
	return len(self.nOrFewerSolutions(1)) > 0
}

//HasMultipleSolutions returns true if the grid has more than one solution. Does not mutate the grid.
func (self *Grid) HasMultipleSolutions() bool {
	return len(self.nOrFewerSolutions(2)) >= 2
}

//Solutions returns a slice of grids that represent possible solutions if you were to solve forward this grid. The current grid is not modified.
//If there are no solutions forward from this location it will return a slice with len() 0. Does not mutate the grid.
func (self *Grid) Solutions() (solutions []*Grid) {
	return self.nOrFewerSolutions(0)
}

//The actual workhorse of solutions generating. 0 means "as many as you can find". It might return more than you asked for, if it already had more results than requested sitting around.
func (self *Grid) nOrFewerSolutions(max int) []*Grid {

	self.cachedSolutionsLock.RLock()
	hasNoCachedSolutions := self.cachedSolutions == nil
	cachedSolutionsLen := self.cachedSolutionsRequestedLength
	self.cachedSolutionsLock.RUnlock()

	if hasNoCachedSolutions || (max == 0 && cachedSolutionsLen != 0) || (max > 0 && cachedSolutionsLen < max && cachedSolutionsLen > 0) {

		queueDone := make(chan bool, 1)

		queue := newSyncedFiniteQueue(0, DIM*DIM, queueDone)

		queue.In <- self.Copy()

		//In the past this wasn't buffered, but then when we finished early other items would try to go into it
		//and block, which prevented them from looping back up and getting the signal to shut down.
		//Since there's only a known number of threads, we'll make sure they all ahve a place to leave their work
		//without blocking so they can get the signal to shut down.
		incomingSolutions := make(chan *Grid, _NUM_SOLVER_THREADS)

		//Using a pattern for closing fan in style receivers from http://blog.golang.org/pipelines
		var wg sync.WaitGroup

		var solutions []*Grid

		//TODO: figure out a way to kill all of these threads when necessary.

		for i := 0; i < _NUM_SOLVER_THREADS; i++ {
			go func() {
				//Sovler thread.
				firstRun := true
				defer wg.Done()
				for {
					grid, ok := <-queue.Out
					if !ok {
						return
					}
					result := grid.(*Grid).searchSolutions(queue, firstRun, max)
					grid.(*Grid).Done()
					if result != nil {
						incomingSolutions <- result
					}
					queue.ItemDone <- true
					firstRun = false
				}
			}()
		}

		wg.Add(_NUM_SOLVER_THREADS)

		go func() {
			wg.Wait()
			close(incomingSolutions)
		}()

	OuterLoop:
		for {
			select {
			case solution := <-incomingSolutions:
				//Add it to results
				solutions = append(solutions, solution)
				if max > 0 && len(solutions) >= max {
					break OuterLoop
				}
			case <-queueDone:
				//Well, that's as good as it's going to get.
				break OuterLoop
			}
		}

		//There might be some things waiting to go into incomingSolutions here, but because it has a slot
		//for every thread to be buffered, it's OK, we can just stop now.

		//TODO: the grids waiting in the queue will never have their .Done called. This isn't a big deal--GC should reclaim them--
		//but we won't have as many that we could reuse.
		queue.Exit <- true

		self.cachedSolutionsLock.Lock()
		self.cachedSolutions = solutions
		self.cachedSolutionsRequestedLength = max
		self.cachedSolutionsLock.Unlock()

	}

	//TODO: rejigger this to not need a write lock then a read lock when setting.
	self.cachedSolutionsLock.RLock()
	result := self.cachedSolutions
	self.cachedSolutionsLock.RUnlock()
	return result

}

func (self *Grid) searchSolutions(queue *syncedFiniteQueue, isFirstRun bool, numSoughtSolutions int) *Grid {
	//This will only be called by Solutions.
	//We will return ourselves if we are a solution, and if not we will return nil.
	//If there are any sub children, we will send them to counter before we're done.

	if self.Invalid() {
		return nil
	}

	self.fillSimpleCells()
	//Have any cells noticed they were invalid while solving forward?
	if self.cellsInvalid() {
		return nil
	}

	if self.Solved() {
		return self
	}

	//Well, looks like we're going to have to branch.
	rankedObject := self.queue().NewGetter().Get()
	if rankedObject == nil {
		panic("Queue didn't have any cells.")
	}

	cell, ok := rankedObject.(*Cell)
	if !ok {
		panic("We got back a non-cell from the grid's queue")
	}

	unshuffledPossibilities := cell.Possibilities()

	possibilities := make([]int, len(unshuffledPossibilities))

	for i, j := range rand.Perm(len(unshuffledPossibilities)) {
		possibilities[i] = unshuffledPossibilities[j]
	}

	var result *Grid

	for i, num := range possibilities {
		copy := self.Copy()
		copy.Cell(cell.Row(), cell.Col()).SetNumber(num)
		//As an optimization for cases where there are many solutions, we'll just continue a DFS until we barf then unroll back up.
		//It doesn't appear to slow things down in the general case
		if i == 0 && !isFirstRun {
			result = copy.searchSolutions(queue, false, numSoughtSolutions)
			if result != nil && numSoughtSolutions == 1 {
				//No need to spin off other branches, just return up.
				return result
			}
		} else {
			queue.In <- copy
		}
	}

	return result

}

//Fills in all of the cells it can without branching or doing any advanced
//techniques that require anything more than a single cell's possibles list.
func (self *Grid) fillSimpleCells() int {
	count := 0
	getter := self.queue().NewGetter()
	obj := getter.GetSmallerThan(2)
	for obj != nil && !self.cellsInvalid() {
		cell, ok := obj.(*Cell)
		if !ok {
			continue
		}
		cell.SetNumber(cell.implicitNumber())
		count++
		obj = getter.GetSmallerThan(2)
	}
	return count
}
<commit_msg>TESTS FAIL. Check for the end of incomingSolutions. Doesn't fix anything, but seems better.<commit_after>package sudoku

import (
	"math/rand"
	"sync"
)

//Solve searches for a solution to the puzzle as it currently exists without
//unfilling any cells. If one exists, it will fill in all cells to fit that
//solution and return true. If there are no solutions the grid will remain
//untouched and it will return false. If multiple solutions exist, Solve will pick one at random.
func (self *Grid) Solve() bool {

	//Special case; check if it's already solved.
	//TODO: removing this causes Solve, when called on an already solved grid, to sometimes fail. Why is that?
	if self.Solved() {
		return true
	}

	//TODO: Optimization: we only need one, so we can bail as soon as we find a single one.
	solutions := self.Solutions()
	if len(solutions) == 0 {
		return false
	}
	self.Load(solutions[0].DataString())
	return true
}

//NumSolutions returns the total number of solutions found in the grid when it is solved forward
//from this point. A valid Sudoku puzzle has only one solution. Does not mutate the grid.
func (self *Grid) NumSolutions() int {
	return len(self.Solutions())
}

//HasSolution returns true if the grid has at least one solution. Does not mutate the grid.
func (self *Grid) HasSolution() bool {
	//TODO: optimize this to bail as soon as we find a single solution.
	return len(self.nOrFewerSolutions(1)) > 0
}

//HasMultipleSolutions returns true if the grid has more than one solution. Does not mutate the grid.
func (self *Grid) HasMultipleSolutions() bool {
	return len(self.nOrFewerSolutions(2)) >= 2
}

//Solutions returns a slice of grids that represent possible solutions if you were to solve forward this grid. The current grid is not modified.
//If there are no solutions forward from this location it will return a slice with len() 0. Does not mutate the grid.
func (self *Grid) Solutions() (solutions []*Grid) {
	return self.nOrFewerSolutions(0)
}

//The actual workhorse of solutions generating. 0 means "as many as you can find". It might return more than you asked for, if it already had more results than requested sitting around.
func (self *Grid) nOrFewerSolutions(max int) []*Grid {

	self.cachedSolutionsLock.RLock()
	hasNoCachedSolutions := self.cachedSolutions == nil
	cachedSolutionsLen := self.cachedSolutionsRequestedLength
	self.cachedSolutionsLock.RUnlock()

	if hasNoCachedSolutions || (max == 0 && cachedSolutionsLen != 0) || (max > 0 && cachedSolutionsLen < max && cachedSolutionsLen > 0) {

		queueDone := make(chan bool, 1)

		queue := newSyncedFiniteQueue(0, DIM*DIM, queueDone)

		queue.In <- self.Copy()

		//In the past this wasn't buffered, but then when we finished early other items would try to go into it
		//and block, which prevented them from looping back up and getting the signal to shut down.
		//Since there's only a known number of threads, we'll make sure they all ahve a place to leave their work
		//without blocking so they can get the signal to shut down.
		incomingSolutions := make(chan *Grid, _NUM_SOLVER_THREADS)

		//Using a pattern for closing fan in style receivers from http://blog.golang.org/pipelines
		var wg sync.WaitGroup

		var solutions []*Grid

		//TODO: figure out a way to kill all of these threads when necessary.

		for i := 0; i < _NUM_SOLVER_THREADS; i++ {
			go func() {
				//Sovler thread.
				firstRun := true
				defer wg.Done()
				for {
					grid, ok := <-queue.Out
					if !ok {
						return
					}
					result := grid.(*Grid).searchSolutions(queue, firstRun, max)
					grid.(*Grid).Done()
					if result != nil {
						incomingSolutions <- result
					}
					queue.ItemDone <- true
					firstRun = false
				}
			}()
		}

		wg.Add(_NUM_SOLVER_THREADS)

		go func() {
			wg.Wait()
			close(incomingSolutions)
		}()

	OuterLoop:
		for {
			select {
			case solution := <-incomingSolutions:
				//incomingSolutions must have been closed because no more work to do.
				if solution == nil {
					break OuterLoop
				}
				//Add it to results
				solutions = append(solutions, solution)
				if max > 0 && len(solutions) >= max {
					break OuterLoop
				}
			case <-queueDone:
				//Well, that's as good as it's going to get.
				break OuterLoop
			}
		}

		//There might be some things waiting to go into incomingSolutions here, but because it has a slot
		//for every thread to be buffered, it's OK, we can just stop now.

		//TODO: the grids waiting in the queue will never have their .Done called. This isn't a big deal--GC should reclaim them--
		//but we won't have as many that we could reuse.
		queue.Exit <- true

		self.cachedSolutionsLock.Lock()
		self.cachedSolutions = solutions
		self.cachedSolutionsRequestedLength = max
		self.cachedSolutionsLock.Unlock()

	}

	//TODO: rejigger this to not need a write lock then a read lock when setting.
	self.cachedSolutionsLock.RLock()
	result := self.cachedSolutions
	self.cachedSolutionsLock.RUnlock()
	return result

}

func (self *Grid) searchSolutions(queue *syncedFiniteQueue, isFirstRun bool, numSoughtSolutions int) *Grid {
	//This will only be called by Solutions.
	//We will return ourselves if we are a solution, and if not we will return nil.
	//If there are any sub children, we will send them to counter before we're done.

	if self.Invalid() {
		return nil
	}

	self.fillSimpleCells()
	//Have any cells noticed they were invalid while solving forward?
	if self.cellsInvalid() {
		return nil
	}

	if self.Solved() {
		return self
	}

	//Well, looks like we're going to have to branch.
	rankedObject := self.queue().NewGetter().Get()
	if rankedObject == nil {
		panic("Queue didn't have any cells.")
	}

	cell, ok := rankedObject.(*Cell)
	if !ok {
		panic("We got back a non-cell from the grid's queue")
	}

	unshuffledPossibilities := cell.Possibilities()

	possibilities := make([]int, len(unshuffledPossibilities))

	for i, j := range rand.Perm(len(unshuffledPossibilities)) {
		possibilities[i] = unshuffledPossibilities[j]
	}

	var result *Grid

	for i, num := range possibilities {
		copy := self.Copy()
		copy.Cell(cell.Row(), cell.Col()).SetNumber(num)
		//As an optimization for cases where there are many solutions, we'll just continue a DFS until we barf then unroll back up.
		//It doesn't appear to slow things down in the general case
		if i == 0 && !isFirstRun {
			result = copy.searchSolutions(queue, false, numSoughtSolutions)
			if result != nil && numSoughtSolutions == 1 {
				//No need to spin off other branches, just return up.
				return result
			}
		} else {
			queue.In <- copy
		}
	}

	return result

}

//Fills in all of the cells it can without branching or doing any advanced
//techniques that require anything more than a single cell's possibles list.
func (self *Grid) fillSimpleCells() int {
	count := 0
	getter := self.queue().NewGetter()
	obj := getter.GetSmallerThan(2)
	for obj != nil && !self.cellsInvalid() {
		cell, ok := obj.(*Cell)
		if !ok {
			continue
		}
		cell.SetNumber(cell.implicitNumber())
		count++
		obj = getter.GetSmallerThan(2)
	}
	return count
}
<|endoftext|>


<commit_before>package main

import (
    "fmt"
    //"html"
    "log"
    "net/http"
	"io/ioutil"
	"strings"
)

var (
	head string = `<!DOCTYPE html>

<title>Page Title</title>

This is a Heading
`

	tail string =	`</body></html>`

	script string = ``
)

func main() {
	http.HandleFunc("/List", List)
	http.HandleFunc("/Watch/", Watch)
	http.Handle("/", http.FileServer(http.Dir("./Vids/")))
	log.Fatal(http.ListenAndServe(":8080", nil))

}

func List(w http.ResponseWriter, r *http.Request){
	fmt.Fprintf(w, head + getVideos() + tail)
}

func Watch(w http.ResponseWriter, r *http.Request){
	fileToWatch := r.URL.Path[len("/view/"):]
	fileText := ("<video width=\"400\" preload=\"none\" controls><source src=\""+fileToWatch+"\" type=\"video/mp4\">Your browser does not support HTML5 video.</video>")
	fmt.Fprintf(w, head + fileText + script + tail)
}

func getVideos() string{
	fileText:=""
	files, err := ioutil.ReadDir("./Vids")
	if(err != nil){
		fileText = `<p>No Files Found</p>`
	}
	for _, file := range files {
		if strings.Contains(strings.ToLower(file.Name()), "mp4"){
			fileText += (""+file.Name()+"\n
\n")
		}else{
			fileText += ("
" + file.Name() + "
\n
\n")
		}

	}
	return fileText;
}
<commit_msg>minor change<commit_after>package main

import (
    "fmt"
    //"html"
    "log"
    "net/http"
	"io/ioutil"
	"strings"
)

var (
	head string = `<!DOCTYPE html>

<title>Page Title</title>

This is a Heading
`

	tail string =	`</body></html>`

	script string = ``
)

func main() {
	http.HandleFunc("/List", List)
	http.HandleFunc("/Watch/", Watch)
	http.Handle("/", http.FileServer(http.Dir("./Vids/")))
	log.Fatal(http.ListenAndServe(":8080", nil))

}

func List(w http.ResponseWriter, r *http.Request){
	fmt.Fprintf(w, head + getVideos() + tail)
}

func Watch(w http.ResponseWriter, r *http.Request){
	fileToWatch := r.URL.Path[len("/Watch"):]
	fmt.Printf("%q", r.URL.Path)
	fileText := ("<video width=\"400\" preload=\"none\" controls><source src=\""+fileToWatch+"\" type=\"video/mp4\">Your browser does not support HTML5 video.</video>")
	fmt.Fprintf(w, head + fileText + script + tail)
}

func getVideos() string{
	fileText:=""
	files, err := ioutil.ReadDir("./Vids")
	if(err != nil){
		fileText = `<p>No Files Found</p>`
	}
	for _, file := range files {
		if strings.Contains(strings.ToLower(file.Name()), "mp4"){
			fileText += (""+file.Name()+"\n
\n")
		}else{
			fileText += ("
" + file.Name() + "
\n
\n")
		}

	}
	return fileText;
}
<|endoftext|>


<commit_before>package main

import "fmt"

func main() {
	fmt.Printf("Hello, world.\n")
}
<commit_msg>use newmath package<commit_after>package main

import (
	"fmt"

	"github.com/elgrillo83/newmath"
)

func main() {
	fmt.Printf("Hello, world. Sqrt(2) = %v\n", newmath.Sqrt(2))
}
<|endoftext|>


<commit_before><commit_msg>Add dump example<commit_after><|endoftext|>


<commit_before><commit_msg>Do not export helper function<commit_after><|endoftext|>


<commit_before>// Package start combines four common tasks for setting up an
// commandline application:
//
// * Reading settings from a configuration file
// * Reading environment variables
// * Reading command line flags
// * Defining commands and subcommands
//
// See the file README.md about usage of the start package.
//
// Copyright (c) Christoph Berger. All rights reserved.
// Use of this source code is governed by the BSD (3-Clause)
// License that can be found in the LICENSE.txt file.
//
// This source code may import third-party source code whose
// licenses are provided in the respective license files.
//
package start

import (
	"errors"
	"fmt"
	"os"
	"strings"

	"github.com/laurent22/toml-go"
	flag "github.com/spf13/pflag"
)

var (
	// Public variables:

	// Commands is the global command list.
	Commands = CommandMap{}

	// Private package variables.

	// Note: I do explicitly make use of my right to use package-global variables.
	// First, this package acts like a Singleton. No accidental reuse can happen.
	// Second, these variables do not pollute the global name spaces, as they are
	// package variables and private.
	// These variables might get refactored into a struct at a later time.
	app           string // app name
	cfgFile       *configFile
	cfgFileName   string
	customName    bool
	alreadyParsed bool
	privateFlags  = privateFlagsMap{}
	description   string
	version       string
	rawCmdArgs    string // the raw argument string for a command, minus the program name and the command name

	// GlobalInit is a function for initializing resources for all commands.
	// GlobalInit is called AFTER parsing and BEFORE invoking a command.
	// If needed, assign your own function via SetInitFunc() before calling Up().
	globalInit func() error
)

// SetConfigFile allows to set a custom file name and/or path.
// Call this before Parse() or Up(), respectively. Afterwards it has of course
// no effect.
func SetConfigFile(fn string) {
	cfgFileName = fn
	customName = true
}

// SetDescription sets a description of the app. It receives a string containing
// a brief description of the application. If a user runs the application with
// no arguments, or if the user invokes the help command, Usage() will print
// this description string and list the available commands.
func SetDescription(descr string) {
	description = descr
}

// SetVersion sets the version number of the application. Used by the pre-defined
// version command.
func SetVersion(ver string) {
	version = ver
}

// SetInitFunc sets a function that is called after parsing the variables
// but before calling the command. Useful for global initialization that affects
// all commands alike.
func SetInitFunc(initf func() error) {
	globalInit = initf
}

// Parse initializes all flag variables from command line flags, environment
// variables, configuration file entries, or default values.
// After this, each flag variable has a value either -
// - from a command line flag, or
// - from an environment variable, if the flag is not set, or
// - from an entry in the config file, if the environment variable is not set, or
// - from its default value, if there is no entry in the config file.
// Note: For better efficiency, Parse reads the config file and environment
// variables only once. Subsequent calls only parse the flags again, so you can
// call Parse() from multiple places in your code without actually repeating the
// complete parse process. Use Reparse() if you must execute the full parse
// process again.
// This behavior diverges from the behavior of flag.Parse(), which parses always.
func Parse() error {
	if alreadyParsed {
		flag.Parse()
		return nil
	}
	err := parse()
	if err != nil {
		return errors.New("Cannot parse flags: " + err.Error())
	}
	alreadyParsed = true
	return nil
}

// Reparse is the same as Parse but parses always.
func Reparse() error {
	return parse()
}

func parse() error {
	cfgFile, err := newConfigFile(cfgFileName)
	if err != nil {
		return err
	}
	flag.VisitAll(func(f *flag.Flag) {
		// first, set the values from the config file:
		val := cfgFile.String(f.Name)
		if len(val) > 0 {
			f.Value.Set(val)
		}
		// then, find and apply environment variables:
		envVar := os.Getenv(strings.ToUpper(appName() + "_" + f.Name))
		if len(envVar) > 0 {
			f.Value.Set(envVar)
		}
	})
	// finally, parse the command line flags:
	flag.Parse()
	return nil
}

// Up parses all flags and then evaluates and executes the command line.
func Up() {
	err := Parse()
	if err != nil {
		fmt.Fprintln(os.Stderr, "Error while parsing flags:")
		fmt.Fprintln(os.Stderr, err)
		return
	}

	err = globalInit()
	if err != nil {
		fmt.Fprintln(os.Stderr, "Error during initialization:")
		fmt.Fprintln(os.Stderr, err)
		return
	}

	Commands["help"] =
		&Command{
			Name:  "help",
			Short: "Lists commands, or describes a specific command",
			Long: "Lists the available commands.\n" +
				"Use help <command> to get detailed help for a specific command.",
			Cmd: help,
		}

	Commands["version"] =
		&Command{
			Name:  "version",
			Short: "Shows the version number.",
			Long:  "Shows the application's version number.",
			Cmd:   showVersion,
		}

	cmd, err := readCommand(flag.Args())
	if err != nil {
		fmt.Fprintln(os.Stderr, "Error while reading a command:")
		fmt.Fprintln(os.Stderr, err)
		// Execution can continue safely despite the error, because in this
		// case, readCommand returns the Usage command.
	}

	err = cmd.Cmd(cmd)
	if err != nil {
		fmt.Fprintln(os.Stderr, "Error on executing a command:")
		fmt.Fprintln(os.Stderr, err)
	}
}

// ConfigFilePath returns the path of the config file that has been read in.
// Use after calling Up() or Parse().
// Returns an empty path if no config file was found.
func ConfigFilePath() string {
	return cfgFile.Path()
}

// ConfigFileToml returns the toml document created from the config file.
// Useful for fetching additional content from the config file than the one used
// by the flags.
func ConfigFileToml() toml.Document {
	return cfgFile.Toml()
}

func init() {
	app = appName()
	version = "1.0" // SetVersion() overrides this default.
	rawCmdArgs = ""
	if len(os.Args) >= 2 { // TODO why 2
		rawCmdArgs = strings.Join(os.Args[2:], " ")
	}
	globalInit = func() error {
		return nil
	}
}
<commit_msg>Expose App name<commit_after>// Package start combines four common tasks for setting up an
// commandline application:
//
// * Reading settings from a configuration file
// * Reading environment variables
// * Reading command line flags
// * Defining commands and subcommands
//
// See the file README.md about usage of the start package.
//
// Copyright (c) Christoph Berger. All rights reserved.
// Use of this source code is governed by the BSD (3-Clause)
// License that can be found in the LICENSE.txt file.
//
// This source code may import third-party source code whose
// licenses are provided in the respective license files.
//
package start

import (
	"errors"
	"fmt"
	"os"
	"strings"

	"github.com/laurent22/toml-go"
	flag "github.com/spf13/pflag"
)

var (
	// Public variables:

	// Commands is the global command list.
	Commands = CommandMap{}

	// Private package variables.

	// Note: I do explicitly make use of my right to use package-global variables.
	// First, this package acts like a Singleton. No accidental reuse can happen.
	// Second, these variables do not pollute the global name spaces, as they are
	// package variables and private.
	// These variables might get refactored into a struct at a later time.
	App           string // app name
	cfgFile       *configFile
	cfgFileName   string
	customName    bool
	alreadyParsed bool
	privateFlags  = privateFlagsMap{}
	description   string
	version       string
	rawCmdArgs    string // the raw argument string for a command, minus the program name and the command name

	// GlobalInit is a function for initializing resources for all commands.
	// GlobalInit is called AFTER parsing and BEFORE invoking a command.
	// If needed, assign your own function via SetInitFunc() before calling Up().
	globalInit func() error
)

// SetConfigFile allows to set a custom file name and/or path.
// Call this before Parse() or Up(), respectively. Afterwards it has of course
// no effect.
func SetConfigFile(fn string) {
	cfgFileName = fn
	customName = true
}

// SetDescription sets a description of the app. It receives a string containing
// a brief description of the application. If a user runs the application with
// no arguments, or if the user invokes the help command, Usage() will print
// this description string and list the available commands.
func SetDescription(descr string) {
	description = descr
}

// SetVersion sets the version number of the application. Used by the pre-defined
// version command.
func SetVersion(ver string) {
	version = ver
}

// SetInitFunc sets a function that is called after parsing the variables
// but before calling the command. Useful for global initialization that affects
// all commands alike.
func SetInitFunc(initf func() error) {
	globalInit = initf
}

// Parse initializes all flag variables from command line flags, environment
// variables, configuration file entries, or default values.
// After this, each flag variable has a value either -
// - from a command line flag, or
// - from an environment variable, if the flag is not set, or
// - from an entry in the config file, if the environment variable is not set, or
// - from its default value, if there is no entry in the config file.
// Note: For better efficiency, Parse reads the config file and environment
// variables only once. Subsequent calls only parse the flags again, so you can
// call Parse() from multiple places in your code without actually repeating the
// complete parse process. Use Reparse() if you must execute the full parse
// process again.
// This behavior diverges from the behavior of flag.Parse(), which parses always.
func Parse() error {
	if alreadyParsed {
		flag.Parse()
		return nil
	}
	err := parse()
	if err != nil {
		return errors.New("Cannot parse flags: " + err.Error())
	}
	alreadyParsed = true
	return nil
}

// Reparse is the same as Parse but parses always.
func Reparse() error {
	return parse()
}

func parse() error {
	cfgFile, err := newConfigFile(cfgFileName)
	if err != nil {
		return err
	}
	flag.VisitAll(func(f *flag.Flag) {
		// first, set the values from the config file:
		val := cfgFile.String(f.Name)
		if len(val) > 0 {
			f.Value.Set(val)
		}
		// then, find and apply environment variables:
		envVar := os.Getenv(strings.ToUpper(appName() + "_" + f.Name))
		if len(envVar) > 0 {
			f.Value.Set(envVar)
		}
	})
	// finally, parse the command line flags:
	flag.Parse()
	return nil
}

// Up parses all flags and then evaluates and executes the command line.
func Up() {
	err := Parse()
	if err != nil {
		fmt.Fprintln(os.Stderr, "Error while parsing flags:")
		fmt.Fprintln(os.Stderr, err)
		return
	}

	err = globalInit()
	if err != nil {
		fmt.Fprintln(os.Stderr, "Error during initialization:")
		fmt.Fprintln(os.Stderr, err)
		return
	}

	Commands["help"] =
		&Command{
			Name:  "help",
			Short: "Lists commands, or describes a specific command",
			Long: "Lists the available commands.\n" +
				"Use help <command> to get detailed help for a specific command.",
			Cmd: help,
		}

	Commands["version"] =
		&Command{
			Name:  "version",
			Short: "Shows the version number.",
			Long:  "Shows the application's version number.",
			Cmd:   showVersion,
		}

	cmd, err := readCommand(flag.Args())
	if err != nil {
		fmt.Fprintln(os.Stderr, "Error while reading a command:")
		fmt.Fprintln(os.Stderr, err)
		// Execution can continue safely despite the error, because in this
		// case, readCommand returns the Usage command.
	}

	err = cmd.Cmd(cmd)
	if err != nil {
		fmt.Fprintln(os.Stderr, "Error on executing a command:")
		fmt.Fprintln(os.Stderr, err)
	}
}

// ConfigFilePath returns the path of the config file that has been read in.
// Use after calling Up() or Parse().
// Returns an empty path if no config file was found.
func ConfigFilePath() string {
	return cfgFile.Path()
}

// ConfigFileToml returns the toml document created from the config file.
// Useful for fetching additional content from the config file than the one used
// by the flags.
func ConfigFileToml() toml.Document {
	return cfgFile.Toml()
}

func init() {
	App = appName()
	version = "1.0" // SetVersion() overrides this default.
	rawCmdArgs = ""
	if len(os.Args) >= 2 { // TODO why 2
		rawCmdArgs = strings.Join(os.Args[2:], " ")
	}
	globalInit = func() error {
		return nil
	}
}
<|endoftext|>


<commit_before><commit_msg>Add TreeView IsBlankAtPos<commit_after><|endoftext|>


<commit_before><commit_msg>fixes CC-738<commit_after><|endoftext|>