<commit_before>package timer

import (
	"sync"
	"testing"
	"time"
)

func TestNullTimout(t *testing.T) {
	// Timeout for 0 seconds.
	start := time.Now()
	timer := NewTimer(0)
	<-timer.C
	if int(time.Since(start).Seconds()) != 0 {
		t.Errorf("took ~%v seconds, should be ~0 seconds\n", int(time.Since(start).Seconds()))
	}
}

func TestNegativeTimout(t *testing.T) {
	// Timeout for -1 seconds.
	start := time.Now()
	timer := NewTimer(-1)
	<-timer.C
	if int(time.Since(start).Seconds()) != 0 {
		t.Errorf("took ~%v seconds, should be ~0 seconds\n", int(time.Since(start).Seconds()))
	}

	// Timeout for -100 seconds.
	start = time.Now()
	timer = NewTimer(-100 * time.Second)
	<-timer.C
	if int(time.Since(start).Seconds()) != 0 {
		t.Errorf("took ~%v seconds, should be ~0 seconds\n", int(time.Since(start).Seconds()))
	}
}

func TestOverflowTimout(t *testing.T) {
	timer := NewTimer(1<<63 - 1)
	defer timer.Stop()
	if timer.when != 1<<63-1 {
		t.Errorf("overflow: invalid max value")
	}
}

func TestTimeValue(t *testing.T) {
	// Timeout for 0 seconds.
	start := time.Now()
	timer := NewTimer(time.Second)
	v := <-timer.C
	if diff := v.Sub(start).Seconds(); int(diff) != 1 {
		t.Errorf("invalid time value: %v", int(diff))
	}
}

func TestSingleTimout(t *testing.T) {
	// Timeout for 1 second and wait.
	start := time.Now()
	timer := NewTimer(time.Second)
	<-timer.C
	if int(time.Since(start).Seconds()) != 1 {
		t.Errorf("took ~%v seconds, should be ~1 seconds\n", int(time.Since(start).Seconds()))
	}
}

func TestMultipleTimouts(t *testing.T) {
	start := time.Now()
	var timers []*Timer

	for i := 0; i < 1000; i++ {
		timers = append(timers, NewTimer(time.Second))
	}

	// Wait for them all to expire.
	for _, timer := range timers {
		<-timer.C
	}

	if int(time.Since(start).Seconds()) != 1 {
		t.Errorf("took ~%v seconds, should be ~1 seconds\n", int(time.Since(start).Seconds()))
	}
}

func TestMultipleDifferentTimouts(t *testing.T) {
	start := time.Now()
	var timers []*Timer

	for i := 0; i < 1000; i++ {
		timers = append(timers, NewTimer(time.Duration(i%4)*time.Second))
	}

	// Wait for them all to expire.
	for _, timer := range timers {
		<-timer.C
	}

	if int(time.Since(start).Seconds()) != 3 {
		t.Errorf("took ~%v seconds, should be ~3 seconds\n", int(time.Since(start).Seconds()))
	}
}

func TestStoppedTimer(t *testing.T) {
	timer := NewStoppedTimer()
	if timer.when != 0 {
		t.Errorf("invalid stopped timer when value")
	}

	start := time.Now()
	wasActive := timer.Reset(time.Second)
	if wasActive {
		t.Errorf("stopped timer: was active is true")
	}

	<-timer.C
	if int(time.Since(start).Seconds()) != 1 {
		t.Errorf("took ~%v seconds, should be ~1 seconds\n", int(time.Since(start).Seconds()))
	}
}

func TestStop(t *testing.T) {
	timer := NewTimer(time.Second)
	wasActive := timer.Stop()
	if !wasActive {
		t.Errorf("stop timer: was active is false")
	}

	select {
	case <-timer.C:
		t.Errorf("failed to stop timer")
	case <-time.After(2 * time.Second):
	}

	wasActive = timer.Stop()
	if wasActive {
		t.Errorf("stop timer: was active is true")
	}
}

func TestStopPanic(t *testing.T) {
	defer func() {
		r := recover()
		if r == nil || r.(string) != "timer: Stop called on uninitialized Timer" {
			t.Errorf("stop timer: invalid stop panic")
		}
	}()

	timer := &Timer{}
	timer.Stop()
}

func TestMultipleStop(t *testing.T) {
	var timers []*Timer

	for i := 0; i < 1000; i++ {
		timer := NewTimer(time.Second)
		wasActive := timer.Stop()
		if !wasActive {
			t.Errorf("stop timer: was active is false")
		}

		timers = append(timers, timer)
	}

	time.Sleep(2 * time.Second)

	// All channels must block.
	for _, timer := range timers {
		select {
		case <-timer.C:
			t.Errorf("failed to stop timer")
		default:
		}
	}

	for _, timer := range timers {
		wasActive := timer.Stop()
		if wasActive {
			t.Errorf("stop timer: was active is true")
		}
	}
}

func TestReset(t *testing.T) {
	start := time.Now()
	timer := NewTimer(time.Second)
	wasActive := timer.Reset(2 * time.Second)
	if !wasActive {
		t.Errorf("reset timer: was active is false")
	}

	<-timer.C

	if int(time.Since(start).Seconds()) != 2 {
		t.Errorf("took ~%v seconds, should be ~2 seconds\n", int(time.Since(start).Seconds()))
	}

	start = time.Now()
	wasActive = timer.Reset(time.Second)
	if wasActive {
		t.Errorf("reset timer: was active is true")
	}

	<-timer.C

	if int(time.Since(start).Seconds()) != 1 {
		t.Errorf("took ~%v seconds, should be ~1 seconds\n", int(time.Since(start).Seconds()))
	}
}

func TestNegativeReset(t *testing.T) {
	// Timeout for -1 seconds.
	start := time.Now()
	timer := NewTimer(time.Second)
	timer.Reset(-1)
	<-timer.C
	if int(time.Since(start).Seconds()) != 0 {
		t.Errorf("took ~%v seconds, should be ~0 seconds\n", int(time.Since(start).Seconds()))
	}

	// Timeout for -100 seconds.
	start = time.Now()
	timer = NewTimer(time.Second)
	timer.Reset(-100 * time.Second)
	<-timer.C
	if int(time.Since(start).Seconds()) != 0 {
		t.Errorf("took ~%v seconds, should be ~0 seconds\n", int(time.Since(start).Seconds()))
	}
}

func TestOverflowReset(t *testing.T) {
	timer := NewTimer(time.Second)
	timer.Reset(1<<63 - 1)
	defer timer.Stop()
	if timer.when != 1<<63-1 {
		t.Errorf("overflow: invalid max value")
	}
}

func TestMultipleResets(t *testing.T) {
	start := time.Now()
	var timers []*Timer

	for i := 0; i < 1000; i++ {
		timer := NewTimer(time.Second)
		timers = append(timers, timer)
		timer.Reset(2 * time.Second)
	}

	// Wait for them all to expire.
	for _, timer := range timers {
		<-timer.C
	}

	if int(time.Since(start).Seconds()) != 2 {
		t.Errorf("took ~%v seconds, should be ~2 seconds\n", int(time.Since(start).Seconds()))
	}
}

func TestMultipleZeroResets(t *testing.T) {
	start := time.Now()
	var timers []*Timer

	for i := 0; i < 1000; i++ {
		timer := NewTimer(time.Second)
		timers = append(timers, timer)
		timer.Reset(0)
	}

	// Wait for them all to expire.
	for _, timer := range timers {
		<-timer.C
	}

	if int(time.Since(start).Seconds()) != 0 {
		t.Errorf("took ~%v seconds, should be ~0 seconds\n", int(time.Since(start).Seconds()))
	}
}

func TestResetChannelClear(t *testing.T) {
	timer := NewTimer(0)
	time.Sleep(time.Second)

	if len(timer.C) != 1 {
		t.Errorf("reset timer: channel should be filled")
	}

	wasActive := timer.Reset(2 * time.Second)
	if wasActive {
		t.Errorf("reset timer: was active is true")
	}

	if len(timer.C) != 0 {
		t.Errorf("reset timer: channel should be empty")
	}

	start := time.Now()
	<-timer.C

	if int(time.Since(start).Seconds()) != 2 {
		t.Errorf("took ~%v seconds, should be ~2 seconds\n", int(time.Since(start).Seconds()))
	}
}

func TestResetPanic(t *testing.T) {
	defer func() {
		r := recover()
		if r == nil || r.(string) != "timer: Reset called on uninitialized Timer" {
			t.Errorf("reset timer: invalid reset panic")
		}
	}()

	timer := &Timer{}
	timer.Reset(0)
}

func TestResetBehavior(t *testing.T) {
	start := time.Now()

	// Start a new timer with a timeout of 1 second.
	timer := NewTimer(1 * time.Second)

	// Wait for 2 seconds.
	// Meanwhile the timer fired filled the channel.
	time.Sleep(2 * time.Second)

	// Reset the timer. This should act exactly as creating a new timer.
	timer.Reset(1 * time.Second)

	// However this will fire immediately, because the channel was not drained.
	// See issue: https://github.com/golang/go/issues/11513
	<-timer.C

	if int(time.Since(start).Seconds()) != 3 {
		t.Errorf("took ~%v seconds, should be ~3 seconds\n", int(time.Since(start).Seconds()))
	}
}

func TestAfterFunc(t *testing.T) {
	start := time.Now()

	var wg sync.WaitGroup
	wg.Add(1)

	AfterFunc(time.Second, func() {
		wg.Done()
	})

	wg.Wait()

	if int(time.Since(start).Seconds()) != 1 {
		t.Errorf("took ~%v seconds, should be ~1 seconds\n", int(time.Since(start).Seconds()))
	}
}

func TestAfterFuncReset(t *testing.T) {
	start := time.Now()

	var wg sync.WaitGroup
	wg.Add(1)

	timer := AfterFunc(time.Second, func() {
		wg.Done()
	})
	timer.Reset(2 * time.Second)

	wg.Wait()

	if int(time.Since(start).Seconds()) != 2 {
		t.Errorf("took ~%v seconds, should be ~2 seconds\n", int(time.Since(start).Seconds()))
	}
}

func TestAfterFuncStop(t *testing.T) {
	start := time.Now()

	var wg sync.WaitGroup
	wg.Add(1)

	go func() {
		time.Sleep(2 * time.Second)
		wg.Done()
	}()

	timer := AfterFunc(time.Second, func() {
		wg.Done()
	})
	timer.Stop()

	wg.Wait()

	if int(time.Since(start).Seconds()) != 2 {
		t.Errorf("took ~%v seconds, should be ~2 seconds\n", int(time.Since(start).Seconds()))
	}
}
<commit_msg>Added another test<commit_after>package timer

import (
	"sync"
	"testing"
	"time"
)

func TestNullTimout(t *testing.T) {
	// Timeout for 0 seconds.
	start := time.Now()
	timer := NewTimer(0)
	<-timer.C
	if int(time.Since(start).Seconds()) != 0 {
		t.Errorf("took ~%v seconds, should be ~0 seconds\n", int(time.Since(start).Seconds()))
	}
}

func TestNegativeTimout(t *testing.T) {
	// Timeout for -1 seconds.
	start := time.Now()
	timer := NewTimer(-1)
	<-timer.C
	if int(time.Since(start).Seconds()) != 0 {
		t.Errorf("took ~%v seconds, should be ~0 seconds\n", int(time.Since(start).Seconds()))
	}

	// Timeout for -100 seconds.
	start = time.Now()
	timer = NewTimer(-100 * time.Second)
	<-timer.C
	if int(time.Since(start).Seconds()) != 0 {
		t.Errorf("took ~%v seconds, should be ~0 seconds\n", int(time.Since(start).Seconds()))
	}
}

