<commit_before>/*
Package bloom provides data structures and methods for creating Bloom filters.

A Bloom filter is a representation of a set of _n_ items, where the main
requirement is to make membership queries; _i.e._, whether an item is a
member of a set.

A Bloom filter has two parameters: _m_, a maximum size (typically a reasonably large
multiple of the cardinality of the set to represent) and _k_, the number of hashing
functions on elements of the set. (The actual hashing functions are important, too,
but this is not a parameter for this implementation). A Bloom filter is backed by
a BitSet; a key is represented in the filter by setting the bits at each value of the
hashing functions (modulo _m_). Set membership is done by _testing_ whether the
bits at each value of the hashing functions (again, modulo _m_) are set. If so,
the item is in the set. If the item is actually in the set, a Bloom filter will
never fail (the true positive rate is 1.0); but it is susceptible to false
positives. The art is to choose _k_ and _m_ correctly.

In this implementation, the hashing functions used is a local version of FNV,
a non-cryptographic hashing function, seeded with the index number of
the kth hashing function.

This implementation accepts keys for setting as testing as []byte. Thus, to
add a string item, "Love":

    uint n = 1000
    filter := bloom.New(20*n, 5) // load of 20, 5 keys
    filter.Add([]byte("Love"))

Similarly, to test if "Love" is in bloom:

    if filter.Test([]byte("Love"))

For numeric data, I recommend that you look into the binary/encoding library. But,
for example, to add a uint32 to the filter:

    i := uint32(100)
    n1 := make([]byte,4)
    binary.BigEndian.PutUint32(n1,i)
    f.Add(n1)

Finally, there is a method to estimate the false positive rate of a particular
Bloom filter for a set of size _n_:

    if filter.EstimateFalsePositiveRate(1000) > 0.001

Given the particular hashing scheme, it's best to be empirical about this. Note
that estimating the FP rate will clear the Bloom filter.
*/
package bloom

import (
	"bytes"
	"encoding/binary"
	"encoding/json"
	"fmt"
	"io"
	"math"

	"github.com/spaolacci/murmur3"
	"github.com/willf/bitset"
)

// A BloomFilter is a representation of a set of _n_ items, where the main
// requirement is to make membership queries; _i.e._, whether an item is a
// member of a set.
type BloomFilter struct {
	m uint
	k uint
	b *bitset.BitSet
}

// New creates a new Bloom filter with _m_ bits and _k_ hashing functions
func New(m uint, k uint) *BloomFilter {
	return &BloomFilter{m, k, bitset.New(m)}
}

// baseHashes returns the four hash values of data that are used to create k
// hashes
func baseHashes(data []byte) [4]uint64 {
	a1 := []byte{1} // to grab another bit of data
	hasher := murmur3.New128()
	_, _ = hasher.Write(data)
	v1, v2 := hasher.Sum128()
	_, _ = hasher.Write(a1)
	v3, v4 := hasher.Sum128()
	return [4]uint64{
		v1, v2, v3, v4,
	}
}

// location returns the ith hashed location using the four base hash values
func (f *BloomFilter) location(h [4]uint64, i uint) (location uint) {
	ii := uint64(i)
	location = uint((h[ii%2] + ii*h[2+(((ii+(ii%2))%4)/2)]) % uint64(f.m))
	return
}

// EstimateParameters estimates requirements for m and k.
// Based on https://bitbucket.org/ww/bloom/src/829aa19d01d9/bloom.go
// used with permission.
func EstimateParameters(n uint, p float64) (m uint, k uint) {
	m = uint(math.Ceil(-1 * float64(n) * math.Log(p) / math.Pow(math.Log(2), 2)))
	k = uint(math.Ceil(math.Log(2) * float64(m) / float64(n)))
	return
}

// NewWithEstimates creates a new Bloom filter for about n items with fp
// false positive rate
func NewWithEstimates(n uint, fp float64) *BloomFilter {
	m, k := EstimateParameters(n, fp)
	return New(m, k)
}

// Cap returns the capacity, _m_, of a Bloom filter
func (f *BloomFilter) Cap() uint {
	return f.m
}

// K returns the number of hash functions used in the BloomFilter
func (f *BloomFilter) K() uint {
	return f.k
}

// Add data to the Bloom Filter. Returns the filter (allows chaining)
func (f *BloomFilter) Add(data []byte) *BloomFilter {
	h := baseHashes(data)
	for i := uint(0); i < f.k; i++ {
		f.b.Set(f.location(h, i))
	}
	return f
}

// Merge the data from two Bloom Filters.
func (f *BloomFilter) Merge(g *BloomFilter) error {
	// Make sure the m's and k's are the same, otherwise merging has no real use.
	if f.m != g.m {
		return fmt.Errorf("m's don't match: %d != %d", f.m, g.m)
	}

	if f.k != g.k {
		return fmt.Errorf("k's don't match: %d != %d", f.m, g.m)
	}

	f.b.InPlaceUnion(g.b)
	return nil
}

// Copy creates a copy of a Bloom filter.
func (f *BloomFilter) Copy() *BloomFilter {
	fc := New(f.m, f.k)
	_ = fc.Merge(f)
	return fc
}

// AddString to the Bloom Filter. Returns the filter (allows chaining)
func (f *BloomFilter) AddString(data string) *BloomFilter {
	return f.Add([]byte(data))
}

// Test returns true if the data is in the BloomFilter, false otherwise.
// If true, the result might be a false positive. If false, the data
// is definitely not in the set.
func (f *BloomFilter) Test(data []byte) bool {
	h := baseHashes(data)
	for i := uint(0); i < f.k; i++ {
		if !f.b.Test(f.location(h, i)) {
			return false
		}
	}
	return true
}

// TestString returns true if the string is in the BloomFilter, false otherwise.
// If true, the result might be a false positive. If false, the data
// is definitely not in the set.
func (f *BloomFilter) TestString(data string) bool {
	return f.Test([]byte(data))
}

// TestAndAdd is the equivalent to calling Test(data) then Add(data).
// Returns the result of Test.
func (f *BloomFilter) TestAndAdd(data []byte) bool {
	present := true
	h := baseHashes(data)
	for i := uint(0); i < f.k; i++ {
		l := f.location(h, i)
		if !f.b.Test(l) {
			present = false
		}
		f.b.Set(l)
	}
	return present
}

// TestAndAddString is the equivalent to calling Test(string) then Add(string).
// Returns the result of Test.
func (f *BloomFilter) TestAndAddString(data string) bool {
	return f.TestAndAdd([]byte(data))
}

// ClearAll clears all the data in a Bloom filter, removing all keys
func (f *BloomFilter) ClearAll() *BloomFilter {
	f.b.ClearAll()
	return f
}

// EstimateFalsePositiveRate returns, for a BloomFilter with a estimate of m bits
// and k hash functions, what the false positive rate will be
// while storing n entries; runs 100,000 tests. This is an empirical
// test using integers as keys. As a side-effect, it clears the BloomFilter.
func (f *BloomFilter) EstimateFalsePositiveRate(n uint) (fpRate float64) {
	rounds := uint32(100000)
	f.ClearAll()
	n1 := make([]byte, 4)
	for i := uint32(0); i < uint32(n); i++ {
		binary.BigEndian.PutUint32(n1, i)
		f.Add(n1)
	}
	fp := 0
	// test for number of rounds
	for i := uint32(0); i < rounds; i++ {
		binary.BigEndian.PutUint32(n1, i+uint32(n)+1)
		if f.Test(n1) {
			//fmt.Printf("%v failed.\n", i+uint32(n)+1)
			fp++
		}
	}
	fpRate = float64(fp) / (float64(rounds))
	f.ClearAll()
	return
}

// bloomFilterJSON is an unexported type for marshaling/unmarshaling BloomFilter struct.
type bloomFilterJSON struct {
	M uint           `json:"m"`
	K uint           `json:"k"`
	B *bitset.BitSet `json:"b"`
}

// MarshalJSON implements json.Marshaler interface.
func (f *BloomFilter) MarshalJSON() ([]byte, error) {
	return json.Marshal(bloomFilterJSON{f.m, f.k, f.b})
}

// UnmarshalJSON implements json.Unmarshaler interface.
func (f *BloomFilter) UnmarshalJSON(data []byte) error {
	var j bloomFilterJSON
	err := json.Unmarshal(data, &j)
	if err != nil {
		return err
	}
	f.m = j.M
	f.k = j.K
	f.b = j.B
	return nil
}

// WriteTo writes a binary representation of the BloomFilter to an i/o stream.
// It returns the number of bytes written.
func (f *BloomFilter) WriteTo(stream io.Writer) (int64, error) {
	err := binary.Write(stream, binary.BigEndian, uint64(f.m))
	if err != nil {
		return 0, err
	}
	err = binary.Write(stream, binary.BigEndian, uint64(f.k))
	if err != nil {
		return 0, err
	}
	numBytes, err := f.b.WriteTo(stream)
	return numBytes + int64(2*binary.Size(uint64(0))), err
}

// ReadFrom reads a binary representation of the BloomFilter (such as might
// have been written by WriteTo()) from an i/o stream. It returns the number
// of bytes read.
func (f *BloomFilter) ReadFrom(stream io.Reader) (int64, error) {
	var m, k uint64
	err := binary.Read(stream, binary.BigEndian, &m)
	if err != nil {
		return 0, err
	}
	err = binary.Read(stream, binary.BigEndian, &k)
	if err != nil {
		return 0, err
	}
	b := &bitset.BitSet{}
	numBytes, err := b.ReadFrom(stream)
	if err != nil {
		return 0, err
	}
	f.m = uint(m)
	f.k = uint(k)
	f.b = b
	return numBytes + int64(2*binary.Size(uint64(0))), nil
}

// GobEncode implements gob.GobEncoder interface.
func (f *BloomFilter) GobEncode() ([]byte, error) {
	var buf bytes.Buffer
	_, err := f.WriteTo(&buf)
	if err != nil {
		return nil, err
	}

	return buf.Bytes(), nil
}

// GobDecode implements gob.GobDecoder interface.
func (f *BloomFilter) GobDecode(data []byte) error {
	buf := bytes.NewBuffer(data)
	_, err := f.ReadFrom(buf)

	return err
}

// Equal tests for the equality of two Bloom filters
func (f *BloomFilter) Equal(g *BloomFilter) bool {
	return f.m == g.m && f.k == g.k && f.b.Equal(g.b)
}
<commit_msg>revert<commit_after>/*
Package bloom provides data structures and methods for creating Bloom filters.

A Bloom filter is a representation of a set of _n_ items, where the main
requirement is to make membership queries; _i.e._, whether an item is a
member of a set.

A Bloom filter has two parameters: _m_, a maximum size (typically a reasonably large
multiple of the cardinality of the set to represent) and _k_, the number of hashing
functions on elements of the set. (The actual hashing functions are important, too,
but this is not a parameter for this implementation). A Bloom filter is backed by
a BitSet; a key is represented in the filter by setting the bits at each value of the
hashing functions (modulo _m_). Set membership is done by _testing_ whether the
bits at each value of the hashing functions (again, modulo _m_) are set. If so,
the item is in the set. If the item is actually in the set, a Bloom filter will
never fail (the true positive rate is 1.0); but it is susceptible to false
positives. The art is to choose _k_ and _m_ correctly.

In this implementation, the hashing functions used is a local version of FNV,
a non-cryptographic hashing function, seeded with the index number of
the kth hashing function.

This implementation accepts keys for setting as testing as []byte. Thus, to
add a string item, "Love":

    uint n = 1000
    filter := bloom.New(20*n, 5) // load of 20, 5 keys
    filter.Add([]byte("Love"))

Similarly, to test if "Love" is in bloom:

    if filter.Test([]byte("Love"))

For numeric data, I recommend that you look into the binary/encoding library. But,
for example, to add a uint32 to the filter:

    i := uint32(100)
    n1 := make([]byte,4)
    binary.BigEndian.PutUint32(n1,i)
    f.Add(n1)

Finally, there is a method to estimate the false positive rate of a particular
Bloom filter for a set of size _n_:

    if filter.EstimateFalsePositiveRate(1000) > 0.001

Given the particular hashing scheme, it's best to be empirical about this. Note
that estimating the FP rate will clear the Bloom filter.
*/
package bloom

import (
	"bytes"
	"encoding/binary"
	"encoding/json"
	"fmt"
	"io"
	"math"

	"github.com/spaolacci/murmur3"
	"github.com/willf/bitset"
)

// A BloomFilter is a representation of a set of _n_ items, where the main
// requirement is to make membership queries; _i.e._, whether an item is a
// member of a set.
type BloomFilter struct {
	m uint
	k uint
	b *bitset.BitSet
}

// New creates a new Bloom filter with _m_ bits and _k_ hashing functions
func New(m uint, k uint) *BloomFilter {
	return &BloomFilter{m, k, bitset.New(m)}
}

