<commit_before>// Copyright 2017 The go-interpreter 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 operators

import (
	"github.com/go-interpreter/wagon/wasm"
)

var (
	I32Load    = newOp(0x28, "i32.load", []wasm.ValueType{wasm.ValueTypeI32}, wasm.ValueTypeI32)
	I64Load    = newOp(0x29, "i64.load", []wasm.ValueType{wasm.ValueTypeI32}, wasm.ValueTypeI64)
	F32Load    = newOp(0x2a, "f32.load", []wasm.ValueType{wasm.ValueTypeI32}, wasm.ValueTypeF32)
	F64Load    = newOp(0x2b, "f64.load", []wasm.ValueType{wasm.ValueTypeI32}, wasm.ValueTypeF64)
	I32Load8s  = newOp(0x2c, "i32.load8_s", []wasm.ValueType{wasm.ValueTypeI32}, wasm.ValueTypeI32)
	I32Load8u  = newOp(0x2d, "i32.load8_u", []wasm.ValueType{wasm.ValueTypeI32}, wasm.ValueTypeI32)
	I32Load16s = newOp(0x2e, "i32.load16_s", []wasm.ValueType{wasm.ValueTypeI32}, wasm.ValueTypeI32)
	I32Load16u = newOp(0x2f, "i32.load16_u", []wasm.ValueType{wasm.ValueTypeI32}, wasm.ValueTypeI32)
	I64Load8s  = newOp(0x30, "i64.load8_s", []wasm.ValueType{wasm.ValueTypeI32}, wasm.ValueTypeI64)
	I64Load8u  = newOp(0x31, "i64.load8_u", []wasm.ValueType{wasm.ValueTypeI32}, wasm.ValueTypeI64)
	I64Load16s = newOp(0x32, "i64.load16_s", []wasm.ValueType{wasm.ValueTypeI32}, wasm.ValueTypeI64)
	I64Load16u = newOp(0x33, "i64.load16_u", []wasm.ValueType{wasm.ValueTypeI32}, wasm.ValueTypeI64)
	I64Load32s = newOp(0x34, "i64.load32_s", []wasm.ValueType{wasm.ValueTypeI32}, wasm.ValueTypeI64)
	I64Load32u = newOp(0x35, "i64.load32_u", []wasm.ValueType{wasm.ValueTypeI32}, wasm.ValueTypeI64)

	I32Store   = newOp(0x36, "i32.store", []wasm.ValueType{wasm.ValueTypeI32, wasm.ValueTypeI32}, noReturn)
	I64Store   = newOp(0x37, "i64.store", []wasm.ValueType{wasm.ValueTypeI64, wasm.ValueTypeI32}, noReturn)
	F32Store   = newOp(0x38, "f32.store", []wasm.ValueType{wasm.ValueTypeF32, wasm.ValueTypeI32}, noReturn)
	F64Store   = newOp(0x39, "f64.store", []wasm.ValueType{wasm.ValueTypeF64, wasm.ValueTypeI32}, noReturn)
	I32Store8  = newOp(0x3a, "i32.store8", []wasm.ValueType{wasm.ValueTypeI32, wasm.ValueTypeI32}, noReturn)
	I32Store16 = newOp(0x3b, "i32.store16", []wasm.ValueType{wasm.ValueTypeI32, wasm.ValueTypeI32}, noReturn)
	I64Store8  = newOp(0x3c, "i64.store8", []wasm.ValueType{wasm.ValueTypeI64, wasm.ValueTypeI32}, noReturn)
	I64Store16 = newOp(0x3d, "i64.store16", []wasm.ValueType{wasm.ValueTypeI64, wasm.ValueTypeI32}, noReturn)
	I64Store32 = newOp(0x3e, "i64.store32", []wasm.ValueType{wasm.ValueTypeI64, wasm.ValueTypeI32}, noReturn)

	CurrentMemory = newOp(0x3f, "current_memory", nil, wasm.ValueTypeI32)
	GrowMemory    = newOp(0x40, "grow_memory", []wasm.ValueType{wasm.ValueTypeI32}, wasm.ValueTypeI32)
)
<commit_msg>operators: update names of memory-related ops according to wasm2wat<commit_after>// Copyright 2017 The go-interpreter 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 operators

import (
	"github.com/go-interpreter/wagon/wasm"
)

var (
	I32Load    = newOp(0x28, "i32.load", []wasm.ValueType{wasm.ValueTypeI32}, wasm.ValueTypeI32)
	I64Load    = newOp(0x29, "i64.load", []wasm.ValueType{wasm.ValueTypeI32}, wasm.ValueTypeI64)
	F32Load    = newOp(0x2a, "f32.load", []wasm.ValueType{wasm.ValueTypeI32}, wasm.ValueTypeF32)
	F64Load    = newOp(0x2b, "f64.load", []wasm.ValueType{wasm.ValueTypeI32}, wasm.ValueTypeF64)
	I32Load8s  = newOp(0x2c, "i32.load8_s", []wasm.ValueType{wasm.ValueTypeI32}, wasm.ValueTypeI32)
	I32Load8u  = newOp(0x2d, "i32.load8_u", []wasm.ValueType{wasm.ValueTypeI32}, wasm.ValueTypeI32)
	I32Load16s = newOp(0x2e, "i32.load16_s", []wasm.ValueType{wasm.ValueTypeI32}, wasm.ValueTypeI32)
	I32Load16u = newOp(0x2f, "i32.load16_u", []wasm.ValueType{wasm.ValueTypeI32}, wasm.ValueTypeI32)
	I64Load8s  = newOp(0x30, "i64.load8_s", []wasm.ValueType{wasm.ValueTypeI32}, wasm.ValueTypeI64)
	I64Load8u  = newOp(0x31, "i64.load8_u", []wasm.ValueType{wasm.ValueTypeI32}, wasm.ValueTypeI64)
	I64Load16s = newOp(0x32, "i64.load16_s", []wasm.ValueType{wasm.ValueTypeI32}, wasm.ValueTypeI64)
	I64Load16u = newOp(0x33, "i64.load16_u", []wasm.ValueType{wasm.ValueTypeI32}, wasm.ValueTypeI64)
	I64Load32s = newOp(0x34, "i64.load32_s", []wasm.ValueType{wasm.ValueTypeI32}, wasm.ValueTypeI64)
	I64Load32u = newOp(0x35, "i64.load32_u", []wasm.ValueType{wasm.ValueTypeI32}, wasm.ValueTypeI64)

	I32Store   = newOp(0x36, "i32.store", []wasm.ValueType{wasm.ValueTypeI32, wasm.ValueTypeI32}, noReturn)
	I64Store   = newOp(0x37, "i64.store", []wasm.ValueType{wasm.ValueTypeI64, wasm.ValueTypeI32}, noReturn)
	F32Store   = newOp(0x38, "f32.store", []wasm.ValueType{wasm.ValueTypeF32, wasm.ValueTypeI32}, noReturn)
	F64Store   = newOp(0x39, "f64.store", []wasm.ValueType{wasm.ValueTypeF64, wasm.ValueTypeI32}, noReturn)
	I32Store8  = newOp(0x3a, "i32.store8", []wasm.ValueType{wasm.ValueTypeI32, wasm.ValueTypeI32}, noReturn)
	I32Store16 = newOp(0x3b, "i32.store16", []wasm.ValueType{wasm.ValueTypeI32, wasm.ValueTypeI32}, noReturn)
	I64Store8  = newOp(0x3c, "i64.store8", []wasm.ValueType{wasm.ValueTypeI64, wasm.ValueTypeI32}, noReturn)
	I64Store16 = newOp(0x3d, "i64.store16", []wasm.ValueType{wasm.ValueTypeI64, wasm.ValueTypeI32}, noReturn)
	I64Store32 = newOp(0x3e, "i64.store32", []wasm.ValueType{wasm.ValueTypeI64, wasm.ValueTypeI32}, noReturn)

	CurrentMemory = newOp(0x3f, "memory.size", nil, wasm.ValueTypeI32)
	GrowMemory    = newOp(0x40, "memory.grow", []wasm.ValueType{wasm.ValueTypeI32}, wasm.ValueTypeI32)
)
<|endoftext|>


<commit_before>package upkeep

import (
	d "github.com/jeffjen/docker-monitor/driver"
	disc "github.com/jeffjen/go-discovery"
	"github.com/jeffjen/go-libkv/libkv"
	timer "github.com/jeffjen/go-libkv/timer"

	log "github.com/Sirupsen/logrus"
	etcd "github.com/coreos/etcd/client"
	docker "github.com/fsouza/go-dockerclient"
	ctx "golang.org/x/net/context"

	"encoding/gob"
	"fmt"
	"path"
	"strings"
	"time"
)

const (
	DEFAULT_HEARTBEAT = 2 * time.Minute
	DEFAULT_TTL       = 2*time.Minute + 5*time.Second

	DEFAULT_SYNC_PATH  = "/tmp"
	DEFAULT_SYNC_CYCLE = 2 * time.Minute
)

var (
	Sched *timer.Timer

	rec *libkv.Store

	AllocDriver func(string) (d.Driver, error) = nil
)

func sync(jobId int64) {
	if err := rec.Save(DEFAULT_SYNC_PATH); err != nil {
		log.Warningf("unable to persist: %v", err)
	} else {
		log.Infof("persist: %v", DEFAULT_SYNC_PATH)
	}
}

func noop(string) (d.Driver, error) {
	return &d.Noop{}, nil
}

func Init(persist bool) {
	var err error

	if AllocDriver == nil {
		AllocDriver = noop // default safety net for driver maker
	}

	Sched = timer.NewTimer()

	Sched.Tic() // start the scheduler, don't ever stop

	if persist {
		if rec, err = libkv.Load(DEFAULT_SYNC_PATH); err != nil {
			log.Warningf("unable to load: %v", err)
		}
		for _, k := range rec.Key() {
			MakeService(rec.Get(k).(*Service))
		}
		Sched.RepeatFunc(DEFAULT_SYNC_CYCLE, 1, sync)
	} else {
		rec = libkv.NewStore()
	}
}

func ParseDuration(s string, df time.Duration) time.Duration {
	if d, err := time.ParseDuration(s); err != nil {
		return df
	} else {
		return d
	}
}

func Validate(iden, srv, port string, network []docker.APIPort) bool {
	if srv == "" {
		log.WithFields(log.Fields{"ID": iden}).Warning("not tracking: service")
		return false
	}
	if port == "" {
		if len(network) == 0 {
			log.WithFields(log.Fields{"ID": iden}).Warning("not tracking: port")
			return false
		}
		open := 0
		for _, net := range network {
			if net.PublicPort != 0 {
				open += 1
			}
		}
		if open == 0 {
			log.WithFields(log.Fields{"ID": iden}).Warning("not tracking: port")
			return false
		}
	}
	return true
}

func MakeService(s *Service) {
	s.f = log.Fields{"ID": s.Id[:12], "srv": s.Srv, "heartbeat": s.Hb, "ttl": s.TTL}

	if s.Port != "" {
		s.key = path.Join(s.Srv, fmt.Sprintf("%s:%s", disc.Advertise, s.Port))
	} else if len(s.Net) > 0 {
		key := make([]string, 0)
		for _, p := range s.Net {
			if p.PublicPort != 0 && p.IP == "0.0.0.0" {
				key = append(key, fmt.Sprintf("%s:%d", disc.Advertise, p.PublicPort))
			}
		}
		if len(key) == 1 {
			s.key = path.Join(s.Srv, strings.Join(key, ","))
		} else {
			log.WithFields(log.Fields{"ID": s.Id[:12], "Net": s.Net}).Warning("refuse; 0 or too many port")
			return
		}
	}

	s.opts = &etcd.SetOptions{TTL: s.TTL}

	if s.Start() {
		rec.Set(s.Id, s)
	} else {
		log.WithFields(log.Fields{"ID": s.Id[:12]}).Error("not tracking: probe failed")
	}
}

func NewService(heartbeat, ttl time.Duration, iden, service, port string, net []docker.APIPort) (s *Service) {
	s = &Service{
		Hb:   heartbeat,
		TTL:  ttl,
		Id:   iden,
		Srv:  service,
		Port: port,
		Net:  net,
	}
	MakeService(s)
	return
}

func ServiceStop(iden string) (s *Service) {
	if s, _ := rec.Get(iden).(*Service); s != nil && s.Running() {
		s.Stop()
	}
	return
}

func ServiceDie(iden string) (s *Service) {
	if s, _ := rec.Get(iden).(*Service); s != nil {
		if s.Running() {
			s.Stop()
		}
		rec.Del(iden)
		log.WithFields(log.Fields{"ID": s.Id[:12], "srv": s.Srv}).Info("die")
	}
	return
}

func Get(iden string) (s *Service) {
	s, _ = rec.Get(iden).(*Service)
	return
}