func TestOverflowTimout(t *testing.T) {
	timer := NewTimer(1<<63 - 1)
	defer timer.Stop()
	if timer.when != 1<<63-1 {
		t.Errorf("overflow: invalid max value")
	}
}

func TestTimeValue(t *testing.T) {
	// Timeout for 0 seconds.
	start := time.Now()
	timer := NewTimer(time.Second)
	v := <-timer.C
	if diff := v.Sub(start).Seconds(); int(diff) != 1 {
		t.Errorf("invalid time value: %v", int(diff))
	}
}

func TestSingleTimout(t *testing.T) {
	// Timeout for 1 second and wait.
	start := time.Now()
	timer := NewTimer(time.Second)
	<-timer.C
	if int(time.Since(start).Seconds()) != 1 {
		t.Errorf("took ~%v seconds, should be ~1 seconds\n", int(time.Since(start).Seconds()))
	}
}

func TestMultipleTimouts(t *testing.T) {
	start := time.Now()
	var timers []*Timer

	for i := 0; i < 1000; i++ {
		timers = append(timers, NewTimer(time.Second))
	}

	// Wait for them all to expire.
	for _, timer := range timers {
		<-timer.C
	}

	if int(time.Since(start).Seconds()) != 1 {
		t.Errorf("took ~%v seconds, should be ~1 seconds\n", int(time.Since(start).Seconds()))
	}
}

func TestMultipleDifferentTimouts(t *testing.T) {
	start := time.Now()
	var timers []*Timer

	for i := 0; i < 1000; i++ {
		timers = append(timers, NewTimer(time.Duration(i%4)*time.Second))
	}

	// Wait for them all to expire.
	for _, timer := range timers {
		<-timer.C
	}

	if int(time.Since(start).Seconds()) != 3 {
		t.Errorf("took ~%v seconds, should be ~3 seconds\n", int(time.Since(start).Seconds()))
	}
}

func TestStoppedTimer(t *testing.T) {
	timer := NewStoppedTimer()
	if timer.when != 0 {
		t.Errorf("invalid stopped timer when value")
	}

	start := time.Now()
	wasActive := timer.Reset(time.Second)
	if wasActive {
		t.Errorf("stopped timer: was active is true")
	}

	<-timer.C
	if int(time.Since(start).Seconds()) != 1 {
		t.Errorf("took ~%v seconds, should be ~1 seconds\n", int(time.Since(start).Seconds()))
	}
}

func TestStop(t *testing.T) {
	timer := NewTimer(time.Second)
	wasActive := timer.Stop()
	if !wasActive {
		t.Errorf("stop timer: was active is false")
	}

	select {
	case <-timer.C:
		t.Errorf("failed to stop timer")
	case <-time.After(2 * time.Second):
	}

	wasActive = timer.Stop()
	if wasActive {
		t.Errorf("stop timer: was active is true")
	}
}

func TestStopPanic(t *testing.T) {
	defer func() {
		r := recover()
		if r == nil || r.(string) != "timer: Stop called on uninitialized Timer" {
			t.Errorf("stop timer: invalid stop panic")
		}
	}()

	timer := &Timer{}
	timer.Stop()
}

func TestMultipleStop(t *testing.T) {
	var timers []*Timer

	for i := 0; i < 1000; i++ {
		timer := NewTimer(time.Second)
		wasActive := timer.Stop()
		if !wasActive {
			t.Errorf("stop timer: was active is false")
		}

		timers = append(timers, timer)
	}

	time.Sleep(2 * time.Second)

	// All channels must block.
	for _, timer := range timers {
		select {
		case <-timer.C:
			t.Errorf("failed to stop timer")
		default:
		}
	}

	for _, timer := range timers {
		wasActive := timer.Stop()
		if wasActive {
			t.Errorf("stop timer: was active is true")
		}
	}
}

func TestReset(t *testing.T) {
	start := time.Now()
	timer := NewTimer(time.Second)
	wasActive := timer.Reset(2 * time.Second)
	if !wasActive {
		t.Errorf("reset timer: was active is false")
	}

	<-timer.C

	if int(time.Since(start).Seconds()) != 2 {
		t.Errorf("took ~%v seconds, should be ~2 seconds\n", int(time.Since(start).Seconds()))
	}

	start = time.Now()
	wasActive = timer.Reset(time.Second)
	if wasActive {
		t.Errorf("reset timer: was active is true")
	}

	<-timer.C

	if int(time.Since(start).Seconds()) != 1 {
		t.Errorf("took ~%v seconds, should be ~1 seconds\n", int(time.Since(start).Seconds()))
	}
}

func TestNegativeReset(t *testing.T) {
	// Timeout for -1 seconds.
	start := time.Now()
	timer := NewTimer(time.Second)
	timer.Reset(-1)
	<-timer.C
	if int(time.Since(start).Seconds()) != 0 {
		t.Errorf("took ~%v seconds, should be ~0 seconds\n", int(time.Since(start).Seconds()))
	}

	// Timeout for -100 seconds.
	start = time.Now()
	timer = NewTimer(time.Second)
	timer.Reset(-100 * time.Second)
	<-timer.C
	if int(time.Since(start).Seconds()) != 0 {
		t.Errorf("took ~%v seconds, should be ~0 seconds\n", int(time.Since(start).Seconds()))
	}
}

func TestOverflowReset(t *testing.T) {
	timer := NewTimer(time.Second)
	timer.Reset(1<<63 - 1)
	defer timer.Stop()
	if timer.when != 1<<63-1 {
		t.Errorf("overflow: invalid max value")
	}
}

func TestMultipleResets(t *testing.T) {
	start := time.Now()
	var timers []*Timer

	for i := 0; i < 1000; i++ {
		timer := NewTimer(time.Second)
		timers = append(timers, timer)
		timer.Reset(2 * time.Second)
	}

	// Wait for them all to expire.
	for _, timer := range timers {
		<-timer.C
	}

	if int(time.Since(start).Seconds()) != 2 {
		t.Errorf("took ~%v seconds, should be ~2 seconds\n", int(time.Since(start).Seconds()))
	}
}

func TestMultipleZeroResets(t *testing.T) {
	start := time.Now()
	var timers []*Timer

	for i := 0; i < 1000; i++ {
		timer := NewTimer(time.Second)
		timers = append(timers, timer)
		timer.Reset(0)
	}

	// Wait for them all to expire.
	for _, timer := range timers {
		<-timer.C
	}

	if int(time.Since(start).Seconds()) != 0 {
		t.Errorf("took ~%v seconds, should be ~0 seconds\n", int(time.Since(start).Seconds()))
	}
}

func TestResetChannelClear(t *testing.T) {
	timer := NewTimer(0)
	time.Sleep(time.Second)

	if len(timer.C) != 1 {
		t.Errorf("reset timer: channel should be filled")
	}

	wasActive := timer.Reset(2 * time.Second)
	if wasActive {
		t.Errorf("reset timer: was active is true")
	}

	if len(timer.C) != 0 {
		t.Errorf("reset timer: channel should be empty")
	}

	start := time.Now()
	<-timer.C

	if int(time.Since(start).Seconds()) != 2 {
		t.Errorf("took ~%v seconds, should be ~2 seconds\n", int(time.Since(start).Seconds()))
	}
}

func TestResetPanic(t *testing.T) {
	defer func() {
		r := recover()
		if r == nil || r.(string) != "timer: Reset called on uninitialized Timer" {
			t.Errorf("reset timer: invalid reset panic")
		}
	}()

	timer := &Timer{}
	timer.Reset(0)
}

func TestResetBehavior(t *testing.T) {
	start := time.Now()

	// Start a new timer with a timeout of 1 second.
	timer := NewTimer(1 * time.Second)

	// Wait for 2 seconds.
	// Meanwhile the timer fired filled the channel.
	time.Sleep(2 * time.Second)

	// Reset the timer. This should act exactly as creating a new timer.
	timer.Reset(1 * time.Second)

	// However this will fire immediately, because the channel was not drained.
	// See issue: https://github.com/golang/go/issues/11513
	<-timer.C

	if int(time.Since(start).Seconds()) != 3 {
		t.Errorf("took ~%v seconds, should be ~3 seconds\n", int(time.Since(start).Seconds()))
	}
}

func TestAfterFunc(t *testing.T) {
	start := time.Now()

	var wg sync.WaitGroup
	wg.Add(1)

	AfterFunc(time.Second, func() {
		wg.Done()
	})

	wg.Wait()

	if int(time.Since(start).Seconds()) != 1 {
		t.Errorf("took ~%v seconds, should be ~1 seconds\n", int(time.Since(start).Seconds()))
	}
}

func TestAfterFuncReset(t *testing.T) {
	start := time.Now()

	var wg sync.WaitGroup
	wg.Add(1)

	timer := AfterFunc(time.Second, func() {
		wg.Done()
	})
	timer.Reset(2 * time.Second)

	wg.Wait()

	if int(time.Since(start).Seconds()) != 2 {
		t.Errorf("took ~%v seconds, should be ~2 seconds\n", int(time.Since(start).Seconds()))
	}
}

func TestAfterFuncStop(t *testing.T) {
	start := time.Now()

	var wg sync.WaitGroup
	wg.Add(1)

	go func() {
		time.Sleep(2 * time.Second)
		wg.Done()
	}()

	timer := AfterFunc(time.Second, func() {
		wg.Done()
	})
	timer.Stop()

	wg.Wait()

	if int(time.Since(start).Seconds()) != 2 {
		t.Errorf("took ~%v seconds, should be ~2 seconds\n", int(time.Since(start).Seconds()))
	}
}

func TestMultipleTimersForValidTimeouts(t *testing.T) {
	var wg sync.WaitGroup

	for i := 0; i < 1000; i++ {
		dur := time.Duration(i%11) * time.Second
		start := time.Now()
		timer := NewTimer(dur)
		wg.Add(1)
		go func() {
			dur /= time.Second
			<-timer.C
			if int(time.Since(start).Seconds()) != int(dur) {
				t.Errorf("took ~%v seconds, should be ~%v seconds\n", int(time.Since(start).Seconds()), int(dur))
			}
			wg.Done()
		}()
	}

	wg.Wait()
}
<|endoftext|>


<commit_before>	package geo_skeleton

import "github.com/sjsafranek/DiffDB/diff_store"
import "github.com/sjsafranek/SkeletonDB"
// import "github.com/sjsafranek/DiffDB/diff_db"

var GeoTsDB GeoTimeseriesDB

func init() {
	GeoTsDB = GeoTimeseriesDB{}
	GeoTsDB.Init()
}

type GeoTimeseriesDB struct {
	File string
	Table    string
	DB       skeleton.Database
}

func (self GeoTimeseriesDB) Init() {

	self.DB = skeleton.Database{File: self.getFile()}
	self.DB.Init()

	conn := self.DB.Connect()
	defer conn.Close()

	err := self.DB.CreateTable(conn, self.getTable())
	if nil != err {
		panic(err)
	}
}

func (self GeoTimeseriesDB) getFile() {
	if "" == self.File {
		return "geo_ts.db"
	}
	return self.File
}

func (self GeoTimeseriesDB) getTable() {
	if "" == self.Table {
		return "GeoTimeseriesData"
	}
	return self.Table
}

func (self GeoTimeseriesDB) Select(datasource_id) ([]byte, error) {
	data, err := self.DB.Select(self.getTable, datasource_id)
	return data, err
}