// baseHashes returns the four hash values of data that are used to create k
// hashes
func baseHashes(data []byte) [4]uint64 {
	a1 := []byte{1} // to grab another bit of data
	hasher := murmur3.New128()
	hasher.Write(data) // #nosec
	v1, v2 := hasher.Sum128()
	hasher.Write(a1) // #nosec
	v3, v4 := hasher.Sum128()
	return [4]uint64{
		v1, v2, v3, v4,
	}
}

// location returns the ith hashed location using the four base hash values
func (f *BloomFilter) location(h [4]uint64, i uint) (location uint) {
	ii := uint64(i)
	location = uint((h[ii%2] + ii*h[2+(((ii+(ii%2))%4)/2)]) % uint64(f.m))
	return
}

// EstimateParameters estimates requirements for m and k.
// Based on https://bitbucket.org/ww/bloom/src/829aa19d01d9/bloom.go
// used with permission.
func EstimateParameters(n uint, p float64) (m uint, k uint) {
	m = uint(math.Ceil(-1 * float64(n) * math.Log(p) / math.Pow(math.Log(2), 2)))
	k = uint(math.Ceil(math.Log(2) * float64(m) / float64(n)))
	return
}

// NewWithEstimates creates a new Bloom filter for about n items with fp
// false positive rate
func NewWithEstimates(n uint, fp float64) *BloomFilter {
	m, k := EstimateParameters(n, fp)
	return New(m, k)
}

// Cap returns the capacity, _m_, of a Bloom filter
func (f *BloomFilter) Cap() uint {
	return f.m
}

// K returns the number of hash functions used in the BloomFilter
func (f *BloomFilter) K() uint {
	return f.k
}

// Add data to the Bloom Filter. Returns the filter (allows chaining)
func (f *BloomFilter) Add(data []byte) *BloomFilter {
	h := baseHashes(data)
	for i := uint(0); i < f.k; i++ {
		f.b.Set(f.location(h, i))
	}
	return f
}

// Merge the data from two Bloom Filters.
func (f *BloomFilter) Merge(g *BloomFilter) error {
	// Make sure the m's and k's are the same, otherwise merging has no real use.
	if f.m != g.m {
		return fmt.Errorf("m's don't match: %d != %d", f.m, g.m)
	}

	if f.k != g.k {
		return fmt.Errorf("k's don't match: %d != %d", f.m, g.m)
	}

	f.b.InPlaceUnion(g.b)
	return nil
}

// Copy creates a copy of a Bloom filter.
func (f *BloomFilter) Copy() *BloomFilter {
	fc := New(f.m, f.k)
	fc.Merge(f) // #nosec
	return fc
}

// AddString to the Bloom Filter. Returns the filter (allows chaining)
func (f *BloomFilter) AddString(data string) *BloomFilter {
	return f.Add([]byte(data))
}

// Test returns true if the data is in the BloomFilter, false otherwise.
// If true, the result might be a false positive. If false, the data
// is definitely not in the set.
func (f *BloomFilter) Test(data []byte) bool {
	h := baseHashes(data)
	for i := uint(0); i < f.k; i++ {
		if !f.b.Test(f.location(h, i)) {
			return false
		}
	}
	return true
}

// TestString returns true if the string is in the BloomFilter, false otherwise.
// If true, the result might be a false positive. If false, the data
// is definitely not in the set.
func (f *BloomFilter) TestString(data string) bool {
	return f.Test([]byte(data))
}

// TestAndAdd is the equivalent to calling Test(data) then Add(data).
// Returns the result of Test.
func (f *BloomFilter) TestAndAdd(data []byte) bool {
	present := true
	h := baseHashes(data)
	for i := uint(0); i < f.k; i++ {
		l := f.location(h, i)
		if !f.b.Test(l) {
			present = false
		}
		f.b.Set(l)
	}
	return present
}

// TestAndAddString is the equivalent to calling Test(string) then Add(string).
// Returns the result of Test.
func (f *BloomFilter) TestAndAddString(data string) bool {
	return f.TestAndAdd([]byte(data))
}

// ClearAll clears all the data in a Bloom filter, removing all keys
func (f *BloomFilter) ClearAll() *BloomFilter {
	f.b.ClearAll()
	return f
}

// EstimateFalsePositiveRate returns, for a BloomFilter with a estimate of m bits
// and k hash functions, what the false positive rate will be
// while storing n entries; runs 100,000 tests. This is an empirical
// test using integers as keys. As a side-effect, it clears the BloomFilter.
func (f *BloomFilter) EstimateFalsePositiveRate(n uint) (fpRate float64) {
	rounds := uint32(100000)
	f.ClearAll()
	n1 := make([]byte, 4)
	for i := uint32(0); i < uint32(n); i++ {
		binary.BigEndian.PutUint32(n1, i)
		f.Add(n1)
	}
	fp := 0
	// test for number of rounds
	for i := uint32(0); i < rounds; i++ {
		binary.BigEndian.PutUint32(n1, i+uint32(n)+1)
		if f.Test(n1) {
			//fmt.Printf("%v failed.\n", i+uint32(n)+1)
			fp++
		}
	}
	fpRate = float64(fp) / (float64(rounds))
	f.ClearAll()
	return
}

// bloomFilterJSON is an unexported type for marshaling/unmarshaling BloomFilter struct.
type bloomFilterJSON struct {
	M uint           `json:"m"`
	K uint           `json:"k"`
	B *bitset.BitSet `json:"b"`
}

// MarshalJSON implements json.Marshaler interface.
func (f *BloomFilter) MarshalJSON() ([]byte, error) {
	return json.Marshal(bloomFilterJSON{f.m, f.k, f.b})
}

// UnmarshalJSON implements json.Unmarshaler interface.
func (f *BloomFilter) UnmarshalJSON(data []byte) error {
	var j bloomFilterJSON
	err := json.Unmarshal(data, &j)
	if err != nil {
		return err
	}
	f.m = j.M
	f.k = j.K
	f.b = j.B
	return nil
}

// WriteTo writes a binary representation of the BloomFilter to an i/o stream.
// It returns the number of bytes written.
func (f *BloomFilter) WriteTo(stream io.Writer) (int64, error) {
	err := binary.Write(stream, binary.BigEndian, uint64(f.m))
	if err != nil {
		return 0, err
	}
	err = binary.Write(stream, binary.BigEndian, uint64(f.k))
	if err != nil {
		return 0, err
	}
	numBytes, err := f.b.WriteTo(stream)
	return numBytes + int64(2*binary.Size(uint64(0))), err
}

// ReadFrom reads a binary representation of the BloomFilter (such as might
// have been written by WriteTo()) from an i/o stream. It returns the number
// of bytes read.
func (f *BloomFilter) ReadFrom(stream io.Reader) (int64, error) {
	var m, k uint64
	err := binary.Read(stream, binary.BigEndian, &m)
	if err != nil {
		return 0, err
	}
	err = binary.Read(stream, binary.BigEndian, &k)
	if err != nil {
		return 0, err
	}
	b := &bitset.BitSet{}
	numBytes, err := b.ReadFrom(stream)
	if err != nil {
		return 0, err
	}
	f.m = uint(m)
	f.k = uint(k)
	f.b = b
	return numBytes + int64(2*binary.Size(uint64(0))), nil
}

// GobEncode implements gob.GobEncoder interface.
func (f *BloomFilter) GobEncode() ([]byte, error) {
	var buf bytes.Buffer
	_, err := f.WriteTo(&buf)
	if err != nil {
		return nil, err
	}

	return buf.Bytes(), nil
}

// GobDecode implements gob.GobDecoder interface.
func (f *BloomFilter) GobDecode(data []byte) error {
	buf := bytes.NewBuffer(data)
	_, err := f.ReadFrom(buf)

	return err
}

// Equal tests for the equality of two Bloom filters
func (f *BloomFilter) Equal(g *BloomFilter) bool {
	return f.m == g.m && f.k == g.k && f.b.Equal(g.b)
}
<|endoftext|>


<commit_before>/**********************************************************\
|                                                          |
|                          hprose                          |
|                                                          |
| Official WebSite: http://www.hprose.com/                 |
|                   http://www.hprose.org/                 |
|                                                          |
\**********************************************************/
/**********************************************************\
 *                                                        *
 * promise/functions.go                                   *
 *                                                        *
 * some functions of promise for Go.                      *
 *                                                        *
 * LastModified: Aug 14, 2016                             *
 * Author: Ma Bingyao <andot@hprose.com>                  *
 *                                                        *
\**********************************************************/

package promise

import (
	"errors"
	"sync/atomic"
	"time"
)

// Create creates a Promise object containing the result of asynchronously
// calling computation.
//
// If calling computation returns error, the returned Promise is rejected with
// the error.
//
// If calling computation returns a Promise object, completion of the created
// Promise will wait until the returned Promise completes, and will then
// complete with the same result.
//
// If calling computation returns a non-Promise value, the returned Promise is
// completed with that value.
func Create(computation func() (interface{}, error)) Promise {
	promise := New()
	go call(promise, computation)
	return promise
}

// Sync creates a Promise object containing the result of immediately calling
// computation.
//
// If calling computation returns error, the returned Promise is rejected with
// the error.
//
// If calling computation returns a Promise object, completion of the created
// Promise will wait until the returned Promise completes, and will then
// complete with the same result.
//
// If calling computation returns a non-Promise value, the returned Promise is
// completed with that value.
func Sync(computation func() (interface{}, error)) Promise {
	promise := New()
	call(promise, computation)
	return promise
}

// Delayed creates a Promise object with the given value after a delay.
//
// If the value is a Callable function, it will be executed after the given
// duration has passed, and the Promise object is completed with the result.
func Delayed(duration time.Duration, value interface{}) Promise {
	promise := New()
	go func() {
		time.Sleep(duration)
		switch computation := value.(type) {
		case func() (interface{}, error):
			call(promise, computation)
		case func():
			call1(promise, computation)
		default:
			promise.Resolve(value)
		}
	}()
	return promise
}

// All function returns a promise that resolves when all of the promises in the
// iterable argument have resolved, or rejects with the reason of the first
// passed promise that rejects.
func All(iterable ...interface{}) Promise {
	count := int64(len(iterable))
	if count == 0 {
		return Resolve(nil)
	}
	result := make([]interface{}, count)
	promise := New()
	for index, value := range iterable {
		ToPromise(value).Then(
			allHandler(promise, result, index, &count),
			promise.Reject)
	}
	return promise
}

func allHandler(promise Promise, result []interface{}, index int, count *int64) func(value interface{}) {
	return func(value interface{}) {
		result[index] = value
		if atomic.AddInt64(count, -1) == 0 {
			promise.Resolve(result)
		}
	}
}

// Race function returns a promise that resolves or rejects as soon as one of
// the promises in the iterable resolves or rejects, with the value or reason
// from that promise.
func Race(iterable ...interface{}) Promise {
	promise := New()
	for _, value := range iterable {
		ToPromise(value).Fill(promise)
	}
	return promise
}

// Any function is a competitive race that allows one winner.
//
// The returned promise will fulfill as soon as any one of the input promises
// fulfills, with the value of the fulfilled input promise.
//
// Or reject with a IllegalArgumentError if the input iterable is empty--i.e. it
// is impossible to have one winner.
//
// Or reject with an iterable of all the rejection reasons, if the input
// iterable is non-empty, and all input promises reject.
func Any(iterable ...interface{}) Promise {
	count := int64(len(iterable))
	if count == 0 {
		return Reject(IllegalArgumentError("any(): iterable must not be empty"))
	}
	promise := New()
	for _, value := range iterable {
		ToPromise(value).Then(promise.Resolve, func() {
			if atomic.AddInt64(&count, -1) == 0 {
				promise.Reject(errors.New("any(): all promises failed"))
			}
		})
	}
	return promise
}

// Each function executes a provided function once per element of iterable.
//
// The callback parameter is a function to execute for each element:
//
//		func(index int, value interface{})
//
// index: The index of the current element being processed.
//
// value: The current element being processed.
//
// If any of the promises in iterable is rejected, the callback will not be
// executed. the returned promise will be rejected with the rejection reason
// of the first promise that was rejected.
func Each(callback func(int, interface{}), iterable ...interface{}) Promise {
	return All(iterable...).Then(func(a interface{}) {
		if a != nil {
			each(callback, a.([]interface{}))
		}
	})
}

func each(callback func(int, interface{}), iterable []interface{}) {
	for index, value := range iterable {
		callback(index, value)
	}
}

// Every function tests whether all elements in the iterable pass the test
// implemented by the provided function.
//
// The callback parameter is a function to test for each element:
//
//		func(index int, value interface{}) bool
//
// index: The index of the current element being processed.
//
// value: The current element being processed.
//
// If any of the promises in iterable is rejected, the callback will not be
// executed. the returned promise will be rejected with the rejection reason
// of the first promise that was rejected.
//
// The returned promise will fulfill with false if the callback function returns
// false for any iterable element immediately. Otherwise, if callback returned
// a true value for all elements, Every will return promise fulfill with true.
//
// If iterable is empty, The returned promise will fulfill with true.
func Every(callback func(int, interface{}) bool, iterable ...interface{}) Promise {
	return All(iterable...).Then(func(a interface{}) (interface{}, error) {
		if a == nil {
			return true, nil
		}
		return every(callback, a.([]interface{})), nil
	})
}

