<commit_before>// Copyright © 2017 Kent Gibson <warthog618@gmail.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

//
// Test suite for interrupt module.
//
// Tests use Raspberry Pi J8 pins 15 and 16 which must be jumpered together.
//
package gpio

import (
	"errors"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
)

func waitInterrupt(ch chan int, timeout time.Duration) (int, error) {
	expired := make(chan bool)
	go func() {
		time.Sleep(timeout)
		close(expired)
	}()
	select {
	case v := <-ch:
		return v, nil
	case <-expired:
		return 0, errors.New("timeout")
	}
}

func setupIntr(t *testing.T) (pinIn *Pin, pinOut *Pin, watcher *Watcher) {
	assert.Nil(t, Open())
	pinIn = NewPin(J8p15)
	pinOut = NewPin(J8p16)
	watcher = getDefaultWatcher()
	pinIn.SetMode(Input)
	pinOut.Write(Low)
	pinOut.SetMode(Output)
	return
}

func teardownIntr(pinIn *Pin, pinOut *Pin, watcher *Watcher) {
	pinOut.SetMode(Input)
	watcher.UnregisterPin(pinIn)
	Close()
}

func TestRegister(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	defer teardownIntr(pinIn, pinOut, watcher)
	ich := make(chan int)
	count := 0
	assert.Nil(t, watcher.RegisterPin(pinIn, EdgeRising, func(pin *Pin) {
		count++
		ich <- count
	}))
	v, err := waitInterrupt(ich, 10*time.Millisecond)
	assert.Nil(t, err)
	assert.Equal(t, 1, v)
	_, err = waitInterrupt(ich, 10*time.Millisecond)
	assert.NotNil(t, err, "Spurious interrupt")
}

func TestReregister(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	defer teardownIntr(pinIn, pinOut, watcher)
	ich := make(chan int)
	assert.Nil(t, watcher.RegisterPin(pinIn, EdgeRising, func(pin *Pin) {
		ich <- 1
	}))
	v, err := waitInterrupt(ich, 10*time.Millisecond)
	assert.Nil(t, err)
	assert.Equal(t, 1, v)
	assert.NotNil(t, watcher.RegisterPin(pinIn, EdgeRising, func(pin *Pin) {
		ich <- 2
	}), "Reregistration didn't fail.")
	pinOut.High()
	v, err = waitInterrupt(ich, 10*time.Millisecond)
	assert.Nil(t, err)
	assert.Equal(t, 1, v)
}

func TestUnregister(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	defer teardownIntr(pinIn, pinOut, watcher)
	ich := make(chan int)
	assert.Nil(t, watcher.RegisterPin(pinIn, EdgeRising, func(pin *Pin) {
		ich <- 1
	}), "Registration failed")
	v, err := waitInterrupt(ich, 10*time.Millisecond)
	assert.Nil(t, err)
	assert.Equal(t, 1, v)
	watcher.UnregisterPin(pinIn)
	pinOut.High()
	_, err = waitInterrupt(ich, 10*time.Millisecond)
	assert.NotNil(t, err)
	// And again just for coverage.
	watcher.UnregisterPin(pinIn)
}

func TestEdgeRising(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	defer teardownIntr(pinIn, pinOut, watcher)
	ich := make(chan int)
	assert.Nil(t, watcher.RegisterPin(pinIn, EdgeRising, func(pin *Pin) {
		if pin.Read() == High {
			ich <- 1
		} else {
			ich <- 0
		}
	}))
	v, err := waitInterrupt(ich, 10*time.Millisecond)
	assert.Nil(t, err)
	assert.Equal(t, 0, v)
	// Can take a while for the init to be applied before it starts triggering
	// interrupts, so wait a bit...
	time.Sleep(time.Millisecond)
	for i := 0; i < 10; i++ {
		pinOut.High()
		v, err := waitInterrupt(ich, 10*time.Millisecond)
		if err != nil {
			t.Error("Missed high at", i)
		} else if v == 0 {
			t.Error("Triggered while low at", i)
		}
		pinOut.Low()
		_, err = waitInterrupt(ich, 10*time.Millisecond)
		if err == nil {
			t.Error("Spurious or delayed trigger at", i)
		}
	}
}

func TestEdgeFalling(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	defer teardownIntr(pinIn, pinOut, watcher)
	ich := make(chan int)
	assert.Nil(t, watcher.RegisterPin(pinIn, EdgeFalling, func(pin *Pin) {
		if pin.Read() == High {
			ich <- 1
		} else {
			ich <- 0
		}
	}))
	v, err := waitInterrupt(ich, 10*time.Millisecond)
	assert.Nil(t, err)
	assert.Equal(t, 0, v)
	for i := 0; i < 10; i++ {
		pinOut.High()
		_, err := waitInterrupt(ich, 10*time.Millisecond)
		if err == nil {
			t.Error("Spurious or delayed trigger at", i)
		}
		pinOut.Low()
		v, err = waitInterrupt(ich, 10*time.Millisecond)
		if err != nil {
			t.Error("Missed low at", i)
		} else if v == 1 {
			t.Error("Triggered while low at", i)
		}
	}
}

func TestEdgeBoth(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	defer teardownIntr(pinIn, pinOut, watcher)
	ich := make(chan int)
	assert.Nil(t, watcher.RegisterPin(pinIn, EdgeBoth, func(pin *Pin) {
		if pin.Read() == High {
			ich <- 1
		} else {
			ich <- 0
		}
	}))
	v, err := waitInterrupt(ich, 10*time.Millisecond)
	assert.Nil(t, err)
	assert.Equal(t, 0, v)
	for i := 0; i < 10; i++ {
		pinOut.High()
		v, err := waitInterrupt(ich, 10*time.Millisecond)
		if err != nil {
			t.Error("Missed high at", i)
		} else if v == 0 {
			t.Error("Triggered while low at", i)
		}
		pinOut.Low()
		v, err = waitInterrupt(ich, 10*time.Millisecond)
		if err != nil {
			t.Error("Missed low at", i)
		} else if v == 1 {
			t.Error("Triggered while high at", i)
		}
	}
}

func TestEdgeNone(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	defer teardownIntr(pinIn, pinOut, watcher)
	ich := make(chan int)
	assert.Nil(t, watcher.RegisterPin(pinIn, EdgeNone, func(pin *Pin) {
		if pin.Read() == High {
			ich <- 1
		} else {
			ich <- 0
		}
	}))
	v, err := waitInterrupt(ich, 10*time.Millisecond)
	assert.Nil(t, err)
	assert.Equal(t, 0, v)
	for i := 0; i < 10; i++ {
		pinOut.High()
		v, err := waitInterrupt(ich, 10*time.Millisecond)
		if err == nil {
			t.Error("Spurious or delayed trigger at", i, v)
		}
		pinOut.Low()
		v, err = waitInterrupt(ich, 10*time.Millisecond)
		if err == nil {
			t.Error("Spurious or delayed trigger at", i, v)
		}
	}
}

func TestUnexportedEdge(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	assert.NotNil(t, setEdge(pinIn, EdgeNone))
	defer teardownIntr(pinIn, pinOut, watcher)
}

func TestCloseInterrupts(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	defer teardownIntr(pinIn, pinOut, watcher)
	ich := make(chan int)
	assert.Nil(t, watcher.RegisterPin(pinIn, EdgeNone, func(pin *Pin) {
		if pin.Read() == High {
			ich <- 1
		} else {
			ich <- 0
		}
	}))
	closeInterrupts()
	_, err := waitInterrupt(ich, 10*time.Millisecond)
	assert.NotNil(t, err, "Spurious interrupt during close")
	pinOut.High()
	_, err = waitInterrupt(ich, 10*time.Millisecond)
	assert.NotNil(t, err, "Interrupts still active after close")
}

func TestWatchExists(t *testing.T) {
	assert.Nil(t, Open())
	defer Close()
	pinIn := NewPin(J8p15)
	pinIn.SetMode(Input)
	count := 0
	assert.Nil(t, pinIn.Watch(EdgeFalling, func(pin *Pin) {
		count++
	}))
	assert.NotNil(t, pinIn.Watch(EdgeFalling, func(pin *Pin) {
		count++
	}))
	time.Sleep(2 * time.Millisecond)
	if count != 1 {
		t.Error("Second handler called")
	}
}

// Looped tests require a jumper across Raspberry Pi J8 pins 15 and 16.
// This is just a smoke test for the Watch and Unwatch methods.
func TestWatchLooped(t *testing.T) {
	assert.Nil(t, Open())
	defer Close()
	pinIn := NewPin(J8p15)
	pinOut := NewPin(J8p16)
	pinIn.SetMode(Input)
	defer pinOut.SetMode(Input)
	pinOut.Write(Low)
	pinOut.SetMode(Output)
	mode := pinOut.Mode()
	assert.Equal(t, Output, mode)
	called := false
	assert.Nil(t, pinIn.Watch(EdgeFalling, func(pin *Pin) {
		called = true
	}))
	time.Sleep(2 * time.Millisecond)
	assert.True(t, called)
	called = false
	pinOut.High()
	time.Sleep(2 * time.Millisecond)
	assert.False(t, called)
	pinOut.Low()
	time.Sleep(2 * time.Millisecond)
	assert.True(t, called)
	pinIn.Unwatch()
	called = false
	pinOut.High()
	pinOut.Low()
	time.Sleep(2 * time.Millisecond)
	assert.False(t, called)
}

// This provides a coarse estimate of the interrupt latency,
// i.e. the time between an interrupt being triggered and handled.
// There is some overhead in there due to the handshaking via a channel etc...
// so this provides an upper bound.
func BenchmarkInterruptLatency(b *testing.B) {
	assert.Nil(b, Open())
	defer Close()
	pinIn := NewPin(J8p15)
	pinOut := NewPin(J8p16)
	pinIn.SetMode(Input)
	defer pinOut.SetMode(Input)
	pinOut.Write(Low)
	pinOut.SetMode(Output)
	mode := pinOut.Mode()
	assert.Equal(b, Output, mode)
	ich := make(chan int)
	assert.Nil(b, pinIn.Watch(EdgeBoth, func(pin *Pin) {
		ich <- 1
	}))
	defer pinIn.Unwatch()
	for i := 0; i < b.N; i++ {
		pinOut.Toggle()
		waitInterrupt(ich, 10*time.Millisecond)
	}
}
<commit_msg>streamline latency benchmark<commit_after>// Copyright © 2017 Kent Gibson <warthog618@gmail.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

//
// Test suite for interrupt module.
//
// Tests use Raspberry Pi J8 pins 15 and 16 which must be jumpered together.
//
package gpio

import (
	"errors"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
)

func waitInterrupt(ch chan int, timeout time.Duration) (int, error) {
	select {
	case v := <-ch:
		return v, nil
	case <-time.After(timeout):
		return 0, errors.New("timeout")
	}
}

func setupIntr(t *testing.T) (pinIn *Pin, pinOut *Pin, watcher *Watcher) {
	assert.Nil(t, Open())
	pinIn = NewPin(J8p15)
	pinOut = NewPin(J8p16)
	watcher = getDefaultWatcher()
	pinIn.SetMode(Input)
	pinOut.Write(Low)
	pinOut.SetMode(Output)
	return
}

func teardownIntr(pinIn *Pin, pinOut *Pin, watcher *Watcher) {
	pinOut.SetMode(Input)
	watcher.UnregisterPin(pinIn)
	Close()
}

func TestRegister(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	defer teardownIntr(pinIn, pinOut, watcher)
	ich := make(chan int)
	count := 0
	assert.Nil(t, watcher.RegisterPin(pinIn, EdgeRising, func(pin *Pin) {
		count++
		ich <- count
	}))
	v, err := waitInterrupt(ich, 10*time.Millisecond)
	assert.Nil(t, err)
	assert.Equal(t, 1, v)
	_, err = waitInterrupt(ich, 10*time.Millisecond)
	assert.NotNil(t, err, "Spurious interrupt")
}

func TestReregister(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	defer teardownIntr(pinIn, pinOut, watcher)
	ich := make(chan int)
	assert.Nil(t, watcher.RegisterPin(pinIn, EdgeRising, func(pin *Pin) {
		ich <- 1
	}))
	v, err := waitInterrupt(ich, 10*time.Millisecond)
	assert.Nil(t, err)
	assert.Equal(t, 1, v)
	assert.NotNil(t, watcher.RegisterPin(pinIn, EdgeRising, func(pin *Pin) {
		ich <- 2
	}), "Reregistration didn't fail.")
	pinOut.High()
	v, err = waitInterrupt(ich, 10*time.Millisecond)
	assert.Nil(t, err)
	assert.Equal(t, 1, v)
}

func TestUnregister(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	defer teardownIntr(pinIn, pinOut, watcher)
	ich := make(chan int)
	assert.Nil(t, watcher.RegisterPin(pinIn, EdgeRising, func(pin *Pin) {
		ich <- 1
	}), "Registration failed")
	v, err := waitInterrupt(ich, 10*time.Millisecond)
	assert.Nil(t, err)
	assert.Equal(t, 1, v)
	watcher.UnregisterPin(pinIn)
	pinOut.High()
	_, err = waitInterrupt(ich, 10*time.Millisecond)
	assert.NotNil(t, err)
	// And again just for coverage.
	watcher.UnregisterPin(pinIn)
}

func TestEdgeRising(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	defer teardownIntr(pinIn, pinOut, watcher)
	ich := make(chan int)
	assert.Nil(t, watcher.RegisterPin(pinIn, EdgeRising, func(pin *Pin) {
		if pin.Read() == High {
			ich <- 1
		} else {
			ich <- 0
		}
	}))
	v, err := waitInterrupt(ich, 10*time.Millisecond)
	assert.Nil(t, err)
	assert.Equal(t, 0, v)
	// Can take a while for the init to be applied before it starts triggering
	// interrupts, so wait a bit...
	time.Sleep(time.Millisecond)
	for i := 0; i < 10; i++ {
		pinOut.High()
		v, err := waitInterrupt(ich, 10*time.Millisecond)
		if err != nil {
			t.Error("Missed high at", i)
		} else if v == 0 {
			t.Error("Triggered while low at", i)
		}
		pinOut.Low()
		_, err = waitInterrupt(ich, 10*time.Millisecond)
		if err == nil {
			t.Error("Spurious or delayed trigger at", i)
		}
	}
}