func update_timeseries_datasource(datasource_id string, value []byte) {

	update_value := string(value)
	var ddata diff_store.DiffStore
	data, err := GeoTsDB.Select(datasource_id)
	if nil != err {
		if err.Error() == "Not found" {
			// create new diffstore if key not found in database
			ddata = diff_store.NewDiffStore(datasource_id)
		} else {
			panic(err)
		}
	} else {
		ddata.Decode(data)
	}

	// update diffstore
	ddata.Update(update_value)

	// save to database
	enc, err := ddata.Encode()
	if nil != err {
		panic(err)
	}

	ddata.Name = datasource_id
	err = GeoTsDB.Save(string(ddata.Name), enc)

}
<commit_msg>fixed geots<commit_after>	package geo_skeleton

import "github.com/sjsafranek/DiffDB/diff_store"
import "github.com/sjsafranek/SkeletonDB"
// import "github.com/sjsafranek/DiffDB/diff_db"

var GeoTsDB GeoTimeseriesDB

func init() {
	GeoTsDB = GeoTimeseriesDB{}
	GeoTsDB.Init()
}

type GeoTimeseriesDB struct {
	File string
	Table    string
	DB       skeleton.Database
}

func (self GeoTimeseriesDB) Init() {

	self.DB = skeleton.Database{File: self.getFile()}
	self.DB.Init()

	conn := self.DB.Connect()
	defer conn.Close()

	err := self.DB.CreateTable(conn, self.getTable())
	if nil != err {
		panic(err)
	}
}

func (self GeoTimeseriesDB) getFile() string {
	if "" == self.File {
		return "geo_ts.db"
	}
	return self.File
}

func (self GeoTimeseriesDB) getTable() string {
	if "" == self.Table {
		return "GeoTimeseriesData"
	}
	return self.Table
}

func (self GeoTimeseriesDB) Insert(datasource_id string, enc []byte) ([]byte, error) {
	data, err := self.DB.Insert(self.getTable(), datasource_id, enc)
	return data, err
}

func (self GeoTimeseriesDB) Select(datasource_id string) ([]byte, error) {
	data, err := self.DB.Select(self.getTable(), datasource_id)
	return data, err
}

func update_timeseries_datasource(datasource_id string, value []byte) {

	update_value := string(value)
	var ddata diff_store.DiffStore
	data, err := GeoTsDB.Select(datasource_id)
	if nil != err {
		if err.Error() == "Not found" {
			// create new diffstore if key not found in database
			ddata = diff_store.NewDiffStore(datasource_id)
		} else {
			panic(err)
		}
	} else {
		ddata.Decode(data)
	}

	// update diffstore
	ddata.Update(update_value)

	// save to database
	enc, err := ddata.Encode()
	if nil != err {
		panic(err)
	}

	ddata.Name = datasource_id
	err = GeoTsDB.Insert(string(ddata.Name), enc)

}
<|endoftext|>


<commit_before>package ohauth

import (
	"fmt"

	"github.com/dgrijalva/jwt-go"
	"github.com/mitchellh/mapstructure"
)

type Tokenizer interface {
	Tokenize(tc *TokenClaims, signingKey []byte) (string, error)
	Parse(token string, verifyKey []byte) (*TokenClaims, error)
}

type jwtTokenizer struct {
	method jwt.SigningMethod
}

func NewJWTTokenizer(signingMethod jwt.SigningMethod) Tokenizer {
	return &jwtTokenizer{signingMethod}
}

func (t *jwtTokenizer) Tokenize(tc *TokenClaims, signingKey []byte) (string, error) {
	if tc.Expires == 0 {
		return "", fmt.Errorf("Token expiry not set")
	}

	token := jwt.New(t.method)
	token.Claims = tc.Map()
	return token.SignedString(signingKey)
}

func (t *jwtTokenizer) Parse(raw string, verifyKey []byte) (*TokenClaims, error) {
	if t.method == nil {
		return nil, fmt.Errorf("No signing method specified")
	}
	token, err := jwt.Parse(raw, func(token *jwt.Token) (interface{}, error) {
		if token.Method.Alg() != t.method.Alg() {
			return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
		}
		return verifyKey, nil
	})
	if err != nil {
		return nil, err
	}
	if !token.Valid {
		return nil, nil
	}

	tc := &TokenClaims{}

	err = mapstructure.Decode(token.Claims, tc)
	if err != nil {
		return nil, err
	}

	return tc, nil
}
<commit_msg>fixed mapping of string scope to *Scope<commit_after>package ohauth

import (
	"fmt"
	"reflect"

	"github.com/dgrijalva/jwt-go"
	"github.com/mitchellh/mapstructure"
)

type Tokenizer interface {
	Tokenize(tc *TokenClaims, signingKey []byte) (string, error)
	Parse(token string, verifyKey []byte) (*TokenClaims, error)
}

type jwtTokenizer struct {
	method jwt.SigningMethod
}

func NewJWTTokenizer(signingMethod jwt.SigningMethod) Tokenizer {
	return &jwtTokenizer{signingMethod}
}

func (t *jwtTokenizer) Tokenize(tc *TokenClaims, signingKey []byte) (string, error) {
	if tc.Expires == 0 {
		return "", fmt.Errorf("Token expiry not set")
	}

	token := jwt.New(t.method)
	token.Claims = tc.Map()
	return token.SignedString(signingKey)
}

func (t *jwtTokenizer) Parse(raw string, verifyKey []byte) (*TokenClaims, error) {
	if t.method == nil {
		return nil, fmt.Errorf("No signing method specified")
	}
	token, err := jwt.Parse(raw, func(token *jwt.Token) (interface{}, error) {
		if token.Method.Alg() != t.method.Alg() {
			return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
		}
		return verifyKey, nil
	})
	if err != nil {
		return nil, err
	}

	tc := &TokenClaims{}

	d, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
		Result:  tc,
		TagName: "json",
		DecodeHook: func(from, to reflect.Type, data interface{}) (interface{}, error) {
			if from.Kind() == reflect.String && to.Kind() == reflect.TypeOf(tc.Scope).Kind() {
				return ParseScope(data.(string)), nil
			}
			return data, nil
		},
	})
	if err != nil {
		return nil, err
	}
	err = d.Decode(token.Claims)
	if err != nil {
		return nil, err
	}

	return tc, nil
}
<|endoftext|>


<commit_before>package controllers

import (
	"github.com/vincent3i/beego-blog/models"
	"github.com/vincent3i/beego-blog/models/blog"
	"github.com/vincent3i/beego-blog/models/catalog"
)

type ArticleController struct {
	AdminController
}

func (this *ArticleController) Draft() {
	var blogs []*models.Blog
	blog.Blogs().Filter("Status", 0).All(&blogs)
	this.Data["Blogs"] = blogs
	this.Layout = "layout/admin.html"
	this.TplNames = "article/draft.html"
}

func (this *ArticleController) Add() {
	this.Data["Catalogs"] = catalog.All()
	this.Data["IsPost"] = true
	this.Layout = "layout/admin.html"
	this.TplNames = "article/add.html"
	this.JsStorage("deleteKey", "post/new")
}

func (this *ArticleController) DoAdd() {
	title := this.GetString("title")
	ident := this.GetString("ident")
	keywords := this.GetString("keywords")
	catalog_id := this.GetIntWithDefault("catalog_id", -1)
	aType := this.GetIntWithDefault("type", -1)
	status := this.GetIntWithDefault("status", -1)
	content := this.GetString("content")

	if catalog_id == -1 || aType == -1 || status == -1 {
		this.Ctx.WriteString("catalog || type || status is illegal")
		return
	}

	if title == "" || ident == "" {
		this.Ctx.WriteString("title or ident is blank")
		return
	}

	cp := catalog.OneById(int64(catalog_id))
	if cp == nil {
		this.Ctx.WriteString("catalog_id not exists")
		return
	}

	b := &models.Blog{Ident: ident, Title: title, Keywords: keywords, CatalogId: int64(catalog_id), Type: int8(aType), Status: int8(status)}
	_, err := blog.Save(b, content)

	if err != nil {
		this.Ctx.WriteString(err.Error())
		return
	}

	this.JsStorage("deleteKey", "post/new")
	this.Redirect("/catalog/"+cp.Ident, 302)

}

func (this *ArticleController) Edit() {
	id, err := this.GetInt64("id")
	if err != nil {
		this.Ctx.WriteString("get param id fail")
		return
	}

	b := blog.OneById(id)
	if b == nil {
		this.Ctx.WriteString("no such article")
		return
	}

	this.Data["Content"] = blog.ReadBlogContent(b).Content
	this.Data["Blog"] = b
	this.Data["Catalogs"] = catalog.All()
	this.Layout = "layout/admin.html"
	this.TplNames = "article/edit.html"
}

func (this *ArticleController) DoEdit() {
	id, err := this.GetInt64("id")
	if err != nil {
		this.Ctx.WriteString("get param id fail")
		return
	}

	b := blog.OneById(id)
	if b == nil {
		this.Ctx.WriteString("no such article")
		return
	}

	title := this.GetString("title")
	ident := this.GetString("ident")
	keywords := this.GetString("keywords")
	catalog_id := this.GetIntWithDefault("catalog_id", -1)
	aType := this.GetIntWithDefault("type", -1)
	status := this.GetIntWithDefault("status", -1)
	content := this.GetString("content")

	if catalog_id == -1 || aType == -1 || status == -1 {
		this.Ctx.WriteString("catalog || type || status is illegal")
		return
	}

	if title == "" || ident == "" {
		this.Ctx.WriteString("title or ident is blank")
		return
	}

	cp := catalog.OneById(int64(catalog_id))
	if cp == nil {
		this.Ctx.WriteString("catalog_id not exists")
		return
	}

	b.Ident = ident
	b.Title = title
	b.Keywords = keywords
	b.CatalogId = int64(catalog_id)
	b.Type = int8(aType)
	b.Status = int8(status)

	err = blog.Update(b, content)

	if err != nil {
		this.Ctx.WriteString(err.Error())
		return
	}

	this.JsStorage("deleteKey", "post/edit")
	this.Redirect("/catalog/"+cp.Ident, 302)
}

func (this *ArticleController) Del() {
	id, err := this.GetInt64("id")
	if err != nil {
		this.Ctx.WriteString("get param id fail")
		return
	}

	b := blog.OneById(id)
	if b == nil {
		this.Ctx.WriteString("no such article")
		return
	}

	err = blog.Del(b)
	if err != nil {
		this.Ctx.WriteString(err.Error())
		return
	}

	this.Ctx.WriteString("del success")
	return
}
<commit_msg>add this.Data["IsDraft"] = true t fix UI<commit_after>package controllers

import (
	"github.com/vincent3i/beego-blog/models"
	"github.com/vincent3i/beego-blog/models/blog"
	"github.com/vincent3i/beego-blog/models/catalog"
)

type ArticleController struct {
	AdminController
}

func (this *ArticleController) Draft() {
	var blogs []*models.Blog
	blog.Blogs().Filter("Status", 0).All(&blogs)
	this.Data["Blogs"] = blogs
	this.Data["IsDraft"] = true
	this.Layout = "layout/admin.html"
	this.TplNames = "article/draft.html"
}

func (this *ArticleController) Add() {
	this.Data["Catalogs"] = catalog.All()
	this.Data["IsPost"] = true
	this.Layout = "layout/admin.html"
	this.TplNames = "article/add.html"
	this.JsStorage("deleteKey", "post/new")
}