func every(callback func(int, interface{}) bool, iterable []interface{}) bool {
	for index, value := range iterable {
		if !callback(index, value) {
			return false
		}
	}
	return true
}

// Some function tests whether some element in the iterable passes the test
// implemented by the provided function.
//
// The callback parameter is a function to test for each element:
//
//		func(index int, value interface{}) bool
//
// index: The index of the current element being processed.
//
// value: The current element being processed.
//
// If any of the promises in iterable is rejected, the callback will not be
// executed. the returned promise will be rejected with the rejection reason
// of the first promise that was rejected.
//
// The returned promise will fulfill with true if the callback function returns
// true for any iterable element immediately. Otherwise, if callback returned a
// false value for all elements, Some will return promise fulfill with false.
//
// If iterable is empty, The returned promise will fulfill with false.
func Some(callback func(int, interface{}) bool, iterable ...interface{}) Promise {
	return All(iterable...).Then(func(a interface{}) (interface{}, error) {
		if a == nil {
			return false, nil
		}
		return some(callback, a.([]interface{})), nil
	})
}

func some(callback func(int, interface{}) bool, iterable []interface{}) bool {
	for index, value := range iterable {
		if callback(index, value) {
			return true
		}
	}
	return false
}

// Filter function returns a promise fulfill with a slice that has all elements
// pass the test implemented by the provided function.
//
// The callback parameter is a function to test for each element:
//
//		func(index int, value interface{}) bool
//
// index: The index of the current element being processed.
//
// value: The current element being processed.
//
// If any of the promises in iterable is rejected, the callback will not be
// executed. the returned promise will be rejected with the rejection reason
// of the first promise that was rejected.
func Filter(callback func(int, interface{}) bool, iterable ...interface{}) Promise {
	return All(iterable...).Then(func(a interface{}) (interface{}, error) {
		if a == nil {
			return nil, nil
		}
		return filter(callback, a.([]interface{})), nil
	})
}

func filter(callback func(int, interface{}) bool, iterable []interface{}) []interface{} {
	result := make([]interface{}, 0, len(iterable))
	for index, value := range iterable {
		if callback(index, value) {
			result = append(result, value)
		}
	}
	return result
}

// Map function returns a promise fulfill with a slice that has the results of
// calling a provided function on every element in iterable.
//
// The callback parameter produces an element of the new slice:
//
//		func(index int, value interface{}) interface{}
//
// index: The index of the current element being processed.
//
// value: The current element being processed.
//
// If any of the promises in iterable is rejected, the callback will not be
// executed. the returned promise will be rejected with the rejection reason
// of the first promise that was rejected.
func Map(callback func(int, interface{}) interface{}, iterable ...interface{}) Promise {
	return All(iterable...).Then(func(a interface{}) (interface{}, error) {
		if a == nil {
			return nil, nil
		}
		iterable := a.([]interface{})
		result := make([]interface{}, len(iterable))
		for index, value := range iterable {
			result[index] = callback(index, value)
		}
		return result, nil
	})
}
<commit_msg>Update Any<commit_after>/**********************************************************\
|                                                          |
|                          hprose                          |
|                                                          |
| Official WebSite: http://www.hprose.com/                 |
|                   http://www.hprose.org/                 |
|                                                          |
\**********************************************************/
/**********************************************************\
 *                                                        *
 * promise/functions.go                                   *
 *                                                        *
 * some functions of promise for Go.                      *
 *                                                        *
 * LastModified: Aug 14, 2016                             *
 * Author: Ma Bingyao <andot@hprose.com>                  *
 *                                                        *
\**********************************************************/

package promise

import (
	"errors"
	"sync/atomic"
	"time"
)

// Create creates a Promise object containing the result of asynchronously
// calling computation.
//
// If calling computation returns error, the returned Promise is rejected with
// the error.
//
// If calling computation returns a Promise object, completion of the created
// Promise will wait until the returned Promise completes, and will then
// complete with the same result.
//
// If calling computation returns a non-Promise value, the returned Promise is
// completed with that value.
func Create(computation func() (interface{}, error)) Promise {
	promise := New()
	go call(promise, computation)
	return promise
}

// Sync creates a Promise object containing the result of immediately calling
// computation.
//
// If calling computation returns error, the returned Promise is rejected with
// the error.
//
// If calling computation returns a Promise object, completion of the created
// Promise will wait until the returned Promise completes, and will then
// complete with the same result.
//
// If calling computation returns a non-Promise value, the returned Promise is
// completed with that value.
func Sync(computation func() (interface{}, error)) Promise {
	promise := New()
	call(promise, computation)
	return promise
}

// Delayed creates a Promise object with the given value after a delay.
//
// If the value is a Callable function, it will be executed after the given
// duration has passed, and the Promise object is completed with the result.
func Delayed(duration time.Duration, value interface{}) Promise {
	promise := New()
	go func() {
		time.Sleep(duration)
		switch computation := value.(type) {
		case func() (interface{}, error):
			call(promise, computation)
		case func():
			call1(promise, computation)
		default:
			promise.Resolve(value)
		}
	}()
	return promise
}

// All function returns a promise that resolves when all of the promises in the
// iterable argument have resolved, or rejects with the reason of the first
// passed promise that rejects.
func All(iterable ...interface{}) Promise {
	count := int64(len(iterable))
	if count == 0 {
		return Resolve(nil)
	}
	result := make([]interface{}, count)
	promise := New()
	for index, value := range iterable {
		ToPromise(value).Then(
			allHandler(promise, result, index, &count),
			promise.Reject)
	}
	return promise
}

func allHandler(promise Promise, result []interface{}, index int, count *int64) func(value interface{}) {
	return func(value interface{}) {
		result[index] = value
		if atomic.AddInt64(count, -1) == 0 {
			promise.Resolve(result)
		}
	}
}

// Race function returns a promise that resolves or rejects as soon as one of
// the promises in the iterable resolves or rejects, with the value or reason
// from that promise.
func Race(iterable ...interface{}) Promise {
	promise := New()
	for _, value := range iterable {
		ToPromise(value).Fill(promise)
	}
	return promise
}

// Any function is a competitive race that allows one winner.
//
// The returned promise will fulfill as soon as any one of the input promises
// fulfills, with the value of the fulfilled input promise.
//
// Or reject with a IllegalArgumentError if the input iterable is empty--i.e. it
// is impossible to have one winner.
//
// Or reject with an iterable of all the rejection reasons, if the input
// iterable is non-empty, and all input promises reject.
func Any(iterable ...interface{}) Promise {
	count := int64(len(iterable))
	if count == 0 {
		return Reject(IllegalArgumentError("any(): iterable must not be empty"))
	}
	promise := New()
	for _, value := range iterable {
		ToPromise(value).Then(promise.Resolve, anyHandler(promise, &count))
	}
	return promise
}

func anyHandler(promise Promise, count *int64) func() {
	return func() {
		if atomic.AddInt64(count, -1) == 0 {
			promise.Reject(errors.New("any(): all promises failed"))
		}
	}
}

// Each function executes a provided function once per element of iterable.
//
// The callback parameter is a function to execute for each element:
//
//		func(index int, value interface{})
//
// index: The index of the current element being processed.
//
// value: The current element being processed.
//
// If any of the promises in iterable is rejected, the callback will not be
// executed. the returned promise will be rejected with the rejection reason
// of the first promise that was rejected.
func Each(callback func(int, interface{}), iterable ...interface{}) Promise {
	return All(iterable...).Then(func(a interface{}) {
		if a != nil {
			each(callback, a.([]interface{}))
		}
	})
}

func each(callback func(int, interface{}), iterable []interface{}) {
	for index, value := range iterable {
		callback(index, value)
	}
}

// Every function tests whether all elements in the iterable pass the test
// implemented by the provided function.
//
// The callback parameter is a function to test for each element:
//
//		func(index int, value interface{}) bool
//
// index: The index of the current element being processed.
//
// value: The current element being processed.
//
// If any of the promises in iterable is rejected, the callback will not be
// executed. the returned promise will be rejected with the rejection reason
// of the first promise that was rejected.
//
// The returned promise will fulfill with false if the callback function returns
// false for any iterable element immediately. Otherwise, if callback returned
// a true value for all elements, Every will return promise fulfill with true.
//
// If iterable is empty, The returned promise will fulfill with true.
func Every(callback func(int, interface{}) bool, iterable ...interface{}) Promise {
	return All(iterable...).Then(func(a interface{}) (interface{}, error) {
		if a == nil {
			return true, nil
		}
		return every(callback, a.([]interface{})), nil
	})
}

func every(callback func(int, interface{}) bool, iterable []interface{}) bool {
	for index, value := range iterable {
		if !callback(index, value) {
			return false
		}
	}
	return true
}

// Some function tests whether some element in the iterable passes the test
// implemented by the provided function.
//
// The callback parameter is a function to test for each element:
//
//		func(index int, value interface{}) bool
//
// index: The index of the current element being processed.
//
// value: The current element being processed.
//
// If any of the promises in iterable is rejected, the callback will not be
// executed. the returned promise will be rejected with the rejection reason
// of the first promise that was rejected.
//
// The returned promise will fulfill with true if the callback function returns
// true for any iterable element immediately. Otherwise, if callback returned a
// false value for all elements, Some will return promise fulfill with false.
//
// If iterable is empty, The returned promise will fulfill with false.
func Some(callback func(int, interface{}) bool, iterable ...interface{}) Promise {
	return All(iterable...).Then(func(a interface{}) (interface{}, error) {
		if a == nil {
			return false, nil
		}
		return some(callback, a.([]interface{})), nil
	})
}

func some(callback func(int, interface{}) bool, iterable []interface{}) bool {
	for index, value := range iterable {
		if callback(index, value) {
			return true
		}
	}
	return false
}

// Filter function returns a promise fulfill with a slice that has all elements
// pass the test implemented by the provided function.
//
// The callback parameter is a function to test for each element:
//
//		func(index int, value interface{}) bool
//
// index: The index of the current element being processed.
//
// value: The current element being processed.
//
// If any of the promises in iterable is rejected, the callback will not be
// executed. the returned promise will be rejected with the rejection reason
// of the first promise that was rejected.
func Filter(callback func(int, interface{}) bool, iterable ...interface{}) Promise {
	return All(iterable...).Then(func(a interface{}) (interface{}, error) {
		if a == nil {
			return nil, nil
		}
		return filter(callback, a.([]interface{})), nil
	})
}

func filter(callback func(int, interface{}) bool, iterable []interface{}) []interface{} {
	result := make([]interface{}, 0, len(iterable))
	for index, value := range iterable {
		if callback(index, value) {
			result = append(result, value)
		}
	}
	return result
}

// Map function returns a promise fulfill with a slice that has the results of
// calling a provided function on every element in iterable.
//
// The callback parameter produces an element of the new slice:
//
//		func(index int, value interface{}) interface{}
//
// index: The index of the current element being processed.
//
// value: The current element being processed.
//
// If any of the promises in iterable is rejected, the callback will not be
// executed. the returned promise will be rejected with the rejection reason
// of the first promise that was rejected.
func Map(callback func(int, interface{}) interface{}, iterable ...interface{}) Promise {
	return All(iterable...).Then(func(a interface{}) (interface{}, error) {
		if a == nil {
			return nil, nil
		}
		iterable := a.([]interface{})
		result := make([]interface{}, len(iterable))
		for index, value := range iterable {
			result[index] = callback(index, value)
		}
		return result, nil
	})
}
<|endoftext|>


<commit_before>// Copyright 2015 Matthew Collins
//
// 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 steven

import (
	"runtime"

	"github.com/go-gl/glfw/v3.1/glfw"
	"github.com/thinkofdeath/steven/protocol"
	"github.com/thinkofdeath/steven/render/gl"
)

var window *glfw.Window

func startWindow() {
	runtime.LockOSThread()

	if err := glfw.Init(); err != nil {
		panic(err)
	}
	defer glfw.Terminate()

	glfw.WindowHint(glfw.ContextVersionMajor, 3)
	glfw.WindowHint(glfw.ContextVersionMinor, 2)
	glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile)
	glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True)

	var err error
	window, err = glfw.CreateWindow(800, 480, "Steven", nil, nil)
	if err != nil {
		panic(err)
	}
	window.MakeContextCurrent()
	glfw.SwapInterval(1)

	window.SetCursorPosCallback(onMouseMove)
	window.SetMouseButtonCallback(onMouseClick)
	window.SetKeyCallback(onKey)
	window.SetScrollCallback(onScroll)

	gl.Init()

	start()

	for !window.ShouldClose() {
		draw()
		window.SwapBuffers()
		glfw.PollEvents()
	}
}