type Service struct {
	Hb  time.Duration `json: "Heartbeat"`
	TTL time.Duration `json: "TTL"`

	Id   string           `json: "ContainerID"`
	Srv  string           `json: "Service"`
	Port string           `json: "Port"`
	Net  []docker.APIPort `json: "Net"`

	kAPI etcd.KeysAPI     `json:-`
	key  string           `json:-`
	opts *etcd.SetOptions `json:-`

	jobId int64 `json:-`

	f log.Fields `json:-`

	driver d.Driver `json:-`
	fail   int      `json:-`
}

func (s *Service) Done(jobId int64) {
	if s.Probe() != nil {
		s.fail += 1
		log.WithFields(s.f).Warning("probe missed")
		return
	}
	if s.fail > 3 {
		s.Stop()
		return
	} else {
		s.fail = 0
		s.Upkeep()
	}
}

func (s *Service) Probe() error {
	return s.driver.Probe()
}

func (s *Service) Upkeep() {
	if _, err := s.kAPI.Set(ctx.Background(), s.key, s.Id, s.opts); err != nil {
		log.WithFields(s.f).Warning(err)
		s.opts.PrevExist = etcd.PrevIgnore
	} else {
		log.WithFields(s.f).Info("up")
		s.opts.PrevExist = etcd.PrevExist
	}
}

func (s *Service) Update() {
	Sched.Cancel(s.jobId)
	log.WithFields(s.f).Info("update")
	MakeService(s)
}

func (s *Service) Start() bool {
	// FIXME: we probably need a allow specific port for probing
	if s.driver, _ = AllocDriver(path.Base(s.key)); s.driver == nil {
		return false
	}

	s.kAPI = etcd.NewKeysAPI(disc.NewDiscovery())

	s.Upkeep()
	if s.Probe() != nil {
		s.fail += 1
		log.WithFields(s.f).Warning("probe missed")
	}

	s.jobId = Sched.Repeat(s.Hb, 1, s)

	return true
}

func (s *Service) Stop() {
	Sched.Cancel(s.jobId)
	if s.driver != nil {
		s.driver.Close()
		s.driver = nil
	}
	s.kAPI = nil
	s.jobId = -1
	s.opts.PrevExist = etcd.PrevIgnore
	log.WithFields(s.f).Info("down")
}

func (s *Service) Running() bool {
	return s.jobId != -1
}

func init() {
	gob.Register(&Service{})
	gob.Register([]docker.APIPort{})
}
<commit_msg>FIX: discovery adverise use host part<commit_after>package upkeep

import (
	d "github.com/jeffjen/docker-monitor/driver"
	disc "github.com/jeffjen/go-discovery"
	"github.com/jeffjen/go-libkv/libkv"
	timer "github.com/jeffjen/go-libkv/timer"

	log "github.com/Sirupsen/logrus"
	etcd "github.com/coreos/etcd/client"
	docker "github.com/fsouza/go-dockerclient"
	ctx "golang.org/x/net/context"

	"encoding/gob"
	"fmt"
	"path"
	"strings"
	"time"
)

const (
	DEFAULT_HEARTBEAT = 2 * time.Minute
	DEFAULT_TTL       = 2*time.Minute + 5*time.Second

	DEFAULT_SYNC_PATH  = "/tmp"
	DEFAULT_SYNC_CYCLE = 2 * time.Minute
)

var (
	Sched *timer.Timer

	rec *libkv.Store

	AllocDriver func(string) (d.Driver, error) = nil

	Advertise string
)

func sync(jobId int64) {
	if err := rec.Save(DEFAULT_SYNC_PATH); err != nil {
		log.Warningf("unable to persist: %v", err)
	} else {
		log.Infof("persist: %v", DEFAULT_SYNC_PATH)
	}
}

func noop(string) (d.Driver, error) {
	return &d.Noop{}, nil
}

func Init(persist bool) {
	var err error

	Advertise, _, _ = net.SplitHostPort(disc.Advertise)

	if AllocDriver == nil {
		AllocDriver = noop // default safety net for driver maker
	}

	Sched = timer.NewTimer()

	Sched.Tic() // start the scheduler, don't ever stop

	if persist {
		if rec, err = libkv.Load(DEFAULT_SYNC_PATH); err != nil {
			log.Warningf("unable to load: %v", err)
		}
		for _, k := range rec.Key() {
			MakeService(rec.Get(k).(*Service))
		}
		Sched.RepeatFunc(DEFAULT_SYNC_CYCLE, 1, sync)
	} else {
		rec = libkv.NewStore()
	}
}

func ParseDuration(s string, df time.Duration) time.Duration {
	if d, err := time.ParseDuration(s); err != nil {
		return df
	} else {
		return d
	}
}

func Validate(iden, srv, port string, network []docker.APIPort) bool {
	if srv == "" {
		log.WithFields(log.Fields{"ID": iden}).Warning("not tracking: service")
		return false
	}
	if port == "" {
		if len(network) == 0 {
			log.WithFields(log.Fields{"ID": iden}).Warning("not tracking: port")
			return false
		}
		open := 0
		for _, net := range network {
			if net.PublicPort != 0 {
				open += 1
			}
		}
		if open == 0 {
			log.WithFields(log.Fields{"ID": iden}).Warning("not tracking: port")
			return false
		}
	}
	return true
}

func MakeService(s *Service) {
	s.f = log.Fields{"ID": s.Id[:12], "srv": s.Srv, "heartbeat": s.Hb, "ttl": s.TTL}

	if s.Port != "" {
		s.key = path.Join(s.Srv, fmt.Sprintf("%s:%s", Advertise, s.Port))
	} else if len(s.Net) > 0 {
		key := make([]string, 0)
		for _, p := range s.Net {
			if p.PublicPort != 0 && p.IP == "0.0.0.0" {
				key = append(key, fmt.Sprintf("%s:%d", Advertise, p.PublicPort))
			}
		}
		if len(key) == 1 {
			s.key = path.Join(s.Srv, strings.Join(key, ","))
		} else {
			log.WithFields(log.Fields{"ID": s.Id[:12], "Net": s.Net}).Warning("refuse; 0 or too many port")
			return
		}
	}

	s.opts = &etcd.SetOptions{TTL: s.TTL}

	if s.Start() {
		rec.Set(s.Id, s)
	} else {
		log.WithFields(log.Fields{"ID": s.Id[:12]}).Error("not tracking: probe failed")
	}
}

func NewService(heartbeat, ttl time.Duration, iden, service, port string, net []docker.APIPort) (s *Service) {
	s = &Service{
		Hb:   heartbeat,
		TTL:  ttl,
		Id:   iden,
		Srv:  service,
		Port: port,
		Net:  net,
	}
	MakeService(s)
	return
}

func ServiceStop(iden string) (s *Service) {
	if s, _ := rec.Get(iden).(*Service); s != nil && s.Running() {
		s.Stop()
	}
	return
}

func ServiceDie(iden string) (s *Service) {
	if s, _ := rec.Get(iden).(*Service); s != nil {
		if s.Running() {
			s.Stop()
		}
		rec.Del(iden)
		log.WithFields(log.Fields{"ID": s.Id[:12], "srv": s.Srv}).Info("die")
	}
	return
}

func Get(iden string) (s *Service) {
	s, _ = rec.Get(iden).(*Service)
	return
}

type Service struct {
	Hb  time.Duration `json: "Heartbeat"`
	TTL time.Duration `json: "TTL"`

	Id   string           `json: "ContainerID"`
	Srv  string           `json: "Service"`
	Port string           `json: "Port"`
	Net  []docker.APIPort `json: "Net"`

	kAPI etcd.KeysAPI     `json:-`
	key  string           `json:-`
	opts *etcd.SetOptions `json:-`

	jobId int64 `json:-`

	f log.Fields `json:-`

	driver d.Driver `json:-`
	fail   int      `json:-`
}

func (s *Service) Done(jobId int64) {
	if s.Probe() != nil {
		s.fail += 1
		log.WithFields(s.f).Warning("probe missed")
		return
	}
	if s.fail > 3 {
		s.Stop()
		return
	} else {
		s.fail = 0
		s.Upkeep()
	}
}

func (s *Service) Probe() error {
	return s.driver.Probe()
}

func (s *Service) Upkeep() {
	if _, err := s.kAPI.Set(ctx.Background(), s.key, s.Id, s.opts); err != nil {
		log.WithFields(s.f).Warning(err)
		s.opts.PrevExist = etcd.PrevIgnore
	} else {
		log.WithFields(s.f).Info("up")
		s.opts.PrevExist = etcd.PrevExist
	}
}

func (s *Service) Update() {
	Sched.Cancel(s.jobId)
	log.WithFields(s.f).Info("update")
	MakeService(s)
}

func (s *Service) Start() bool {
	// FIXME: we probably need a allow specific port for probing
	if s.driver, _ = AllocDriver(path.Base(s.key)); s.driver == nil {
		return false
	}

	s.kAPI = etcd.NewKeysAPI(disc.NewDiscovery())

	s.Upkeep()
	if s.Probe() != nil {
		s.fail += 1
		log.WithFields(s.f).Warning("probe missed")
	}

	s.jobId = Sched.Repeat(s.Hb, 1, s)

	return true
}

func (s *Service) Stop() {
	Sched.Cancel(s.jobId)
	if s.driver != nil {
		s.driver.Close()
		s.driver = nil
	}
	s.kAPI = nil
	s.jobId = -1
	s.opts.PrevExist = etcd.PrevIgnore
	log.WithFields(s.f).Info("down")
}

func (s *Service) Running() bool {
	return s.jobId != -1
}

func init() {
	gob.Register(&Service{})
	gob.Register([]docker.APIPort{})
}
<|endoftext|>


<commit_before>package user

import (
	"github.com/stretchr/testify/assert"
	"gopkg.in/DATA-DOG/go-sqlmock.v1"
	"testing"

	"github.com/eirka/eirka-libs/config"
	"github.com/eirka/eirka-libs/db"
	e "github.com/eirka/eirka-libs/errors"
)

func init() {
	config.Settings.Limits.PasswordMinLength = 8
	config.Settings.Limits.PasswordMaxLength = 128
}

func TestDefaultUser(t *testing.T) {

	user := DefaultUser()

	assert.Equal(t, uint(1), user.Id, "default user id should be 1")

	assert.False(t, user.IsAuthenticated, "default user should not be authenticated")

}

func TestSetId(t *testing.T) {

	user := DefaultUser()

	user.SetId(2)

	assert.Equal(t, uint(2), user.Id, "user id should be 2")

}

func TestSetAuthenticated(t *testing.T) {

	user := DefaultUser()

	user.SetAuthenticated()

	assert.False(t, user.IsAuthenticated, "User should be not authorized")

	user.SetId(2)

	user.SetAuthenticated()

	assert.True(t, user.IsAuthenticated, "User should be authorized")

	assert.True(t, user.IsValid(), "Authed non-anon user should be valid")

}

func TestIsValid(t *testing.T) {

	user := DefaultUser()

	assert.True(t, user.IsValid(), "DefaultUser should be valid")

	user.SetId(2)

	assert.False(t, user.IsValid(), "Unauthenticated non-anon should be invalid")

	user.SetAuthenticated()

	assert.True(t, user.IsValid(), "Authed non-anon user should be valid")

	user.SetId(0)

	assert.False(t, user.IsValid(), "User zero should be invalid")

	user.SetId(1)

	assert.False(t, user.IsValid(), "An authenticated anon user should be invalid")

}

func TestIsValidName(t *testing.T) {

	assert.True(t, IsValidName("cooldude2"), "Name should validate")

	assert.True(t, IsValidName("cool dude"), "Name should validate")

	assert.True(t, IsValidName("cool_dude"), "Name should validate")

	assert.True(t, IsValidName("cool-dude"), "Name should validate")

	assert.False(t, IsValidName("cool.dude"), "Name should not validate")

	assert.False(t, IsValidName("cooldude!"), "Name should not validate")

	assert.False(t, IsValidName("admin"), "Name should not validate")

	assert.False(t, IsValidName("Admin"), "Name should not validate")

	assert.False(t, IsValidName("Admin "), "Name should not validate")

	assert.False(t, IsValidName(" Admin  "), "Name should not validate")

}

