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

// Package rand implements pseudo-random number generators.
//
// Random numbers are generated by a Source. Top-level functions, such as
// Float64 and Int, use a default shared Source that produces a deterministic
// sequence of values each time a program is run. Use the Seed function to
// initialize the default Source if different behavior is required for each run.
// The default Source is safe for concurrent use by multiple goroutines.
//
// For random numbers suitable for security-sensitive work, see the crypto/rand
// package.
package rand

import "sync"

// A Source represents a source of uniformly-distributed
// pseudo-random int64 values in the range [0, 1<<63).
type Source interface {
	Int63() int64
	Seed(seed int64)
}

// NewSource returns a new pseudo-random Source seeded with the given value.
func NewSource(seed int64) Source {
	var rng rngSource
	rng.Seed(seed)
	return &rng
}

// A Rand is a source of random numbers.
type Rand struct {
	src Source
}

// New returns a new Rand that uses random values from src
// to generate other random values.
func New(src Source) *Rand { return &Rand{src} }

// Seed uses the provided seed value to initialize the generator to a deterministic state.
func (r *Rand) Seed(seed int64) { r.src.Seed(seed) }

// Int63 returns a non-negative pseudo-random 63-bit integer as an int64.
func (r *Rand) Int63() int64 { return r.src.Int63() }

// Uint32 returns a pseudo-random 32-bit value as a uint32.
func (r *Rand) Uint32() uint32 { return uint32(r.Int63() >> 31) }

// Int31 returns a non-negative pseudo-random 31-bit integer as an int32.
func (r *Rand) Int31() int32 { return int32(r.Int63() >> 32) }

// Int returns a non-negative pseudo-random int.
func (r *Rand) Int() int {
	u := uint(r.Int63())
	return int(u << 1 >> 1) // clear sign bit if int == int32
}

// Int63n returns, as an int64, a non-negative pseudo-random number in [0,n).
// It panics if n <= 0.
func (r *Rand) Int63n(n int64) int64 {
	if n <= 0 {
		panic("invalid argument to Int63n")
	}
	if n&(n-1) == 0 { // n is power of two, can mask
		return r.Int63() & (n - 1)
	}
	max := int64((1 << 63) - 1 - (1<<63)%uint64(n))
	v := r.Int63()
	for v > max {
		v = r.Int63()
	}
	return v % n
}

// Int31n returns, as an int32, a non-negative pseudo-random number in [0,n).
// It panics if n <= 0.
func (r *Rand) Int31n(n int32) int32 {
	if n <= 0 {
		panic("invalid argument to Int31n")
	}
	if n&(n-1) == 0 { // n is power of two, can mask
		return r.Int31() & (n - 1)
	}
	max := int32((1 << 31) - 1 - (1<<31)%uint32(n))
	v := r.Int31()
	for v > max {
		v = r.Int31()
	}
	return v % n
}

// Intn returns, as an int, a non-negative pseudo-random number in [0,n).
// It panics if n <= 0.
func (r *Rand) Intn(n int) int {
	if n <= 0 {
		panic("invalid argument to Intn")
	}
	if n <= 1<<31-1 {
		return int(r.Int31n(int32(n)))
	}
	return int(r.Int63n(int64(n)))
}

// Float64 returns, as a float64, a pseudo-random number in [0.0,1.0).
func (r *Rand) Float64() float64 {
	// A clearer, simpler implementation would be:
	//	return float64(r.Int63n(1<<53)) / (1<<53)
	// However, Go 1 shipped with
	//	return float64(r.Int63()) / (1 << 63)
	// and we want to preserve that value stream.
	//
	// There is one bug in the value stream: r.Int63() may be so close
	// to 1<<63 that the division rounds up to 1.0, and we've guaranteed
	// that the result is always less than 1.0.
	//
	// We tried to fix this by mapping 1.0 back to 0.0, but since float64
	// values near 0 are much denser than near 1, mapping 1 to 0 caused
	// a theoretically significant overshoot in the probability of returning 0.
	// Instead of that, if we round up to 1, just try again.
	// Getting 1 only happens 1/2⁵³ of the time, so most clients
	// will not observe it anyway.
again:
	f := float64(r.Int63()) / (1 << 63)
	if f == 1 {
		goto again // resample; this branch is taken O(never)
	}
	return f
}

// Float32 returns, as a float32, a pseudo-random number in [0.0,1.0).
func (r *Rand) Float32() float32 {
	// Same rationale as in Float64: we want to preserve the Go 1 value
	// stream except we want to fix it not to return 1.0
	// This only happens 1/2²⁴ of the time (plus the 1/2⁵³ of the time in Float64).
again:
	f := float32(r.Float64())
	if f == 1 {
		goto again // resample; this branch is taken O(very rarely)
	}
	return f
}

// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n).
func (r *Rand) Perm(n int) []int {
	m := make([]int, n)
	// In the following loop, the iteration when i=0 always swaps m[0] with m[0].
	// A change to remove this useless iteration is to assign 1 to i in the init
	// statement. But Perm also effects r. Making this change will affect
	// the final state of r. So this change can't be made for compatibility
	// reasons for Go 1.
	for i := 0; i < n; i++ {
		j := r.Intn(i + 1)
		m[i] = m[j]
		m[j] = i
	}
	return m
}

// Read generates len(p) random bytes and writes them into p. It
// always returns len(p) and a nil error.
func (r *Rand) Read(p []byte) (n int, err error) {
	for i := 0; i < len(p); i += 7 {
		val := r.src.Int63()
		for j := 0; i+j < len(p) && j < 7; j++ {
			p[i+j] = byte(val)
			val >>= 8
		}
	}
	return len(p), nil
}

/*
 * Top-level convenience functions
 */

var globalRand = New(&lockedSource{src: NewSource(1)})

// Seed uses the provided seed value to initialize the default Source to a
// deterministic state. If Seed is not called, the generator behaves as
// if seeded by Seed(1).
func Seed(seed int64) { globalRand.Seed(seed) }

// Int63 returns a non-negative pseudo-random 63-bit integer as an int64
// from the default Source.
func Int63() int64 { return globalRand.Int63() }

// Uint32 returns a pseudo-random 32-bit value as a uint32
// from the default Source.
func Uint32() uint32 { return globalRand.Uint32() }

// Int31 returns a non-negative pseudo-random 31-bit integer as an int32
// from the default Source.
func Int31() int32 { return globalRand.Int31() }

// Int returns a non-negative pseudo-random int from the default Source.
func Int() int { return globalRand.Int() }

// Int63n returns, as an int64, a non-negative pseudo-random number in [0,n)
// from the default Source.
// It panics if n <= 0.
func Int63n(n int64) int64 { return globalRand.Int63n(n) }

// Int31n returns, as an int32, a non-negative pseudo-random number in [0,n)
// from the default Source.
// It panics if n <= 0.
func Int31n(n int32) int32 { return globalRand.Int31n(n) }

// Intn returns, as an int, a non-negative pseudo-random number in [0,n)
// from the default Source.
// It panics if n <= 0.
func Intn(n int) int { return globalRand.Intn(n) }

// Float64 returns, as a float64, a pseudo-random number in [0.0,1.0)
// from the default Source.
func Float64() float64 { return globalRand.Float64() }

// Float32 returns, as a float32, a pseudo-random number in [0.0,1.0)
// from the default Source.
func Float32() float32 { return globalRand.Float32() }

// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n)
// from the default Source.
func Perm(n int) []int { return globalRand.Perm(n) }

// Read generates len(p) random bytes from the default Source and
// writes them into p. It always returns len(p) and a nil error.
func Read(p []byte) (n int, err error) { return globalRand.Read(p) }

// NormFloat64 returns a normally distributed float64 in the range
// [-math.MaxFloat64, +math.MaxFloat64] with
// standard normal distribution (mean = 0, stddev = 1)
// from the default Source.
// To produce a different normal distribution, callers can
// adjust the output using:
//
//  sample = NormFloat64() * desiredStdDev + desiredMean
//
func NormFloat64() float64 { return globalRand.NormFloat64() }

// ExpFloat64 returns an exponentially distributed float64 in the range
// (0, +math.MaxFloat64] with an exponential distribution whose rate parameter
// (lambda) is 1 and whose mean is 1/lambda (1) from the default Source.
// To produce a distribution with a different rate parameter,
// callers can adjust the output using:
//
//  sample = ExpFloat64() / desiredRateParameter
//
func ExpFloat64() float64 { return globalRand.ExpFloat64() }

type lockedSource struct {
	lk  sync.Mutex
	src Source
}

func (r *lockedSource) Int63() (n int64) {
	r.lk.Lock()
	n = r.src.Int63()
	r.lk.Unlock()
	return
}

func (r *lockedSource) Seed(seed int64) {
	r.lk.Lock()
	r.src.Seed(seed)
	r.lk.Unlock()
}
<commit_msg>math/rand: Doc fix for how many bits Seed uses<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package rand implements pseudo-random number generators.
//
// Random numbers are generated by a Source. Top-level functions, such as
// Float64 and Int, use a default shared Source that produces a deterministic
// sequence of values each time a program is run. Use the Seed function to
// initialize the default Source if different behavior is required for each run.
// The default Source is safe for concurrent use by multiple goroutines.
//
// For random numbers suitable for security-sensitive work, see the crypto/rand
// package.
package rand

import "sync"

// A Source represents a source of uniformly-distributed
// pseudo-random int64 values in the range [0, 1<<63).
type Source interface {
	Int63() int64
	Seed(seed int64)
}

// NewSource returns a new pseudo-random Source seeded with the given value.
func NewSource(seed int64) Source {
	var rng rngSource
	rng.Seed(seed)
	return &rng
}

// A Rand is a source of random numbers.
type Rand struct {
	src Source
}

// New returns a new Rand that uses random values from src
// to generate other random values.
func New(src Source) *Rand { return &Rand{src} }

// Seed uses the provided seed value to initialize the generator to a deterministic state.
func (r *Rand) Seed(seed int64) { r.src.Seed(seed) }

// Int63 returns a non-negative pseudo-random 63-bit integer as an int64.
func (r *Rand) Int63() int64 { return r.src.Int63() }

// Uint32 returns a pseudo-random 32-bit value as a uint32.
func (r *Rand) Uint32() uint32 { return uint32(r.Int63() >> 31) }

// Int31 returns a non-negative pseudo-random 31-bit integer as an int32.
func (r *Rand) Int31() int32 { return int32(r.Int63() >> 32) }

// Int returns a non-negative pseudo-random int.
func (r *Rand) Int() int {
	u := uint(r.Int63())
	return int(u << 1 >> 1) // clear sign bit if int == int32
}

// Int63n returns, as an int64, a non-negative pseudo-random number in [0,n).
// It panics if n <= 0.
func (r *Rand) Int63n(n int64) int64 {
	if n <= 0 {
		panic("invalid argument to Int63n")
	}
	if n&(n-1) == 0 { // n is power of two, can mask
		return r.Int63() & (n - 1)
	}
	max := int64((1 << 63) - 1 - (1<<63)%uint64(n))
	v := r.Int63()
	for v > max {
		v = r.Int63()
	}
	return v % n
}

// Int31n returns, as an int32, a non-negative pseudo-random number in [0,n).
// It panics if n <= 0.
func (r *Rand) Int31n(n int32) int32 {
	if n <= 0 {
		panic("invalid argument to Int31n")
	}
	if n&(n-1) == 0 { // n is power of two, can mask
		return r.Int31() & (n - 1)
	}
	max := int32((1 << 31) - 1 - (1<<31)%uint32(n))
	v := r.Int31()
	for v > max {
		v = r.Int31()
	}
	return v % n
}

// Intn returns, as an int, a non-negative pseudo-random number in [0,n).
// It panics if n <= 0.
func (r *Rand) Intn(n int) int {
	if n <= 0 {
		panic("invalid argument to Intn")
	}
	if n <= 1<<31-1 {
		return int(r.Int31n(int32(n)))
	}
	return int(r.Int63n(int64(n)))
}