func onScroll(w *glfw.Window, xoff float64, yoff float64) {
	if yoff < 0 {
		Client.currentHotbarSlot++
	} else {
		Client.currentHotbarSlot--
	}
	if Client.currentHotbarSlot < 0 {
		Client.currentHotbarSlot = 0
	} else if Client.currentHotbarSlot > 8 {
		Client.currentHotbarSlot = 8
	}

	writeChan <- &protocol.HeldItemChange{Slot: int16(Client.currentHotbarSlot)}
}

var lockMouse bool

func onMouseMove(w *glfw.Window, xpos float64, ypos float64) {
	width, height := w.GetFramebufferSize()
	if currentScreen != nil {
		currentScreen.hover(xpos, ypos, width, height)
		return
	}
	if !lockMouse {
		return
	}
	ww, hh := float64(width/2), float64(height/2)
	w.SetCursorPos(ww, hh)

	rotate((xpos-ww)/2000.0, (ypos-hh)/2000.0)
}

func onMouseClick(w *glfw.Window, button glfw.MouseButton, action glfw.Action, mod glfw.ModifierKey) {
	if currentScreen != nil {
		if button != glfw.MouseButtonLeft || action != glfw.Release {
			return
		}
		width, height := w.GetFramebufferSize()
		xpos, ypos := w.GetCursorPos()
		currentScreen.click(xpos, ypos, width, height)
		return
	}
	if button == glfw.MouseButtonLeft && action == glfw.Press && !Client.chat.enteringText {
		lockMouse = true
		w.SetInputMode(glfw.CursorMode, glfw.CursorDisabled)
	}
}

type Key int

const (
	KeyForward Key = iota
	KeyBackwards
	KeyLeft
	KeyRight
)

func onKey(w *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) {
	if currentScreen != nil {
		return
	}
	if Client.chat.enteringText {
		Client.chat.handleKey(w, key, scancode, action, mods)
		return
	}
	switch key {
	case glfw.KeyEscape:
		lockMouse = false
		w.SetInputMode(glfw.CursorMode, glfw.CursorNormal)
	case glfw.KeyW:
		if action != glfw.Repeat {
			Client.KeyState[KeyForward] = action == glfw.Press
		}
	case glfw.KeyS:
		if action != glfw.Repeat {
			Client.KeyState[KeyBackwards] = action == glfw.Press
		}
	case glfw.KeyA:
		if action != glfw.Repeat {
			Client.KeyState[KeyLeft] = action == glfw.Press
		}
	case glfw.KeyD:
		if action != glfw.Repeat {
			Client.KeyState[KeyRight] = action == glfw.Press
		}
	case glfw.KeyF1:
		if action == glfw.Release {
			if Client.scene.IsVisible() {
				Client.scene.Hide()
			} else {
				Client.scene.Show()
			}
		}
	case glfw.KeyF2:
		if action == glfw.Release {
			conn.Close()
		}
	case glfw.KeyF3:
		if action == glfw.Release {
			Client.toggleDebug()
		}
	case glfw.KeyTab:
		if action == glfw.Press {
			Client.playerList.set(true)
		} else if action == glfw.Release {
			Client.playerList.set(false)
		}
	case glfw.KeyT, glfw.KeySlash:
		Client.chat.enteringText = true
		Client.chat.first = true
		if key == glfw.KeySlash {
			Client.chat.inputLine = append(Client.chat.inputLine, '/')
		}
		lockMouse = false
		w.SetInputMode(glfw.CursorMode, glfw.CursorNormal)
		w.SetCharCallback(Client.chat.handleChar)
	case glfw.KeySpace:
		if action != glfw.Repeat {
			Client.Jumping = action == glfw.Press
		}
	}
}
<commit_msg>steven: fix deadlock when using the scroll wheel on the main menu<commit_after>// Copyright 2015 Matthew Collins
//
// 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 steven

import (
	"runtime"

	"github.com/go-gl/glfw/v3.1/glfw"
	"github.com/thinkofdeath/steven/protocol"
	"github.com/thinkofdeath/steven/render/gl"
)

var window *glfw.Window

func startWindow() {
	runtime.LockOSThread()

	if err := glfw.Init(); err != nil {
		panic(err)
	}
	defer glfw.Terminate()

	glfw.WindowHint(glfw.ContextVersionMajor, 3)
	glfw.WindowHint(glfw.ContextVersionMinor, 2)
	glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile)
	glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True)

	var err error
	window, err = glfw.CreateWindow(800, 480, "Steven", nil, nil)
	if err != nil {
		panic(err)
	}
	window.MakeContextCurrent()
	glfw.SwapInterval(1)

	window.SetCursorPosCallback(onMouseMove)
	window.SetMouseButtonCallback(onMouseClick)
	window.SetKeyCallback(onKey)
	window.SetScrollCallback(onScroll)

	gl.Init()

	start()

	for !window.ShouldClose() {
		draw()
		window.SwapBuffers()
		glfw.PollEvents()
	}
}

func onScroll(w *glfw.Window, xoff float64, yoff float64) {
	if currentScreen != nil || !ready {
		return
	}
	if yoff < 0 {
		Client.currentHotbarSlot++
	} else {
		Client.currentHotbarSlot--
	}
	if Client.currentHotbarSlot < 0 {
		Client.currentHotbarSlot = 0
	} else if Client.currentHotbarSlot > 8 {
		Client.currentHotbarSlot = 8
	}

	writeChan <- &protocol.HeldItemChange{Slot: int16(Client.currentHotbarSlot)}
}

var lockMouse bool

func onMouseMove(w *glfw.Window, xpos float64, ypos float64) {
	width, height := w.GetFramebufferSize()
	if currentScreen != nil {
		currentScreen.hover(xpos, ypos, width, height)
		return
	}
	if !lockMouse {
		return
	}
	ww, hh := float64(width/2), float64(height/2)
	w.SetCursorPos(ww, hh)

	rotate((xpos-ww)/2000.0, (ypos-hh)/2000.0)
}

func onMouseClick(w *glfw.Window, button glfw.MouseButton, action glfw.Action, mod glfw.ModifierKey) {
	if currentScreen != nil {
		if button != glfw.MouseButtonLeft || action != glfw.Release {
			return
		}
		width, height := w.GetFramebufferSize()
		xpos, ypos := w.GetCursorPos()
		currentScreen.click(xpos, ypos, width, height)
		return
	}
	if button == glfw.MouseButtonLeft && action == glfw.Press && !Client.chat.enteringText {
		lockMouse = true
		w.SetInputMode(glfw.CursorMode, glfw.CursorDisabled)
	}
}

type Key int

const (
	KeyForward Key = iota
	KeyBackwards
	KeyLeft
	KeyRight
)

func onKey(w *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) {
	if currentScreen != nil {
		return
	}
	if Client.chat.enteringText {
		Client.chat.handleKey(w, key, scancode, action, mods)
		return
	}
	switch key {
	case glfw.KeyEscape:
		lockMouse = false
		w.SetInputMode(glfw.CursorMode, glfw.CursorNormal)
	case glfw.KeyW:
		if action != glfw.Repeat {
			Client.KeyState[KeyForward] = action == glfw.Press
		}
	case glfw.KeyS:
		if action != glfw.Repeat {
			Client.KeyState[KeyBackwards] = action == glfw.Press
		}
	case glfw.KeyA:
		if action != glfw.Repeat {
			Client.KeyState[KeyLeft] = action == glfw.Press
		}
	case glfw.KeyD:
		if action != glfw.Repeat {
			Client.KeyState[KeyRight] = action == glfw.Press
		}
	case glfw.KeyF1:
		if action == glfw.Release {
			if Client.scene.IsVisible() {
				Client.scene.Hide()
			} else {
				Client.scene.Show()
			}
		}
	case glfw.KeyF2:
		if action == glfw.Release {
			conn.Close()
		}
	case glfw.KeyF3:
		if action == glfw.Release {
			Client.toggleDebug()
		}
	case glfw.KeyTab:
		if action == glfw.Press {
			Client.playerList.set(true)
		} else if action == glfw.Release {
			Client.playerList.set(false)
		}
	case glfw.KeyT, glfw.KeySlash:
		Client.chat.enteringText = true
		Client.chat.first = true
		if key == glfw.KeySlash {
			Client.chat.inputLine = append(Client.chat.inputLine, '/')
		}
		lockMouse = false
		w.SetInputMode(glfw.CursorMode, glfw.CursorNormal)
		w.SetCharCallback(Client.chat.handleChar)
	case glfw.KeySpace:
		if action != glfw.Repeat {
			Client.Jumping = action == glfw.Press
		}
	}
}
<|endoftext|>


<commit_before>// +build linux

package linux

import (
	"bufio"
	"fmt"
	"os"
	"regexp"
	"strconv"
	"time"

	"github.com/mackerelio/mackerel-agent/logging"
	"github.com/mackerelio/mackerel-agent/metrics"
)

/*
collect network interface I/O

`interface.{interface}.{metric}.delta`: The increased amount of network I/O per minute retrieved from /proc/net/dev

interface = "eth0", "eth1" and so on...

metric = "rxBytes", "rxPackets", "rxErrors", "rxDrops", "rxFifo", "rxFrame", "rxCompressed", "rxMulticast", "txBytes", "txPackets", "txErrors", "txDrops", "txFifo", "txColls", "txCarrier", "txCompressed"

cat /proc/net/dev sample:
	Inter-|   Receive                                                |  Transmit
	 face |bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo colls carrier compressed
	eth0: 5461472598 24386569    0    2    0     0          0         0 7215710422 6079810    0    0    0     0       0          0
	lo: 7779878638 1952628    0    0    0     0          0         0 7779878638 1952628    0    0    0     0       0          0
	docker0: 250219988  333736    0    0    0     0          0         0 2024726607 1409929    0    0    0     0       0          0
*/

// InterfaceGenerator XXX
type InterfaceGenerator struct {
	Interval time.Duration
}

var interfaceMetrics = []string{
	"rxBytes", "rxPackets", "rxErrors", "rxDrops",
	"rxFifo", "rxFrame", "rxCompressed", "rxMulticast",
	"txBytes", "txPackets", "txErrors", "txDrops",
	"txFifo", "txColls", "txCarrier", "txCompressed",
}

// metrics for posting to Mackerel
var postInterfaceMetricsRegexp = regexp.MustCompile(`^interface\..+\.(rxBytes|txBytes)$`)

var interfaceLogger = logging.GetLogger("metrics.interface")

// Generate XXX
func (g *InterfaceGenerator) Generate() (metrics.Values, error) {
	prevValues, err := g.collectIntarfacesValues()
	if err != nil {
		return nil, err
	}

	time.Sleep(g.Interval)

	currValues, err := g.collectIntarfacesValues()
	if err != nil {
		return nil, err
	}

	ret := make(map[string]float64)
	for name, value := range prevValues {
		if !postInterfaceMetricsRegexp.MatchString(name) {
			continue
		}
		currValue, ok := currValues[name]
		if ok {
			ret[name+".delta"] = (currValue - value) / g.Interval.Seconds()
		}
	}

	return metrics.Values(ret), nil
}

func (g *InterfaceGenerator) collectIntarfacesValues() (metrics.Values, error) {
	file, err := os.Open("/proc/net/dev")
	if err != nil {
		interfaceLogger.Errorf("Failed (skip these metrics): %s", err)
		return nil, err
	}

	lineScanner := bufio.NewScanner(bufio.NewReader(file))
	results := make(map[string]float64)
	for lineScanner.Scan() {
		line := lineScanner.Text()
		if matches := regexp.MustCompile(`^\s*([^:]+):\s*(.*)$`).FindStringSubmatch(line); matches != nil {
			name := regexp.MustCompile(`[^A-Za-z0-9_-]`).ReplaceAllString(matches[1], "_")
			if name == "lo" {
				continue
			}

			cols := regexp.MustCompile(`\s+`).Split(matches[2], len(interfaceMetrics))
			if len(cols) < len(interfaceMetrics) {
				continue
			}

			interfaceResult := make(map[string]float64)
			hasNonZeroValue := false
			for i := range interfaceMetrics {
				key := fmt.Sprintf("interface.%s.%s", name, interfaceMetrics[i])
				value, err := strconv.ParseFloat(cols[i], 64)
				if err != nil {
					interfaceLogger.Warningf("Failed to parse host interfaces: %s", err)
					break
				}
				if value != 0 {
					hasNonZeroValue = true
				}
				interfaceResult[key] = value
			}
			if hasNonZeroValue {
				for k, v := range interfaceResult {
					results[k] = v
				}
			}
		}
	}

	// results (eth0) sample
	/** [%!s(*metrics.Value=&{interface.eth0.rxBytes 6.6074069281e+10})
	     %!s(*metrics.Value=&{interface.eth0.rxPackets 1.0483646e+08})
	     %!s(*metrics.Value=&{interface.eth0.rxErrors 0})
	     %!s(*metrics.Value=&{interface.eth0.rxDrops 1})
	     %!s(*metrics.Value=&{interface.eth0.rxFifo 0})
	     %!s(*metrics.Value=&{interface.eth0.rxFrame 0})
	     %!s(*metrics.Value=&{interface.eth0.rxCompressed 0})
	     %!s(*metrics.Value=&{interface.eth0.rxMulticast 0})
	     %!s(*metrics.Value=&{interface.eth0.txBytes 9.180531994e+09})
	     %!s(*metrics.Value=&{interface.eth0.txPackets 5.3107958e+07})
	     %!s(*metrics.Value=&{interface.eth0.txErrors 0})
	     %!s(*metrics.Value=&{interface.eth0.txDrops 0})
	     %!s(*metrics.Value=&{interface.eth0.txFifo 0})
	     %!s(*metrics.Value=&{interface.eth0.txColls 0})
	     %!s(*metrics.Value=&{interface.eth0.txCarrier 0})
	     %!s(*metrics.Value=&{interface.eth0.txCompressed 0})
	    ]
	**/

	return metrics.Values(results), nil
}
<commit_msg>fix typo<commit_after>// +build linux

