<commit_before>package rx

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

//jig:template Observable<Foo> Do

// Do calls a function for each next value passing through the observable.
func (o ObservableFoo) Do(f func(next foo)) ObservableFoo {
	observable := func(observe FooObserveFunc, subscribeOn Scheduler, subscriber Subscriber) {
		observer := func(next foo, err error, done bool) {
			if !done {
				f(next)
			}
			observe(next, err, done)
		}
		o(observer, subscribeOn, subscriber)
	}
	return observable
}

//jig:template Observable<Foo> DoOnError

// DoOnError calls a function for any error on the stream.
func (o ObservableFoo) DoOnError(f func(err error)) ObservableFoo {
	observable := func(observe FooObserveFunc, subscribeOn Scheduler, subscriber Subscriber) {
		observer := func(next foo, err error, done bool) {
			if err != nil {
				f(err)
			}
			observe(next, err, done)
		}
		o(observer, subscribeOn, subscriber)
	}
	return observable
}

//jig:template Observable<Foo> DoOnComplete

// DoOnComplete calls a function when the stream completes.
func (o ObservableFoo) DoOnComplete(f func()) ObservableFoo {
	observable := func(observe FooObserveFunc, subscribeOn Scheduler, subscriber Subscriber) {
		observer := func(next foo, err error, done bool) {
			if err == nil && done {
				f()
			}
			observe(next, err, done)
		}
		o(observer, subscribeOn, subscriber)
	}
	return observable
}

//jig:template Observable<Foo> Delay

// Delay shifts the emission from an Observable forward in time by a particular amount of time.
func (o ObservableFoo) Delay(duration time.Duration) ObservableFoo {
	observable := func(observe FooObserveFunc, subscribeOn Scheduler, subscriber Subscriber) {
		firstTime := true
		observer := func(next foo, err error, done bool) {
			if firstTime {
				firstTime = false
				time.Sleep(duration)
			}
			observe(next, err, done)
		}
		o(observer, subscribeOn, subscriber)
	}
	return observable
}

//jig:template Observable<Foo> Finally

// Finally applies a function for any error or completion on the stream.
// This doesn't expose whether this was an error or a completion.
func (o ObservableFoo) Finally(f func()) ObservableFoo {
	observable := func(observe FooObserveFunc, subscribeOn Scheduler, subscriber Subscriber) {
		observer := func(next foo, err error, done bool) {
			if done {
				f()
			}
			observe(next, err, done)
		}
		o(observer, subscribeOn, subscriber)
	}
	return observable
}

//jig:template Observable<Foo> Passthrough

// Passthrough just passes through all output from the ObservableFoo.
func (o ObservableFoo) Passthrough() ObservableFoo {
	// Operator scope
	observable := func(observe FooObserveFunc, subscribeOn Scheduler, subscriber Subscriber) {
		// Subscribe scope
		observer := func(next foo, err error, done bool) {
			// Observe scope
			observe(next, err, done)
		}
		o(observer, subscribeOn, subscriber)
	}
	return observable
}

//jig:template Observable<Foo> Serialize

// Serialize forces an ObservableFoo to make serialized calls and to be
// well-behaved.
func (o ObservableFoo) Serialize() ObservableFoo {
	observable := func(observe FooObserveFunc, subscribeOn Scheduler, subscriber Subscriber) {
		var (
			mutex       sync.Mutex
			alreadyDone bool
		)
		observer := func(next foo, err error, done bool) {
			mutex.Lock()
			defer mutex.Unlock()
			if !alreadyDone {
				alreadyDone = done
				observe(next, err, done)
			}
		}
		o(observer, subscribeOn, subscriber)
	}
	return observable
}

//jig:template Observable Timeout
//jig:needs RxError, Observable Serialize

// ErrTimeout is delivered to an observer if the stream times out.
const ErrTimeout = RxError("timeout")

// Timeout mirrors the source Observable, but issues an error notification if a
// particular period of time elapses without any emitted items.
//
// This observer starts a goroutine for every subscription to monitor the
// timeout deadline. It is guaranteed that calls to the observer for this
// subscription will never be called concurrently. It is however almost certain
// that any timeout error will be delivered on a goroutine other than the one
// delivering the next values.
func (o Observable) Timeout(timeout time.Duration) Observable {
	observable := Observable(func(observe ObserveFunc, subscribeOn Scheduler, subscriber Subscriber) {
		deadline := time.NewTimer(timeout)
		unsubscribe := make(chan struct{})
		observer := func(next interface{}, err error, done bool) {
			if deadline.Stop() {
				if subscriber.Closed() {
					return
				}
				observe(next, err, done)
				if done {
					return
				}
				deadline.Reset(timeout)
			}
		}
		watchdog := func() {
			select {
			case <-deadline.C:
				if subscriber.Closed() {
					return
				}
				observe(nil, ErrTimeout, true)
			case <-unsubscribe:
			}
		}
		go watchdog()
		o(observer, subscribeOn, subscriber.Add(func() { close(unsubscribe) }))
	})
	return observable.Serialize()
}

//jig:template Observable<Foo> Timeout
//jig:needs Observable Timeout

// Timeout mirrors the source ObservableFoo, but issues an error notification if
// a particular period of time elapses without any emitted items.
//
// This observer starts a goroutine for every subscription to monitor the
// timeout deadline. It is guaranteed that calls to the observer for this
// subscription will never be called concurrently. It is however almost certain
// that any timeout error will be delivered on a goroutine other than the one
// delivering the next values.
func (o ObservableFoo) Timeout(timeout time.Duration) ObservableFoo {
	return o.AsObservable().Timeout(timeout).AsObservableFoo()
}

//jig:template ErrObservableContractViolation
//jig:needs RxError

const ErrObservableContractViolationConcurrentNotifications = RxError("observable contract violation: concurrent notifications")
const ErrObservableContractViolationNextAfterTermination = RxError("observable contract violation: next after termination")
const ErrObservableContractViolationErrorAfterTermination = RxError("observable contract violation: error after termination")
const ErrObservableContractViolationCompleteAfterTermination = RxError("observable contract violation: complete after termination")

//jig:template Observable<Foo> Validated
//jig:needs ErrObservableContractViolation

// Validated will check for violations of the observable contract. More specific
// it will detect concurrent notifications from the observable and it will
// detect notifications sent after an error or complete notification was already
// processed. A violation is reported via the ObservableFoo when the observable
// is not already terminated (we don't want to break the contract ourselves).
// A violation will always be reported via the onViolation callback. If nil is
// passed as the callback, the operation will use panic to report the violation.
func (o ObservableFoo) Validated(onViolation func(err error)) ObservableFoo {
	observable := func(observe FooObserveFunc, subscribeOn Scheduler, subscriber Subscriber) {
		const (
			operational int32 = iota
			terminated
			violation
		)
		nextstate := func(done bool) int32 {
			if done {
				return terminated
			} else {
				return operational
			}
		}
		if onViolation == nil {
			onViolation = func(err error) { panic(err) }
		}
		concurrent := int32(0)
		state := operational
		var mu sync.Mutex
		observer := func(next foo, err error, done bool) {
			if atomic.AddInt32(&concurrent, 1) > 1 {
				mu.Lock()
				if atomic.CompareAndSwapInt32(&state, operational, violation) {
					err = ErrObservableContractViolationConcurrentNotifications
					observe(zeroFoo, err, true)
					onViolation(err)
				} else if atomic.CompareAndSwapInt32(&state, terminated, violation) {
					onViolation(ErrObservableContractViolationConcurrentNotifications)
				}
				mu.Unlock()
			} else {
				mu.Lock()
				if atomic.CompareAndSwapInt32(&state, terminated, violation) {
					if !done {
						onViolation(ErrObservableContractViolationNextAfterTermination)
					} else {
						if err != nil {
							onViolation(ErrObservableContractViolationErrorAfterTermination)
						} else {
							onViolation(ErrObservableContractViolationCompleteAfterTermination)
						}
					}
				} else if atomic.CompareAndSwapInt32(&state, operational, nextstate(done)) {
					observe(next, err, done)
				}
				mu.Unlock()
			}
			atomic.AddInt32(&concurrent, -1)
		}
		o(observer, subscribeOn, subscriber)
	}
	return observable
}
<commit_msg>Rename watchdog function to timeouter to match operator name.<commit_after>package rx

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

//jig:template Observable<Foo> Do

// Do calls a function for each next value passing through the observable.
func (o ObservableFoo) Do(f func(next foo)) ObservableFoo {
	observable := func(observe FooObserveFunc, subscribeOn Scheduler, subscriber Subscriber) {
		observer := func(next foo, err error, done bool) {
			if !done {
				f(next)
			}
			observe(next, err, done)
		}
		o(observer, subscribeOn, subscriber)
	}
	return observable
}

//jig:template Observable<Foo> DoOnError

// DoOnError calls a function for any error on the stream.
func (o ObservableFoo) DoOnError(f func(err error)) ObservableFoo {
	observable := func(observe FooObserveFunc, subscribeOn Scheduler, subscriber Subscriber) {
		observer := func(next foo, err error, done bool) {
			if err != nil {
				f(err)
			}
			observe(next, err, done)
		}
		o(observer, subscribeOn, subscriber)
	}
	return observable
}

//jig:template Observable<Foo> DoOnComplete

// DoOnComplete calls a function when the stream completes.
func (o ObservableFoo) DoOnComplete(f func()) ObservableFoo {
	observable := func(observe FooObserveFunc, subscribeOn Scheduler, subscriber Subscriber) {
		observer := func(next foo, err error, done bool) {
			if err == nil && done {
				f()
			}
			observe(next, err, done)
		}
		o(observer, subscribeOn, subscriber)
	}
	return observable
}

//jig:template Observable<Foo> Delay

// Delay shifts the emission from an Observable forward in time by a particular amount of time.
func (o ObservableFoo) Delay(duration time.Duration) ObservableFoo {
	observable := func(observe FooObserveFunc, subscribeOn Scheduler, subscriber Subscriber) {
		firstTime := true
		observer := func(next foo, err error, done bool) {
			if firstTime {
				firstTime = false
				time.Sleep(duration)
			}
			observe(next, err, done)
		}
		o(observer, subscribeOn, subscriber)
	}
	return observable
}

//jig:template Observable<Foo> Finally

// Finally applies a function for any error or completion on the stream.
// This doesn't expose whether this was an error or a completion.
func (o ObservableFoo) Finally(f func()) ObservableFoo {
	observable := func(observe FooObserveFunc, subscribeOn Scheduler, subscriber Subscriber) {
		observer := func(next foo, err error, done bool) {
			if done {
				f()
			}
			observe(next, err, done)
		}
		o(observer, subscribeOn, subscriber)
	}
	return observable
}

//jig:template Observable<Foo> Passthrough

// Passthrough just passes through all output from the ObservableFoo.
func (o ObservableFoo) Passthrough() ObservableFoo {
	// Operator scope
	observable := func(observe FooObserveFunc, subscribeOn Scheduler, subscriber Subscriber) {
		// Subscribe scope
		observer := func(next foo, err error, done bool) {
			// Observe scope
			observe(next, err, done)
		}
		o(observer, subscribeOn, subscriber)
	}
	return observable
}

//jig:template Observable<Foo> Serialize

// Serialize forces an ObservableFoo to make serialized calls and to be
// well-behaved.
func (o ObservableFoo) Serialize() ObservableFoo {
	observable := func(observe FooObserveFunc, subscribeOn Scheduler, subscriber Subscriber) {
		var (
			mutex       sync.Mutex
			alreadyDone bool
		)
		observer := func(next foo, err error, done bool) {
			mutex.Lock()
			defer mutex.Unlock()
			if !alreadyDone {
				alreadyDone = done
				observe(next, err, done)
			}
		}
		o(observer, subscribeOn, subscriber)
	}
	return observable
}

//jig:template Observable Timeout
//jig:needs RxError, Observable Serialize

// ErrTimeout is delivered to an observer if the stream times out.
const ErrTimeout = RxError("timeout")

// Timeout mirrors the source Observable, but issues an error notification if a
// particular period of time elapses without any emitted items.
//
// This observer starts a goroutine for every subscription to monitor the
// timeout deadline. It is guaranteed that calls to the observer for this
// subscription will never be called concurrently. It is however almost certain
// that any timeout error will be delivered on a goroutine other than the one
// delivering the next values.
func (o Observable) Timeout(timeout time.Duration) Observable {
	observable := Observable(func(observe ObserveFunc, subscribeOn Scheduler, subscriber Subscriber) {
		deadline := time.NewTimer(timeout)
		unsubscribe := make(chan struct{})
		observer := func(next interface{}, err error, done bool) {
			if deadline.Stop() {
				if subscriber.Closed() {
					return
				}
				observe(next, err, done)
				if done {
					return
				}
				deadline.Reset(timeout)
			}
		}
		timeouter := func() {
			select {
			case <-deadline.C:
				if subscriber.Closed() {
					return
				}
				observe(nil, ErrTimeout, true)
			case <-unsubscribe:
			}
		}
		go timeouter()
		o(observer, subscribeOn, subscriber.Add(func() { close(unsubscribe) }))
	})
	return observable.Serialize()
}

//jig:template Observable<Foo> Timeout
//jig:needs Observable Timeout

// Timeout mirrors the source ObservableFoo, but issues an error notification if
// a particular period of time elapses without any emitted items.
//
// This observer starts a goroutine for every subscription to monitor the
// timeout deadline. It is guaranteed that calls to the observer for this
// subscription will never be called concurrently. It is however almost certain
// that any timeout error will be delivered on a goroutine other than the one
// delivering the next values.
func (o ObservableFoo) Timeout(timeout time.Duration) ObservableFoo {
	return o.AsObservable().Timeout(timeout).AsObservableFoo()
}