func TestEdgeFalling(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	defer teardownIntr(pinIn, pinOut, watcher)
	ich := make(chan int)
	assert.Nil(t, watcher.RegisterPin(pinIn, EdgeFalling, func(pin *Pin) {
		if pin.Read() == High {
			ich <- 1
		} else {
			ich <- 0
		}
	}))
	v, err := waitInterrupt(ich, 10*time.Millisecond)
	assert.Nil(t, err)
	assert.Equal(t, 0, v)
	for i := 0; i < 10; i++ {
		pinOut.High()
		_, err := waitInterrupt(ich, 10*time.Millisecond)
		if err == nil {
			t.Error("Spurious or delayed trigger at", i)
		}
		pinOut.Low()
		v, err = waitInterrupt(ich, 10*time.Millisecond)
		if err != nil {
			t.Error("Missed low at", i)
		} else if v == 1 {
			t.Error("Triggered while low at", i)
		}
	}
}

func TestEdgeBoth(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	defer teardownIntr(pinIn, pinOut, watcher)
	ich := make(chan int)
	assert.Nil(t, watcher.RegisterPin(pinIn, EdgeBoth, func(pin *Pin) {
		if pin.Read() == High {
			ich <- 1
		} else {
			ich <- 0
		}
	}))
	v, err := waitInterrupt(ich, 10*time.Millisecond)
	assert.Nil(t, err)
	assert.Equal(t, 0, v)
	for i := 0; i < 10; i++ {
		pinOut.High()
		v, err := waitInterrupt(ich, 10*time.Millisecond)
		if err != nil {
			t.Error("Missed high at", i)
		} else if v == 0 {
			t.Error("Triggered while low at", i)
		}
		pinOut.Low()
		v, err = waitInterrupt(ich, 10*time.Millisecond)
		if err != nil {
			t.Error("Missed low at", i)
		} else if v == 1 {
			t.Error("Triggered while high at", i)
		}
	}
}

func TestEdgeNone(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	defer teardownIntr(pinIn, pinOut, watcher)
	ich := make(chan int)
	assert.Nil(t, watcher.RegisterPin(pinIn, EdgeNone, func(pin *Pin) {
		if pin.Read() == High {
			ich <- 1
		} else {
			ich <- 0
		}
	}))
	v, err := waitInterrupt(ich, 10*time.Millisecond)
	assert.Nil(t, err)
	assert.Equal(t, 0, v)
	for i := 0; i < 10; i++ {
		pinOut.High()
		v, err := waitInterrupt(ich, 10*time.Millisecond)
		if err == nil {
			t.Error("Spurious or delayed trigger at", i, v)
		}
		pinOut.Low()
		v, err = waitInterrupt(ich, 10*time.Millisecond)
		if err == nil {
			t.Error("Spurious or delayed trigger at", i, v)
		}
	}
}

func TestUnexportedEdge(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	assert.NotNil(t, setEdge(pinIn, EdgeNone))
	defer teardownIntr(pinIn, pinOut, watcher)
}

func TestCloseInterrupts(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	defer teardownIntr(pinIn, pinOut, watcher)
	ich := make(chan int)
	assert.Nil(t, watcher.RegisterPin(pinIn, EdgeNone, func(pin *Pin) {
		if pin.Read() == High {
			ich <- 1
		} else {
			ich <- 0
		}
	}))
	closeInterrupts()
	_, err := waitInterrupt(ich, 10*time.Millisecond)
	assert.NotNil(t, err, "Spurious interrupt during close")
	pinOut.High()
	_, err = waitInterrupt(ich, 10*time.Millisecond)
	assert.NotNil(t, err, "Interrupts still active after close")
}

func TestWatchExists(t *testing.T) {
	assert.Nil(t, Open())
	defer Close()
	pinIn := NewPin(J8p15)
	pinIn.SetMode(Input)
	count := 0
	assert.Nil(t, pinIn.Watch(EdgeFalling, func(pin *Pin) {
		count++
	}))
	assert.NotNil(t, pinIn.Watch(EdgeFalling, func(pin *Pin) {
		count++
	}))
	time.Sleep(2 * time.Millisecond)
	if count != 1 {
		t.Error("Second handler called")
	}
}

// Looped tests require a jumper across Raspberry Pi J8 pins 15 and 16.
// This is just a smoke test for the Watch and Unwatch methods.
func TestWatchLooped(t *testing.T) {
	assert.Nil(t, Open())
	defer Close()
	pinIn := NewPin(J8p15)
	pinOut := NewPin(J8p16)
	pinIn.SetMode(Input)
	defer pinOut.SetMode(Input)
	pinOut.Write(Low)
	pinOut.SetMode(Output)
	mode := pinOut.Mode()
	assert.Equal(t, Output, mode)
	called := false
	assert.Nil(t, pinIn.Watch(EdgeFalling, func(pin *Pin) {
		called = true
	}))
	time.Sleep(2 * time.Millisecond)
	assert.True(t, called)
	called = false
	pinOut.High()
	time.Sleep(2 * time.Millisecond)
	assert.False(t, called)
	pinOut.Low()
	time.Sleep(2 * time.Millisecond)
	assert.True(t, called)
	pinIn.Unwatch()
	called = false
	pinOut.High()
	pinOut.Low()
	time.Sleep(2 * time.Millisecond)
	assert.False(t, called)
}

// This provides a coarse estimate of the interrupt latency,
// i.e. the time between an interrupt being triggered and handled.
// There is some overhead in there due to the handshaking via a channel etc...
// so this provides an upper bound.
func BenchmarkInterruptLatency(b *testing.B) {
	assert.Nil(b, Open())
	defer Close()
	pinIn := NewPin(J8p15)
	pinOut := NewPin(J8p16)
	pinIn.SetMode(Input)
	defer pinOut.SetMode(Input)
	pinOut.Write(Low)
	pinOut.SetMode(Output)
	mode := pinOut.Mode()
	assert.Equal(b, Output, mode)
	ich := make(chan int)
	assert.Nil(b, pinIn.Watch(EdgeBoth, func(pin *Pin) {
		ich <- 1
	}))
	defer pinIn.Unwatch()
	for i := 0; i < b.N; i++ {
		pinOut.Toggle()
		<-ich
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"time"

	"google.golang.org/api/drive/v2"
)

type getFile struct {
	finished bool

	directory string
	name      string
	id        string
	size      int64
}

// Returns a list of IDs representing the files under the folder given. Returns only one id if it references a file.
func getIdList(cl *drive.Service, basedir string, root string, is_id bool, idchan chan getFile) {
	getIdListRecursive(cl, basedir, root, is_id, idchan)

	// Send one "finished" message per downloader thread
	for i := 0; i < FLAG_par; i++ {
		idchan <- getFile{finished: true}
	}

	return
}

func getIdListRecursive(cl *drive.Service, basedir, root string, is_id bool, idchan chan getFile) {

	if !is_id {
		for {
			q := "title = '" + root + "'"

			fl, err := cl.Files.List().Q(q).MaxResults(100).Do()

			if err != nil {
				log.Println(err)
				continue
			}

			for i, f := range fl.Items {
				if f.MimeType != "application/vnd.google-apps.folder" {
					if i > 0 {
						idchan <- getFile{directory: basedir, id: f.Id, name: fmt.Sprintf("%d_%s", i, f.Title), size: f.FileSize}
					} else {
						idchan <- getFile{directory: basedir, id: f.Id, name: f.Title, size: f.FileSize}
					}
				} else {
					getIdListRecursive(cl, basedir+f.Title+"/", f.Id, true, idchan)
				}
			}
			break
		}
	} else {
		nextPageToken := ""
		// loop while results are coming (continuing using a continuation token)
		for {
			clist, err := cl.Children.List(root).MaxResults(1000).PageToken(nextPageToken).Do()

			if err != nil {
				log.Println(err)
				time.Sleep(250 * time.Millisecond)
				continue
			}

			nextPageToken = clist.NextPageToken
			fmt.Println(nextPageToken)

			if len(clist.Items) == 0 {
				for {
					f, err := cl.Files.Get(root).Do()

					if err != nil {
						log.Println(err)
						time.Sleep(250 * time.Millisecond)
						continue
					}
					idchan <- getFile{id: root, directory: basedir, name: f.Title, size: f.FileSize}
					break
				}
				break
			} else {
				for _, child := range clist.Items {
					for {
						f, err := cl.Files.Get(child.Id).Do()

						if err != nil {
							log.Println(err)
							time.Sleep(250 * time.Millisecond)
							continue
						}
						if f.MimeType != "application/vnd.google-apps.folder" {
							idchan <- getFile{directory: basedir, id: f.Id, name: f.Title, size: f.FileSize}
						} else {
							getIdListRecursive(cl, basedir+f.Title+"/", f.Id, true, idchan)
						}
						break
					}
				}
			}
		}
	}
}

func getFiles(cl *drive.Service, idchan chan getFile, wg *sync.WaitGroup) error {
	defer wg.Done()

	for file := range idchan {
		if file.finished {
			return nil
		}

		if file.directory != "" {
			os.MkdirAll(file.directory, 0755)
		}

		f, err := os.OpenFile(filepath.Join(file.directory, file.name), os.O_WRONLY|os.O_CREATE, 0644)

		if err != nil {
			log.Println(err)
			continue
		}

		for {
			fmt.Printf("...%s (%s)\n", file.name, sizeToString(file.size))

			resp, err := cl.Files.Get(file.id).Download()

			if err != nil && (strings.Contains(err.Error(), "403") || strings.Contains(err.Error(), "500")) {
				fmt.Println("Retrying", file.name)
				time.Sleep(250 * time.Millisecond)
				continue
			}

			if err != nil && (strings.Contains(err.Error(), "400") || strings.Contains(err.Error(), "404")) {
				log.Println("Couldn't download", file.name)
				break
			}

			if err != nil {
				log.Println("Couldn't download", file.name)
				log.Println(err)
				break
			}

			var i int64

			for {
				n, err := io.CopyN(f, resp.Body, file.size/100)
				if err != nil {
					break
				}
				i += n
			}

			fmt.Printf("Finished %s\n", file.name)

			f.Close()
			resp.Body.Close()

			break
		}

	}

	return nil
}
<commit_msg>Skip download of existing files (to resume a download)<commit_after>package main

import (
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"time"

	"google.golang.org/api/drive/v2"
)

type getFile struct {
	finished bool

	directory string
	name      string
	id        string
	size      int64
}

// Returns a list of IDs representing the files under the folder given. Returns only one id if it references a file.
func getIdList(cl *drive.Service, basedir string, root string, is_id bool, idchan chan getFile) {
	getIdListRecursive(cl, basedir, root, is_id, idchan)

	// Send one "finished" message per downloader thread
	for i := 0; i < FLAG_par; i++ {
		idchan <- getFile{finished: true}
	}

	return
}

func getIdListRecursive(cl *drive.Service, basedir, root string, is_id bool, idchan chan getFile) {

	if !is_id {
		for {
			q := "title = '" + root + "'"

			fl, err := cl.Files.List().Q(q).MaxResults(100).Do()

			if err != nil {
				log.Println(err)
				continue
			}

			for i, f := range fl.Items {
				if f.MimeType != "application/vnd.google-apps.folder" {
					if i > 0 {
						idchan <- getFile{directory: basedir, id: f.Id, name: fmt.Sprintf("%d_%s", i, f.Title), size: f.FileSize}
					} else {
						idchan <- getFile{directory: basedir, id: f.Id, name: f.Title, size: f.FileSize}
					}
				} else {
					getIdListRecursive(cl, basedir+f.Title+"/", f.Id, true, idchan)
				}
			}
			break
		}
	} else {
		nextPageToken := ""
		// loop while results are coming (continuing using a continuation token)
		for {
			clist, err := cl.Children.List(root).MaxResults(1000).PageToken(nextPageToken).Do()

			if err != nil {
				log.Println(err)
				time.Sleep(250 * time.Millisecond)
				continue
			}

			nextPageToken = clist.NextPageToken
			fmt.Println(nextPageToken)

			if len(clist.Items) == 0 {
				for {
					f, err := cl.Files.Get(root).Do()

					if err != nil {
						log.Println(err)
						time.Sleep(250 * time.Millisecond)
						continue
					}
					idchan <- getFile{id: root, directory: basedir, name: f.Title, size: f.FileSize}
					break
				}
				break
			} else {
				for _, child := range clist.Items {
					for {
						f, err := cl.Files.Get(child.Id).Do()

						if err != nil {
							log.Println(err)
							time.Sleep(250 * time.Millisecond)
							continue
						}
						if f.MimeType != "application/vnd.google-apps.folder" {
							idchan <- getFile{directory: basedir, id: f.Id, name: f.Title, size: f.FileSize}
						} else {
							getIdListRecursive(cl, basedir+f.Title+"/", f.Id, true, idchan)
						}
						break
					}
				}
			}
		}
	}
}

func getFiles(cl *drive.Service, idchan chan getFile, wg *sync.WaitGroup) error {
	defer wg.Done()

	for file := range idchan {
		if file.finished {
			return nil
		}

		if file.directory != "" {
			os.MkdirAll(file.directory, 0755)
		}

		if _, err := os.Stat(filepath.Join(file.directory, file.name)); err == nil {
		    fmt.Println("Skipped existing file", filepath.Join(file.directory, file.name))
		    continue
		}

		f, err := os.OpenFile(filepath.Join(file.directory, file.name), os.O_WRONLY|os.O_CREATE, 0644)

		if err != nil {
			log.Println(err)
			continue
		}

		for {
			fmt.Printf("...%s (%s)\n", file.name, sizeToString(file.size))

			resp, err := cl.Files.Get(file.id).Download()

			if err != nil && (strings.Contains(err.Error(), "403") || strings.Contains(err.Error(), "500")) {
				fmt.Println("Retrying", file.name)
				time.Sleep(250 * time.Millisecond)
				continue
			}

			if err != nil && (strings.Contains(err.Error(), "400") || strings.Contains(err.Error(), "404")) {
				log.Println("Couldn't download", file.name)
				break
			}

			if err != nil {
				log.Println("Couldn't download", file.name)
				log.Println(err)
				break
			}

			var i int64

			for {
				n, err := io.CopyN(f, resp.Body, file.size/100)
				if err != nil {
					break
				}
				i += n
			}

			fmt.Printf("Finished %s\n", file.name)

			f.Close()
			resp.Body.Close()

			break
		}

	}

	return nil
}
<|endoftext|>


<commit_before>package driver

import (
	"fmt"
	"net"
	"syscall"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/vishvananda/netlink"
	"github.com/vishvananda/netlink/nl"
	"sync"
)

const neighChanLen = 256

func (d *Driver) tryAddress(addr *net.IPNet) error {
	r, err := d.ns.probeAndWait(addr)
	if err != nil {
		log.WithError(err).Fatal("Error determining if addr is reachable")
		return err
	}
	if r {
		return fmt.Errorf("Address already in use: %v", addr)
	}
	return nil
}

func (ns *neighSubscription) addrStatus(addr net.IP) (known, reachable bool) {
	neighList, err := netlink.NeighList(0, netlink.FAMILY_V4)
	if err != nil {
		log.WithError(err).Error("Error refreshing neighbor table.")
		return
	}
	for _, n := range neighList {
		if n.IP.Equal(addr) {
			return parseAddrStatus(&n)
		}
	}
	return
}

func parseAddrStatus(n *netlink.Neigh) (known, reachable bool) {
	if n != nil {
		known = n.State == netlink.NUD_FAILED || n.State == netlink.NUD_REACHABLE
		reachable = known && n.State != netlink.NUD_FAILED
		return
	}
	return
}

type neighSubscription struct {
	quit     <-chan struct{}
	addSubCh chan *subscription
}

type subscription struct {
	ip      *net.IPNet
	created time.Time
	sub     chan *netlink.Neigh
	close   chan struct{}
}

func (ns *neighSubscription) probeAndWait(addr *net.IPNet) (reachable bool, err error) {
	var known bool
	known, reachable = ns.addrStatus(addr.IP)
	if known {
		return
	}

	t := time.NewTicker(1 * time.Second)
	to := time.Now().Add(5 * time.Second)
	defer t.Stop()
	sub := ns.addSub(addr)
	defer sub.delSub()

	probe(addr.IP)
	for {
		select {
		case <-ns.quit:
			return
		case n := <-sub.sub:
			known, reachable = parseAddrStatus(n)
			if known {
				return
			}
		case <-t.C:
		}
		known, reachable = ns.addrStatus(addr.IP)
		if known {
			return
		}
		if time.Now().After(to) {
			return true, fmt.Errorf("Error determining reachability for %v", addr)
		}
		probe(addr.IP)
	}
}

func (ns *neighSubscription) addSub(ip *net.IPNet) *subscription {
	sub := &subscription{
		ip:      ip,
		created: time.Now(),
		sub:     make(chan *netlink.Neigh, neighChanLen),
		close:   make(chan struct{}),
	}
	go func() { ns.addSubCh <- sub }()
	return sub
}

func (sub *subscription) delSub() {
	close(sub.close)
}

type neighUpdate struct {
	time  time.Time
	neigh *netlink.Neigh
}

func newNeighSubscription(quit <-chan struct{}) *neighSubscription {
	ns := &neighSubscription{
		quit:     quit,
		addSubCh: make(chan *subscription),
	}
	return ns
}

func (ns *neighSubscription) start() error {
	quit := ns.quit
	defer close(ns.addSubCh)
	wg := sync.WaitGroup{}

	s, err := nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_NEIGH)
	if err != nil {
		return err
	}

	wg.Add(1)
	go func() {
		defer wg.Done()
		<-quit
		s.Close()
	}()

	neighSubCh := make(chan []*neighUpdate, neighChanLen)
	wg.Add(1)
	go func() {
		defer wg.Done()
		for {
			for {
				msgs, err := s.Receive()
				select {
				case <-quit:
					return
				default:
				}

				if err != nil {
					log.WithError(err).Error("Error recieving neighbor update")
				}
				t := time.Now()
				go func(t time.Time) {
					var ns []*neighUpdate
					for _, m := range msgs {
						n, err := netlink.NeighDeserialize(m.Data)
						if err != nil {
							log.Errorf("Error deserializing neighbor message %v", m.Data)
							continue
						}
						ns = append(ns, &neighUpdate{
							time:  t,
							neigh: n,
						})
					}
					neighSubCh <- ns
				}(t)
			}
		}
	}()

	subs := make(map[string][]*subscription)
	wg.Add(1)
	go func() {
		defer wg.Done()
		for {
			select {
			case <-quit:
				return
			case sub := <-ns.addSubCh:
				subs[sub.ip.String()] = append(subs[sub.ip.String()], sub)
				continue
			case neighList := <-neighSubCh:
				for _, n := range neighList {
					sendNeighUpdates(n.neigh, subs[n.neigh.IP.String()])
				}
				continue
			}
		}
	}()

	wg.Wait()
	return nil
}