package linux

import (
	"bufio"
	"fmt"
	"os"
	"regexp"
	"strconv"
	"time"

	"github.com/mackerelio/mackerel-agent/logging"
	"github.com/mackerelio/mackerel-agent/metrics"
)

/*
collect network interface I/O

`interface.{interface}.{metric}.delta`: The increased amount of network I/O per minute retrieved from /proc/net/dev

interface = "eth0", "eth1" and so on...

metric = "rxBytes", "rxPackets", "rxErrors", "rxDrops", "rxFifo", "rxFrame", "rxCompressed", "rxMulticast", "txBytes", "txPackets", "txErrors", "txDrops", "txFifo", "txColls", "txCarrier", "txCompressed"

cat /proc/net/dev sample:
	Inter-|   Receive                                                |  Transmit
	 face |bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo colls carrier compressed
	eth0: 5461472598 24386569    0    2    0     0          0         0 7215710422 6079810    0    0    0     0       0          0
	lo: 7779878638 1952628    0    0    0     0          0         0 7779878638 1952628    0    0    0     0       0          0
	docker0: 250219988  333736    0    0    0     0          0         0 2024726607 1409929    0    0    0     0       0          0
*/

// InterfaceGenerator XXX
type InterfaceGenerator struct {
	Interval time.Duration
}

var interfaceMetrics = []string{
	"rxBytes", "rxPackets", "rxErrors", "rxDrops",
	"rxFifo", "rxFrame", "rxCompressed", "rxMulticast",
	"txBytes", "txPackets", "txErrors", "txDrops",
	"txFifo", "txColls", "txCarrier", "txCompressed",
}

// metrics for posting to Mackerel
var postInterfaceMetricsRegexp = regexp.MustCompile(`^interface\..+\.(rxBytes|txBytes)$`)

var interfaceLogger = logging.GetLogger("metrics.interface")

// Generate XXX
func (g *InterfaceGenerator) Generate() (metrics.Values, error) {
	prevValues, err := g.collectInterfacesValues()
	if err != nil {
		return nil, err
	}

	time.Sleep(g.Interval)

	currValues, err := g.collectInterfacesValues()
	if err != nil {
		return nil, err
	}

	ret := make(map[string]float64)
	for name, value := range prevValues {
		if !postInterfaceMetricsRegexp.MatchString(name) {
			continue
		}
		currValue, ok := currValues[name]
		if ok {
			ret[name+".delta"] = (currValue - value) / g.Interval.Seconds()
		}
	}

	return metrics.Values(ret), nil
}

func (g *InterfaceGenerator) collectInterfacesValues() (metrics.Values, error) {
	file, err := os.Open("/proc/net/dev")
	if err != nil {
		interfaceLogger.Errorf("Failed (skip these metrics): %s", err)
		return nil, err
	}

	lineScanner := bufio.NewScanner(bufio.NewReader(file))
	results := make(map[string]float64)
	for lineScanner.Scan() {
		line := lineScanner.Text()
		if matches := regexp.MustCompile(`^\s*([^:]+):\s*(.*)$`).FindStringSubmatch(line); matches != nil {
			name := regexp.MustCompile(`[^A-Za-z0-9_-]`).ReplaceAllString(matches[1], "_")
			if name == "lo" {
				continue
			}

			cols := regexp.MustCompile(`\s+`).Split(matches[2], len(interfaceMetrics))
			if len(cols) < len(interfaceMetrics) {
				continue
			}

			interfaceResult := make(map[string]float64)
			hasNonZeroValue := false
			for i := range interfaceMetrics {
				key := fmt.Sprintf("interface.%s.%s", name, interfaceMetrics[i])
				value, err := strconv.ParseFloat(cols[i], 64)
				if err != nil {
					interfaceLogger.Warningf("Failed to parse host interfaces: %s", err)
					break
				}
				if value != 0 {
					hasNonZeroValue = true
				}
				interfaceResult[key] = value
			}
			if hasNonZeroValue {
				for k, v := range interfaceResult {
					results[k] = v
				}
			}
		}
	}

	// results (eth0) sample
	/** [%!s(*metrics.Value=&{interface.eth0.rxBytes 6.6074069281e+10})
	     %!s(*metrics.Value=&{interface.eth0.rxPackets 1.0483646e+08})
	     %!s(*metrics.Value=&{interface.eth0.rxErrors 0})
	     %!s(*metrics.Value=&{interface.eth0.rxDrops 1})
	     %!s(*metrics.Value=&{interface.eth0.rxFifo 0})
	     %!s(*metrics.Value=&{interface.eth0.rxFrame 0})
	     %!s(*metrics.Value=&{interface.eth0.rxCompressed 0})
	     %!s(*metrics.Value=&{interface.eth0.rxMulticast 0})
	     %!s(*metrics.Value=&{interface.eth0.txBytes 9.180531994e+09})
	     %!s(*metrics.Value=&{interface.eth0.txPackets 5.3107958e+07})
	     %!s(*metrics.Value=&{interface.eth0.txErrors 0})
	     %!s(*metrics.Value=&{interface.eth0.txDrops 0})
	     %!s(*metrics.Value=&{interface.eth0.txFifo 0})
	     %!s(*metrics.Value=&{interface.eth0.txColls 0})
	     %!s(*metrics.Value=&{interface.eth0.txCarrier 0})
	     %!s(*metrics.Value=&{interface.eth0.txCompressed 0})
	    ]
	**/

	return metrics.Values(results), nil
}
<|endoftext|>


<commit_before>// warren takes home monitoring data and feeds it into
// [seriesly](https://github.com/dustin/seriesly).
package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"strconv"
	"syscall"
	"time"

	"github.com/huin/gocc"
)

var (
	serieslyUrl  = flag.String("seriesly-url", "", "HTTP URL to Seriesly server database, e.g http://localhost:3133/db")
	ccSerialPort = flag.String("cc-port", "/dev/ttyUSB0", "Filesystem path to Current Cost serial port")
	logPath      = flag.String("log-path", "", "Log to file, default logs to STDERR.")
)

func initLogging() {
	if *logPath == "" {
		// Leave default logging as STDERR.
		return
	}

	f, err := os.OpenFile(*logPath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, syscall.S_IWUSR|syscall.S_IRUSR)
	if err != nil {
		log.Fatalf("Failed to open log file: %v", err)
	}
	log.SetOutput(f)
}

type ccMsg struct {
	Temperature *float32       `json:"temperature,omitempty"`
	Watts       map[string]int `json:"watts,omitempty"`
}

func currentCost() error {
	msgReader, err := gocc.NewSerialMessageReader(*ccSerialPort)
	if err != nil {
		return err
	}
	defer msgReader.Close()

	for {
		msg, err := msgReader.ReadMessage()
		if err != nil {
			return err
		}

		data := &ccMsg{}
		data.Temperature = msg.Temperature
		if msg.Sensor != nil && *msg.Sensor >= 0 && msg.Channel1 != nil {
			data.Watts = map[string]int{strconv.Itoa(*msg.Sensor): msg.Channel1.Watts}
		}

		jsonData, err := json.Marshal(data)
		if len(jsonData) == 2 {
			// No data - "{}".
			continue
		}
		if err != nil {
			log.Printf("Error encoding Current Cost data as JSON: %v", err)
		}
		log.Printf("jsonData = %s", jsonData)
		reqBuf := bytes.NewBuffer(jsonData)
		resp, err := http.Post(*serieslyUrl, "application/json", reqBuf)
		if err != nil {
			log.Printf("Error sending JSON to %s: %v", *serieslyUrl, err)
		} else if resp.StatusCode != http.StatusCreated {
			respBuf := &bytes.Buffer{}
			_, _ = io.CopyN(respBuf, resp.Body, 80)
			log.Printf("HTTP response status %d, body: %s", resp.StatusCode, respBuf.Bytes())
			_, _ = io.Copy(ioutil.Discard, resp.Body)
			resp.Body.Close()
		}
	}
	panic("unreachable")
}

func main() {
	flag.Parse()
	initLogging()

	if *serieslyUrl == "" {
		log.Fatal("Bad value for --seriesly-url")
	}

	for {
		log.Print("Current Cost monitoring error: %v", currentCost())

		// Avoid tightlooping on recurring failure.
		time.Sleep(5 * time.Second)
	}
}
<commit_msg>Fix file descriptor leak.<commit_after>// warren takes home monitoring data and feeds it into
// [seriesly](https://github.com/dustin/seriesly).
package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"strconv"
	"syscall"
	"time"

	"github.com/huin/gocc"
)

var (
	serieslyUrl  = flag.String("seriesly-url", "", "HTTP URL to Seriesly server database, e.g http://localhost:3133/db")
	ccSerialPort = flag.String("cc-port", "/dev/ttyUSB0", "Filesystem path to Current Cost serial port")
	logPath      = flag.String("log-path", "", "Log to file, default logs to STDERR.")
)

func initLogging() {
	if *logPath == "" {
		// Leave default logging as STDERR.
		return
	}

	f, err := os.OpenFile(*logPath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, syscall.S_IWUSR|syscall.S_IRUSR)
	if err != nil {
		log.Fatalf("Failed to open log file: %v", err)
	}
	log.SetOutput(f)
}

type ccMsg struct {
	Temperature *float32       `json:"temperature,omitempty"`
	Watts       map[string]int `json:"watts,omitempty"`
}

func currentCost() error {
	msgReader, err := gocc.NewSerialMessageReader(*ccSerialPort)
	if err != nil {
		return err
	}
	defer msgReader.Close()

	for {
		msg, err := msgReader.ReadMessage()
		if err != nil {
			return err
		}

		data := &ccMsg{}
		data.Temperature = msg.Temperature
		if msg.Sensor != nil && *msg.Sensor >= 0 && msg.Channel1 != nil {
			data.Watts = map[string]int{strconv.Itoa(*msg.Sensor): msg.Channel1.Watts}
		}

		jsonData, err := json.Marshal(data)
		if len(jsonData) == 2 {
			// No data - "{}".
			continue
		}
		if err != nil {
			log.Printf("Error encoding Current Cost data as JSON: %v", err)
		}
		log.Printf("jsonData = %s", jsonData)
		reqBuf := bytes.NewBuffer(jsonData)
		resp, err := http.Post(*serieslyUrl, "application/json", reqBuf)
		if err != nil {
			log.Printf("Error sending JSON to %s: %v", *serieslyUrl, err)
		} else {
			if resp.StatusCode != http.StatusCreated {
				respBuf := &bytes.Buffer{}
				_, _ = io.CopyN(respBuf, resp.Body, 80)
				log.Printf("Unexpected HTTP response status %d, body: %s", resp.StatusCode, respBuf.Bytes())
			}
			_, _ = io.Copy(ioutil.Discard, resp.Body)
			resp.Body.Close()
		}
	}
	panic("unreachable")
}

func main() {
	flag.Parse()
	initLogging()

	if *serieslyUrl == "" {
		log.Fatal("Bad value for --seriesly-url")
	}

	for {
		log.Print("Current Cost monitoring error: %v", currentCost())

		// Avoid tightlooping on recurring failure.
		time.Sleep(5 * time.Second)
	}
}
<|endoftext|>


<commit_before>package cloudca

import (
	"encoding/json"
	"github.com/cloud-ca/go-cloudca/api"
	"github.com/cloud-ca/go-cloudca/services"
)

type ComputeOffering struct {
	Id        string `json:"id,omitempty"`
	Name      string `json:"name,omitempty"`
	Memory    int    `json:"memory,omitempty"`
	CpuNumber int    `json:"cpuNumber,omitempty"`
}

type ComputeOfferingService interface {
	Get(id string) (*ComputeOffering, error)
	List() ([]ComputeOffering, error)
	ListWithOptions(options map[string]string) ([]ComputeOffering, error)
}

type ComputeOfferingApi struct {
	entityService services.EntityService
}