//jig:template ErrObservableContractViolation
//jig:needs RxError

const ErrObservableContractViolationConcurrentNotifications = RxError("observable contract violation: concurrent notifications")
const ErrObservableContractViolationNextAfterTermination = RxError("observable contract violation: next after termination")
const ErrObservableContractViolationErrorAfterTermination = RxError("observable contract violation: error after termination")
const ErrObservableContractViolationCompleteAfterTermination = RxError("observable contract violation: complete after termination")

//jig:template Observable<Foo> Validated
//jig:needs ErrObservableContractViolation

// Validated will check for violations of the observable contract. More specific
// it will detect concurrent notifications from the observable and it will
// detect notifications sent after an error or complete notification was already
// processed. A violation is reported via the ObservableFoo when the observable
// is not already terminated (we don't want to break the contract ourselves).
// A violation will always be reported via the onViolation callback. If nil is
// passed as the callback, the operation will use panic to report the violation.
func (o ObservableFoo) Validated(onViolation func(err error)) ObservableFoo {
	observable := func(observe FooObserveFunc, subscribeOn Scheduler, subscriber Subscriber) {
		const (
			operational int32 = iota
			terminated
			violation
		)
		nextstate := func(done bool) int32 {
			if done {
				return terminated
			} else {
				return operational
			}
		}
		if onViolation == nil {
			onViolation = func(err error) { panic(err) }
		}
		concurrent := int32(0)
		state := operational
		var mu sync.Mutex
		observer := func(next foo, err error, done bool) {
			if atomic.AddInt32(&concurrent, 1) > 1 {
				mu.Lock()
				if atomic.CompareAndSwapInt32(&state, operational, violation) {
					err = ErrObservableContractViolationConcurrentNotifications
					observe(zeroFoo, err, true)
					onViolation(err)
				} else if atomic.CompareAndSwapInt32(&state, terminated, violation) {
					onViolation(ErrObservableContractViolationConcurrentNotifications)
				}
				mu.Unlock()
			} else {
				mu.Lock()
				if atomic.CompareAndSwapInt32(&state, terminated, violation) {
					if !done {
						onViolation(ErrObservableContractViolationNextAfterTermination)
					} else {
						if err != nil {
							onViolation(ErrObservableContractViolationErrorAfterTermination)
						} else {
							onViolation(ErrObservableContractViolationCompleteAfterTermination)
						}
					}
				} else if atomic.CompareAndSwapInt32(&state, operational, nextstate(done)) {
					observe(next, err, done)
				}
				mu.Unlock()
			}
			atomic.AddInt32(&concurrent, -1)
		}
		o(observer, subscribeOn, subscriber)
	}
	return observable
}
<|endoftext|>


<commit_before>package timed // import "resenje.org/boltdbpool/timed"

import (
	"errors"
	"os"
	"path/filepath"
	"sync"
	"time"

	"resenje.org/boltdbpool"
)

var (
	ErrUnknownDB     = errors.New("unknown database")
	ErrUnknownPeriod = errors.New("unknown period")
)

type period int

const (
	_             = iota
	Hourly period = iota
	Daily
	Monthly
	Yearly
)

type Pool struct {
	pool   *boltdbpool.Pool
	series []string
	dir    string
	period period
	mu     *sync.Mutex
}

func New(dir string, p period, options *boltdbpool.Options) (*Pool, error) {
	series := []string{}
	switch p {
	case Hourly:
		matches, err := filepath.Glob(filepath.Join(dir, "??????", "??????????.db"))
		if err != nil {
			return nil, err
		}
		for _, match := range matches {
			match = filepath.Base(match)
			if len(match) >= 10 {
				series = append(series, match[:10])
			}
		}
	case Daily:
		matches, err := filepath.Glob(filepath.Join(dir, "??????", "????????.db"))
		if err != nil {
			return nil, err
		}
		for _, match := range matches {
			match = filepath.Base(match)
			if len(match) >= 8 {
				series = append(series, match[:8])
			}
		}
	case Monthly:
		matches, err := filepath.Glob(filepath.Join(dir, "??????.db"))
		if err != nil {
			return nil, err
		}
		for _, match := range matches {
			match = filepath.Base(match)
			if len(match) >= 6 {
				series = append(series, match[:6])
			}
		}
	case Yearly:
		matches, err := filepath.Glob(filepath.Join(dir, "????.db"))
		if err != nil {
			return nil, err
		}
		for _, match := range matches {
			match = filepath.Base(match)
			if len(match) >= 4 {
				series = append(series, match[:4])
			}
		}
	default:
		return nil, ErrUnknownPeriod
	}
	return &Pool{
		pool:   boltdbpool.New(options),
		series: series,
		dir:    dir,
		period: p,
		mu:     &sync.Mutex{},
	}, nil
}

func (p Pool) seriesFromTime(t time.Time) string {
	if p.period == Hourly {
		return t.Format("2006010215")
	}
	if p.period == Daily {
		return t.Format("20060102")
	}
	if p.period == Monthly {
		return t.Format("200601")
	}
	if p.period == Yearly {
		return t.Format("2006")
	}
	return ""
}

func (p Pool) pathFromSeries(series string) (path string) {
	if p.period == Hourly && len(series) == 10 {
		return filepath.Join(p.dir, series[:6], series+".db")
	}
	if p.period == Daily && len(series) == 8 {
		return filepath.Join(p.dir, series[:6], series+".db")
	}
	if p.period == Monthly && len(series) == 6 {
		return filepath.Join(p.dir, series+".db")
	}
	if p.period == Yearly && len(series) == 4 {
		return filepath.Join(p.dir, series+".db")
	}
	return
}

func (p Pool) connFromPath(path string) (c *boltdbpool.Connection, err error) {
	if path == "" {
		err = ErrUnknownDB
		return
	}
	return p.pool.Get(path)
}

func (p *Pool) NewConnection(t time.Time) (conn *Connection, err error) {
	series := p.seriesFromTime(t)
	path := p.pathFromSeries(series)
	c, err := p.pool.Get(path)
	if err != nil {
		return nil, err
	}

	found := false
	p.mu.Lock()
	for i := len(p.series) - 1; i >= 0; i-- {
		if p.series[i] == series {
			found = true
			break
		}
	}
	if !found {
		p.series = append(p.series, series)
	}
	p.mu.Unlock()

	return &Connection{
		Connection: c,
		pool:       p,
		series:     series,
	}, nil
}

func (p *Pool) GetConnection(t time.Time) (conn *Connection, err error) {
	series := p.seriesFromTime(t)
	path := p.pathFromSeries(series)
	if _, err = os.Stat(path); os.IsNotExist(err) {
		p.mu.Lock()
		for i := len(p.series) - 1; i >= 0; i-- {
			if p.series[i] == series {
				p.series = append(p.series[:i], p.series[i+1:]...)
				break
			}
		}
		p.mu.Unlock()
		err = ErrUnknownDB
		return
	} else if err != nil {
		return
	}
	c, err := p.pool.Get(path)
	if err != nil {
		return nil, err
	}
	return &Connection{
		Connection: c,
		pool:       p,
		series:     series,
	}, nil
}

type Connection struct {
	*boltdbpool.Connection
	pool   *Pool
	series string
}

func (c Connection) Next() (*Connection, error) {
	c.pool.mu.Lock()
	defer c.pool.mu.Unlock()

	for i := 0; i < len(c.pool.series)-1; i++ {
		s := c.pool.series[i]
		if s == c.series {
			ns := c.pool.series[i+1]
			nc, err := c.pool.connFromPath(c.pool.pathFromSeries(ns))
			if err != nil {
				return nil, err
			}
			return &Connection{
				Connection: nc,
				pool:       c.pool,
				series:     ns,
			}, nil
		}
	}
	return nil, ErrUnknownDB
}

func (c Connection) Previous() (*Connection, error) {
	c.pool.mu.Lock()
	defer c.pool.mu.Unlock()

	for i := len(c.pool.series) - 1; i > 0; i-- {
		s := c.pool.series[i]
		if s == c.series {
			ns := c.pool.series[i-1]
			nc, err := c.pool.connFromPath(c.pool.pathFromSeries(ns))
			if err != nil {
				return nil, err
			}
			return &Connection{
				Connection: nc,
				pool:       c.pool,
				series:     ns,
			}, nil
		}
	}
	return nil, ErrUnknownDB
}
<commit_msg>timed: add Pool.NextConnection and Pool.PrevConnection<commit_after>package timed // import "resenje.org/boltdbpool/timed"

import (
	"errors"
	"os"
	"path/filepath"
	"sync"
	"time"

	"resenje.org/boltdbpool"
)

var (
	ErrUnknownDB     = errors.New("unknown database")
	ErrUnknownPeriod = errors.New("unknown period")
)

type period int

const (
	_             = iota
	Hourly period = iota
	Daily
	Monthly
	Yearly
)

type Pool struct {
	pool   *boltdbpool.Pool
	series []string
	dir    string
	period period
	mu     *sync.Mutex
}

func New(dir string, p period, options *boltdbpool.Options) (*Pool, error) {
	series := []string{}
	switch p {
	case Hourly:
		matches, err := filepath.Glob(filepath.Join(dir, "??????", "??????????.db"))
		if err != nil {
			return nil, err
		}
		for _, match := range matches {
			match = filepath.Base(match)
			if len(match) >= 10 {
				series = append(series, match[:10])
			}
		}
	case Daily:
		matches, err := filepath.Glob(filepath.Join(dir, "??????", "????????.db"))
		if err != nil {
			return nil, err
		}
		for _, match := range matches {
			match = filepath.Base(match)
			if len(match) >= 8 {
				series = append(series, match[:8])
			}
		}
	case Monthly:
		matches, err := filepath.Glob(filepath.Join(dir, "??????.db"))
		if err != nil {
			return nil, err
		}
		for _, match := range matches {
			match = filepath.Base(match)
			if len(match) >= 6 {
				series = append(series, match[:6])
			}
		}
	case Yearly:
		matches, err := filepath.Glob(filepath.Join(dir, "????.db"))
		if err != nil {
			return nil, err
		}
		for _, match := range matches {
			match = filepath.Base(match)
			if len(match) >= 4 {
				series = append(series, match[:4])
			}
		}
	default:
		return nil, ErrUnknownPeriod
	}
	return &Pool{
		pool:   boltdbpool.New(options),
		series: series,
		dir:    dir,
		period: p,
		mu:     &sync.Mutex{},
	}, nil
}

func (p Pool) seriesFromTime(t time.Time) string {
	if p.period == Hourly {
		return t.Format("2006010215")
	}
	if p.period == Daily {
		return t.Format("20060102")
	}
	if p.period == Monthly {
		return t.Format("200601")
	}
	if p.period == Yearly {
		return t.Format("2006")
	}
	return ""
}

func (p Pool) pathFromSeries(series string) (path string) {
	if p.period == Hourly && len(series) == 10 {
		return filepath.Join(p.dir, series[:6], series+".db")
	}
	if p.period == Daily && len(series) == 8 {
		return filepath.Join(p.dir, series[:6], series+".db")
	}
	if p.period == Monthly && len(series) == 6 {
		return filepath.Join(p.dir, series+".db")
	}
	if p.period == Yearly && len(series) == 4 {
		return filepath.Join(p.dir, series+".db")
	}
	return
}

func (p Pool) connFromPath(path string) (c *boltdbpool.Connection, err error) {
	if path == "" {
		err = ErrUnknownDB
		return
	}
	return p.pool.Get(path)
}

func (p *Pool) NewConnection(t time.Time) (conn *Connection, err error) {
	series := p.seriesFromTime(t)
	path := p.pathFromSeries(series)
	c, err := p.pool.Get(path)
	if err != nil {
		return nil, err
	}

	found := false
	p.mu.Lock()
	for i := len(p.series) - 1; i >= 0; i-- {
		if p.series[i] == series {
			found = true
			break
		}
	}
	if !found {
		p.series = append(p.series, series)
	}
	p.mu.Unlock()

	return &Connection{
		Connection: c,
		pool:       p,
		series:     series,
	}, nil
}

func (p *Pool) GetConnection(t time.Time) (conn *Connection, err error) {
	series := p.seriesFromTime(t)
	path := p.pathFromSeries(series)
	if _, err = os.Stat(path); os.IsNotExist(err) {
		p.mu.Lock()
		for i := len(p.series) - 1; i >= 0; i-- {
			if p.series[i] == series {
				p.series = append(p.series[:i], p.series[i+1:]...)
				break
			}
		}
		p.mu.Unlock()
		err = ErrUnknownDB
		return
	} else if err != nil {
		return
	}
	c, err := p.pool.Get(path)
	if err != nil {
		return nil, err
	}
	return &Connection{
		Connection: c,
		pool:       p,
		series:     series,
	}, nil
}

func (p *Pool) NextConnection(t time.Time) (conn *Connection, err error) {
	path := ""
	series := p.seriesFromTime(t)
	for i := 0; i < len(p.series); i++ {
		s := p.series[i]
		if s > series {
			path = p.pathFromSeries(s)
			if _, err = os.Stat(path); os.IsNotExist(err) {
				p.mu.Lock()
				p.series = append(p.series[:i], p.series[i+1:]...)
				p.mu.Unlock()
				continue
			} else if err != nil {
				return
			}
			series = s
			break
		}
	}
	if path == "" {
		err = ErrUnknownDB
		return
	}
	c, err := p.pool.Get(path)
	if err != nil {
		return nil, err
	}
	return &Connection{
		Connection: c,
		pool:       p,
		series:     series,
	}, nil
}