func sendNeighUpdates(n *netlink.Neigh, subs []*subscription) {
	l := len(subs)
	for i := range subs {
		j := l - i - 1 // loop in reverse order
		sub := subs[j]
		select {
		// Delete closed subs
		case <-sub.close:
			subs = append(subs[:j], subs[j+1:]...)
			close(sub.sub)
		// Send the update
		default:
			go func(sub *subscription, n *netlink.Neigh) {
				sub.sub <- n
			}(sub, n)
		}
	}
}

func probe(ip net.IP) {
	conn, err := net.Dial("udp", ip.String()+":8765")
	if err != nil {
		log.WithError(err).WithField("ip", ip).Error("Error creating probe connection.")
		return
	}
	if _, err := conn.Write([]byte("probe")); err != nil {
		log.WithError(err).WithField("ip", ip).Error("Error probing connection.")
	}
	if err := conn.Close(); err != nil {
		log.WithError(err).WithField("ip", ip).Error("Error clossing probe connection.")
	}
	return
}
<commit_msg>longer timeout for probe and wait<commit_after>package driver

import (
	"fmt"
	"net"
	"syscall"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/vishvananda/netlink"
	"github.com/vishvananda/netlink/nl"
	"sync"
)

const neighChanLen = 256

func (d *Driver) tryAddress(addr *net.IPNet) error {
	r, err := d.ns.probeAndWait(addr)
	if err != nil {
		log.WithError(err).Fatal("Error determining if addr is reachable")
		return err
	}
	if r {
		return fmt.Errorf("Address already in use: %v", addr)
	}
	return nil
}

func (ns *neighSubscription) addrStatus(addr net.IP) (known, reachable bool) {
	neighList, err := netlink.NeighList(0, netlink.FAMILY_V4)
	if err != nil {
		log.WithError(err).Error("Error refreshing neighbor table.")
		return
	}
	for _, n := range neighList {
		if n.IP.Equal(addr) {
			return parseAddrStatus(&n)
		}
	}
	return
}

func parseAddrStatus(n *netlink.Neigh) (known, reachable bool) {
	if n != nil {
		known = n.State == netlink.NUD_FAILED || n.State == netlink.NUD_REACHABLE
		reachable = known && n.State != netlink.NUD_FAILED
		return
	}
	return
}

type neighSubscription struct {
	quit     <-chan struct{}
	addSubCh chan *subscription
}

type subscription struct {
	ip      *net.IPNet
	created time.Time
	sub     chan *netlink.Neigh
	close   chan struct{}
}

func (ns *neighSubscription) probeAndWait(addr *net.IPNet) (reachable bool, err error) {
	var known bool
	known, reachable = ns.addrStatus(addr.IP)
	if known {
		return
	}

	t := time.NewTicker(1 * time.Second)
	to := time.Now().Add(8 * time.Second)
	defer t.Stop()
	sub := ns.addSub(addr)
	defer sub.delSub()

	probe(addr.IP)
	for {
		select {
		case <-ns.quit:
			return
		case n := <-sub.sub:
			known, reachable = parseAddrStatus(n)
			if known {
				return
			}
		case <-t.C:
		}
		known, reachable = ns.addrStatus(addr.IP)
		if known {
			return
		}
		if time.Now().After(to) {
			return true, fmt.Errorf("Error determining reachability for %v", addr)
		}
		probe(addr.IP)
	}
}

func (ns *neighSubscription) addSub(ip *net.IPNet) *subscription {
	sub := &subscription{
		ip:      ip,
		created: time.Now(),
		sub:     make(chan *netlink.Neigh, neighChanLen),
		close:   make(chan struct{}),
	}
	go func() { ns.addSubCh <- sub }()
	return sub
}

func (sub *subscription) delSub() {
	close(sub.close)
}

type neighUpdate struct {
	time  time.Time
	neigh *netlink.Neigh
}

func newNeighSubscription(quit <-chan struct{}) *neighSubscription {
	ns := &neighSubscription{
		quit:     quit,
		addSubCh: make(chan *subscription),
	}
	return ns
}

func (ns *neighSubscription) start() error {
	quit := ns.quit
	defer close(ns.addSubCh)
	wg := sync.WaitGroup{}

	s, err := nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_NEIGH)
	if err != nil {
		return err
	}

	wg.Add(1)
	go func() {
		defer wg.Done()
		<-quit
		s.Close()
	}()

	neighSubCh := make(chan []*neighUpdate, neighChanLen)
	wg.Add(1)
	go func() {
		defer wg.Done()
		for {
			for {
				msgs, err := s.Receive()
				select {
				case <-quit:
					return
				default:
				}

				if err != nil {
					log.WithError(err).Error("Error recieving neighbor update")
				}
				t := time.Now()
				go func(t time.Time) {
					var ns []*neighUpdate
					for _, m := range msgs {
						n, err := netlink.NeighDeserialize(m.Data)
						if err != nil {
							log.Errorf("Error deserializing neighbor message %v", m.Data)
							continue
						}
						ns = append(ns, &neighUpdate{
							time:  t,
							neigh: n,
						})
					}
					neighSubCh <- ns
				}(t)
			}
		}
	}()

	subs := make(map[string][]*subscription)
	wg.Add(1)
	go func() {
		defer wg.Done()
		for {
			select {
			case <-quit:
				return
			case sub := <-ns.addSubCh:
				subs[sub.ip.String()] = append(subs[sub.ip.String()], sub)
				continue
			case neighList := <-neighSubCh:
				for _, n := range neighList {
					sendNeighUpdates(n.neigh, subs[n.neigh.IP.String()])
				}
				continue
			}
		}
	}()

	wg.Wait()
	return nil
}

func sendNeighUpdates(n *netlink.Neigh, subs []*subscription) {
	l := len(subs)
	for i := range subs {
		j := l - i - 1 // loop in reverse order
		sub := subs[j]
		select {
		// Delete closed subs
		case <-sub.close:
			subs = append(subs[:j], subs[j+1:]...)
			close(sub.sub)
		// Send the update
		default:
			go func(sub *subscription, n *netlink.Neigh) {
				sub.sub <- n
			}(sub, n)
		}
	}
}

func probe(ip net.IP) {
	conn, err := net.Dial("udp", ip.String()+":8765")
	if err != nil {
		log.WithError(err).WithField("ip", ip).Error("Error creating probe connection.")
		return
	}
	if _, err := conn.Write([]byte("probe")); err != nil {
		log.WithError(err).WithField("ip", ip).Error("Error probing connection.")
	}
	if err := conn.Close(); err != nil {
		log.WithError(err).WithField("ip", ip).Error("Error clossing probe connection.")
	}
	return
}
<|endoftext|>


<commit_before>// Interface for all container drivers

package drivers

type Driver interface {
	Run(*models.Job) RunResult
}

// RunResult will provide methods to access the job completion status, logs, etc.
type RunResult interface {

}
<commit_msg>driver/docker: start porting gorunner Docker driver to Titan<commit_after>// Interface for all container drivers

package drivers

import "os"

type Driver interface {
	// Run(*models.Job) RunResult
	Run(task ContainerTask, isCancelled chan bool) RunResult
}

// RunResult will provide methods to access the job completion status, logs, etc.
type RunResult interface {
	// Err() is an actionable/checkable error from the container.
	Error() error

	// Status() should return the current status of the task.
	// It must never return Enqueued.
	Status() string

	// Log() will be a Reader interface that allows the driver to read the content
	// of the log output for the task that was run.
	// Each driver is free to implement this in its own way, either streaming or at
	// the end of execution.
	//
	// It must return a valid Reader at any time.
	Log() *os.File // TODO: change to io.Reader
}

type ContainerTask interface {
	Command() string
	Config() string
	EnvVars() map[string]string
	Id() string
	Image() string
	Payload() string
	Timeout() uint
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"github.com/gorilla/mux"
	"io"
	"io/ioutil"
	"koding/kontrol/kontrolproxy/proxyconfig"
	"net/http"
)

type FiltersPostMessage struct {
	FilterType  *string `json:"type"`
	FilterName  *string `json:"name"`
	FilterMatch *string `json:"match"`
}

func GetFilters(writer http.ResponseWriter, req *http.Request) {
	fmt.Println("GET\t/filters")
	res := proxyDB.GetFilters()
	data, err := json.MarshalIndent(res, "", "  ")
	if err != nil {
		http.Error(writer, fmt.Sprintf("{\"err\":\"%s\"}\n", err), http.StatusBadRequest)
		return
	}

	writer.Write([]byte(data))
}

func GetFilter(writer http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	match := vars["match"]
	fmt.Printf("GET\t/filters/%s\n", match)

	res, err := proxyDB.GetFilter(match)
	if err != nil {
		http.Error(writer, fmt.Sprintf("{\"err\":\"%s\"}\n", err), http.StatusBadRequest)
		return
	}

	data, err := json.MarshalIndent(res, "", "  ")
	if err != nil {
		http.Error(writer, fmt.Sprintf("{\"err\":\"%s\"}\n", err), http.StatusBadRequest)
		return
	}
	writer.Write([]byte(data))
}