// Float64 returns, as a float64, a pseudo-random number in [0.0,1.0).
func (r *Rand) Float64() float64 {
	// A clearer, simpler implementation would be:
	//	return float64(r.Int63n(1<<53)) / (1<<53)
	// However, Go 1 shipped with
	//	return float64(r.Int63()) / (1 << 63)
	// and we want to preserve that value stream.
	//
	// There is one bug in the value stream: r.Int63() may be so close
	// to 1<<63 that the division rounds up to 1.0, and we've guaranteed
	// that the result is always less than 1.0.
	//
	// We tried to fix this by mapping 1.0 back to 0.0, but since float64
	// values near 0 are much denser than near 1, mapping 1 to 0 caused
	// a theoretically significant overshoot in the probability of returning 0.
	// Instead of that, if we round up to 1, just try again.
	// Getting 1 only happens 1/2⁵³ of the time, so most clients
	// will not observe it anyway.
again:
	f := float64(r.Int63()) / (1 << 63)
	if f == 1 {
		goto again // resample; this branch is taken O(never)
	}
	return f
}

// Float32 returns, as a float32, a pseudo-random number in [0.0,1.0).
func (r *Rand) Float32() float32 {
	// Same rationale as in Float64: we want to preserve the Go 1 value
	// stream except we want to fix it not to return 1.0
	// This only happens 1/2²⁴ of the time (plus the 1/2⁵³ of the time in Float64).
again:
	f := float32(r.Float64())
	if f == 1 {
		goto again // resample; this branch is taken O(very rarely)
	}
	return f
}

// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n).
func (r *Rand) Perm(n int) []int {
	m := make([]int, n)
	// In the following loop, the iteration when i=0 always swaps m[0] with m[0].
	// A change to remove this useless iteration is to assign 1 to i in the init
	// statement. But Perm also effects r. Making this change will affect
	// the final state of r. So this change can't be made for compatibility
	// reasons for Go 1.
	for i := 0; i < n; i++ {
		j := r.Intn(i + 1)
		m[i] = m[j]
		m[j] = i
	}
	return m
}

// Read generates len(p) random bytes and writes them into p. It
// always returns len(p) and a nil error.
func (r *Rand) Read(p []byte) (n int, err error) {
	for i := 0; i < len(p); i += 7 {
		val := r.src.Int63()
		for j := 0; i+j < len(p) && j < 7; j++ {
			p[i+j] = byte(val)
			val >>= 8
		}
	}
	return len(p), nil
}

/*
 * Top-level convenience functions
 */

var globalRand = New(&lockedSource{src: NewSource(1)})

// Seed uses the provided seed value to initialize the default Source to a
// deterministic state. If Seed is not called, the generator behaves as
// if seeded by Seed(1). Only uses the bottom 31 bits of seed; the top 33
// bits are ignored.
func Seed(seed int64) { globalRand.Seed(seed) }

// Int63 returns a non-negative pseudo-random 63-bit integer as an int64
// from the default Source.
func Int63() int64 { return globalRand.Int63() }

// Uint32 returns a pseudo-random 32-bit value as a uint32
// from the default Source.
func Uint32() uint32 { return globalRand.Uint32() }

// Int31 returns a non-negative pseudo-random 31-bit integer as an int32
// from the default Source.
func Int31() int32 { return globalRand.Int31() }

// Int returns a non-negative pseudo-random int from the default Source.
func Int() int { return globalRand.Int() }

// Int63n returns, as an int64, a non-negative pseudo-random number in [0,n)
// from the default Source.
// It panics if n <= 0.
func Int63n(n int64) int64 { return globalRand.Int63n(n) }

// Int31n returns, as an int32, a non-negative pseudo-random number in [0,n)
// from the default Source.
// It panics if n <= 0.
func Int31n(n int32) int32 { return globalRand.Int31n(n) }

// Intn returns, as an int, a non-negative pseudo-random number in [0,n)
// from the default Source.
// It panics if n <= 0.
func Intn(n int) int { return globalRand.Intn(n) }

// Float64 returns, as a float64, a pseudo-random number in [0.0,1.0)
// from the default Source.
func Float64() float64 { return globalRand.Float64() }

// Float32 returns, as a float32, a pseudo-random number in [0.0,1.0)
// from the default Source.
func Float32() float32 { return globalRand.Float32() }

// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n)
// from the default Source.
func Perm(n int) []int { return globalRand.Perm(n) }

// Read generates len(p) random bytes from the default Source and
// writes them into p. It always returns len(p) and a nil error.
func Read(p []byte) (n int, err error) { return globalRand.Read(p) }

// NormFloat64 returns a normally distributed float64 in the range
// [-math.MaxFloat64, +math.MaxFloat64] with
// standard normal distribution (mean = 0, stddev = 1)
// from the default Source.
// To produce a different normal distribution, callers can
// adjust the output using:
//
//  sample = NormFloat64() * desiredStdDev + desiredMean
//
func NormFloat64() float64 { return globalRand.NormFloat64() }

// ExpFloat64 returns an exponentially distributed float64 in the range
// (0, +math.MaxFloat64] with an exponential distribution whose rate parameter
// (lambda) is 1 and whose mean is 1/lambda (1) from the default Source.
// To produce a distribution with a different rate parameter,
// callers can adjust the output using:
//
//  sample = ExpFloat64() / desiredRateParameter
//
func ExpFloat64() float64 { return globalRand.ExpFloat64() }

type lockedSource struct {
	lk  sync.Mutex
	src Source
}

func (r *lockedSource) Int63() (n int64) {
	r.lk.Lock()
	n = r.src.Int63()
	r.lk.Unlock()
	return
}

func (r *lockedSource) Seed(seed int64) {
	r.lk.Lock()
	r.src.Seed(seed)
	r.lk.Unlock()
}
<|endoftext|>


<commit_before>package cluster

import (
	"encoding/json"

	"github.com/SparrowDb/sparrowdb/db"
	"github.com/SparrowDb/sparrowdb/errors"
	"github.com/SparrowDb/sparrowdb/model"
	"github.com/SparrowDb/sparrowdb/slog"
	"github.com/SparrowDb/sparrowdb/spql"
	"github.com/SparrowDb/sparrowdb/util"
	"github.com/SparrowDb/sparrowdb/util/uuid"
	"github.com/nats-io/nats"
)

var (
	_config        *db.SparrowConfig
	_dbm           *db.DBManager
	_queryExecutor *spql.QueryExecutor
	_connection    *nats.Conn
	_encon         *nats.EncodedConn
	_enconData     *nats.EncodedConn

	_sparrowQuerySub = "sparrow.query"
	_sparrowDataSub  = "sparrow.data"

	chRecvData chan string
	chSendData chan string
)

type message struct {
	Name    string
	Vars    map[string]string
	Content interface{}
}

func connect() {
	var err error
	_connection, err = nats.Connect(_config.PublisherServers)
	if err != nil {
		slog.Fatalf(err.Error())
	}

	_encon, err = nats.NewEncodedConn(_connection, nats.JSON_ENCODER)
	if err != nil {
		slog.Fatalf(err.Error())
	}

	_enconData, err = nats.NewEncodedConn(_connection, nats.GOB_ENCODER)
	if err != nil {
		slog.Fatalf(err.Error())
	}

	registerReceiverBinder()
}

func registerReceiverBinder() {
	_encon.Subscribe(_sparrowQuerySub, func(m *message) {
		if m.Name != _config.NodeName {
			var qr spql.QueryRequest
			str := m.Content.(string)
			json.Unmarshal([]byte(str), &qr)

			q, _ := qr.ParseQuery()
			results := <-_queryExecutor.ExecuteQuery(&q)
			if results == nil {
				slog.Errorf(errors.ErrEmptyQueryResult.Error())
			}
		}
	})

	_enconData.Subscribe(_sparrowDataSub, func(m *message) {
		if m.Name != _config.NodeName {
			dbname := m.Vars["database"]

			if db, ok := _dbm.GetDatabase(dbname); ok == true {
				bs := util.NewByteStreamFromBytes(m.Content.([]byte))
				df := model.NewDataDefinitionFromByteStream(bs)

				storedDf, found := db.GetDataByKey(df.Key)

				if found {
					tm, _ := uuid.ParseUUID(df.Token)
					stm, _ := uuid.ParseUUID(storedDf.Token)

					if tm.Time().Before(stm.Time()) || tm.Time().Equal(stm.Time()) {
						return
					}

					df.Revision = storedDf.Revision
					df.Revision++
				}

				db.InsertCheckUpsert(df, true)
			}
		}
	})
}

// PublishQuery publishes query
func PublishQuery(query spql.QueryRequest) {
	if query.Action == "select" {
		return
	}

	b, _ := json.Marshal(query)
	m := message{
		_config.NodeName,
		map[string]string{},
		string(b),
	}
	_encon.Publish(_sparrowQuerySub, m)
}

// PublishData plushes data
func PublishData(df model.DataDefinition, dbname string) {
	m := message{
		_config.NodeName,
		map[string]string{
			"database": dbname,
		},
		df.ToByteStream().Bytes(),
	}
	_enconData.Publish(_sparrowDataSub, m)
}

// Close finishes cluster service
func Close() {
	slog.Infof("Stopping Cluster service")
	_encon.Close()
	_enconData.Close()
	_connection.Close()
}

// Start Starts cluster service
func Start(config *db.SparrowConfig, dbm *db.DBManager) {
	slog.Infof("Starting Cluster service")
	_config = config
	_dbm = dbm
	_queryExecutor = spql.NewQueryExecutor(dbm)
	connect()
}
<commit_msg>nats log<commit_after>package cluster

import (
	"encoding/json"

	"github.com/SparrowDb/sparrowdb/db"
	"github.com/SparrowDb/sparrowdb/errors"
	"github.com/SparrowDb/sparrowdb/model"
	"github.com/SparrowDb/sparrowdb/slog"
	"github.com/SparrowDb/sparrowdb/spql"
	"github.com/SparrowDb/sparrowdb/util"
	"github.com/SparrowDb/sparrowdb/util/uuid"
	"github.com/nats-io/nats"
)

var (
	_config        *db.SparrowConfig
	_dbm           *db.DBManager
	_queryExecutor *spql.QueryExecutor
	_connection    *nats.Conn
	_encon         *nats.EncodedConn
	_enconData     *nats.EncodedConn

	_sparrowQuerySub = "sparrow.query"
	_sparrowDataSub  = "sparrow.data"

	chRecvData chan string
	chSendData chan string
)

type message struct {
	Name    string
	Vars    map[string]string
	Content interface{}
}

func onreconnect(nc *nats.Conn) {
	slog.Warnf("Reconnected to %v\n", nc.ConnectedUrl())
}

func ondisconnect(nc *nats.Conn) {
	slog.Warnf("Disconnected from cluster\n")
}

func onclose(nc *nats.Conn) {
	slog.Warnf("Connection closed. Reason: %q\n", nc.LastError())
}

func onerror(nc *nats.Conn, sub *nats.Subscription, err error) {
	slog.Errorf("Cluster error:%v\n", err.Error())
}

func connect() {
	var err error
	_connection, err = nats.Connect(_config.PublisherServers)
	_connection.SetReconnectHandler(onreconnect)
	_connection.SetDisconnectHandler(ondisconnect)
	_connection.SetClosedHandler(ondisconnect)
	_connection.SetErrorHandler(onerror)

	if err != nil {
		slog.Fatalf(err.Error())
	}

	_encon, err = nats.NewEncodedConn(_connection, nats.JSON_ENCODER)
	if err != nil {
		slog.Fatalf(err.Error())
	}

	_enconData, err = nats.NewEncodedConn(_connection, nats.GOB_ENCODER)
	if err != nil {
		slog.Fatalf(err.Error())
	}

	registerReceiverBinder()
}

func registerReceiverBinder() {
	_encon.Subscribe(_sparrowQuerySub, func(m *message) {
		if m.Name != _config.NodeName {
			var qr spql.QueryRequest
			str := m.Content.(string)
			json.Unmarshal([]byte(str), &qr)

			q, _ := qr.ParseQuery()
			results := <-_queryExecutor.ExecuteQuery(&q)
			if results == nil {
				slog.Errorf(errors.ErrEmptyQueryResult.Error())
			}
		}
	})

	_enconData.Subscribe(_sparrowDataSub, func(m *message) {
		if m.Name != _config.NodeName {
			dbname := m.Vars["database"]

			if db, ok := _dbm.GetDatabase(dbname); ok == true {
				bs := util.NewByteStreamFromBytes(m.Content.([]byte))
				df := model.NewDataDefinitionFromByteStream(bs)

				storedDf, found := db.GetDataByKey(df.Key)

				if found {
					tm, _ := uuid.ParseUUID(df.Token)
					stm, _ := uuid.ParseUUID(storedDf.Token)

					if tm.Time().Before(stm.Time()) || tm.Time().Equal(stm.Time()) {
						return
					}

					df.Revision = storedDf.Revision
					df.Revision++
				}

				db.InsertCheckUpsert(df, true)
			}
		}
	})
}