func (this *ArticleController) DoAdd() {
	title := this.GetString("title")
	ident := this.GetString("ident")
	keywords := this.GetString("keywords")
	catalog_id := this.GetIntWithDefault("catalog_id", -1)
	aType := this.GetIntWithDefault("type", -1)
	status := this.GetIntWithDefault("status", -1)
	content := this.GetString("content")

	if catalog_id == -1 || aType == -1 || status == -1 {
		this.Ctx.WriteString("catalog || type || status is illegal")
		return
	}

	if title == "" || ident == "" {
		this.Ctx.WriteString("title or ident is blank")
		return
	}

	cp := catalog.OneById(int64(catalog_id))
	if cp == nil {
		this.Ctx.WriteString("catalog_id not exists")
		return
	}

	b := &models.Blog{Ident: ident, Title: title, Keywords: keywords, CatalogId: int64(catalog_id), Type: int8(aType), Status: int8(status)}
	_, err := blog.Save(b, content)

	if err != nil {
		this.Ctx.WriteString(err.Error())
		return
	}

	this.JsStorage("deleteKey", "post/new")
	this.Redirect("/catalog/"+cp.Ident, 302)

}

func (this *ArticleController) Edit() {
	id, err := this.GetInt64("id")
	if err != nil {
		this.Ctx.WriteString("get param id fail")
		return
	}

	b := blog.OneById(id)
	if b == nil {
		this.Ctx.WriteString("no such article")
		return
	}

	this.Data["Content"] = blog.ReadBlogContent(b).Content
	this.Data["Blog"] = b
	this.Data["Catalogs"] = catalog.All()
	this.Layout = "layout/admin.html"
	this.TplNames = "article/edit.html"
}

func (this *ArticleController) DoEdit() {
	id, err := this.GetInt64("id")
	if err != nil {
		this.Ctx.WriteString("get param id fail")
		return
	}

	b := blog.OneById(id)
	if b == nil {
		this.Ctx.WriteString("no such article")
		return
	}

	title := this.GetString("title")
	ident := this.GetString("ident")
	keywords := this.GetString("keywords")
	catalog_id := this.GetIntWithDefault("catalog_id", -1)
	aType := this.GetIntWithDefault("type", -1)
	status := this.GetIntWithDefault("status", -1)
	content := this.GetString("content")

	if catalog_id == -1 || aType == -1 || status == -1 {
		this.Ctx.WriteString("catalog || type || status is illegal")
		return
	}

	if title == "" || ident == "" {
		this.Ctx.WriteString("title or ident is blank")
		return
	}

	cp := catalog.OneById(int64(catalog_id))
	if cp == nil {
		this.Ctx.WriteString("catalog_id not exists")
		return
	}

	b.Ident = ident
	b.Title = title
	b.Keywords = keywords
	b.CatalogId = int64(catalog_id)
	b.Type = int8(aType)
	b.Status = int8(status)

	err = blog.Update(b, content)

	if err != nil {
		this.Ctx.WriteString(err.Error())
		return
	}

	this.JsStorage("deleteKey", "post/edit")
	this.Redirect("/catalog/"+cp.Ident, 302)
}

func (this *ArticleController) Del() {
	id, err := this.GetInt64("id")
	if err != nil {
		this.Ctx.WriteString("get param id fail")
		return
	}

	b := blog.OneById(id)
	if b == nil {
		this.Ctx.WriteString("no such article")
		return
	}

	err = blog.Del(b)
	if err != nil {
		this.Ctx.WriteString(err.Error())
		return
	}

	this.Ctx.WriteString("del success")
	return
}
<|endoftext|>


<commit_before>// Copyright © 2017 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

package handler

import (
	"time"

	ttnlog "github.com/TheThingsNetwork/go-utils/log"
	"github.com/TheThingsNetwork/ttn/core/types"
	"github.com/TheThingsNetwork/ttn/mqtt"
)

// MQTTTimeout indicates how long we should wait for an MQTT publish
var MQTTTimeout = 2 * time.Second

// MQTTBufferSize indicates the size for uplink channel buffers
var MQTTBufferSize = 10

func (h *handler) HandleMQTT(username, password string, mqttBrokers ...string) error {
	h.mqttClient = mqtt.NewClient(h.Ctx, "ttnhdl", username, password, mqttBrokers...)

	err := h.mqttClient.Connect()
	if err != nil {
		return err
	}

	h.mqttUp = make(chan *types.UplinkMessage, MQTTBufferSize)
	h.mqttEvent = make(chan *types.DeviceEvent, MQTTBufferSize)

	token := h.mqttClient.SubscribeDownlink(func(client mqtt.Client, appID string, devID string, msg types.DownlinkMessage) {
		down := &msg
		down.DevID = devID
		down.AppID = appID
		go h.EnqueueDownlink(down)
	})
	token.Wait()
	if token.Error() != nil {
		return err
	}

	ctx := h.Ctx.WithField("Protocol", "MQTT")

	go func() {
		for up := range h.mqttUp {
			ctx.WithFields(ttnlog.Fields{
				"DevID": up.DevID,
				"AppID": up.AppID,
			}).Debug("Publish Uplink")
			upToken := h.mqttClient.PublishUplink(*up)
			go func() {
				if upToken.WaitTimeout(MQTTTimeout) {
					if upToken.Error() != nil {
						ctx.WithError(upToken.Error()).Warn("Could not publish Uplink")
					}
				} else {
					ctx.Warn("Uplink publish timeout")
				}
			}()
			if len(up.PayloadFields) > 0 {
				fieldsToken := h.mqttClient.PublishUplinkFields(up.AppID, up.DevID, up.PayloadFields)
				go func() {
					if fieldsToken.WaitTimeout(MQTTTimeout) {
						if fieldsToken.Error() != nil {
							ctx.WithError(fieldsToken.Error()).Warn("Could not publish Uplink Fields")
						}
					} else {
						ctx.Warn("Uplink Fields publish timeout")
					}
				}()
			}
		}
	}()

	go func() {
		for event := range h.mqttEvent {
			h.Ctx.WithFields(ttnlog.Fields{
				"DevID": event.DevID,
				"AppID": event.AppID,
				"Event": event.Event,
			}).Debug("Publish Event")
			var token mqtt.Token
			if event.DevID == "" {
				token = h.mqttClient.PublishAppEvent(event.AppID, event.Event, event.Data)
			} else {
				token = h.mqttClient.PublishDeviceEvent(event.AppID, event.DevID, event.Event, event.Data)
			}
			go func() {
				if token.WaitTimeout(MQTTTimeout) {
					if token.Error() != nil {
						h.Ctx.WithError(token.Error()).Warn("Could not publish Event")
					}
				} else {
					h.Ctx.Warn("Event publish timeout")
				}
			}()
		}
	}()

	return nil
}
<commit_msg>Log metadata when MQTT publish fails<commit_after>// Copyright © 2017 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

package handler

import (
	"time"

	ttnlog "github.com/TheThingsNetwork/go-utils/log"
	"github.com/TheThingsNetwork/ttn/core/types"
	"github.com/TheThingsNetwork/ttn/mqtt"
)

// MQTTTimeout indicates how long we should wait for an MQTT publish
var MQTTTimeout = 2 * time.Second

// MQTTBufferSize indicates the size for uplink channel buffers
var MQTTBufferSize = 10

func (h *handler) HandleMQTT(username, password string, mqttBrokers ...string) error {
	h.mqttClient = mqtt.NewClient(h.Ctx, "ttnhdl", username, password, mqttBrokers...)

	err := h.mqttClient.Connect()
	if err != nil {
		return err
	}

	h.mqttUp = make(chan *types.UplinkMessage, MQTTBufferSize)
	h.mqttEvent = make(chan *types.DeviceEvent, MQTTBufferSize)

	token := h.mqttClient.SubscribeDownlink(func(client mqtt.Client, appID string, devID string, msg types.DownlinkMessage) {
		down := &msg
		down.DevID = devID
		down.AppID = appID
		go h.EnqueueDownlink(down)
	})
	token.Wait()
	if token.Error() != nil {
		return err
	}

	ctx := h.Ctx.WithField("Protocol", "MQTT")

	go func() {
		for up := range h.mqttUp {
			ctx.WithFields(ttnlog.Fields{
				"DevID": up.DevID,
				"AppID": up.AppID,
			}).Debug("Publish Uplink")
			upToken := h.mqttClient.PublishUplink(*up)
			go func(ctx ttnlog.Interface) {
				if upToken.WaitTimeout(MQTTTimeout) {
					if upToken.Error() != nil {
						ctx.WithError(upToken.Error()).Warn("Could not publish Uplink")
					}
				} else {
					ctx.Warn("Uplink publish timeout")
				}
			}(ctx)
			if len(up.PayloadFields) > 0 {
				fieldsToken := h.mqttClient.PublishUplinkFields(up.AppID, up.DevID, up.PayloadFields)
				go func(ctx ttnlog.Interface) {
					if fieldsToken.WaitTimeout(MQTTTimeout) {
						if fieldsToken.Error() != nil {
							ctx.WithError(fieldsToken.Error()).Warn("Could not publish Uplink Fields")
						}
					} else {
						ctx.Warn("Uplink Fields publish timeout")
					}
				}(ctx)
			}
		}
	}()

	go func() {
		for event := range h.mqttEvent {
			h.Ctx.WithFields(ttnlog.Fields{
				"DevID": event.DevID,
				"AppID": event.AppID,
				"Event": event.Event,
			}).Debug("Publish Event")
			var token mqtt.Token
			if event.DevID == "" {
				token = h.mqttClient.PublishAppEvent(event.AppID, event.Event, event.Data)
			} else {
				token = h.mqttClient.PublishDeviceEvent(event.AppID, event.DevID, event.Event, event.Data)
			}
			go func() {
				if token.WaitTimeout(MQTTTimeout) {
					if token.Error() != nil {
						h.Ctx.WithError(token.Error()).Warn("Could not publish Event")
					}
				} else {
					h.Ctx.Warn("Event publish timeout")
				}
			}()
		}
	}()

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"log"
	"math/rand"
	"time"
)

// Tournament is the main container of data for this app.
type Tournament struct {
	Name        string    `json:"name"`
	ID          string    `json:"id"`
	Players     []Player  `json:"players"`
	Winners     []Player  `json:"winners"` // TODO: Refactor to pointer
	Runnerups   []string  `json:"runnerups"`
	Judges      []Judge   `json:"judges"`
	Tryouts     []*Match  `json:"tryouts"`
	Semis       []*Match  `json:"semis"`
	Final       *Match    `json:"final"`
	Opened      time.Time `json:"opened"`
	Started     time.Time `json:"started"`
	Ended       time.Time `json:"ended"`
	db          *Database
	server      *Server
	length      int
	finalLength int
}

// NewTournament returns a completely new Tournament
func NewTournament(name, id string, server *Server) (*Tournament, error) {
	t := Tournament{
		Name:   name,
		ID:     id,
		Opened: time.Now(),
		db:     server.DB,
		server: server,
	}

	for i := 0; i < 4; i++ {
		match := NewMatch(&t, i, "tryout")
		t.Tryouts = append(t.Tryouts, match)
	}

	t.Semis = []*Match{NewMatch(&t, 0, "semi"), NewMatch(&t, 1, "semi")}
	t.Final = NewMatch(&t, 0, "final")

	t.SetMatchPointers()
	t.Persist()
	return &t, nil
}

// LoadTournament loads a tournament from persisted JSON data
func LoadTournament(data []byte, db *Database) (t *Tournament, e error) {
	t = &Tournament{}
	err := json.Unmarshal(data, t)
	if err != nil {
		log.Print(err)
		return t, err
	}

	t.db = db
	t.server = db.Server

	t.SetMatchPointers()
	return
}

// Persist tells the database to save this tournament to disk
func (t *Tournament) Persist() error {
	if t.db == nil {
		// This might happen in tests.
		return errors.New("no database instantiated")
	}

	go t.server.SendWebsocketUpdate()

	return t.db.SaveTournament(t)
}