func TestPassword(t *testing.T) {

	_, err := HashPassword("")
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrPasswordEmpty, "Error should match")
	}

	_, err = HashPassword("heh")
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrPasswordShort, "Error should match")
	}

	_, err = HashPassword("k8dyuCqJfW9v5iFUeeS4YOeiuk5Wee6Q9tZvWFHqE10ftzhaxVzxlKzx4n7CcBpRcgtaX9dZ2lBIRrsvgqXPPvmjNpIgnrums2Xtst8FsZkpZo61u3ChCs7MEO1DGy4Qa")
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrPasswordLong, "Error should match")
	}

	password, err := HashPassword("testpassword")
	if assert.NoError(t, err, "An error was not expected") {
		assert.NotNil(t, password, "password should be returned")
	}

	user := DefaultUser()
	user.SetId(2)
	user.SetAuthenticated()

	assert.False(t, user.ComparePassword("atestpassword"), "Password should not validate")

	user.hash = password

	assert.False(t, user.ComparePassword(""), "Password should not validate")

	assert.False(t, user.ComparePassword("wrongpassword"), "Password should not validate")

	assert.True(t, user.ComparePassword("testpassword"), "Password should validate")

}

func TestCreateToken(t *testing.T) {

	Secret = ""

	user := DefaultUser()

	// secret must be set
	token, err := user.CreateToken()
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrNoSecret, "Error should match")
		assert.Empty(t, token, "Token should be empty")
	}

	Secret = "secret"

	// default user state should never get a token
	token, err = user.CreateToken()
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrUserNotValid, "Error should match")
		assert.Empty(t, token, "Token should be empty")
	}

	user.SetId(2)

	// a non authed user should never get a token
	token, err = user.CreateToken()
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrUserNotValid, "Error should match")
		assert.Empty(t, token, "Token should be empty")
	}

	user.SetAuthenticated()

	// a user that doesnt have a validated password should never get a token
	token, err = user.CreateToken()
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrInvalidPassword, "Error should match")
		assert.Empty(t, token, "Token should be empty")
	}

	user.hash, err = HashPassword("testpassword")
	if assert.NoError(t, err, "An error was not expected") {
		assert.NotNil(t, user.hash, "password should be returned")
	}

	assert.True(t, user.ComparePassword("testpassword"), "Password should validate")

	token, err = user.CreateToken()
	if assert.NoError(t, err, "An error was not expected") {
		assert.NotEmpty(t, token, "Token should not be empty")
	}

}

func TestCreateTokenAnonAuth(t *testing.T) {

	Secret = "secret"

	invalidUser := DefaultUser()
	invalidUser.SetId(1)
	invalidUser.SetAuthenticated()

	notoken, err := invalidUser.CreateToken()
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrUserNotValid, "Error should match")
		assert.Empty(t, notoken, "token should not be returned")
	}
}

func TestCreateTokenZeroAuth(t *testing.T) {

	Secret = "secret"

	invalidUser := DefaultUser()
	invalidUser.SetId(0)
	invalidUser.SetAuthenticated()

	notoken, err := invalidUser.CreateToken()
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrUserNotValid, "Error should match")
		assert.Empty(t, notoken, "token should not be returned")
	}
}

func TestCreateTokenZeroNoAuth(t *testing.T) {

	Secret = "secret"

	invalidUser := DefaultUser()
	invalidUser.SetId(0)

	notoken, err := invalidUser.CreateToken()
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrUserNotValid, "Error should match")
		assert.Empty(t, notoken, "token should not be returned")
	}
}

func TestUserPassword(t *testing.T) {

	Secret = "secret"

	user := DefaultUser()
	user.SetId(2)
	user.SetAuthenticated()

	password, err := HashPassword("testpassword")
	if assert.NoError(t, err, "An error was not expected") {
		assert.NotNil(t, password, "password should be returned")
	}

	mock, err := db.NewTestDb()
	assert.NoError(t, err, "An error was not expected")

	rows := sqlmock.NewRows([]string{"name", "password"}).AddRow("testaccount", password)

	mock.ExpectQuery("select user_name, user_password from users where user_id").WillReturnRows(rows)

	assert.NoError(t, user.Password(), "An error was not expected")

	assert.Equal(t, user.Name, "testaccount", "Name should match")

	assert.True(t, user.ComparePassword("testpassword"), "Password should validate")

}

func TestUserBadPassword(t *testing.T) {

	Secret = "secret"

	user := DefaultUser()
	user.SetId(2)
	user.SetAuthenticated()

	password, err := HashPassword("testpassword")
	if assert.NoError(t, err, "An error was not expected") {
		assert.NotNil(t, password, "password should be returned")
	}

	mock, err := db.NewTestDb()
	assert.NoError(t, err, "An error was not expected")

	rows := sqlmock.NewRows([]string{"name", "password"}).AddRow("testaccount", password)

	mock.ExpectQuery("select user_name, user_password from users where user_id").WillReturnRows(rows)

	assert.NoError(t, user.Password(), "An error was not expected")

	assert.Equal(t, user.Name, "testaccount", "Name should match")

	assert.False(t, user.ComparePassword("badpassword"), "Password should not validate")

}

func TestFromName(t *testing.T) {

	Secret = "secret"

	user := DefaultUser()

	password, err := HashPassword("testpassword")
	if assert.NoError(t, err, "An error was not expected") {
		assert.NotNil(t, password, "password should be returned")
	}

	mock, err := db.NewTestDb()
	assert.NoError(t, err, "An error was not expected")

	rows := sqlmock.NewRows([]string{"id", "password"}).AddRow(2, password)

	mock.ExpectQuery("select user_id, user_password from users where user_name").WillReturnRows(rows)

	assert.NoError(t, user.FromName("testaccount"), "An error was not expected")

	assert.Equal(t, user.Id, uint(2), "Id should match")

	assert.True(t, user.IsAuthenticated, "User should be authenticated")

	assert.True(t, user.ComparePassword("testpassword"), "Password should validate")

}

func TestFromNameEmptyName(t *testing.T) {

	Secret = "secret"

	user := DefaultUser()

	err := user.FromName("")
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrUserNotValid, "Error should match")
	}

}

func TestFromNameBadId(t *testing.T) {

	Secret = "secret"

	user := DefaultUser()

	password, err := HashPassword("testpassword")
	if assert.NoError(t, err, "An error was not expected") {
		assert.NotNil(t, password, "password should be returned")
	}

	mock, err := db.NewTestDb()
	assert.NoError(t, err, "An error was not expected")

	rows := sqlmock.NewRows([]string{"id", "password"}).AddRow(0, password)

	mock.ExpectQuery("select user_id, user_password from users where user_name").WillReturnRows(rows)

	err = user.FromName("test")
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrUserNotValid, "Error should match")
	}

}
<commit_msg>add user password sql check<commit_after>package user

import (
	"github.com/stretchr/testify/assert"
	"gopkg.in/DATA-DOG/go-sqlmock.v1"
	"testing"

	"github.com/eirka/eirka-libs/config"
	"github.com/eirka/eirka-libs/db"
	e "github.com/eirka/eirka-libs/errors"
)

func init() {
	config.Settings.Limits.PasswordMinLength = 8
	config.Settings.Limits.PasswordMaxLength = 128
}

func TestDefaultUser(t *testing.T) {

	user := DefaultUser()

	assert.Equal(t, uint(1), user.Id, "default user id should be 1")

	assert.False(t, user.IsAuthenticated, "default user should not be authenticated")

}

func TestSetId(t *testing.T) {

	user := DefaultUser()

	user.SetId(2)

	assert.Equal(t, uint(2), user.Id, "user id should be 2")

}

func TestSetAuthenticated(t *testing.T) {

	user := DefaultUser()

	user.SetAuthenticated()

	assert.False(t, user.IsAuthenticated, "User should be not authorized")

	user.SetId(2)

	user.SetAuthenticated()

	assert.True(t, user.IsAuthenticated, "User should be authorized")

	assert.True(t, user.IsValid(), "Authed non-anon user should be valid")

}

func TestIsValid(t *testing.T) {

	user := DefaultUser()

	assert.True(t, user.IsValid(), "DefaultUser should be valid")

	user.SetId(2)

	assert.False(t, user.IsValid(), "Unauthenticated non-anon should be invalid")

	user.SetAuthenticated()

	assert.True(t, user.IsValid(), "Authed non-anon user should be valid")

	user.SetId(0)

	assert.False(t, user.IsValid(), "User zero should be invalid")

	user.SetId(1)

	assert.False(t, user.IsValid(), "An authenticated anon user should be invalid")

}

func TestIsValidName(t *testing.T) {

	assert.True(t, IsValidName("cooldude2"), "Name should validate")

	assert.True(t, IsValidName("cool dude"), "Name should validate")

	assert.True(t, IsValidName("cool_dude"), "Name should validate")

	assert.True(t, IsValidName("cool-dude"), "Name should validate")

	assert.False(t, IsValidName("cool.dude"), "Name should not validate")

	assert.False(t, IsValidName("cooldude!"), "Name should not validate")

	assert.False(t, IsValidName("admin"), "Name should not validate")

	assert.False(t, IsValidName("Admin"), "Name should not validate")

	assert.False(t, IsValidName("Admin "), "Name should not validate")

	assert.False(t, IsValidName(" Admin  "), "Name should not validate")

}

func TestPassword(t *testing.T) {

	_, err := HashPassword("")
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrPasswordEmpty, "Error should match")
	}

	_, err = HashPassword("heh")
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrPasswordShort, "Error should match")
	}

	_, err = HashPassword("k8dyuCqJfW9v5iFUeeS4YOeiuk5Wee6Q9tZvWFHqE10ftzhaxVzxlKzx4n7CcBpRcgtaX9dZ2lBIRrsvgqXPPvmjNpIgnrums2Xtst8FsZkpZo61u3ChCs7MEO1DGy4Qa")
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrPasswordLong, "Error should match")
	}

	password, err := HashPassword("testpassword")
	if assert.NoError(t, err, "An error was not expected") {
		assert.NotNil(t, password, "password should be returned")
	}

	user := DefaultUser()
	user.SetId(2)
	user.SetAuthenticated()

	assert.False(t, user.ComparePassword("atestpassword"), "Password should not validate")

	user.hash = password

	assert.False(t, user.ComparePassword(""), "Password should not validate")

	assert.False(t, user.ComparePassword("wrongpassword"), "Password should not validate")

	assert.True(t, user.ComparePassword("testpassword"), "Password should validate")

}

func TestCreateToken(t *testing.T) {

	Secret = ""

	user := DefaultUser()

	// secret must be set
	token, err := user.CreateToken()
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrNoSecret, "Error should match")
		assert.Empty(t, token, "Token should be empty")
	}

	Secret = "secret"

	// default user state should never get a token
	token, err = user.CreateToken()
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrUserNotValid, "Error should match")
		assert.Empty(t, token, "Token should be empty")
	}

	user.SetId(2)

	// a non authed user should never get a token
	token, err = user.CreateToken()
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrUserNotValid, "Error should match")
		assert.Empty(t, token, "Token should be empty")
	}

	user.SetAuthenticated()

	// a user that doesnt have a validated password should never get a token
	token, err = user.CreateToken()
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrInvalidPassword, "Error should match")
		assert.Empty(t, token, "Token should be empty")
	}

	user.hash, err = HashPassword("testpassword")
	if assert.NoError(t, err, "An error was not expected") {
		assert.NotNil(t, user.hash, "password should be returned")
	}

	assert.True(t, user.ComparePassword("testpassword"), "Password should validate")

	token, err = user.CreateToken()
	if assert.NoError(t, err, "An error was not expected") {
		assert.NotEmpty(t, token, "Token should not be empty")
	}

}

func TestCreateTokenAnonAuth(t *testing.T) {

	Secret = "secret"

	invalidUser := DefaultUser()
	invalidUser.SetId(1)
	invalidUser.SetAuthenticated()

	notoken, err := invalidUser.CreateToken()
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrUserNotValid, "Error should match")
		assert.Empty(t, notoken, "token should not be returned")
	}
}

func TestCreateTokenZeroAuth(t *testing.T) {

	Secret = "secret"

	invalidUser := DefaultUser()
	invalidUser.SetId(0)
	invalidUser.SetAuthenticated()

	notoken, err := invalidUser.CreateToken()
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrUserNotValid, "Error should match")
		assert.Empty(t, notoken, "token should not be returned")
	}
}

func TestCreateTokenZeroNoAuth(t *testing.T) {

	Secret = "secret"

	invalidUser := DefaultUser()
	invalidUser.SetId(0)

	notoken, err := invalidUser.CreateToken()
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrUserNotValid, "Error should match")
		assert.Empty(t, notoken, "token should not be returned")
	}
}

func TestUserPassword(t *testing.T) {

	Secret = "secret"

	user := DefaultUser()
	user.SetId(2)
	user.SetAuthenticated()

	password, err := HashPassword("testpassword")
	if assert.NoError(t, err, "An error was not expected") {
		assert.NotNil(t, password, "password should be returned")
	}

	mock, err := db.NewTestDb()
	assert.NoError(t, err, "An error was not expected")

	rows := sqlmock.NewRows([]string{"name", "password"}).AddRow("testaccount", password)

	mock.ExpectQuery("select user_name, user_password from users where user_id").WillReturnRows(rows)

	err = user.Password()
	if assert.NoError(t, err, "An error was not expected") {
		assert.Equal(t, user.Name, "testaccount", "Name should match")
		assert.True(t, user.ComparePassword("testpassword"), "Password should validate")
	}
}