func NewComputeOfferingService(apiClient api.ApiClient, serviceCode string, environmentName string) ComputeOfferingService {
	return &ComputeOfferingApi{
		entityService: services.NewEntityService(apiClient, serviceCode, environmentName, COMPUTE_OFFERING_ENTITY_TYPE),
	}
}

func parseComputeOffering(data []byte) *ComputeOffering {
	computeOffering := ComputeOffering{}
	json.Unmarshal(data, &computeOffering)
	return &computeOffering
}

func parseComputeOfferingList(data []byte) []ComputeOffering {
	computeOfferings := []ComputeOffering{}
	json.Unmarshal(data, &computeOfferings)
	return computeOfferings
}

//Get compute offering with the specified id for the current environment
func (computeOfferingApi *ComputeOfferingApi) Get(id string) (*ComputeOffering, error) {
	data, err := computeOfferingApi.entityService.Get(id, map[string]string{})
	if err != nil {
		return nil, err
	}
	return parseComputeOffering(data), nil
}

//List all compute offerings for the current environment
func (computeOfferingApi *ComputeOfferingApi) List() ([]ComputeOffering, error) {
	return computeOfferingApi.ListWithOptions(map[string]string{})
}

//List all compute offerings for the current environment. Can use options to do sorting and paging.
func (computeOfferingApi *ComputeOfferingApi) ListWithOptions(options map[string]string) ([]ComputeOffering, error) {
	data, err := computeOfferingApi.entityService.List(options)
	if err != nil {
		return nil, err
	}
	return parseComputeOfferingList(data), nil
}
<commit_msg>Updated compute offering fields<commit_after>package cloudca

import (
	"encoding/json"
	"github.com/cloud-ca/go-cloudca/api"
	"github.com/cloud-ca/go-cloudca/services"
)

type ComputeOffering struct {
	Id            string `json:"id,omitempty"`
	Name          string `json:"name,omitempty"`
	MemoryInMB    int    `json:"memoryInMB,omitempty"`
	CpuCount      int    `json:"cpuCount,omitempty"`
   Custom        bool    `json:"custom,omitempty"`
}

type ComputeOfferingService interface {
	Get(id string) (*ComputeOffering, error)
	List() ([]ComputeOffering, error)
	ListWithOptions(options map[string]string) ([]ComputeOffering, error)
}

type ComputeOfferingApi struct {
	entityService services.EntityService
}

func NewComputeOfferingService(apiClient api.ApiClient, serviceCode string, environmentName string) ComputeOfferingService {
	return &ComputeOfferingApi{
		entityService: services.NewEntityService(apiClient, serviceCode, environmentName, COMPUTE_OFFERING_ENTITY_TYPE),
	}
}

func parseComputeOffering(data []byte) *ComputeOffering {
	computeOffering := ComputeOffering{}
	json.Unmarshal(data, &computeOffering)
	return &computeOffering
}

func parseComputeOfferingList(data []byte) []ComputeOffering {
	computeOfferings := []ComputeOffering{}
	json.Unmarshal(data, &computeOfferings)
	return computeOfferings
}

//Get compute offering with the specified id for the current environment
func (computeOfferingApi *ComputeOfferingApi) Get(id string) (*ComputeOffering, error) {
	data, err := computeOfferingApi.entityService.Get(id, map[string]string{})
	if err != nil {
		return nil, err
	}
	return parseComputeOffering(data), nil
}

//List all compute offerings for the current environment
func (computeOfferingApi *ComputeOfferingApi) List() ([]ComputeOffering, error) {
	return computeOfferingApi.ListWithOptions(map[string]string{})
}

//List all compute offerings for the current environment. Can use options to do sorting and paging.
func (computeOfferingApi *ComputeOfferingApi) ListWithOptions(options map[string]string) ([]ComputeOffering, error) {
	data, err := computeOfferingApi.entityService.List(options)
	if err != nil {
		return nil, err
	}
	return parseComputeOfferingList(data), nil
}
<|endoftext|>


<commit_before>package v2ray

import (
	"context"
	"errors"
	"fmt"
	"io"
	"log"
	"net"
	"sync"

	vcore "v2ray.com/core"
	vnet "v2ray.com/core/common/net"
	vsession "v2ray.com/core/common/session"

	"github.com/eycorsican/go-tun2socks/core"
	"github.com/eycorsican/go-tun2socks/proxy"
)

type connEntry struct {
	conn   net.Conn
	target vnet.Destination
}

type handler struct {
	sync.Mutex

	ctx      context.Context
	v        *vcore.Instance
	conns    map[core.Connection]*connEntry
	dnsCache *proxy.DNSCache
}

func (h *handler) fetchInput(conn core.Connection) {
	defer func() {
		h.Close(conn)
		conn.Close() // also close tun2socks connection here
	}()

	h.Lock()
	c, ok := h.conns[conn]
	h.Unlock()
	if !ok {
		return
	}

	// Seems a DNS response, cache it
	if c.target.Network == vnet.Network_UDP && c.target.Port.Value() == proxy.COMMON_DNS_PORT {
		buf := core.NewBytes(core.BufSize)
		defer core.FreeBytes(buf)
		for {
			n, err := c.conn.Read(buf)
			if err != nil {
				log.Printf("fetch input failed: %v", err)
				return
			}
			_, err = conn.Write(buf[:n])
			if err != nil {
				log.Printf("write local failed: %v", err)
				return
			}
			h.dnsCache.Store(buf[:n])
			return // DNS responses
		}
	} else {
		_, err := io.Copy(conn, c.conn)
		if err != nil {
			log.Printf("fetch input failed: %v", err)
		}
	}
}

func NewHandler(ctx context.Context, instance *vcore.Instance) core.ConnectionHandler {
	return &handler{
		ctx:      ctx,
		v:        instance,
		conns:    make(map[core.Connection]*connEntry, 16),
		dnsCache: proxy.NewDNSCache(),
	}
}

func (h *handler) Connect(conn core.Connection, target net.Addr) error {
	dest := vnet.DestinationFromAddr(target)
	sid := vsession.NewID()
	ctx := vsession.ContextWithID(h.ctx, sid)
	c, err := vcore.Dial(ctx, h.v, dest)
	if err != nil {
		return errors.New(fmt.Sprintf("dial V proxy connection failed: %v", err))
	}
	h.Lock()
	h.conns[conn] = &connEntry{conn: c, target: dest}
	h.Unlock()
	go h.fetchInput(conn)
	return nil
}

func (h *handler) DidReceive(conn core.Connection, data []byte) error {
	h.Lock()
	c, ok := h.conns[conn]
	h.Unlock()
	if ok {
		// Seems a DNS request, try to find the record in the cache first.
		if c.target.Network == vnet.Network_UDP && c.target.Port.Value() == proxy.COMMON_DNS_PORT {
			if answer := h.dnsCache.Query(data); answer != nil {
				var buf [1024]byte
				if dnsAnswer, err := answer.PackBuffer(buf[:]); err == nil {
					_, err = conn.Write(dnsAnswer)
					if err != nil {
						return errors.New(fmt.Sprintf("cache dns answer failed: %v", err))
					}
					h.Close(conn)
					conn.Close() // also close tun2socks connection here
					return nil
				}
			}
		}

		_, err := c.conn.Write(data)
		if err != nil {
			h.Close(conn)
			return errors.New(fmt.Sprintf("write remote failed: %v", err))
		}
		return nil
	} else {
		h.Close(conn)
		return errors.New(fmt.Sprintf("proxy connection %v->%v does not exists", conn.LocalAddr(), conn.RemoteAddr()))
	}
}

func (h *handler) DidSend(conn core.Connection, len uint16) {
	// unused
}

func (h *handler) DidClose(conn core.Connection) {
	h.Close(conn)
}

func (h *handler) LocalDidClose(conn core.Connection) {
	h.Close(conn)
}

func (h *handler) Close(conn core.Connection) {
	h.Lock()
	defer h.Unlock()

	if c, found := h.conns[conn]; found {
		c.conn.Close()
	}
	delete(h.conns, conn)
}
<commit_msg>use v2ray's dns client for dns handling<commit_after>package v2ray

import (
	"context"
	"errors"
	"fmt"
	"log"
	"net"
	"sync"
	"time"

	"github.com/miekg/dns"
	vcore "v2ray.com/core"
	vnet "v2ray.com/core/common/net"
	vsession "v2ray.com/core/common/session"
	vdns "v2ray.com/core/features/dns"

	"github.com/eycorsican/go-tun2socks/core"
	"github.com/eycorsican/go-tun2socks/proxy"
)

func isIPv4(ip net.IP) bool {
	if ip.To4() != nil {
		return true
	}
	return false
}

func isIPv6(ip net.IP) bool {
	// To16() also valid for ipv4, ensure it's not an ipv4 address
	if ip.To4() != nil {
		return false
	}
	if ip.To16() != nil {
		return true
	}
	return false
}

type connEntry struct {
	conn                net.Conn
	target              vnet.Destination
	cancelFetchingInput context.CancelFunc
	fetchingInputCtx    context.Context
}

type dnsRespEntry struct {
	err  error
	data []byte
	conn core.Connection
}

type handler struct {
	sync.Mutex

	ctx        context.Context
	v          *vcore.Instance
	conns      map[core.Connection]*connEntry
	dispatched map[core.Connection]bool
	dnsRespCh  chan *dnsRespEntry
	dnsClient  vdns.Client
}

func (h *handler) shouldAcceptDNSQuery(data []byte) bool {
	req := new(dns.Msg)
	err := req.Unpack(data)
	if err != nil {
		return false
	}

	// TODO: allow multiple question
	if len(req.Question) != 1 {
		return false
	}

	qtype := req.Question[0].Qtype
	if qtype != dns.TypeA && qtype != dns.TypeAAAA {
		return false
	}

	fqdn := req.Question[0].Name
	domain := fqdn[:len(fqdn)-1]

	if _, ok := dns.IsDomainName(domain); !ok {
		return false
	}

	return true
}

func (h *handler) handleDNSQuery(conn core.Connection, data []byte) {
	var err error
	var answer []byte = nil
	defer func() {
		h.dnsRespCh <- &dnsRespEntry{conn: conn, data: answer, err: err}
	}()

	req := new(dns.Msg)
	err = req.Unpack(data)
	if err != nil {
		// TODO checks should already done in shouldAcceptDNSQeury(), can't be failed.
		// Leaving them for debugging purposes, remove later.
		log.Fatal(errors.New(fmt.Sprintf("unpacking dns msg failed: %v", err)))
	}
	if len(req.Question) == 0 {
		log.Fatal(errors.New("no question in dns msg"))
	}
	qtype := req.Question[0].Qtype
	if qtype != dns.TypeA && qtype != dns.TypeAAAA {
		log.Fatal(errors.New(fmt.Sprintf("not A or AAAA query type, qtype: %v", qtype)))
	}
	fqdn := req.Question[0].Name
	domain := fqdn[:len(fqdn)-1]

	ips, err := h.dnsClient.LookupIP(domain)
	if err != nil {
		err = errors.New(fmt.Sprintf("lookup ip failed: %v", err))
		return
	}

	resp := new(dns.Msg)
	resp.SetReply(req)
	// resp.Authoritative = true
	resp.RecursionAvailable = true
	for _, ip := range ips {
		if isIPv4(ip) && qtype == dns.TypeA {
			resp.Answer = append(resp.Answer, &dns.A{
				Hdr: dns.RR_Header{
					Name:     fqdn,
					Rrtype:   dns.TypeA,
					Class:    dns.ClassINET,
					Ttl:      1, // cached in V2Ray
					Rdlength: 4,
				},
				A: ip,
			})
		} else if isIPv6(ip) && qtype == dns.TypeAAAA {
			resp.Answer = append(resp.Answer, &dns.AAAA{
				Hdr: dns.RR_Header{
					Name:     fqdn,
					Rrtype:   dns.TypeAAAA,
					Class:    dns.ClassINET,
					Ttl:      1, // cached in V2Ray
					Rdlength: 16,
				},
				AAAA: ip,
			})
		}
	}
	if len(resp.Answer) == 0 {
		err = errors.New("no answer")
		return
	}
	buf := core.NewBytes(core.BufSize)
	defer core.FreeBytes(buf)
	dnsAnswer, err := resp.PackBuffer(buf)
	if err != nil {
		err = errors.New(fmt.Sprintf("packing dns resp msg failed: %v", err))
	} else {
		answer = append([]byte(nil), dnsAnswer...)
	}
	return
}

func (h *handler) handleDNSResponse() {
	for {
		select {
		case respEntry := <-h.dnsRespCh:
			if respEntry.err == nil {
				_, err := respEntry.conn.Write(respEntry.data)
				if err != nil {
					log.Printf("write dns response to local failed: %v", err)
				}
			} else {
				log.Printf("dispatch dns request failed: %v", respEntry.err)
			}
			h.Close(respEntry.conn)
			respEntry.conn.Close()
		}
	}
}