func (p *Pool) PrevConnection(t time.Time) (conn *Connection, err error) {
	path := ""
	series := p.seriesFromTime(t)
	for i := len(p.series) - 1; i >= 0; i-- {
		s := p.series[i]
		if s < series {
			path = p.pathFromSeries(s)
			if _, err = os.Stat(path); os.IsNotExist(err) {
				p.mu.Lock()
				p.series = append(p.series[:i], p.series[i+1:]...)
				p.mu.Unlock()
				continue
			} else if err != nil {
				return
			}
			series = s
			break
		}
	}
	if path == "" {
		err = ErrUnknownDB
		return
	}
	c, err := p.pool.Get(path)
	if err != nil {
		return nil, err
	}
	return &Connection{
		Connection: c,
		pool:       p,
		series:     series,
	}, nil
}

type Connection struct {
	*boltdbpool.Connection
	pool   *Pool
	series string
}

func (c Connection) Next() (*Connection, error) {
	c.pool.mu.Lock()
	defer c.pool.mu.Unlock()

	for i := 0; i < len(c.pool.series)-1; i++ {
		s := c.pool.series[i]
		if s == c.series {
			ns := c.pool.series[i+1]
			nc, err := c.pool.connFromPath(c.pool.pathFromSeries(ns))
			if err != nil {
				return nil, err
			}
			return &Connection{
				Connection: nc,
				pool:       c.pool,
				series:     ns,
			}, nil
		}
	}
	return nil, ErrUnknownDB
}

func (c Connection) Prev() (*Connection, error) {
	c.pool.mu.Lock()
	defer c.pool.mu.Unlock()

	for i := len(c.pool.series) - 1; i > 0; i-- {
		s := c.pool.series[i]
		if s == c.series {
			ns := c.pool.series[i-1]
			nc, err := c.pool.connFromPath(c.pool.pathFromSeries(ns))
			if err != nil {
				return nil, err
			}
			return &Connection{
				Connection: nc,
				pool:       c.pool,
				series:     ns,
			}, nil
		}
	}
	return nil, ErrUnknownDB
}
<|endoftext|>


<commit_before>package leds

import (
	"fmt"
	"log"
	"os"
	"sync"
	"time"
)

var Colors = map[string][]int{
	"black":   {0, 0, 0},
	"red":     {1, 0, 0},
	"green":   {0, 1, 0},
	"blue":    {0, 0, 1},
	"cyan":    {0, 1, 1},
	"magenta": {1, 0, 1},
	"yellow":  {1, 1, 0},
	"white":   {1, 1, 1},
}

var LedNames = []string{
	"power",
	"wired_internet",
	"wireless",
	"pairing",
	"radio",
}

var LedPositions = [][]int{
	{15, 13, 14},
	{12, 10, 11},
	{9, 1, 8},
	{2, 4, 3},
	{5, 7, 6},
}

// holds the state for an array of leds on our board.
type LedArray struct {
	Leds      []int
	LedStates []LedState
	ticker    *time.Ticker
	lock      *sync.Mutex
}

type LedState struct {
	Flash bool
	Color string
	On    bool
}

func CreateLedArray() *LedArray {
	ledArr := &LedArray{
		Leds:      []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
		LedStates: make([]LedState, 5),
		lock:      &sync.Mutex{},
	}
	initLEDs()
	go ledArr.setupBackgroundJob()

	return ledArr
}

func (l *LedArray) setupBackgroundJob() {
	l.ticker = time.NewTicker(1 * time.Second)

	for {
		select {
		case <-l.ticker.C:

			l.lock.Lock()

			//log.Println("[DEBUG] flash")
			for n := range l.LedStates {
				if l.LedStates[n].Flash {

					if l.LedStates[n].On {
						l.setColorInt(n, Colors["black"])
						l.LedStates[n].On = false
					} else {
						l.setColorInt(n, Colors[l.LedStates[n].Color])
						l.LedStates[n].On = true
					}
				}
			}
			// we should use a cached copy of the array then do a diff and conditionally
			// set leds.
			l.SetLEDs()

			l.lock.Unlock()

		}
	}
}

func (l *LedArray) setColorInt(position int, color []int) {
	var indexes = LedPositions[position]
	for i := 0; i < 3; i++ {
		l.Leds[indexes[i]] = color[i]
	}
}

func (l *LedArray) SetPwmBrightness(brightness int) {
	writetofile("/sys/class/backlight/pwm-backlight/brightness", fmt.Sprintf("%d", brightness))
}

func (l *LedArray) SetColor(position int, color string, flash bool) {
	defer l.lock.Unlock()
	l.lock.Lock()
	l.LedStates[position].Flash = flash
	l.LedStates[position].Color = color
	l.LedStates[position].On = true
	l.setColorInt(position, Colors[color])
	// apply it
	l.SetLEDs()
}

func (l *LedArray) Reset() {
	defer l.lock.Unlock()
	l.lock.Lock()
	for n := range LedNames {
		l.SetColor(n, "black", false)
	}
	// apply it
	l.SetLEDs()
}

func ValidBrightness(brightness int) bool {
	return brightness >= 0 && brightness <= 100
}

func ValidColor(color string) bool {
	return Colors[color] != nil
}

func ValidLedName(name string) bool {
	for n := range LedNames {
		if LedNames[n] == name {
			return true
		}
	}
	return false
}

func LedNameIndex(name string) int {
	for n := range LedNames {
		if LedNames[n] == name {
			return n
		}
	}
	panic("LedName didn't exist.")
}

func initLEDs() {
	log.Printf("Initializing LEDs")
	writetofile("/sys/kernel/debug/omap_mux/lcd_data15", "27")
	writetofile("/sys/kernel/debug/omap_mux/lcd_data14", "27")
	writetofile("/sys/kernel/debug/omap_mux/uart0_ctsn", "27")
	writetofile("/sys/kernel/debug/omap_mux/mii1_col", "27")

	if _, err := os.Stat("/sys/class/gpio/gpio11/direction"); os.IsNotExist(err) {
		writetofile("/sys/class/gpio/export", "11")
	}

	if _, err := os.Stat("/sys/class/gpio/gpio10/direction"); os.IsNotExist(err) {
		writetofile("/sys/class/gpio/export", "10")
	}

	if _, err := os.Stat("/sys/class/gpio/gpio40/direction"); os.IsNotExist(err) {
		writetofile("/sys/class/gpio/export", "40")
	}

	if _, err := os.Stat("/sys/class/gpio/gpio96/direction"); os.IsNotExist(err) {
		writetofile("/sys/class/gpio/export", "96")
	}

	writetofile("/sys/class/gpio/gpio11/direction", "low")
	writetofile("/sys/class/gpio/gpio10/direction", "low")
	writetofile("/sys/class/gpio/gpio40/direction", "low")
	writetofile("/sys/class/gpio/gpio96/direction", "low")

}

func (l *LedArray) SetLEDs() {
	//	log.Printf("[DEBUG] Updating leds: %v", l.Leds)
	//	log.Printf("[DEBUG] Updating flashstate: %v", l.LedStates)

	for i := range l.Leds {
		writetofile("/sys/class/gpio/gpio40/value", fmt.Sprintf("%d", l.Leds[i]))
		writetofile("/sys/class/gpio/gpio96/value", "1")
		writetofile("/sys/class/gpio/gpio96/value", "0")
	}

	writetofile("/sys/class/gpio/gpio11/value", "1")
	writetofile("/sys/class/gpio/gpio11/value", "0")
}

func writetofile(fn string, val string) error {

	df, err := os.OpenFile(fn, os.O_WRONLY|os.O_SYNC, 0666)

	if err != nil {
		log.Printf("[ERROR] failed to open file %s - %s", fn, err)
		return err
	}

	defer df.Close()

	if _, err = fmt.Fprintln(df, val); err != nil {
		log.Printf("[ERROR] failed write to %s - %s", fn, err)
		return err
	}

	return nil
}
<commit_msg>Fixed issue with the blink states not being updated.<commit_after>package leds

import (
	"fmt"
	"log"
	"os"
	"sync"
	"time"
)

var Colors = map[string][]int{
	"black":   {0, 0, 0},
	"red":     {1, 0, 0},
	"green":   {0, 1, 0},
	"blue":    {0, 0, 1},
	"cyan":    {0, 1, 1},
	"magenta": {1, 0, 1},
	"yellow":  {1, 1, 0},
	"white":   {1, 1, 1},
}

var LedNames = []string{
	"power",
	"wired_internet",
	"wireless",
	"pairing",
	"radio",
}

var LedPositions = [][]int{
	{15, 13, 14},
	{12, 10, 11},
	{9, 1, 8},
	{2, 4, 3},
	{5, 7, 6},
}

// holds the state for an array of leds on our board.
type LedArray struct {
	Leds      []int
	LedStates []LedState
	ticker    *time.Ticker
	lock      *sync.Mutex
}

type LedState struct {
	Flash bool
	Color string
	On    bool
}

func CreateLedArray() *LedArray {
	ledArr := &LedArray{
		Leds:      []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
		LedStates: make([]LedState, 5),
		lock:      &sync.Mutex{},
	}
	initLEDs()
	go ledArr.setupBackgroundJob()

	return ledArr
}

func (l *LedArray) setupBackgroundJob() {
	l.ticker = time.NewTicker(1 * time.Second)

	for {
		select {
		case <-l.ticker.C:

			l.lock.Lock()

			//log.Println("[DEBUG] flash")
			for n := range l.LedStates {
				if l.LedStates[n].Flash {

					if l.LedStates[n].On {
						l.setColorInt(n, Colors["black"])
						l.LedStates[n].On = false
					} else {
						l.setColorInt(n, Colors[l.LedStates[n].Color])
						l.LedStates[n].On = true
					}
				}
			}
			// we should use a cached copy of the array then do a diff and conditionally
			// set leds.
			l.SetLEDs()

			l.lock.Unlock()

		}
	}
}

func (l *LedArray) setColorInt(position int, color []int) {
	var indexes = LedPositions[position]
	for i := 0; i < 3; i++ {
		l.Leds[indexes[i]] = color[i]
	}
}

func (l *LedArray) SetPwmBrightness(brightness int) {
	writetofile("/sys/class/backlight/pwm-backlight/brightness", fmt.Sprintf("%d", brightness))
}

func (l *LedArray) SetColor(position int, color string, flash bool) {
	defer l.lock.Unlock()
	l.lock.Lock()
	// update the state
	l.LedStates[position].Flash = flash
	l.LedStates[position].Color = color
	l.LedStates[position].On = true
	l.setColorInt(position, Colors[color])
	// apply it
	l.SetLEDs()
}

func (l *LedArray) Reset() {
	defer l.lock.Unlock()
	l.lock.Lock()
	for pos := range LedNames {
		// update the states
		l.LedStates[pos].Flash = false
		l.LedStates[pos].Color = "black"
		l.LedStates[pos].On = true
		l.SetColor(pos, "black", false)
	}
	// apply it
	l.SetLEDs()
}

func ValidBrightness(brightness int) bool {
	return brightness >= 0 && brightness <= 100
}

func ValidColor(color string) bool {
	return Colors[color] != nil
}

func ValidLedName(name string) bool {
	for n := range LedNames {
		if LedNames[n] == name {
			return true
		}
	}
	return false
}

func LedNameIndex(name string) int {
	for n := range LedNames {
		if LedNames[n] == name {
			return n
		}
	}
	panic("LedName didn't exist.")
}

func initLEDs() {
	log.Printf("Initializing LEDs")
	writetofile("/sys/kernel/debug/omap_mux/lcd_data15", "27")
	writetofile("/sys/kernel/debug/omap_mux/lcd_data14", "27")
	writetofile("/sys/kernel/debug/omap_mux/uart0_ctsn", "27")
	writetofile("/sys/kernel/debug/omap_mux/mii1_col", "27")

	if _, err := os.Stat("/sys/class/gpio/gpio11/direction"); os.IsNotExist(err) {
		writetofile("/sys/class/gpio/export", "11")
	}

	if _, err := os.Stat("/sys/class/gpio/gpio10/direction"); os.IsNotExist(err) {
		writetofile("/sys/class/gpio/export", "10")
	}

	if _, err := os.Stat("/sys/class/gpio/gpio40/direction"); os.IsNotExist(err) {
		writetofile("/sys/class/gpio/export", "40")
	}

	if _, err := os.Stat("/sys/class/gpio/gpio96/direction"); os.IsNotExist(err) {
		writetofile("/sys/class/gpio/export", "96")
	}

	writetofile("/sys/class/gpio/gpio11/direction", "low")
	writetofile("/sys/class/gpio/gpio10/direction", "low")
	writetofile("/sys/class/gpio/gpio40/direction", "low")
	writetofile("/sys/class/gpio/gpio96/direction", "low")

}

func (l *LedArray) SetLEDs() {
	//	log.Printf("[DEBUG] Updating leds: %v", l.Leds)
	//	log.Printf("[DEBUG] Updating flashstate: %v", l.LedStates)

	for i := range l.Leds {
		writetofile("/sys/class/gpio/gpio40/value", fmt.Sprintf("%d", l.Leds[i]))
		writetofile("/sys/class/gpio/gpio96/value", "1")
		writetofile("/sys/class/gpio/gpio96/value", "0")
	}

	writetofile("/sys/class/gpio/gpio11/value", "1")
	writetofile("/sys/class/gpio/gpio11/value", "0")
}