func TestUserBadPassword(t *testing.T) {

	Secret = "secret"

	user := DefaultUser()
	user.SetId(2)
	user.SetAuthenticated()

	password, err := HashPassword("testpassword")
	if assert.NoError(t, err, "An error was not expected") {
		assert.NotNil(t, password, "password should be returned")
	}

	mock, err := db.NewTestDb()
	assert.NoError(t, err, "An error was not expected")

	rows := sqlmock.NewRows([]string{"name", "password"}).AddRow("testaccount", password)

	mock.ExpectQuery("select user_name, user_password from users where user_id").WillReturnRows(rows)

	err = user.Password()
	if assert.NoError(t, err, "An error was not expected") {
		assert.Equal(t, user.Name, "testaccount", "Name should match")
		assert.False(t, user.ComparePassword("badpassword"), "Password should not validate")
	}
}

func TestFromName(t *testing.T) {

	Secret = "secret"

	user := DefaultUser()

	password, err := HashPassword("testpassword")
	if assert.NoError(t, err, "An error was not expected") {
		assert.NotNil(t, password, "password should be returned")
	}

	mock, err := db.NewTestDb()
	assert.NoError(t, err, "An error was not expected")

	rows := sqlmock.NewRows([]string{"id", "password"}).AddRow(2, password)

	mock.ExpectQuery("select user_id, user_password from users where user_name").WillReturnRows(rows)

	err = user.FromName("testaccount")
	if assert.NoError(t, err, "An error was not expected") {
		assert.Equal(t, user.Id, uint(2), "Id should match")
		assert.True(t, user.IsAuthenticated, "User should be authenticated")
		assert.True(t, user.ComparePassword("testpassword"), "Password should validate")
	}

}

func TestFromNameEmptyName(t *testing.T) {

	Secret = "secret"

	user := DefaultUser()

	err := user.FromName("")
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrUserNotValid, "Error should match")
	}

}

func TestFromNameBadId(t *testing.T) {

	Secret = "secret"

	user := DefaultUser()

	password, err := HashPassword("testpassword")
	if assert.NoError(t, err, "An error was not expected") {
		assert.NotNil(t, password, "password should be returned")
	}

	mock, err := db.NewTestDb()
	assert.NoError(t, err, "An error was not expected")

	rows := sqlmock.NewRows([]string{"id", "password"}).AddRow(0, password)

	mock.ExpectQuery("select user_id, user_password from users where user_name").WillReturnRows(rows)

	err = user.FromName("test")
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrUserNotValid, "Error should match")
	}

}
<|endoftext|>


<commit_before>package rcmgr

import (
	"context"
	"fmt"
	"sync"
	"time"

	"github.com/libp2p/go-libp2p-core/network"
	"github.com/libp2p/go-libp2p-core/peer"
	"github.com/libp2p/go-libp2p-core/protocol"
)

type resourceManager struct {
	limits Limiter

	system    *systemScope
	transient *transientScope

	mx    sync.Mutex
	svc   map[string]*serviceScope
	proto map[protocol.ID]*protocolScope
	peer  map[peer.ID]*peerScope

	cancelCtx context.Context
	cancel    func()
	wg        sync.WaitGroup
}

var _ network.ResourceManager = (*resourceManager)(nil)

type systemScope struct {
	*resourceScope
}

var _ network.ResourceScope = (*systemScope)(nil)

type transientScope struct {
	*resourceScope

	system *systemScope
}

var _ network.ResourceScope = (*transientScope)(nil)

type serviceScope struct {
	*resourceScope

	name   string
	system *systemScope
}

var _ network.ServiceScope = (*serviceScope)(nil)

type protocolScope struct {
	*resourceScope

	proto  protocol.ID
	system *systemScope
}

var _ network.ProtocolScope = (*protocolScope)(nil)

type peerScope struct {
	*resourceScope

	peer  peer.ID
	rcmgr *resourceManager
}

var _ network.PeerScope = (*peerScope)(nil)

type connectionScope struct {
	*resourceScope

	dir   network.Direction
	usefd bool
	rcmgr *resourceManager
	peer  *peerScope
}

var _ network.ConnectionScope = (*connectionScope)(nil)
var _ network.ConnectionManagementScope = (*connectionScope)(nil)

type streamScope struct {
	*resourceScope

	dir   network.Direction
	rcmgr *resourceManager
	peer  *peerScope
	svc   *serviceScope
	proto *protocolScope
}

var _ network.StreamScope = (*streamScope)(nil)
var _ network.StreamManagementScope = (*streamScope)(nil)

func NewResourceManager(limits Limiter) network.ResourceManager {
	r := &resourceManager{
		limits: limits,
		svc:    make(map[string]*serviceScope),
		proto:  make(map[protocol.ID]*protocolScope),
		peer:   make(map[peer.ID]*peerScope),
	}

	r.system = newSystemScope(limits.GetSystemLimits())
	r.system.IncRef()
	r.transient = newTransientScope(limits.GetTransientLimits(), r.system)
	r.transient.IncRef()

	r.cancelCtx, r.cancel = context.WithCancel(context.Background())

	r.wg.Add(1)
	go r.background()

	return r
}

func (r *resourceManager) ViewSystem(f func(network.ResourceScope) error) error {
	return f(r.system)
}

func (r *resourceManager) ViewTransient(f func(network.ResourceScope) error) error {
	return f(r.transient)
}

func (r *resourceManager) ViewService(srv string, f func(network.ServiceScope) error) error {
	s := r.getServiceScope(srv)
	defer s.DecRef()

	return f(s)
}

func (r *resourceManager) ViewProtocol(proto protocol.ID, f func(network.ProtocolScope) error) error {
	s := r.getProtocolScope(proto)
	defer s.DecRef()

	return f(s)
}

func (r *resourceManager) ViewPeer(p peer.ID, f func(network.PeerScope) error) error {
	s := r.getPeerScope(p)
	defer s.DecRef()

	return f(s)
}

func (r *resourceManager) getServiceScope(svc string) *serviceScope {
	r.mx.Lock()
	defer r.mx.Unlock()

	s, ok := r.svc[svc]
	if !ok {
		s = newServiceScope(svc, r.limits.GetServiceLimits(svc), r.system)
		r.svc[svc] = s
	}

	s.IncRef()
	return s
}

func (r *resourceManager) getProtocolScope(proto protocol.ID) *protocolScope {
	r.mx.Lock()
	defer r.mx.Unlock()

	s, ok := r.proto[proto]
	if !ok {
		s = newProtocolScope(proto, r.limits.GetProtocolLimits(proto), r.system)
		r.proto[proto] = s
	}

	s.IncRef()
	return s
}

func (r *resourceManager) getPeerScope(p peer.ID) *peerScope {
	r.mx.Lock()
	defer r.mx.Unlock()

	s, ok := r.peer[p]
	if !ok {
		s = newPeerScope(p, r.limits.GetPeerLimits(p), r)
		r.peer[p] = s
	}

	s.IncRef()
	return s
}

func (r *resourceManager) OpenConnection(dir network.Direction, usefd bool) (network.ConnectionManagementScope, error) {
	conn := newConnectionScope(dir, usefd, r.limits.GetConnLimits(), r)

	if err := conn.AddConn(dir, usefd); err != nil {
		conn.Done()
		return nil, err
	}

	return conn, nil
}

func (r *resourceManager) OpenStream(p peer.ID, dir network.Direction) (network.StreamManagementScope, error) {
	peer := r.getPeerScope(p)
	stream := newStreamScope(dir, r.limits.GetStreamLimits(p), peer)
	peer.DecRef() // we have the reference in constraints

	err := stream.AddStream(dir)
	if err != nil {
		stream.Done()
		return nil, err
	}

	return stream, nil
}

func (r *resourceManager) Close() error {
	r.cancel()
	r.wg.Wait()

	return nil
}

func (r *resourceManager) background() {
	defer r.wg.Done()

	// periodically garbage collects unused peer and protocol scopes
	ticker := time.NewTicker(time.Minute)
	defer ticker.Stop()

	for {
		select {
		case <-ticker.C:
			r.gc()
		case <-r.cancelCtx.Done():
			return
		}
	}
}

func (r *resourceManager) gc() {
	r.mx.Lock()
	defer r.mx.Unlock()

	for proto, s := range r.proto {
		if s.IsUnused() {
			s.Done()
			delete(r.proto, proto)
		}
	}

	for p, s := range r.peer {
		if s.IsUnused() {
			s.Done()
			delete(r.peer, p)
		}
	}
}

func newSystemScope(limit Limit) *systemScope {
	return &systemScope{
		resourceScope: newResourceScope(limit, nil),
	}
}

func newTransientScope(limit Limit, system *systemScope) *transientScope {
	return &transientScope{
		resourceScope: newResourceScope(limit, []*resourceScope{system.resourceScope}),
		system:        system,
	}
}

func newServiceScope(name string, limit Limit, system *systemScope) *serviceScope {
	return &serviceScope{
		resourceScope: newResourceScope(limit, []*resourceScope{system.resourceScope}),
		name:          name,
		system:        system,
	}
}

func newProtocolScope(proto protocol.ID, limit Limit, system *systemScope) *protocolScope {
	return &protocolScope{
		resourceScope: newResourceScope(limit, []*resourceScope{system.resourceScope}),
		proto:         proto,
		system:        system,
	}
}

func newPeerScope(p peer.ID, limit Limit, rcmgr *resourceManager) *peerScope {
	return &peerScope{
		resourceScope: newResourceScope(limit, []*resourceScope{rcmgr.system.resourceScope}),
		peer:          p,
		rcmgr:         rcmgr,
	}
}

func newConnectionScope(dir network.Direction, usefd bool, limit Limit, rcmgr *resourceManager) *connectionScope {
	return &connectionScope{
		resourceScope: newResourceScope(limit, []*resourceScope{rcmgr.transient.resourceScope, rcmgr.system.resourceScope}),
		dir:           dir,
		usefd:         usefd,
		rcmgr:         rcmgr,
	}
}

func newStreamScope(dir network.Direction, limit Limit, peer *peerScope) *streamScope {
	return &streamScope{
		resourceScope: newResourceScope(limit, []*resourceScope{peer.resourceScope, peer.rcmgr.transient.resourceScope, peer.rcmgr.system.resourceScope}),
		dir:           dir,
		rcmgr:         peer.rcmgr,
		peer:          peer,
	}
}

func (s *serviceScope) Name() string {
	return s.name
}

func (s *protocolScope) Protocol() protocol.ID {
	return s.proto
}

func (s *peerScope) Peer() peer.ID {
	return s.peer
}

func (s *connectionScope) PeerScope() network.PeerScope {
	s.Lock()
	defer s.Unlock()
	return s.peer
}

func (s *connectionScope) SetPeer(p peer.ID) error {
	s.Lock()
	defer s.Unlock()

	if s.peer != nil {
		return fmt.Errorf("connection scope already attached to a peer")
	}
	s.peer = s.rcmgr.getPeerScope(p)

	// juggle resources from transient scope to peer scope
	stat := s.resourceScope.rc.stat()
	if err := s.peer.ReserveForChild(stat); err != nil {
		s.peer.DecRef()
		s.peer = nil
		return err
	}

	s.rcmgr.transient.ReleaseForChild(stat)
	s.rcmgr.transient.DecRef() // removed from constraints

	// update constraints
	constraints := []*resourceScope{
		s.peer.resourceScope,
		s.rcmgr.system.resourceScope,
	}
	s.resourceScope.constraints = constraints

	return nil
}

func (s *streamScope) ProtocolScope() network.ProtocolScope {
	s.Lock()
	defer s.Unlock()
	return s.proto
}

func (s *streamScope) SetProtocol(proto protocol.ID) error {
	s.Lock()
	defer s.Unlock()

	if s.proto != nil {
		return fmt.Errorf("stream scope already attached to a protocol")
	}

	s.proto = s.rcmgr.getProtocolScope(proto)

	// juggle resources from transient scope to protocol scope
	stat := s.resourceScope.rc.stat()
	if err := s.proto.ReserveForChild(stat); err != nil {
		s.proto.DecRef()
		s.proto = nil
		return err
	}

	s.rcmgr.transient.ReleaseForChild(stat)
	s.rcmgr.transient.DecRef() // removed from constraints

	// update constraints
	constraints := []*resourceScope{
		s.peer.resourceScope,
		s.proto.resourceScope,
		s.rcmgr.system.resourceScope,
	}
	s.resourceScope.constraints = constraints

	return nil
}

func (s *streamScope) ServiceScope() network.ServiceScope {
	s.Lock()
	defer s.Unlock()
	return s.svc
}