func CreateFilterByMatch(writer http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	match := vars["domain"]
	fmt.Printf("POST\t/filters/%s\n", match)

	var msg FiltersPostMessage
	var filterType string

	body, _ := ioutil.ReadAll(req.Body)
	err := json.Unmarshal(body, &msg)
	if err != nil {
		http.Error(writer, fmt.Sprintf("{\"err\":\"%s\"}\n", err), http.StatusBadRequest)
		return
	}

	if match == "" {
		err := "match field can't be empty"
		http.Error(writer, fmt.Sprintf("{\"err\":\"%s\"}\n", err), http.StatusBadRequest)
		return
	}
	if msg.FilterType != nil {
		filterType = *msg.FilterType
	} else {
		err := "no 'type' field available"
		http.Error(writer, fmt.Sprintf("{\"err\":\"%s\"}\n", err), http.StatusBadRequest)
		return
	}

	// disabled for now, is generated automatically
	// if msg.FilterName != nil {
	// 	ruleName = *msg.FilterName
	// } else {
	// 	err := "no 'name' field available"
	// 	http.Error(writer, fmt.Sprintf("{\"err\":\"%s\"}\n", err), http.StatusBadRequest)
	// 	return
	// }

	filter := proxyconfig.NewFilter(filterType, "", match)
	resFilter, err := proxyDB.AddFilter(filter)
	if err != nil {
		http.Error(writer, fmt.Sprintf("{\"err\":\"%s\"}\n", err), http.StatusBadRequest)
		return
	}

	data, err := json.MarshalIndent(resFilter, "", "  ")
	if err != nil {
		http.Error(writer, fmt.Sprintf("{\"err\":\"%s\"}\n", err), http.StatusBadRequest)
		return
	}
	writer.Write([]byte(data))
	return
}

func DeleteFilterByMatch(writer http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	match := vars["match"]
	fmt.Printf("DELETE\t/filters/%s\n", match)

	err := proxyDB.DeleteFilter(match)
	if err != nil {
		http.Error(writer, fmt.Sprintf("{\"err\":\"%s\"}\n", err), http.StatusBadRequest)
		return
	}

	resp := fmt.Sprintf("filter with match '%s' is deleted", match)
	io.WriteString(writer, fmt.Sprintf("{\"res\":\"%s\"}\n", resp))
	return
}
<commit_msg>kontrolapi: fix wrong key<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"github.com/gorilla/mux"
	"io"
	"io/ioutil"
	"koding/kontrol/kontrolproxy/proxyconfig"
	"net/http"
)

type FiltersPostMessage struct {
	FilterType  *string `json:"type"`
	FilterName  *string `json:"name"`
	FilterMatch *string `json:"match"`
}

func GetFilters(writer http.ResponseWriter, req *http.Request) {
	fmt.Println("GET\t/filters")
	res := proxyDB.GetFilters()
	data, err := json.MarshalIndent(res, "", "  ")
	if err != nil {
		http.Error(writer, fmt.Sprintf("{\"err\":\"%s\"}\n", err), http.StatusBadRequest)
		return
	}

	writer.Write([]byte(data))
}

func GetFilter(writer http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	match := vars["match"]
	fmt.Printf("GET\t/filters/%s\n", match)

	res, err := proxyDB.GetFilter(match)
	if err != nil {
		http.Error(writer, fmt.Sprintf("{\"err\":\"%s\"}\n", err), http.StatusBadRequest)
		return
	}

	data, err := json.MarshalIndent(res, "", "  ")
	if err != nil {
		http.Error(writer, fmt.Sprintf("{\"err\":\"%s\"}\n", err), http.StatusBadRequest)
		return
	}
	writer.Write([]byte(data))
}

func CreateFilterByMatch(writer http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	match := vars["match"]
	fmt.Printf("POST\t/filters/%s\n", match)

	var msg FiltersPostMessage
	var filterType string

	body, _ := ioutil.ReadAll(req.Body)
	err := json.Unmarshal(body, &msg)
	if err != nil {
		http.Error(writer, fmt.Sprintf("{\"err\":\"%s\"}\n", err), http.StatusBadRequest)
		return
	}

	if match == "" {
		err := "match field can't be empty"
		http.Error(writer, fmt.Sprintf("{\"err\":\"%s\"}\n", err), http.StatusBadRequest)
		return
	}
	if msg.FilterType != nil {
		filterType = *msg.FilterType
	} else {
		err := "no 'type' field available"
		http.Error(writer, fmt.Sprintf("{\"err\":\"%s\"}\n", err), http.StatusBadRequest)
		return
	}

	// disabled for now, is generated automatically
	// if msg.FilterName != nil {
	// 	ruleName = *msg.FilterName
	// } else {
	// 	err := "no 'name' field available"
	// 	http.Error(writer, fmt.Sprintf("{\"err\":\"%s\"}\n", err), http.StatusBadRequest)
	// 	return
	// }

	filter := proxyconfig.NewFilter(filterType, "", match)
	resFilter, err := proxyDB.AddFilter(filter)
	if err != nil {
		http.Error(writer, fmt.Sprintf("{\"err\":\"%s\"}\n", err), http.StatusBadRequest)
		return
	}

	data, err := json.MarshalIndent(resFilter, "", "  ")
	if err != nil {
		http.Error(writer, fmt.Sprintf("{\"err\":\"%s\"}\n", err), http.StatusBadRequest)
		return
	}
	writer.Write([]byte(data))
	return
}

func DeleteFilterByMatch(writer http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	match := vars["match"]
	fmt.Printf("DELETE\t/filters/%s\n", match)

	err := proxyDB.DeleteFilter(match)
	if err != nil {
		http.Error(writer, fmt.Sprintf("{\"err\":\"%s\"}\n", err), http.StatusBadRequest)
		return
	}

	resp := fmt.Sprintf("filter with match '%s' is deleted", match)
	io.WriteString(writer, fmt.Sprintf("{\"res\":\"%s\"}\n", resp))
	return
}
<|endoftext|>


<commit_before>package models

type ChannelContainer struct {
	Channel             Channel                  `json:"channel"`
	IsParticipant       bool                     `json:"isParticipant"`
	ParticipantCount    int                      `json:"participantCount"`
	ParticipantsPreview []string                 `json:"participantsPreview"`
	LastMessage         *ChannelMessageContainer `json:"lastMessage"`
	UnreadCount         int                      `json:"unreadCount"`
	Err                 error                    `json:"-"`
}

func NewChannelContainer() *ChannelContainer {
	return &ChannelContainer{}
}

func (c *ChannelContainer) ById(id int64) (*ChannelContainer, error) {
	return c, nil
}

func PopulateChannelContainers(channelList []Channel, accountId int64) ([]*ChannelContainer, error) {
	channelContainers := make([]*ChannelContainer, len(channelList))

	var err error
	for i, channel := range channelList {
		channelContainers[i], err = PopulateChannelContainer(channel, accountId)
		if err != nil {
			return nil, err
		}
	}

	return channelContainers, nil
}

func PopulateChannelContainersWithUnreadCount(channelList []Channel, accountId int64) ([]*ChannelContainer, error) {
	channelContainers, err := PopulateChannelContainers(channelList, accountId)
	if err != nil {
		return nil, err
	}

	cml := NewChannelMessageList()
	for i, container := range channelContainers {
		if !container.IsParticipant {
			continue
		}

		cp := NewChannelParticipant()
		cp.ChannelId = container.Channel.Id
		cp.AccountId = accountId
		if err := cp.FetchParticipant(); err != nil {
			// helper.MustGetLogger().Error(err.Error())
			continue
		}

		// for private messages calculate the unread reply count
		if container.Channel.TypeConstant == Channel_TYPE_PRIVATE_MESSAGE {
			if container.LastMessage == nil || container.LastMessage.Message == nil || container.LastMessage.Message.Id == 0 {
				continue
			}

			count, err := NewMessageReply().UnreadCount(container.LastMessage.Message.Id, cp.LastSeenAt)
			if err != nil {
				continue
			}

			channelContainers[i].UnreadCount = count
			continue
		}

		count, _ := cml.UnreadCount(cp)
		if err != nil {
			// helper.MustGetLogger().Error(err.Error())
			continue
		}
		channelContainers[i].UnreadCount = count
	}

	return channelContainers, nil
}

func PopulateChannelContainer(channel Channel, accountId int64) (*ChannelContainer, error) {
	cp := NewChannelParticipant()
	cp.ChannelId = channel.Id

	// add participantCount
	participantCount, err := cp.FetchParticipantCount()
	if err != nil {
		return nil, err
	}

	// add participant preview
	cpList, err := cp.ListAccountIds(5)
	if err != nil {
		return nil, err
	}

	// add participation status
	isParticipant, err := cp.IsParticipant(accountId)
	if err != nil {
		return nil, err
	}

	cc := NewChannelContainer()
	cc.Channel = channel
	cc.IsParticipant = isParticipant
	cc.ParticipantCount = participantCount
	participantOldIds, err := FetchAccountOldsIdByIdsFromCache(cpList)
	if err != nil {
		return nil, err
	}

	cc.ParticipantsPreview = participantOldIds

	// add last message of the channel
	cm, err := channel.FetchLastMessage()
	if err != nil {
		return nil, err
	}

	if cm != nil {
		cmc, err := cm.BuildEmptyMessageContainer()
		if err != nil {
			return nil, err
		}
		cc.LastMessage = cmc
	}

	return cc, nil
}
<commit_msg>Social: added AddUnreadCount function for  ChannelContainer with chaining support<commit_after>package models

type ChannelContainer struct {
	Channel             Channel                  `json:"channel"`
	IsParticipant       bool                     `json:"isParticipant"`
	ParticipantCount    int                      `json:"participantCount"`
	ParticipantsPreview []string                 `json:"participantsPreview"`
	LastMessage         *ChannelMessageContainer `json:"lastMessage"`
	UnreadCount         int                      `json:"unreadCount"`
	Err                 error                    `json:"-"`
}

func NewChannelContainer() *ChannelContainer {
	return &ChannelContainer{}
}

func (c *ChannelContainer) ById(id int64) (*ChannelContainer, error) {
	return c, nil
}

func PopulateChannelContainers(channelList []Channel, accountId int64) ([]*ChannelContainer, error) {
	channelContainers := make([]*ChannelContainer, len(channelList))

	var err error
	for i, channel := range channelList {
		channelContainers[i], err = PopulateChannelContainer(channel, accountId)
		if err != nil {
			return nil, err
		}
	}

	return channelContainers, nil
}

func PopulateChannelContainersWithUnreadCount(channelList []Channel, accountId int64) ([]*ChannelContainer, error) {
	channelContainers, err := PopulateChannelContainers(channelList, accountId)
	if err != nil {
		return nil, err
	}

	cml := NewChannelMessageList()
	for i, container := range channelContainers {
		if !container.IsParticipant {
			continue
		}

		cp := NewChannelParticipant()
		cp.ChannelId = container.Channel.Id
		cp.AccountId = accountId
		if err := cp.FetchParticipant(); err != nil {
			// helper.MustGetLogger().Error(err.Error())
			continue
		}

		// for private messages calculate the unread reply count
		if container.Channel.TypeConstant == Channel_TYPE_PRIVATE_MESSAGE {
			if container.LastMessage == nil || container.LastMessage.Message == nil || container.LastMessage.Message.Id == 0 {
				continue
			}

			count, err := NewMessageReply().UnreadCount(container.LastMessage.Message.Id, cp.LastSeenAt)
			if err != nil {
				continue
			}

			channelContainers[i].UnreadCount = count
			continue
		}

		count, _ := cml.UnreadCount(cp)
		if err != nil {
			// helper.MustGetLogger().Error(err.Error())
			continue
		}
		channelContainers[i].UnreadCount = count
	}

	return channelContainers, nil
}

func PopulateChannelContainer(channel Channel, accountId int64) (*ChannelContainer, error) {
	cp := NewChannelParticipant()
	cp.ChannelId = channel.Id

	// add participantCount
	participantCount, err := cp.FetchParticipantCount()
	if err != nil {
		return nil, err
	}

	// add participant preview
	cpList, err := cp.ListAccountIds(5)
	if err != nil {
		return nil, err
	}

	// add participation status
	isParticipant, err := cp.IsParticipant(accountId)
	if err != nil {
		return nil, err
func (cr *ChannelContainer) AddUnreadCount(accountId int64) *ChannelContainer {
	return withChecks(cr, func(cc *ChannelContainer) error {

		cml := NewChannelMessageList()

		// if the user is not a participant of the channel, do not add unread
		// count
		if !cc.IsParticipant {
			return nil
		}

		// for private messages calculate the unread reply count
		if cc.Channel.TypeConstant == Channel_TYPE_PRIVATE_MESSAGE {
			// validate that last message is set
			if cc.LastMessage == nil || cc.LastMessage.Message == nil || cc.LastMessage.Message.Id == 0 {
				return nil
			}

			cp, err := getChannelParticipant(cc.Channel.Id, accountId)
			if err != nil {
				return err
			}

			count, err := NewMessageReply().UnreadCount(cc.LastMessage.Message.Id, cp.LastSeenAt)
			if err != nil {
				return err
			}

			cc.UnreadCount = count
			return nil
		}

		cp, err := getChannelParticipant(cc.Channel.Id, accountId)
		if err != nil {
			return err
		}

		count, err := cml.UnreadCount(cp)
		if err != nil {
			return err
		}

		cc.UnreadCount = count

		return nil

	})
}
	}

	cc := NewChannelContainer()
	cc.Channel = channel
	cc.IsParticipant = isParticipant
	cc.ParticipantCount = participantCount
	participantOldIds, err := FetchAccountOldsIdByIdsFromCache(cpList)
	if err != nil {
		return nil, err
	}

	cc.ParticipantsPreview = participantOldIds

	// add last message of the channel
	cm, err := channel.FetchLastMessage()
	if err != nil {
		return nil, err
	}

	if cm != nil {
		cmc, err := cm.BuildEmptyMessageContainer()
		if err != nil {
			return nil, err
		}
		cc.LastMessage = cmc
	}

	return cc, nil
}
<|endoftext|>