func writetofile(fn string, val string) error {

	df, err := os.OpenFile(fn, os.O_WRONLY|os.O_SYNC, 0666)

	if err != nil {
		log.Printf("[ERROR] failed to open file %s - %s", fn, err)
		return err
	}

	defer df.Close()

	if _, err = fmt.Fprintln(df, val); err != nil {
		log.Printf("[ERROR] failed write to %s - %s", fn, err)
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package handlers

import (
	"fmt"
	"github.com/mitchellh/mapstructure"
	"time"
)

// User represents the user information exchanged between the server and the client.
type User struct {
	CreatedAt   time.Time `json:"createdAt" gorethink:"createdAt"`
	Name        string    `json:"name" gorethink:"name"`
	Email       string    `json:"email" gorethink:"email"`
	Login       string    `json:"login" gorethink:"login"`
	AccessToken string    `json:"accessToken" gorethink:"accessToken"`
}

// GetUser gets an user.
//
// The happy flow:
// 1. Decode received data
// 3. Get the github client for this user
// 4. Get the github UserName
func GetUser(communicator Communicator, data interface{}) {
	var user User
	err := mapstructure.Decode(data, &user)
	if err != nil {
		communicator.SetSend("error", "Error decoding json: ")
		return
	}
	githubClient := GetGithubClient(user.AccessToken, communicator)
	authorizedUser, err := GetGithubUser(githubClient)
	if err != nil {
		communicator.SetSend("logout", "Cannot get the authorized user.")
		return
	}
	authorizedUser.AccessToken = user.AccessToken
	authorizedUser.CreatedAt = time.Now()
	err = communicator.GetDBSession().AddUser(authorizedUser)
	if err != nil {
		fmt.Print(err)
		communicator.SetSend("error", "Could not register the user. Please try again.")
		return
	}
	communicator.SetSend("user set", authorizedUser)
}
<commit_msg>Remove a debug print<commit_after>package handlers

import (
	"github.com/mitchellh/mapstructure"
	"time"
)

// User represents the user information exchanged between the server and the client.
type User struct {
	CreatedAt   time.Time `json:"createdAt" gorethink:"createdAt"`
	Name        string    `json:"name" gorethink:"name"`
	Email       string    `json:"email" gorethink:"email"`
	Login       string    `json:"login" gorethink:"login"`
	AccessToken string    `json:"accessToken" gorethink:"accessToken"`
}

// GetUser gets an user.
//
// The happy flow:
// 1. Decode received data
// 3. Get the github client for this user
// 4. Get the github UserName
func GetUser(communicator Communicator, data interface{}) {
	var user User
	err := mapstructure.Decode(data, &user)
	if err != nil {
		communicator.SetSend("error", "Error decoding json: ")
		return
	}
	githubClient := GetGithubClient(user.AccessToken, communicator)
	authorizedUser, err := GetGithubUser(githubClient)
	if err != nil {
		communicator.SetSend("logout", "Cannot get the authorized user.")
		return
	}
	authorizedUser.AccessToken = user.AccessToken
	authorizedUser.CreatedAt = time.Now()
	err = communicator.GetDBSession().AddUser(authorizedUser)
	if err != nil {
		communicator.SetSend("error", "Could not register the user. Please try again.")
		return
	}
	communicator.SetSend("user set", authorizedUser)
}
<|endoftext|>


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

package prometheus_test

import (
	"log"
	"net/http"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

// ClusterManager is an example for a system that might have been built without
// Prometheus in mind. It models a central manager of jobs running in a
// cluster. Thus, we implement a custom Collector called
// ClusterManagerCollector, which collects information from a ClusterManager
// using its provided methods and turns them into Prometheus Metrics for
// collection.
//
// An additional challenge is that multiple instances of the ClusterManager are
// run within the same binary, each in charge of a different zone. We need to
// make use of wrapping Registerers to be able to register each
// ClusterManagerCollector instance with Prometheus.
type ClusterManager struct {
	Zone string
	// Contains many more fields not listed in this example.
}

// ReallyExpensiveAssessmentOfTheSystemState is a mock for the data gathering a
// real cluster manager would have to do. Since it may actually be really
// expensive, it must only be called once per collection. This implementation,
// obviously, only returns some made-up data.
func (c *ClusterManager) ReallyExpensiveAssessmentOfTheSystemState() (
	oomCountByHost map[string]int, ramUsageByHost map[string]float64,
) {
	// Just example fake data.
	oomCountByHost = map[string]int{
		"foo.example.org": 42,
		"bar.example.org": 2001,
	}
	ramUsageByHost = map[string]float64{
		"foo.example.org": 6.023e23,
		"bar.example.org": 3.14,
	}
	return
}

// ClusterManagerCollector implements the Collector interface.
type ClusterManagerCollector struct {
	ClusterManager *ClusterManager
}

// Descriptors used by the ClusterManagerCollector below.
var (
	oomCountDesc = prometheus.NewDesc(
		"clustermanager_oom_crashes_total",
		"Number of OOM crashes.",
		[]string{"host"}, nil,
	)
	ramUsageDesc = prometheus.NewDesc(
		"clustermanager_ram_usage_bytes",
		"RAM usage as reported to the cluster manager.",
		[]string{"host"}, nil,
	)
)

// Describe is implemented with DescribeByCollect. That's possible because the
// Collect method will always return the same two metrics with the same two
// descriptors.
func (cc ClusterManagerCollector) Describe(ch chan<- *prometheus.Desc) {
	prometheus.DescribeByCollect(cc, ch)
}

// Collect first triggers the ReallyExpensiveAssessmentOfTheSystemState. Then it
// creates constant metrics for each host on the fly based on the returned data.
//
// Note that Collect could be called concurrently, so we depend on
// ReallyExpensiveAssessmentOfTheSystemState to be concurrency-safe.
func (cc ClusterManagerCollector) Collect(ch chan<- prometheus.Metric) {
	oomCountByHost, ramUsageByHost := cc.ClusterManager.ReallyExpensiveAssessmentOfTheSystemState()
	for host, oomCount := range oomCountByHost {
		ch <- prometheus.MustNewConstMetric(
			oomCountDesc,
			prometheus.CounterValue,
			float64(oomCount),
			host,
		)
	}
	for host, ramUsage := range ramUsageByHost {
		ch <- prometheus.MustNewConstMetric(
			ramUsageDesc,
			prometheus.GaugeValue,
			ramUsage,
			host,
		)
	}
}

// NewClusterManager first creates a Prometheus-ignorant ClusterManager
// instance. Then, it creates a ClusterManagerCollector for the just created
// ClusterManager. Finally, it registers the ClusterManagerCollector with a
// wrapping Registerer that adds the zone as a label. In this way, the metrics
// collected by different ClusterManagerCollectors do not collide.
func NewClusterManager(zone string, reg prometheus.Registerer) *ClusterManager {
	c := &ClusterManager{
		Zone: zone,
	}
	cc := ClusterManagerCollector{ClusterManager: c}
	prometheus.WrapRegistererWith(prometheus.Labels{"zone": zone}, reg).MustRegister(cc)
	return c
}

func ExampleCollector() {
	// Since we are dealing with custom Collector implementations, it might
	// be a good idea to try it out with a pedantic registry.
	reg := prometheus.NewPedanticRegistry()

	// Construct cluster managers. In real code, we would assign them to
	// variables to then do something with them.
	NewClusterManager("db", reg)
	NewClusterManager("ca", reg)

	// Add the built in process and golang metrics to this registry
	reg.MustRegister(
		prometheus.NewProcessCollector(prometheus.ProcessCollectorOpts{}),
		prometheus.NewGoCollector(),
	)

	http.Handle("/metrics", promhttp.HandlerFor(reg, promhttp.HandlerOpts{}))
	log.Fatal(http.ListenAndServe(":8080", nil))
}
<commit_msg>Nitpicking a doc comment<commit_after>// Copyright 2014 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package prometheus_test

import (
	"log"
	"net/http"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

// ClusterManager is an example for a system that might have been built without
// Prometheus in mind. It models a central manager of jobs running in a
// cluster. Thus, we implement a custom Collector called
// ClusterManagerCollector, which collects information from a ClusterManager
// using its provided methods and turns them into Prometheus Metrics for
// collection.
//
// An additional challenge is that multiple instances of the ClusterManager are
// run within the same binary, each in charge of a different zone. We need to
// make use of wrapping Registerers to be able to register each
// ClusterManagerCollector instance with Prometheus.
type ClusterManager struct {
	Zone string
	// Contains many more fields not listed in this example.
}

// ReallyExpensiveAssessmentOfTheSystemState is a mock for the data gathering a
// real cluster manager would have to do. Since it may actually be really
// expensive, it must only be called once per collection. This implementation,
// obviously, only returns some made-up data.
func (c *ClusterManager) ReallyExpensiveAssessmentOfTheSystemState() (
	oomCountByHost map[string]int, ramUsageByHost map[string]float64,
) {
	// Just example fake data.
	oomCountByHost = map[string]int{
		"foo.example.org": 42,
		"bar.example.org": 2001,
	}
	ramUsageByHost = map[string]float64{
		"foo.example.org": 6.023e23,
		"bar.example.org": 3.14,
	}
	return
}

// ClusterManagerCollector implements the Collector interface.
type ClusterManagerCollector struct {
	ClusterManager *ClusterManager
}

// Descriptors used by the ClusterManagerCollector below.
var (
	oomCountDesc = prometheus.NewDesc(
		"clustermanager_oom_crashes_total",
		"Number of OOM crashes.",
		[]string{"host"}, nil,
	)
	ramUsageDesc = prometheus.NewDesc(
		"clustermanager_ram_usage_bytes",
		"RAM usage as reported to the cluster manager.",
		[]string{"host"}, nil,
	)
)

// Describe is implemented with DescribeByCollect. That's possible because the
// Collect method will always return the same two metrics with the same two
// descriptors.
func (cc ClusterManagerCollector) Describe(ch chan<- *prometheus.Desc) {
	prometheus.DescribeByCollect(cc, ch)
}

// Collect first triggers the ReallyExpensiveAssessmentOfTheSystemState. Then it
// creates constant metrics for each host on the fly based on the returned data.
//
// Note that Collect could be called concurrently, so we depend on
// ReallyExpensiveAssessmentOfTheSystemState to be concurrency-safe.
func (cc ClusterManagerCollector) Collect(ch chan<- prometheus.Metric) {
	oomCountByHost, ramUsageByHost := cc.ClusterManager.ReallyExpensiveAssessmentOfTheSystemState()
	for host, oomCount := range oomCountByHost {
		ch <- prometheus.MustNewConstMetric(
			oomCountDesc,
			prometheus.CounterValue,
			float64(oomCount),
			host,
		)
	}
	for host, ramUsage := range ramUsageByHost {
		ch <- prometheus.MustNewConstMetric(
			ramUsageDesc,
			prometheus.GaugeValue,
			ramUsage,
			host,
		)
	}
}

// NewClusterManager first creates a Prometheus-ignorant ClusterManager
// instance. Then, it creates a ClusterManagerCollector for the just created
// ClusterManager. Finally, it registers the ClusterManagerCollector with a
// wrapping Registerer that adds the zone as a label. In this way, the metrics
// collected by different ClusterManagerCollectors do not collide.
func NewClusterManager(zone string, reg prometheus.Registerer) *ClusterManager {
	c := &ClusterManager{
		Zone: zone,
	}
	cc := ClusterManagerCollector{ClusterManager: c}
	prometheus.WrapRegistererWith(prometheus.Labels{"zone": zone}, reg).MustRegister(cc)
	return c
}

func ExampleCollector() {
	// Since we are dealing with custom Collector implementations, it might
	// be a good idea to try it out with a pedantic registry.
	reg := prometheus.NewPedanticRegistry()

	// Construct cluster managers. In real code, we would assign them to
	// variables to then do something with them.
	NewClusterManager("db", reg)
	NewClusterManager("ca", reg)

	// Add the standard process and Go metrics to the custom registry.
	reg.MustRegister(
		prometheus.NewProcessCollector(prometheus.ProcessCollectorOpts{}),
		prometheus.NewGoCollector(),
	)

	http.Handle("/metrics", promhttp.HandlerFor(reg, promhttp.HandlerOpts{}))
	log.Fatal(http.ListenAndServe(":8080", nil))
}
<|endoftext|>


<commit_before>package golomb

import (
	"bufio"
	"bytes"
	"crypto/md5"
	"encoding/hex"
	"io"
	"os"
	"reflect"
	"sort"
	"strconv"
	"testing"

	"github.com/tcnksm/go-casper/internal/bits"
)

func TestDecode(t *testing.T) {
	cases := []struct {
		input []byte
		p     uint
		want  uint
		err   error
	}{
		{
			[]byte{0xcb, 0x80}, // 11001011 10000000
			1 << 6,
			151,
			nil,
		},
		{
			[]byte{0xcb}, // 11001011
			1 << 5,
			75,
			io.EOF,
		},
		{
			[]byte{0x00}, // 00000000
			1 << 7,
			0,
			errPadding,
		},
	}

	for _, tc := range cases {
		rd := bytes.NewReader(tc.input)
		br := bits.NewReader(rd)
		got, err := decode(br, tc.p)
		if err != tc.err {
			t.Errorf("error=%v, want=%v", err, tc.err)
		}

		if got != tc.want {
			t.Errorf("decode=%v, want=%v", got, tc.want)
		}

	}
}

func TestDecodeAll(t *testing.T) {
	cases := []struct {
		input []byte
		p     uint
		want  []uint
	}{
		{
			[]byte{0xcb, 0x80}, // 11001011 10000000
			1 << 6,
			[]uint{151},
		},

		{
			[]byte{0xcb, 0xcf}, // 11001011 11001111
			1 << 5,
			[]uint{75, 154},
		},
	}

	for _, tc := range cases {
		got, err := DecodeAll(tc.input, tc.p)
		if err != nil {
			t.Fatal(err)
		}

		if !reflect.DeepEqual(got, tc.want) {
			t.Errorf("Decode=%v, want=%v", got, tc.want)
		}

	}
}

func TestEncoding(t *testing.T) {
	cases := []struct {
		input []uint
		p     uint
		want  []byte
	}{
		{
			[]uint{151},
			1 << 6,
			[]byte{0xcb, 0x80}, // 11001011 10000000
		},
	}

	for _, tc := range cases {
		var buf bytes.Buffer
		if err := Encode(&buf, tc.input, tc.p); err != nil {
			t.Fatal(err)
		}

		if got := buf.Bytes(); !bytes.Equal(got, tc.want) {
			t.Errorf("Encode=%x, want=%x", got, tc.want)
		}
	}
}

// This test used data set from https://github.com/rasky/gcs
func TestGlombSet(t *testing.T) {

	cases := []struct {
		input string
		want  bool
	}{
		{"alpha", true},
		{"hotel", true},
		{"whiskey", true},
		{"november", true},

		{"Taichi", false},
		{"Nakashima", false},
	}

	n, p := uint(26), uint(64)
	file := "./testdata/words.nato"
	f, err := os.Open(file)
	if err != nil {
		t.Fatal(err)
	}
	defer f.Close()

	hashFunc := func(v []byte) uint {
		h := md5.New()
		h.Write(v)
		b := h.Sum(nil)

		s := hex.EncodeToString(b[12:16])
		i, err := strconv.ParseUint(s, 16, 32)
		if err != nil {
			panic(err)
		}
		return uint(i) % (n * p)
	}

	sc := bufio.NewScanner(f)
	a := make([]uint, 0, n)
	for sc.Scan() {
		a = append(a, hashFunc(sc.Bytes()))
	}

	sort.Slice(a, func(i, j int) bool {
		return a[i] < a[j]
	})

	// Encode hash value array to Golomb-coded sets
	// and write it to buffer.
	var buf bytes.Buffer
	if err := Encode(&buf, a, p); err != nil {
		t.Fatal(err)
	}

	// DecodeAll
	decoded, err := DecodeAll(buf.Bytes(), p)
	if err != nil {
		t.Fatal(err)
	}

	for _, tc := range cases {
		if got := search(decoded, hashFunc([]byte(tc.input))); got != tc.want {
			t.Errorf("Search(%s)=%t, want=%t", tc.input, got, tc.want)
		}
	}
}

func search(a []uint, h uint) bool {
	// TODO(tcnksm): Binary search
	for i := 0; i < len(a); i++ {
		if h == a[i] {
			return true
		}

		if h < a[i] {
			return false
		}
	}
	return false
}
<commit_msg>Add Example<commit_after>package golomb

import (
	"bufio"
	"bytes"
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"io"
	"os"
	"reflect"
	"sort"
	"strconv"
	"testing"

	"github.com/tcnksm/go-casper/internal/bits"
)

func TestDecode(t *testing.T) {
	cases := []struct {
		input []byte
		p     uint
		want  uint
		err   error
	}{
		{
			[]byte{0xcb, 0x80}, // 11001011 10000000
			1 << 6,
			151,
			nil,
		},
		{
			[]byte{0xcb}, // 11001011
			1 << 5,
			75,
			io.EOF,
		},
		{
			[]byte{0x00}, // 00000000
			1 << 7,
			0,
			errPadding,
		},
	}

	for _, tc := range cases {
		rd := bytes.NewReader(tc.input)
		br := bits.NewReader(rd)
		got, err := decode(br, tc.p)
		if err != tc.err {
			t.Errorf("error=%v, want=%v", err, tc.err)
		}

		if got != tc.want {
			t.Errorf("decode=%v, want=%v", got, tc.want)
		}

	}
}

func TestDecodeAll(t *testing.T) {
	cases := []struct {
		input []byte
		p     uint
		want  []uint
	}{
		{
			[]byte{0xcb, 0x80}, // 11001011 10000000
			1 << 6,
			[]uint{151},
		},

		{
			[]byte{0xcb, 0xcf}, // 11001011 11001111
			1 << 5,
			[]uint{75, 154},
		},
	}

	for _, tc := range cases {
		got, err := DecodeAll(tc.input, tc.p)
		if err != nil {
			t.Fatal(err)
		}

		if !reflect.DeepEqual(got, tc.want) {
			t.Errorf("Decode=%v, want=%v", got, tc.want)
		}

	}
}

func TestEncoding(t *testing.T) {
	cases := []struct {
		input []uint
		p     uint
		want  []byte
	}{
		{
			[]uint{151},
			1 << 6,
			[]byte{0xcb, 0x80}, // 11001011 10000000
		},
	}

	for _, tc := range cases {
		var buf bytes.Buffer
		if err := Encode(&buf, tc.input, tc.p); err != nil {
			t.Fatal(err)
		}

		if got := buf.Bytes(); !bytes.Equal(got, tc.want) {
			t.Errorf("Encode=%x, want=%x", got, tc.want)
		}
	}
}

func ExampleGlombSet() {
	// Number of elements and false positive probability.
	//
	// Minimum number of bits is N*log(P)
	// = 26 * log(1<<6) = 156 bits = 19 bytes
	N, P := uint(26), uint(1<<6)

	// Example data set comes from https://github.com/rasky/gcs
	file := "./testdata/words.nato"
	f, _ := os.Open(file)
	sc := bufio.NewScanner(f)
	defer f.Close()

	hashF := func(v []byte) uint {
		h := md5.New()
		h.Write(v)
		b := h.Sum(nil)

		s := hex.EncodeToString(b[12:16])
		i, err := strconv.ParseUint(s, 16, 32)
		if err != nil {
			panic(err)
		}
		return uint(i) % (N * P)
	}

	a := make([]uint, 0, N)
	for sc.Scan() {
		a = append(a, hashF(sc.Bytes()))
	}
	sort.Slice(a, func(i, j int) bool {
		return a[i] < a[j]
	})

	// Encode hash value array to Golomb-coded sets
	// and write it to buffer.
	var buf bytes.Buffer
	Encode(&buf, a, P)

	fmt.Printf("%x", buf.Bytes())
	// Output: cba920f780663a061f2065198ab1032d624c50331e66ae9818
}
<|endoftext|>


<commit_before>package container // import "github.com/docker/docker/integration/container"

import (
	"context"
	"io/ioutil"
	"os"
	"testing"

	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/filters"
	"github.com/docker/docker/integration/internal/container"
	"github.com/docker/docker/internal/test/request"
	"github.com/gotestyourself/gotestyourself/assert"
	is "github.com/gotestyourself/gotestyourself/assert/cmp"
	"github.com/gotestyourself/gotestyourself/skip"
)

func TestLinksEtcHostsContentMatch(t *testing.T) {
	skip.If(t, testEnv.IsRemoteDaemon())

	hosts, err := ioutil.ReadFile("/etc/hosts")
	skip.If(t, os.IsNotExist(err))

	defer setupTest(t)()
	client := request.NewAPIClient(t)
	ctx := context.Background()

	cID := container.Run(t, ctx, client, container.WithNetworkMode("host"))
	res, err := container.Exec(ctx, client, cID, []string{"cat", "/etc/hosts"})
	assert.NilError(t, err)
	assert.Assert(t, is.Len(res.Stderr(), 0))
	assert.Equal(t, 0, res.ExitCode)

	assert.Check(t, is.Equal(string(hosts), res.Stdout()))
}

func TestLinksContainerNames(t *testing.T) {
	skip.If(t, testEnv.DaemonInfo.OSType != "linux")

	defer setupTest(t)()
	client := request.NewAPIClient(t)
	ctx := context.Background()

	container.Run(t, ctx, client, container.WithName("first"))
	container.Run(t, ctx, client, container.WithName("second"), container.WithLinks("first:first"))

	f := filters.NewArgs(filters.Arg("name", "first"))

	containers, err := client.ContainerList(ctx, types.ContainerListOptions{
		Filters: f,
	})
	assert.NilError(t, err)
	assert.Check(t, is.Equal(1, len(containers)))
	assert.Check(t, is.DeepEqual([]string{"/first", "/second/first"}, containers[0].Names))
}
<commit_msg>integration tests under integration/container/links_linux_test.go use unique names<commit_after>package container // import "github.com/docker/docker/integration/container"

import (
	"context"
	"io/ioutil"
	"os"
	"testing"

	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/filters"
	"github.com/docker/docker/integration/internal/container"
	"github.com/docker/docker/internal/test/request"
	"github.com/gotestyourself/gotestyourself/assert"
	is "github.com/gotestyourself/gotestyourself/assert/cmp"
	"github.com/gotestyourself/gotestyourself/skip"
)

func TestLinksEtcHostsContentMatch(t *testing.T) {
	skip.If(t, testEnv.IsRemoteDaemon())

	hosts, err := ioutil.ReadFile("/etc/hosts")
	skip.If(t, os.IsNotExist(err))

	defer setupTest(t)()
	client := request.NewAPIClient(t)
	ctx := context.Background()

	cID := container.Run(t, ctx, client, container.WithNetworkMode("host"))
	res, err := container.Exec(ctx, client, cID, []string{"cat", "/etc/hosts"})
	assert.NilError(t, err)
	assert.Assert(t, is.Len(res.Stderr(), 0))
	assert.Equal(t, 0, res.ExitCode)

	assert.Check(t, is.Equal(string(hosts), res.Stdout()))
}

func TestLinksContainerNames(t *testing.T) {
	skip.If(t, testEnv.DaemonInfo.OSType != "linux")

	defer setupTest(t)()
	client := request.NewAPIClient(t)
	ctx := context.Background()

	containerA := "first_" + t.Name()
	containerB := "second_" + t.Name()
	container.Run(t, ctx, client, container.WithName(containerA))
	container.Run(t, ctx, client, container.WithName(containerB), container.WithLinks(containerA+":"+containerA))

	f := filters.NewArgs(filters.Arg("name", containerA))

	containers, err := client.ContainerList(ctx, types.ContainerListOptions{
		Filters: f,
	})
	assert.NilError(t, err)
	assert.Check(t, is.Equal(1, len(containers)))
	assert.Check(t, is.DeepEqual([]string{"/" + containerA, "/" + containerB + "/" + containerA}, containers[0].Names))
}
<|endoftext|>


<commit_before>package loader

import (
	"bytes"
	"debug/dwarf"
	"debug/macho"
	"encoding/binary"
	"errors"
	"fmt"
	"io"

	"github.com/lunixbochs/usercorn/go/models"
)

const (
	machoLoadCmdReqDyld  = 0x80000000
	machoLoadCmdDylinker = 0xe
	machoLoadCmdMain     = 0x28 | machoLoadCmdReqDyld
)

var machoCpuMap = map[macho.Cpu]string{
	macho.Cpu386:   "x86",
	macho.CpuAmd64: "x86_64",
	macho.CpuArm:   "arm",
	macho.CpuPpc:   "ppc",
	macho.CpuPpc64: "ppc64",
}

var fatMagic = []byte{0xca, 0xfe, 0xba, 0xbe}

var machoMagics = [][]byte{
	fatMagic,
	{0xfe, 0xed, 0xfa, 0xce},
	{0xfe, 0xed, 0xfa, 0xcf},
	{0xce, 0xfa, 0xed, 0xfe},
	{0xcf, 0xfa, 0xed, 0xfe},
}

type MachOLoader struct {
	LoaderHeader
	file *macho.File
}

func findEntry(f *macho.File, bits int) (uint64, error) {
	var entry uint64
	for _, l := range f.Loads {
		var cmd macho.LoadCmd
		data := l.Raw()
		binary.Read(bytes.NewReader(data), f.ByteOrder, &cmd)
		if cmd == macho.LoadCmdUnixThread {
			// LC_UNIXTHREAD
			if bits == 64 {
				ip := 144
				entry = f.ByteOrder.Uint64(data[ip : ip+8])
			} else {
				ip := 56
				entry = uint64(f.ByteOrder.Uint32(data[ip : ip+4]))
			}
			return entry, nil
		} else if cmd == machoLoadCmdMain {
			// [8:16] == entry - __TEXT, data[16:24] == stack size
			__TEXT := f.Segment("__TEXT")
			if __TEXT == nil {
				return 0, errors.New("Found LC_MAIN but did not find __TEXT segment.")
			}
			entry = f.ByteOrder.Uint64(data[8:16]) + __TEXT.Addr
			return entry, nil
		}
	}
	return 0, errors.New("Could not find entry point.")
}

func MatchMachO(r io.ReaderAt) bool {
	magic := getMagic(r)
	for _, check := range machoMagics {
		if bytes.Equal(magic, check) {
			return true
		}
	}
	return false
}

func NewMachOLoader(r io.ReaderAt, archHint string) (models.Loader, error) {
	var (
		file    *macho.File
		fatFile *macho.FatFile
		err     error
	)
	magic := getMagic(r)
	if bytes.Equal(magic, fatMagic) {
		fatFile, err = macho.NewFatFile(r)
		if fatFile != nil {
			for _, arch := range fatFile.Arches {
				if machineName, ok := machoCpuMap[arch.Cpu]; ok {
					if machineName == archHint || archHint == "any" {
						file = arch.File
						break
					}
				}
			}
			if file == nil {
				return nil, fmt.Errorf("Could not find Mach-O fat binary entry for arch '%s'.", archHint)
			}
		}
	} else {
		file, err = macho.NewFile(r)
	}
	if err != nil {
		return nil, err
	}
	var bits int
	switch file.Magic {
	case macho.Magic32:
		bits = 32
	case macho.Magic64:
		bits = 64
	default:
		return nil, errors.New("Unknown ELF class.")
	}
	machineName, ok := machoCpuMap[file.Cpu]
	if !ok {
		return nil, fmt.Errorf("Unsupported CPU: %s", file.Cpu)
	}
	entry, err := findEntry(file, bits)
	if err != nil {
		return nil, err
	}
	return &MachOLoader{
		LoaderHeader: LoaderHeader{
			arch:  machineName,
			bits:  bits,
			os:    "darwin",
			entry: entry,
		},
		file: file,
	}, nil
}

func (m *MachOLoader) Interp() string {
	for _, l := range m.file.Loads {
		var cmd macho.LoadCmd
		data := l.Raw()
		binary.Read(bytes.NewReader(data), m.file.ByteOrder, &cmd)
		if cmd == machoLoadCmdDylinker {
			length := m.file.ByteOrder.Uint32(data[8:12])
			dylinker := data[12 : 13+length]
			return string(dylinker)
		}
	}
	return ""
}

func (m *MachOLoader) Header() (uint64, []byte, int) {
	__TEXT := m.file.Segment("__TEXT")
	if __TEXT != nil {
		return __TEXT.Addr, nil, 0
	}
	return 0, nil, 0
}

func (m *MachOLoader) Type() int {
	switch m.file.Type {
	case macho.TypeExec:
		return EXEC
	case macho.TypeDylib, 0x7: // type dylinker
		return DYN
	default:
		return EXEC
	}
}

func (m *MachOLoader) DataSegment() (start, end uint64) {
	seg := m.file.Segment("__DATA")
	if seg != nil {
		return seg.Addr, seg.Addr + seg.Memsz
	}
	return 0, 0
}

func (m *MachOLoader) Segments() ([]models.SegmentData, error) {
	ret := make([]models.SegmentData, 0, len(m.file.Loads))
	for _, l := range m.file.Loads {
		if s, ok := l.(*macho.Segment); ok {
			switch s.Cmd {
			case macho.LoadCmdSegment, macho.LoadCmdSegment64:
				if s.Name == "__PAGEZERO" {
					continue
				}
				ret = append(ret, models.SegmentData{
					Off:  s.Offset,
					Addr: s.Addr,
					Size: s.Memsz,
					Prot: int(s.Flag) & 7,
					DataFunc: func() ([]byte, error) {
						return s.Data()
					},
				})
			}
		}
	}
	return ret, nil
}

func (m *MachOLoader) getSymbols() ([]models.Symbol, error) {
	var symbols []models.Symbol
	if m.file.Symtab == nil {
		return nil, errors.New("no symbol table found")
	} else {
		syms := m.file.Symtab.Syms
		symbols = make([]models.Symbol, len(syms))
		for i, s := range syms {
			symbols[i] = models.Symbol{
				Name:  s.Name,
				Start: s.Value,
				End:   0,
			}
			if i > 0 {
				symbols[i-1].End = symbols[i].Start
			}
		}
	}
	if m.file.Dysymtab != nil {
		for _, v := range m.file.Dysymtab.IndirectSyms {
			if v < uint32(len(symbols)) {
				symbols[v].Dynamic = true
			}
		}
	}
	return symbols, nil
}

func (m *MachOLoader) Symbols() ([]models.Symbol, error) {
	var err error
	if m.symCache == nil {
		m.symCache, err = m.getSymbols()
	}
	return m.symCache, err
}

func (m *MachOLoader) DWARF() (*dwarf.Data, error) {
	return m.file.DWARF()
}
<commit_msg>fix loading dylibs<commit_after>package loader

import (
	"bytes"
	"debug/dwarf"
	"debug/macho"
	"encoding/binary"
	"errors"
	"fmt"
	"io"

	"github.com/lunixbochs/usercorn/go/models"
)

const (
	machoLoadCmdReqDyld  = 0x80000000
	machoLoadCmdDylinker = 0xe
	machoLoadCmdMain     = 0x28 | machoLoadCmdReqDyld
)

var machoCpuMap = map[macho.Cpu]string{
	macho.Cpu386:   "x86",
	macho.CpuAmd64: "x86_64",
	macho.CpuArm:   "arm",
	macho.CpuPpc:   "ppc",
	macho.CpuPpc64: "ppc64",
}

var fatMagic = []byte{0xca, 0xfe, 0xba, 0xbe}

var machoMagics = [][]byte{
	fatMagic,
	{0xfe, 0xed, 0xfa, 0xce},
	{0xfe, 0xed, 0xfa, 0xcf},
	{0xce, 0xfa, 0xed, 0xfe},
	{0xcf, 0xfa, 0xed, 0xfe},
}

type MachOLoader struct {
	LoaderHeader
	file *macho.File
}

func findEntry(f *macho.File, bits int) (uint64, error) {
	var entry uint64
	for _, l := range f.Loads {
		var cmd macho.LoadCmd
		data := l.Raw()
		binary.Read(bytes.NewReader(data), f.ByteOrder, &cmd)
		if cmd == macho.LoadCmdUnixThread {
			// LC_UNIXTHREAD
			if bits == 64 {
				ip := 144
				entry = f.ByteOrder.Uint64(data[ip : ip+8])
			} else {
				ip := 56
				entry = uint64(f.ByteOrder.Uint32(data[ip : ip+4]))
			}
			return entry, nil
		} else if cmd == machoLoadCmdMain {
			// [8:16] == entry - __TEXT, data[16:24] == stack size
			__TEXT := f.Segment("__TEXT")
			if __TEXT == nil {
				return 0, errors.New("Found LC_MAIN but did not find __TEXT segment.")
			}
			entry = f.ByteOrder.Uint64(data[8:16]) + __TEXT.Addr
			return entry, nil
		}
	}
	return 0, errors.New("Could not find entry point.")
}

func MatchMachO(r io.ReaderAt) bool {
	magic := getMagic(r)
	for _, check := range machoMagics {
		if bytes.Equal(magic, check) {
			return true
		}
	}
	return false
}

func NewMachOLoader(r io.ReaderAt, archHint string) (models.Loader, error) {
	var (
		file    *macho.File
		fatFile *macho.FatFile
		err     error
	)
	magic := getMagic(r)
	if bytes.Equal(magic, fatMagic) {
		fatFile, err = macho.NewFatFile(r)
		if fatFile != nil {
			for _, arch := range fatFile.Arches {
				if machineName, ok := machoCpuMap[arch.Cpu]; ok {
					if machineName == archHint || archHint == "any" {
						file = arch.File
						break
					}
				}
			}
			if file == nil {
				return nil, fmt.Errorf("Could not find Mach-O fat binary entry for arch '%s'.", archHint)
			}
		}
	} else {
		file, err = macho.NewFile(r)
	}
	if err != nil {
		return nil, err
	}
	var bits int
	switch file.Magic {
	case macho.Magic32:
		bits = 32
	case macho.Magic64:
		bits = 64
	default:
		return nil, errors.New("Unknown ELF class.")
	}
	machineName, ok := machoCpuMap[file.Cpu]
	if !ok {
		return nil, fmt.Errorf("Unsupported CPU: %s", file.Cpu)
	}
	entry, _ := findEntry(file, bits)
	return &MachOLoader{
		LoaderHeader: LoaderHeader{
			arch:  machineName,
			bits:  bits,
			os:    "darwin",
			entry: entry,
		},
		file: file,
	}, nil
}

func (m *MachOLoader) Interp() string {
	for _, l := range m.file.Loads {
		var cmd macho.LoadCmd
		data := l.Raw()
		binary.Read(bytes.NewReader(data), m.file.ByteOrder, &cmd)
		if cmd == machoLoadCmdDylinker {
			length := m.file.ByteOrder.Uint32(data[8:12])
			dylinker := data[12 : 13+length]
			return string(dylinker)
		}
	}
	return ""
}

func (m *MachOLoader) Header() (uint64, []byte, int) {
	__TEXT := m.file.Segment("__TEXT")
	if __TEXT != nil {
		return __TEXT.Addr, nil, 0
	}
	return 0, nil, 0
}

func (m *MachOLoader) Type() int {
	switch m.file.Type {
	case macho.TypeExec:
		return EXEC
	case macho.TypeDylib, 0x7: // type dylinker
		return DYN
	default:
		return EXEC
	}
}

func (m *MachOLoader) DataSegment() (start, end uint64) {
	seg := m.file.Segment("__DATA")
	if seg != nil {
		return seg.Addr, seg.Addr + seg.Memsz
	}
	return 0, 0
}

func (m *MachOLoader) Segments() ([]models.SegmentData, error) {
	ret := make([]models.SegmentData, 0, len(m.file.Loads))
	for _, l := range m.file.Loads {
		if s, ok := l.(*macho.Segment); ok {
			switch s.Cmd {
			case macho.LoadCmdSegment, macho.LoadCmdSegment64:
				if s.Name == "__PAGEZERO" {
					continue
				}
				ret = append(ret, models.SegmentData{
					Off:  s.Offset,
					Addr: s.Addr,
					Size: s.Memsz,
					Prot: int(s.Flag) & 7,
					DataFunc: func() ([]byte, error) {
						return s.Data()
					},
				})
			}
		}
	}
	return ret, nil
}

func (m *MachOLoader) getSymbols() ([]models.Symbol, error) {
	var symbols []models.Symbol
	if m.file.Symtab == nil {
		return nil, errors.New("no symbol table found")
	} else {
		syms := m.file.Symtab.Syms
		symbols = make([]models.Symbol, len(syms))
		for i, s := range syms {
			symbols[i] = models.Symbol{
				Name:  s.Name,
				Start: s.Value,
				End:   0,
			}
			if i > 0 {
				symbols[i-1].End = symbols[i].Start
			}
		}
	}
	if m.file.Dysymtab != nil {
		for _, v := range m.file.Dysymtab.IndirectSyms {
			if v < uint32(len(symbols)) {
				symbols[v].Dynamic = true
			}
		}
	}
	return symbols, nil
}

func (m *MachOLoader) Symbols() ([]models.Symbol, error) {
	var err error
	if m.symCache == nil {
		m.symCache, err = m.getSymbols()
	}
	return m.symCache, err
}

func (m *MachOLoader) DWARF() (*dwarf.Data, error) {
	return m.file.DWARF()
}
<|endoftext|>


<commit_before>package service

import (
	"fmt"
	"io/ioutil"
	"net"
	"os"
	"path"

	"github.com/codegangsta/cli"
	"github.com/keybase/client/go/libcmdline"
	"github.com/keybase/client/go/libkb"
	keybase1 "github.com/keybase/client/protocol/go"
	"github.com/maxtaco/go-framed-msgpack-rpc/rpc2"
)

// Keep this around to simplify things
var G = libkb.G

type Service struct {
	chdirTo string
	lockPid *libkb.LockPIDFile
}

func NewService(d bool) *Service {
	return &Service{}
}

func RegisterProtocols(srv *rpc2.Server, xp *rpc2.Transport) {
	srv.Register(keybase1.BTCProtocol(NewBTCHandler(xp)))
	srv.Register(keybase1.ConfigProtocol(ConfigHandler{xp}))
	srv.Register(keybase1.CryptoProtocol(NewCryptoHandler(xp)))
	srv.Register(keybase1.CtlProtocol(CtlHandler{}))
	srv.Register(keybase1.DeviceProtocol(NewDeviceHandler(xp)))
	srv.Register(keybase1.DoctorProtocol(NewDoctorHandler(xp)))
	srv.Register(keybase1.IdentifyProtocol(NewIdentifyHandler(xp)))
	srv.Register(keybase1.LoginProtocol(NewLoginHandler(xp)))
	srv.Register(keybase1.ProveProtocol(NewProveHandler(xp)))
	srv.Register(keybase1.SessionProtocol(NewSessionHandler(xp)))
	srv.Register(keybase1.SignupProtocol(NewSignupHandler(xp)))
	srv.Register(keybase1.SigsProtocol(NewSigsHandler(xp)))
	srv.Register(keybase1.PgpProtocol(NewPGPHandler(xp)))
	srv.Register(keybase1.RevokeProtocol(NewRevokeHandler(xp)))
	srv.Register(keybase1.TrackProtocol(NewTrackHandler(xp)))
	srv.Register(keybase1.UserProtocol(NewUserHandler(xp)))
}

func (d *Service) Handle(c net.Conn) {
	xp := rpc2.NewTransport(c, libkb.NewRpcLogFactory(), libkb.WrapError)
	server := rpc2.NewServer(xp, libkb.WrapError)
	RegisterProtocols(server, xp)
	server.Run(true)
}

func (d *Service) RunClient() (err error) {
	return fmt.Errorf("can't run service in client mode")
}

func (d *Service) Run() (err error) {
	G.Service = true

	err = d.writeVersionFile()
	if err != nil {
		return
	}

	if len(d.chdirTo) != 0 {
		e_tmp := os.Chdir(d.chdirTo)
		if e_tmp != nil {
			G.Log.Warning("Could not change directory to %s: %s",
				d.chdirTo, e_tmp.Error())
		} else {
			G.Log.Info("Changing runtime dir to %s", d.chdirTo)
		}
	}

	if err = d.GetExclusiveLock(); err != nil {
		return
	}
	if err = d.OpenSocket(); err != nil {
		return
	}
	if err = d.ConfigRpcServer(); err != nil {
		return
	}
	if err = d.ListenLoop(); err != nil {
		return
	}
	return
}

// If the daemon is already running, we need to be able to check what version
// it is, in case the client has been updated.
func (d *Service) writeVersionFile() error {
	versionFilePath := path.Join(G.Env.GetCacheDir(), "service.version")
	return ioutil.WriteFile(versionFilePath, []byte(libkb.CLIENT_VERSION), 0644)
}

func (d *Service) ReleaseLock() error {
	return d.lockPid.Close()
}

func (d *Service) GetExclusiveLock() error {
	dir, err := G.Env.GetRuntimeDir()
	if err != nil {
		return err
	}
	if err = os.MkdirAll(dir, libkb.PERM_DIR); err != nil {
		return err
	}
	if err := d.lockPIDFile(); err != nil {
		return err
	}
	return nil
}

func (d *Service) OpenSocket() error {
	sf, err := G.Env.GetSocketFile()
	if err != nil {
		return err
	}
	if exists, err := libkb.FileExists(sf); err != nil {
		return err
	} else if exists {
		G.Log.Debug("removing stale socket file: %s", sf)
		if err = os.Remove(sf); err != nil {
			G.Log.Warning("error removing stale socket file: %s", err)
			return err
		}
	}
	return nil
}

func (d *Service) lockPIDFile() (err error) {
	var fn string
	if fn, err = G.Env.GetPidFile(); err != nil {
		return
	}
	d.lockPid = libkb.NewLockPIDFile(fn)
	if err = d.lockPid.Lock(); err != nil {
		return fmt.Errorf("error locking %s: server already running", fn)
	}
	G.Log.Debug("Locking pidfile %s\n", fn)
	return nil
}

func (d *Service) ConfigRpcServer() (err error) {
	return nil
}

func (d *Service) ListenLoop() (err error) {

	var l net.Listener
	if l, err = G.BindToSocket(); err != nil {
		return
	}
	G.PushShutdownHook(func() error {
		G.Log.Info("Closing socket")
		d.lockPid.Close()
		return l.Close()
	})
	for {
		var c net.Conn
		if c, err = l.Accept(); err != nil {
			return
		}
		go d.Handle(c)

	}
}

func (d *Service) ParseArgv(ctx *cli.Context) error {
	d.chdirTo = ctx.String("chdir")
	return nil
}

func NewCmdService(cl *libcmdline.CommandLine) cli.Command {
	return cli.Command{
		Name:        "service",
		Usage:       "keybase service [--chdir <dir>]",
		Description: "run the keybase local service",
		Flags: []cli.Flag{
			cli.StringFlag{
				Name:  "chdir",
				Usage: "specify where to run as a daemon (via chdir)",
			},
		},
		Action: func(c *cli.Context) {
			cl.ChooseCommand(&Service{}, "service", c)
			cl.SetService()
		},
	}
}

func (d *Service) GetUsage() libkb.Usage {
	return libkb.Usage{
		Config:     true,
		KbKeyring:  true,
		GpgKeyring: true,
		API:        true,
		Socket:     true,
	}
}

func GetCommands(cl *libcmdline.CommandLine) []cli.Command {
	return []cli.Command{
		NewCmdService(cl),
	}
}
<commit_msg>create the .cache/keybase dir before writing service.version<commit_after>package service

import (
	"fmt"
	"io/ioutil"
	"net"
	"os"
	"path"

	"github.com/codegangsta/cli"
	"github.com/keybase/client/go/libcmdline"
	"github.com/keybase/client/go/libkb"
	keybase1 "github.com/keybase/client/protocol/go"
	"github.com/maxtaco/go-framed-msgpack-rpc/rpc2"
)

// Keep this around to simplify things
var G = libkb.G

type Service struct {
	chdirTo string
	lockPid *libkb.LockPIDFile
}

func NewService(d bool) *Service {
	return &Service{}
}

func RegisterProtocols(srv *rpc2.Server, xp *rpc2.Transport) {
	srv.Register(keybase1.BTCProtocol(NewBTCHandler(xp)))
	srv.Register(keybase1.ConfigProtocol(ConfigHandler{xp}))
	srv.Register(keybase1.CryptoProtocol(NewCryptoHandler(xp)))
	srv.Register(keybase1.CtlProtocol(CtlHandler{}))
	srv.Register(keybase1.DeviceProtocol(NewDeviceHandler(xp)))
	srv.Register(keybase1.DoctorProtocol(NewDoctorHandler(xp)))
	srv.Register(keybase1.IdentifyProtocol(NewIdentifyHandler(xp)))
	srv.Register(keybase1.LoginProtocol(NewLoginHandler(xp)))
	srv.Register(keybase1.ProveProtocol(NewProveHandler(xp)))
	srv.Register(keybase1.SessionProtocol(NewSessionHandler(xp)))
	srv.Register(keybase1.SignupProtocol(NewSignupHandler(xp)))
	srv.Register(keybase1.SigsProtocol(NewSigsHandler(xp)))
	srv.Register(keybase1.PgpProtocol(NewPGPHandler(xp)))
	srv.Register(keybase1.RevokeProtocol(NewRevokeHandler(xp)))
	srv.Register(keybase1.TrackProtocol(NewTrackHandler(xp)))
	srv.Register(keybase1.UserProtocol(NewUserHandler(xp)))
}

func (d *Service) Handle(c net.Conn) {
	xp := rpc2.NewTransport(c, libkb.NewRpcLogFactory(), libkb.WrapError)
	server := rpc2.NewServer(xp, libkb.WrapError)
	RegisterProtocols(server, xp)
	server.Run(true)
}

func (d *Service) RunClient() (err error) {
	return fmt.Errorf("can't run service in client mode")
}

func (d *Service) Run() (err error) {
	G.Service = true

	err = d.writeVersionFile()
	if err != nil {
		return
	}

	if len(d.chdirTo) != 0 {
		e_tmp := os.Chdir(d.chdirTo)
		if e_tmp != nil {
			G.Log.Warning("Could not change directory to %s: %s",
				d.chdirTo, e_tmp.Error())
		} else {
			G.Log.Info("Changing runtime dir to %s", d.chdirTo)
		}
	}

	if err = d.GetExclusiveLock(); err != nil {
		return
	}
	if err = d.OpenSocket(); err != nil {
		return
	}
	if err = d.ConfigRpcServer(); err != nil {
		return
	}
	if err = d.ListenLoop(); err != nil {
		return
	}
	return
}

// If the daemon is already running, we need to be able to check what version
// it is, in case the client has been updated.
func (d *Service) writeVersionFile() error {
	os.MkdirAll(G.Env.GetCacheDir(), 0700) // 0700 as per the XDG standard
	versionFilePath := path.Join(G.Env.GetCacheDir(), "service.version")
	return ioutil.WriteFile(versionFilePath, []byte(libkb.CLIENT_VERSION), 0644)
}

func (d *Service) ReleaseLock() error {
	return d.lockPid.Close()
}

func (d *Service) GetExclusiveLock() error {
	dir, err := G.Env.GetRuntimeDir()
	if err != nil {
		return err
	}
	if err = os.MkdirAll(dir, libkb.PERM_DIR); err != nil {
		return err
	}
	if err := d.lockPIDFile(); err != nil {
		return err
	}
	return nil
}

func (d *Service) OpenSocket() error {
	sf, err := G.Env.GetSocketFile()
	if err != nil {
		return err
	}
	if exists, err := libkb.FileExists(sf); err != nil {
		return err
	} else if exists {
		G.Log.Debug("removing stale socket file: %s", sf)
		if err = os.Remove(sf); err != nil {
			G.Log.Warning("error removing stale socket file: %s", err)
			return err
		}
	}
	return nil
}

func (d *Service) lockPIDFile() (err error) {
	var fn string
	if fn, err = G.Env.GetPidFile(); err != nil {
		return
	}
	d.lockPid = libkb.NewLockPIDFile(fn)
	if err = d.lockPid.Lock(); err != nil {
		return fmt.Errorf("error locking %s: server already running", fn)
	}
	G.Log.Debug("Locking pidfile %s\n", fn)
	return nil
}

func (d *Service) ConfigRpcServer() (err error) {
	return nil
}

func (d *Service) ListenLoop() (err error) {

	var l net.Listener
	if l, err = G.BindToSocket(); err != nil {
		return
	}
	G.PushShutdownHook(func() error {
		G.Log.Info("Closing socket")
		d.lockPid.Close()
		return l.Close()
	})
	for {
		var c net.Conn
		if c, err = l.Accept(); err != nil {
			return
		}
		go d.Handle(c)

	}
}

func (d *Service) ParseArgv(ctx *cli.Context) error {
	d.chdirTo = ctx.String("chdir")
	return nil
}

func NewCmdService(cl *libcmdline.CommandLine) cli.Command {
	return cli.Command{
		Name:        "service",
		Usage:       "keybase service [--chdir <dir>]",
		Description: "run the keybase local service",
		Flags: []cli.Flag{
			cli.StringFlag{
				Name:  "chdir",
				Usage: "specify where to run as a daemon (via chdir)",
			},
		},
		Action: func(c *cli.Context) {
			cl.ChooseCommand(&Service{}, "service", c)
			cl.SetService()
		},
	}
}

func (d *Service) GetUsage() libkb.Usage {
	return libkb.Usage{
		Config:     true,
		KbKeyring:  true,
		GpgKeyring: true,
		API:        true,
		Socket:     true,
	}
}

func GetCommands(cl *libcmdline.CommandLine) []cli.Command {
	return []cli.Command{
		NewCmdService(cl),
	}
}
<|endoftext|>


<commit_before>package hawser

import (
	"fmt"
	"github.com/hawser/git-hawser/git"
	"github.com/rubyist/tracerx"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"strings"
)

const Version = "0.3.6"

var (
	LargeSizeThreshold = 5 * 1024 * 1024
	TempDir            = filepath.Join(os.TempDir(), "hawser")
	UserAgent          string
	LocalWorkingDir    string
	LocalGitDir        string
	LocalMediaDir      string
	LocalLogDir        string
	checkedTempDir     string
)

func TempFile(prefix string) (*os.File, error) {
	if checkedTempDir != TempDir {
		if err := os.MkdirAll(TempDir, 0774); err != nil {
			return nil, err
		}
		checkedTempDir = TempDir
	}

	return ioutil.TempFile(TempDir, prefix)
}

func ResetTempDir() error {
	checkedTempDir = ""
	return os.RemoveAll(TempDir)
}

func LocalMediaPath(sha string) (string, error) {
	path := filepath.Join(LocalMediaDir, sha[0:2], sha[2:4])
	if err := os.MkdirAll(path, 0744); err != nil {
		return "", fmt.Errorf("Error trying to create local media directory in '%s': %s", path, err)
	}

	return filepath.Join(path, sha), nil
}

func Environ() []string {
	osEnviron := os.Environ()
	env := make([]string, 4, len(osEnviron)+4)
	env[0] = fmt.Sprintf("LocalWorkingDir=%s", LocalWorkingDir)
	env[1] = fmt.Sprintf("LocalGitDir=%s", LocalGitDir)
	env[2] = fmt.Sprintf("LocalMediaDir=%s", LocalMediaDir)
	env[3] = fmt.Sprintf("TempDir=%s", TempDir)

	for _, e := range osEnviron {
		if !strings.Contains(e, "GIT_") {
			continue
		}
		env = append(env, e)
	}

	return env
}

func InRepo() bool {
	return LocalWorkingDir != ""
}

func init() {
	var err error

	tracerx.DefaultKey = "GIT"
	tracerx.Prefix = "trace hawser: "

	LocalWorkingDir, LocalGitDir, err = resolveGitDir()
	if err == nil {
		LocalMediaDir = filepath.Join(LocalGitDir, "hawser", "objects")
		LocalLogDir = filepath.Join(LocalMediaDir, "logs")
		TempDir = filepath.Join(LocalGitDir, "hawser", "tmp")

		if err := os.MkdirAll(LocalMediaDir, 0744); err != nil {
			panic(fmt.Errorf("Error trying to create objects directory in '%s': %s", LocalMediaDir, err))
		}

		if err := os.MkdirAll(LocalLogDir, 0744); err != nil {
			panic(fmt.Errorf("Error trying to create log directory in '%s': %s", LocalLogDir, err))
		}

		if err := os.MkdirAll(TempDir, 0744); err != nil {
			panic(fmt.Errorf("Error trying to create temp directory in '%s': %s", TempDir, err))
		}

	}

	gitVersion, err := git.Config.Version()
	if err != nil {
		gitVersion = "unknown"
	}

	UserAgent = fmt.Sprintf("git-hawser/%s (GitHub; %s %s; git %s; go %s)", Version,
		runtime.GOOS,
		runtime.GOARCH,
		strings.Replace(gitVersion, "git version ", "", 1),
		strings.Replace(runtime.Version(), "go", "", 1))
}

func resolveGitDir() (string, string, error) {
	wd, err := os.Getwd()
	if err != nil {
		return "", "", err
	}

	return recursiveResolveGitDir(wd)
}

func recursiveResolveGitDir(dir string) (string, string, error) {
	var cleanDir = filepath.Clean(dir)
	if cleanDir[len(cleanDir)-1] == os.PathSeparator {
		return "", "", fmt.Errorf("Git repository not found")
	}

	if filepath.Base(dir) == gitExt {
		return filepath.Dir(dir), dir, nil
	}

	gitDir := filepath.Join(dir, gitExt)
	if info, err := os.Stat(gitDir); err == nil {
		if info.IsDir() {
			return dir, gitDir, nil
		} else {
			return processDotGitFile(gitDir)
		}
	}

	return recursiveResolveGitDir(filepath.Dir(dir))
}

func processDotGitFile(file string) (string, string, error) {
	f, err := os.Open(file)
	defer f.Close()

	if err != nil {
		return "", "", err
	}

	data := make([]byte, 512)
	n, err := f.Read(data)
	if err != nil {
		return "", "", err
	}

	contents := string(data[0:n])
	wd, _ := os.Getwd()
	if strings.HasPrefix(contents, gitPtrPrefix) {
		dir := strings.TrimSpace(strings.Split(contents, gitPtrPrefix)[1])
		absDir, _ := filepath.Abs(dir)
		return wd, absDir, nil
	}

	return wd, "", nil
}

const (
	gitExt       = ".git"
	gitPtrPrefix = "gitdir: "
)
<commit_msg>yay v0.4.0<commit_after>package hawser

import (
	"fmt"
	"github.com/hawser/git-hawser/git"
	"github.com/rubyist/tracerx"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"strings"
)

const Version = "0.4.0"

var (
	LargeSizeThreshold = 5 * 1024 * 1024
	TempDir            = filepath.Join(os.TempDir(), "hawser")
	UserAgent          string
	LocalWorkingDir    string
	LocalGitDir        string
	LocalMediaDir      string
	LocalLogDir        string
	checkedTempDir     string
)

func TempFile(prefix string) (*os.File, error) {
	if checkedTempDir != TempDir {
		if err := os.MkdirAll(TempDir, 0774); err != nil {
			return nil, err
		}
		checkedTempDir = TempDir
	}

	return ioutil.TempFile(TempDir, prefix)
}

func ResetTempDir() error {
	checkedTempDir = ""
	return os.RemoveAll(TempDir)
}

func LocalMediaPath(sha string) (string, error) {
	path := filepath.Join(LocalMediaDir, sha[0:2], sha[2:4])
	if err := os.MkdirAll(path, 0744); err != nil {
		return "", fmt.Errorf("Error trying to create local media directory in '%s': %s", path, err)
	}

	return filepath.Join(path, sha), nil
}

func Environ() []string {
	osEnviron := os.Environ()
	env := make([]string, 4, len(osEnviron)+4)
	env[0] = fmt.Sprintf("LocalWorkingDir=%s", LocalWorkingDir)
	env[1] = fmt.Sprintf("LocalGitDir=%s", LocalGitDir)
	env[2] = fmt.Sprintf("LocalMediaDir=%s", LocalMediaDir)
	env[3] = fmt.Sprintf("TempDir=%s", TempDir)

	for _, e := range osEnviron {
		if !strings.Contains(e, "GIT_") {
			continue
		}
		env = append(env, e)
	}

	return env
}

func InRepo() bool {
	return LocalWorkingDir != ""
}

func init() {
	var err error

	tracerx.DefaultKey = "GIT"
	tracerx.Prefix = "trace hawser: "

	LocalWorkingDir, LocalGitDir, err = resolveGitDir()
	if err == nil {
		LocalMediaDir = filepath.Join(LocalGitDir, "hawser", "objects")
		LocalLogDir = filepath.Join(LocalMediaDir, "logs")
		TempDir = filepath.Join(LocalGitDir, "hawser", "tmp")

		if err := os.MkdirAll(LocalMediaDir, 0744); err != nil {
			panic(fmt.Errorf("Error trying to create objects directory in '%s': %s", LocalMediaDir, err))
		}

		if err := os.MkdirAll(LocalLogDir, 0744); err != nil {
			panic(fmt.Errorf("Error trying to create log directory in '%s': %s", LocalLogDir, err))
		}

		if err := os.MkdirAll(TempDir, 0744); err != nil {
			panic(fmt.Errorf("Error trying to create temp directory in '%s': %s", TempDir, err))
		}

	}

	gitVersion, err := git.Config.Version()
	if err != nil {
		gitVersion = "unknown"
	}

	UserAgent = fmt.Sprintf("git-hawser/%s (GitHub; %s %s; git %s; go %s)", Version,
		runtime.GOOS,
		runtime.GOARCH,
		strings.Replace(gitVersion, "git version ", "", 1),
		strings.Replace(runtime.Version(), "go", "", 1))
}

func resolveGitDir() (string, string, error) {
	wd, err := os.Getwd()
	if err != nil {
		return "", "", err
	}

	return recursiveResolveGitDir(wd)
}

func recursiveResolveGitDir(dir string) (string, string, error) {
	var cleanDir = filepath.Clean(dir)
	if cleanDir[len(cleanDir)-1] == os.PathSeparator {
		return "", "", fmt.Errorf("Git repository not found")
	}

	if filepath.Base(dir) == gitExt {
		return filepath.Dir(dir), dir, nil
	}

	gitDir := filepath.Join(dir, gitExt)
	if info, err := os.Stat(gitDir); err == nil {
		if info.IsDir() {
			return dir, gitDir, nil
		} else {
			return processDotGitFile(gitDir)
		}
	}

	return recursiveResolveGitDir(filepath.Dir(dir))
}

func processDotGitFile(file string) (string, string, error) {
	f, err := os.Open(file)
	defer f.Close()

	if err != nil {
		return "", "", err
	}

	data := make([]byte, 512)
	n, err := f.Read(data)
	if err != nil {
		return "", "", err
	}

	contents := string(data[0:n])
	wd, _ := os.Getwd()
	if strings.HasPrefix(contents, gitPtrPrefix) {
		dir := strings.TrimSpace(strings.Split(contents, gitPtrPrefix)[1])
		absDir, _ := filepath.Abs(dir)
		return wd, absDir, nil
	}

	return wd, "", nil
}

const (
	gitExt       = ".git"
	gitPtrPrefix = "gitdir: "
)
<|endoftext|>


<commit_before>package gotweet
import (
	"encoding/json"
	"github.com/mrjones/oauth"
	"io/ioutil"
)

type App struct {
	consumer    *oauth.Consumer
	accessToken *oauth.AccessToken
}

type APIkeys struct{
	APIKey string
	APISecret string
	AccessToken string
	AccessTokenSecret string
}
type Twitter struct {
	Users TwitterUsers
}
type TwitterUsers struct {
	contributors_enabled bool
	created_at string

}

func TwitterServiceProvider() oauth.ServiceProvider {
	return oauth.ServiceProvider{RequestTokenUrl: "http://api.twitter.com/oauth/request_token",
		AuthorizeTokenUrl: "https://api.twitter.com/oauth/authorize",
		AccessTokenUrl:    "https://api.twitter.com/oauth/access_token"}
}
func Newapp(a APIkeys, sv oauth.ServiceProvider) *App {
	app := new(App)
	app.consumer = oauth.NewConsumer(a.APIKey, a.APISecret, sv)
	app.accessToken = &oauth.AccessToken{Token:a.AccessToken, Secret: a.AccessTokenSecret}
	return app
}
func (t *App) Get(url string, params map[string]string) (interface{}, error) {
	response, err := t.consumer.Get(url, params, t.accessToken)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()

	b, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}

	// decode
	var result interface{}
	err = json.Unmarshal(b, &result)
	return result, err
}

func (t *App) Post(url string, params map[string]string) (interface{}, error) {
	response, err := t.consumer.Post(url, params, t.accessToken)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()

	b, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}

	// decode
	var result interface{}
	err = json.Unmarshal(b, &result)
	return result, err
}<commit_msg>[add]　スライス処理<commit_after>package gotweet

import (
	"encoding/json"
	"github.com/mrjones/oauth"
	"io/ioutil"
	"unicode/utf8"
)

type App struct {
	consumer    *oauth.Consumer
	accessToken *oauth.AccessToken
}
type APIkeys struct {
	APIKey            string
	APISecret         string
	AccessToken       string
	AccessTokenSecret string
}
type objects map[string]string

type Users struct {
	Contributors_enabled               bool
	Created_at                         string
	Default_profile                    bool
	Default_profile_image              bool
	Description                        string
	Entities                           Entities
	Favourites_count                   int
	Follow_request_sent                interface{}
	Following                          interface{}
	Followers_count                    int
	Friends_count                      int
	Geo_enabled                        bool
	Id                                 int64
	Id_str                             string
	Is_translator                      bool
	Lang                               string
	Listed_count                       int
	Location                           string
	Name                               string
	Notifications                      bool
	Profile_background_color           string
	Profile_background_image_url       string
	Profile_background_image_url_https string
	Profile_background_tile            bool
	Profile_banner_url                 string
	Profile_image_url                  string
	Profile_image_url_https            string
	Profile_link_color                 string
	Profile_sidebar_border_color       string
	Profile_sidebar_fill_color         string
	Profile_text_color                 string
	Profile_use_background_image       bool
	Protected                          bool
	Screen_name                        string
	Show_all_inline_media              bool
	Status                             objects //Tweets
	Statuses_count                     int
	Time_zone                          string
	Url                                string
	Utc_offset                         int
	Verified                           bool
	Withheld_in_countries              string
	Withheld_scope                     string
}
type Entities struct {
	Hashtags []struct {
		Indices []int
		Text    string
	}
	Media []struct {
		Display_url     string
		Expanded_url    string
		Id              int64
		Id_str          string
		Indices         []int
		Media_url       string
		Media_url_https string
		Sizes           struct {
			Thumb  Size
			Large  Size
			Medium Size
			Small  Size
		}
		Source_status_id     int64
		Source_status_id_str string
		Type                 string
		Url                  string
	}
	Urls []struct {
		Display_url  string
		Expanded_url string
		Idices       []int
		Url          string
	}
	User_mentions []struct {
		Id          int64
		Id_str      string
		Indices     []int
		Name        string
		Screen_name string
	}
}
type Size struct {
	H      int
	Resize string
	W      int
}
type Tweets struct {
	Contributors              string `json:"contributors"` //非推奨
	Coordinates               interface{}
	Created_at                string
	Current_user_retweet      objects
	Entities                  Entities
	Favorite_count            int
	Favorited                 bool
	Filter_level              string
	Geo                       objects
	Id                        int64
	Id_str                    string `json:"id_str"`
	In_reply_to_screen_name   string
	In_reply_to_status_id     int64
	In_reply_to_status_id_str string
	In_reply_to_user_id       int64
	In_reply_to_user_id_str   string
	Lang                      string
	Place                     struct {
		Attributes   objects
		Bounding_box objects
		Country      string
		Country_code string
		Full_name    string
		Id           string
		Name         string
		Place_type   string
		Url          string
	}
	Possibly_sensitive    bool
	Quoted_status_id      int64
	Quoted_status_id_str  string
	Quoted_status         objects
	Scopes                objects
	Retweet_count         int
	Retweeted             bool
	Retweeted_status      objects
	Source                string
	Text                  string
	Truncated             bool
	User                  Users
	Withheld_copyright    bool
	Withheld_in_countries []string
	Withheld_scope        string
}
type Coordinates map[string]string

func twitterServiceProvider() oauth.ServiceProvider {
	return oauth.ServiceProvider{RequestTokenUrl: "http://api.twitter.com/oauth/request_token",
		AuthorizeTokenUrl: "https://api.twitter.com/oauth/authorize",
		AccessTokenUrl:    "https://api.twitter.com/oauth/access_token"}
}
func Newapp(a APIkeys) *App {
	app := new(App)
	app.consumer = oauth.NewConsumer(a.APIKey, a.APISecret, twitterServiceProvider())
	app.accessToken = &oauth.AccessToken{Token: a.AccessToken, Secret: a.AccessTokenSecret}
	return app
}
func (t *App) Get(url string, params map[string]string, result interface{}) (interface{}, error) {
	response, err := t.consumer.Get(url, params, t.accessToken)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()

	b, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}

	// decode
	err = json.Unmarshal(b, &result)
	return result, err
}

func (t *App) Post(url string, params map[string]string) (interface{}, error) {

	response, err := t.consumer.Post(url, params, t.accessToken)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()

	b, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}
	var result interface{}
	// decoded
	err = json.Unmarshal(b, &result)
	return result, err
}
func (t *App) Tweet(params map[string]string) (Tweets, error) {
	result := Tweets{}
	url := "https://api.twitter.com/1.1/statuses/update.json"
	response, err := t.consumer.Post(url, params, t.accessToken)
	if err != nil {
		return result, err
	}
	defer response.Body.Close()

	b, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return result, err
	}
	err = json.Unmarshal(b, &result)
	return result, err

}
func Distsrings(max int, s string) []string {
	wc := utf8.RuneCountInString(s)
	result := append([]string{}, s)
	if wc <= max {
		min := wc/max + 1
		if min==9{}
	}
	return result
}
func SliceStrlen(slice []string) []int {
	result := make([]int, len(slice))
	for n, s := range slice {
		result[n] = utf8.RuneCountInString(s)
	}
	return result
}
func SliceFindfunc(t interface{}, f func(interface{}) bool) []int {
	result := []int{}
	buf := SliceInterface(t)
	for n, r := range buf {
		if f(r) {
			result = append(result, n)
		} else {
			continue
		}
	}
	return result
}
func SliceInterface(t interface{}) []interface{} {
	buf := []interface{}{}
	switch sl := t.(type) {
	case []int:
		for _, i := range sl {
			buf = append(buf, i)
		}
	case []bool:
		for _, i := range sl {
			buf = append(buf, i)
		}
	case []string:
		for _, i := range sl {
			buf = append(buf, i)
		}
	case string:
		for _, i := range sl {
			buf = append(buf, i)
		}
	default:
		panic("This Type can't use")
	}
	return buf
}
<|endoftext|>