func (s *streamScope) SetService(svc string) error {
	s.Lock()
	defer s.Unlock()

	if s.proto == nil {
		return fmt.Errorf("stream scope not attached to a protocol")
	}
	if s.svc != nil {
		return fmt.Errorf("stream scope already attached to a service")
	}

	s.svc = s.rcmgr.getServiceScope(svc)

	// reserve resources in service
	if err := s.svc.ReserveForChild(s.resourceScope.rc.stat()); err != nil {
		s.svc.DecRef()
		s.svc = nil
		return err
	}

	// update constraints
	constraints := []*resourceScope{
		s.peer.resourceScope,
		s.proto.resourceScope,
		s.svc.resourceScope,
		s.rcmgr.system.resourceScope,
	}
	s.resourceScope.constraints = constraints

	return nil
}

func (s *streamScope) PeerScope() network.PeerScope {
	s.Lock()
	defer s.Unlock()
	return s.peer
}
<commit_msg>proper mutex hat<commit_after>package rcmgr

import (
	"context"
	"fmt"
	"sync"
	"time"

	"github.com/libp2p/go-libp2p-core/network"
	"github.com/libp2p/go-libp2p-core/peer"
	"github.com/libp2p/go-libp2p-core/protocol"
)

type resourceManager struct {
	limits Limiter

	system    *systemScope
	transient *transientScope

	cancelCtx context.Context
	cancel    func()
	wg        sync.WaitGroup

	mx    sync.Mutex
	svc   map[string]*serviceScope
	proto map[protocol.ID]*protocolScope
	peer  map[peer.ID]*peerScope
}

var _ network.ResourceManager = (*resourceManager)(nil)

type systemScope struct {
	*resourceScope
}

var _ network.ResourceScope = (*systemScope)(nil)

type transientScope struct {
	*resourceScope

	system *systemScope
}

var _ network.ResourceScope = (*transientScope)(nil)

type serviceScope struct {
	*resourceScope

	name   string
	system *systemScope
}

var _ network.ServiceScope = (*serviceScope)(nil)

type protocolScope struct {
	*resourceScope

	proto  protocol.ID
	system *systemScope
}

var _ network.ProtocolScope = (*protocolScope)(nil)

type peerScope struct {
	*resourceScope

	peer  peer.ID
	rcmgr *resourceManager
}

var _ network.PeerScope = (*peerScope)(nil)

type connectionScope struct {
	*resourceScope

	dir   network.Direction
	usefd bool
	rcmgr *resourceManager
	peer  *peerScope
}

var _ network.ConnectionScope = (*connectionScope)(nil)
var _ network.ConnectionManagementScope = (*connectionScope)(nil)

type streamScope struct {
	*resourceScope

	dir   network.Direction
	rcmgr *resourceManager
	peer  *peerScope
	svc   *serviceScope
	proto *protocolScope
}

var _ network.StreamScope = (*streamScope)(nil)
var _ network.StreamManagementScope = (*streamScope)(nil)

func NewResourceManager(limits Limiter) network.ResourceManager {
	r := &resourceManager{
		limits: limits,
		svc:    make(map[string]*serviceScope),
		proto:  make(map[protocol.ID]*protocolScope),
		peer:   make(map[peer.ID]*peerScope),
	}

	r.system = newSystemScope(limits.GetSystemLimits())
	r.system.IncRef()
	r.transient = newTransientScope(limits.GetTransientLimits(), r.system)
	r.transient.IncRef()

	r.cancelCtx, r.cancel = context.WithCancel(context.Background())

	r.wg.Add(1)
	go r.background()

	return r
}

func (r *resourceManager) ViewSystem(f func(network.ResourceScope) error) error {
	return f(r.system)
}

func (r *resourceManager) ViewTransient(f func(network.ResourceScope) error) error {
	return f(r.transient)
}

func (r *resourceManager) ViewService(srv string, f func(network.ServiceScope) error) error {
	s := r.getServiceScope(srv)
	defer s.DecRef()

	return f(s)
}

func (r *resourceManager) ViewProtocol(proto protocol.ID, f func(network.ProtocolScope) error) error {
	s := r.getProtocolScope(proto)
	defer s.DecRef()

	return f(s)
}

func (r *resourceManager) ViewPeer(p peer.ID, f func(network.PeerScope) error) error {
	s := r.getPeerScope(p)
	defer s.DecRef()

	return f(s)
}

func (r *resourceManager) getServiceScope(svc string) *serviceScope {
	r.mx.Lock()
	defer r.mx.Unlock()

	s, ok := r.svc[svc]
	if !ok {
		s = newServiceScope(svc, r.limits.GetServiceLimits(svc), r.system)
		r.svc[svc] = s
	}

	s.IncRef()
	return s
}

func (r *resourceManager) getProtocolScope(proto protocol.ID) *protocolScope {
	r.mx.Lock()
	defer r.mx.Unlock()

	s, ok := r.proto[proto]
	if !ok {
		s = newProtocolScope(proto, r.limits.GetProtocolLimits(proto), r.system)
		r.proto[proto] = s
	}

	s.IncRef()
	return s
}

func (r *resourceManager) getPeerScope(p peer.ID) *peerScope {
	r.mx.Lock()
	defer r.mx.Unlock()

	s, ok := r.peer[p]
	if !ok {
		s = newPeerScope(p, r.limits.GetPeerLimits(p), r)
		r.peer[p] = s
	}

	s.IncRef()
	return s
}

func (r *resourceManager) OpenConnection(dir network.Direction, usefd bool) (network.ConnectionManagementScope, error) {
	conn := newConnectionScope(dir, usefd, r.limits.GetConnLimits(), r)

	if err := conn.AddConn(dir, usefd); err != nil {
		conn.Done()
		return nil, err
	}

	return conn, nil
}

func (r *resourceManager) OpenStream(p peer.ID, dir network.Direction) (network.StreamManagementScope, error) {
	peer := r.getPeerScope(p)
	stream := newStreamScope(dir, r.limits.GetStreamLimits(p), peer)
	peer.DecRef() // we have the reference in constraints

	err := stream.AddStream(dir)
	if err != nil {
		stream.Done()
		return nil, err
	}

	return stream, nil
}

func (r *resourceManager) Close() error {
	r.cancel()
	r.wg.Wait()

	return nil
}

func (r *resourceManager) background() {
	defer r.wg.Done()

	// periodically garbage collects unused peer and protocol scopes
	ticker := time.NewTicker(time.Minute)
	defer ticker.Stop()

	for {
		select {
		case <-ticker.C:
			r.gc()
		case <-r.cancelCtx.Done():
			return
		}
	}
}

func (r *resourceManager) gc() {
	r.mx.Lock()
	defer r.mx.Unlock()

	for proto, s := range r.proto {
		if s.IsUnused() {
			s.Done()
			delete(r.proto, proto)
		}
	}

	for p, s := range r.peer {
		if s.IsUnused() {
			s.Done()
			delete(r.peer, p)
		}
	}
}

func newSystemScope(limit Limit) *systemScope {
	return &systemScope{
		resourceScope: newResourceScope(limit, nil),
	}
}

func newTransientScope(limit Limit, system *systemScope) *transientScope {
	return &transientScope{
		resourceScope: newResourceScope(limit, []*resourceScope{system.resourceScope}),
		system:        system,
	}
}

func newServiceScope(name string, limit Limit, system *systemScope) *serviceScope {
	return &serviceScope{
		resourceScope: newResourceScope(limit, []*resourceScope{system.resourceScope}),
		name:          name,
		system:        system,
	}
}

func newProtocolScope(proto protocol.ID, limit Limit, system *systemScope) *protocolScope {
	return &protocolScope{
		resourceScope: newResourceScope(limit, []*resourceScope{system.resourceScope}),
		proto:         proto,
		system:        system,
	}
}

func newPeerScope(p peer.ID, limit Limit, rcmgr *resourceManager) *peerScope {
	return &peerScope{
		resourceScope: newResourceScope(limit, []*resourceScope{rcmgr.system.resourceScope}),
		peer:          p,
		rcmgr:         rcmgr,
	}
}

func newConnectionScope(dir network.Direction, usefd bool, limit Limit, rcmgr *resourceManager) *connectionScope {
	return &connectionScope{
		resourceScope: newResourceScope(limit, []*resourceScope{rcmgr.transient.resourceScope, rcmgr.system.resourceScope}),
		dir:           dir,
		usefd:         usefd,
		rcmgr:         rcmgr,
	}
}

func newStreamScope(dir network.Direction, limit Limit, peer *peerScope) *streamScope {
	return &streamScope{
		resourceScope: newResourceScope(limit, []*resourceScope{peer.resourceScope, peer.rcmgr.transient.resourceScope, peer.rcmgr.system.resourceScope}),
		dir:           dir,
		rcmgr:         peer.rcmgr,
		peer:          peer,
	}
}

func (s *serviceScope) Name() string {
	return s.name
}

func (s *protocolScope) Protocol() protocol.ID {
	return s.proto
}

func (s *peerScope) Peer() peer.ID {
	return s.peer
}

func (s *connectionScope) PeerScope() network.PeerScope {
	s.Lock()
	defer s.Unlock()
	return s.peer
}

func (s *connectionScope) SetPeer(p peer.ID) error {
	s.Lock()
	defer s.Unlock()

	if s.peer != nil {
		return fmt.Errorf("connection scope already attached to a peer")
	}
	s.peer = s.rcmgr.getPeerScope(p)

	// juggle resources from transient scope to peer scope
	stat := s.resourceScope.rc.stat()
	if err := s.peer.ReserveForChild(stat); err != nil {
		s.peer.DecRef()
		s.peer = nil
		return err
	}

	s.rcmgr.transient.ReleaseForChild(stat)
	s.rcmgr.transient.DecRef() // removed from constraints

	// update constraints
	constraints := []*resourceScope{
		s.peer.resourceScope,
		s.rcmgr.system.resourceScope,
	}
	s.resourceScope.constraints = constraints

	return nil
}

func (s *streamScope) ProtocolScope() network.ProtocolScope {
	s.Lock()
	defer s.Unlock()
	return s.proto
}

func (s *streamScope) SetProtocol(proto protocol.ID) error {
	s.Lock()
	defer s.Unlock()

	if s.proto != nil {
		return fmt.Errorf("stream scope already attached to a protocol")
	}

	s.proto = s.rcmgr.getProtocolScope(proto)

	// juggle resources from transient scope to protocol scope
	stat := s.resourceScope.rc.stat()
	if err := s.proto.ReserveForChild(stat); err != nil {
		s.proto.DecRef()
		s.proto = nil
		return err
	}

	s.rcmgr.transient.ReleaseForChild(stat)
	s.rcmgr.transient.DecRef() // removed from constraints

	// update constraints
	constraints := []*resourceScope{
		s.peer.resourceScope,
		s.proto.resourceScope,
		s.rcmgr.system.resourceScope,
	}
	s.resourceScope.constraints = constraints

	return nil
}

func (s *streamScope) ServiceScope() network.ServiceScope {
	s.Lock()
	defer s.Unlock()
	return s.svc
}

func (s *streamScope) SetService(svc string) error {
	s.Lock()
	defer s.Unlock()

	if s.proto == nil {
		return fmt.Errorf("stream scope not attached to a protocol")
	}
	if s.svc != nil {
		return fmt.Errorf("stream scope already attached to a service")
	}

	s.svc = s.rcmgr.getServiceScope(svc)

	// reserve resources in service
	if err := s.svc.ReserveForChild(s.resourceScope.rc.stat()); err != nil {
		s.svc.DecRef()
		s.svc = nil
		return err
	}

	// update constraints
	constraints := []*resourceScope{
		s.peer.resourceScope,
		s.proto.resourceScope,
		s.svc.resourceScope,
		s.rcmgr.system.resourceScope,
	}
	s.resourceScope.constraints = constraints

	return nil
}

func (s *streamScope) PeerScope() network.PeerScope {
	s.Lock()
	defer s.Unlock()
	return s.peer
}
<|endoftext|>


<commit_before>package edc

// Education - struct for education
type Education struct {
	ID        int64  `sql:"id"         json:"id"         form:"id"         query:"id" `
	ContactID int64  `sql:"contact_id" json:"contact_id" form:"contact_id" query:"contact_id"`
	StartDate string `sql:"start_date" json:"start_date" form:"start_date" query:"start_date"`
	EndDate   string `sql:"end_date"   json:"end_date"   form:"end_date"   query:"end_date"`
	StartStr  string `sql:"-"          json:"start_str"  form:"start_str"  query:"start_str"`
	EndStr    string `sql:"-"          json:"end_str"    form:"end_str"    query:"end_str"`
	PostID    int64  `sql:"post_id"    json:"post_id"    form:"post_id"    query:"post_id"`
	Note      string `sql:"note,null"  json:"note"       form:"note"       query:"note"`
	CreatedAt string `sql:"created_at" json:"-"`
	UpdatedAt string `sql:"updated_at" json:"-"`
}