// JSON returns a JSON representation of the Tournament
func (t *Tournament) JSON() (out []byte, err error) {
	out, err = json.Marshal(t)
	return
}

// URL returns the URL for the tournament
func (t *Tournament) URL() string {
	out := fmt.Sprintf("/%s/", t.ID)
	return out
}

// AddPlayer adds a player into the tournament
//
// If the four default tryout matches are full, four more will be generated.
func (t *Tournament) AddPlayer(ps *Person) error {
	if err := t.CanJoin(ps); err != nil {
		return err
	}

	p := Player{Person: ps}
	t.Players = append(t.Players, p)
	t.Persist() // TODO: Error handling

	return nil
}

// ShufflePlayers will reposition players into matches
func (t *Tournament) ShufflePlayers() {
	// Shuffle all the players
	slice := t.Players
	for i := range slice {
		j := rand.Intn(i + 1)
		slice[i], slice[j] = slice[j], slice[i]
	}

	// Loop the players and set them into the matches
	for i, p := range slice {
		m := t.Tryouts[i/4]
		m.AddPlayer(p)
	}
}

// StartTournament will generate the tournament.
//
// This includes:
//  Generating Tryout matches
//  Setting Started date
//
// It will fail if there are not between 8 and 24 players.
func (t *Tournament) StartTournament() error {
	ps := len(t.Players)
	if ps < 8 || ps > 32 {
		return fmt.Errorf("Tournament needs at 8-32 players, got %d", ps)
	}

	// More than 16 players - add four more tryouts
	if ps > 16 {
		for i := 0; i < 4; i++ {
			match := NewMatch(t, i+4, "tryout")
			t.Tryouts = append(t.Tryouts, match)
		}
	}

	t.ShufflePlayers()
	t.Started = time.Now()
	t.Persist()
	return nil
}

// PopulateRunnerups fills a match with the runnerups with best scores
func (t *Tournament) PopulateRunnerups(m *Match) error {
	r, err := t.GetRunnerups()
	if err != nil {
		return err
	}

	for i := 0; len(m.Players) < 4; i++ {
		p := r[i]
		m.AddPlayer(p)
	}
	return nil
}

// GetRunnerups gets the runnerups for this tournament
//
// The returned list is sorted descending by score.
func (t *Tournament) GetRunnerups() (ps []Player, err error) {
	err = t.UpdatePlayers()
	if err != nil {
		return
	}

	rs := len(t.Runnerups)
	p := make([]Player, 0, rs)
	for _, r := range t.Runnerups {
		l := t.getPlayer(r)
		p = append(p, *l)
	}
	bs := SortByRunnerup(p)
	return bs, nil
}

// UpdatePlayers updates all the player objects with their scores from
// all the matches they have participated in.
func (t *Tournament) UpdatePlayers() error {
	// Make sure all players have their score reset to nothing
	for i := range t.Players {
		t.Players[i].Reset()
	}

	for _, m := range t.Tryouts {
		for _, p := range m.Players {
			t.getPlayer(p.Name()).Update(p)
		}
	}

	for _, m := range t.Semis {
		for _, p := range m.Players {
			t.getPlayer(p.Name()).Update(p)
		}
	}

	for _, p := range t.Final.Players {
		t.getPlayer(p.Name()).Update(p)
	}

	return nil
}

// MovePlayers moves the winner(s) of a Match into the next bracket of matches
// or into the Runnerup bracket.
func (t *Tournament) MovePlayers(m *Match) error {
	if m.Kind == "tryout" {
		ps := SortByKills(m.Players)
		for i := 0; i < len(ps); i++ {
			p := ps[i]
			// If we are in a four-match tryout, both the winner and the second-place
			// are to be sent to the semis
			if len(t.Tryouts) == 4 && i < 2 || i == 0 {
				// This spreads the winners into the semis so that the winners do not
				// face off immediately in the semis
				index := (i + m.Index) % 2
				t.Semis[index].AddPlayer(p)

				// If the player is also inside of the runnerups, move them from the
				// runnerup roster since they now have advanced to the finals. This
				// only happens for players that win the runnerup rounds.
				for j := 0; j < len(t.Runnerups); j++ {
					r := t.Runnerups[j]
					if r == p.Name() {
						t.Runnerups = append(t.Runnerups[:j], t.Runnerups[j+1:]...)
						break
					}
				}

			} else {
				// For everyone else, add them into the Runnerup bracket unless they are
				// already in there.
				found := false
				for j := 0; j < len(t.Runnerups); j++ {
					r := t.Runnerups[j]
					if r == p.Name() {
						found = true
						break
					}
				}
				if !found {
					t.Runnerups = append(t.Runnerups, p.Name())
				}
			}
		}
	}

	if m.Kind == "semi" {
		// For the semis, just place the winner and silver into the final
		for i, p := range SortByKills(m.Players) {
			if i < 2 {
				t.Final.AddPlayer(p)
			}
		}
	}

	// Get the runnerups and sort their names into the Runnerup array
	ps, err := t.GetRunnerups()
	if err != nil {
		log.Fatal(err)
	}
	t.Runnerups = make([]string, 0)
	for _, p := range ps {
		t.Runnerups = append(t.Runnerups, p.Name())
	}
	return nil
}

// NextMatch returns the next match
func (t *Tournament) NextMatch() (m *Match, err error) {
	// Firstly, check the tryouts
	for x := range t.Tryouts {
		m = t.Tryouts[x]
		if !m.IsEnded() {
			return
		}
	}

	// If we don't have any tryouts, or there are no tryouts left,
	// check the semis
	for x := range t.Semis {
		m = t.Semis[x]
		if !m.IsEnded() {
			return
		}
	}

	if !t.Final.IsEnded() {
		return t.Final, nil
	}

	return m, errors.New("all matches have been played")
}

// AwardMedals places the winning players in the Winners position
func (t *Tournament) AwardMedals(m *Match) error {
	if m.Kind != "final" {
		return errors.New("awarding medals outside of the final")
	}

	ps := SortByKills(m.Players)
	t.Winners = ps[0:3]

	t.Ended = time.Now()
	t.Persist()

	return nil
}

// IsOpen returns boolean true if the tournament is open for registration
func (t *Tournament) IsOpen() bool {
	return !t.Opened.IsZero()
}

// IsJoinable returns boolean true if the tournament is joinable
func (t *Tournament) IsJoinable() bool {
	if len(t.Players) >= 32 {
		return false
	}
	return t.IsOpen() && t.Started.IsZero()
}

// IsStartable returns boolean true if the tournament can be started
func (t *Tournament) IsStartable() bool {
	p := len(t.Players)
	return t.IsOpen() && t.Started.IsZero() && p >= 16 && p <= 32
}

// IsRunning returns boolean true if the tournament is running or not
func (t *Tournament) IsRunning() bool {
	return !t.Started.IsZero() && t.Ended.IsZero()
}

// CanJoin checks if a player is allowed to join or is already in the tournament
func (t *Tournament) CanJoin(ps *Person) error {
	if len(t.Players) >= 32 {
		return errors.New("tournament is full")
	}
	for _, p := range t.Players {
		if p.Name() == ps.Name {
			return errors.New("already in tournament")
		}
	}
	return nil
}

// SetMatchPointers loops over all matches in the tournament and sets the tournament reference
//
// When loading tournaments from the database, these references will not be set.
// This also sets *Match pointers for Player objects.
func (t *Tournament) SetMatchPointers() error {
	var m *Match
	// log.Printf("%s: Setting match pointers...", t.ID)

	for i := range t.Tryouts {
		m = t.Tryouts[i]
		m.Tournament = t
		for j := range m.Players {
			m.Players[j].Match = m
		}
	}

	for i := range t.Semis {
		m = t.Semis[i]
		m.Tournament = t
		for j := range m.Players {
			m.Players[j].Match = m
		}
	}
	t.Final.Tournament = t
	for i := range t.Final.Players {
		t.Final.Players[i].Match = t.Final
	}

	// log.Printf("%s: Pointers loaded.", t.ID)
	return nil
}

// SetupFakeTournament creates a fake tournament
func SetupFakeTournament(s *Server) *Tournament {
	title, id := FakeTournamentTitle()
	t, _ := NewTournament(title, id, s)

	// Fake between 8 and 32 players
	for i := 0; i < rand.Intn(24)+8; i++ {
		ps := &Person{
			Name:            FakeName(),
			Nick:            FakeNick(),
			AvatarURL:       FakeAvatar(),
			ColorPreference: []string{Colors[rand.Intn(len(Colors))]},
		}
		t.AddPlayer(ps)
	}

	return t
}

func (t *Tournament) getPlayer(name string) (p *Player) {
	for i := range t.Players {
		p := &t.Players[i]
		if p.Name() == name {
			return p
		}
	}

	log.Print(fmt.Sprintf("no player named %s found", name))
	return
}
<commit_msg>Fake more players<commit_after>package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"log"
	"math/rand"
	"time"
)

// Tournament is the main container of data for this app.
type Tournament struct {
	Name        string    `json:"name"`
	ID          string    `json:"id"`
	Players     []Player  `json:"players"`
	Winners     []Player  `json:"winners"` // TODO: Refactor to pointer
	Runnerups   []string  `json:"runnerups"`
	Judges      []Judge   `json:"judges"`
	Tryouts     []*Match  `json:"tryouts"`
	Semis       []*Match  `json:"semis"`
	Final       *Match    `json:"final"`
	Opened      time.Time `json:"opened"`
	Started     time.Time `json:"started"`
	Ended       time.Time `json:"ended"`
	db          *Database
	server      *Server
	length      int
	finalLength int
}

// NewTournament returns a completely new Tournament
func NewTournament(name, id string, server *Server) (*Tournament, error) {
	t := Tournament{
		Name:   name,
		ID:     id,
		Opened: time.Now(),
		db:     server.DB,
		server: server,
	}

	for i := 0; i < 4; i++ {
		match := NewMatch(&t, i, "tryout")
		t.Tryouts = append(t.Tryouts, match)
	}

	t.Semis = []*Match{NewMatch(&t, 0, "semi"), NewMatch(&t, 1, "semi")}
	t.Final = NewMatch(&t, 0, "final")

	t.SetMatchPointers()
	t.Persist()
	return &t, nil
}

// LoadTournament loads a tournament from persisted JSON data
func LoadTournament(data []byte, db *Database) (t *Tournament, e error) {
	t = &Tournament{}
	err := json.Unmarshal(data, t)
	if err != nil {
		log.Print(err)
		return t, err
	}

	t.db = db
	t.server = db.Server

	t.SetMatchPointers()
	return
}

// Persist tells the database to save this tournament to disk
func (t *Tournament) Persist() error {
	if t.db == nil {
		// This might happen in tests.
		return errors.New("no database instantiated")
	}

	go t.server.SendWebsocketUpdate()

	return t.db.SaveTournament(t)
}

// JSON returns a JSON representation of the Tournament
func (t *Tournament) JSON() (out []byte, err error) {
	out, err = json.Marshal(t)
	return
}

// URL returns the URL for the tournament
func (t *Tournament) URL() string {
	out := fmt.Sprintf("/%s/", t.ID)
	return out
}

// AddPlayer adds a player into the tournament
//
// If the four default tryout matches are full, four more will be generated.
func (t *Tournament) AddPlayer(ps *Person) error {
	if err := t.CanJoin(ps); err != nil {
		return err
	}

	p := Player{Person: ps}
	t.Players = append(t.Players, p)
	t.Persist() // TODO: Error handling

	return nil
}