// PublishQuery publishes query
func PublishQuery(query spql.QueryRequest) {
	if query.Action == "select" {
		return
	}

	b, _ := json.Marshal(query)
	m := message{
		_config.NodeName,
		map[string]string{},
		string(b),
	}
	_encon.Publish(_sparrowQuerySub, m)
}

// PublishData plushes data
func PublishData(df model.DataDefinition, dbname string) {
	m := message{
		_config.NodeName,
		map[string]string{
			"database": dbname,
		},
		df.ToByteStream().Bytes(),
	}
	_enconData.Publish(_sparrowDataSub, m)
}

// Close finishes cluster service
func Close() {
	slog.Infof("Stopping Cluster service")
	_encon.Close()
	_enconData.Close()
	_connection.Close()
}

// Start Starts cluster service
func Start(config *db.SparrowConfig, dbm *db.DBManager) {
	slog.Infof("Starting Cluster service")
	_config = config
	_dbm = dbm
	_queryExecutor = spql.NewQueryExecutor(dbm)
	connect()
}
<|endoftext|>


<commit_before>
package main

import(
  "fmt"
  "path/filepath"
  "os/exec"
  "strings"
)

func main() {
  files, _ := filepath.Glob("../mapgen/map-10[0]*.xml")
  fmt.Println(files)
  for _,element := range files {
    out := strings.Split(element, "/")[2]
    out = strings.Split(out, ".")[0] + ".gexf"
    fmt.Println(out)
    command := exec.Command("prun", "-no-panda", "../src/cgc", "1", "-G", "-m",
    element, "-g", out)
    command.Run()
  }
}
<commit_msg>Updated make gexf script.<commit_after>
package main

import(
  "fmt"
  "path/filepath"
  "os/exec"
  "strings"
)

func main() {
  files, _ := filepath.Glob("../mapgen/map-*.xml")
  // fmt.Println(files)
  for i := 0; i < len(files); i++ {
    element := files[i]
    out := strings.Split(element, "/")[2]
    out = strings.Split(out, ".")[0] + ".gexf"
    var size int
    fmt.Sscanf(out, "map-%d.gexf", &size)
    if size > 10000 {
      fmt.Println("Skipping gexf with", size, "nodes.")
      continue
    }
    fmt.Println(out)

    command := exec.Command("prun", "-no-panda", "../src/cgc", "1", "-G", "-t",
    "50", "-m", element, "-g", out)
    command.Run()
  }
}
<|endoftext|>


<commit_before>// Copyright 2015 Hajime Hoshi
//
// 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.

// +build js

package audio

import (
	"io"
	"io/ioutil"

	"github.com/gopherjs/gopherjs/js"
)

var context *js.Object

type player struct {
	src          io.ReadSeeker
	sampleRate   int
	position     float64
	bufferSource *js.Object
}

func initialize() bool {
	// Do nothing in node.js.
	if js.Global.Get("require") != js.Undefined {
		return false
	}

	class := js.Global.Get("AudioContext")
	if class == js.Undefined {
		class = js.Global.Get("webkitAudioContext")
	}
	if class == js.Undefined {
		return false
	}
	context = class.New()
	return true
}

func newPlayer(src io.ReadSeeker, sampleRate int) *Player {
	if context == nil {
		if !initialize() {
			panic("audio couldn't be initialized")
		}
	}

	p := &player{
		src:          src,
		sampleRate:   sampleRate,
		position:     context.Get("currentTime").Float(),
		bufferSource: nil,
	}
	return &Player{p}
}

func toLR(data []byte) ([]int16, []int16) {
	l := make([]int16, len(data)/4)
	r := make([]int16, len(data)/4)
	for i := 0; i < len(data)/4; i++ {
		l[i] = int16(data[4*i]) | int16(data[4*i+1])<<8
		r[i] = int16(data[4*i+2]) | int16(data[4*i+3])<<8
	}
	return l, r
}

func (p *player) play() error {
	// TODO: Reading all data at once is temporary implemntation. Treat this as stream.
	buf, err := ioutil.ReadAll(p.src)
	if err != nil {
		return err
	}
	if len(buf) == 0 {
		return nil
	}
	// TODO: p.position should be updated
	if p.bufferSource != nil {
		p.bufferSource.Call("start", p.position)
		return nil
	}
	const channelNum = 2
	const bytesPerSample = channelNum * 16 / 8
	b := context.Call("createBuffer", channelNum, len(buf)/bytesPerSample, p.sampleRate)
	l := b.Call("getChannelData", 0)
	r := b.Call("getChannelData", 1)
	il, ir := toLR(buf)
	const max = 1 << 15
	for i := 0; i < len(il); i++ {
		l.SetIndex(i, float64(il[i])/max)
		r.SetIndex(i, float64(ir[i])/max)
	}
	p.bufferSource = context.Call("createBufferSource")
	p.bufferSource.Set("buffer", b)
	p.bufferSource.Call("connect", context.Get("destination"))
	p.bufferSource.Call("start", p.position)
	p.position += b.Get("duration").Float()
	return nil
}

func (p *player) close() error {
	p.bufferSource.Call("stop")
	p.bufferSource.Call("disconnect")
	return nil
}
<commit_msg>audio: Bug fix: newPlayer should return error in JS<commit_after>// Copyright 2015 Hajime Hoshi
//
// 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.

// +build js

package audio

import (
	"io"
	"io/ioutil"

	"github.com/gopherjs/gopherjs/js"
)

var context *js.Object

type player struct {
	src          io.ReadSeeker
	sampleRate   int
	position     float64
	bufferSource *js.Object
}

func initialize() bool {
	// Do nothing in node.js.
	if js.Global.Get("require") != js.Undefined {
		return false
	}

	class := js.Global.Get("AudioContext")
	if class == js.Undefined {
		class = js.Global.Get("webkitAudioContext")
	}
	if class == js.Undefined {
		return false
	}
	context = class.New()
	return true
}

func newPlayer(src io.ReadSeeker, sampleRate int) (*Player, error) {
	if context == nil {
		if !initialize() {
			panic("audio couldn't be initialized")
		}
	}

	p := &player{
		src:          src,
		sampleRate:   sampleRate,
		position:     context.Get("currentTime").Float(),
		bufferSource: nil,
	}
	return &Player{p}, nil
}

func toLR(data []byte) ([]int16, []int16) {
	l := make([]int16, len(data)/4)
	r := make([]int16, len(data)/4)
	for i := 0; i < len(data)/4; i++ {
		l[i] = int16(data[4*i]) | int16(data[4*i+1])<<8
		r[i] = int16(data[4*i+2]) | int16(data[4*i+3])<<8
	}
	return l, r
}

func (p *player) play() error {
	// TODO: Reading all data at once is temporary implemntation. Treat this as stream.
	buf, err := ioutil.ReadAll(p.src)
	if err != nil {
		return err
	}
	if len(buf) == 0 {
		return nil
	}
	// TODO: p.position should be updated
	if p.bufferSource != nil {
		p.bufferSource.Call("start", p.position)
		return nil
	}
	const channelNum = 2
	const bytesPerSample = channelNum * 16 / 8
	b := context.Call("createBuffer", channelNum, len(buf)/bytesPerSample, p.sampleRate)
	l := b.Call("getChannelData", 0)
	r := b.Call("getChannelData", 1)
	il, ir := toLR(buf)
	const max = 1 << 15
	for i := 0; i < len(il); i++ {
		l.SetIndex(i, float64(il[i])/max)
		r.SetIndex(i, float64(ir[i])/max)
	}
	p.bufferSource = context.Call("createBufferSource")
	p.bufferSource.Set("buffer", b)
	p.bufferSource.Call("connect", context.Get("destination"))
	p.bufferSource.Call("start", p.position)
	p.position += b.Get("duration").Float()
	return nil
}