// EducationList - struct for list of education
type EducationList struct {
	ID          int64  `sql:"id"           json:"id"           form:"id"           query:"id"`
	ContactID   int64  `sql:"contact_id"   json:"contact_id"   form:"contact_id"   query:"contact_id"`
	ContactName string `sql:"contact_name" json:"contact_name" form:"contact_name" query:"contact_name"`
	StartDate   string `sql:"start_date"   json:"start_date"   form:"start_date"   query:"start_date"`
	EndDate     string `sql:"end_date"     json:"end_date"     form:"end_date"     query:"end_date"`
	StartStr    string `sql:"-"            json:"start_str"    form:"start_str"    query:"start_str"`
	EndStr      string `sql:"-"            json:"end_str"      form:"end_str"      query:"end_str"`
	PostID      int64  `sql:"post_id"      json:"post_id"      form:"post_id"      query:"post_id"`
	PostName    string `sql:"post_name"    json:"post_name"    form:"post_name"    query:"post_name"`
	Note        string `sql:"note,null"    json:"note"         form:"note"         query:"note"`
}

// GetEducation - get education by id
func (e *Edb) GetEducation(id int64) (Education, error) {
	var education Education
	if id == 0 {
		return education, nil
	}
	err := e.db.Model(&education).
		Where("id = ?", id).
		Select()
	if err != nil {
		errmsg("GetEducation select", err)
	}
	return education, err
}

// GetEducationListAll - get all education for list
func (e *Edb) GetEducationListAll() ([]EducationList, error) {
	var educations []EducationList
	_, err := e.db.Query(&educations, `
		SELECT
			e.id,
			e.start_date,
			e.end_date,
			e.contact_id,
			c.name AS contact_name,
			e.post_id,
			p.name AS post_name
		FROM
			educations AS e
		LEFT JOIN
			contacts AS c ON c.id = e.contact_id
		LEFT JOIN
			posts AS p ON p.id = e.post_id
		ORDER BY
			start_date DESC
	`)
	for i := range educations {
		educations[i].StartStr = setStrMonth(educations[i].StartDate)
		educations[i].EndStr = setStrMonth(educations[i].EndDate)
	}
	return educations, err
}

// GetEducationNear - get 10 nearest educations
func (e *Edb) GetEducationNear() ([]EducationList, error) {
	var educations []EducationList
	_, err := e.db.Query(&educations, `
		SELECT
			e.id,
			e.start_date,
			e.end_date,
			e.contact_id,
			c.name AS contact_name
		FROM
			educations AS e
		LEFT JOIN
			contacts AS c ON c.id = e.contact_id
		WHERE
			e.start_date > TIMESTAMP 'now'::timestamp - '1 month'::interval
		ORDER BY
			start_date DESC
		LIMIT 10
	`)
	for i := range educations {
		educations[i].StartStr = setStrMonth(educations[i].StartDate)
	}
	if err != nil {
		errmsg("GetEducationNear query", err)
	}
	return educations, err
}

// // GetEducationSelectAll - get all education for select
// func (e *Edb) GetEducationSelectAll() ([]Education, error) {
// 	var educations []Education
// 	err := e.db.Model(&educations).
// 		C("id", "start_date", "end_date").
// 		Order("start_date").
// 		Select()
// 	if err != nil {
// 		errmsg("GetEducationSelectAll select", err)
// 		return educations, err
// 	}
// 	for i := range educations {
// 		educations[i].StartStr = setStrMonth(educations[i].StartDate)
// 		educations[i].EndStr = setStrMonth(educations[i].EndDate)
// 	}
// 	return educations, err
// }

// CreateEducation - create new education
func (e *Edb) CreateEducation(education Education) (int64, error) {
	err := e.db.Insert(&education)
	if err != nil {
		errmsg("CreateEducation insert", err)
	}
	return education.ID, err
}

// UpdateEducation - save changes to education
func (e *Edb) UpdateEducation(education Education) error {
	err := e.db.Update(&education)
	if err != nil {
		errmsg("UpdateEducation update", err)
	}
	return err
}

// DeleteEducation - delete education by id
func (e *Edb) DeleteEducation(id int64) error {
	if id == 0 {
		return nil
	}
	_, err := e.db.Model(&Education{}).
		Where("id = ?", id).
		Delete()
	if err != nil {
		errmsg("DeleteEducation delete", err)
	}
	return err
}

func (e *Edb) educationCreateTable() error {
	str := `
		CREATE TABLE IF NOT EXISTS
			educations (
				id bigserial primary key,
				start_date date,
				end_date date,
				note text,
				post_id bigint,
				created_at TIMESTAMP without time zone,
				updated_at TIMESTAMP without time zone default now()
			)
	`
	_, err := e.db.Exec(str)
	if err != nil {
		errmsg("educationCreateTable exec", err)
	}
	return err
}
<commit_msg>sort nearest educations<commit_after>package edc

// Education - struct for education
type Education struct {
	ID        int64  `sql:"id"         json:"id"         form:"id"         query:"id" `
	ContactID int64  `sql:"contact_id" json:"contact_id" form:"contact_id" query:"contact_id"`
	StartDate string `sql:"start_date" json:"start_date" form:"start_date" query:"start_date"`
	EndDate   string `sql:"end_date"   json:"end_date"   form:"end_date"   query:"end_date"`
	StartStr  string `sql:"-"          json:"start_str"  form:"start_str"  query:"start_str"`
	EndStr    string `sql:"-"          json:"end_str"    form:"end_str"    query:"end_str"`
	PostID    int64  `sql:"post_id"    json:"post_id"    form:"post_id"    query:"post_id"`
	Note      string `sql:"note,null"  json:"note"       form:"note"       query:"note"`
	CreatedAt string `sql:"created_at" json:"-"`
	UpdatedAt string `sql:"updated_at" json:"-"`
}

// EducationList - struct for list of education
type EducationList struct {
	ID          int64  `sql:"id"           json:"id"           form:"id"           query:"id"`
	ContactID   int64  `sql:"contact_id"   json:"contact_id"   form:"contact_id"   query:"contact_id"`
	ContactName string `sql:"contact_name" json:"contact_name" form:"contact_name" query:"contact_name"`
	StartDate   string `sql:"start_date"   json:"start_date"   form:"start_date"   query:"start_date"`
	EndDate     string `sql:"end_date"     json:"end_date"     form:"end_date"     query:"end_date"`
	StartStr    string `sql:"-"            json:"start_str"    form:"start_str"    query:"start_str"`
	EndStr      string `sql:"-"            json:"end_str"      form:"end_str"      query:"end_str"`
	PostID      int64  `sql:"post_id"      json:"post_id"      form:"post_id"      query:"post_id"`
	PostName    string `sql:"post_name"    json:"post_name"    form:"post_name"    query:"post_name"`
	Note        string `sql:"note,null"    json:"note"         form:"note"         query:"note"`
}

// GetEducation - get education by id
func (e *Edb) GetEducation(id int64) (Education, error) {
	var education Education
	if id == 0 {
		return education, nil
	}
	err := e.db.Model(&education).
		Where("id = ?", id).
		Select()
	if err != nil {
		errmsg("GetEducation select", err)
	}
	return education, err
}

// GetEducationListAll - get all education for list
func (e *Edb) GetEducationListAll() ([]EducationList, error) {
	var educations []EducationList
	_, err := e.db.Query(&educations, `
		SELECT
			e.id,
			e.start_date,
			e.end_date,
			e.contact_id,
			c.name AS contact_name,
			e.post_id,
			p.name AS post_name
		FROM
			educations AS e
		LEFT JOIN
			contacts AS c ON c.id = e.contact_id
		LEFT JOIN
			posts AS p ON p.id = e.post_id
		ORDER BY
			start_date DESC
	`)
	for i := range educations {
		educations[i].StartStr = setStrMonth(educations[i].StartDate)
		educations[i].EndStr = setStrMonth(educations[i].EndDate)
	}
	return educations, err
}

// GetEducationNear - get 10 nearest educations
func (e *Edb) GetEducationNear() ([]EducationList, error) {
	var educations []EducationList
	_, err := e.db.Query(&educations, `
		SELECT
			e.id,
			e.start_date,
			e.end_date,
			e.contact_id,
			c.name AS contact_name
		FROM
			educations AS e
		LEFT JOIN
			contacts AS c ON c.id = e.contact_id
		WHERE
			e.start_date > TIMESTAMP 'now'::timestamp - '1 month'::interval
		ORDER BY
			start_date ASC
		LIMIT 10
	`)
	for i := range educations {
		educations[i].StartStr = setStrMonth(educations[i].StartDate)
	}
	if err != nil {
		errmsg("GetEducationNear query", err)
	}
	return educations, err
}

// // GetEducationSelectAll - get all education for select
// func (e *Edb) GetEducationSelectAll() ([]Education, error) {
// 	var educations []Education
// 	err := e.db.Model(&educations).
// 		C("id", "start_date", "end_date").
// 		Order("start_date").
// 		Select()
// 	if err != nil {
// 		errmsg("GetEducationSelectAll select", err)
// 		return educations, err
// 	}
// 	for i := range educations {
// 		educations[i].StartStr = setStrMonth(educations[i].StartDate)
// 		educations[i].EndStr = setStrMonth(educations[i].EndDate)
// 	}
// 	return educations, err
// }

// CreateEducation - create new education
func (e *Edb) CreateEducation(education Education) (int64, error) {
	err := e.db.Insert(&education)
	if err != nil {
		errmsg("CreateEducation insert", err)
	}
	return education.ID, err
}

// UpdateEducation - save changes to education
func (e *Edb) UpdateEducation(education Education) error {
	err := e.db.Update(&education)
	if err != nil {
		errmsg("UpdateEducation update", err)
	}
	return err
}

// DeleteEducation - delete education by id
func (e *Edb) DeleteEducation(id int64) error {
	if id == 0 {
		return nil
	}
	_, err := e.db.Model(&Education{}).
		Where("id = ?", id).
		Delete()
	if err != nil {
		errmsg("DeleteEducation delete", err)
	}
	return err
}

func (e *Edb) educationCreateTable() error {
	str := `
		CREATE TABLE IF NOT EXISTS
			educations (
				id bigserial primary key,
				start_date date,
				end_date date,
				note text,
				post_id bigint,
				created_at TIMESTAMP without time zone,
				updated_at TIMESTAMP without time zone default now()
			)
	`
	_, err := e.db.Exec(str)
	if err != nil {
		errmsg("educationCreateTable exec", err)
	}
	return err
}
<|endoftext|>


<commit_before>package dbfunc

import (
	"fmt"
	"strconv"
	"github.com/boltdb/bolt"
)

type Settings struct {
	Numln		int
	Rate		int
	Ircnick		string
	Uname		string
	Channel		string
	Server		string
	Kdel		int
	Randel		int
}

// func Wrdb(db *bolt.DB, k, v, cbuc []byte) (err error) {

// 	err = db.Update(func(tx *bolt.Tx) error {
// 		buc, err := tx.CreateBucketIfNotExists(cbuc)
// 		if err != nil { return err }

// 		err = buc.Put(k, v)
// 		if err != nil { return err }

// 		return nil
// 	})
// 	return
// }

func Wrdb(db *bolt.DB, k int, v, cbuc []byte) (err error) {

	err = db.Update(func(tx *bolt.Tx) error {
		buc, err := tx.CreateBucketIfNotExists(cbuc)
		if err != nil { return err }

		err = buc.Put([]byte(strconv.Itoa(k)), v)
		if err != nil { return err }

		return nil
	})
	return
}

func Rdb(db *bolt.DB, k int, cbuc []byte) ([]byte, error) {

	var v []byte

	err := db.View(func(tx *bolt.Tx) error {
		buc := tx.Bucket(cbuc)
		if buc == nil { return fmt.Errorf("No bucket!") }

		v = buc.Get([]byte(strconv.Itoa(k)))
		return nil
	})
	return v, err
}
<commit_msg>Cleanup<commit_after>package dbfunc

import (
	"fmt"
	"strconv"
	"github.com/boltdb/bolt"
)

type Settings struct {
	Numln		int
	Rate		int
	Ircnick		string
	Uname		string
	Channel		string
	Server		string
	Kdel		int
	Randel		int
}

func Wrdb(db *bolt.DB, k int, v, cbuc []byte) (err error) {

	err = db.Update(func(tx *bolt.Tx) error {
		buc, err := tx.CreateBucketIfNotExists(cbuc)
		if err != nil { return err }

		err = buc.Put([]byte(strconv.Itoa(k)), v)
		if err != nil { return err }

		return nil
	})
	return
}