func (h *handler) fetchInput(conn core.Connection) {
	h.Lock()
	c, ok := h.conns[conn]
	h.Unlock()
	if !ok {
		return
	}

	buf := core.NewBytes(core.BufSize)

FetchingLoop:
	for {
		c.conn.SetReadDeadline(time.Now().Add(4 * time.Second))
		n, err := c.conn.Read(buf)
		if err, ok := err.(net.Error); ok && err.Timeout() {
			select {
			case <-c.fetchingInputCtx.Done():
				core.FreeBytes(buf)
				// Request was handed to V2Ray, stop fetching but leave the
				// connection open.
				return
			default:
				continue FetchingLoop
			}
		}
		if err != nil {
			log.Printf("fetch input failed: %v", err)
			h.Close(conn)
			conn.Close()
			core.FreeBytes(buf)
			return
		}
		_, err = conn.Write(buf[:n])
		if err != nil {
			log.Printf("write local failed: %v", err)
			h.Close(conn)
			conn.Close()
			core.FreeBytes(buf)
			return
		}
	}
}

func NewHandler(ctx context.Context, instance *vcore.Instance) core.ConnectionHandler {
	h := &handler{
		ctx:        ctx,
		v:          instance,
		conns:      make(map[core.Connection]*connEntry, 16),
		dnsRespCh:  make(chan *dnsRespEntry, 1024),
		dispatched: make(map[core.Connection]bool, 16),
		dnsClient:  instance.GetFeature(vdns.ClientType()).(vdns.Client),
	}
	go h.handleDNSResponse()
	return h
}

func (h *handler) Connect(conn core.Connection, target net.Addr) error {
	dest := vnet.DestinationFromAddr(target)
	sid := vsession.NewID()
	ctx := vsession.ContextWithID(h.ctx, sid)
	c, err := vcore.Dial(ctx, h.v, dest)
	if err != nil {
		return errors.New(fmt.Sprintf("dial V proxy connection failed: %v", err))
	}
	// Note that ctx here is used for canceling fetching input goroutine, not
	// canceling the connection, thus create the cancelable context after Dial().
	ctx, cancel := context.WithCancel(ctx)
	h.Lock()
	h.conns[conn] = &connEntry{
		conn:                c,
		target:              dest,
		cancelFetchingInput: cancel,
		fetchingInputCtx:    ctx,
	}
	h.Unlock()
	go h.fetchInput(conn)
	return nil
}

func (h *handler) DidReceive(conn core.Connection, data []byte) error {
	h.Lock()
	c, ok := h.conns[conn]
	done, ok2 := h.dispatched[conn]
	h.Unlock()
	if ok2 && done {
		// Request already dispatched to V2Ray, ignore.
		return nil
	}
	if ok {
		// If it's a DNS request of type A or AAAA and has only one question,
		// handle it with V2Ray's DNS client, otherwise treat as normal TCP/UDP
		// traffic.
		if c.target.Network == vnet.Network_UDP &&
			c.target.Port.Value() == proxy.COMMON_DNS_PORT &&
			h.shouldAcceptDNSQuery(data) {

			// Parse DNS request and hand to V2Ray, upon V2Ray returns []net.IP,
			// packing them into dns.Msg response message and write back to the client.
			go h.handleDNSQuery(conn, append([]byte(nil), data...))

			// The DNS request has passed to V2Ray for handling, we are safe
			// to cancel the fetching goroutine, but be careful do not close the
			// connection.
			c.cancelFetchingInput()

			h.Lock()
			// The request is successfully handed to V2Ray, mark as dispatched so
			// subsequent retransmissions should be ignored.
			h.dispatched[conn] = true
			h.Unlock()
		} else {
			_, err := c.conn.Write(data)
			if err != nil {
				h.Close(conn)
				return errors.New(fmt.Sprintf("write remote failed: %v", err))
			}
		}
		return nil
	} else {
		h.Close(conn)
		return errors.New(fmt.Sprintf("proxy connection %v->%v does not exists", conn.LocalAddr(), conn.RemoteAddr()))
	}
}

func (h *handler) DidSend(conn core.Connection, len uint16) {
	// unused
}

func (h *handler) DidClose(conn core.Connection) {
	h.Close(conn)
}

func (h *handler) LocalDidClose(conn core.Connection) {
	h.Close(conn)
}

func (h *handler) Close(conn core.Connection) {
	h.Lock()
	defer h.Unlock()

	if c, found := h.conns[conn]; found {
		c.conn.Close()
	}
	delete(h.conns, conn)
}
<|endoftext|>


<commit_before>package env_strings

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"text/template"
)

const (
	ENV_STRINGS_KEY = "ENV_STRINGS"
	ENV_STRINGS_EXT = ".env"
)

type EnvStrings struct {
	envName string
	envExt  string
}

func NewEnvStrings(envName string, envExt string) *EnvStrings {
	if envName == "" {
		panic("env_strings: env name could not be nil")
	}

	return &EnvStrings{
		envName: envName,
		envExt:  envExt,
	}
}

func (p *EnvStrings) Execute(str string) (ret string, err error) {
	strConfigFiles := os.Getenv(p.envName)

	configFiles := strings.Split(strConfigFiles, ";")

	if strConfigFiles == "" || len(configFiles) == 0 {
		return str, nil
	}

	files := []string{}

	for _, confFile := range configFiles {
		var fi os.FileInfo
		if fi, err = os.Stat(confFile); err != nil {
			return
		}

		if fi.IsDir() {
			var dir *os.File
			if dir, err = os.Open(confFile); err != nil {
				return
			}

			var names []string
			if names, err = dir.Readdirnames(-1); err != nil {
				return
			}

			for _, name := range names {
				if ext := filepath.Ext(name); ext == p.envExt {
					filePath := strings.TrimRight(confFile, "/")
					files = append(files, filePath+"/"+name)
				}
			}
		} else {
			if ext := filepath.Ext(confFile); ext == p.envExt {
				files = append(files, confFile)
			}
		}
	}

	envs := map[string]map[string]interface{}{}

	for _, file := range files {
		var str []byte
		if str, err = ioutil.ReadFile(file); err != nil {

			return
		}

		env := map[string]interface{}{}
		if err = json.Unmarshal(str, &env); err != nil {
			return
		}

		envs[file] = env
	}

	allEnvs := map[string]interface{}{}

	for file, env := range envs {
		for envKey, envVal := range env {
			if _, exist := allEnvs[envKey]; exist {
				err = fmt.Errorf("env key of %s already exist, env file: %s", envKey, file)
				return
			} else {
				allEnvs[envKey] = envVal
			}
		}
	}

	var tpl *template.Template

	if tpl, err = template.New("env_strings").Parse(str); err != nil {
		return
	}
	var buf bytes.Buffer
	if err = tpl.Execute(&buf, allEnvs); err != nil {
		return
	}

	ret = buf.String()

	if strings.Contains(ret, "<no value>") {
		err = fmt.Errorf("some env value did not exist")
		return
	}

	return
}

func Execute(str string) (ret string, err error) {
	envStrings := NewEnvStrings(ENV_STRINGS_KEY, ENV_STRINGS_EXT)
	return envStrings.Execute(str)
}
<commit_msg>add more info for values not found<commit_after>package env_strings

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"text/template"
)

const (
	ENV_STRINGS_KEY = "ENV_STRINGS"
	ENV_STRINGS_EXT = ".env"
)

type EnvStrings struct {
	envName string
	envExt  string
}

func NewEnvStrings(envName string, envExt string) *EnvStrings {
	if envName == "" {
		panic("env_strings: env name could not be nil")
	}

	return &EnvStrings{
		envName: envName,
		envExt:  envExt,
	}
}

func (p *EnvStrings) Execute(str string) (ret string, err error) {
	strConfigFiles := os.Getenv(p.envName)

	configFiles := strings.Split(strConfigFiles, ";")

	if strConfigFiles == "" || len(configFiles) == 0 {
		return str, nil
	}

	files := []string{}

	for _, confFile := range configFiles {
		var fi os.FileInfo
		if fi, err = os.Stat(confFile); err != nil {
			return
		}

		if fi.IsDir() {
			var dir *os.File
			if dir, err = os.Open(confFile); err != nil {
				return
			}

			var names []string
			if names, err = dir.Readdirnames(-1); err != nil {
				return
			}

			for _, name := range names {
				if ext := filepath.Ext(name); ext == p.envExt {
					filePath := strings.TrimRight(confFile, "/")
					files = append(files, filePath+"/"+name)
				}
			}
		} else {
			if ext := filepath.Ext(confFile); ext == p.envExt {
				files = append(files, confFile)
			}
		}
	}

	envs := map[string]map[string]interface{}{}

	for _, file := range files {
		var str []byte
		if str, err = ioutil.ReadFile(file); err != nil {

			return
		}

		env := map[string]interface{}{}
		if err = json.Unmarshal(str, &env); err != nil {
			return
		}

		envs[file] = env
	}

	allEnvs := map[string]interface{}{}

	for file, env := range envs {
		for envKey, envVal := range env {
			if _, exist := allEnvs[envKey]; exist {
				err = fmt.Errorf("env key of %s already exist, env file: %s", envKey, file)
				return
			} else {
				allEnvs[envKey] = envVal
			}
		}
	}

	var tpl *template.Template

	if tpl, err = template.New("env_strings").Parse(str); err != nil {
		return
	}
	var buf bytes.Buffer
	if err = tpl.Execute(&buf, allEnvs); err != nil {
		return
	}

	ret = buf.String()

	if strings.Contains(ret, "<no value>") {
		index := strings.Index(ret, "<no value>")
		preIndex := 0
		lastIndex := index + len("<no value>")
		if index-20 >= 0 {
			preIndex = preIndex - 20
		}

		if index+20 <= len(ret) {
			lastIndex = lastIndex + 20
		}

		errorContent := ret[preIndex:lastIndex]
		err = fmt.Errorf("some env value did not exist, content: \n%s\n", errorContent)
		return
	}

	return
}

func Execute(str string) (ret string, err error) {
	envStrings := NewEnvStrings(ENV_STRINGS_KEY, ENV_STRINGS_EXT)
	return envStrings.Execute(str)
}
<|endoftext|>


<commit_before>package trousseau

import (
	"os"
	"fmt"
	"errors"
	"github.com/oleiade/reflections"
)

type Environment struct {
	RemoteHost 		string
	RemotePort 		string
	RemoteUser 		string
	RemoteFilename	string
	S3Bucket   		string `env:"TROUSSEAU_S3_BUCKET"`
	SshPrivateKey	string `env:"TROUSSEAU_SSH_PRIVATE_KEY"`
	Password   		string `env:"TROUSSEAU_PASSWORD"`
}

func NewEnvironment() *Environment {
	env := &Environment{
		RemoteHost: 	"",
		RemotePort: 	"22",
		RemoteUser: 	"",
		RemoteFilename: "trousseau",
		S3Bucket:   	"",
		SshPrivateKey:	gPrivateRsaKeyPath,
		Password:   	"",
	}
	env.Load()

	return env
}

func (e *Environment) Load() error {
	var err 	error
	var envTags	map[string]string

	envTags, err = reflections.Tags(*e, "env")
	if err != nil {
		return err
	}

	for field, tag := range envTags {
		envVar := os.Getenv(tag)

		if envVar != "" {
			err = reflections.SetField(e, field, envVar)
			if err != nil {
				return err
			}
		}
	}

	return nil
}

func (e *Environment) OverrideWith(data map[string]string) error {
	for field, value := range data {
		has, err := reflections.HasField(*e, field)
		if !has {
			errMsg := fmt.Sprintf("No such field %s in Environement struct",
								  field)
			return errors.New(errMsg)
		} else if err != nil {
			return err
		}

		if value != "" {
			reflections.SetField(e, field, value)
		}
	}

	return nil
}<commit_msg>Update: environment documentation<commit_after>package trousseau

import (
	"os"
	"fmt"
	"errors"
	"github.com/oleiade/reflections"
)

type Environment struct {
	RemoteHost 		string
	RemotePort 		string
	RemoteUser 		string
	RemoteFilename	string
	S3Bucket   		string `env:"TROUSSEAU_S3_BUCKET"`
	SshPrivateKey	string `env:"TROUSSEAU_SSH_PRIVATE_KEY"`
	Password   		string `env:"TROUSSEAU_PASSWORD"`
}

func NewEnvironment() *Environment {
	env := &Environment{
		RemoteHost: 	"",
		RemotePort: 	"22",
		RemoteUser: 	"",
		RemoteFilename: "trousseau",
		S3Bucket:   	"",
		SshPrivateKey:	gPrivateRsaKeyPath,
		Password:   	"",
	}
	env.Load()

	return env
}

// Load method will try to load Environment struct
// tagged fields value from system environement. Every
// found values will override Environment field current
// value.
func (e *Environment) Load() error {
	var err 	error
	var envTags	map[string]string

	envTags, err = reflections.Tags(*e, "env")
	if err != nil {
		return err
	}

	for field, tag := range envTags {
		envVar := os.Getenv(tag)

		if envVar != "" {
			err = reflections.SetField(e, field, envVar)
			if err != nil {
				return err
			}
		}
	}

	return nil
}