<commit_before>/*
 * The Alluxio Open Foundation licenses this work under the Apache License, version 2.0
 * (the "License"). You may not use this work except in compliance with the License, which is
 * available at www.apache.org/licenses/LICENSE-2.0
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied, as more fully set forth in the License.
 *
 * See the NOTICE file distributed with this work for information regarding copyright ownership.
 */

package cmd

import (
	"fmt"
	"strings"

	"v.io/x/lib/cmdline"
)

var (
	cmdRelease = &cmdline.Command{
		Name:   "release",
		Short:  "Generates all release tarballs",
		Long:   "Generates all release tarballs",
		Runner: cmdline.RunnerFunc(release),
	}

	hadoopDistributionsFlag string
)

func init() {
	cmdRelease.Flags.StringVar(&hadoopDistributionsFlag, "hadoop-distributions", strings.Join(validHadoopDistributions(), ","), "a comma-separated list of hadoop distributions to generate Alluxio distributions for")
}

func checkReleaseFlags() error {
	for _, distribution := range strings.Split(hadoopDistributionsFlag, ",") {
		_, ok := hadoopDistributions[distribution]
		if !ok {
			return fmt.Errorf("hadoop distribution %s not recognized\n", distribution)
		}
	}
	return nil
}

func release(_ *cmdline.Env, _ []string) error {
	if err := checkReleaseFlags(); err != nil {
		return err
	}
	if err := generateTarballs(); err != nil {
		return err
	}
	return nil
}