func Rdb(db *bolt.DB, k int, cbuc []byte) ([]byte, error) {

	var v []byte

	err := db.View(func(tx *bolt.Tx) error {
		buc := tx.Bucket(cbuc)
		if buc == nil { return fmt.Errorf("No bucket!") }

		v = buc.Get([]byte(strconv.Itoa(k)))
		return nil
	})
	return v, err
}
<|endoftext|>


<commit_before>package etcd

import (
	"log"
	"time"

	"github.com/coreos/etcd/client"
	"net/http"
	"os"
	"github.com/coreos/etcd/pkg/transport"
	"context"
	"auto-ng/config"
)

var globalEndpoints []string
var globalCaFile string
var globalCertFile string
var globalKeyFile string

var globalKapi client.KeysAPI

/**
	初始化 etcd客户端的一些链接设置等等
 */

func InitConfig() {
	cfg := config.GetETCDconfig()
	globalEndpoints = cfg.EndPoints
	globalCaFile = cfg.CaFile
	globalCertFile = cfg.CertFile
	globalKeyFile = cfg.KeyFile
}

/**
	获取client，没有创建有就使用
 */

func getKapi() client.KeysAPI {
	if globalKapi == nil {
		transport, err := getTransport()
		if err != nil {
			log.Fatal(err)
		}
		cfg := client.Config{
			Endpoints:globalEndpoints,
			Transport:transport,
			HeaderTimeoutPerRequest:time.Second,
		}
		cli, err := client.New(cfg)
		if err != nil {
			log.Fatal(err)
		}
		globalKapi = client.NewKeysAPI(cli)
	}
	return globalKapi
}

/**
	获取transport
 */

func getTransport() (*http.Transport, error) {
	if globalCaFile == "" {
		globalCaFile = os.Getenv("CA_FILE")
	}
	if globalCertFile == "" {
		globalCertFile = os.Getenv("CERT_FILE")
	}
	if globalKeyFile == "" {
		globalKeyFile = os.Getenv("KEY_FILE")
	}

	tls := transport.TLSInfo{
		CAFile:   globalCaFile,
		CertFile: globalCertFile,
		KeyFile:  globalKeyFile,
	}
	return transport.NewTransport(tls, 30 * time.Second)
}

/**
	某个目录下的所有键
 */
func QueryKeyList(path string) (*client.Response, error) {
	kapi := getKapi()
	opts := &client.GetOptions{}
	opts.Recursive = true
	return kapi.Get(context.Background(), path, opts)
}

/**
	更新某个键的值
 */
func UpdateKey(k, v string) (*client.Response, error) {
	kapi := getKapi()
	return kapi.Update(context.Background(), k, v)
}

/**
	设置某个键的值
 */
func SetKey(k, v string, opts *client.SetOptions) (*client.Response, error) {
	kapi := getKapi()
	return kapi.Set(context.Background(), k, v, opts)
}

/**
	删除某个键
 */
func DeleteKey(k string, opts *client.DeleteOptions) (*client.Response, error) {
	kapi := getKapi()
	return kapi.Delete(context.Background(), k, opts)
}<commit_msg>启动自动加载etcd配置<commit_after>package etcd

import (
	"log"
	"time"

	"github.com/coreos/etcd/client"
	"net/http"
	"os"
	"github.com/coreos/etcd/pkg/transport"
	"context"
	"auto-ng/config"
)

var globalEndpoints []string
var globalCaFile string
var globalCertFile string
var globalKeyFile string

var globalKapi client.KeysAPI

/**
	初始化 etcd客户端的一些链接设置等等
 */

func init() {
	cfg := config.GetETCDconfig()
	globalEndpoints = cfg.EndPoints
	globalCaFile = cfg.CaFile
	globalCertFile = cfg.CertFile
	globalKeyFile = cfg.KeyFile
}

/**
	获取client，没有创建有就使用
 */

func getKapi() client.KeysAPI {
	if globalKapi == nil {
		transport, err := getTransport()
		if err != nil {
			log.Fatal(err)
		}
		cfg := client.Config{
			Endpoints:globalEndpoints,
			Transport:transport,
			HeaderTimeoutPerRequest:time.Second,
		}
		cli, err := client.New(cfg)
		if err != nil {
			log.Fatal(err)
		}
		globalKapi = client.NewKeysAPI(cli)
	}
	return globalKapi
}

/**
	获取transport
 */

func getTransport() (*http.Transport, error) {
	if globalCaFile == "" {
		globalCaFile = os.Getenv("CA_FILE")
	}
	if globalCertFile == "" {
		globalCertFile = os.Getenv("CERT_FILE")
	}
	if globalKeyFile == "" {
		globalKeyFile = os.Getenv("KEY_FILE")
	}

	tls := transport.TLSInfo{
		CAFile:   globalCaFile,
		CertFile: globalCertFile,
		KeyFile:  globalKeyFile,
	}
	return transport.NewTransport(tls, 30 * time.Second)
}

/**
	某个目录下的所有键
 */
func QueryKeyList(path string) (*client.Response, error) {
	kapi := getKapi()
	opts := &client.GetOptions{}
	opts.Recursive = true
	return kapi.Get(context.Background(), path, opts)
}

/**
	更新某个键的值
 */
func UpdateKey(k, v string) (*client.Response, error) {
	kapi := getKapi()
	return kapi.Update(context.Background(), k, v)
}

/**
	设置某个键的值
 */
func SetKey(k, v string, opts *client.SetOptions) (*client.Response, error) {
	kapi := getKapi()
	return kapi.Set(context.Background(), k, v, opts)
}

/**
	删除某个键
 */
func DeleteKey(k string, opts *client.DeleteOptions) (*client.Response, error) {
	kapi := getKapi()
	return kapi.Delete(context.Background(), k, opts)
}<|endoftext|>


<commit_before>// Package openstack generates Machine objects for openstack.
package openstack

import (
	"fmt"

	machineapi "github.com/openshift/cluster-api/pkg/apis/machine/v1beta1"
	"github.com/pkg/errors"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	openstackprovider "sigs.k8s.io/cluster-api-provider-openstack/pkg/apis/openstackproviderconfig/v1alpha1"

	"github.com/openshift/installer/pkg/types"
	"github.com/openshift/installer/pkg/types/openstack"
)

const (
	// TODO(flaper87): We're choosing to hardcode these values to make
	// the environment more predictable. We expect there to a secret
	// named `openstack-credentials` and a cloud named `openstack` in
	// the clouds file stored in this secret.
	cloudsSecret          = "openstack-credentials"
	cloudsSecretNamespace = "kube-system"

	// CloudName is a constant containing the name of the cloud used in the internal cloudsSecret
	CloudName = "openstack"
)

// Machines returns a list of machines for a machinepool.
func Machines(clusterID string, config *types.InstallConfig, pool *types.MachinePool, osImage, role, userDataSecret string) ([]machineapi.Machine, error) {
	if configPlatform := config.Platform.Name(); configPlatform != openstack.Name {
		return nil, fmt.Errorf("non-OpenStack configuration: %q", configPlatform)
	}
	if poolPlatform := pool.Platform.Name(); poolPlatform != openstack.Name {
		return nil, fmt.Errorf("non-OpenStack machine-pool: %q", poolPlatform)
	}
	platform := config.Platform.OpenStack
	mpool := pool.Platform.OpenStack

	total := int64(1)
	if pool.Replicas != nil {
		total = *pool.Replicas
	}
	var machines []machineapi.Machine
	for idx := int64(0); idx < total; idx++ {
		az := ""
		provider, err := provider(clusterID, platform, mpool, osImage, az, role, userDataSecret)
		if err != nil {
			return nil, errors.Wrap(err, "failed to create provider")
		}
		machine := machineapi.Machine{
			TypeMeta: metav1.TypeMeta{
				APIVersion: "machine.openshift.io/v1beta1",
				Kind:       "Machine",
			},
			ObjectMeta: metav1.ObjectMeta{
				Namespace: "openshift-machine-api",
				Name:      fmt.Sprintf("%s-%s-%d", clusterID, pool.Name, idx),
				Labels: map[string]string{
					"machine.openshift.io/cluster-api-cluster":      clusterID,
					"machine.openshift.io/cluster-api-machine-role": role,
					"machine.openshift.io/cluster-api-machine-type": role,
				},
			},
			Spec: machineapi.MachineSpec{
				ProviderSpec: machineapi.ProviderSpec{
					Value: &runtime.RawExtension{Object: provider},
				},
				// we don't need to set Versions, because we control those via operators.
			},
		}

		machines = append(machines, machine)
	}

	return machines, nil
}

func provider(clusterID string, platform *openstack.Platform, mpool *openstack.MachinePool, osImage string, az string, role, userDataSecret string) (*openstackprovider.OpenstackProviderSpec, error) {

	return &openstackprovider.OpenstackProviderSpec{
		TypeMeta: metav1.TypeMeta{
			APIVersion: "openstackproviderconfig.k8s.io/v1alpha1",
			Kind:       "OpenstackProviderSpec",
		},
		Flavor: mpool.FlavorName,
		/*RootVolume: openstackprovider.RootVolume{
			VolumeType: pointer.StringPtr(mpool.Type),
			Size:       pointer.Int64Ptr(int64(mpool.Size)),
		},*/
		Image:          osImage,
		CloudName:      CloudName,
		CloudsSecret:   &corev1.SecretReference{Name: cloudsSecret, Namespace: cloudsSecretNamespace},
		UserDataSecret: &corev1.SecretReference{Name: userDataSecret},
		Networks: []openstackprovider.NetworkParam{
			{
				Subnets: []openstackprovider.SubnetParam{
					{
						Filter: openstackprovider.SubnetFilter{
							Name: "nodes",
							Tags: fmt.Sprintf("%s=%s", "openshiftClusterID", clusterID),
						},
					},
				},
			},
		},
		AvailabilityZone: az,
		SecurityGroups:   []string{role},
		// TODO(flaper87): Trunk support missing. Need to add it back
	}, nil
}

// ConfigMasters sets the PublicIP flag and assigns a set of load balancers to the given machines
func ConfigMasters(machines []machineapi.Machine, clusterID string) {
	/*for _, machine := range machines {
		providerSpec := machine.Spec.ProviderSpec.Value.Object.(*openstackprovider.OpenstackProviderSpec)
	}*/
}
<commit_msg>openstack: Update security group management<commit_after>// Package openstack generates Machine objects for openstack.
package openstack

import (
	"fmt"

	machineapi "github.com/openshift/cluster-api/pkg/apis/machine/v1beta1"
	"github.com/pkg/errors"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	openstackprovider "sigs.k8s.io/cluster-api-provider-openstack/pkg/apis/openstackproviderconfig/v1alpha1"

	"github.com/openshift/installer/pkg/types"
	"github.com/openshift/installer/pkg/types/openstack"
)

const (
	// TODO(flaper87): We're choosing to hardcode these values to make
	// the environment more predictable. We expect there to a secret
	// named `openstack-credentials` and a cloud named `openstack` in
	// the clouds file stored in this secret.
	cloudsSecret          = "openstack-credentials"
	cloudsSecretNamespace = "kube-system"

	// CloudName is a constant containing the name of the cloud used in the internal cloudsSecret
	CloudName = "openstack"
)

// Machines returns a list of machines for a machinepool.
func Machines(clusterID string, config *types.InstallConfig, pool *types.MachinePool, osImage, role, userDataSecret string) ([]machineapi.Machine, error) {
	if configPlatform := config.Platform.Name(); configPlatform != openstack.Name {
		return nil, fmt.Errorf("non-OpenStack configuration: %q", configPlatform)
	}
	if poolPlatform := pool.Platform.Name(); poolPlatform != openstack.Name {
		return nil, fmt.Errorf("non-OpenStack machine-pool: %q", poolPlatform)
	}
	platform := config.Platform.OpenStack
	mpool := pool.Platform.OpenStack

	total := int64(1)
	if pool.Replicas != nil {
		total = *pool.Replicas
	}
	var machines []machineapi.Machine
	for idx := int64(0); idx < total; idx++ {
		az := ""
		provider, err := provider(clusterID, platform, mpool, osImage, az, role, userDataSecret)
		if err != nil {
			return nil, errors.Wrap(err, "failed to create provider")
		}
		machine := machineapi.Machine{
			TypeMeta: metav1.TypeMeta{
				APIVersion: "machine.openshift.io/v1beta1",
				Kind:       "Machine",
			},
			ObjectMeta: metav1.ObjectMeta{
				Namespace: "openshift-machine-api",
				Name:      fmt.Sprintf("%s-%s-%d", clusterID, pool.Name, idx),
				Labels: map[string]string{
					"machine.openshift.io/cluster-api-cluster":      clusterID,
					"machine.openshift.io/cluster-api-machine-role": role,
					"machine.openshift.io/cluster-api-machine-type": role,
				},
			},
			Spec: machineapi.MachineSpec{
				ProviderSpec: machineapi.ProviderSpec{
					Value: &runtime.RawExtension{Object: provider},
				},
				// we don't need to set Versions, because we control those via operators.
			},
		}

		machines = append(machines, machine)
	}

	return machines, nil
}