// OverrideWith will override the Environment values
// according to a provided key-value map.
func (e *Environment) OverrideWith(data map[string]string) error {
	for field, value := range data {
		has, err := reflections.HasField(*e, field)
		if !has {
			errMsg := fmt.Sprintf("No such field %s in Environement struct",
								  field)
			return errors.New(errMsg)
		} else if err != nil {
			return err
		}

		if value != "" {
			reflections.SetField(e, field, value)
		}
	}

	return nil
}<|endoftext|>


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

package cacher

import (
	"github.com/garyburd/redigo/redis"
	"github.com/jelmersnoeck/cacher/internal/numbers"
)

// RedisCache is a caching implementation that stores the data in memory. The
// cache will be emptied when the application has run.
type RedisCache struct {
	client redis.Conn
}

// NewRedisCache creates a new instance of RedisCache and initiates the
// storage map.
func NewRedisCache(client redis.Conn) *RedisCache {
	cache := new(RedisCache)
	cache.client = client

	return cache
}

// Add an item to the cache. If the item is already cached, the value won't be
// overwritten.
//
// ttl defines the number of seconds the value should be cached. If ttl is 0,
// the item will be cached infinitely.
func (c *RedisCache) Add(key string, value []byte, ttl int64) bool {
	if c.exists(key) {
		return false
	}

	return c.Set(key, value, ttl)
}

// Set sets the value of an item, regardless of wether or not the value is
// already cached.
//
// ttl defines the number of seconds the value should be cached. If ttl is 0,
// the item will be cached infinitely.
func (c *RedisCache) Set(key string, value []byte, ttl int64) bool {
	if ttl > 0 {
		c.client.Do("SETEX", key, ttl, value)
	} else {
		c.client.Do("SET", key, value)
	}

	return true
}

// SetMulti sets multiple values for their respective keys. This is a shorthand
// to use `Set` multiple times.
func (c *RedisCache) SetMulti(items map[string][]byte, ttl int64) map[string]bool {
	results := make(map[string]bool)

	for key, value := range items {
		results[key] = c.Set(key, value, ttl)
	}

	return results
}

// Replace will update and only update the value of a cache key. If the key is
// not previously used, we will return false.
func (c *RedisCache) Replace(key string, value []byte, ttl int64) bool {
	if !c.exists(key) {
		return false
	}

	return c.Set(key, value, ttl)
}

// Get gets the value out of the map associated with the provided key.
func (c *RedisCache) Get(key string) ([]byte, bool) {
	value, _ := c.client.Do("GET", key)
	val, ok := value.([]byte)

	if !ok {
		return nil, false
	}

	return val, true
}

// GetMulti gets multiple values from the cache and returns them as a map. It
// uses `Get` internally to retrieve the data.
func (c *RedisCache) GetMulti(keys []string) map[string][]byte {
	items := make(map[string][]byte)

	for _, key := range keys {
		items[key], _ = c.Get(key)
	}

	return items
}

// Increment adds a value of offset to the initial value. If the initial value
// is already set, it will be added to the value currently stored in the cache.
func (c *RedisCache) Increment(key string, initial, offset, ttl int64) bool {
	if initial < 0 || offset <= 0 {
		return false
	}

	return c.incrementOffset(key, initial, offset, ttl)
}

// Decrement subtracts a value of offset to the initial value. If the initial
// value is already set, it will be added to the value currently stored in the
// cache.
func (c *RedisCache) Decrement(key string, initial, offset, ttl int64) bool {
	if initial < 0 || offset <= 0 {
		return false
	}

	return c.incrementOffset(key, initial, offset*-1, ttl)
}

// Flush will remove all the items from the hash.
func (c *RedisCache) Flush() bool {
	c.client.Do("FLUSHDB")

	return true
}

// Delete will validate if the key actually is stored in the cache. If it is
// stored, it will remove the item from the cache. If it is not stored, it will
// return false.
func (c *RedisCache) Delete(key string) bool {
	_, err := c.client.Do("DEL", key)

	if err != nil {
		return false
	}

	return true
}

// DeleteMulti will delete multiple values at a time. It uses the `Delete`
// method internally to do so. It will return a map of results to see if the
// deletion is successful.
func (c *RedisCache) DeleteMulti(keys []string) map[string]bool {
	results := make(map[string]bool)

	for _, v := range keys {
		results[v] = c.Delete(v)
	}

	return results
}

// incrementOffset is a common incrementor method used between Increment and
// Decrement. If the key isn't set before, we will set the initial value. If
// there is a value present, we will add the given offset to that value and
// update the value with the new TTL.
func (c *RedisCache) incrementOffset(key string, initial, offset, ttl int64) bool {
	if !c.exists(key) {
		return c.Set(key, numbers.Int64Bytes(initial), ttl)
	}

	getValue, _ := c.Get(key)
	val, ok := numbers.BytesInt64(getValue)

	if !ok {
		return false
	}

	val += offset
	if val < 0 {
		return false
	}

	return c.Set(key, numbers.Int64Bytes(val), ttl)
}

func (c *RedisCache) exists(key string) bool {
	val, _ := c.client.Do("EXISTS", key)

	if val.(int64) == 1 {
		return true
	}

	return false
}
<commit_msg>Redis: use transactions for increments.<commit_after>// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a MIT-style license that can be found
// in the LICENSE file.

package cacher

import (
	"github.com/garyburd/redigo/redis"
	"github.com/jelmersnoeck/cacher/internal/numbers"
)

// RedisCache is a caching implementation that stores the data in memory. The
// cache will be emptied when the application has run.
type RedisCache struct {
	client redis.Conn
}

// NewRedisCache creates a new instance of RedisCache and initiates the
// storage map.
func NewRedisCache(client redis.Conn) *RedisCache {
	cache := new(RedisCache)
	cache.client = client

	return cache
}

// Add an item to the cache. If the item is already cached, the value won't be
// overwritten.
//
// ttl defines the number of seconds the value should be cached. If ttl is 0,
// the item will be cached infinitely.
func (c *RedisCache) Add(key string, value []byte, ttl int64) bool {
	if c.exists(key) {
		return false
	}

	return c.Set(key, value, ttl)
}

// Set sets the value of an item, regardless of wether or not the value is
// already cached.
//
// ttl defines the number of seconds the value should be cached. If ttl is 0,
// the item will be cached infinitely.
func (c *RedisCache) Set(key string, value []byte, ttl int64) bool {
	if ttl > 0 {
		c.client.Do("SETEX", key, ttl, value)
	} else {
		c.client.Do("SET", key, value)
	}

	return true
}

// SetMulti sets multiple values for their respective keys. This is a shorthand
// to use `Set` multiple times.
func (c *RedisCache) SetMulti(items map[string][]byte, ttl int64) map[string]bool {
	results := make(map[string]bool)

	for key, value := range items {
		results[key] = c.Set(key, value, ttl)
	}

	return results
}

// Replace will update and only update the value of a cache key. If the key is
// not previously used, we will return false.
func (c *RedisCache) Replace(key string, value []byte, ttl int64) bool {
	if !c.exists(key) {
		return false
	}

	return c.Set(key, value, ttl)
}

// Get gets the value out of the map associated with the provided key.
func (c *RedisCache) Get(key string) ([]byte, bool) {
	value, _ := c.client.Do("GET", key)
	val, ok := value.([]byte)

	if !ok {
		return nil, false
	}

	return val, true
}

// GetMulti gets multiple values from the cache and returns them as a map. It
// uses `Get` internally to retrieve the data.
func (c *RedisCache) GetMulti(keys []string) map[string][]byte {
	items := make(map[string][]byte)

	for _, key := range keys {
		items[key], _ = c.Get(key)
	}

	return items
}

// Increment adds a value of offset to the initial value. If the initial value
// is already set, it will be added to the value currently stored in the cache.
func (c *RedisCache) Increment(key string, initial, offset, ttl int64) bool {
	if initial < 0 || offset <= 0 {
		return false
	}

	return c.incrementOffset(key, initial, offset, ttl)
}

// Decrement subtracts a value of offset to the initial value. If the initial
// value is already set, it will be added to the value currently stored in the
// cache.
func (c *RedisCache) Decrement(key string, initial, offset, ttl int64) bool {
	if initial < 0 || offset <= 0 {
		return false
	}

	return c.incrementOffset(key, initial, offset*-1, ttl)
}

// Flush will remove all the items from the hash.
func (c *RedisCache) Flush() bool {
	c.client.Do("FLUSHDB")

	return true
}

// Delete will validate if the key actually is stored in the cache. If it is
// stored, it will remove the item from the cache. If it is not stored, it will
// return false.
func (c *RedisCache) Delete(key string) bool {
	_, err := c.client.Do("DEL", key)

	if err != nil {
		return false
	}

	return true
}

// DeleteMulti will delete multiple values at a time. It uses the `Delete`
// method internally to do so. It will return a map of results to see if the
// deletion is successful.
func (c *RedisCache) DeleteMulti(keys []string) map[string]bool {
	results := make(map[string]bool)

	for _, v := range keys {
		results[v] = c.Delete(v)
	}

	return results
}

// incrementOffset is a common incrementor method used between Increment and
// Decrement. If the key isn't set before, we will set the initial value. If
// there is a value present, we will add the given offset to that value and
// update the value with the new TTL.
func (c *RedisCache) incrementOffset(key string, initial, offset, ttl int64) bool {
	c.client.Do("WATCH", key)

	if !c.exists(key) {
		c.client.Do("MULTI")
		defer c.client.Do("EXEC")
		return c.Set(key, numbers.Int64Bytes(initial), ttl)
	}

	getValue, _ := c.Get(key)
	val, ok := numbers.BytesInt64(getValue)

	if !ok {
		return false
	}

	c.client.Do("MULTI")
	defer c.client.Do("EXEC")

	val += offset
	if val < 0 {
		return false
	}

	return c.Set(key, numbers.Int64Bytes(val), ttl)
}

func (c *RedisCache) exists(key string) bool {
	val, _ := c.client.Do("EXISTS", key)

	if val.(int64) == 1 {
		return true
	}

	return false
}
<|endoftext|>


<commit_before>package main

import (
    "fmt"
	"encoding/json"
    "net/http"
	"io/ioutil"
)

var file []byte
var jsontype jsonobject

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "%v<form action=\"/Blame Brune\" method=\"POST\">"+
        "<input type=\"submit\" value=\"Blame Brune\">"+
        "</form>", jsontype.Object.Counter)
	jsontype.Object.Counter++
}

func bruneHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "%v<form action=\"/Blame Brune\" method=\"POST\">"+
        "<input type=\"submit\" value=\"Blame Brune\">"+
        "</form>", jsontype.Object.Counter)
	fmt.Print(jsontype)
	jsontype.Object.Counter++
	data, err := json.Marshal(jsontype)
	err = ioutil.WriteFile("config.json", data, 755)
	if err != nil {
		fmt.Println("Can't write file.")
		return
	}
}

type jsonobject struct {
    Object ObjectType
}

type ObjectType struct {
	Counter int64
}

func main() {
	file, e := ioutil.ReadFile("config.json")
    if e != nil {
        fmt.Printf("File error: %v\n", e)
		return
    }
    json.Unmarshal(file, &jsontype)
    fmt.Printf("Brunes counted: %v", jsontype)
    fmt.Printf("%s\n", string(file))
    http.HandleFunc("/", handler)
	http.HandleFunc("/Blame Brune", bruneHandler)
    http.ListenAndServe(":80", nil)
	fmt.Print(jsontype)
}
<commit_msg>Debug less.<commit_after>package main

import (
    "fmt"
	"encoding/json"
    "net/http"
	"io/ioutil"
)

var file []byte
var jsontype jsonobject

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "%v<form action=\"/Blame Brune\" method=\"POST\">"+
        "<input type=\"submit\" value=\"Blame Brune\">"+
        "</form>", jsontype.Object.Counter)
	jsontype.Object.Counter++
}

func bruneHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "%v<form action=\"/Blame Brune\" method=\"POST\">"+
        "<input type=\"submit\" value=\"Blame Brune\">"+
        "</form>", jsontype.Object.Counter)
	jsontype.Object.Counter++
	data, err := json.Marshal(jsontype)
	err = ioutil.WriteFile("config.json", data, 755)
	if err != nil {
		fmt.Println("Can't write file.")
		return
	}
}

type jsonobject struct {
    Object ObjectType
}

type ObjectType struct {
	Counter int64
}

func main() {
	file, e := ioutil.ReadFile("config.json")
    if e != nil {
        fmt.Printf("File error: %v\n", e)
		return
    }
    json.Unmarshal(file, &jsontype)
    fmt.Printf("Brunes counted: %v", jsontype)
    fmt.Printf("%s\n", string(file))
    http.HandleFunc("/", handler)
	http.HandleFunc("/Blame Brune", bruneHandler)
    http.ListenAndServe(":80", nil)
	fmt.Print(jsontype)
}
<|endoftext|>