// ShufflePlayers will reposition players into matches
func (t *Tournament) ShufflePlayers() {
	// Shuffle all the players
	slice := t.Players
	for i := range slice {
		j := rand.Intn(i + 1)
		slice[i], slice[j] = slice[j], slice[i]
	}

	// Loop the players and set them into the matches
	for i, p := range slice {
		m := t.Tryouts[i/4]
		m.AddPlayer(p)
	}
}

// StartTournament will generate the tournament.
//
// This includes:
//  Generating Tryout matches
//  Setting Started date
//
// It will fail if there are not between 8 and 24 players.
func (t *Tournament) StartTournament() error {
	ps := len(t.Players)
	if ps < 8 || ps > 32 {
		return fmt.Errorf("Tournament needs at 8-32 players, got %d", ps)
	}

	// More than 16 players - add four more tryouts
	if ps > 16 {
		for i := 0; i < 4; i++ {
			match := NewMatch(t, i+4, "tryout")
			t.Tryouts = append(t.Tryouts, match)
		}
	}

	t.ShufflePlayers()
	t.Started = time.Now()
	t.Persist()
	return nil
}

// PopulateRunnerups fills a match with the runnerups with best scores
func (t *Tournament) PopulateRunnerups(m *Match) error {
	r, err := t.GetRunnerups()
	if err != nil {
		return err
	}

	for i := 0; len(m.Players) < 4; i++ {
		p := r[i]
		m.AddPlayer(p)
	}
	return nil
}

// GetRunnerups gets the runnerups for this tournament
//
// The returned list is sorted descending by score.
func (t *Tournament) GetRunnerups() (ps []Player, err error) {
	err = t.UpdatePlayers()
	if err != nil {
		return
	}

	rs := len(t.Runnerups)
	p := make([]Player, 0, rs)
	for _, r := range t.Runnerups {
		l := t.getPlayer(r)
		p = append(p, *l)
	}
	bs := SortByRunnerup(p)
	return bs, nil
}

// UpdatePlayers updates all the player objects with their scores from
// all the matches they have participated in.
func (t *Tournament) UpdatePlayers() error {
	// Make sure all players have their score reset to nothing
	for i := range t.Players {
		t.Players[i].Reset()
	}

	for _, m := range t.Tryouts {
		for _, p := range m.Players {
			t.getPlayer(p.Name()).Update(p)
		}
	}

	for _, m := range t.Semis {
		for _, p := range m.Players {
			t.getPlayer(p.Name()).Update(p)
		}
	}

	for _, p := range t.Final.Players {
		t.getPlayer(p.Name()).Update(p)
	}

	return nil
}

// MovePlayers moves the winner(s) of a Match into the next bracket of matches
// or into the Runnerup bracket.
func (t *Tournament) MovePlayers(m *Match) error {
	if m.Kind == "tryout" {
		ps := SortByKills(m.Players)
		for i := 0; i < len(ps); i++ {
			p := ps[i]
			// If we are in a four-match tryout, both the winner and the second-place
			// are to be sent to the semis
			if len(t.Tryouts) == 4 && i < 2 || i == 0 {
				// This spreads the winners into the semis so that the winners do not
				// face off immediately in the semis
				index := (i + m.Index) % 2
				t.Semis[index].AddPlayer(p)

				// If the player is also inside of the runnerups, move them from the
				// runnerup roster since they now have advanced to the finals. This
				// only happens for players that win the runnerup rounds.
				for j := 0; j < len(t.Runnerups); j++ {
					r := t.Runnerups[j]
					if r == p.Name() {
						t.Runnerups = append(t.Runnerups[:j], t.Runnerups[j+1:]...)
						break
					}
				}

			} else {
				// For everyone else, add them into the Runnerup bracket unless they are
				// already in there.
				found := false
				for j := 0; j < len(t.Runnerups); j++ {
					r := t.Runnerups[j]
					if r == p.Name() {
						found = true
						break
					}
				}
				if !found {
					t.Runnerups = append(t.Runnerups, p.Name())
				}
			}
		}
	}

	if m.Kind == "semi" {
		// For the semis, just place the winner and silver into the final
		for i, p := range SortByKills(m.Players) {
			if i < 2 {
				t.Final.AddPlayer(p)
			}
		}
	}

	// Get the runnerups and sort their names into the Runnerup array
	ps, err := t.GetRunnerups()
	if err != nil {
		log.Fatal(err)
	}
	t.Runnerups = make([]string, 0)
	for _, p := range ps {
		t.Runnerups = append(t.Runnerups, p.Name())
	}
	return nil
}

// NextMatch returns the next match
func (t *Tournament) NextMatch() (m *Match, err error) {
	// Firstly, check the tryouts
	for x := range t.Tryouts {
		m = t.Tryouts[x]
		if !m.IsEnded() {
			return
		}
	}

	// If we don't have any tryouts, or there are no tryouts left,
	// check the semis
	for x := range t.Semis {
		m = t.Semis[x]
		if !m.IsEnded() {
			return
		}
	}

	if !t.Final.IsEnded() {
		return t.Final, nil
	}

	return m, errors.New("all matches have been played")
}

// AwardMedals places the winning players in the Winners position
func (t *Tournament) AwardMedals(m *Match) error {
	if m.Kind != "final" {
		return errors.New("awarding medals outside of the final")
	}

	ps := SortByKills(m.Players)
	t.Winners = ps[0:3]

	t.Ended = time.Now()
	t.Persist()

	return nil
}

// IsOpen returns boolean true if the tournament is open for registration
func (t *Tournament) IsOpen() bool {
	return !t.Opened.IsZero()
}

// IsJoinable returns boolean true if the tournament is joinable
func (t *Tournament) IsJoinable() bool {
	if len(t.Players) >= 32 {
		return false
	}
	return t.IsOpen() && t.Started.IsZero()
}

// IsStartable returns boolean true if the tournament can be started
func (t *Tournament) IsStartable() bool {
	p := len(t.Players)
	return t.IsOpen() && t.Started.IsZero() && p >= 16 && p <= 32
}

// IsRunning returns boolean true if the tournament is running or not
func (t *Tournament) IsRunning() bool {
	return !t.Started.IsZero() && t.Ended.IsZero()
}

// CanJoin checks if a player is allowed to join or is already in the tournament
func (t *Tournament) CanJoin(ps *Person) error {
	if len(t.Players) >= 32 {
		return errors.New("tournament is full")
	}
	for _, p := range t.Players {
		if p.Name() == ps.Name {
			return errors.New("already in tournament")
		}
	}
	return nil
}

// SetMatchPointers loops over all matches in the tournament and sets the tournament reference
//
// When loading tournaments from the database, these references will not be set.
// This also sets *Match pointers for Player objects.
func (t *Tournament) SetMatchPointers() error {
	var m *Match
	// log.Printf("%s: Setting match pointers...", t.ID)

	for i := range t.Tryouts {
		m = t.Tryouts[i]
		m.Tournament = t
		for j := range m.Players {
			m.Players[j].Match = m
		}
	}

	for i := range t.Semis {
		m = t.Semis[i]
		m.Tournament = t
		for j := range m.Players {
			m.Players[j].Match = m
		}
	}
	t.Final.Tournament = t
	for i := range t.Final.Players {
		t.Final.Players[i].Match = t.Final
	}

	// log.Printf("%s: Pointers loaded.", t.ID)
	return nil
}

// SetupFakeTournament creates a fake tournament
func SetupFakeTournament(s *Server) *Tournament {
	title, id := FakeTournamentTitle()
	t, _ := NewTournament(title, id, s)

	// Fake between 14 and 32 players
	for i := 0; i < rand.Intn(18)+14; i++ {
		ps := &Person{
			Name:            FakeName(),
			Nick:            FakeNick(),
			AvatarURL:       FakeAvatar(),
			ColorPreference: []string{Colors[rand.Intn(len(Colors))]},
		}
		t.AddPlayer(ps)
	}

	return t
}

func (t *Tournament) getPlayer(name string) (p *Player) {
	for i := range t.Players {
		p := &t.Players[i]
		if p.Name() == name {
			return p
		}
	}

	log.Print(fmt.Sprintf("no player named %s found", name))
	return
}
<|endoftext|>


<commit_before>// Copyright 2016 The Netstack 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 unix

import (
	"sync"

	"github.com/google/netstack/tcpip"
	"github.com/google/netstack/tcpip/transport/queue"
	"github.com/google/netstack/waiter"
)

// UniqueIDProvider generates a sequence of unique identifiers useful for,
// among other things, lock ordering.
type UniqueIDProvider interface {
	// UniqueID returns a new unique identifier.
	UniqueID() uint64
}

// A ConnectingEndpoint is a connectioned unix endpoint that is attempting to
// establish a bidirectional connection with a BoundEndpoint.
type ConnectingEndpoint interface {
	// ID returns the endpoint's globally unique identifier. This identifier
	// must be used to determine locking order if more than one endpoint is
	// to be locked in the same codepath. The endpoint with the smaller
	// identifier must be locked before endpoints with larger identifiers.
	ID() uint64

	// Passcred implements socket.Credentialer.Passcred.
	Passcred() bool

	// Type returns the socket type, typically either SockStream or
	// SockSeqpacket. The connection attempt must be aborted if this
	// value doesn't match the ConnectableEndpoint's type.
	Type() SockType

	// GetLocalAddress returns the bound path.
	GetLocalAddress() (tcpip.FullAddress, *tcpip.Error)

	// Locker protects the following methods. While locked, only the holder of
	// the lock can change the return value of the protected methods.
	sync.Locker

	// Connected returns true iff the ConnectingEndpoint is in the connected
	// state. ConnectingEndpoints can only be connected to a single endpoint,
	// so the connection attempt must be aborted if this returns true.
	Connected() bool

	// Listening returns true iff the ConnectingEndpoint is in the listening
	// state. ConnectingEndpoints cannot make connections while listening, so
	// the connection attempt must be aborted if this returns true.
	Listening() bool

	// WaiterQueue returns a pointer to the endpoint's waiter queue.
	WaiterQueue() *waiter.Queue
}

// connectionedEndpoint is a Unix-domain connected or connectable endpoint and implements
// ConnectingEndpoint, ConnectableEndpoint and tcpip.Endpoint.
//
// connectionedEndpoints must be in connected state in order to transfer data.
//
// This implementation includes STREAM and SEQPACKET Unix sockets created with
// socket(2), accept(2) or socketpair(2) and dgram unix sockets created with
// socketpair(2). See unix_connectionless.go for the implementation of DGRAM
// Unix sockets created with socket(2).
//
// The state is much simpler than a TCP endpoint, so it is not encoded
// explicitly. Instead we enforce the following invariants:
//
// receiver != nil, connected != nil => connected.
// path != "" && acceptedChan == nil => bound, not listening.
// path != "" && acceptedChan != nil => bound and listening.
//
// Only one of these will be true at any moment.
type connectionedEndpoint struct {
	baseEndpoint

	// id is the unique endpoint identifier. This is used exclusively for
	// lock ordering within connect.
	id uint64

	// idGenerator is used to generate new unique endpoint identifiers.
	idGenerator UniqueIDProvider

	// stype is used by connecting sockets to ensure that they are the
	// same type. The value is typically either tcpip.SockSeqpacket or
	// tcpip.SockStream.
	stype SockType

	// acceptedChan is per the TCP endpoint implementation. Note that the
	// sockets in this channel are _already in the connected state_, and
	// have another associated connectionedEndpoint.
	//
	// If nil, then no listen call has been made.
	acceptedChan chan *connectionedEndpoint
}