func generateTarballs() error {
	for _, distribution := range strings.Split(hadoopDistributionsFlag, ",") {
		if distribution == "default" {
			targetFlag = fmt.Sprintf("alluxio-%v-bin.tar.gz", versionMarker)
		} else {
			targetFlag = fmt.Sprintf("alluxio-%v-%v.tar.gz", versionMarker, distribution)
		}
		fmt.Printf("Generating distribution for %v at %v", distribution, targetFlag)
		if err := generateTarball(distribution); err != nil {
			return err
		}
	}
	return nil
}
<commit_msg>Include -bin in generated release tarballs (#7593)<commit_after>/*
 * The Alluxio Open Foundation licenses this work under the Apache License, version 2.0
 * (the "License"). You may not use this work except in compliance with the License, which is
 * available at www.apache.org/licenses/LICENSE-2.0
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied, as more fully set forth in the License.
 *
 * See the NOTICE file distributed with this work for information regarding copyright ownership.
 */

package cmd

import (
	"fmt"
	"strings"

	"v.io/x/lib/cmdline"
)

var (
	cmdRelease = &cmdline.Command{
		Name:   "release",
		Short:  "Generates all release tarballs",
		Long:   "Generates all release tarballs",
		Runner: cmdline.RunnerFunc(release),
	}

	hadoopDistributionsFlag string
)

func init() {
	cmdRelease.Flags.StringVar(&hadoopDistributionsFlag, "hadoop-distributions", strings.Join(validHadoopDistributions(), ","), "a comma-separated list of hadoop distributions to generate Alluxio distributions for")
}

func checkReleaseFlags() error {
	for _, distribution := range strings.Split(hadoopDistributionsFlag, ",") {
		_, ok := hadoopDistributions[distribution]
		if !ok {
			return fmt.Errorf("hadoop distribution %s not recognized\n", distribution)
		}
	}
	return nil
}

func release(_ *cmdline.Env, _ []string) error {
	if err := checkReleaseFlags(); err != nil {
		return err
	}
	if err := generateTarballs(); err != nil {
		return err
	}
	return nil
}

func generateTarballs() error {
	for _, distribution := range strings.Split(hadoopDistributionsFlag, ",") {
		if distribution == "default" {
			targetFlag = fmt.Sprintf("alluxio-%v-bin.tar.gz", versionMarker)
		} else {
			targetFlag = fmt.Sprintf("alluxio-%v-%v-bin.tar.gz", versionMarker, distribution)
		}
		fmt.Printf("Generating distribution for %v at %v", distribution, targetFlag)
		if err := generateTarball(distribution); err != nil {
			return err
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net/http"
	"os"
	"io/ioutil"
	"bytes"
	storage "github.com/MSOpenTech/azure-sdk-for-go/storage"
	fb "github.com/huandu/facebook"
	"code.google.com/p/gorest"
)

func main() {

    gorest.RegisterService(new(DropletServer))
    http.Handle("/",gorest.Handle())
    http.ListenAndServe(":8080",nil)

    res, _ := fb.Get("/4", fb.Params{
        "fields": "username",
    })
    fmt.Println("here is my facebook username:", res["username"])

}

type Droplet struct{
    Id             int
    Content        string
}

type DropletServer struct {
    gorest.RestService `root:"/" consumes:"application/json" produces:"application/json"`

	item    gorest.EndPoint `method:"GET" path:"/item/{Id:int}" output:"Droplet"`
    items   gorest.EndPoint `method:"GET" path:"/items/" output:"[]Droplet"`
    insert  gorest.EndPoint `method:"POST" path:"/insert/" postdata:"[]Droplet"`
    getDroplet    gorest.EndPoint `method:"GET" 	path:"/d/{userName:string}/{dropletName:string}" output:"Droplet"`
    getDroplets   gorest.EndPoint `method:"GET" 	path:"/d/{userName:string}" output:"[]Droplet"`
    putDroplet    gorest.EndPoint `method:"POST" 	path:"/d/{userName:string}/{dropletName:string}" postdata:"Droplet"`
}

func(serv DropletServer) Item(Id int) Droplet {
    serv.ResponseBuilder().SetResponseCode(200)
    item := Droplet {Id:Id, Content:"Name with id returned"}
    return item
}

func(serv DropletServer) Items() []Droplet{
    serv.ResponseBuilder().SetResponseCode(200)
    slice := []Droplet{
      Droplet {Id:0, Content:"Name 0"},
      Droplet {Id:1, Content:"Name 1"},
    }

    item := Droplet {Id:200, Content:"Name 4"}
    slice = append(slice, item)

    return slice
}

func(serv DropletServer) Insert(items []Droplet) {
    fmt.Println("Got a request to insert items")
    fmt.Println("Item Count", len(items))
    serv.ResponseBuilder().SetResponseCode(200)
}

var blobClient *storage.BlobStorageClient

func(serv DropletServer) GetDroplets(userName string) []Droplet {
	if blobClient == nil {
    	err := initializeBlobClient()
    	 if err != nil {

    	}
    }

	droplets := []Droplet{}
	marker := ""
	for {
		resp, err := blobClient.ListBlobs(userName, storage.ListBlobsParameters{
			MaxResults: 1024,
			Marker:     marker})
		if err != nil {
			serv.ResponseBuilder().SetResponseCode(500)
			return []Droplet{}
		}

		for _, v := range resp.Blobs {

			fmt.Printf(v.Name)
			err, droplet := getDropletItem(userName, v.Name)

		    if err != nil {
		    	serv.ResponseBuilder().SetResponseCode(500)
		    	return nil
		    }

			droplets = append(droplets, droplet)
		}

		marker = resp.NextMarker

		if marker == "" || len(resp.Blobs) == 0 {
			break
		}
	}

	return droplets;
}

func(serv DropletServer) GetDroplet(userName string, dropletName string) Droplet {
    serv.ResponseBuilder().SetResponseCode(200)

    if blobClient == nil {
    	err := initializeBlobClient()
    	 if err != nil {
    	 	serv.ResponseBuilder().SetResponseCode(500)
    		return Droplet{}
    	}
    }

    err, droplet := getDropletItem(userName, dropletName)

    if err != nil {
    	serv.ResponseBuilder().SetResponseCode(500)
    	return Droplet{}
    }

    return droplet
}

func getDropletItem(userName string, dropletName string) (error, Droplet) {

    resp, err := blobClient.GetBlob(userName, dropletName)

	if err != nil {
		fmt.Printf("Error trying to check blob contents!\n")
		return err, Droplet{}
	}

	respBody, err := ioutil.ReadAll(resp)

	defer resp.Close()

	if err != nil {
		fmt.Printf("Error trying to get blob contents!\n")
		return err, Droplet{}
	}

	contents := string(respBody[:len(respBody)])

    item := Droplet {Id:100, Content:contents}

    return nil, item
}

func(serv DropletServer) PutDroplet(droplet Droplet, userName string, dropletName string)  {

    if blobClient == nil {
    	err := initializeBlobClient()
    	 if err != nil {
    		return;
    	}
    }

    // Create the blob and add contents to it
	err := blobClient.PutBlockBlob(userName, dropletName, bytes.NewReader([]byte(droplet.Content)))

	if err == nil {
		serv.ResponseBuilder().SetResponseCode(200)
	} else {
		serv.ResponseBuilder().SetResponseCode(500)
	}
}

func initializeBlobClient() (error) {
	name := os.Getenv("STORAGE_ACCOUNT_NAME")
	key := os.Getenv("STORAGE_KEY")
	cli, err := storage.NewBasicClient(name, key)

	if err != nil {
		return err
	}

	blobClient = cli.GetBlobService()
	return nil
}<commit_msg>add ability to add a bunch of droplets<commit_after>package main

import (
	"fmt"
	"net/http"
	"os"
	"io/ioutil"
	"bytes"
	storage "github.com/MSOpenTech/azure-sdk-for-go/storage"
	fb "github.com/huandu/facebook"
	"code.google.com/p/gorest"
)

func main() {

    gorest.RegisterService(new(DropletServer))
    http.Handle("/",gorest.Handle())
    http.ListenAndServe(":8080",nil)

    res, _ := fb.Get("/4", fb.Params{
        "fields": "username",
    })
    fmt.Println("here is my facebook username:", res["username"])

}

type Droplet struct{
    Id             int
    Name           string
    Content        string
}

type DropletServer struct {
    gorest.RestService `root:"/" consumes:"application/json" produces:"application/json"`

	item    gorest.EndPoint `method:"GET" path:"/item/{Id:int}" output:"Droplet"`
    items   gorest.EndPoint `method:"GET" path:"/items/" output:"[]Droplet"`
    insert  gorest.EndPoint `method:"POST" path:"/insert/" postdata:"[]Droplet"`
    getDroplet    gorest.EndPoint `method:"GET" 	path:"/d/{userName:string}/{dropletName:string}" output:"Droplet"`
    getDroplets   gorest.EndPoint `method:"GET" 	path:"/d/{userName:string}" output:"[]Droplet"`
    putDroplet    gorest.EndPoint `method:"POST" 	path:"/d/{userName:string}/{dropletName:string}" postdata:"Droplet"`
    putDroplets   gorest.EndPoint `method:"POST" 	path:"/d/{userName:string}" postdata:"[]Droplet"`
}

func(serv DropletServer) Item(Id int) Droplet {
    serv.ResponseBuilder().SetResponseCode(200)
    item := Droplet {Id:Id, Content:"Name with id returned"}
    return item
}

func(serv DropletServer) Items() []Droplet{
    serv.ResponseBuilder().SetResponseCode(200)
    slice := []Droplet{
      Droplet {Id:0, Content:"Name 0"},
      Droplet {Id:1, Content:"Name 1"},
    }

    item := Droplet {Id:200, Content:"Name 4"}
    slice = append(slice, item)

    return slice
}

func(serv DropletServer) Insert(items []Droplet) {
    fmt.Println("Got a request to insert items")
    fmt.Println("Item Count", len(items))
    serv.ResponseBuilder().SetResponseCode(200)
}

var blobClient *storage.BlobStorageClient

func(serv DropletServer) GetDroplets(userName string) []Droplet {
	if blobClient == nil {
    	err := initializeBlobClient()
    	 if err != nil {

    	}
    }

	droplets := []Droplet{}
	marker := ""
	for {
		resp, err := blobClient.ListBlobs(userName, storage.ListBlobsParameters{
			MaxResults: 1024,
			Marker:     marker})
		if err != nil {
			serv.ResponseBuilder().SetResponseCode(500)
			return []Droplet{}
		}

		for _, v := range resp.Blobs {

			fmt.Println("getDroplets: ", v.Name)
			err, droplet := getDropletItem(userName, v.Name)

		    if err != nil {
		    	serv.ResponseBuilder().SetResponseCode(500)
		    	return nil
		    }

			droplets = append(droplets, droplet)
		}

		marker = resp.NextMarker

		if marker == "" || len(resp.Blobs) == 0 {
			break
		}
	}

	return droplets;
}

func(serv DropletServer) GetDroplet(userName string, dropletName string) Droplet {
    serv.ResponseBuilder().SetResponseCode(200)

    if blobClient == nil {
    	err := initializeBlobClient()
    	 if err != nil {
    	 	serv.ResponseBuilder().SetResponseCode(500)
    		return Droplet{}
    	}
    }

    err, droplet := getDropletItem(userName, dropletName)

    if err != nil {
    	serv.ResponseBuilder().SetResponseCode(500)
    	return Droplet{}
    }

    return droplet
}

func getDropletItem(userName string, dropletName string) (error, Droplet) {

    resp, err := blobClient.GetBlob(userName, dropletName)

	if err != nil {
		fmt.Println("getDropletItem: Error trying to check blob contents!\n")
		return err, Droplet{}
	}

	respBody, err := ioutil.ReadAll(resp)

	defer resp.Close()

	if err != nil {
		fmt.Println("getDropletItem: Error trying to get blob contents!\n")
		return err, Droplet{}
	}

	contents := string(respBody[:len(respBody)])

    item := Droplet {Id:100, Name:dropletName, Content:contents}

    return nil, item
}

func(serv DropletServer) PutDroplet(droplet Droplet, userName string, dropletName string)  {

    // Create the blob and add contents to it
	err := putDropletItem(userName, droplet.Name, droplet)

	if err == nil {
		serv.ResponseBuilder().SetResponseCode(200)
	} else {
		serv.ResponseBuilder().SetResponseCode(500)
	}
}

func putDropletItem(userName string, dropletName string, droplet Droplet) (error) {
	if blobClient == nil {
    	err := initializeBlobClient()
    	 if err != nil {
    	 	fmt.Println("putDropletItem: ", err)
    		return err;
    	}
    }

    // Create the blob and add contents to it
	return blobClient.PutBlockBlob(userName, dropletName, bytes.NewReader([]byte(droplet.Content)))
}

func(serv DropletServer) PutDroplets(droplets []Droplet, userName string)  {

    if blobClient == nil {
    	err := initializeBlobClient()
    	 if err != nil {
    	 	fmt.Println("PutDroplets: ", err)
    		return;
    	}
    }

    for _, droplet := range droplets {
    	fmt.Println("PutDroplets: Processing ", droplet.Name)
	    err := putDropletItem(userName, droplet.Name, droplet)

		if err != nil {
			fmt.Println("PutDroplets: Error ", err)
			serv.ResponseBuilder().SetResponseCode(500)
			return
		}
	}

	serv.ResponseBuilder().SetResponseCode(200)
}

func initializeBlobClient() (error) {
	name := os.Getenv("STORAGE_ACCOUNT_NAME")
	key := os.Getenv("STORAGE_KEY")
	cli, err := storage.NewBasicClient(name, key)

	if err != nil {
		return err
	}

	blobClient = cli.GetBlobService()
	return nil
}<|endoftext|>


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

package dummy

import "github.com/zagrodzki/goscope/scope"

type triangleChan struct{}

func (triangleChan) ID() scope.ChanID                   { return "triangle" }
func (triangleChan) GetVoltRange() scope.VoltRange      { return 1 }
func (triangleChan) GetVoltRanges() []scope.VoltRange   { return []scope.VoltRange{1} }
func (triangleChan) SetVoltRange(scope.VoltRange) error { return nil }
func (ch triangleChan) data(offset int) []scope.Sample {
	ret := make([]scope.Sample, numSamples)
	for i := 0; i < numSamples; i++ {
		if i%40 < 20 {
			ret[i] = scope.Sample(float64((i+offset)%20-10) / 10)
		} else {
			ret[i] = scope.Sample(float64(30-(i+offset)%40) / 10)
		}
	}
	return ret
}
<commit_msg>Use the same offset in the switch as in the value calculation.<commit_after>//  Copyright 2016 The goscope Authors
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.

package dummy

import "github.com/zagrodzki/goscope/scope"

type triangleChan struct{}

func (triangleChan) ID() scope.ChanID                   { return "triangle" }
func (triangleChan) GetVoltRange() scope.VoltRange      { return 1 }
func (triangleChan) GetVoltRanges() []scope.VoltRange   { return []scope.VoltRange{1} }
func (triangleChan) SetVoltRange(scope.VoltRange) error { return nil }
func (ch triangleChan) data(offset int) []scope.Sample {
	ret := make([]scope.Sample, numSamples)
	for i := 0; i < numSamples; i++ {
		if (i+offset)%40 < 20 {
			ret[i] = scope.Sample(float64((i+offset)%20-10) / 10)
		} else {
			ret[i] = scope.Sample(float64(30-(i+offset)%40) / 10)
		}
	}
	return ret
}
<|endoftext|>


<commit_before>package profile

import (
	"errors"

	"github.com/fatih/structs"
	"github.com/godbus/dbus"
	"github.com/muka/go-bluetooth/bluez"
)

// NewGattCharacteristic1 create a new GattCharacteristic1 client
func NewGattCharacteristic1(path string) *GattCharacteristic1 {
	g := new(GattCharacteristic1)
	g.client = bluez.NewClient(
		&bluez.Config{
			Name:  "org.bluez",
			Iface: bluez.GattCharacteristic1Interface,
			Path:  path,
			Bus:   bluez.SystemBus,
		},
	)

	g.Properties = new(GattCharacteristic1Properties)

	_, err := g.GetProperties()
	if err != nil {
		panic(err)
	}

	return g
}

// GattCharacteristic1 client
type GattCharacteristic1 struct {
	client     *bluez.Client
	Properties *GattCharacteristic1Properties
	channel    chan *dbus.Signal
}

// GattCharacteristic1Properties exposed properties for GattCharacteristic1
type GattCharacteristic1Properties struct {
	Value          []byte
	Notifying      bool
	NotifyAcquired bool
	WriteAcquired  bool
	Service        dbus.ObjectPath
	UUID           string
	Flags          []string
	Descriptors    []dbus.ObjectPath
}

//ToMap serialize properties
func (d *GattCharacteristic1Properties) ToMap() (map[string]interface{}, error) {
	if !d.Service.IsValid() {
		return nil, errors.New("GattCharacteristic1Properties: Service ObjectPath is not valid")
	}
	for i := 0; i < len(d.Descriptors); i++ {
		if d.Descriptors[i].IsValid() {
			return nil, errors.New("GattCharacteristic1Properties: Descriptors contains an ObjectPath that is not valid")
		}
	}
	return structs.Map(d), nil
}

// Close the connection
func (d *GattCharacteristic1) Close() {
	d.client.Disconnect()
}

//Register for changes signalling
func (d *GattCharacteristic1) Register() (chan *dbus.Signal, error) {
	if d.channel == nil {
		channel, err := d.client.Register(d.client.Config.Path, bluez.PropertiesInterface)
		if err != nil {
			return nil, err
		}
		d.channel = channel
	}
	return d.channel, nil
}

//Unregister for changes signalling
func (d *GattCharacteristic1) Unregister() error {
	if d.channel != nil {
		close(d.channel)
	}
	return d.client.Unregister(d.client.Config.Path, bluez.PropertiesInterface)
}

//GetProperties load all available properties
func (d *GattCharacteristic1) GetProperties() (*GattCharacteristic1Properties, error) {
	err := d.client.GetProperties(d.Properties)
	return d.Properties, err
}

//GetProperty load a single property
func (d *GattCharacteristic1) GetProperty(name string) (interface{}, error) {
	val, err := d.client.GetProperty(name)
	if err != nil {
		return nil, err
	}
	return val.Value(), nil
}

//ReadValue read a value from a characteristic
func (d *GattCharacteristic1) ReadValue(options map[string]dbus.Variant) ([]byte, error) {
	var b []byte
	err := d.client.Call("ReadValue", 0, options).Store(&b)
	return b, err
}

//WriteValue write a value to a characteristic
func (d *GattCharacteristic1) WriteValue(b []byte, options map[string]dbus.Variant) error {
	err := d.client.Call("WriteValue", 0, b, options).Store()
	return err
}

//StartNotify start notifications
func (d *GattCharacteristic1) StartNotify() error {
	return d.client.Call("StartNotify", 0).Store()
}

//StopNotify stop notifications
func (d *GattCharacteristic1) StopNotify() error {
	return d.client.Call("StopNotify", 0).Store()
}

//AcquireWrite acquire file descriptor and MTU for writing [experimental]
func (d *GattCharacteristic1) AcquireWrite() (dbus.UnixFD, uint16, error) {
	var fd dbus.UnixFD
	var mtu uint16
	err := d.client.Call("AcquireWrite", 0).Store(&fd, &mtu)
	return fd, mtu, err
}

//AcquireNotify acquire file descriptor and MTU for notify [experimental]
func (d *GattCharacteristic1) AcquireNotify() (dbus.UnixFD, uint16, error) {
	var fd dbus.UnixFD
	var mtu uint16
	err := d.client.Call("AcquireNotify", 0).Store(&fd, &mtu)
	return fd, mtu, err
}
<commit_msg>Determining the path/source of an update is much easier when the characteristic knows it's own path.<commit_after>package profile

import (
	"errors"

	"github.com/fatih/structs"
	"github.com/godbus/dbus"
	"github.com/muka/go-bluetooth/bluez"
)

// NewGattCharacteristic1 create a new GattCharacteristic1 client
func NewGattCharacteristic1(path string) *GattCharacteristic1 {
	g := new(GattCharacteristic1)
	g.client = bluez.NewClient(
		&bluez.Config{
			Name:  "org.bluez",
			Iface: bluez.GattCharacteristic1Interface,
			Path:  path,
			Bus:   bluez.SystemBus,
		},
	)

	g.Path = path

	g.Properties = new(GattCharacteristic1Properties)

	_, err := g.GetProperties()
	if err != nil {
		panic(err)
	}

	return g
}

// GattCharacteristic1 client
type GattCharacteristic1 struct {
	client     *bluez.Client
	Properties *GattCharacteristic1Properties
	channel    chan *dbus.Signal
	Path       string
}

// GattCharacteristic1Properties exposed properties for GattCharacteristic1
type GattCharacteristic1Properties struct {
	Value          []byte
	Notifying      bool
	NotifyAcquired bool
	WriteAcquired  bool
	Service        dbus.ObjectPath
	UUID           string
	Flags          []string
	Descriptors    []dbus.ObjectPath
}

//ToMap serialize properties
func (d *GattCharacteristic1Properties) ToMap() (map[string]interface{}, error) {
	if !d.Service.IsValid() {
		return nil, errors.New("GattCharacteristic1Properties: Service ObjectPath is not valid")
	}
	for i := 0; i < len(d.Descriptors); i++ {
		if d.Descriptors[i].IsValid() {
			return nil, errors.New("GattCharacteristic1Properties: Descriptors contains an ObjectPath that is not valid")
		}
	}
	return structs.Map(d), nil
}

// Close the connection
func (d *GattCharacteristic1) Close() {
	d.client.Disconnect()
}

//Register for changes signalling
func (d *GattCharacteristic1) Register() (chan *dbus.Signal, error) {
	if d.channel == nil {
		channel, err := d.client.Register(d.client.Config.Path, bluez.PropertiesInterface)
		if err != nil {
			return nil, err
		}
		d.channel = channel
	}
	return d.channel, nil
}

//Unregister for changes signalling
func (d *GattCharacteristic1) Unregister() error {
	if d.channel != nil {
		close(d.channel)
	}
	return d.client.Unregister(d.client.Config.Path, bluez.PropertiesInterface)
}

//GetProperties load all available properties
func (d *GattCharacteristic1) GetProperties() (*GattCharacteristic1Properties, error) {
	err := d.client.GetProperties(d.Properties)
	return d.Properties, err
}

//GetProperty load a single property
func (d *GattCharacteristic1) GetProperty(name string) (interface{}, error) {
	val, err := d.client.GetProperty(name)
	if err != nil {
		return nil, err
	}
	return val.Value(), nil
}

//ReadValue read a value from a characteristic
func (d *GattCharacteristic1) ReadValue(options map[string]dbus.Variant) ([]byte, error) {
	var b []byte
	err := d.client.Call("ReadValue", 0, options).Store(&b)
	return b, err
}

//WriteValue write a value to a characteristic
func (d *GattCharacteristic1) WriteValue(b []byte, options map[string]dbus.Variant) error {
	err := d.client.Call("WriteValue", 0, b, options).Store()
	return err
}

//StartNotify start notifications
func (d *GattCharacteristic1) StartNotify() error {
	return d.client.Call("StartNotify", 0).Store()
}

//StopNotify stop notifications
func (d *GattCharacteristic1) StopNotify() error {
	return d.client.Call("StopNotify", 0).Store()
}

//AcquireWrite acquire file descriptor and MTU for writing [experimental]
func (d *GattCharacteristic1) AcquireWrite() (dbus.UnixFD, uint16, error) {
	var fd dbus.UnixFD
	var mtu uint16
	err := d.client.Call("AcquireWrite", 0).Store(&fd, &mtu)
	return fd, mtu, err
}

//AcquireNotify acquire file descriptor and MTU for notify [experimental]
func (d *GattCharacteristic1) AcquireNotify() (dbus.UnixFD, uint16, error) {
	var fd dbus.UnixFD
	var mtu uint16
	err := d.client.Call("AcquireNotify", 0).Store(&fd, &mtu)
	return fd, mtu, err
}
<|endoftext|>


<commit_before>package latest

import (
	"encoding/json"
	"github.com/gorilla/mux"
	"github.com/jinzhu/gorm"
	"net/http"
	"strconv"
)

type Orders struct {
	gorm.Model
	Project     string `gorm:"not null"`
	Environment string `gorm:"not null"` // poc,dev,staging,prod
	CostCentre  int    `gorm:"not null"`
	Owner       string `gorm:"not null"`
	Service     string `gorm:"not null"` // aws_account,aws_ami, aws_j5
	Tier        string // Tier: 1,2,3
	Status      string `sql:"DEFAULT:'submitted'"`
	Tracking    string
	Account     Accounts
	Image       Images
}

type Accounts struct {
	gorm.Model
	Environment string `gorm:"not null"`
	Version     int    `gorm:"not null"`
	AccountId   int    `gorm:"not null;unique"`
	Status      string
	Email       string `gorm:"not null;unique"`
}

type Images struct {
	gorm.Model
	Reference   string `gorm:"not null;unique"`
	Description string `gorm:"not null"`
}

// ** ACCOUNTS ** WEB HANDLERS

func (app *App) get_accounts(w http.ResponseWriter, r *http.Request) {

	accounts, rowCount := get_accounts(app.Db)

	if rowCount == 0 {
		respondWithError(w, 404, "record not found")
		return
	}

	respondWithJSON(w, http.StatusOK, accounts)

}

func (app *App) get_account(w http.ResponseWriter, r *http.Request) {

	vars := mux.Vars(r)
	id, err := strconv.Atoi(vars["id"])

	if err != nil {
		respondWithError(w, http.StatusBadRequest, "invalid id")
		return
	}

	account := Accounts{Model: gorm.Model{ID: uint(id)}}

	if RecordNotFound := account.get(app.Db); RecordNotFound {
		respondWithError(w, 404, "record not found")
		return
	}

	respondWithJSON(w, http.StatusOK, account)

}

func (app *App) create_account(w http.ResponseWriter, r *http.Request) {

	var account Accounts
	decoder := json.NewDecoder(r.Body)

	if err := decoder.Decode(&account); err != nil {
		respondWithError(w, http.StatusBadRequest, "invalid request payload")
		return
	}
	defer r.Body.Close()

	if err := account.create(app.Db); err != nil {
		respondWithError(w, http.StatusBadRequest, err.Error())
		return
	}

	respondWithJSON(w, http.StatusCreated, account)

}

// ** ACCOUNTS ** DATABASE HANDLERS

func (account *Accounts) create(db *gorm.DB) (err error) {
	return db.Create(&account).Error
}

func get_accounts(db *gorm.DB) (account []Accounts, rowCount int64) {

	var accounts []Accounts
	rowCount = db.Find(&accounts).RowsAffected

	return accounts, rowCount
}

func (account *Accounts) get(db *gorm.DB) (RecordNotFound bool) {
	return db.First(&account, &account.ID).RecordNotFound()
}

//func (a *Accounts) update(db *gorm.DB) {
//	db.Save(&a).Where("Id", &a.Id)
//}
//
//func (a *Accounts) del(db *gorm.DB) {
//	db.Delete(a).Where("Id", &a.Id)
//}
<commit_msg>Account Model using GORM<commit_after>package latest

import (
	"encoding/json"
	"github.com/gorilla/mux"
	"github.com/jinzhu/gorm"
	"net/http"
	"strconv"
)

type Orders struct {
	gorm.Model
	Project     string `gorm:"not null"`
	Environment string `gorm:"not null"` // poc,dev,staging,prod
	CostCentre  int    `gorm:"not null"`
	Owner       string `gorm:"not null"`
	Service     string `gorm:"not null"` // aws_account,aws_ami, aws_j5
	Tier        string // Tier: 1,2,3
	Status      string `sql:"DEFAULT:'submitted'"`
	Tracking    string
	Account     Accounts
	Image       Images
}

type Accounts struct {
	gorm.Model
	Environment string `gorm:"not null"`
	Version     int    `gorm:"not null"`
	AccountId   int    `gorm:"not null;unique"`
	Status      string
	Email       string `gorm:"not null;unique"`
}

type Images struct {
	gorm.Model
	Reference   string `gorm:"not null;unique"`
	Description string `gorm:"not null"`
}

// ** ACCOUNTS ** WEB HANDLERS

func (app *App) get_accounts(w http.ResponseWriter, r *http.Request) {

	accounts, rowCount := get_accounts(app.Db)

	if rowCount == 0 {
		respondWithError(w, 404, "record not found")
		return
	}

	respondWithJSON(w, http.StatusOK, accounts)

}

func (app *App) get_account(w http.ResponseWriter, r *http.Request) {

	vars := mux.Vars(r)
	id, err := strconv.Atoi(vars["id"])

	if err != nil {
		respondWithError(w, http.StatusBadRequest, "invalid id")
		return
	}

	account := Accounts{Model: gorm.Model{ID: uint(id)}}

	if RecordNotFound := account.get(app.Db); RecordNotFound {
		respondWithError(w, 404, "record not found")
		return
	}

	respondWithJSON(w, http.StatusOK, account)

}

func (app *App) create_account(w http.ResponseWriter, r *http.Request) {

	var account Accounts
	decoder := json.NewDecoder(r.Body)

	if err := decoder.Decode(&account); err != nil {
		respondWithError(w, http.StatusBadRequest, "invalid request payload")
		return
	}
	defer r.Body.Close()

	if err := account.create(app.Db); err != nil {
		respondWithError(w, http.StatusBadRequest, err.Error())
		return
	}

	respondWithJSON(w, http.StatusCreated, account)

}

// ** ACCOUNTS ** DATABASE HANDLERS

func (account *Accounts) create(db *gorm.DB) (err error) {
	return db.Create(&account).Error
}

func get_accounts(db *gorm.DB) (account []Accounts, rowCount int64) {

	var accounts []Accounts
	rowCount = db.Find(&accounts).RowsAffected

	return accounts, rowCount
}

func (account *Accounts) get(db *gorm.DB) (RecordNotFound bool) {
	return db.Unscoped().First(&account, &account.ID).RecordNotFound()
}

//func (a *Accounts) update(db *gorm.DB) {
//	db.Save(&a).Where("Id", &a.Id)
//}
//
//func (a *Accounts) del(db *gorm.DB) {
//	db.Delete(a).Where("Id", &a.Id)
//}
<|endoftext|>


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

package gobuild

import (
	"fmt";
	"gobuild";
	"io";
	"path";
	"template";
)

var makefileTemplate =
	"# DO NOT EDIT.  Automatically generated by gobuild.\n"
	"{Args|args} >Makefile\n"
	"\n"
	"D={.section Dir}/{@}{.end}\n"
	"\n"
	"include $(GOROOT)/src/Make.$(GOARCH)\n"
	"AR=gopack\n"
	"\n"
	"default: packages\n"
	"\n"
	"clean:\n"
	"	rm -rf *.[$(OS)] *.a [$(OS)].out {ObjDir}\n"
	"\n"
	"test: packages\n"
	"	gotest\n"
	"\n"
	"coverage: packages\n"
	"	gotest\n"
	"	6cov -g `pwd` | grep -v '_test\\.go:'\n"
	"\n"
	"%.$O: %.go\n"
	"	$(GC) -I{ObjDir} $*.go\n"
	"\n"
	"%.$O: %.c\n"
	"	$(CC) $*.c\n"
	"\n"
	"%.$O: %.s\n"
	"	$(AS) $*.s\n"
	"\n"
	"{.repeated section Phases}\n"
	"O{Phase}=\\\n"
	"{.repeated section ArCmds}\n"
	"{.repeated section Files}\n"
	"	{Name|basename}.$O\\\n"
	"{.end}\n"
	"{.end}\n"
	"\n"
	"{.end}\n"
	"\n"
	"phases:{.repeated section Phases} a{Phase}{.end}\n"
	"{.repeated section Packages}\n"
	"{ObjDir}$D/{Name}.a: phases\n"
	"{.end}\n"
	"\n"
	"{.repeated section Phases}\n"
	"a{Phase}: $(O{Phase})\n"
	"{.repeated section ArCmds}\n"
	"	$(AR) grc {ObjDir}$D/{.section Pkg}{Name}.a{.end}{.repeated section Files} {Name|basename}.$O{.end}\n"
	"{.end}\n"
	"	rm -f $(O{Phase})\n"
	"\n"
	"{.end}\n"
	"\n"
	"newpkg: clean\n"
	"	mkdir -p {ObjDir}$D\n"
	"{.repeated section Packages}\n"
	"	$(AR) grc {ObjDir}$D/{Name}.a\n"
	"{.end}\n"
	"\n"
	"$(O1): newpkg\n"
	"{.repeated section Phases}\n"
	"$(O{Phase|+1}): a{Phase}\n"
	"{.end}\n"
	"\n"
	"nuke: clean\n"
	"	rm -f{.repeated section Packages} $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D/{Name}.a{.end}\n"
	"\n"
	"packages:{.repeated section Packages} {ObjDir}$D/{Name}.a{.end}\n"
	"\n"
	"install: packages\n"
	"	test -d $(GOROOT)/pkg && mkdir -p $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D\n"
	"{.repeated section Packages}\n"
	"	cp {ObjDir}$D/{Name}.a $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D/{Name}.a\n"
	"{.end}\n"

func argsFmt(w io.Writer, x interface{}, format string) {
	args := x.([]string);
	fmt.Fprint(w, "#");
	for i, a := range args {
		fmt.Fprint(w, " ", ShellString(a));
	}
}

func basenameFmt(w io.Writer, x interface{}, format string) {
	t := fmt.Sprint(x);
	t = t[0:len(t)-len(path.Ext(t))];
	fmt.Fprint(w, MakeString(t));
}

func plus1Fmt(w io.Writer, x interface{}, format string) {
	fmt.Fprint(w, x.(int) + 1);
}

func makeFmt(w io.Writer, x interface{}, format string) {
	fmt.Fprint(w, MakeString(fmt.Sprint(x)));
}

var makefileMap = template.FormatterMap {
	"": makeFmt,
	"+1": plus1Fmt,
	"args": argsFmt,
	"basename": basenameFmt,
}
<commit_msg>use multiline string literal in gobuild<commit_after>// Copyright 2009 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gobuild

import (
	"fmt";
	"gobuild";
	"io";
	"path";
	"template";
)

var makefileTemplate = `
# DO NOT EDIT.  Automatically generated by gobuild.
{Args|args} >Makefile

D={.section Dir}/{@}{.end}

include $(GOROOT)/src/Make.$(GOARCH)
AR=gopack

default: packages

clean:
	rm -rf *.[$(OS)] *.a [$(OS)].out {ObjDir}

test: packages
	gotest

coverage: packages
	gotest
	6cov -g $$(pwd) | grep -v '_test\.go:'

%.$O: %.go
	$(GC) -I{ObjDir} $*.go

%.$O: %.c
	$(CC) $*.c

%.$O: %.s
	$(AS) $*.s

{.repeated section Phases}
O{Phase}=\
{.repeated section ArCmds}
{.repeated section Files}
	{Name|basename}.$O\
{.end}
{.end}

{.end}

phases:{.repeated section Phases} a{Phase}{.end}
{.repeated section Packages}
{ObjDir}$D/{Name}.a: phases
{.end}

{.repeated section Phases}
a{Phase}: $(O{Phase})
{.repeated section ArCmds}
	$(AR) grc {ObjDir}$D/{.section Pkg}{Name}.a{.end}{.repeated section Files} {Name|basename}.$O{.end}
{.end}
	rm -f $(O{Phase})

{.end}

newpkg: clean
	mkdir -p {ObjDir}$D
{.repeated section Packages}
	$(AR) grc {ObjDir}$D/{Name}.a
{.end}

$(O1): newpkg
{.repeated section Phases}
$(O{Phase|+1}): a{Phase}
{.end}

nuke: clean
	rm -f{.repeated section Packages} $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D/{Name}.a{.end}

packages:{.repeated section Packages} {ObjDir}$D/{Name}.a{.end}

install: packages
	test -d $(GOROOT)/pkg && mkdir -p $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D
{.repeated section Packages}
	cp {ObjDir}$D/{Name}.a $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D/{Name}.a
{.end}
`

func argsFmt(w io.Writer, x interface{}, format string) {
	args := x.([]string);
	fmt.Fprint(w, "#");
	for i, a := range args {
		fmt.Fprint(w, " ", ShellString(a));
	}
}

func basenameFmt(w io.Writer, x interface{}, format string) {
	t := fmt.Sprint(x);
	t = t[0:len(t)-len(path.Ext(t))];
	fmt.Fprint(w, MakeString(t));
}

func plus1Fmt(w io.Writer, x interface{}, format string) {
	fmt.Fprint(w, x.(int) + 1);
}

func makeFmt(w io.Writer, x interface{}, format string) {
	fmt.Fprint(w, MakeString(fmt.Sprint(x)));
}

var makefileMap = template.FormatterMap {
	"": makeFmt,
	"+1": plus1Fmt,
	"args": argsFmt,
	"basename": basenameFmt,
}
<|endoftext|>


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

package obj

import "cmd/internal/src"

// InlTree is a collection of inlined calls. The Parent field of an
// InlinedCall is the index of another InlinedCall in InlTree.
//
// The compiler maintains a global inlining tree and adds a node to it
// every time a function is inlined. For example, suppose f() calls g()
// and g has two calls to h(), and that f, g, and h are inlineable:
//
//	 1 func main() {
//	 2     f()
//	 3 }
//	 4 func f() {
//	 5     g()
//	 6 }
//	 7 func g() {
//	 8     h()
//	 9     h()
//	10 }
//	11 func h() {
//	12     println("H")
//	13 }
//
// Assuming the global tree starts empty, inlining will produce the
// following tree:
//
//	[]InlinedCall{
//	  {Parent: -1, Func: "f", Pos: <line 2>},
//	  {Parent:  0, Func: "g", Pos: <line 5>},
//	  {Parent:  1, Func: "h", Pos: <line 8>},
//	  {Parent:  1, Func: "h", Pos: <line 9>},
//	}
//
// The nodes of h inlined into main will have inlining indexes 2 and 3.
//
// Eventually, the compiler extracts a per-function inlining tree from
// the global inlining tree (see pcln.go).
type InlTree struct {
	nodes []InlinedCall
}

// InlinedCall is a node in an InlTree.
type InlinedCall struct {
	Parent   int      // index of the parent in the InlTree or < 0 if outermost call
	Pos      src.XPos // position of the inlined call
	Func     *LSym    // function that was inlined
	ParentPC int32    // PC of instruction just before inlined body. Only valid in local trees.
}

// Add adds a new call to the tree, returning its index.
func (tree *InlTree) Add(parent int, pos src.XPos, func_ *LSym) int {
	r := len(tree.nodes)
	call := InlinedCall{
		Parent: parent,
		Pos:    pos,
		Func:   func_,
	}
	tree.nodes = append(tree.nodes, call)
	return r
}

func (tree *InlTree) Parent(inlIndex int) int {
	return tree.nodes[inlIndex].Parent
}

func (tree *InlTree) InlinedFunction(inlIndex int) *LSym {
	return tree.nodes[inlIndex].Func
}

func (tree *InlTree) CallPos(inlIndex int) src.XPos {
	return tree.nodes[inlIndex].Pos
}

func (tree *InlTree) setParentPC(inlIndex int, pc int32) {
	tree.nodes[inlIndex].ParentPC = pc
}

// OutermostPos returns the outermost position corresponding to xpos,
// which is where xpos was ultimately inlined to. In the example for
// InlTree, main() contains inlined AST nodes from h(), but the
// outermost position for those nodes is line 2.
func (ctxt *Link) OutermostPos(xpos src.XPos) src.Pos {
	pos := ctxt.InnermostPos(xpos)

	outerxpos := xpos
	for ix := pos.Base().InliningIndex(); ix >= 0; {
		call := ctxt.InlTree.nodes[ix]
		ix = call.Parent
		outerxpos = call.Pos
	}
	return ctxt.PosTable.Pos(outerxpos)
}

// InnermostPos returns the innermost position corresponding to xpos,
// that is, the code that is inlined and that inlines nothing else.
// In the example for InlTree above, the code for println within h
// would have an innermost position with line number 12, whether
// h was not inlined, inlined into g, g-then-f, or g-then-f-then-main.
// This corresponds to what someone debugging main, f, g, or h might
// expect to see while single-stepping.
func (ctxt *Link) InnermostPos(xpos src.XPos) src.Pos {
	return ctxt.PosTable.Pos(xpos)
}

// AllPos returns a slice of the positions inlined at xpos, from
// innermost (index zero) to outermost.  To avoid gratuitous allocation
// the result is passed in and extended if necessary.
func (ctxt *Link) AllPos(xpos src.XPos, result []src.Pos) []src.Pos {
	pos := ctxt.InnermostPos(xpos)
	result = result[:0]
	result = append(result, ctxt.PosTable.Pos(xpos))
	for ix := pos.Base().InliningIndex(); ix >= 0; {
		call := ctxt.InlTree.nodes[ix]
		ix = call.Parent
		result = append(result, ctxt.PosTable.Pos(call.Pos))
	}
	return result
}

func dumpInlTree(ctxt *Link, tree InlTree) {
	for i, call := range tree.nodes {
		pos := ctxt.PosTable.Pos(call.Pos)
		ctxt.Logf("%0d | %0d | %s (%s) pc=%d\n", i, call.Parent, call.Func, pos, call.ParentPC)
	}
}
<commit_msg>cmd/internal/obj: adjust (*Link).AllPos comment in inl.go<commit_after>// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package obj

import "cmd/internal/src"

// InlTree is a collection of inlined calls. The Parent field of an
// InlinedCall is the index of another InlinedCall in InlTree.
//
// The compiler maintains a global inlining tree and adds a node to it
// every time a function is inlined. For example, suppose f() calls g()
// and g has two calls to h(), and that f, g, and h are inlineable:
//
//	 1 func main() {
//	 2     f()
//	 3 }
//	 4 func f() {
//	 5     g()
//	 6 }
//	 7 func g() {
//	 8     h()
//	 9     h()
//	10 }
//	11 func h() {
//	12     println("H")
//	13 }
//
// Assuming the global tree starts empty, inlining will produce the
// following tree:
//
//	[]InlinedCall{
//	  {Parent: -1, Func: "f", Pos: <line 2>},
//	  {Parent:  0, Func: "g", Pos: <line 5>},
//	  {Parent:  1, Func: "h", Pos: <line 8>},
//	  {Parent:  1, Func: "h", Pos: <line 9>},
//	}
//
// The nodes of h inlined into main will have inlining indexes 2 and 3.
//
// Eventually, the compiler extracts a per-function inlining tree from
// the global inlining tree (see pcln.go).
type InlTree struct {
	nodes []InlinedCall
}

// InlinedCall is a node in an InlTree.
type InlinedCall struct {
	Parent   int      // index of the parent in the InlTree or < 0 if outermost call
	Pos      src.XPos // position of the inlined call
	Func     *LSym    // function that was inlined
	ParentPC int32    // PC of instruction just before inlined body. Only valid in local trees.
}

// Add adds a new call to the tree, returning its index.
func (tree *InlTree) Add(parent int, pos src.XPos, func_ *LSym) int {
	r := len(tree.nodes)
	call := InlinedCall{
		Parent: parent,
		Pos:    pos,
		Func:   func_,
	}
	tree.nodes = append(tree.nodes, call)
	return r
}

func (tree *InlTree) Parent(inlIndex int) int {
	return tree.nodes[inlIndex].Parent
}

func (tree *InlTree) InlinedFunction(inlIndex int) *LSym {
	return tree.nodes[inlIndex].Func
}

func (tree *InlTree) CallPos(inlIndex int) src.XPos {
	return tree.nodes[inlIndex].Pos
}

func (tree *InlTree) setParentPC(inlIndex int, pc int32) {
	tree.nodes[inlIndex].ParentPC = pc
}

// OutermostPos returns the outermost position corresponding to xpos,
// which is where xpos was ultimately inlined to. In the example for
// InlTree, main() contains inlined AST nodes from h(), but the
// outermost position for those nodes is line 2.
func (ctxt *Link) OutermostPos(xpos src.XPos) src.Pos {
	pos := ctxt.InnermostPos(xpos)

	outerxpos := xpos
	for ix := pos.Base().InliningIndex(); ix >= 0; {
		call := ctxt.InlTree.nodes[ix]
		ix = call.Parent
		outerxpos = call.Pos
	}
	return ctxt.PosTable.Pos(outerxpos)
}

// InnermostPos returns the innermost position corresponding to xpos,
// that is, the code that is inlined and that inlines nothing else.
// In the example for InlTree above, the code for println within h
// would have an innermost position with line number 12, whether
// h was not inlined, inlined into g, g-then-f, or g-then-f-then-main.
// This corresponds to what someone debugging main, f, g, or h might
// expect to see while single-stepping.
func (ctxt *Link) InnermostPos(xpos src.XPos) src.Pos {
	return ctxt.PosTable.Pos(xpos)
}

// AllPos returns a slice of the positions inlined at xpos, from
// innermost (index zero) to outermost.  To avoid allocation
// the input slice is truncated, and used for the result, extended
// as necessary.
func (ctxt *Link) AllPos(xpos src.XPos, result []src.Pos) []src.Pos {
	pos := ctxt.InnermostPos(xpos)
	result = result[:0]
	result = append(result, ctxt.PosTable.Pos(xpos))
	for ix := pos.Base().InliningIndex(); ix >= 0; {
		call := ctxt.InlTree.nodes[ix]
		ix = call.Parent
		result = append(result, ctxt.PosTable.Pos(call.Pos))
	}
	return result
}

func dumpInlTree(ctxt *Link, tree InlTree) {
	for i, call := range tree.nodes {
		pos := ctxt.PosTable.Pos(call.Pos)
		ctxt.Logf("%0d | %0d | %s (%s) pc=%d\n", i, call.Parent, call.Func, pos, call.ParentPC)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"net/http"
	"net/url"
	"rais/src/iiif"
	"rais/src/magick"
	"rais/src/openjpeg"
	"rais/src/plugins"
	"rais/src/version"
	"strings"
	"sync"
	"time"

	"github.com/BurntSushi/toml"
	"github.com/hashicorp/golang-lru"
	"github.com/spf13/viper"
	"github.com/uoregon-libraries/gopkg/interrupts"
	"github.com/uoregon-libraries/gopkg/logger"
)

var infoCache *lru.Cache
var tileCache *lru.TwoQueueCache

// Logger is the server's central logger.Logger instance
var Logger *logger.Logger

// cacheHits and cacheMisses allow some rudimentary tracking of cache value
var cacheHits, cacheMisses int64

func main() {
	parseConf()
	Logger = logger.New(logger.LogLevelFromString(viper.GetString("LogLevel")))
	openjpeg.Logger = Logger
	magick.Logger = Logger

	setupCaches()
	LoadPlugins(Logger, strings.Split(viper.GetString("Plugins"), ","))

	tilePath := viper.GetString("TilePath")
	address := viper.GetString("Address")

	ih := NewImageHandler(tilePath)
	ih.Maximums.Area = viper.GetInt64("ImageMaxArea")
	ih.Maximums.Width = viper.GetInt("ImageMaxWidth")
	ih.Maximums.Height = viper.GetInt("ImageMaxHeight")

	iiifBase, _ := url.Parse(viper.GetString("IIIFURL"))

	Logger.Infof("IIIF enabled at %s", iiifBase.String())
	ih.EnableIIIF(iiifBase)

	capfile := viper.GetString("CapabilitiesFile")
	if capfile != "" {
		ih.FeatureSet = &iiif.FeatureSet{}
		_, err := toml.DecodeFile(capfile, &ih.FeatureSet)
		if err != nil {
			Logger.Fatalf("Invalid file or formatting in capabilities file '%s'", capfile)
		}
		Logger.Debugf("Setting IIIF capabilities from file '%s'", capfile)
	}

	handle(ih.IIIFBase.Path+"/", http.HandlerFunc(ih.IIIFRoute))
	handle("/images/dzi/", http.HandlerFunc(ih.DZIRoute))

	Logger.Infof("RAIS v%s starting...", version.Version)
	var srv = &http.Server{
		ReadTimeout:  5 * time.Second,
		WriteTimeout: 30 * time.Second,
		Addr:         address,
	}

	var wait sync.WaitGroup

	interrupts.TrapIntTerm(func() {
		wait.Add(1)
		Logger.Infof("Stopping RAIS...")
		srv.Shutdown(nil)

		if len(teardownPlugins) > 0 {
			Logger.Infof("Tearing down plugins")
			for _, plug := range teardownPlugins {
				plug()
			}
			Logger.Infof("Plugin teardown complete")
		}

		Logger.Infof("Stopped")
		wait.Done()
	})

	if err := srv.ListenAndServe(); err != nil {
		// Don't report a fatal error when we close the server
		if err != http.ErrServerClosed {
			Logger.Fatalf("Error starting listener: %s", err)
		}
	}
	wait.Wait()
}

func setupCaches() {
	var err error
	icl := viper.GetInt("InfoCacheLen")
	if icl > 0 {
		infoCache, err = lru.New(icl)
		if err != nil {
			Logger.Fatalf("Unable to start info cache: %s", err)
		}
	}

	tcl := viper.GetInt("TileCacheLen")
	if tcl > 0 {
		Logger.Debugf("Creating a tile cache to hold up to %d tiles", tcl)
		tileCache, err = lru.New2Q(tcl)
		if err != nil {
			Logger.Fatalf("Unable to start info cache: %s", err)
		}
	}
}

// handle sends the pattern and raw handler to plugins, and sets up routing on
// whatever is returned (if anything).  All plugins which wrap handlers are
// allowed to run, but the behavior could definitely get weird depending on
// what a given plugin does.  Ye be warned.
func handle(pattern string, handler http.Handler) {
	for _, plug := range wrapHandlerPlugins {
		var h2, err = plug(pattern, handler)
		if err == nil {
			handler = h2
		} else if err != plugins.ErrSkipped {
			logger.Fatalf("Error trying to wrap handler %q: %s", pattern, err)
		}
	}
	http.Handle(pattern, handler)
}
<commit_msg>rais-server: fix shutdown messaging<commit_after>package main

import (
	"net/http"
	"net/url"
	"rais/src/iiif"
	"rais/src/magick"
	"rais/src/openjpeg"
	"rais/src/plugins"
	"rais/src/version"
	"strings"
	"sync"
	"time"

	"github.com/BurntSushi/toml"
	"github.com/hashicorp/golang-lru"
	"github.com/spf13/viper"
	"github.com/uoregon-libraries/gopkg/interrupts"
	"github.com/uoregon-libraries/gopkg/logger"
)

var infoCache *lru.Cache
var tileCache *lru.TwoQueueCache

// Logger is the server's central logger.Logger instance
var Logger *logger.Logger

// cacheHits and cacheMisses allow some rudimentary tracking of cache value
var cacheHits, cacheMisses int64

func main() {
	parseConf()
	Logger = logger.New(logger.LogLevelFromString(viper.GetString("LogLevel")))
	openjpeg.Logger = Logger
	magick.Logger = Logger

	setupCaches()
	LoadPlugins(Logger, strings.Split(viper.GetString("Plugins"), ","))

	tilePath := viper.GetString("TilePath")
	address := viper.GetString("Address")

	ih := NewImageHandler(tilePath)
	ih.Maximums.Area = viper.GetInt64("ImageMaxArea")
	ih.Maximums.Width = viper.GetInt("ImageMaxWidth")
	ih.Maximums.Height = viper.GetInt("ImageMaxHeight")

	iiifBase, _ := url.Parse(viper.GetString("IIIFURL"))

	Logger.Infof("IIIF enabled at %s", iiifBase.String())
	ih.EnableIIIF(iiifBase)

	capfile := viper.GetString("CapabilitiesFile")
	if capfile != "" {
		ih.FeatureSet = &iiif.FeatureSet{}
		_, err := toml.DecodeFile(capfile, &ih.FeatureSet)
		if err != nil {
			Logger.Fatalf("Invalid file or formatting in capabilities file '%s'", capfile)
		}
		Logger.Debugf("Setting IIIF capabilities from file '%s'", capfile)
	}

	handle(ih.IIIFBase.Path+"/", http.HandlerFunc(ih.IIIFRoute))
	handle("/images/dzi/", http.HandlerFunc(ih.DZIRoute))

	Logger.Infof("RAIS v%s starting...", version.Version)
	var srv = &http.Server{
		ReadTimeout:  5 * time.Second,
		WriteTimeout: 30 * time.Second,
		Addr:         address,
	}

	var wait sync.WaitGroup

	interrupts.TrapIntTerm(func() {
		wait.Add(1)
		Logger.Infof("Stopping RAIS...")
		srv.Shutdown(nil)

		if len(teardownPlugins) > 0 {
			Logger.Infof("Tearing down plugins")
			for _, plug := range teardownPlugins {
				plug()
			}
			Logger.Infof("Plugin teardown complete")
		}

		Logger.Infof("RAIS Stopped")
		wait.Done()
	})

	if err := srv.ListenAndServe(); err != nil {
		// Don't report a fatal error when we close the server
		if err != http.ErrServerClosed {
			Logger.Fatalf("Error starting listener: %s", err)
		}
	}
	wait.Wait()
}

func setupCaches() {
	var err error
	icl := viper.GetInt("InfoCacheLen")
	if icl > 0 {
		infoCache, err = lru.New(icl)
		if err != nil {
			Logger.Fatalf("Unable to start info cache: %s", err)
		}
	}

	tcl := viper.GetInt("TileCacheLen")
	if tcl > 0 {
		Logger.Debugf("Creating a tile cache to hold up to %d tiles", tcl)
		tileCache, err = lru.New2Q(tcl)
		if err != nil {
			Logger.Fatalf("Unable to start info cache: %s", err)
		}
	}
}

// handle sends the pattern and raw handler to plugins, and sets up routing on
// whatever is returned (if anything).  All plugins which wrap handlers are
// allowed to run, but the behavior could definitely get weird depending on
// what a given plugin does.  Ye be warned.
func handle(pattern string, handler http.Handler) {
	for _, plug := range wrapHandlerPlugins {
		var h2, err = plug(pattern, handler)
		if err == nil {
			handler = h2
		} else if err != plugins.ErrSkipped {
			logger.Fatalf("Error trying to wrap handler %q: %s", pattern, err)
		}
	}
	http.Handle(pattern, handler)
}
<|endoftext|>