func (p *player) close() error {
	p.bufferSource.Call("stop")
	p.bufferSource.Call("disconnect")
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2015 Hajime Hoshi
//
// 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.

// +build js

package audio

import (
	"io"
	"runtime"

	"github.com/gopherjs/gopherjs/js"
)

type player struct {
	src               io.Reader
	sampleRate        int
	positionInSamples int64
	context           *js.Object
	bufferSource      *js.Object
}

func startPlaying(src io.Reader, sampleRate int) (*player, error) {
	// Do nothing in node.js.
	if js.Global.Get("require") != js.Undefined {
		return nil, nil
	}

	class := js.Global.Get("AudioContext")
	if class == js.Undefined {
		class = js.Global.Get("webkitAudioContext")
	}
	if class == js.Undefined {
		panic("audio: audio couldn't be initialized")
	}
	p := &player{
		src:          src,
		sampleRate:   sampleRate,
		bufferSource: nil,
		context:      class.New(),
	}
	p.positionInSamples = int64(p.context.Get("currentTime").Float() * float64(p.sampleRate))
	if err := p.start(); err != nil {
		return nil, err
	}
	return p, nil
}

func toLR(data []byte) ([]int16, []int16) {
	l := make([]int16, len(data)/4)
	r := make([]int16, len(data)/4)
	for i := 0; i < len(data)/4; i++ {
		l[i] = int16(data[4*i]) | int16(data[4*i+1])<<8
		r[i] = int16(data[4*i+2]) | int16(data[4*i+3])<<8
	}
	return l, r
}

func max64(a, b int64) int64 {
	if a > b {
		return a
	}
	return b
}

func (p *player) proceed() error {
	const bufferSize = 4096
	c := int64(p.context.Get("currentTime").Float() * float64(p.sampleRate))
	if p.positionInSamples < c {
		p.positionInSamples = c
	}
	b := make([]byte, bufferSize)
	for 0 < len(b) {
		n, err := p.src.Read(b)
		if 0 < n {
			const channelNum = 2
			const bytesPerSample = channelNum * 16 / 8
			buf := p.context.Call("createBuffer", channelNum, n/bytesPerSample, p.sampleRate)
			l := buf.Call("getChannelData", 0)
			r := buf.Call("getChannelData", 1)
			il, ir := toLR(b[:n])
			const max = 1 << 15
			for i := 0; i < len(il); i++ {
				l.SetIndex(i, float64(il[i])/max)
				r.SetIndex(i, float64(ir[i])/max)
			}
			p.bufferSource = p.context.Call("createBufferSource")
			p.bufferSource.Set("buffer", buf)
			p.bufferSource.Call("connect", p.context.Get("destination"))
			p.bufferSource.Call("start", float64(max64(p.positionInSamples, c))/float64(p.sampleRate))
			p.positionInSamples += int64(len(il))
			b = b[n:]
		}
		if err != nil {
			return err
		}
		runtime.Gosched()
	}
	return nil
}

func (p *player) start() error {
	// TODO: What if play is already called?
	go func() {
		defer p.close()
		for {
			err := p.proceed()
			if err == io.EOF {
				break
			}
			if err != nil {
				// TODO: Record the last error
				panic(err)
			}
			runtime.Gosched()
		}
	}()
	return nil
}

func (p *player) close() error {
	if p.bufferSource == nil {
		return nil
	}
	p.bufferSource.Call("stop")
	p.bufferSource.Call("disconnect")
	p.bufferSource = nil
	return nil
}
<commit_msg>audio: Refactoring: Remove unneeded for loop<commit_after>// Copyright 2015 Hajime Hoshi
//
// 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.

// +build js

package audio

import (
	"io"
	"runtime"

	"github.com/gopherjs/gopherjs/js"
)

type player struct {
	src               io.Reader
	sampleRate        int
	positionInSamples int64
	context           *js.Object
	bufferSource      *js.Object
}

func startPlaying(src io.Reader, sampleRate int) (*player, error) {
	// Do nothing in node.js.
	if js.Global.Get("require") != js.Undefined {
		return nil, nil
	}

	class := js.Global.Get("AudioContext")
	if class == js.Undefined {
		class = js.Global.Get("webkitAudioContext")
	}
	if class == js.Undefined {
		panic("audio: audio couldn't be initialized")
	}
	p := &player{
		src:          src,
		sampleRate:   sampleRate,
		bufferSource: nil,
		context:      class.New(),
	}
	p.positionInSamples = int64(p.context.Get("currentTime").Float() * float64(p.sampleRate))
	if err := p.start(); err != nil {
		return nil, err
	}
	return p, nil
}

func toLR(data []byte) ([]int16, []int16) {
	l := make([]int16, len(data)/4)
	r := make([]int16, len(data)/4)
	for i := 0; i < len(data)/4; i++ {
		l[i] = int16(data[4*i]) | int16(data[4*i+1])<<8
		r[i] = int16(data[4*i+2]) | int16(data[4*i+3])<<8
	}
	return l, r
}

func max64(a, b int64) int64 {
	if a > b {
		return a
	}
	return b
}

func (p *player) proceed() error {
	const bufferSize = 4096
	c := int64(p.context.Get("currentTime").Float() * float64(p.sampleRate))
	if p.positionInSamples < c {
		p.positionInSamples = c
	}
	b := make([]byte, bufferSize)
	n, err := p.src.Read(b)
	if 0 < n {
		const channelNum = 2
		const bytesPerSample = channelNum * 16 / 8
		buf := p.context.Call("createBuffer", channelNum, n/bytesPerSample, p.sampleRate)
		l := buf.Call("getChannelData", 0)
		r := buf.Call("getChannelData", 1)
		il, ir := toLR(b[:n])
		const max = 1 << 15
		for i := 0; i < len(il); i++ {
			l.SetIndex(i, float64(il[i])/max)
			r.SetIndex(i, float64(ir[i])/max)
		}
		p.bufferSource = p.context.Call("createBufferSource")
		p.bufferSource.Set("buffer", buf)
		p.bufferSource.Call("connect", p.context.Get("destination"))
		p.bufferSource.Call("start", float64(p.positionInSamples)/float64(p.sampleRate))
		p.positionInSamples += int64(len(il))
	}
	return err
}

func (p *player) start() error {
	// TODO: What if play is already called?
	go func() {
		defer p.close()
		for {
			err := p.proceed()
			if err == io.EOF {
				break
			}
			if err != nil {
				// TODO: Record the last error
				panic(err)
			}
			runtime.Gosched()
		}
	}()
	return nil
}

func (p *player) close() error {
	if p.bufferSource == nil {
		return nil
	}
	p.bufferSource.Call("stop")
	p.bufferSource.Call("disconnect")
	p.bufferSource = nil
	return nil
}
<|endoftext|>


<commit_before>package weed_server

import (
	"bytes"
	"io"
	"mime"
	"mime/multipart"
	"net/http"
	"net/url"
	"path"
	"strconv"
	"strings"
	"time"

	"encoding/json"

	"github.com/chrislusf/seaweedfs/weed/glog"
	"github.com/chrislusf/seaweedfs/weed/images"
	"github.com/chrislusf/seaweedfs/weed/operation"
	"github.com/chrislusf/seaweedfs/weed/storage"
	"github.com/chrislusf/seaweedfs/weed/util"
)

var fileNameEscaper = strings.NewReplacer("\\", "\\\\", "\"", "\\\"")

func (vs *VolumeServer) GetOrHeadHandler(w http.ResponseWriter, r *http.Request) {
	n := new(storage.Needle)
	vid, fid, filename, ext, _ := parseURLPath(r.URL.Path)
	volumeId, err := storage.NewVolumeId(vid)
	if err != nil {
		glog.V(2).Infoln("parsing error:", err, r.URL.Path)
		w.WriteHeader(http.StatusBadRequest)
		return
	}
	err = n.ParsePath(fid)
	if err != nil {
		glog.V(2).Infoln("parsing fid error:", err, r.URL.Path)
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	glog.V(4).Infoln("volume", volumeId, "reading", n)
	if !vs.store.HasVolume(volumeId) {
		if !vs.ReadRedirect {
			glog.V(2).Infoln("volume is not local:", err, r.URL.Path)
			w.WriteHeader(http.StatusNotFound)
			return
		}
		lookupResult, err := operation.Lookup(vs.GetMaster(), volumeId.String())
		glog.V(2).Infoln("volume", volumeId, "found on", lookupResult, "error", err)
		if err == nil && len(lookupResult.Locations) > 0 {
			u, _ := url.Parse(util.NormalizeUrl(lookupResult.Locations[0].PublicUrl))
			u.Path = r.URL.Path
			arg := url.Values{}
			if c := r.FormValue("collection"); c != "" {
				arg.Set("collection", c)
			}
			u.RawQuery = arg.Encode()
			http.Redirect(w, r, u.String(), http.StatusMovedPermanently)

		} else {
			glog.V(2).Infoln("lookup error:", err, r.URL.Path)
			w.WriteHeader(http.StatusNotFound)
		}
		return
	}
	cookie := n.Cookie
	count, e := vs.store.ReadVolumeNeedle(volumeId, n)
	glog.V(4).Infoln("read bytes", count, "error", e)
	if e != nil || count < 0 {
		glog.V(0).Infof("read %s error:", r.URL.Path, e)
		w.WriteHeader(http.StatusNotFound)
		return
	}
	if n.Cookie != cookie {
		glog.V(0).Infoln("request", r.URL.Path, "with unmaching cookie seen:", cookie, "expected:", n.Cookie, "from", r.RemoteAddr, "agent", r.UserAgent())
		w.WriteHeader(http.StatusNotFound)
		return
	}
	if n.LastModified != 0 {
		w.Header().Set("Last-Modified", time.Unix(int64(n.LastModified), 0).UTC().Format(http.TimeFormat))
		if r.Header.Get("If-Modified-Since") != "" {
			if t, parseError := time.Parse(http.TimeFormat, r.Header.Get("If-Modified-Since")); parseError == nil {
				if t.Unix() >= int64(n.LastModified) {
					w.WriteHeader(http.StatusNotModified)
					return
				}
			}
		}
	}
	etag := n.Etag()
	if inm := r.Header.Get("If-None-Match"); inm == etag {
		w.WriteHeader(http.StatusNotModified)
		return
	}
	w.Header().Set("Etag", etag)

	if n.HasPairs() {
		pairMap := make(map[string]string)
		err = json.Unmarshal(n.Pairs, &pairMap)
		if err != nil {
			glog.V(0).Infoln("Unmarshal pairs error:", err)
		}
		for k, v := range pairMap {
			w.Header().Set(k, v)
		}
	}

	if vs.tryHandleChunkedFile(n, filename, w, r) {
		return
	}

	if n.NameSize > 0 && filename == "" {
		filename = string(n.Name)
		if ext == "" {
			ext = path.Ext(filename)
		}
	}
	mtype := ""
	if n.MimeSize > 0 {
		mt := string(n.Mime)
		if !strings.HasPrefix(mt, "application/octet-stream") {
			mtype = mt
		}
	}

	if ext != ".gz" {
		if n.IsGzipped() {
			if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
				w.Header().Set("Content-Encoding", "gzip")
			} else {
				if n.Data, err = operation.UnGzipData(n.Data); err != nil {
					glog.V(0).Infoln("ungzip error:", err, r.URL.Path)
				}
			}
		}
	}

	rs := conditionallyResizeImages(bytes.NewReader(n.Data), ext, r)

	if e := writeResponseContent(filename, mtype, rs, w, r); e != nil {
		glog.V(2).Infoln("response write error:", e)
	}
}

func (vs *VolumeServer) tryHandleChunkedFile(n *storage.Needle, fileName string, w http.ResponseWriter, r *http.Request) (processed bool) {
	if !n.IsChunkedManifest() || r.URL.Query().Get("cm") == "false" {
		return false
	}

	chunkManifest, e := operation.LoadChunkManifest(n.Data, n.IsGzipped())
	if e != nil {
		glog.V(0).Infof("load chunked manifest (%s) error: %v", r.URL.Path, e)
		return false
	}
	if fileName == "" && chunkManifest.Name != "" {
		fileName = chunkManifest.Name
	}

	ext := path.Ext(fileName)

	mType := ""
	if chunkManifest.Mime != "" {
		mt := chunkManifest.Mime
		if !strings.HasPrefix(mt, "application/octet-stream") {
			mType = mt
		}
	}

	w.Header().Set("X-File-Store", "chunked")

	chunkedFileReader := &operation.ChunkedFileReader{
		Manifest: chunkManifest,
		Master:   vs.GetMaster(),
	}
	defer chunkedFileReader.Close()

	rs := conditionallyResizeImages(chunkedFileReader, ext, r)

	if e := writeResponseContent(fileName, mType, rs, w, r); e != nil {
		glog.V(2).Infoln("response write error:", e)
	}
	return true
}

func conditionallyResizeImages(originalDataReaderSeeker io.ReadSeeker, ext string, r *http.Request) io.ReadSeeker {
	rs := originalDataReaderSeeker
	if len(ext) > 0 {
		ext = strings.ToLower(ext)
	}
	if ext == ".png" || ext == ".jpg" || ext == ".jpeg" || ext == ".gif" {
		width, height := 0, 0
		if r.FormValue("width") != "" {
			width, _ = strconv.Atoi(r.FormValue("width"))
		}
		if r.FormValue("height") != "" {
			height, _ = strconv.Atoi(r.FormValue("height"))
		}
		rs, _, _ = images.Resized(ext, originalDataReaderSeeker, width, height, r.FormValue("mode"))
	}
	return rs
}

func writeResponseContent(filename, mimeType string, rs io.ReadSeeker, w http.ResponseWriter, r *http.Request) error {
	totalSize, e := rs.Seek(0, 2)
	if mimeType == "" {
		if ext := path.Ext(filename); ext != "" {
			mimeType = mime.TypeByExtension(ext)
		}
	}
	if mimeType != "" {
		w.Header().Set("Content-Type", mimeType)
	}
	if filename != "" {
		contentDisposition := "inline"
		if r.FormValue("dl") != "" {
			if dl, _ := strconv.ParseBool(r.FormValue("dl")); dl {
				contentDisposition = "attachment"
			}
		}
		w.Header().Set("Content-Disposition", contentDisposition+`; filename="`+fileNameEscaper.Replace(filename)+`"`)
	}
	w.Header().Set("Accept-Ranges", "bytes")
	if r.Method == "HEAD" {
		w.Header().Set("Content-Length", strconv.FormatInt(totalSize, 10))
		return nil
	}
	rangeReq := r.Header.Get("Range")
	if rangeReq == "" {
		w.Header().Set("Content-Length", strconv.FormatInt(totalSize, 10))
		if _, e = rs.Seek(0, 0); e != nil {
			return e
		}
		_, e = io.Copy(w, rs)
		return e
	}

	//the rest is dealing with partial content request
	//mostly copy from src/pkg/net/http/fs.go
	ranges, err := parseRange(rangeReq, totalSize)
	if err != nil {
		http.Error(w, err.Error(), http.StatusRequestedRangeNotSatisfiable)
		return nil
	}
	if sumRangesSize(ranges) > totalSize {
		// The total number of bytes in all the ranges
		// is larger than the size of the file by
		// itself, so this is probably an attack, or a
		// dumb client.  Ignore the range request.
		return nil
	}
	if len(ranges) == 0 {
		return nil
	}
	if len(ranges) == 1 {
		// RFC 2616, Section 14.16:
		// "When an HTTP message includes the content of a single
		// range (for example, a response to a request for a
		// single range, or to a request for a set of ranges
		// that overlap without any holes), this content is
		// transmitted with a Content-Range header, and a
		// Content-Length header showing the number of bytes
		// actually transferred.
		// ...
		// A response to a request for a single range MUST NOT
		// be sent using the multipart/byteranges media type."
		ra := ranges[0]
		w.Header().Set("Content-Length", strconv.FormatInt(ra.length, 10))
		w.Header().Set("Content-Range", ra.contentRange(totalSize))
		w.WriteHeader(http.StatusPartialContent)
		if _, e = rs.Seek(ra.start, 0); e != nil {
			return e
		}

		_, e = io.CopyN(w, rs, ra.length)
		return e
	}
	// process multiple ranges
	for _, ra := range ranges {
		if ra.start > totalSize {
			http.Error(w, "Out of Range", http.StatusRequestedRangeNotSatisfiable)
			return nil
		}
	}
	sendSize := rangesMIMESize(ranges, mimeType, totalSize)
	pr, pw := io.Pipe()
	mw := multipart.NewWriter(pw)
	w.Header().Set("Content-Type", "multipart/byteranges; boundary="+mw.Boundary())
	sendContent := pr
	defer pr.Close() // cause writing goroutine to fail and exit if CopyN doesn't finish.
	go func() {
		for _, ra := range ranges {
			part, e := mw.CreatePart(ra.mimeHeader(mimeType, totalSize))
			if e != nil {
				pw.CloseWithError(e)
				return
			}
			if _, e = rs.Seek(ra.start, 0); e != nil {
				pw.CloseWithError(e)
				return
			}
			if _, e = io.CopyN(part, rs, ra.length); e != nil {
				pw.CloseWithError(e)
				return
			}
		}
		mw.Close()
		pw.Close()
	}()
	if w.Header().Get("Content-Encoding") == "" {
		w.Header().Set("Content-Length", strconv.FormatInt(sendSize, 10))
	}
	w.WriteHeader(http.StatusPartialContent)
	_, e = io.CopyN(w, sendContent, sendSize)
	return e
}
<commit_msg>fix build error<commit_after>package weed_server

import (
	"bytes"
	"io"
	"mime"
	"mime/multipart"
	"net/http"
	"net/url"
	"path"
	"strconv"
	"strings"
	"time"

	"encoding/json"

	"github.com/chrislusf/seaweedfs/weed/glog"
	"github.com/chrislusf/seaweedfs/weed/images"
	"github.com/chrislusf/seaweedfs/weed/operation"
	"github.com/chrislusf/seaweedfs/weed/storage"
	"github.com/chrislusf/seaweedfs/weed/util"
)

var fileNameEscaper = strings.NewReplacer("\\", "\\\\", "\"", "\\\"")

func (vs *VolumeServer) GetOrHeadHandler(w http.ResponseWriter, r *http.Request) {
	n := new(storage.Needle)
	vid, fid, filename, ext, _ := parseURLPath(r.URL.Path)
	volumeId, err := storage.NewVolumeId(vid)
	if err != nil {
		glog.V(2).Infoln("parsing error:", err, r.URL.Path)
		w.WriteHeader(http.StatusBadRequest)
		return
	}
	err = n.ParsePath(fid)
	if err != nil {
		glog.V(2).Infoln("parsing fid error:", err, r.URL.Path)
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	glog.V(4).Infoln("volume", volumeId, "reading", n)
	if !vs.store.HasVolume(volumeId) {
		if !vs.ReadRedirect {
			glog.V(2).Infoln("volume is not local:", err, r.URL.Path)
			w.WriteHeader(http.StatusNotFound)
			return
		}
		lookupResult, err := operation.Lookup(vs.GetMaster(), volumeId.String())
		glog.V(2).Infoln("volume", volumeId, "found on", lookupResult, "error", err)
		if err == nil && len(lookupResult.Locations) > 0 {
			u, _ := url.Parse(util.NormalizeUrl(lookupResult.Locations[0].PublicUrl))
			u.Path = r.URL.Path
			arg := url.Values{}
			if c := r.FormValue("collection"); c != "" {
				arg.Set("collection", c)
			}
			u.RawQuery = arg.Encode()
			http.Redirect(w, r, u.String(), http.StatusMovedPermanently)

		} else {
			glog.V(2).Infoln("lookup error:", err, r.URL.Path)
			w.WriteHeader(http.StatusNotFound)
		}
		return
	}
	cookie := n.Cookie
	count, e := vs.store.ReadVolumeNeedle(volumeId, n)
	glog.V(4).Infoln("read bytes", count, "error", e)
	if e != nil || count < 0 {
		glog.V(0).Infof("read %s error: %v", r.URL.Path, e)
		w.WriteHeader(http.StatusNotFound)
		return
	}
	if n.Cookie != cookie {
		glog.V(0).Infoln("request", r.URL.Path, "with unmaching cookie seen:", cookie, "expected:", n.Cookie, "from", r.RemoteAddr, "agent", r.UserAgent())
		w.WriteHeader(http.StatusNotFound)
		return
	}
	if n.LastModified != 0 {
		w.Header().Set("Last-Modified", time.Unix(int64(n.LastModified), 0).UTC().Format(http.TimeFormat))
		if r.Header.Get("If-Modified-Since") != "" {
			if t, parseError := time.Parse(http.TimeFormat, r.Header.Get("If-Modified-Since")); parseError == nil {
				if t.Unix() >= int64(n.LastModified) {
					w.WriteHeader(http.StatusNotModified)
					return
				}
			}
		}
	}
	etag := n.Etag()
	if inm := r.Header.Get("If-None-Match"); inm == etag {
		w.WriteHeader(http.StatusNotModified)
		return
	}
	w.Header().Set("Etag", etag)

	if n.HasPairs() {
		pairMap := make(map[string]string)
		err = json.Unmarshal(n.Pairs, &pairMap)
		if err != nil {
			glog.V(0).Infoln("Unmarshal pairs error:", err)
		}
		for k, v := range pairMap {
			w.Header().Set(k, v)
		}
	}

	if vs.tryHandleChunkedFile(n, filename, w, r) {
		return
	}

	if n.NameSize > 0 && filename == "" {
		filename = string(n.Name)
		if ext == "" {
			ext = path.Ext(filename)
		}
	}
	mtype := ""
	if n.MimeSize > 0 {
		mt := string(n.Mime)
		if !strings.HasPrefix(mt, "application/octet-stream") {
			mtype = mt
		}
	}

	if ext != ".gz" {
		if n.IsGzipped() {
			if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
				w.Header().Set("Content-Encoding", "gzip")
			} else {
				if n.Data, err = operation.UnGzipData(n.Data); err != nil {
					glog.V(0).Infoln("ungzip error:", err, r.URL.Path)
				}
			}
		}
	}

	rs := conditionallyResizeImages(bytes.NewReader(n.Data), ext, r)

	if e := writeResponseContent(filename, mtype, rs, w, r); e != nil {
		glog.V(2).Infoln("response write error:", e)
	}
}

func (vs *VolumeServer) tryHandleChunkedFile(n *storage.Needle, fileName string, w http.ResponseWriter, r *http.Request) (processed bool) {
	if !n.IsChunkedManifest() || r.URL.Query().Get("cm") == "false" {
		return false
	}

	chunkManifest, e := operation.LoadChunkManifest(n.Data, n.IsGzipped())
	if e != nil {
		glog.V(0).Infof("load chunked manifest (%s) error: %v", r.URL.Path, e)
		return false
	}
	if fileName == "" && chunkManifest.Name != "" {
		fileName = chunkManifest.Name
	}

	ext := path.Ext(fileName)

	mType := ""
	if chunkManifest.Mime != "" {
		mt := chunkManifest.Mime
		if !strings.HasPrefix(mt, "application/octet-stream") {
			mType = mt
		}
	}

	w.Header().Set("X-File-Store", "chunked")

	chunkedFileReader := &operation.ChunkedFileReader{
		Manifest: chunkManifest,
		Master:   vs.GetMaster(),
	}
	defer chunkedFileReader.Close()

	rs := conditionallyResizeImages(chunkedFileReader, ext, r)

	if e := writeResponseContent(fileName, mType, rs, w, r); e != nil {
		glog.V(2).Infoln("response write error:", e)
	}
	return true
}

func conditionallyResizeImages(originalDataReaderSeeker io.ReadSeeker, ext string, r *http.Request) io.ReadSeeker {
	rs := originalDataReaderSeeker
	if len(ext) > 0 {
		ext = strings.ToLower(ext)
	}
	if ext == ".png" || ext == ".jpg" || ext == ".jpeg" || ext == ".gif" {
		width, height := 0, 0
		if r.FormValue("width") != "" {
			width, _ = strconv.Atoi(r.FormValue("width"))
		}
		if r.FormValue("height") != "" {
			height, _ = strconv.Atoi(r.FormValue("height"))
		}
		rs, _, _ = images.Resized(ext, originalDataReaderSeeker, width, height, r.FormValue("mode"))
	}
	return rs
}

func writeResponseContent(filename, mimeType string, rs io.ReadSeeker, w http.ResponseWriter, r *http.Request) error {
	totalSize, e := rs.Seek(0, 2)
	if mimeType == "" {
		if ext := path.Ext(filename); ext != "" {
			mimeType = mime.TypeByExtension(ext)
		}
	}
	if mimeType != "" {
		w.Header().Set("Content-Type", mimeType)
	}
	if filename != "" {
		contentDisposition := "inline"
		if r.FormValue("dl") != "" {
			if dl, _ := strconv.ParseBool(r.FormValue("dl")); dl {
				contentDisposition = "attachment"
			}
		}
		w.Header().Set("Content-Disposition", contentDisposition+`; filename="`+fileNameEscaper.Replace(filename)+`"`)
	}
	w.Header().Set("Accept-Ranges", "bytes")
	if r.Method == "HEAD" {
		w.Header().Set("Content-Length", strconv.FormatInt(totalSize, 10))
		return nil
	}
	rangeReq := r.Header.Get("Range")
	if rangeReq == "" {
		w.Header().Set("Content-Length", strconv.FormatInt(totalSize, 10))
		if _, e = rs.Seek(0, 0); e != nil {
			return e
		}
		_, e = io.Copy(w, rs)
		return e
	}

	//the rest is dealing with partial content request
	//mostly copy from src/pkg/net/http/fs.go
	ranges, err := parseRange(rangeReq, totalSize)
	if err != nil {
		http.Error(w, err.Error(), http.StatusRequestedRangeNotSatisfiable)
		return nil
	}
	if sumRangesSize(ranges) > totalSize {
		// The total number of bytes in all the ranges
		// is larger than the size of the file by
		// itself, so this is probably an attack, or a
		// dumb client.  Ignore the range request.
		return nil
	}
	if len(ranges) == 0 {
		return nil
	}
	if len(ranges) == 1 {
		// RFC 2616, Section 14.16:
		// "When an HTTP message includes the content of a single
		// range (for example, a response to a request for a
		// single range, or to a request for a set of ranges
		// that overlap without any holes), this content is
		// transmitted with a Content-Range header, and a
		// Content-Length header showing the number of bytes
		// actually transferred.
		// ...
		// A response to a request for a single range MUST NOT
		// be sent using the multipart/byteranges media type."
		ra := ranges[0]
		w.Header().Set("Content-Length", strconv.FormatInt(ra.length, 10))
		w.Header().Set("Content-Range", ra.contentRange(totalSize))
		w.WriteHeader(http.StatusPartialContent)
		if _, e = rs.Seek(ra.start, 0); e != nil {
			return e
		}

		_, e = io.CopyN(w, rs, ra.length)
		return e
	}
	// process multiple ranges
	for _, ra := range ranges {
		if ra.start > totalSize {
			http.Error(w, "Out of Range", http.StatusRequestedRangeNotSatisfiable)
			return nil
		}
	}
	sendSize := rangesMIMESize(ranges, mimeType, totalSize)
	pr, pw := io.Pipe()
	mw := multipart.NewWriter(pw)
	w.Header().Set("Content-Type", "multipart/byteranges; boundary="+mw.Boundary())
	sendContent := pr
	defer pr.Close() // cause writing goroutine to fail and exit if CopyN doesn't finish.
	go func() {
		for _, ra := range ranges {
			part, e := mw.CreatePart(ra.mimeHeader(mimeType, totalSize))
			if e != nil {
				pw.CloseWithError(e)
				return
			}
			if _, e = rs.Seek(ra.start, 0); e != nil {
				pw.CloseWithError(e)
				return
			}
			if _, e = io.CopyN(part, rs, ra.length); e != nil {
				pw.CloseWithError(e)
				return
			}
		}
		mw.Close()
		pw.Close()
	}()
	if w.Header().Get("Content-Encoding") == "" {
		w.Header().Set("Content-Length", strconv.FormatInt(sendSize, 10))
	}
	w.WriteHeader(http.StatusPartialContent)
	_, e = io.CopyN(w, sendContent, sendSize)
	return e
}
<|endoftext|>


<commit_before>package storage

import (
	"errors"
	"fmt"
	"io"
	"path"
)

const TAG_PREFIX = "tag_"

type Storage interface {
	init() error

	Get(string) ([]byte, error)
	Put(string, []byte) error
	GetReader(string) (io.ReadCloser, error)
	PutReader(string, io.Reader, func(io.Reader)) error
	List(string) ([]string, error)
	Exists(string) (bool, error)
	Size(string) (int64, error)
	Remove(string) error
	RemoveAll(string) error
}

type Config struct {
	Type  string
	Local *Local
	S3    *S3
}

func New(cfg *Config) (Storage, error) {
	switch cfg.Type {
	case "local":
		if cfg.Local != nil {
			return cfg.Local, cfg.Local.init()
		}
		return nil, errors.New("No config for storage type 'local' found")
	case "s3":
		if cfg.S3 != nil {
			return cfg.S3, cfg.S3.init()
		}
		return nil, errors.New("No config for storage type 's3' found")
	default:
		return nil, errors.New("Invalid storage type: " + cfg.Type)
	}
}

func ImageJsonPath(id string) string {
	return fmt.Sprintf("images/%s/json", id)
}

func ImageMarkPath(id string) string {
	return fmt.Sprintf("images/%s/_inprogress", id)
}

func ImageChecksumPath(id string) string {
	return fmt.Sprintf("images/%s/_checksum", id)
}

func ImageLayerPath(id string) string {
	return fmt.Sprintf("images/%s/layer", id)
}

func ImageAncestryPath(id string) string {
	return fmt.Sprintf("images/%s/ancestry", id)
}

func ImageFilesPath(id string) string {
	return fmt.Sprintf("images/%s/_files", id)
}

func ImageDiffPath(id string) string {
	return fmt.Sprintf("images/%s/_diff", id)
}

func RepoImagesListPath(namespace, repo string) string {
	return fmt.Sprintf("repositories/%s/_images_list", path.Join(namespace, repo))
}

func RepoTagPath(namespace, repo, tag string) string {
	if tag == "" {
		return fmt.Sprintf("repositories/%s", path.Join(namespace, repo))
	}
	return fmt.Sprintf("repositories/%s/%s", path.Join(namespace, repo), TAG_PREFIX+tag)
}

func RepoJsonPath(namespace, repo string) string {
	return fmt.Sprintf("repositories/%s/json", path.Join(namespace, repo))
}

func RepoIndexImagesPath(namespace, repo string) string {
	return fmt.Sprintf("repositories/%s/_index_images", path.Join(namespace, repo))
}

func RepoPrivatePath(namespace, repo string) string {
	return fmt.Sprintf("repositories/%s/_private", path.Join(namespace, repo))
}
<commit_msg>lowercase storage config json keys<commit_after>package storage

import (
	"errors"
	"fmt"
	"io"
	"path"
)

const TAG_PREFIX = "tag_"

type Storage interface {
	init() error

	Get(string) ([]byte, error)
	Put(string, []byte) error
	GetReader(string) (io.ReadCloser, error)
	PutReader(string, io.Reader, func(io.Reader)) error
	List(string) ([]string, error)
	Exists(string) (bool, error)
	Size(string) (int64, error)
	Remove(string) error
	RemoveAll(string) error
}

type Config struct {
	Type  string `json:"type"`
	Local *Local `json:"local"`
	S3    *S3    `json:"s3"`
}

func New(cfg *Config) (Storage, error) {
	switch cfg.Type {
	case "local":
		if cfg.Local != nil {
			return cfg.Local, cfg.Local.init()
		}
		return nil, errors.New("No config for storage type 'local' found")
	case "s3":
		if cfg.S3 != nil {
			return cfg.S3, cfg.S3.init()
		}
		return nil, errors.New("No config for storage type 's3' found")
	default:
		return nil, errors.New("Invalid storage type: " + cfg.Type)
	}
}

func ImageJsonPath(id string) string {
	return fmt.Sprintf("images/%s/json", id)
}

func ImageMarkPath(id string) string {
	return fmt.Sprintf("images/%s/_inprogress", id)
}

func ImageChecksumPath(id string) string {
	return fmt.Sprintf("images/%s/_checksum", id)
}

func ImageLayerPath(id string) string {
	return fmt.Sprintf("images/%s/layer", id)
}

func ImageAncestryPath(id string) string {
	return fmt.Sprintf("images/%s/ancestry", id)
}

func ImageFilesPath(id string) string {
	return fmt.Sprintf("images/%s/_files", id)
}

func ImageDiffPath(id string) string {
	return fmt.Sprintf("images/%s/_diff", id)
}

func RepoImagesListPath(namespace, repo string) string {
	return fmt.Sprintf("repositories/%s/_images_list", path.Join(namespace, repo))
}

func RepoTagPath(namespace, repo, tag string) string {
	if tag == "" {
		return fmt.Sprintf("repositories/%s", path.Join(namespace, repo))
	}
	return fmt.Sprintf("repositories/%s/%s", path.Join(namespace, repo), TAG_PREFIX+tag)
}

func RepoJsonPath(namespace, repo string) string {
	return fmt.Sprintf("repositories/%s/json", path.Join(namespace, repo))
}

func RepoIndexImagesPath(namespace, repo string) string {
	return fmt.Sprintf("repositories/%s/_index_images", path.Join(namespace, repo))
}

func RepoPrivatePath(namespace, repo string) string {
	return fmt.Sprintf("repositories/%s/_private", path.Join(namespace, repo))
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"os"
	"os/signal"

	"github.com/Sirupsen/logrus"
	_ "github.com/eliothedeman/bangarang/alarm/console"
	_ "github.com/eliothedeman/bangarang/alarm/email"
	_ "github.com/eliothedeman/bangarang/alarm/influxdb"
	_ "github.com/eliothedeman/bangarang/alarm/pd"
	"github.com/eliothedeman/bangarang/api"
	"github.com/eliothedeman/bangarang/config"
	"github.com/eliothedeman/bangarang/pipeline"
	_ "github.com/eliothedeman/bangarang/provider/http"
	_ "github.com/eliothedeman/bangarang/provider/tcp"
)

var (
	confFile = flag.String("conf", "/etc/bangarang/conf.json", "path main config file")
)

func init() {
	logrus.SetLevel(logrus.WarnLevel)
	tf := &logrus.TextFormatter{}
	tf.FullTimestamp = true
	logrus.SetFormatter(tf)
}

func handleSigs() {
	stop := make(chan os.Signal)
	signal.Notify(stop, os.Kill, os.Interrupt)

	done := <-stop
	logrus.Fatal(done.String())
}

func main() {
	flag.Parse()
	logrus.Infof("Loading config file %s", *confFile)
	ac, err := config.LoadConfigFile(*confFile)
	if err != nil {
		logrus.Fatal(err)
	}

	if ac.LogLevel == "" {
		ac.LogLevel = config.DEFAULT_LOG_LEVEL
	}

	ll, err := logrus.ParseLevel(ac.LogLevel)
	if err != nil {
		logrus.Error(err)
	} else {
		logrus.SetLevel(ll)
	}

	logrus.Infof("Starting processing pipeline with %d policie(s)", len(ac.Policies))
	// create and start up a new pipeline
	p := pipeline.NewPipeline(ac)
	p.Start()

	logrus.Infof("Serving the http api on port %d", 8081)
	// create and start a new api server
	apiServer := api.NewServer(ac.ApiPort, p, ac.Auths)
	apiServer.Serve()
	handleSigs()
}
<commit_msg>remove support for influxdb for the time being<commit_after>package main

import (
	"flag"
	"os"
	"os/signal"

	"github.com/Sirupsen/logrus"
	_ "github.com/eliothedeman/bangarang/alarm/console"
	_ "github.com/eliothedeman/bangarang/alarm/email"
	// _ "github.com/eliothedeman/bangarang/alarm/influxdb"
	_ "github.com/eliothedeman/bangarang/alarm/pd"
	"github.com/eliothedeman/bangarang/api"
	"github.com/eliothedeman/bangarang/config"
	"github.com/eliothedeman/bangarang/pipeline"
	_ "github.com/eliothedeman/bangarang/provider/http"
	_ "github.com/eliothedeman/bangarang/provider/tcp"
)

var (
	confFile = flag.String("conf", "/etc/bangarang/conf.json", "path main config file")
)

func init() {
	logrus.SetLevel(logrus.WarnLevel)
	tf := &logrus.TextFormatter{}
	tf.FullTimestamp = true
	logrus.SetFormatter(tf)
}

func handleSigs() {
	stop := make(chan os.Signal)
	signal.Notify(stop, os.Kill, os.Interrupt)

	done := <-stop
	logrus.Fatal(done.String())
}

func main() {
	flag.Parse()
	logrus.Infof("Loading config file %s", *confFile)
	ac, err := config.LoadConfigFile(*confFile)
	if err != nil {
		logrus.Fatal(err)
	}

	if ac.LogLevel == "" {
		ac.LogLevel = config.DEFAULT_LOG_LEVEL
	}

	ll, err := logrus.ParseLevel(ac.LogLevel)
	if err != nil {
		logrus.Error(err)
	} else {
		logrus.SetLevel(ll)
	}

	logrus.Infof("Starting processing pipeline with %d policie(s)", len(ac.Policies))
	// create and start up a new pipeline
	p := pipeline.NewPipeline(ac)
	p.Start()

	logrus.Infof("Serving the http api on port %d", 8081)
	// create and start a new api server
	apiServer := api.NewServer(ac.ApiPort, p, ac.Auths)
	apiServer.Serve()
	handleSigs()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"strings"
	"text/template"
	"time"

	"encoding/json"

	is "github.com/containers/image/storage"
	"github.com/containers/storage"
	"github.com/pkg/errors"
	"github.com/urfave/cli"
)

type jsonImage struct {
	ID    string   `json:"id"`
	Names []string `json:"names"`
}

type imageOutputParams struct {
	ID        string
	Name      string
	Digest    string
	CreatedAt string
	Size      string
}

type filterParams struct {
	dangling         string
	label            string
	beforeImage      string // Images are sorted by date, so we can just output until we see the image
	sinceImage       string // Images are sorted by date, so we can just output until we don't see the image
	beforeDate       time.Time
	sinceDate        time.Time
	referencePattern string
}

var (
	imagesFlags = []cli.Flag{
		cli.BoolFlag{
			Name:  "quiet, q",
			Usage: "display only image IDs",
		},
		cli.BoolFlag{
			Name:  "noheading, n",
			Usage: "do not print column headings",
		},
		cli.BoolFlag{
			Name:  "no-trunc, notruncate",
			Usage: "do not truncate output",
		},
		cli.BoolFlag{
			Name:  "json",
			Usage: "output in JSON format",
		},
		cli.BoolFlag{
			Name:  "digests",
			Usage: "show digests",
		},
		cli.StringFlag{
			Name:  "format",
			Usage: "pretty-print images using a Go template. will override --quiet",
		},
		cli.StringFlag{
			Name:  "filter, f",
			Usage: "filter output based on conditions provided (default [])",
		},
	}

	imagesDescription = "Lists locally stored images."
	imagesCommand     = cli.Command{
		Name:        "images",
		Usage:       "List images in local storage",
		Description: imagesDescription,
		Flags:       imagesFlags,
		Action:      imagesCmd,
		ArgsUsage:   " ",
	}
)

func imagesCmd(c *cli.Context) error {
	store, err := getStore(c)
	if err != nil {
		return err
	}

	images, err := store.Images()
	if err != nil {
		return errors.Wrapf(err, "error reading images")
	}

	quiet := false
	if c.IsSet("quiet") {
		quiet = c.Bool("quiet")
	}
	noheading := false
	if c.IsSet("noheading") {
		noheading = c.Bool("noheading")
	}
	truncate := true
	if c.IsSet("no-trunc") {
		truncate = !c.Bool("no-trunc")
	}
	digests := false
	if c.IsSet("digests") {
		digests = c.Bool("digests")
	}
	formatString := ""
	hasTemplate := false
	if c.IsSet("format") {
		formatString = c.String("format")
		hasTemplate = true
	}

	name := ""
	if len(c.Args()) == 1 {
		name = c.Args().Get(0)
	} else if len(c.Args()) > 1 {
		return errors.New("'buildah images' requires at most 1 argument")
	}
	if c.IsSet("json") {
		JSONImages := []jsonImage{}
		for _, image := range images {
			JSONImages = append(JSONImages, jsonImage{ID: image.ID, Names: image.Names})
		}
		data, err2 := json.MarshalIndent(JSONImages, "", "    ")
		if err2 != nil {
			return err2
		}
		fmt.Printf("%s\n", data)
		return nil
	}
	if len(images) > 0 && !noheading && !quiet {
		if truncate {
			fmt.Printf("%-12s %s\n", "IMAGE ID", "IMAGE NAME")
		} else {
			fmt.Printf("%-64s %s\n", "IMAGE ID", "IMAGE NAME")
		}
	}

	var params *filterParams
	if c.IsSet("filter") {
		params, err = parseFilter(images, c.String("filter"))
		if err != nil {
			return errors.Wrapf(err, "error parsing filter")
		}
	} else {
		params = nil
	}

	if len(images) > 0 && !noheading && !quiet && !hasTemplate {
		outputHeader(truncate, digests)
	}

	return outputImages(images, formatString, store, params, name, hasTemplate, truncate, digests, quiet)
}

func parseFilter(images []storage.Image, filter string) (*filterParams, error) {
	params := new(filterParams)
	filterStrings := strings.Split(filter, ",")
	for _, param := range filterStrings {
		pair := strings.SplitN(param, "=", 2)
		switch strings.TrimSpace(pair[0]) {
		case "dangling":
			if pair[1] == "true" || pair[1] == "false" {
				params.dangling = pair[1]
			} else {
				return nil, fmt.Errorf("invalid filter: '%s=[%s]'", pair[0], pair[1])
			}
		case "label":
			params.label = pair[1]
		case "before":
			beforeDate, err := setFilterDate(images, pair[1])
			if err != nil {
				return nil, fmt.Errorf("no such id: %s", pair[0])
			}
			params.beforeDate = beforeDate
		case "since":
			sinceDate, err := setFilterDate(images, pair[1])
			if err != nil {
				return nil, fmt.Errorf("no such id: %s", pair[0])
			}
			params.sinceDate = sinceDate
		case "reference":
			params.referencePattern = pair[1]
		default:
			return nil, fmt.Errorf("invalid filter: '%s'", pair[0])
		}
	}
	return params, nil
}

func setFilterDate(images []storage.Image, imgName string) (time.Time, error) {
	for _, image := range images {
		for _, name := range image.Names {
			if matchesReference(name, imgName) {
				// Set the date to this image
				im, err := parseMetadata(image)
				if err != nil {
					return time.Time{}, errors.Wrapf(err, "could not get creation date for image %q", imgName)
				}
				date := im.CreatedTime
				return date, nil
			}
		}
	}
	return time.Time{}, fmt.Errorf("Could not locate image %q", imgName)
}

func outputHeader(truncate, digests bool) {
	if truncate {
		fmt.Printf("%-20s %-56s ", "IMAGE ID", "IMAGE NAME")
	} else {
		fmt.Printf("%-64s %-56s ", "IMAGE ID", "IMAGE NAME")
	}

	if digests {
		fmt.Printf("%-64s ", "DIGEST")
	}

	fmt.Printf("%-22s %s\n", "CREATED AT", "SIZE")
}

func outputImages(images []storage.Image, format string, store storage.Store, filters *filterParams, argName string, hasTemplate, truncate, digests, quiet bool) error {
	for _, image := range images {
		imageMetadata, err := parseMetadata(image)
		if err != nil {
			fmt.Println(err)
		}
		createdTime := imageMetadata.CreatedTime.Format("Jan 2, 2006 15:04")
		digest := ""
		if len(imageMetadata.Blobs) > 0 {
			digest = string(imageMetadata.Blobs[0].Digest)
		}
		size, _ := getSize(image, store)

		names := []string{""}
		if len(image.Names) > 0 {
			names = image.Names
		} else {
			// images without names should be printed with "<none>" as the image name
			names = append(names, "<none>")
		}
		for _, name := range names {
			if !matchesFilter(image, store, name, filters) || !matchesReference(name, argName) {
				continue
			}
			if quiet {
				fmt.Printf("%-64s\n", image.ID)
				// We only want to print each id once
				break
			}

			params := imageOutputParams{
				ID:        image.ID,
				Name:      name,
				Digest:    digest,
				CreatedAt: createdTime,
				Size:      formattedSize(size),
			}
			if hasTemplate {
				err = outputUsingTemplate(format, params)
				if err != nil {
					return err
				}
				continue
			}

			outputUsingFormatString(truncate, digests, params)
		}
	}
	return nil
}

func matchesFilter(image storage.Image, store storage.Store, name string, params *filterParams) bool {
	if params == nil {
		return true
	}
	if params.dangling != "" && !matchesDangling(name, params.dangling) {
		return false
	} else if params.label != "" && !matchesLabel(image, store, params.label) {
		return false
	} else if params.beforeImage != "" && !matchesBeforeImage(image, name, params) {
		return false
	} else if params.sinceImage != "" && !matchesSinceImage(image, name, params) {
		return false
	} else if params.referencePattern != "" && !matchesReference(name, params.referencePattern) {
		return false
	}
	return true
}

func matchesDangling(name string, dangling string) bool {
	if dangling == "false" && name != "<none>" {
		return true
	} else if dangling == "true" && name == "<none>" {
		return true
	}
	return false
}

func matchesLabel(image storage.Image, store storage.Store, label string) bool {
	storeRef, err := is.Transport.ParseStoreReference(store, "@"+image.ID)
	if err != nil {

	}
	img, err := storeRef.NewImage(nil)
	if err != nil {
		return false
	}
	info, err := img.Inspect()
	if err != nil {
		return false
	}

	pair := strings.SplitN(label, "=", 2)
	for key, value := range info.Labels {
		if key == pair[0] {
			if len(pair) == 2 {
				if value == pair[1] {
					return true
				}
			} else {
				return false
			}
		}
	}
	return false
}

// Returns true if the image was created since the filter image.  Returns
// false otherwise
func matchesBeforeImage(image storage.Image, name string, params *filterParams) bool {
	im, err := parseMetadata(image)
	if err != nil {
		return false
	}
	if im.CreatedTime.Before(params.beforeDate) {
		return true
	}
	return false
}

// Returns true if the image was created since the filter image.  Returns
// false otherwise
func matchesSinceImage(image storage.Image, name string, params *filterParams) bool {
	im, err := parseMetadata(image)
	if err != nil {
		return false
	}
	if im.CreatedTime.After(params.sinceDate) {
		return true
	}
	return false
}

func matchesID(id, argID string) bool {
	return strings.HasPrefix(argID, id)
}

func matchesReference(name, argName string) bool {
	if argName == "" {
		return true
	}
	splitName := strings.Split(name, ":")
	// If the arg contains a tag, we handle it differently than if it does not
	if strings.Contains(argName, ":") {
		splitArg := strings.Split(argName, ":")
		return strings.HasSuffix(splitName[0], splitArg[0]) && (splitName[1] == splitArg[1])
	}
	return strings.HasSuffix(splitName[0], argName)
}

func formattedSize(size int64) string {
	suffixes := [5]string{"B", "KB", "MB", "GB", "TB"}

	count := 0
	formattedSize := float64(size)
	for formattedSize >= 1024 && count < 4 {
		formattedSize /= 1024
		count++
	}
	return fmt.Sprintf("%.4g %s", formattedSize, suffixes[count])
}

func outputUsingTemplate(format string, params imageOutputParams) error {
	tmpl, err := template.New("image").Parse(format)
	if err != nil {
		return errors.Wrapf(err, "Template parsing error")
	}

	err = tmpl.Execute(os.Stdout, params)
	if err != nil {
		return err
	}
	fmt.Println()
	return nil
}

func outputUsingFormatString(truncate, digests bool, params imageOutputParams) {
	if truncate {
		fmt.Printf("%-20.12s %-56s", params.ID, params.Name)
	} else {
		fmt.Printf("%-64s %-56s", params.ID, params.Name)
	}

	if digests {
		fmt.Printf(" %-64s", params.Digest)
	}
	fmt.Printf(" %-22s %s\n", params.CreatedAt, params.Size)
}
<commit_msg>Only print heading once when executing buildah images<commit_after>package main

import (
	"fmt"
	"os"
	"strings"
	"text/template"
	"time"

	"encoding/json"

	is "github.com/containers/image/storage"
	"github.com/containers/storage"
	"github.com/pkg/errors"
	"github.com/urfave/cli"
)

type jsonImage struct {
	ID    string   `json:"id"`
	Names []string `json:"names"`
}

type imageOutputParams struct {
	ID        string
	Name      string
	Digest    string
	CreatedAt string
	Size      string
}

type filterParams struct {
	dangling         string
	label            string
	beforeImage      string // Images are sorted by date, so we can just output until we see the image
	sinceImage       string // Images are sorted by date, so we can just output until we don't see the image
	beforeDate       time.Time
	sinceDate        time.Time
	referencePattern string
}

var (
	imagesFlags = []cli.Flag{
		cli.BoolFlag{
			Name:  "quiet, q",
			Usage: "display only image IDs",
		},
		cli.BoolFlag{
			Name:  "noheading, n",
			Usage: "do not print column headings",
		},
		cli.BoolFlag{
			Name:  "no-trunc, notruncate",
			Usage: "do not truncate output",
		},
		cli.BoolFlag{
			Name:  "json",
			Usage: "output in JSON format",
		},
		cli.BoolFlag{
			Name:  "digests",
			Usage: "show digests",
		},
		cli.StringFlag{
			Name:  "format",
			Usage: "pretty-print images using a Go template. will override --quiet",
		},
		cli.StringFlag{
			Name:  "filter, f",
			Usage: "filter output based on conditions provided (default [])",
		},
	}

	imagesDescription = "Lists locally stored images."
	imagesCommand     = cli.Command{
		Name:        "images",
		Usage:       "List images in local storage",
		Description: imagesDescription,
		Flags:       imagesFlags,
		Action:      imagesCmd,
		ArgsUsage:   " ",
	}
)

func imagesCmd(c *cli.Context) error {
	store, err := getStore(c)
	if err != nil {
		return err
	}

	images, err := store.Images()
	if err != nil {
		return errors.Wrapf(err, "error reading images")
	}

	quiet := false
	if c.IsSet("quiet") {
		quiet = c.Bool("quiet")
	}
	noheading := false
	if c.IsSet("noheading") {
		noheading = c.Bool("noheading")
	}
	truncate := true
	if c.IsSet("no-trunc") {
		truncate = !c.Bool("no-trunc")
	}
	digests := false
	if c.IsSet("digests") {
		digests = c.Bool("digests")
	}
	formatString := ""
	hasTemplate := false
	if c.IsSet("format") {
		formatString = c.String("format")
		hasTemplate = true
	}

	name := ""
	if len(c.Args()) == 1 {
		name = c.Args().Get(0)
	} else if len(c.Args()) > 1 {
		return errors.New("'buildah images' requires at most 1 argument")
	}
	if c.IsSet("json") {
		JSONImages := []jsonImage{}
		for _, image := range images {
			JSONImages = append(JSONImages, jsonImage{ID: image.ID, Names: image.Names})
		}
		data, err2 := json.MarshalIndent(JSONImages, "", "    ")
		if err2 != nil {
			return err2
		}
		fmt.Printf("%s\n", data)
		return nil
	}
	var params *filterParams
	if c.IsSet("filter") {
		params, err = parseFilter(images, c.String("filter"))
		if err != nil {
			return errors.Wrapf(err, "error parsing filter")
		}
	} else {
		params = nil
	}

	if len(images) > 0 && !noheading && !quiet && !hasTemplate {
		outputHeader(truncate, digests)
	}

	return outputImages(images, formatString, store, params, name, hasTemplate, truncate, digests, quiet)
}

func parseFilter(images []storage.Image, filter string) (*filterParams, error) {
	params := new(filterParams)
	filterStrings := strings.Split(filter, ",")
	for _, param := range filterStrings {
		pair := strings.SplitN(param, "=", 2)
		switch strings.TrimSpace(pair[0]) {
		case "dangling":
			if pair[1] == "true" || pair[1] == "false" {
				params.dangling = pair[1]
			} else {
				return nil, fmt.Errorf("invalid filter: '%s=[%s]'", pair[0], pair[1])
			}
		case "label":
			params.label = pair[1]
		case "before":
			beforeDate, err := setFilterDate(images, pair[1])
			if err != nil {
				return nil, fmt.Errorf("no such id: %s", pair[0])
			}
			params.beforeDate = beforeDate
		case "since":
			sinceDate, err := setFilterDate(images, pair[1])
			if err != nil {
				return nil, fmt.Errorf("no such id: %s", pair[0])
			}
			params.sinceDate = sinceDate
		case "reference":
			params.referencePattern = pair[1]
		default:
			return nil, fmt.Errorf("invalid filter: '%s'", pair[0])
		}
	}
	return params, nil
}

func setFilterDate(images []storage.Image, imgName string) (time.Time, error) {
	for _, image := range images {
		for _, name := range image.Names {
			if matchesReference(name, imgName) {
				// Set the date to this image
				im, err := parseMetadata(image)
				if err != nil {
					return time.Time{}, errors.Wrapf(err, "could not get creation date for image %q", imgName)
				}
				date := im.CreatedTime
				return date, nil
			}
		}
	}
	return time.Time{}, fmt.Errorf("Could not locate image %q", imgName)
}

func outputHeader(truncate, digests bool) {
	if truncate {
		fmt.Printf("%-20s %-56s ", "IMAGE ID", "IMAGE NAME")
	} else {
		fmt.Printf("%-64s %-56s ", "IMAGE ID", "IMAGE NAME")
	}

	if digests {
		fmt.Printf("%-64s ", "DIGEST")
	}

	fmt.Printf("%-22s %s\n", "CREATED AT", "SIZE")
}

func outputImages(images []storage.Image, format string, store storage.Store, filters *filterParams, argName string, hasTemplate, truncate, digests, quiet bool) error {
	for _, image := range images {
		imageMetadata, err := parseMetadata(image)
		if err != nil {
			fmt.Println(err)
		}
		createdTime := imageMetadata.CreatedTime.Format("Jan 2, 2006 15:04")
		digest := ""
		if len(imageMetadata.Blobs) > 0 {
			digest = string(imageMetadata.Blobs[0].Digest)
		}
		size, _ := getSize(image, store)

		names := []string{""}
		if len(image.Names) > 0 {
			names = image.Names
		} else {
			// images without names should be printed with "<none>" as the image name
			names = append(names, "<none>")
		}
		for _, name := range names {
			if !matchesFilter(image, store, name, filters) || !matchesReference(name, argName) {
				continue
			}
			if quiet {
				fmt.Printf("%-64s\n", image.ID)
				// We only want to print each id once
				break
			}

			params := imageOutputParams{
				ID:        image.ID,
				Name:      name,
				Digest:    digest,
				CreatedAt: createdTime,
				Size:      formattedSize(size),
			}
			if hasTemplate {
				err = outputUsingTemplate(format, params)
				if err != nil {
					return err
				}
				continue
			}

			outputUsingFormatString(truncate, digests, params)
		}
	}
	return nil
}

func matchesFilter(image storage.Image, store storage.Store, name string, params *filterParams) bool {
	if params == nil {
		return true
	}
	if params.dangling != "" && !matchesDangling(name, params.dangling) {
		return false
	} else if params.label != "" && !matchesLabel(image, store, params.label) {
		return false
	} else if params.beforeImage != "" && !matchesBeforeImage(image, name, params) {
		return false
	} else if params.sinceImage != "" && !matchesSinceImage(image, name, params) {
		return false
	} else if params.referencePattern != "" && !matchesReference(name, params.referencePattern) {
		return false
	}
	return true
}

func matchesDangling(name string, dangling string) bool {
	if dangling == "false" && name != "<none>" {
		return true
	} else if dangling == "true" && name == "<none>" {
		return true
	}
	return false
}

func matchesLabel(image storage.Image, store storage.Store, label string) bool {
	storeRef, err := is.Transport.ParseStoreReference(store, "@"+image.ID)
	if err != nil {

	}
	img, err := storeRef.NewImage(nil)
	if err != nil {
		return false
	}
	info, err := img.Inspect()
	if err != nil {
		return false
	}

	pair := strings.SplitN(label, "=", 2)
	for key, value := range info.Labels {
		if key == pair[0] {
			if len(pair) == 2 {
				if value == pair[1] {
					return true
				}
			} else {
				return false
			}
		}
	}
	return false
}

// Returns true if the image was created since the filter image.  Returns
// false otherwise
func matchesBeforeImage(image storage.Image, name string, params *filterParams) bool {
	im, err := parseMetadata(image)
	if err != nil {
		return false
	}
	if im.CreatedTime.Before(params.beforeDate) {
		return true
	}
	return false
}

// Returns true if the image was created since the filter image.  Returns
// false otherwise
func matchesSinceImage(image storage.Image, name string, params *filterParams) bool {
	im, err := parseMetadata(image)
	if err != nil {
		return false
	}
	if im.CreatedTime.After(params.sinceDate) {
		return true
	}
	return false
}

func matchesID(id, argID string) bool {
	return strings.HasPrefix(argID, id)
}

func matchesReference(name, argName string) bool {
	if argName == "" {
		return true
	}
	splitName := strings.Split(name, ":")
	// If the arg contains a tag, we handle it differently than if it does not
	if strings.Contains(argName, ":") {
		splitArg := strings.Split(argName, ":")
		return strings.HasSuffix(splitName[0], splitArg[0]) && (splitName[1] == splitArg[1])
	}
	return strings.HasSuffix(splitName[0], argName)
}

func formattedSize(size int64) string {
	suffixes := [5]string{"B", "KB", "MB", "GB", "TB"}

	count := 0
	formattedSize := float64(size)
	for formattedSize >= 1024 && count < 4 {
		formattedSize /= 1024
		count++
	}
	return fmt.Sprintf("%.4g %s", formattedSize, suffixes[count])
}

func outputUsingTemplate(format string, params imageOutputParams) error {
	tmpl, err := template.New("image").Parse(format)
	if err != nil {
		return errors.Wrapf(err, "Template parsing error")
	}

	err = tmpl.Execute(os.Stdout, params)
	if err != nil {
		return err
	}
	fmt.Println()
	return nil
}

func outputUsingFormatString(truncate, digests bool, params imageOutputParams) {
	if truncate {
		fmt.Printf("%-20.12s %-56s", params.ID, params.Name)
	} else {
		fmt.Printf("%-64s %-56s", params.ID, params.Name)
	}

	if digests {
		fmt.Printf(" %-64s", params.Digest)
	}
	fmt.Printf(" %-22s %s\n", params.CreatedAt, params.Size)
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/clawio/clawiod/root"
	"github.com/go-kit/kit/log/levels"
	"github.com/gorilla/handlers"
	"github.com/gorilla/mux"
	"github.com/prometheus/client_golang/prometheus"
	"io"
	"net/http"
)

type server struct {
	logger     levels.Levels
	router     http.Handler
	config     root.Configuration
	httpLogger io.Writer
}

func newServer(config root.Configuration) (*server, error) {
	logger, err := getLogger(config)
	if err != nil {
		return nil, err
	}
	s := &server{logger: logger, config: config}
	err = s.configureRouter()
	if err != nil {
		return nil, err
	}
	return s, nil
}

func (s *server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	handlers.CombinedLoggingHandler(s.httpLogger, s.router).ServeHTTP(w, r)
}

func (s *server) configureRouter() error {
	config := s.config

	httpLogger, err := getHTTPLogger(config)
	if err != nil {
		s.logger.Error().Log("error", err)
		return err
	}
	s.httpLogger = httpLogger

	loggerMiddleware, err := getLoggerMiddleware(config)
	if err != nil {
		s.logger.Error().Log("error", err)
		return err
	}

	corsMiddleware, err := getCORSMiddleware(config)
	if err != nil {
		s.logger.Error().Log("error", err)
		return err
	}

	webServices, err := getWebServices(config)
	if err != nil {
		s.logger.Error().Log("error", err)
		return err
	}
	s.logger.Info().Log("msg", "web services enabled", "webservices", config.GetEnabledWebServices())

	router := mux.NewRouter()
	for key, service := range webServices {
		s.logger.Info().Log("msg", key+" web service enabled")
		for path, methods := range service.Endpoints() {
			for method, handlerFunc := range methods {
				handlerFunc = loggerMiddleware.HandlerFunc(handlerFunc)
				handlerFunc := http.HandlerFunc(handlerFunc)
				var handler http.Handler
				if config.IsCORSMiddlewareEnabled() {
					handler = handlerFunc
					handler = corsMiddleware.Handler(handler)
					router.Handle(path, handler).Methods(method)
					prometheus.InstrumentHandler(path, handler)
					s.logger.Info().Log("method", method, "endpoint", path, "msg", "endpoint available")
					router.Handle(path, handler).Methods("OPTIONS")
					s.logger.Info().Log("method", "OPTIONS", "endpoint", path, "msg", "endpoint available - created by corsmiddleware")
				} else {
					handler = handlerFunc
					router.Handle(path, handler).Methods(method)
					prometheus.InstrumentHandler(path, handler)
					s.logger.Info().Log("method", method, "endpoint", path, "msg", "endpoint available")
				}
			}
		}
	}
	s.router = router
	return nil
}
<commit_msg>Add prometheus handler<commit_after>package main

import (
	"github.com/clawio/clawiod/root"
	"github.com/go-kit/kit/log/levels"
	"github.com/gorilla/handlers"
	"github.com/gorilla/mux"
	"github.com/prometheus/client_golang/prometheus"
	"io"
	"net/http"
)

type server struct {
	logger     levels.Levels
	router     http.Handler
	config     root.Configuration
	httpLogger io.Writer
}

func newServer(config root.Configuration) (*server, error) {
	logger, err := getLogger(config)
	if err != nil {
		return nil, err
	}
	s := &server{logger: logger, config: config}
	err = s.configureRouter()
	if err != nil {
		return nil, err
	}
	return s, nil
}

func (s *server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	handlers.CombinedLoggingHandler(s.httpLogger, s.router).ServeHTTP(w, r)
}

func (s *server) configureRouter() error {
	config := s.config

	httpLogger, err := getHTTPLogger(config)
	if err != nil {
		s.logger.Error().Log("error", err)
		return err
	}
	s.httpLogger = httpLogger

	loggerMiddleware, err := getLoggerMiddleware(config)
	if err != nil {
		s.logger.Error().Log("error", err)
		return err
	}

	corsMiddleware, err := getCORSMiddleware(config)
	if err != nil {
		s.logger.Error().Log("error", err)
		return err
	}

	webServices, err := getWebServices(config)
	if err != nil {
		s.logger.Error().Log("error", err)
		return err
	}
	s.logger.Info().Log("msg", "web services enabled", "webservices", config.GetEnabledWebServices())

	router := mux.NewRouter()
	router.Handle("/metrics", prometheus.Handler()).Methods("GET")
	s.logger.Info().Log("method", "GET", "endpoint", "/metrics", "msg", "endpoint available - created by prometheus")
	for key, service := range webServices {
		s.logger.Info().Log("msg", key+" web service enabled")
		for path, methods := range service.Endpoints() {
			for method, handlerFunc := range methods {
				handlerFunc = loggerMiddleware.HandlerFunc(handlerFunc)
				handlerFunc := http.HandlerFunc(handlerFunc)
				var handler http.Handler
				if config.IsCORSMiddlewareEnabled() {
					handler = handlerFunc
					handler = corsMiddleware.Handler(handler)
					router.Handle(path, handler).Methods(method)
					prometheus.InstrumentHandler(path, handler)
					s.logger.Info().Log("method", method, "endpoint", path, "msg", "endpoint available")
					router.Handle(path, handler).Methods("OPTIONS")
					s.logger.Info().Log("method", "OPTIONS", "endpoint", path, "msg", "endpoint available - created by corsmiddleware")
				} else {
					handler = handlerFunc
					router.Handle(path, handler).Methods(method)
					prometheus.InstrumentHandler(path, handler)
					s.logger.Info().Log("method", method, "endpoint", path, "msg", "endpoint available")
				}
			}
		}
	}
	s.router = router
	return nil
}
<|endoftext|>