func provider(clusterID string, platform *openstack.Platform, mpool *openstack.MachinePool, osImage string, az string, role, userDataSecret string) (*openstackprovider.OpenstackProviderSpec, error) {

	return &openstackprovider.OpenstackProviderSpec{
		TypeMeta: metav1.TypeMeta{
			APIVersion: "openstackproviderconfig.k8s.io/v1alpha1",
			Kind:       "OpenstackProviderSpec",
		},
		Flavor: mpool.FlavorName,
		/*RootVolume: openstackprovider.RootVolume{
			VolumeType: pointer.StringPtr(mpool.Type),
			Size:       pointer.Int64Ptr(int64(mpool.Size)),
		},*/
		Image:          osImage,
		CloudName:      CloudName,
		CloudsSecret:   &corev1.SecretReference{Name: cloudsSecret, Namespace: cloudsSecretNamespace},
		UserDataSecret: &corev1.SecretReference{Name: userDataSecret},
		Networks: []openstackprovider.NetworkParam{
			{
				Subnets: []openstackprovider.SubnetParam{
					{
						Filter: openstackprovider.SubnetFilter{
							Name: "nodes",
							Tags: fmt.Sprintf("%s=%s", "openshiftClusterID", clusterID),
						},
					},
				},
			},
		},
		AvailabilityZone: az,
		SecurityGroups: []openstackprovider.SecurityGroupParam{
			{
				Name: role,
			},
		},
		// TODO(flaper87): Trunk support missing. Need to add it back
	}, nil
}

// ConfigMasters sets the PublicIP flag and assigns a set of load balancers to the given machines
func ConfigMasters(machines []machineapi.Machine, clusterID string) {
	/*for _, machine := range machines {
		providerSpec := machine.Spec.ProviderSpec.Value.Object.(*openstackprovider.OpenstackProviderSpec)
	}*/
}
<|endoftext|>


<commit_before>package home

import (
	"errors"
	"net/http"
	"net/url"
	"strconv"
	"time"

	"github.com/belogik/goes"
	"github.com/go-martini/martini"

	"github.com/firstrow/logvoyage/common"
	"github.com/firstrow/logvoyage/web/context"
	"github.com/firstrow/logvoyage/web/widgets"
)

const (
	timeLayout = "2006/01/02 15:04" // Users input time format
	perPage    = 100
)

type DateTimeRange struct {
	Start string
	Stop  string
}

func (this *DateTimeRange) IsValid() bool {
	return this.Start != "" || this.Stop != ""
}

// Represents search request to perform in ES
type SearchRequest struct {
	Text      string   // test to search
	Indexes   []string // ES indexeses to perform search
	Types     []string // search types
	Size      int      // home much objects ES must return
	From      int      // how much objects should ES skip from first
	TimeRange DateTimeRange
}

func buildSearchRequest(text string, indexes []string, types []string, size int, from int, datetime DateTimeRange) SearchRequest {
	return SearchRequest{
		Text:      text,
		Indexes:   indexes,
		From:      from,
		Types:     types,
		Size:      perPage,
		TimeRange: datetime,
	}
}

// Detects time range from request and returns
// elastic compatible format string
func buildTimeRange(req *http.Request) DateTimeRange {
	var timeRange DateTimeRange

	switch req.URL.Query().Get("time") {
	case "15m":
		timeRange.Start = "now-15m"
	case "30m":
		timeRange.Start = "now-30m"
	case "60m":
		timeRange.Start = "now-60m"
	case "12h":
		timeRange.Start = "now-12h"
	case "24h":
		timeRange.Start = "now-24h"
	case "week":
		timeRange.Start = "now-7d"
	case "custom":
		timeStart, err := time.Parse(timeLayout, req.URL.Query().Get("time_start"))
		if err == nil {
			timeRange.Start = timeStart.Format(time.RFC3339)
		}
		timeStop, err := time.Parse(timeLayout, req.URL.Query().Get("time_stop"))
		if err == nil {
			timeRange.Stop = timeStop.Format(time.RFC3339)
		}
	}

	return timeRange
}

// Search logs in elastic.
func search(searchRequest SearchRequest) (*goes.Response, error) {
	conn := common.GetConnection()

	var query = map[string]interface{}{
		"from": searchRequest.From,
		"size": searchRequest.Size,
		"sort": map[string]string{
			"datetime": "desc",
		},
	}

	if len(searchRequest.Text) > 0 {
		strconv.Quote(searchRequest.Text)
		query["query"] = map[string]interface{}{
			"query_string": map[string]string{
				"default_field": "message",
				"query":         searchRequest.Text,
			},
		}
	}

	// Build time range query
	if searchRequest.TimeRange.IsValid() {
		datetime := make(map[string]string)
		if searchRequest.TimeRange.Start != "" {
			datetime["gte"] = searchRequest.TimeRange.Start
		}
		if searchRequest.TimeRange.Stop != "" {
			datetime["lte"] = searchRequest.TimeRange.Stop
		}
		query["filter"] = map[string]interface{}{
			"range": map[string]interface{}{
				"datetime": datetime,
			},
		}
	}

	extraArgs := make(url.Values, 0)
	searchResults, err := conn.Search(query, searchRequest.Indexes, searchRequest.Types, extraArgs)

	if err != nil {
		return goes.Response{}, errors.New("No records found.")
	} else {
		return searchResults, nil
	}
}

// This function handles two routes "/" and "/project/:id"
func ProjectSearch(ctx *context.Context, params martini.Params) {
	var types []string
	var project *common.Project

	query_text := ctx.Request.URL.Query().Get("q")
	selected_types := ctx.Request.URL.Query()["types"]

	// Project scope
	if _, err := params["id"]; err {
		project, err := ctx.User.GetProject(params["id"])
		if err != nil {
			ctx.HTML("shared/error", context.ViewData{
				"message": "Project not found",
			})
			return
		}
		if len(project.Types) == 0 {
			ctx.HTML("home/empty_project", context.ViewData{
				"project": project,
			})
			return
		}
		if len(selected_types) > 0 {
			types = selected_types
		} else {
			types = project.Types
		}
	}

	// Pagination
	pagination := widgets.NewPagination(ctx.Request)
	pagination.SetPerPage(perPage)

	// Load records
	searchRequest := buildSearchRequest(
		query_text,
		[]string{ctx.User.GetIndexName()},
		types,
		pagination.GetPerPage(),
		pagination.DetectFrom(),
		buildTimeRange(ctx.Request),
	)
	// Search data in elastic
	data, _ := search(searchRequest)

	pagination.SetTotalRecords(data.Hits.Total)

	var viewName string
	viewData := context.ViewData{
		"project":    project,
		"logs":       data.Hits.Hits,
		"total":      data.Hits.Total,
		"took":       data.Took,
		"types":      types,
		"time":       ctx.Request.URL.Query().Get("time"),
		"time_start": ctx.Request.URL.Query().Get("time_start"),
		"time_stop":  ctx.Request.URL.Query().Get("time_stop"),
		"query_text": query_text,
		"pagination": pagination,
	}

	if ctx.Request.Header.Get("X-Requested-With") == "XMLHttpRequest" {
		viewName = "home/table"
	} else {
		viewName = "home/index"
	}

	ctx.HTML(viewName, viewData)
}
<commit_msg>return pointers<commit_after>package home

import (
	"errors"
	"net/http"
	"net/url"
	"strconv"
	"time"

	"github.com/belogik/goes"
	"github.com/go-martini/martini"

	"github.com/firstrow/logvoyage/common"
	"github.com/firstrow/logvoyage/web/context"
	"github.com/firstrow/logvoyage/web/widgets"
)

const (
	timeLayout = "2006/01/02 15:04" // Users input time format
	perPage    = 100
)

type DateTimeRange struct {
	Start string
	Stop  string
}

func (this *DateTimeRange) IsValid() bool {
	return this.Start != "" || this.Stop != ""
}

// Represents search request to perform in ES
type SearchRequest struct {
	Text      string   // test to search
	Indexes   []string // ES indexeses to perform search
	Types     []string // search types
	Size      int      // home much objects ES must return
	From      int      // how much objects should ES skip from first
	TimeRange DateTimeRange
}

func buildSearchRequest(text string, indexes []string, types []string, size int, from int, datetime DateTimeRange) SearchRequest {
	return SearchRequest{
		Text:      text,
		Indexes:   indexes,
		From:      from,
		Types:     types,
		Size:      perPage,
		TimeRange: datetime,
	}
}

// Detects time range from request and returns
// elastic compatible format string
func buildTimeRange(req *http.Request) DateTimeRange {
	var timeRange DateTimeRange

	switch req.URL.Query().Get("time") {
	case "15m":
		timeRange.Start = "now-15m"
	case "30m":
		timeRange.Start = "now-30m"
	case "60m":
		timeRange.Start = "now-60m"
	case "12h":
		timeRange.Start = "now-12h"
	case "24h":
		timeRange.Start = "now-24h"
	case "week":
		timeRange.Start = "now-7d"
	case "custom":
		timeStart, err := time.Parse(timeLayout, req.URL.Query().Get("time_start"))
		if err == nil {
			timeRange.Start = timeStart.Format(time.RFC3339)
		}
		timeStop, err := time.Parse(timeLayout, req.URL.Query().Get("time_stop"))
		if err == nil {
			timeRange.Stop = timeStop.Format(time.RFC3339)
		}
	}

	return timeRange
}

// Search logs in elastic.
func search(searchRequest SearchRequest) (goes.Response, error) {
	conn := common.GetConnection()

	var query = map[string]interface{}{
		"from": searchRequest.From,
		"size": searchRequest.Size,
		"sort": map[string]string{
			"datetime": "desc",
		},
	}

	if len(searchRequest.Text) > 0 {
		strconv.Quote(searchRequest.Text)
		query["query"] = map[string]interface{}{
			"query_string": map[string]string{
				"default_field": "message",
				"query":         searchRequest.Text,
			},
		}
	}

	// Build time range query
	if searchRequest.TimeRange.IsValid() {
		datetime := make(map[string]string)
		if searchRequest.TimeRange.Start != "" {
			datetime["gte"] = searchRequest.TimeRange.Start
		}
		if searchRequest.TimeRange.Stop != "" {
			datetime["lte"] = searchRequest.TimeRange.Stop
		}
		query["filter"] = map[string]interface{}{
			"range": map[string]interface{}{
				"datetime": datetime,
			},
		}
	}

	extraArgs := make(url.Values, 0)
	searchResults, err := conn.Search(query, searchRequest.Indexes, searchRequest.Types, extraArgs)

	if err != nil {
		return &goes.Response{}, errors.New("No records found.")
	} else {
		return &searchResults, nil
	}
}

// This function handles two routes "/" and "/project/:id"
func ProjectSearch(ctx *context.Context, params martini.Params) {
	var types []string
	var project *common.Project

	query_text := ctx.Request.URL.Query().Get("q")
	selected_types := ctx.Request.URL.Query()["types"]

	// Project scope
	if _, err := params["id"]; err {
		project, err := ctx.User.GetProject(params["id"])
		if err != nil {
			ctx.HTML("shared/error", context.ViewData{
				"message": "Project not found",
			})
			return
		}
		if len(project.Types) == 0 {
			ctx.HTML("home/empty_project", context.ViewData{
				"project": project,
			})
			return
		}
		if len(selected_types) > 0 {
			types = selected_types
		} else {
			types = project.Types
		}
	}

	// Pagination
	pagination := widgets.NewPagination(ctx.Request)
	pagination.SetPerPage(perPage)

	// Load records
	searchRequest := buildSearchRequest(
		query_text,
		[]string{ctx.User.GetIndexName()},
		types,
		pagination.GetPerPage(),
		pagination.DetectFrom(),
		buildTimeRange(ctx.Request),
	)
	// Search data in elastic
	data, _ := search(searchRequest)

	pagination.SetTotalRecords(data.Hits.Total)

	var viewName string
	viewData := context.ViewData{
		"project":    project,
		"logs":       data.Hits.Hits,
		"total":      data.Hits.Total,
		"took":       data.Took,
		"types":      types,
		"time":       ctx.Request.URL.Query().Get("time"),
		"time_start": ctx.Request.URL.Query().Get("time_start"),
		"time_stop":  ctx.Request.URL.Query().Get("time_stop"),
		"query_text": query_text,
		"pagination": pagination,
	}

	if ctx.Request.Header.Get("X-Requested-With") == "XMLHttpRequest" {
		viewName = "home/table"
	} else {
		viewName = "home/index"
	}

	ctx.HTML(viewName, viewData)
}
<|endoftext|>