// NewConnectioned creates a new unbound connectionedEndpoint.
func NewConnectioned(stype SockType, uid UniqueIDProvider) Endpoint {
	return &connectionedEndpoint{
		baseEndpoint: baseEndpoint{Queue: &waiter.Queue{}},
		id:           uid.UniqueID(),
		idGenerator:  uid,
		stype:        stype,
	}
}

// NewPair allocates a new pair of connected unix-domain connectionedEndpoints.
func NewPair(stype SockType, uid UniqueIDProvider) (Endpoint, Endpoint) {
	a := &connectionedEndpoint{
		baseEndpoint: baseEndpoint{Queue: &waiter.Queue{}},
		id:           uid.UniqueID(),
		idGenerator:  uid,
		stype:        stype,
	}
	b := &connectionedEndpoint{
		baseEndpoint: baseEndpoint{Queue: &waiter.Queue{}},
		id:           uid.UniqueID(),
		idGenerator:  uid,
		stype:        stype,
	}

	q1 := queue.New(a.Queue, b.Queue, initialLimit)
	q2 := queue.New(b.Queue, a.Queue, initialLimit)

	if stype == SockStream {
		a.receiver = &streamQueueReceiver{queueReceiver: queueReceiver{q1}}
		b.receiver = &streamQueueReceiver{queueReceiver: queueReceiver{q2}}
	} else {
		a.receiver = &queueReceiver{q1}
		b.receiver = &queueReceiver{q2}
	}

	a.connected = &connectedEndpoint{
		endpoint:   b,
		writeQueue: q2,
	}
	b.connected = &connectedEndpoint{
		endpoint:   a,
		writeQueue: q1,
	}

	return a, b
}

// ID implements ConnectingEndpoint.ID.
func (e *connectionedEndpoint) ID() uint64 {
	return e.id
}

// Type implements ConnectingEndpoint.Type and Endpoint.Type.
func (e *connectionedEndpoint) Type() SockType {
	return e.stype
}

// WaiterQueue implements ConnectingEndpoint.WaiterQueue.
func (e *connectionedEndpoint) WaiterQueue() *waiter.Queue {
	return e.Queue
}

// isBound returns true iff the connectionedEndpoint is bound (but not
// listening).
func (e *connectionedEndpoint) isBound() bool {
	return e.path != "" && e.acceptedChan == nil
}

// Listening implements ConnectingEndpoint.Listening.
func (e *connectionedEndpoint) Listening() bool {
	return e.acceptedChan != nil
}

// Close puts the connectionedEndpoint in a closed state and frees all
// resources associated with it.
//
// The socket will be a fresh state after a call to close and may be reused.
// That is, close may be used to "unbind" or "disconnect" the socket in error
// paths.
func (e *connectionedEndpoint) Close() {
	e.Lock()
	var c ConnectedEndpoint
	var r Receiver
	switch {
	case e.Connected():
		e.connected.CloseSend()
		e.receiver.CloseRecv()
		c = e.connected
		r = e.receiver
		e.connected = nil
		e.receiver = nil
	case e.isBound():
		e.path = ""
	case e.Listening():
		close(e.acceptedChan)
		for n := range e.acceptedChan {
			n.Close()
		}
		e.acceptedChan = nil
		e.path = ""
	}
	e.Unlock()
	if c != nil {
		c.CloseNotify()
		c.Release()
	}
	if r != nil {
		r.CloseNotify()
		r.Release()
	}
}

// BidirectionalConnect implements BoundEndpoint.BidirectionalConnect.
func (e *connectionedEndpoint) BidirectionalConnect(ce ConnectingEndpoint, returnConnect func(Receiver, ConnectedEndpoint)) *tcpip.Error {
	if ce.Type() != e.stype {
		return tcpip.ErrConnectionRefused
	}

	// Check if ce is e to avoid a deadlock.
	if ce, ok := ce.(*connectionedEndpoint); ok && ce == e {
		return tcpip.ErrInvalidEndpointState
	}

	// Do a dance to safely acquire locks on both endpoints.
	if e.id < ce.ID() {
		e.Lock()
		ce.Lock()
	} else {
		ce.Lock()
		e.Lock()
	}

	// Check connecting state.
	if ce.Connected() {
		e.Unlock()
		ce.Unlock()
		return tcpip.ErrAlreadyConnected
	}
	if ce.Listening() {
		e.Unlock()
		ce.Unlock()
		return tcpip.ErrInvalidEndpointState
	}

	// Check bound state.
	if !e.Listening() {
		e.Unlock()
		ce.Unlock()
		return tcpip.ErrConnectionRefused
	}

	// Create a newly bound connectionedEndpoint.
	ne := &connectionedEndpoint{
		baseEndpoint: baseEndpoint{
			path:  e.path,
			Queue: &waiter.Queue{},
		},
		id:          e.idGenerator.UniqueID(),
		idGenerator: e.idGenerator,
		stype:       e.stype,
	}
	readQueue := queue.New(ce.WaiterQueue(), ne.Queue, initialLimit)
	writeQueue := queue.New(ne.Queue, ce.WaiterQueue(), initialLimit)
	ne.connected = &connectedEndpoint{
		endpoint:   ce,
		writeQueue: readQueue,
	}
	if e.stype == SockStream {
		ne.receiver = &streamQueueReceiver{queueReceiver: queueReceiver{readQueue: writeQueue}}
	} else {
		ne.receiver = &queueReceiver{readQueue: writeQueue}
	}

	select {
	case e.acceptedChan <- ne:
		// Commit state.
		connected := &connectedEndpoint{
			endpoint:   ne,
			writeQueue: writeQueue,
		}
		if e.stype == SockStream {
			returnConnect(&streamQueueReceiver{queueReceiver: queueReceiver{readQueue: readQueue}}, connected)
		} else {
			returnConnect(&queueReceiver{readQueue: readQueue}, connected)
		}

		// Notify can deadlock if we are holding these locks.
		e.Unlock()
		ce.Unlock()

		// Notify on both ends.
		e.Notify(waiter.EventIn)
		ce.WaiterQueue().Notify(waiter.EventOut)

		return nil
	default:
		// Busy; return ECONNREFUSED per spec.
		ne.Close()
		e.Unlock()
		ce.Unlock()
		return tcpip.ErrConnectionRefused
	}
}

// UnidirectionalConnect implements BoundEndpoint.UnidirectionalConnect.
func (e *connectionedEndpoint) UnidirectionalConnect() (ConnectedEndpoint, *tcpip.Error) {
	return nil, tcpip.ErrConnectionRefused
}

// Connect attempts to directly connect to another Endpoint.
// Implements Endpoint.Connect.
func (e *connectionedEndpoint) Connect(server BoundEndpoint) *tcpip.Error {
	returnConnect := func(r Receiver, ce ConnectedEndpoint) {
		e.receiver = r
		e.connected = ce
	}

	return server.BidirectionalConnect(e, returnConnect)
}

// Listen starts listening on the connection.
func (e *connectionedEndpoint) Listen(backlog int) *tcpip.Error {
	e.Lock()
	defer e.Unlock()
	if e.Listening() {
		// Adjust the size of the channel iff we can fix existing
		// pending connections into the new one.
		if len(e.acceptedChan) > backlog {
			return tcpip.ErrInvalidEndpointState
		}
		origChan := e.acceptedChan
		e.acceptedChan = make(chan *connectionedEndpoint, backlog)
		close(origChan)
		for ep := range origChan {
			e.acceptedChan <- ep
		}
		return nil
	}
	if !e.isBound() {
		return tcpip.ErrInvalidEndpointState
	}

	// Normal case.
	e.acceptedChan = make(chan *connectionedEndpoint, backlog)
	return nil
}

// Accept accepts a new connection.
func (e *connectionedEndpoint) Accept() (Endpoint, *tcpip.Error) {
	e.Lock()
	defer e.Unlock()

	if !e.Listening() {
		return nil, tcpip.ErrInvalidEndpointState
	}

	select {
	case ne := <-e.acceptedChan:
		return ne, nil

	default:
		// Nothing left.
		return nil, tcpip.ErrWouldBlock
	}
}

// Bind binds the connection.
//
// For Unix connectionedEndpoints, this _only sets the address associated with
// the socket_. Work associated with sockets in the filesystem or finding those
// sockets must be done by a higher level.
//
// Bind will fail only if the socket is connected, bound or the passed address
// is invalid (the empty string).
func (e *connectionedEndpoint) Bind(addr tcpip.FullAddress, commit func() *tcpip.Error) *tcpip.Error {
	e.Lock()
	defer e.Unlock()
	if e.isBound() || e.Listening() {
		return tcpip.ErrAlreadyBound
	}
	if addr.Addr == "" {
		// The empty string is not permitted.
		return tcpip.ErrBadLocalAddress
	}
	if commit != nil {
		if err := commit(); err != nil {
			return err
		}
	}

	// Save the bound address.
	e.path = string(addr.Addr)
	return nil
}

// Readiness returns the current readiness of the connectionedEndpoint. For
// example, if waiter.EventIn is set, the connectionedEndpoint is immediately
// readable.
func (e *connectionedEndpoint) Readiness(mask waiter.EventMask) waiter.EventMask {
	e.Lock()
	defer e.Unlock()

	ready := waiter.EventMask(0)
	switch {
	case e.Connected():
		if mask&waiter.EventIn != 0 && e.receiver.Readable() {
			ready |= waiter.EventIn
		}
		if mask&waiter.EventOut != 0 && e.connected.Writable() {
			ready |= waiter.EventOut
		}
	case e.Listening():
		if mask&waiter.EventIn != 0 && len(e.acceptedChan) > 0 {
			ready |= waiter.EventIn
		}
	}

	return ready
}
<commit_msg>Fix sendto semantics on unbound UDS.<commit_after>// Copyright 2016 The Netstack 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 unix

import (
	"sync"

	"github.com/google/netstack/tcpip"
	"github.com/google/netstack/tcpip/transport/queue"
	"github.com/google/netstack/waiter"
)

// UniqueIDProvider generates a sequence of unique identifiers useful for,
// among other things, lock ordering.
type UniqueIDProvider interface {
	// UniqueID returns a new unique identifier.
	UniqueID() uint64
}

// A ConnectingEndpoint is a connectioned unix endpoint that is attempting to
// establish a bidirectional connection with a BoundEndpoint.
type ConnectingEndpoint interface {
	// ID returns the endpoint's globally unique identifier. This identifier
	// must be used to determine locking order if more than one endpoint is
	// to be locked in the same codepath. The endpoint with the smaller
	// identifier must be locked before endpoints with larger identifiers.
	ID() uint64

	// Passcred implements socket.Credentialer.Passcred.
	Passcred() bool

	// Type returns the socket type, typically either SockStream or
	// SockSeqpacket. The connection attempt must be aborted if this
	// value doesn't match the ConnectableEndpoint's type.
	Type() SockType

	// GetLocalAddress returns the bound path.
	GetLocalAddress() (tcpip.FullAddress, *tcpip.Error)

	// Locker protects the following methods. While locked, only the holder of
	// the lock can change the return value of the protected methods.
	sync.Locker

	// Connected returns true iff the ConnectingEndpoint is in the connected
	// state. ConnectingEndpoints can only be connected to a single endpoint,
	// so the connection attempt must be aborted if this returns true.
	Connected() bool

	// Listening returns true iff the ConnectingEndpoint is in the listening
	// state. ConnectingEndpoints cannot make connections while listening, so
	// the connection attempt must be aborted if this returns true.
	Listening() bool

	// WaiterQueue returns a pointer to the endpoint's waiter queue.
	WaiterQueue() *waiter.Queue
}

// connectionedEndpoint is a Unix-domain connected or connectable endpoint and implements
// ConnectingEndpoint, ConnectableEndpoint and tcpip.Endpoint.
//
// connectionedEndpoints must be in connected state in order to transfer data.
//
// This implementation includes STREAM and SEQPACKET Unix sockets created with
// socket(2), accept(2) or socketpair(2) and dgram unix sockets created with
// socketpair(2). See unix_connectionless.go for the implementation of DGRAM
// Unix sockets created with socket(2).
//
// The state is much simpler than a TCP endpoint, so it is not encoded
// explicitly. Instead we enforce the following invariants:
//
// receiver != nil, connected != nil => connected.
// path != "" && acceptedChan == nil => bound, not listening.
// path != "" && acceptedChan != nil => bound and listening.
//
// Only one of these will be true at any moment.
type connectionedEndpoint struct {
	baseEndpoint

	// id is the unique endpoint identifier. This is used exclusively for
	// lock ordering within connect.
	id uint64

	// idGenerator is used to generate new unique endpoint identifiers.
	idGenerator UniqueIDProvider

	// stype is used by connecting sockets to ensure that they are the
	// same type. The value is typically either tcpip.SockSeqpacket or
	// tcpip.SockStream.
	stype SockType

	// acceptedChan is per the TCP endpoint implementation. Note that the
	// sockets in this channel are _already in the connected state_, and
	// have another associated connectionedEndpoint.
	//
	// If nil, then no listen call has been made.
	acceptedChan chan *connectionedEndpoint
}

// NewConnectioned creates a new unbound connectionedEndpoint.
func NewConnectioned(stype SockType, uid UniqueIDProvider) Endpoint {
	return &connectionedEndpoint{
		baseEndpoint: baseEndpoint{Queue: &waiter.Queue{}},
		id:           uid.UniqueID(),
		idGenerator:  uid,
		stype:        stype,
	}
}

// NewPair allocates a new pair of connected unix-domain connectionedEndpoints.
func NewPair(stype SockType, uid UniqueIDProvider) (Endpoint, Endpoint) {
	a := &connectionedEndpoint{
		baseEndpoint: baseEndpoint{Queue: &waiter.Queue{}},
		id:           uid.UniqueID(),
		idGenerator:  uid,
		stype:        stype,
	}
	b := &connectionedEndpoint{
		baseEndpoint: baseEndpoint{Queue: &waiter.Queue{}},
		id:           uid.UniqueID(),
		idGenerator:  uid,
		stype:        stype,
	}

	q1 := queue.New(a.Queue, b.Queue, initialLimit)
	q2 := queue.New(b.Queue, a.Queue, initialLimit)

	if stype == SockStream {
		a.receiver = &streamQueueReceiver{queueReceiver: queueReceiver{q1}}
		b.receiver = &streamQueueReceiver{queueReceiver: queueReceiver{q2}}
	} else {
		a.receiver = &queueReceiver{q1}
		b.receiver = &queueReceiver{q2}
	}

	a.connected = &connectedEndpoint{
		endpoint:   b,
		writeQueue: q2,
	}
	b.connected = &connectedEndpoint{
		endpoint:   a,
		writeQueue: q1,
	}

	return a, b
}

// ID implements ConnectingEndpoint.ID.
func (e *connectionedEndpoint) ID() uint64 {
	return e.id
}

// Type implements ConnectingEndpoint.Type and Endpoint.Type.
func (e *connectionedEndpoint) Type() SockType {
	return e.stype
}

// WaiterQueue implements ConnectingEndpoint.WaiterQueue.
func (e *connectionedEndpoint) WaiterQueue() *waiter.Queue {
	return e.Queue
}

// isBound returns true iff the connectionedEndpoint is bound (but not
// listening).
func (e *connectionedEndpoint) isBound() bool {
	return e.path != "" && e.acceptedChan == nil
}

// Listening implements ConnectingEndpoint.Listening.
func (e *connectionedEndpoint) Listening() bool {
	return e.acceptedChan != nil
}

// Close puts the connectionedEndpoint in a closed state and frees all
// resources associated with it.
//
// The socket will be a fresh state after a call to close and may be reused.
// That is, close may be used to "unbind" or "disconnect" the socket in error
// paths.
func (e *connectionedEndpoint) Close() {
	e.Lock()
	var c ConnectedEndpoint
	var r Receiver
	switch {
	case e.Connected():
		e.connected.CloseSend()
		e.receiver.CloseRecv()
		c = e.connected
		r = e.receiver
		e.connected = nil
		e.receiver = nil
	case e.isBound():
		e.path = ""
	case e.Listening():
		close(e.acceptedChan)
		for n := range e.acceptedChan {
			n.Close()
		}
		e.acceptedChan = nil
		e.path = ""
	}
	e.Unlock()
	if c != nil {
		c.CloseNotify()
		c.Release()
	}
	if r != nil {
		r.CloseNotify()
		r.Release()
	}
}

// BidirectionalConnect implements BoundEndpoint.BidirectionalConnect.
func (e *connectionedEndpoint) BidirectionalConnect(ce ConnectingEndpoint, returnConnect func(Receiver, ConnectedEndpoint)) *tcpip.Error {
	if ce.Type() != e.stype {
		return tcpip.ErrConnectionRefused
	}

	// Check if ce is e to avoid a deadlock.
	if ce, ok := ce.(*connectionedEndpoint); ok && ce == e {
		return tcpip.ErrInvalidEndpointState
	}

	// Do a dance to safely acquire locks on both endpoints.
	if e.id < ce.ID() {
		e.Lock()
		ce.Lock()
	} else {
		ce.Lock()
		e.Lock()
	}

	// Check connecting state.
	if ce.Connected() {
		e.Unlock()
		ce.Unlock()
		return tcpip.ErrAlreadyConnected
	}
	if ce.Listening() {
		e.Unlock()
		ce.Unlock()
		return tcpip.ErrInvalidEndpointState
	}

	// Check bound state.
	if !e.Listening() {
		e.Unlock()
		ce.Unlock()
		return tcpip.ErrConnectionRefused
	}

	// Create a newly bound connectionedEndpoint.
	ne := &connectionedEndpoint{
		baseEndpoint: baseEndpoint{
			path:  e.path,
			Queue: &waiter.Queue{},
		},
		id:          e.idGenerator.UniqueID(),
		idGenerator: e.idGenerator,
		stype:       e.stype,
	}
	readQueue := queue.New(ce.WaiterQueue(), ne.Queue, initialLimit)
	writeQueue := queue.New(ne.Queue, ce.WaiterQueue(), initialLimit)
	ne.connected = &connectedEndpoint{
		endpoint:   ce,
		writeQueue: readQueue,
	}
	if e.stype == SockStream {
		ne.receiver = &streamQueueReceiver{queueReceiver: queueReceiver{readQueue: writeQueue}}
	} else {
		ne.receiver = &queueReceiver{readQueue: writeQueue}
	}

	select {
	case e.acceptedChan <- ne:
		// Commit state.
		connected := &connectedEndpoint{
			endpoint:   ne,
			writeQueue: writeQueue,
		}
		if e.stype == SockStream {
			returnConnect(&streamQueueReceiver{queueReceiver: queueReceiver{readQueue: readQueue}}, connected)
		} else {
			returnConnect(&queueReceiver{readQueue: readQueue}, connected)
		}

		// Notify can deadlock if we are holding these locks.
		e.Unlock()
		ce.Unlock()

		// Notify on both ends.
		e.Notify(waiter.EventIn)
		ce.WaiterQueue().Notify(waiter.EventOut)

		return nil
	default:
		// Busy; return ECONNREFUSED per spec.
		ne.Close()
		e.Unlock()
		ce.Unlock()
		return tcpip.ErrConnectionRefused
	}
}

// UnidirectionalConnect implements BoundEndpoint.UnidirectionalConnect.
func (e *connectionedEndpoint) UnidirectionalConnect() (ConnectedEndpoint, *tcpip.Error) {
	return nil, tcpip.ErrConnectionRefused
}

// Connect attempts to directly connect to another Endpoint.
// Implements Endpoint.Connect.
func (e *connectionedEndpoint) Connect(server BoundEndpoint) *tcpip.Error {
	returnConnect := func(r Receiver, ce ConnectedEndpoint) {
		e.receiver = r
		e.connected = ce
	}

	return server.BidirectionalConnect(e, returnConnect)
}

// Listen starts listening on the connection.
func (e *connectionedEndpoint) Listen(backlog int) *tcpip.Error {
	e.Lock()
	defer e.Unlock()
	if e.Listening() {
		// Adjust the size of the channel iff we can fix existing
		// pending connections into the new one.
		if len(e.acceptedChan) > backlog {
			return tcpip.ErrInvalidEndpointState
		}
		origChan := e.acceptedChan
		e.acceptedChan = make(chan *connectionedEndpoint, backlog)
		close(origChan)
		for ep := range origChan {
			e.acceptedChan <- ep
		}
		return nil
	}
	if !e.isBound() {
		return tcpip.ErrInvalidEndpointState
	}

	// Normal case.
	e.acceptedChan = make(chan *connectionedEndpoint, backlog)
	return nil
}

// Accept accepts a new connection.
func (e *connectionedEndpoint) Accept() (Endpoint, *tcpip.Error) {
	e.Lock()
	defer e.Unlock()

	if !e.Listening() {
		return nil, tcpip.ErrInvalidEndpointState
	}

	select {
	case ne := <-e.acceptedChan:
		return ne, nil

	default:
		// Nothing left.
		return nil, tcpip.ErrWouldBlock
	}
}

// Bind binds the connection.
//
// For Unix connectionedEndpoints, this _only sets the address associated with
// the socket_. Work associated with sockets in the filesystem or finding those
// sockets must be done by a higher level.
//
// Bind will fail only if the socket is connected, bound or the passed address
// is invalid (the empty string).
func (e *connectionedEndpoint) Bind(addr tcpip.FullAddress, commit func() *tcpip.Error) *tcpip.Error {
	e.Lock()
	defer e.Unlock()
	if e.isBound() || e.Listening() {
		return tcpip.ErrAlreadyBound
	}
	if addr.Addr == "" {
		// The empty string is not permitted.
		return tcpip.ErrBadLocalAddress
	}
	if commit != nil {
		if err := commit(); err != nil {
			return err
		}
	}

	// Save the bound address.
	e.path = string(addr.Addr)
	return nil
}

// SendMsg writes data and a control message to the endpoint's peer.
// This method does not block if the data cannot be written.
func (e *connectionedEndpoint) SendMsg(data [][]byte, c ControlMessages, to BoundEndpoint) (uintptr, *tcpip.Error) {
	// Stream sockets do not support specifying the endpoint. Seqpacket
	// sockets ignore the passed endpoint.
	if e.stype == SockStream && to != nil {
		return 0, tcpip.ErrNotSupported
	}
	return e.baseEndpoint.SendMsg(data, c, to)
}

// Readiness returns the current readiness of the connectionedEndpoint. For
// example, if waiter.EventIn is set, the connectionedEndpoint is immediately
// readable.
func (e *connectionedEndpoint) Readiness(mask waiter.EventMask) waiter.EventMask {
	e.Lock()
	defer e.Unlock()

	ready := waiter.EventMask(0)
	switch {
	case e.Connected():
		if mask&waiter.EventIn != 0 && e.receiver.Readable() {
			ready |= waiter.EventIn
		}
		if mask&waiter.EventOut != 0 && e.connected.Writable() {
			ready |= waiter.EventOut
		}
	case e.Listening():
		if mask&waiter.EventIn != 0 && len(e.acceptedChan) > 0 {
			ready |= waiter.EventIn
		}
	}

	return ready
}
<|endoftext|>