<commit_before>package gogif

import (
	"container/heap"
	"image"
	"image/color"
	"sort"
)

const (
	numDimensions = 3
)

func min(x, y int) int {
	if x < y {
		return x
	}
	return y
}

func max(x, y int) int {
	if x > y {
		return x
	}
	return y
}

type point [numDimensions]int

type block struct {
	minCorner, maxCorner point
	points               []point
	// The index is needed by update and is maintained by the heap.Interface methods.
	index int // The index of the item in the heap.
}

func newBlock(p []point) *block {
	return &block{
		minCorner: point{0x00, 0x00, 0x00},
		maxCorner: point{0xFF, 0xFF, 0xFF},
		points:    p,
	}
}

func (b *block) longestSideIndex() int {
	m := b.maxCorner[0] - b.minCorner[0]
	maxIndex := 0
	for i := 1; i < numDimensions; i++ {
		diff := b.maxCorner[i] - b.minCorner[i]
		if diff > m {
			m = diff
			maxIndex = i
		}
	}
	return maxIndex
}

func (b *block) longestSideLength() int {
	i := b.longestSideIndex()
	return b.maxCorner[i] - b.minCorner[i]
}

func (b *block) shrink() {
	for j := 0; j < numDimensions; j++ {
		b.minCorner[j] = b.points[0][j]
		b.maxCorner[j] = b.points[0][j]
	}
	for i := 1; i < len(b.points); i++ {
		for j := 0; j < numDimensions; j++ {
			b.minCorner[j] = min(b.minCorner[j], b.points[i][j])
			b.maxCorner[j] = max(b.maxCorner[j], b.points[i][j])
		}
	}
}

type pointSorter struct {
	points []point
	by     func(p1, p2 *point) bool
}

func (p *pointSorter) Len() int {
	return len(p.points)
}

func (p *pointSorter) Swap(i, j int) {
	p.points[i], p.points[j] = p.points[j], p.points[i]
}

func (p *pointSorter) Less(i, j int) bool {
	return p.by(&p.points[i], &p.points[j])
}

// A priorityQueue implements heap.Interface and holds blocks.
type priorityQueue []*block

func (pq priorityQueue) Len() int { return len(pq) }

func (pq priorityQueue) Less(i, j int) bool {
	return pq[i].longestSideLength() > pq[j].longestSideLength()
}

func (pq priorityQueue) Swap(i, j int) {
	pq[i], pq[j] = pq[j], pq[i]
	pq[i].index = i
	pq[j].index = j
}

func (pq *priorityQueue) Push(x interface{}) {
	n := len(*pq)
	item := x.(*block)
	item.index = n
	*pq = append(*pq, item)
}

func (pq *priorityQueue) Pop() interface{} {
	old := *pq
	n := len(old)
	item := old[n-1]
	item.index = -1 // for safety
	*pq = old[:n-1]
	return item
}

func (pq *priorityQueue) Top() interface{} {
	n := len(*pq)
	if n == 0 {
		return nil
	}
	return (*pq)[n-1]
}

// MedianCutQuantizer constructs a palette with a maximum of
// NumColor colors by iteratively splitting clusters of color
// points mapped on a three-dimensional (RGB) Euclidian space.
// Once the number of clusters is within the specified bounds,
// the resulting color is computed by averaging those within
// each grouping.
type MedianCutQuantizer struct {
	NumColor int
}

func (q *MedianCutQuantizer) medianCut(points []point) color.Palette {
	if q.NumColor == 0 {
		return color.Palette{}
	}

	initialBlock := newBlock(points)
	initialBlock.shrink()
	pq := &priorityQueue{}
	heap.Init(pq)
	heap.Push(pq, initialBlock)

	for pq.Len() < q.NumColor && len(pq.Top().(*block).points) > 1 {
		longestBlock := heap.Pop(pq).(*block)
		points := longestBlock.points
		li := longestBlock.longestSideIndex()
		// TODO: Instead of sorting the entire slice, finding the median using an
		// algorithm like introselect would give much better performance.
		sort.Sort(&pointSorter{
			points: points,
			by:     func(p1, p2 *point) bool { return p1[li] < p2[li] },
		})
		median := len(points) / 2
		block1 := newBlock(points[:median])
		block2 := newBlock(points[median:])
		block1.shrink()
		block2.shrink()
		heap.Push(pq, block1)
		heap.Push(pq, block2)
	}

	palette := make(color.Palette, q.NumColor)
	var n int
	for n = 0; pq.Len() > 0; n++ {
		block := heap.Pop(pq).(*block)
		var sum [numDimensions]int
		for i := 0; i < len(block.points); i++ {
			for j := 0; j < numDimensions; j++ {
				sum[j] += block.points[i][j]
			}
		}
		palette[n] = color.RGBA64{
			R: uint16(sum[0] / len(block.points)),
			G: uint16(sum[1] / len(block.points)),
			B: uint16(sum[2] / len(block.points)),
			A: 0xFFFF,
		}
	}
	// Trim to only the colors present in the image, which
	// could be less than NumColor.
	return palette[:n]
}

func (q *MedianCutQuantizer) Quantize(dst *image.Paletted, src image.Image) {
	bounds := src.Bounds()
	points := make([]point, bounds.Dx()*bounds.Dy())
	colorSet := make(map[uint32]color.Color, q.NumColor)
	i := 0
	for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
		for x := bounds.Min.X; x < bounds.Max.X; x++ {
			c := src.At(x, y)
			r, g, b, _ := c.RGBA()
			colorSet[(r>>8)<<16|(g>>8)<<8|b>>8] = c
			points[i][0] = int(r)
			points[i][1] = int(g)
			points[i][2] = int(b)
			i++
		}
	}
	if len(colorSet) <= q.NumColor {
		// No need to quantize since the total number of colors
		// fits within the palette.
		dst.Palette = make(color.Palette, len(colorSet))
		i := 0
		for _, c := range colorSet {
			dst.Palette[i] = c
			i++
		}
	} else {
		dst.Palette = q.medianCut(points)
	}

	dst.Stride = bounds.Dx()
	for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
		for x := bounds.Min.X; x < bounds.Max.X; x++ {
			// TODO: this should be done more efficiently.
			dst.Set(x, y, src.At(x, y))
		}
	}
}
<commit_msg>Top is not part of heap.Interface<commit_after>package gogif

import (
	"container/heap"
	"image"
	"image/color"
	"sort"
)

const (
	numDimensions = 3
)

func min(x, y int) int {
	if x < y {
		return x
	}
	return y
}

func max(x, y int) int {
	if x > y {
		return x
	}
	return y
}

type point [numDimensions]int

type block struct {
	minCorner, maxCorner point
	points               []point
	// The index is needed by update and is maintained by the heap.Interface methods.
	index int // The index of the item in the heap.
}

func newBlock(p []point) *block {
	return &block{
		minCorner: point{0x00, 0x00, 0x00},
		maxCorner: point{0xFF, 0xFF, 0xFF},
		points:    p,
	}
}

func (b *block) longestSideIndex() int {
	m := b.maxCorner[0] - b.minCorner[0]
	maxIndex := 0
	for i := 1; i < numDimensions; i++ {
		diff := b.maxCorner[i] - b.minCorner[i]
		if diff > m {
			m = diff
			maxIndex = i
		}
	}
	return maxIndex
}

func (b *block) longestSideLength() int {
	i := b.longestSideIndex()
	return b.maxCorner[i] - b.minCorner[i]
}

func (b *block) shrink() {
	for j := 0; j < numDimensions; j++ {
		b.minCorner[j] = b.points[0][j]
		b.maxCorner[j] = b.points[0][j]
	}
	for i := 1; i < len(b.points); i++ {
		for j := 0; j < numDimensions; j++ {
			b.minCorner[j] = min(b.minCorner[j], b.points[i][j])
			b.maxCorner[j] = max(b.maxCorner[j], b.points[i][j])
		}
	}
}

type pointSorter struct {
	points []point
	by     func(p1, p2 *point) bool
}

func (p *pointSorter) Len() int {
	return len(p.points)
}

func (p *pointSorter) Swap(i, j int) {
	p.points[i], p.points[j] = p.points[j], p.points[i]
}

func (p *pointSorter) Less(i, j int) bool {
	return p.by(&p.points[i], &p.points[j])
}

// A priorityQueue implements heap.Interface and holds blocks.
type priorityQueue []*block

func (pq priorityQueue) Len() int { return len(pq) }

func (pq priorityQueue) Less(i, j int) bool {
	return pq[i].longestSideLength() > pq[j].longestSideLength()
}

func (pq priorityQueue) Swap(i, j int) {
	pq[i], pq[j] = pq[j], pq[i]
	pq[i].index = i
	pq[j].index = j
}

func (pq *priorityQueue) Push(x interface{}) {
	n := len(*pq)
	item := x.(*block)
	item.index = n
	*pq = append(*pq, item)
}

func (pq *priorityQueue) Pop() interface{} {
	old := *pq
	n := len(old)
	item := old[n-1]
	item.index = -1 // for safety
	*pq = old[:n-1]
	return item
}

func (pq *priorityQueue) top() interface{} {
	n := len(*pq)
	if n == 0 {
		return nil
	}
	return (*pq)[n-1]
}

// MedianCutQuantizer constructs a palette with a maximum of
// NumColor colors by iteratively splitting clusters of color
// points mapped on a three-dimensional (RGB) Euclidian space.
// Once the number of clusters is within the specified bounds,
// the resulting color is computed by averaging those within
// each grouping.
type MedianCutQuantizer struct {
	NumColor int
}

func (q *MedianCutQuantizer) medianCut(points []point) color.Palette {
	if q.NumColor == 0 {
		return color.Palette{}
	}

	initialBlock := newBlock(points)
	initialBlock.shrink()
	pq := &priorityQueue{}
	heap.Init(pq)
	heap.Push(pq, initialBlock)

	for pq.Len() < q.NumColor && len(pq.top().(*block).points) > 1 {
		longestBlock := heap.Pop(pq).(*block)
		points := longestBlock.points
		li := longestBlock.longestSideIndex()
		// TODO: Instead of sorting the entire slice, finding the median using an
		// algorithm like introselect would give much better performance.
		sort.Sort(&pointSorter{
			points: points,
			by:     func(p1, p2 *point) bool { return p1[li] < p2[li] },
		})
		median := len(points) / 2
		block1 := newBlock(points[:median])
		block2 := newBlock(points[median:])
		block1.shrink()
		block2.shrink()
		heap.Push(pq, block1)
		heap.Push(pq, block2)
	}

	palette := make(color.Palette, q.NumColor)
	var n int
	for n = 0; pq.Len() > 0; n++ {
		block := heap.Pop(pq).(*block)
		var sum [numDimensions]int
		for i := 0; i < len(block.points); i++ {
			for j := 0; j < numDimensions; j++ {
				sum[j] += block.points[i][j]
			}
		}
		palette[n] = color.RGBA64{
			R: uint16(sum[0] / len(block.points)),
			G: uint16(sum[1] / len(block.points)),
			B: uint16(sum[2] / len(block.points)),
			A: 0xFFFF,
		}
	}
	// Trim to only the colors present in the image, which
	// could be less than NumColor.
	return palette[:n]
}

func (q *MedianCutQuantizer) Quantize(dst *image.Paletted, src image.Image) {
	bounds := src.Bounds()
	points := make([]point, bounds.Dx()*bounds.Dy())
	colorSet := make(map[uint32]color.Color, q.NumColor)
	i := 0
	for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
		for x := bounds.Min.X; x < bounds.Max.X; x++ {
			c := src.At(x, y)
			r, g, b, _ := c.RGBA()
			colorSet[(r>>8)<<16|(g>>8)<<8|b>>8] = c
			points[i][0] = int(r)
			points[i][1] = int(g)
			points[i][2] = int(b)
			i++
		}
	}
	if len(colorSet) <= q.NumColor {
		// No need to quantize since the total number of colors
		// fits within the palette.
		dst.Palette = make(color.Palette, len(colorSet))
		i := 0
		for _, c := range colorSet {
			dst.Palette[i] = c
			i++
		}
	} else {
		dst.Palette = q.medianCut(points)
	}

	dst.Stride = bounds.Dx()
	for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
		for x := bounds.Min.X; x < bounds.Max.X; x++ {
			// TODO: this should be done more efficiently.
			dst.Set(x, y, src.At(x, y))
		}
	}
}
<|endoftext|>


<commit_before>package user

import (
	"bytes"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/stretchr/testify/assert"
	"mime/multipart"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/eirka/eirka-libs/config"
	"github.com/eirka/eirka-libs/db"

	local "github.com/eirka/eirka-post/config"
)

func init() {

	// Database connection settings
	dbase := db.Database{

		User:           local.Settings.Database.User,
		Password:       local.Settings.Database.Password,
		Proto:          local.Settings.Database.Proto,
		Host:           local.Settings.Database.Host,
		Database:       local.Settings.Database.Database,
		MaxIdle:        local.Settings.Database.MaxIdle,
		MaxConnections: local.Settings.Database.MaxConnections,
	}

	// Set up DB connection
	dbase.NewDb()

	// Get limits and stuff from database
	config.GetDatabaseSettings()
}

func performRequest(r http.Handler, method, path string) *httptest.ResponseRecorder {
	req, _ := http.NewRequest(method, path, nil)
	w := httptest.NewRecorder()
	r.ServeHTTP(w, req)
	return w
}

func performJwtHeaderRequest(r http.Handler, method, path, token string) *httptest.ResponseRecorder {
	req, _ := http.NewRequest(method, path, nil)
	req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
	w := httptest.NewRecorder()
	r.ServeHTTP(w, req)
	return w
}

func performJwtFormRequest(r http.Handler, method, path, token string) *httptest.ResponseRecorder {
	var b bytes.Buffer

	mw := multipart.NewWriter(&b)
	mw.WriteField("access_token", token)
	mw.Close()

	req, _ := http.NewRequest(method, path, &b)
	req.Header.Set("Content-Type", mw.FormDataContentType())
	w := httptest.NewRecorder()
	r.ServeHTTP(w, req)
	return w
}

func TestAuthSecret(t *testing.T) {

	var err error

	Secret = ""

	gin.SetMode(gin.ReleaseMode)

	router := gin.New()

	// route is open
	router.Use(Auth(false))

	router.GET("/", func(c *gin.Context) {
		c.String(200, "OK")
		return
	})

	first := performRequest(router, "GET", "/")

	assert.Equal(t, first.Code, 500, "HTTP request code should match")

	Secret = "secret"

	second := performRequest(router, "GET", "/")

	assert.Equal(t, second.Code, 200, "HTTP request code should match")

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

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

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

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

	third := performJwtHeaderRequest(router, "GET", "/", token)

	assert.Equal(t, third.Code, 200, "HTTP request code should match")

}

func TestAuthHeaderToken(t *testing.T) {

	var err error

	Secret = "secret"

	gin.SetMode(gin.ReleaseMode)

	router := gin.New()

	// route is protected
	router.Use(Auth(true))

	router.GET("/", func(c *gin.Context) {
		c.String(200, "OK")
		return
	})

	first := performRequest(router, "GET", "/")

	assert.Equal(t, first.Code, 401, "HTTP request code should match")

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

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

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

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

	Secret = "changed"

	second := performJwtHeaderRequest(router, "GET", "/", badtoken)

	assert.Equal(t, second.Code, 401, "HTTP request code should match")

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

	third := performJwtHeaderRequest(router, "GET", "/", goodtoken)

	assert.Equal(t, third.Code, 200, "HTTP request code should match")

}

func TestAuthFormToken(t *testing.T) {

	var err error

	Secret = "secret"

	gin.SetMode(gin.ReleaseMode)

	router := gin.New()

	// route is protected
	router.Use(Auth(true))

	router.GET("/", func(c *gin.Context) {
		c.String(200, "OK")
		return
	})

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

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

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

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

	Secret = "changed"

	first := performJwtFormRequest(router, "GET", "/", badtoken)

	assert.Equal(t, first.Code, 401, "HTTP request code should match")

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

	second := performJwtFormRequest(router, "GET", "/", goodtoken)

	assert.Equal(t, second.Code, 200, "HTTP request code should match")

}
<commit_msg>enhance auth test to check that logged in users can see anon routes<commit_after>package user

import (
	"bytes"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/stretchr/testify/assert"
	"mime/multipart"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/eirka/eirka-libs/config"
	"github.com/eirka/eirka-libs/db"

	local "github.com/eirka/eirka-post/config"
)

func init() {

	// Database connection settings
	dbase := db.Database{

		User:           local.Settings.Database.User,
		Password:       local.Settings.Database.Password,
		Proto:          local.Settings.Database.Proto,
		Host:           local.Settings.Database.Host,
		Database:       local.Settings.Database.Database,
		MaxIdle:        local.Settings.Database.MaxIdle,
		MaxConnections: local.Settings.Database.MaxConnections,
	}

	// Set up DB connection
	dbase.NewDb()

	// Get limits and stuff from database
	config.GetDatabaseSettings()
}

func performRequest(r http.Handler, method, path string) *httptest.ResponseRecorder {
	req, _ := http.NewRequest(method, path, nil)
	w := httptest.NewRecorder()
	r.ServeHTTP(w, req)
	return w
}

func performJwtHeaderRequest(r http.Handler, method, path, token string) *httptest.ResponseRecorder {
	req, _ := http.NewRequest(method, path, nil)
	req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
	w := httptest.NewRecorder()
	r.ServeHTTP(w, req)
	return w
}

func performJwtFormRequest(r http.Handler, method, path, token string) *httptest.ResponseRecorder {
	var b bytes.Buffer

	mw := multipart.NewWriter(&b)
	mw.WriteField("access_token", token)
	mw.Close()

	req, _ := http.NewRequest(method, path, &b)
	req.Header.Set("Content-Type", mw.FormDataContentType())
	w := httptest.NewRecorder()
	r.ServeHTTP(w, req)
	return w
}

func TestAuthSecret(t *testing.T) {

	var err error

	Secret = ""

	gin.SetMode(gin.ReleaseMode)

	router := gin.New()

	// route is open
	router.Use(Auth(false))

	router.GET("/", func(c *gin.Context) {
		c.String(200, "OK")
		return
	})

	first := performRequest(router, "GET", "/")

	assert.Equal(t, first.Code, 500, "HTTP request code should match")

	Secret = "secret"

	second := performRequest(router, "GET", "/")

	assert.Equal(t, second.Code, 200, "HTTP request code should match")

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

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

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

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

	third := performJwtHeaderRequest(router, "GET", "/", token)

	assert.Equal(t, third.Code, 200, "HTTP request code should match")

}

func TestAuthHeaderToken(t *testing.T) {

	var err error

	Secret = "secret"

	gin.SetMode(gin.ReleaseMode)

	router := gin.New()

	// route is protected
	router.Use(Auth(true))

	router.GET("/", func(c *gin.Context) {
		c.String(200, "OK")
		return
	})

	first := performRequest(router, "GET", "/")

	assert.Equal(t, first.Code, 401, "HTTP request code should match")

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

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

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

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

	Secret = "changed"

	second := performJwtHeaderRequest(router, "GET", "/", badtoken)

	assert.Equal(t, second.Code, 401, "HTTP request code should match")

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

	third := performJwtHeaderRequest(router, "GET", "/", goodtoken)

	assert.Equal(t, third.Code, 200, "HTTP request code should match")

}

func TestAuthFormToken(t *testing.T) {

	var err error

	Secret = "secret"

	gin.SetMode(gin.ReleaseMode)

	router := gin.New()

	// route is protected
	router.Use(Auth(true))

	router.GET("/", func(c *gin.Context) {
		c.String(200, "OK")
		return
	})

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

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

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

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

	Secret = "changed"

	first := performJwtFormRequest(router, "GET", "/", badtoken)

	assert.Equal(t, first.Code, 401, "HTTP request code should match")

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

	second := performJwtFormRequest(router, "GET", "/", goodtoken)

	assert.Equal(t, second.Code, 200, "HTTP request code should match")

}
<|endoftext|>


<commit_before><commit_msg>comment private functions<commit_after><|endoftext|>


<commit_before>package wamp

import (
	"context"
	"fmt"
	"log"

	"github.com/gammazero/nexus/v3/client"
	"github.com/gammazero/nexus/v3/wamp"
)

type Client struct {
	name   string
	client *client.Client
}

func NewClient(server string, realm string, name string) (*Client, error) {
	cfg := client.Config{
		Realm: realm,
	}

	cli, err := client.ConnectNet(context.Background(), fmt.Sprintf("ws://%s", server), cfg)
	if err != nil {
		return nil, err
	}

	res := &Client{
		name:   name,
		client: cli,
	}

	res.Listen()

	return res, nil
}

func (c *Client) Listen() {
	proc := fmt.Sprintf("foo_%s", c.name)

	go func() {
		// Register procedure "foo"
		if err := c.client.Register(proc, foo, nil); err != nil {
			log.Fatal("Failed to register procedure:", err)
		}
		log.Println("Registered procedure foo with router")

	}()
}

func (c *Client) Call(to string, args ...string) error {

	callArgs := make(wamp.List, len(args))
	for i, a := range args {
		callArgs[i] = a
	}

	proc := fmt.Sprintf("foo_%s", to)

	log.Println("Call remote procedure", proc)

	result, err := c.client.Call(context.Background(), proc, nil, callArgs, nil, nil)
	if err != nil {
		log.Fatal(err)
		return err
	}

	for i := range result.Arguments {
		txt, _ := wamp.AsString(result.Arguments[i])
		log.Println(txt)
	}

	return nil

}

func (c *Client) Close() error {
	return c.client.Close()
}

func foo(ctx context.Context, inv *wamp.Invocation) client.InvokeResult {
	log.Println("In foo")

	msg := "bar"

	for _, arg := range inv.Arguments {
		s, ok := wamp.AsString(arg)
		if ok {
			msg = fmt.Sprintf("%s %s", msg, s)
		}
	}

	log.Println(msg)

	return client.InvokeResult{
		Args: wamp.List{msg},
	}
}
<commit_msg>Wamp implementation of Signal<commit_after>package wamp

import (
	"context"
	"encoding/json"
	"fmt"
	"log"

	"github.com/gammazero/nexus/v3/client"
	"github.com/gammazero/nexus/v3/wamp"
	bnet "github.com/mosaicnetworks/babble/src/net"
	"github.com/pion/webrtc/v2"
)

// Client implements the Signal interface. It sends ands receives SDP offers
// through a WAMP server using WebSockets.
type Client struct {
	pubKey   string
	client   *client.Client
	consumer chan bnet.RPC
}

// NewClient instantiates a new Client
func NewClient(server string, realm string, pubKey string) (*Client, error) {
	cfg := client.Config{
		Realm: realm,
	}

	cli, err := client.ConnectNet(context.Background(), fmt.Sprintf("ws://%s", server), cfg)
	if err != nil {
		return nil, err
	}

	res := &Client{
		pubKey:   pubKey,
		client:   cli,
		consumer: make(chan bnet.RPC),
	}

	return res, nil
}

// Addr implements the Signal interface. It returns the pubKey indentifying this
// client
func (c *Client) Addr() string {
	return c.pubKey
}

// Listen implements the Signal interface. It registers a callback within the
// WAMP router. The callback forwards offers to the consumer channel
func (c *Client) Listen() error {
	proc := fmt.Sprintf("foo_%s", c.pubKey)

	if err := c.client.Register(proc, c.foo, nil); err != nil {
		log.Fatal("Failed to register procedure:", err)
		return err
	}

	log.Println("Registered procedure foo with router")
	return nil
}

// Offer implemnts the Signal interface. It sends an offer and waits for an
// answer
func (c *Client) Offer(target string, offer webrtc.SessionDescription) (*webrtc.SessionDescription, error) {
	raw, err := json.Marshal(offer)
	if err != nil {
		return nil, err
	}

	callArgs := wamp.List{
		string(raw),
	}

	proc := fmt.Sprintf("foo_%s", target)

	log.Println("Call remote procedure", proc)

	result, err := c.client.Call(context.Background(), proc, nil, callArgs, nil, nil)
	if err != nil {
		log.Fatal(err)
		return nil, err
	}

	sdp, ok := wamp.AsString(result.Arguments[0])
	if !ok {
		return nil, err
	}

	answer := webrtc.SessionDescription{}
	err = json.Unmarshal([]byte(sdp), &answer)
	if err != nil {
		return nil, err
	}

	return &answer, nil

}

// Consumer implements the Signal interface
func (c *Client) Consumer() <-chan bnet.RPC {
	return c.consumer
}

// Close closes the connection to the WAMP
// server
func (c *Client) Close() error {
	return c.client.Close()
}

func (c *Client) foo(ctx context.Context, inv *wamp.Invocation) client.InvokeResult {
	log.Println("In foo")

	if len(inv.Arguments) != 2 {
		return client.InvokeResult{
			Err: "Error parsing invocation",
		}
	}

	// XXX should track who the sender is
	_, ok := wamp.AsString(inv.Arguments[0])
	if !ok {
		return client.InvokeResult{
			Err: "Error parsing invocation",
		}
	}

	sdp, ok := wamp.AsString(inv.Arguments[1])
	if !ok {
		return client.InvokeResult{
			Err: "Error parsing invocation",
		}
	}

	offer := webrtc.SessionDescription{}
	err := json.Unmarshal([]byte(sdp), &offer)
	if err != nil {
		return client.InvokeResult{
			Err: "Error parsing invocation",
		}
	}

	respCh := make(chan bnet.RPCResponse, 1)

	rpc := bnet.RPC{
		Command:  offer,
		RespChan: respCh,
	}

	c.consumer <- rpc

	// Wait for response
	select {
	case resp := <-respCh:
		fmt.Println("Signal responding answer")
		raw, err := json.Marshal(resp.Response.(webrtc.SessionDescription))
		if err != nil {
			return client.InvokeResult{
				Err: "Error parsing answer",
			}
		}
		return client.InvokeResult{
			Args: wamp.List{string(raw)},
		}
	}

	return client.InvokeResult{
		Err: "Error processing offer",
	}
}
<|endoftext|>


<commit_before>package watchdog

import (
	"testing"
	"time"

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

func TestAlarm(t *testing.T) {
	{
		alarm := NewAlarm(time.Microsecond*500, 20) // 间隔 0.5s，每天最多触发次数 20 次

		index := 0
		for {
			if index == 20 {
				break
			}

			assert.True(t, alarm.ShouldTrigger(), index)
			assert.Equal(t, int(uint(index+1)), int(alarm.triggerTimesToDay), index)

			index++

			time.Sleep(time.Microsecond * 600)
		}

		assert.False(t, alarm.ShouldTrigger(), index)
		assert.Equal(t, 20, int(alarm.triggerTimesToDay), index)

		assert.False(t, alarm.ShouldTrigger(), index)
		assert.Equal(t, 20, int(alarm.triggerTimesToDay), index)

		assert.False(t, alarm.ShouldTrigger(), index)
		assert.Equal(t, 20, int(alarm.triggerTimesToDay), index)
	}

	{
		alarm := NewAlarm(time.Millisecond*200, 20) // 间隔 2s，每天最多触发次数 20 次

		index := 0
		for {
			if index == 20 {
				break
			}

			index++

			_ = alarm.ShouldTrigger()

			time.Sleep(time.Millisecond * 100)
		}

		assert.Equal(t, 10, int(alarm.triggerTimesToDay), index)
	}
}
<commit_msg>fix test<commit_after>package watchdog

import (
	"testing"
	"time"

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

func TestAlarm(t *testing.T) {
	{
		alarm := NewAlarm(time.Microsecond*500, 20) // 间隔 0.5s，每天最多触发次数 20 次

		index := 0
		for {
			if index == 20 {
				break
			}

			assert.True(t, alarm.ShouldTrigger(), index)
			assert.Equal(t, int(uint(index+1)), int(alarm.triggerTimesToDay), index)

			index++

			time.Sleep(time.Microsecond * 600)
		}

		assert.False(t, alarm.ShouldTrigger(), index)
		assert.Equal(t, 20, int(alarm.triggerTimesToDay), index)

		assert.False(t, alarm.ShouldTrigger(), index)
		assert.Equal(t, 20, int(alarm.triggerTimesToDay), index)

		assert.False(t, alarm.ShouldTrigger(), index)
		assert.Equal(t, 20, int(alarm.triggerTimesToDay), index)
	}

	{
		alarm := NewAlarm(time.Microsecond*200, 20) // 间隔 2s，每天最多触发次数 20 次

		index := 0
		for {
			if index == 20 {
				break
			}

			index++

			_ = alarm.ShouldTrigger()

			time.Sleep(time.Microsecond * 100)
		}

		assert.Equal(t, 11, int(alarm.triggerTimesToDay), index)
	}
}
<|endoftext|>


<commit_before>package codegen

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"

	"github.com/golang/protobuf/protoc-gen-go/generator"
)

func Generate(file []byte, name string) ([]byte, error) {
	dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
	if err != nil {
		return nil, err
	}

	protofile := filepath.Join(dir, fmt.Sprintf("%s.proto", name))
	fmt.Println(protofile)
	n := bytes.IndexByte(file, 0)
	err = ioutil.WriteFile(protofile, file[:n], 0644)
	if err != nil {
		return nil, err
	}
	defer os.Remove(protofile)

	go_out := fmt.Sprintf("--go_out=%s", dir)
	proto_path := fmt.Sprintf("--proto_path=%s", dir)
	cmd := exec.Command("protoc", go_out, proto_path, protofile)
	cmd.Stderr = os.Stderr

	err = cmd.Run()
	if err != nil {
		return nil, err
	}
	defer os.Remove(fmt.Sprintf("%s/%s.pb.go", dir, name))

	pbfile := fmt.Sprintf("%s.pb.go", name)
	pb, err := ioutil.ReadFile(pbfile)
	if err != nil {
		return nil, err
	}

	return pb, nil
}
<commit_msg>properly redirecting stderr of protoc<commit_after>package codegen

import (
	"bytes"
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
)

func Generate(file []byte, name string) ([]byte, error) {
	dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
	if err != nil {
		return nil, err
	}

	protofile := filepath.Join(dir, fmt.Sprintf("%s.proto", name))
	fmt.Println(protofile)
	n := bytes.IndexByte(file, 0)
	err = ioutil.WriteFile(protofile, file[:n], 0644)
	if err != nil {
		return nil, err
	}
	defer os.Remove(protofile)

	go_out := fmt.Sprintf("--go_out=%s", dir)
	proto_path := fmt.Sprintf("--proto_path=%s", dir)

	cmd := exec.Command("protoc", go_out, proto_path, protofile)
	var e bytes.Buffer
	cmd.Stderr = &e

	err = cmd.Run()
	if err != nil {
		return nil, errors.New(e.String())
	}

	defer os.Remove(fmt.Sprintf("%s/%s.pb.go", dir, name))

	pbfile := fmt.Sprintf("%s.pb.go", name)
	pb, err := ioutil.ReadFile(pbfile)
	if err != nil {
		return nil, err
	}

	return pb, nil
}
<|endoftext|>


<commit_before>package api

import (
	"log"
	"net/http"

	"github.com/mdlayher/wavepipe/data"

	"github.com/go-martini/martini"
	"github.com/martini-contrib/render"
)

// LogoutResponse represents the JSON response for /api/logouts
type LogoutResponse struct {
	Error   *Error        `json:"error"`
}

// GetLogout destroys a new session from the wavepipe API, and returns a HTTP status and JSON
func GetLogout(r render.Render, req *http.Request, session *data.Session, params martini.Params) {
	// Output struct for logouts request
	res := LogoutResponse{}

	// Check API version
	if version, ok := params["version"]; ok {
		// Check if this API call is supported in the advertised version
		if !apiVersionSet.Has(version) {
			res.Error = new(Error)
			res.Error.Code = 400
			res.Error.Message = "unsupported API version: " + version
			r.JSON(400, res)
			return
		}
	}

	// Destroy the current API session
	if err := session.Delete(); err != nil {
		log.Println(err)

		res.Error = new(Error)
		res.Error.Code = 500
		res.Error.Message = "server error"
		r.JSON(500, res)
		return
	}

	// Build response
	res.Error = nil

	// HTTP 200 OK with JSON
	r.JSON(200, res)
	return
}
<commit_msg>go fmt api/logout.go<commit_after>package api

import (
	"log"
	"net/http"

	"github.com/mdlayher/wavepipe/data"

	"github.com/go-martini/martini"
	"github.com/martini-contrib/render"
)

// LogoutResponse represents the JSON response for /api/logouts
type LogoutResponse struct {
	Error *Error `json:"error"`
}

// GetLogout destroys a new session from the wavepipe API, and returns a HTTP status and JSON
func GetLogout(r render.Render, req *http.Request, session *data.Session, params martini.Params) {
	// Output struct for logouts request
	res := LogoutResponse{}

	// Check API version
	if version, ok := params["version"]; ok {
		// Check if this API call is supported in the advertised version
		if !apiVersionSet.Has(version) {
			res.Error = new(Error)
			res.Error.Code = 400
			res.Error.Message = "unsupported API version: " + version
			r.JSON(400, res)
			return
		}
	}

	// Destroy the current API session
	if err := session.Delete(); err != nil {
		log.Println(err)

		res.Error = new(Error)
		res.Error.Code = 500
		res.Error.Message = "server error"
		r.JSON(500, res)
		return
	}

	// Build response
	res.Error = nil

	// HTTP 200 OK with JSON
	r.JSON(200, res)
	return
}
<|endoftext|>


<commit_before>// Copyright 2015-2016, Cyrill @ Schumacher.fm and the CoreStore contributors
//
// 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 scopedservice

import (
	"context"
	"fmt"
	"io"
	"sort"
	"sync"

	"github.com/corestoreio/csfw/config"
	"github.com/corestoreio/csfw/log"
	"github.com/corestoreio/csfw/net/mw"
	"github.com/corestoreio/csfw/store/scope"
	"github.com/corestoreio/csfw/sync/singleflight"
	"github.com/corestoreio/csfw/util/errors"
)

// Auto generated: Do not edit. See net/internal/scopedService package for more details.

type service struct {
	// Log used for debugging. Defaults to black hole.
	Log log.Logger

	// ErrorHandler gets called whenever a programmer makes an error. Most two
	// cases are: cannot extract scope from the context and scoped configuration
	// is not valid. The default handler prints the error to the client and
	// returns http.StatusServiceUnavailable
	mw.ErrorHandler

	// rootConfig optional backend configuration. Gets only used while running
	// HTTP related middlewares.
	rootConfig config.Getter

	// useWebsite internal flag used in configByContext(w,r) to tell the
	// currenct handler if the scoped configuration is store or website based.
	useWebsite bool

	// optionFactory optional configuration closure, can be nil. It pulls out
	// the configuration settings from a slow backend during a request and
	// caches the settings in the internal map.  This function gets set via
	// WithOptionFactory()
	optionFactory OptionFactoryFunc

	// optionInflight checks on a per scope.TypeID basis if the configuration
	// loading process takes place. Stops the execution of other Goroutines (aka
	// incoming requests) with the same scope.TypeID until the configuration has
	// been fully loaded and applied for that specific scope. This function gets
	// set via WithOptionFactory()
	optionInflight *singleflight.Group

	// optionAfterApply allows to set a custom function which runs every time
	// after the options have been applied. Gets only executed if not nil.
	optionAfterApply func() error

	// rwmu protects all fields below
	rwmu sync.RWMutex

	// scopeCache internal cache for configurations.
	scopeCache map[scope.TypeID]*ScopedConfig
}

func newService(opts ...Option) (*Service, error) {
	s := &Service{
		service: service{
			Log:          log.BlackHole{},
			ErrorHandler: defaultErrorHandler,
			scopeCache:   make(map[scope.TypeID]*ScopedConfig),
		},
	}
	if err := s.Options(WithDefaultConfig(scope.DefaultTypeID)); err != nil {
		return nil, errors.Wrap(err, "[scopedservice] Options WithDefaultConfig")
	}
	if err := s.Options(opts...); err != nil {
		return nil, errors.Wrap(err, "[scopedservice] Options any config")
	}
	return s, nil
}

// MustNew same as New() but panics on error. Use only during app start up process.
func MustNew(opts ...Option) *Service {
	c, err := New(opts...)
	if err != nil {
		panic(err)
	}
	return c
}

// Options applies option at creation time or refreshes them.
func (s *Service) Options(opts ...Option) error {
	for _, opt := range opts {
		// opt can be nil because of the backend options where we have an array instead
		// of a slice.
		if opt != nil {
			if err := opt(s); err != nil {
				return errors.Wrap(err, "[scopedservice] Service.Options")
			}
		}
	}
	if s.optionAfterApply != nil {
		return errors.Wrap(s.optionAfterApply(), "[scopedservice] optionValidation")
	}
	return nil
}

// ClearCache clears the internal map storing all scoped configurations. You
// must reapply all functional options.
// TODO(CyS) all previously applied options will be automatically reapplied.
func (s *Service) ClearCache() error {
	s.scopeCache = make(map[scope.TypeID]*ScopedConfig)
	return nil
}

// DebugCache uses Sprintf to write an ordered list (by scope.TypeID) into a
// writer. Only usable for debugging.
func (s *Service) DebugCache(w io.Writer) error {
	s.rwmu.RLock()
	defer s.rwmu.RUnlock()
	srtScope := make(scope.TypeIDs, len(s.scopeCache))
	var i int
	for scp := range s.scopeCache {
		srtScope[i] = scp
		i++
	}
	sort.Sort(srtScope)
	for _, scp := range srtScope {
		scpCfg := s.scopeCache[scp]
		if _, err := fmt.Fprintf(w, "%s => [%p]=%#v\n", scp, scpCfg, scpCfg); err != nil {
			return errors.Wrap(err, "[scopedservice] DebugCache Fprintf")
		}
	}
	return nil
}

// ConfigByScope creates a new scoped configuration depending on the
// Service.useWebsite flag. If useWebsite==true the scoped configuration
// contains only the website->default scope despite setting a store scope. If an
// OptionFactory is set the configuration gets loaded from the backend. A nil
// root config causes a panic.
func (s *Service) ConfigByScope(websiteID, storeID int64) (ScopedConfig, error) {
	cfg := s.rootConfig.NewScoped(websiteID, storeID)
	if s.useWebsite {
		cfg = s.rootConfig.NewScoped(websiteID, 0)
	}
	return s.ConfigByScopedGetter(cfg)
}

// configByContext extracts the scope (websiteID and storeID) from a  context.
// The scoped configuration gets initialized by configFromScope() and returned.
// It panics if rootConfig if nil. Errors get not logged.
func (s *Service) configByContext(ctx context.Context) (ScopedConfig, error) {
	// extract the scope out of the context and if not found a programmer made a
	// mistake.
	websiteID, storeID, scopeOK := scope.FromContext(ctx)
	if !scopeOK {
		return ScopedConfig{}, errors.NewNotFoundf("[scopedservice] configByContext: scope.FromContext not found")
	}

	scpCfg, err := s.ConfigByScope(websiteID, storeID)
	if err != nil {
		// the scoped configuration is invalid and hence a programmer or package user
		// made a mistake.
		return ScopedConfig{}, errors.Wrap(err, "[scopedservice] Service.configByContext.configFromScope") // rewrite error
	}
	return scpCfg, nil
}

// ConfigByScopedGetter returns the internal configuration depending on the
// ScopedGetter. Mainly used within the middleware.  If you have applied the
// option WithOptionFactory() the configuration will be pulled out only one time
// from the backend configuration service. The field optionInflight handles the
// guaranteed atomic single loading for each scope.
func (s *Service) ConfigByScopedGetter(scpGet config.Scoped) (ScopedConfig, error) {

	current := scope.MakeTypeID(scpGet.Scope()) // can be store or website or default
	parent := scope.MakeTypeID(scpGet.Parent()) // can be website or default

	// 99.9999 % of the hits; 2nd argument must be zero because we must first
	// test if a direct entry can be found; if not we must apply either the
	// optionFactory function or do a fall back to the website scope and/or
	// default scope.
	if sCfg, err := s.ConfigByScopeID(current, 0); err == nil {
		if s.Log.IsDebug() {
			s.Log.Debug("scopedservice.Service.ConfigByScopedGetter.IsValid",
				log.Stringer("requested_scope", current),
				log.Stringer("requested_parent_scope", scope.TypeID(0)),
				log.Stringer("responded_scope", sCfg.ScopeID),
			)
		}
		return sCfg, nil
	}

	// load the configuration from the slow backend. optionInflight guarantees
	// that the closure will only be executed once but the returned result gets
	// returned to all waiting goroutines.
	if s.optionFactory != nil {
		res, ok := <-s.optionInflight.DoChan(current.String(), func() (interface{}, error) {
			if err := s.Options(s.optionFactory(scpGet)...); err != nil {
				return ScopedConfig{}, errors.Wrap(err, "[scopedservice] Options applied by OptionFactoryFunc")
			}
			sCfg, err := s.ConfigByScopeID(current, parent)
			if s.Log.IsDebug() {
				s.Log.Debug("scopedservice.Service.ConfigByScopedGetter.Inflight.Do",
					log.Stringer("requested_scope", current),
					log.Stringer("requested_parent_scope", parent),
					log.Stringer("responded_scope", sCfg.ScopeID),
					log.ErrWithKey("responded_scope_valid", err),
				)
			}
			return sCfg, errors.Wrap(err, "[scopedservice] Options applied by OptionFactoryFunc")
		})
		if !ok { // unlikely to happen but you'll never know. how to test that?
			return ScopedConfig{}, errors.NewFatalf("[scopedservice] Inflight.DoChan returned a closed/unreadable channel")
		}
		if res.Err != nil {
			return ScopedConfig{}, errors.Wrap(res.Err, "[scopedservice] Inflight.DoChan.Error")
		}
		sCfg, ok := res.Val.(ScopedConfig)
		if !ok {
			return ScopedConfig{}, errors.NewFatalf("[scopedservice] Inflight.DoChan res.Val cannot be type asserted to scopedConfig")
		}
		return sCfg, nil
	}

	sCfg, err := s.ConfigByScopeID(current, parent)
	// under very high load: 20 users within 10 MicroSeconds this might get executed
	// 1-3 times. more thinking needed.
	if s.Log.IsDebug() {
		s.Log.Debug("scopedservice.Service.ConfigByScopedGetter.Parent",
			log.Stringer("requested_scope", current),
			log.Stringer("requested_parent_scope", parent),
			log.Stringer("responded_scope", sCfg.ScopeID),
			log.ErrWithKey("responded_scope_valid", err),
		)
	}
	return sCfg, errors.Wrap(err, "[scopedservice] Options applied and finaly validation")
}

// ConfigByScopeID returns the correct configuration for a scope and may fall
// back to the next higher scope: store -> website -> default. If `current`
// TypeID is Store, then the `parent` can only be Website or Default. If an
// entry for a scope cannot be found the next higher scope gets looked up and
// the pointer of the next higher scope gets assigned to the current scope. This
// prevents redundant configurations and enables us to change one scope
// configuration with an impact on all other scopes which depend on the parent
// scope. A zero `parent` triggers no further look ups. This function does not
// load any configuration (config.Getter related) from the backend and accesses
// the internal map of the Service directly.
func (s *Service) ConfigByScopeID(current scope.TypeID, parent scope.TypeID) (scpCfg ScopedConfig, _ error) {
	// current can be store or website scope
	// parent can be website or default scope. If 0 then no fall back

	// pointer must get dereferenced in a lock to avoid race conditions while
	// reading in middleware the config values because we might execute the
	// functional options for another scope while one scope runs in the
	// middleware.

	// lookup store/website scope. this should hit 99% of the calls of this function.
	s.rwmu.RLock()
	pScpCfg, ok := s.scopeCache[current]
	if ok && pScpCfg != nil {
		scpCfg = *pScpCfg
	}
	s.rwmu.RUnlock()
	if ok {
		return scpCfg, errors.Wrap(scpCfg.isValid(), "[scopedservice] Validated directly found")
	}
	if parent == 0 {
		return scpCfg, errConfigNotFound
	}

	// slow path: now lock everything until the fall back has been found.
	s.rwmu.Lock()
	defer s.rwmu.Unlock()

	// if the current scope cannot be found, fall back to parent scope and
	// apply the maybe found configuration to the current scope configuration.
	if !ok && parent.Type() == scope.Website {
		pScpCfg, ok = s.scopeCache[parent]
		if ok && pScpCfg != nil {
			scpCfg = *pScpCfg
		}
		if ok && pScpCfg != nil {
			s.scopeCache[current] = pScpCfg
			return scpCfg, errors.Wrap(scpCfg.isValid(), "[scopedservice] Validated Parent found and applied")
		}
	}

	// if the current and parent scope cannot be found, fall back to default
	// scope and apply the maybe found configuration to the current scope
	// configuration.
	if !ok {
		pScpCfg, ok = s.scopeCache[scope.DefaultTypeID]
		if ok && pScpCfg != nil {
			scpCfg = *pScpCfg
		}
		if ok && pScpCfg != nil {
			s.scopeCache[current] = pScpCfg
		}
	}
	return scpCfg, errors.Wrap(scpCfg.isValid(), "[scopedservice] Validated Default found")
}
<commit_msg>net/internal/scopedservice: Adjust APi to match config.Scoped<commit_after>// Copyright 2015-2016, Cyrill @ Schumacher.fm and the CoreStore contributors
//
// 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 scopedservice

import (
	"context"
	"fmt"
	"io"
	"sort"
	"sync"

	"github.com/corestoreio/csfw/config"
	"github.com/corestoreio/csfw/log"
	"github.com/corestoreio/csfw/net/mw"
	"github.com/corestoreio/csfw/store/scope"
	"github.com/corestoreio/csfw/sync/singleflight"
	"github.com/corestoreio/csfw/util/errors"
)

// Auto generated: Do not edit. See net/internal/scopedService package for more details.

type service struct {
	// Log used for debugging. Defaults to black hole.
	Log log.Logger

	// ErrorHandler gets called whenever a programmer makes an error. Most two
	// cases are: cannot extract scope from the context and scoped configuration
	// is not valid. The default handler prints the error to the client and
	// returns http.StatusServiceUnavailable
	mw.ErrorHandler

	// rootConfig optional backend configuration. Gets only used while running
	// HTTP related middlewares.
	rootConfig config.Getter

	// useWebsite internal flag used in configByContext(w,r) to tell the
	// currenct handler if the scoped configuration is store or website based.
	useWebsite bool

	// optionFactory optional configuration closure, can be nil. It pulls out
	// the configuration settings from a slow backend during a request and
	// caches the settings in the internal map.  This function gets set via
	// WithOptionFactory()
	optionFactory OptionFactoryFunc

	// optionInflight checks on a per scope.TypeID basis if the configuration
	// loading process takes place. Stops the execution of other Goroutines (aka
	// incoming requests) with the same scope.TypeID until the configuration has
	// been fully loaded and applied for that specific scope. This function gets
	// set via WithOptionFactory()
	optionInflight *singleflight.Group

	// optionAfterApply allows to set a custom function which runs every time
	// after the options have been applied. Gets only executed if not nil.
	optionAfterApply func() error

	// rwmu protects all fields below
	rwmu sync.RWMutex

	// scopeCache internal cache for configurations.
	scopeCache map[scope.TypeID]*ScopedConfig
}

func newService(opts ...Option) (*Service, error) {
	s := &Service{
		service: service{
			Log:          log.BlackHole{},
			ErrorHandler: defaultErrorHandler,
			scopeCache:   make(map[scope.TypeID]*ScopedConfig),
		},
	}
	if err := s.Options(WithDefaultConfig(scope.DefaultTypeID)); err != nil {
		return nil, errors.Wrap(err, "[scopedservice] Options WithDefaultConfig")
	}
	if err := s.Options(opts...); err != nil {
		return nil, errors.Wrap(err, "[scopedservice] Options any config")
	}
	return s, nil
}

// MustNew same as New() but panics on error. Use only during app start up process.
func MustNew(opts ...Option) *Service {
	c, err := New(opts...)
	if err != nil {
		panic(err)
	}
	return c
}

// Options applies option at creation time or refreshes them.
func (s *Service) Options(opts ...Option) error {
	for _, opt := range opts {
		// opt can be nil because of the backend options where we have an array instead
		// of a slice.
		if opt != nil {
			if err := opt(s); err != nil {
				return errors.Wrap(err, "[scopedservice] Service.Options")
			}
		}
	}
	if s.optionAfterApply != nil {
		return errors.Wrap(s.optionAfterApply(), "[scopedservice] optionValidation")
	}
	return nil
}

// ClearCache clears the internal map storing all scoped configurations. You
// must reapply all functional options.
// TODO(CyS) all previously applied options will be automatically reapplied.
func (s *Service) ClearCache() error {
	s.scopeCache = make(map[scope.TypeID]*ScopedConfig)
	return nil
}

// DebugCache uses Sprintf to write an ordered list (by scope.TypeID) into a
// writer. Only usable for debugging.
func (s *Service) DebugCache(w io.Writer) error {
	s.rwmu.RLock()
	defer s.rwmu.RUnlock()
	srtScope := make(scope.TypeIDs, len(s.scopeCache))
	var i int
	for scp := range s.scopeCache {
		srtScope[i] = scp
		i++
	}
	sort.Sort(srtScope)
	for _, scp := range srtScope {
		scpCfg := s.scopeCache[scp]
		if _, err := fmt.Fprintf(w, "%s => [%p]=%#v\n", scp, scpCfg, scpCfg); err != nil {
			return errors.Wrap(err, "[scopedservice] DebugCache Fprintf")
		}
	}
	return nil
}

// ConfigByScope creates a new scoped configuration depending on the
// Service.useWebsite flag. If useWebsite==true the scoped configuration
// contains only the website->default scope despite setting a store scope. If an
// OptionFactory is set the configuration gets loaded from the backend. A nil
// root config causes a panic.
func (s *Service) ConfigByScope(websiteID, storeID int64) (ScopedConfig, error) {
	cfg := s.rootConfig.NewScoped(websiteID, storeID)
	if s.useWebsite {
		cfg = s.rootConfig.NewScoped(websiteID, 0)
	}
	return s.ConfigByScopedGetter(cfg)
}

// configByContext extracts the scope (websiteID and storeID) from a  context.
// The scoped configuration gets initialized by configFromScope() and returned.
// It panics if rootConfig if nil. Errors get not logged.
func (s *Service) configByContext(ctx context.Context) (ScopedConfig, error) {
	// extract the scope out of the context and if not found a programmer made a
	// mistake.
	websiteID, storeID, scopeOK := scope.FromContext(ctx)
	if !scopeOK {
		return ScopedConfig{}, errors.NewNotFoundf("[scopedservice] configByContext: scope.FromContext not found")
	}

	scpCfg, err := s.ConfigByScope(websiteID, storeID)
	if err != nil {
		// the scoped configuration is invalid and hence a programmer or package user
		// made a mistake.
		return ScopedConfig{}, errors.Wrap(err, "[scopedservice] Service.configByContext.configFromScope") // rewrite error
	}
	return scpCfg, nil
}

// ConfigByScopedGetter returns the internal configuration depending on the
// ScopedGetter. Mainly used within the middleware.  If you have applied the
// option WithOptionFactory() the configuration will be pulled out only one time
// from the backend configuration service. The field optionInflight handles the
// guaranteed atomic single loading for each scope.
func (s *Service) ConfigByScopedGetter(scpGet config.Scoped) (ScopedConfig, error) {

	parent := scpGet.ParentID() // can be website or default
	current := scpGet.ScopeID() // can be store or website or default

	// 99.9999 % of the hits; 2nd argument must be zero because we must first
	// test if a direct entry can be found; if not we must apply either the
	// optionFactory function or do a fall back to the website scope and/or
	// default scope.
	if sCfg, err := s.ConfigByScopeID(current, 0); err == nil {
		if s.Log.IsDebug() {
			s.Log.Debug("scopedservice.Service.ConfigByScopedGetter.IsValid",
				log.Stringer("requested_scope", current),
				log.Stringer("requested_parent_scope", scope.TypeID(0)),
				log.Stringer("responded_scope", sCfg.ScopeID),
			)
		}
		return sCfg, nil
	}

	// load the configuration from the slow backend. optionInflight guarantees
	// that the closure will only be executed once but the returned result gets
	// returned to all waiting goroutines.
	if s.optionFactory != nil {
		res, ok := <-s.optionInflight.DoChan(current.String(), func() (interface{}, error) {
			if err := s.Options(s.optionFactory(scpGet)...); err != nil {
				return ScopedConfig{}, errors.Wrap(err, "[scopedservice] Options applied by OptionFactoryFunc")
			}
			sCfg, err := s.ConfigByScopeID(current, parent)
			if s.Log.IsDebug() {
				s.Log.Debug("scopedservice.Service.ConfigByScopedGetter.Inflight.Do",
					log.Stringer("requested_scope", current),
					log.Stringer("requested_parent_scope", parent),
					log.Stringer("responded_scope", sCfg.ScopeID),
					log.ErrWithKey("responded_scope_valid", err),
				)
			}
			return sCfg, errors.Wrap(err, "[scopedservice] Options applied by OptionFactoryFunc")
		})
		if !ok { // unlikely to happen but you'll never know. how to test that?
			return ScopedConfig{}, errors.NewFatalf("[scopedservice] Inflight.DoChan returned a closed/unreadable channel")
		}
		if res.Err != nil {
			return ScopedConfig{}, errors.Wrap(res.Err, "[scopedservice] Inflight.DoChan.Error")
		}
		sCfg, ok := res.Val.(ScopedConfig)
		if !ok {
			return ScopedConfig{}, errors.NewFatalf("[scopedservice] Inflight.DoChan res.Val cannot be type asserted to scopedConfig")
		}
		return sCfg, nil
	}

	sCfg, err := s.ConfigByScopeID(current, parent)
	// under very high load: 20 users within 10 MicroSeconds this might get executed
	// 1-3 times. more thinking needed.
	if s.Log.IsDebug() {
		s.Log.Debug("scopedservice.Service.ConfigByScopedGetter.Parent",
			log.Stringer("requested_scope", current),
			log.Stringer("requested_parent_scope", parent),
			log.Stringer("responded_scope", sCfg.ScopeID),
			log.ErrWithKey("responded_scope_valid", err),
		)
	}
	return sCfg, errors.Wrap(err, "[scopedservice] Options applied and finaly validation")
}

// ConfigByScopeID returns the correct configuration for a scope and may fall
// back to the next higher scope: store -> website -> default. If `current`
// TypeID is Store, then the `parent` can only be Website or Default. If an
// entry for a scope cannot be found the next higher scope gets looked up and
// the pointer of the next higher scope gets assigned to the current scope. This
// prevents redundant configurations and enables us to change one scope
// configuration with an impact on all other scopes which depend on the parent
// scope. A zero `parent` triggers no further look ups. This function does not
// load any configuration (config.Getter related) from the backend and accesses
// the internal map of the Service directly.
func (s *Service) ConfigByScopeID(current scope.TypeID, parent scope.TypeID) (scpCfg ScopedConfig, _ error) {
	// current can be store or website scope
	// parent can be website or default scope. If 0 then no fall back

	// pointer must get dereferenced in a lock to avoid race conditions while
	// reading in middleware the config values because we might execute the
	// functional options for another scope while one scope runs in the
	// middleware.

	// lookup store/website scope. this should hit 99% of the calls of this function.
	s.rwmu.RLock()
	pScpCfg, ok := s.scopeCache[current]
	if ok && pScpCfg != nil {
		scpCfg = *pScpCfg
	}
	s.rwmu.RUnlock()
	if ok {
		return scpCfg, errors.Wrap(scpCfg.isValid(), "[scopedservice] Validated directly found")
	}
	if parent == 0 {
		return scpCfg, errConfigNotFound
	}

	// slow path: now lock everything until the fall back has been found.
	s.rwmu.Lock()
	defer s.rwmu.Unlock()

	// if the current scope cannot be found, fall back to parent scope and
	// apply the maybe found configuration to the current scope configuration.
	if !ok && parent.Type() == scope.Website {
		pScpCfg, ok = s.scopeCache[parent]
		if ok && pScpCfg != nil {
			scpCfg = *pScpCfg
		}
		if ok && pScpCfg != nil {
			s.scopeCache[current] = pScpCfg
			return scpCfg, errors.Wrap(scpCfg.isValid(), "[scopedservice] Validated Parent found and applied")
		}
	}

	// if the current and parent scope cannot be found, fall back to default
	// scope and apply the maybe found configuration to the current scope
	// configuration.
	if !ok {
		pScpCfg, ok = s.scopeCache[scope.DefaultTypeID]
		if ok && pScpCfg != nil {
			scpCfg = *pScpCfg
		}
		if ok && pScpCfg != nil {
			s.scopeCache[current] = pScpCfg
		}
	}
	return scpCfg, errors.Wrap(scpCfg.isValid(), "[scopedservice] Validated Default found")
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"strings"
	"text/template"

	"github.com/codegangsta/cli"
	"github.com/docker-library/go-dockerlibrary/manifest"
	"github.com/docker-library/go-dockerlibrary/pkg/templatelib"
)

var DefaultCatFormat = `
{{- if i -}}
	{{- "\n\n" -}}
{{- end -}}
{{- with .TagEntries -}}
	{{- range $i, $e := . -}}
		{{- if $i -}}{{- "\n\n" -}}{{- end -}}
		{{- $e -}}
	{{- end -}}
{{- else -}}
	{{- .Manifest -}}
{{- end -}}
`

func cmdCat(c *cli.Context) error {
	repos, err := repos(c.Bool("all"), c.Args()...)
	if err != nil {
		return cli.NewMultiError(fmt.Errorf(`failed gathering repo list`), err)
	}

	format := c.String("format")
	formatFile := c.String("format-file")

	templateName := "--format"
	tmplMultiErr := fmt.Errorf(`failed parsing --format %q`, format)
	if formatFile != "" {
		b, err := ioutil.ReadFile(formatFile)
		if err != nil {
			return cli.NewMultiError(fmt.Errorf(`failed reading --format-file %q`, formatFile), err)
		}
		templateName = formatFile
		tmplMultiErr = fmt.Errorf(`failed parsing --format-file %q`, formatFile)
		format = string(b)
	}

	var i int
	tmpl, err := template.New(templateName).Funcs(templatelib.FuncMap).Funcs(template.FuncMap{
		"i": func() int {
			return i
		},
		"arch": func() string {
			return arch
		},
		"namespace": func() string {
			return namespace
		},
		"archNamespace": func(arch string) string {
			return archNamespaces[arch]
		},
		"archFilter": func(arch string, entriesArg ...interface{}) []manifest.Manifest2822Entry {
			if len(entriesArg) < 1 {
				panic(`"archFilter" requires at least one argument`)
			}
			entries := []manifest.Manifest2822Entry{}
			for _, entryArg := range entriesArg {
				switch v := entryArg.(type) {
				case []*manifest.Manifest2822Entry:
					for _, e := range v {
						entries = append(entries, *e)
					}
				case []manifest.Manifest2822Entry:
					entries = append(entries, v...)
				case manifest.Manifest2822Entry:
					entries = append(entries, v)
				default:
					panic(fmt.Sprintf(`"archFilter" encountered unknown type: %T`, v, v))
				}
			}
			filtered := []manifest.Manifest2822Entry{}
			for _, entry := range entries {
				if entry.HasArchitecture(arch) {
					filtered = append(filtered, entry)
				}
			}
			return filtered
		},
	}).Parse(format)
	if err != nil {
		return cli.NewMultiError(tmplMultiErr, err)
	}

	var repo string
	for i, repo = range repos {
		r, err := fetch(repo)
		if err != nil {
			return cli.NewMultiError(fmt.Errorf(`failed fetching repo %q`, repo), err)
		}

		buf := &bytes.Buffer{}
		err = tmpl.ExecuteTemplate(buf, templateName, r)
		if err != nil {
			return cli.NewMultiError(fmt.Errorf(`failed executing template for repo %q`, repo), err)
		}
		out := buf.String()
		fmt.Print(out)
		if !strings.HasSuffix(out, "\n") {
			fmt.Println()
		}
	}

	return nil
}
<commit_msg>bashbrew:go:cmd-cat: remove extra v in Sprintf<commit_after>package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"strings"
	"text/template"

	"github.com/codegangsta/cli"
	"github.com/docker-library/go-dockerlibrary/manifest"
	"github.com/docker-library/go-dockerlibrary/pkg/templatelib"
)

var DefaultCatFormat = `
{{- if i -}}
	{{- "\n\n" -}}
{{- end -}}
{{- with .TagEntries -}}
	{{- range $i, $e := . -}}
		{{- if $i -}}{{- "\n\n" -}}{{- end -}}
		{{- $e -}}
	{{- end -}}
{{- else -}}
	{{- .Manifest -}}
{{- end -}}
`

func cmdCat(c *cli.Context) error {
	repos, err := repos(c.Bool("all"), c.Args()...)
	if err != nil {
		return cli.NewMultiError(fmt.Errorf(`failed gathering repo list`), err)
	}

	format := c.String("format")
	formatFile := c.String("format-file")

	templateName := "--format"
	tmplMultiErr := fmt.Errorf(`failed parsing --format %q`, format)
	if formatFile != "" {
		b, err := ioutil.ReadFile(formatFile)
		if err != nil {
			return cli.NewMultiError(fmt.Errorf(`failed reading --format-file %q`, formatFile), err)
		}
		templateName = formatFile
		tmplMultiErr = fmt.Errorf(`failed parsing --format-file %q`, formatFile)
		format = string(b)
	}

	var i int
	tmpl, err := template.New(templateName).Funcs(templatelib.FuncMap).Funcs(template.FuncMap{
		"i": func() int {
			return i
		},
		"arch": func() string {
			return arch
		},
		"namespace": func() string {
			return namespace
		},
		"archNamespace": func(arch string) string {
			return archNamespaces[arch]
		},
		"archFilter": func(arch string, entriesArg ...interface{}) []manifest.Manifest2822Entry {
			if len(entriesArg) < 1 {
				panic(`"archFilter" requires at least one argument`)
			}
			entries := []manifest.Manifest2822Entry{}
			for _, entryArg := range entriesArg {
				switch v := entryArg.(type) {
				case []*manifest.Manifest2822Entry:
					for _, e := range v {
						entries = append(entries, *e)
					}
				case []manifest.Manifest2822Entry:
					entries = append(entries, v...)
				case manifest.Manifest2822Entry:
					entries = append(entries, v)
				default:
					panic(fmt.Sprintf(`"archFilter" encountered unknown type: %T`, v))
				}
			}
			filtered := []manifest.Manifest2822Entry{}
			for _, entry := range entries {
				if entry.HasArchitecture(arch) {
					filtered = append(filtered, entry)
				}
			}
			return filtered
		},
	}).Parse(format)
	if err != nil {
		return cli.NewMultiError(tmplMultiErr, err)
	}

	var repo string
	for i, repo = range repos {
		r, err := fetch(repo)
		if err != nil {
			return cli.NewMultiError(fmt.Errorf(`failed fetching repo %q`, repo), err)
		}

		buf := &bytes.Buffer{}
		err = tmpl.ExecuteTemplate(buf, templateName, r)
		if err != nil {
			return cli.NewMultiError(fmt.Errorf(`failed executing template for repo %q`, repo), err)
		}
		out := buf.String()
		fmt.Print(out)
		if !strings.HasSuffix(out, "\n") {
			fmt.Println()
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package doozer

import (
	"doozer/client"
	"github.com/bmizerany/assert"
	"net"
	"runtime"
	"testing"
)

// Upper bound on number of leaked goroutines.
// Our goal is to reduce this to zero.
const leaked = 23

func mustListen() net.Listener {
	l, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		panic(err)
	}
	return l
}

func mustListenPacket(addr string) net.PacketConn {
	c, err := net.ListenPacket("udp", addr)
	if err != nil {
		panic(err)
	}
	return c
}

func TestDoozerSimple(t *testing.T) {
	l := mustListen()
	defer l.Close()
	u := mustListenPacket(l.Addr().String())
	defer u.Close()

	go Main("a", "", u, l, nil)

	cl, err := client.Dial(l.Addr().String())
	assert.Equal(t, nil, err)
	assert.Equal(t, nil, cl.Noop())
}

func TestDoozerWatchSimple(t *testing.T) {
	l := mustListen()
	defer l.Close()
	u := mustListenPacket(l.Addr().String())
	defer u.Close()

	go Main("a", "", u, l, nil)

	cl, err := client.Dial(l.Addr().String())
	assert.Equal(t, nil, err)

	ch, err := cl.Watch("/test/**")
	assert.Equal(t, nil, err, err)
	defer close(ch)

	// TODO: Remove need to execute in goroutine
	// (i.e. Set/Watch should behave closer to using them natively
	go cl.Set("/test/foo", "bar", "")
	ev := <-ch
	assert.Equal(t, "/test/foo", ev.Path)
	assert.Equal(t, "bar", ev.Body)
	assert.NotEqual(t, "", ev.Cas)

	go cl.Set("/test/fun", "house", "")
	ev = <-ch
	assert.Equal(t, "/test/fun", ev.Path)
	assert.Equal(t, "house", ev.Body)
	assert.NotEqual(t, "", ev.Cas)
}

func TestDoozerGoroutines(t *testing.T) {
	gs := runtime.Goroutines()

	func() {
		l := mustListen()
		defer l.Close()
		u := mustListenPacket(l.Addr().String())
		defer u.Close()

		go Main("a", "", u, l, nil)

		cl, err := client.Dial(l.Addr().String())
		assert.Equal(t, nil, err)
		cl.Noop()
	}()

	assert.T(t, gs+leaked >= runtime.Goroutines(), gs+leaked)
}
<commit_msg>pkg: remove unneeded goroutines in test<commit_after>package doozer

import (
	"doozer/client"
	"github.com/bmizerany/assert"
	"net"
	"runtime"
	"testing"
)

// Upper bound on number of leaked goroutines.
// Our goal is to reduce this to zero.
const leaked = 23

func mustListen() net.Listener {
	l, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		panic(err)
	}
	return l
}

func mustListenPacket(addr string) net.PacketConn {
	c, err := net.ListenPacket("udp", addr)
	if err != nil {
		panic(err)
	}
	return c
}

func TestDoozerSimple(t *testing.T) {
	l := mustListen()
	defer l.Close()
	u := mustListenPacket(l.Addr().String())
	defer u.Close()

	go Main("a", "", u, l, nil)

	cl, err := client.Dial(l.Addr().String())
	assert.Equal(t, nil, err)
	assert.Equal(t, nil, cl.Noop())
}

func TestDoozerWatchSimple(t *testing.T) {
	l := mustListen()
	defer l.Close()
	u := mustListenPacket(l.Addr().String())
	defer u.Close()

	go Main("a", "", u, l, nil)

	cl, err := client.Dial(l.Addr().String())
	assert.Equal(t, nil, err)

	ch, err := cl.Watch("/test/**")
	assert.Equal(t, nil, err, err)
	defer close(ch)

	cl.Set("/test/foo", "bar", "")
	ev := <-ch
	assert.Equal(t, "/test/foo", ev.Path)
	assert.Equal(t, "bar", ev.Body)
	assert.NotEqual(t, "", ev.Cas)

	cl.Set("/test/fun", "house", "")
	ev = <-ch
	assert.Equal(t, "/test/fun", ev.Path)
	assert.Equal(t, "house", ev.Body)
	assert.NotEqual(t, "", ev.Cas)
}

func TestDoozerGoroutines(t *testing.T) {
	gs := runtime.Goroutines()

	func() {
		l := mustListen()
		defer l.Close()
		u := mustListenPacket(l.Addr().String())
		defer u.Close()

		go Main("a", "", u, l, nil)

		cl, err := client.Dial(l.Addr().String())
		assert.Equal(t, nil, err)
		cl.Noop()
	}()

	assert.T(t, gs+leaked >= runtime.Goroutines(), gs+leaked)
}
<|endoftext|>


<commit_before>// TODO FIXME name me
package worker

import (
	"container/list"
	"errors"
	"time"

	context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
	process "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess"
	ratelimit "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess/ratelimit"
	blocks "github.com/jbenet/go-ipfs/blocks"
	exchange "github.com/jbenet/go-ipfs/exchange"
	util "github.com/jbenet/go-ipfs/util"
)

var log = util.Logger("blockservice")

var DefaultConfig = Config{
	NumWorkers:       1,
	ClientBufferSize: 0,
	WorkerBufferSize: 0,
}

type Config struct {
	// NumWorkers sets the number of background workers that provide blocks to
	// the exchange.
	NumWorkers int

	// ClientBufferSize allows clients of HasBlock to send up to
	// |ClientBufferSize| blocks without blocking.
	ClientBufferSize int

	// WorkerBufferSize can be used in conjunction with NumWorkers to reduce
	// communication-coordination within the worker.
	WorkerBufferSize int
}

// TODO FIXME name me
type Worker struct {
	// added accepts blocks from client
	added    chan *blocks.Block
	exchange exchange.Interface

	// workQueue is owned by the client worker
	// process manages life-cycle
	process process.Process
}

func NewWorker(e exchange.Interface, c Config) *Worker {
	if c.NumWorkers < 1 {
		c.NumWorkers = 1 // provide a sane default
	}
	w := &Worker{
		exchange: e,
		added:    make(chan *blocks.Block, c.ClientBufferSize),
		process:  process.WithParent(process.Background()), // internal management
	}
	w.start(c)
	return w
}

func (w *Worker) HasBlock(b *blocks.Block) error {
	select {
	case <-w.process.Closed():
		return errors.New("blockservice worker is closed")
	case w.added <- b:
		return nil
	}
}

func (w *Worker) Close() error {
	log.Debug("blockservice provide worker is shutting down...")
	return w.process.Close()
}

func (w *Worker) start(c Config) {

	workerChan := make(chan *blocks.Block, c.WorkerBufferSize)

	// clientWorker handles incoming blocks from |w.added| and sends to
	// |workerChan|. This will never block the client.
	w.process.Go(func(proc process.Process) {
		defer close(workerChan)

		var workQueue BlockList
		for {

			// take advantage of the fact that sending on nil channel always
			// blocks so that a message is only sent if a block exists
			sendToWorker := workerChan
			nextBlock := workQueue.Pop()
			if nextBlock == nil {
				sendToWorker = nil
			}

			select {

			// if worker is ready and there's a block to process, send the
			// block
			case sendToWorker <- nextBlock:
			case <-time.Tick(5 * time.Second):
				if workQueue.Len() > 0 {
					log.Debugf("%d blocks in blockservice provide queue...", workQueue.Len())
				}
			case block := <-w.added:
				if nextBlock != nil {
					workQueue.Push(nextBlock) // missed the chance to send it
				}
				// if the client sends another block, add it to the queue.
				workQueue.Push(block)
			case <-proc.Closing():
				return
			}
		}
	})

	// reads from |workerChan| until process closes
	w.process.Go(func(proc process.Process) {
		ctx, cancel := context.WithCancel(context.Background())

		// shuts down an in-progress HasBlock operation
		proc.Go(func(proc process.Process) {
			<-proc.Closing()
			cancel()
		})

		limiter := ratelimit.NewRateLimiter(proc, c.NumWorkers)
		for {
			select {
			case <-proc.Closing():
				return
			case block, ok := <-workerChan:
				if !ok {
					return
				}
				limiter.LimitedGo(func(proc process.Process) {
					if err := w.exchange.HasBlock(ctx, block); err != nil {
						// TODO log event?
					}
				})
			}
		}
	})
}

type BlockList struct {
	list list.List
}

func (s *BlockList) PushFront(b *blocks.Block) {
	// FIXME find figures
	s.list.PushFront(b)
}

func (s *BlockList) Push(b *blocks.Block) {
	s.list.PushBack(b)
}

func (s *BlockList) Pop() *blocks.Block {
	if s.list.Len() == 0 {
		return nil
	}
	e := s.list.Front()
	s.list.Remove(e)
	return e.Value.(*blocks.Block)
}

func (s *BlockList) Len() int {
	return s.list.Len()
}
<commit_msg>extract context func<commit_after>// TODO FIXME name me
package worker

import (
	"container/list"
	"errors"
	"time"

	context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
	process "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess"
	ratelimit "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess/ratelimit"
	blocks "github.com/jbenet/go-ipfs/blocks"
	exchange "github.com/jbenet/go-ipfs/exchange"
	util "github.com/jbenet/go-ipfs/util"
)

var log = util.Logger("blockservice")

var DefaultConfig = Config{
	NumWorkers:       1,
	ClientBufferSize: 0,
	WorkerBufferSize: 0,
}

type Config struct {
	// NumWorkers sets the number of background workers that provide blocks to
	// the exchange.
	NumWorkers int

	// ClientBufferSize allows clients of HasBlock to send up to
	// |ClientBufferSize| blocks without blocking.
	ClientBufferSize int

	// WorkerBufferSize can be used in conjunction with NumWorkers to reduce
	// communication-coordination within the worker.
	WorkerBufferSize int
}

// TODO FIXME name me
type Worker struct {
	// added accepts blocks from client
	added    chan *blocks.Block
	exchange exchange.Interface

	// workQueue is owned by the client worker
	// process manages life-cycle
	process process.Process
}

func NewWorker(e exchange.Interface, c Config) *Worker {
	if c.NumWorkers < 1 {
		c.NumWorkers = 1 // provide a sane default
	}
	w := &Worker{
		exchange: e,
		added:    make(chan *blocks.Block, c.ClientBufferSize),
		process:  process.WithParent(process.Background()), // internal management
	}
	w.start(c)
	return w
}

func (w *Worker) HasBlock(b *blocks.Block) error {
	select {
	case <-w.process.Closed():
		return errors.New("blockservice worker is closed")
	case w.added <- b:
		return nil
	}
}

func (w *Worker) Close() error {
	log.Debug("blockservice provide worker is shutting down...")
	return w.process.Close()
}

func (w *Worker) start(c Config) {

	workerChan := make(chan *blocks.Block, c.WorkerBufferSize)

	// clientWorker handles incoming blocks from |w.added| and sends to
	// |workerChan|. This will never block the client.
	w.process.Go(func(proc process.Process) {
		defer close(workerChan)

		var workQueue BlockList
		for {

			// take advantage of the fact that sending on nil channel always
			// blocks so that a message is only sent if a block exists
			sendToWorker := workerChan
			nextBlock := workQueue.Pop()
			if nextBlock == nil {
				sendToWorker = nil
			}

			select {

			// if worker is ready and there's a block to process, send the
			// block
			case sendToWorker <- nextBlock:
			case <-time.Tick(5 * time.Second):
				if workQueue.Len() > 0 {
					log.Debugf("%d blocks in blockservice provide queue...", workQueue.Len())
				}
			case block := <-w.added:
				if nextBlock != nil {
					workQueue.Push(nextBlock) // missed the chance to send it
				}
				// if the client sends another block, add it to the queue.
				workQueue.Push(block)
			case <-proc.Closing():
				return
			}
		}
	})

	// reads from |workerChan| until process closes
	w.process.Go(func(proc process.Process) {
		ctx := childContext(proc) // shut down in-progress HasBlock when time to die
		limiter := ratelimit.NewRateLimiter(proc, c.NumWorkers)
		for {
			select {
			case <-proc.Closing():
				return
			case block, ok := <-workerChan:
				if !ok {
					return
				}
				limiter.LimitedGo(func(proc process.Process) {
					if err := w.exchange.HasBlock(ctx, block); err != nil {
						// TODO log event?
					}
				})
			}
		}
	})
}

type BlockList struct {
	list list.List
}

func (s *BlockList) PushFront(b *blocks.Block) {
	// FIXME find figures
	s.list.PushFront(b)
}

func (s *BlockList) Push(b *blocks.Block) {
	s.list.PushBack(b)
}

func (s *BlockList) Pop() *blocks.Block {
	if s.list.Len() == 0 {
		return nil
	}
	e := s.list.Front()
	s.list.Remove(e)
	return e.Value.(*blocks.Block)
}

func (s *BlockList) Len() int {
	return s.list.Len()
}

// TODO extract
type waitable interface {
	Closing() <-chan struct{}
}

// TODO extract
func childContext(w waitable) context.Context {
	ctx, cancel := context.WithCancel(context.Background())
	go func() {
		<-w.Closing()
		cancel()
	}()
	return ctx
}
<|endoftext|>


<commit_before>// Copyright 2011 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 xml

import (
	"bufio"
	"io"
	"os"
	"reflect"
	"strconv"
	"strings"
)

const (
	// A generic XML header suitable for use with the output of Marshal and MarshalIndent.
	// This is not automatically added to any output of this package, it is provided as a
	// convenience.
	Header = `<?xml version="1.0" encoding="UTF-8">\n`
)

// A Marshaler can produce well-formatted XML representing its internal state.
// It is used by both Marshal and MarshalIndent.
type Marshaler interface {
	MarshalXML() ([]byte, os.Error)
}

type printer struct {
	*bufio.Writer
}

// Marshal writes an XML-formatted representation of v to w.
//
// If v implements Marshaler, then Marshal calls its MarshalXML method.
// Otherwise, Marshal uses the following procedure to create the XML.
//
// Marshal handles an array or slice by marshalling each of the elements.
// Marshal handles a pointer by marshalling the value it points at or, if the
// pointer is nil, by writing nothing.  Marshal handles an interface value by
// marshalling the value it contains or, if the interface value is nil, by
// writing nothing.  Marshal handles all other data by writing a single XML
// element containing the data.
//
// The name of that XML element is taken from, in order of preference:
//     - the tag on an XMLName field, if the data is a struct
//     - the value of an XMLName field of type xml.Name
//     - the tag of the struct field used to obtain the data
//     - the name of the struct field used to obtain the data
//     - the name '???'.
//
// The XML element for a struct contains marshalled elements for each of the
// exported fields of the struct, with these exceptions:
//     - the XMLName field, described above, is omitted.
//     - a field with tag "attr" becomes an attribute in the XML element.
//     - a field with tag "chardata" is written as character data,
//        not as an XML element.
//     - a field with tag "innerxml" is written verbatim,
//        not subject to the usual marshalling procedure.
//
// Marshal will return an error if asked to marshal a channel, function, or map.
func Marshal(w io.Writer, v interface{}) (err os.Error) {
	p := &printer{bufio.NewWriter(w)}
	err = p.marshalValue(reflect.ValueOf(v), "???")
	p.Flush()
	return err
}

func (p *printer) marshalValue(val reflect.Value, name string) os.Error {
	if !val.IsValid() {
		return nil
	}

	kind := val.Kind()
	typ := val.Type()

	// Try Marshaler
	if typ.NumMethod() > 0 {
		if marshaler, ok := val.Interface().(Marshaler); ok {
			bytes, err := marshaler.MarshalXML()
			if err != nil {
				return err
			}
			p.Write(bytes)
			return nil
		}
	}

	// Drill into pointers/interfaces
	if kind == reflect.Ptr || kind == reflect.Interface {
		if val.IsNil() {
			return nil
		}
		return p.marshalValue(val.Elem(), name)
	}

	// Slices and arrays iterate over the elements. They do not have an enclosing tag.
	if (kind == reflect.Slice || kind == reflect.Array) && typ.Elem().Kind() != reflect.Uint8 {
		for i, n := 0, val.Len(); i < n; i++ {
			if err := p.marshalValue(val.Index(i), name); err != nil {
				return err
			}
		}
		return nil
	}

	// Find XML name
	xmlns := ""
	if kind == reflect.Struct {
		if f, ok := typ.FieldByName("XMLName"); ok {
			if tag := f.Tag.Get("xml"); tag != "" {
				if i := strings.Index(tag, " "); i >= 0 {
					xmlns, name = tag[:i], tag[i+1:]
				} else {
					name = tag
				}
			} else if v, ok := val.FieldByIndex(f.Index).Interface().(Name); ok && v.Local != "" {
				xmlns, name = v.Space, v.Local
			}
		}
	}

	p.WriteByte('<')
	p.WriteString(name)

	// Attributes
	if kind == reflect.Struct {
		if len(xmlns) > 0 {
			p.WriteString(` xmlns="`)
			Escape(p, []byte(xmlns))
			p.WriteByte('"')
		}

		for i, n := 0, typ.NumField(); i < n; i++ {
			if f := typ.Field(i); f.PkgPath == "" && f.Tag.Get("xml") == "attr" {
				if f.Type.Kind() == reflect.String {
					if str := val.Field(i).String(); str != "" {
						p.WriteByte(' ')
						p.WriteString(strings.ToLower(f.Name))
						p.WriteString(`="`)
						Escape(p, []byte(str))
						p.WriteByte('"')
					}
				}
			}
		}
	}
	p.WriteByte('>')

	switch k := val.Kind(); k {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		p.WriteString(strconv.Itoa64(val.Int()))
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		p.WriteString(strconv.Uitoa64(val.Uint()))
	case reflect.Float32, reflect.Float64:
		p.WriteString(strconv.Ftoa64(val.Float(), 'g', -1))
	case reflect.String:
		Escape(p, []byte(val.String()))
	case reflect.Bool:
		p.WriteString(strconv.Btoa(val.Bool()))
	case reflect.Array:
		// will be [...]byte
		bytes := make([]byte, val.Len())
		for i := range bytes {
			bytes[i] = val.Index(i).Interface().(byte)
		}
		Escape(p, bytes)
	case reflect.Slice:
		// will be []byte
		bytes := val.Interface().([]byte)
		Escape(p, bytes)
	case reflect.Struct:
		for i, n := 0, val.NumField(); i < n; i++ {
			if f := typ.Field(i); f.Name != "XMLName" && f.PkgPath == "" {
				name := f.Name
				switch tag := f.Tag.Get("xml"); tag {
				case "":
				case "chardata":
					if tk := f.Type.Kind(); tk == reflect.String {
						p.Write([]byte(val.Field(i).String()))
					} else if tk == reflect.Slice {
						if elem, ok := val.Field(i).Interface().([]byte); ok {
							Escape(p, elem)
						}
					}
					continue
				case "innerxml":
					iface := val.Field(i).Interface()
					switch raw := iface.(type) {
					case []byte:
						p.Write(raw)
						continue
					case string:
						p.WriteString(raw)
						continue
					}
				case "attr":
					continue
				default:
					name = tag
				}

				if err := p.marshalValue(val.Field(i), name); err != nil {
					return err
				}
			}
		}
	default:
		return &UnsupportedTypeError{typ}
	}

	p.WriteByte('<')
	p.WriteByte('/')
	p.WriteString(name)
	p.WriteByte('>')

	return nil
}

// A MarshalXMLError is returned when Marshal or MarshalIndent encounter a type
// that cannot be converted into XML.
type UnsupportedTypeError struct {
	Type reflect.Type
}

func (e *UnsupportedTypeError) String() string {
	return "xml: unsupported type: " + e.Type.String()
}
<commit_msg>xml: Header: fix close tag and newline<commit_after>// Copyright 2011 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 xml

import (
	"bufio"
	"io"
	"os"
	"reflect"
	"strconv"
	"strings"
)

const (
	// A generic XML header suitable for use with the output of Marshal and
	// MarshalIndent.  This is not automatically added to any output of this
	// package, it is provided as a convenience.
	Header = `<?xml version="1.0" encoding="UTF-8"?>` + "\n"
)

// A Marshaler can produce well-formatted XML representing its internal state.
// It is used by both Marshal and MarshalIndent.
type Marshaler interface {
	MarshalXML() ([]byte, os.Error)
}

type printer struct {
	*bufio.Writer
}

// Marshal writes an XML-formatted representation of v to w.
//
// If v implements Marshaler, then Marshal calls its MarshalXML method.
// Otherwise, Marshal uses the following procedure to create the XML.
//
// Marshal handles an array or slice by marshalling each of the elements.
// Marshal handles a pointer by marshalling the value it points at or, if the
// pointer is nil, by writing nothing.  Marshal handles an interface value by
// marshalling the value it contains or, if the interface value is nil, by
// writing nothing.  Marshal handles all other data by writing a single XML
// element containing the data.
//
// The name of that XML element is taken from, in order of preference:
//     - the tag on an XMLName field, if the data is a struct
//     - the value of an XMLName field of type xml.Name
//     - the tag of the struct field used to obtain the data
//     - the name of the struct field used to obtain the data
//     - the name '???'.
//
// The XML element for a struct contains marshalled elements for each of the
// exported fields of the struct, with these exceptions:
//     - the XMLName field, described above, is omitted.
//     - a field with tag "attr" becomes an attribute in the XML element.
//     - a field with tag "chardata" is written as character data,
//        not as an XML element.
//     - a field with tag "innerxml" is written verbatim,
//        not subject to the usual marshalling procedure.
//
// Marshal will return an error if asked to marshal a channel, function, or map.
func Marshal(w io.Writer, v interface{}) (err os.Error) {
	p := &printer{bufio.NewWriter(w)}
	err = p.marshalValue(reflect.ValueOf(v), "???")
	p.Flush()
	return err
}

func (p *printer) marshalValue(val reflect.Value, name string) os.Error {
	if !val.IsValid() {
		return nil
	}

	kind := val.Kind()
	typ := val.Type()

	// Try Marshaler
	if typ.NumMethod() > 0 {
		if marshaler, ok := val.Interface().(Marshaler); ok {
			bytes, err := marshaler.MarshalXML()
			if err != nil {
				return err
			}
			p.Write(bytes)
			return nil
		}
	}

	// Drill into pointers/interfaces
	if kind == reflect.Ptr || kind == reflect.Interface {
		if val.IsNil() {
			return nil
		}
		return p.marshalValue(val.Elem(), name)
	}

	// Slices and arrays iterate over the elements. They do not have an enclosing tag.
	if (kind == reflect.Slice || kind == reflect.Array) && typ.Elem().Kind() != reflect.Uint8 {
		for i, n := 0, val.Len(); i < n; i++ {
			if err := p.marshalValue(val.Index(i), name); err != nil {
				return err
			}
		}
		return nil
	}

	// Find XML name
	xmlns := ""
	if kind == reflect.Struct {
		if f, ok := typ.FieldByName("XMLName"); ok {
			if tag := f.Tag.Get("xml"); tag != "" {
				if i := strings.Index(tag, " "); i >= 0 {
					xmlns, name = tag[:i], tag[i+1:]
				} else {
					name = tag
				}
			} else if v, ok := val.FieldByIndex(f.Index).Interface().(Name); ok && v.Local != "" {
				xmlns, name = v.Space, v.Local
			}
		}
	}

	p.WriteByte('<')
	p.WriteString(name)

	// Attributes
	if kind == reflect.Struct {
		if len(xmlns) > 0 {
			p.WriteString(` xmlns="`)
			Escape(p, []byte(xmlns))
			p.WriteByte('"')
		}

		for i, n := 0, typ.NumField(); i < n; i++ {
			if f := typ.Field(i); f.PkgPath == "" && f.Tag.Get("xml") == "attr" {
				if f.Type.Kind() == reflect.String {
					if str := val.Field(i).String(); str != "" {
						p.WriteByte(' ')
						p.WriteString(strings.ToLower(f.Name))
						p.WriteString(`="`)
						Escape(p, []byte(str))
						p.WriteByte('"')
					}
				}
			}
		}
	}
	p.WriteByte('>')

	switch k := val.Kind(); k {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		p.WriteString(strconv.Itoa64(val.Int()))
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		p.WriteString(strconv.Uitoa64(val.Uint()))
	case reflect.Float32, reflect.Float64:
		p.WriteString(strconv.Ftoa64(val.Float(), 'g', -1))
	case reflect.String:
		Escape(p, []byte(val.String()))
	case reflect.Bool:
		p.WriteString(strconv.Btoa(val.Bool()))
	case reflect.Array:
		// will be [...]byte
		bytes := make([]byte, val.Len())
		for i := range bytes {
			bytes[i] = val.Index(i).Interface().(byte)
		}
		Escape(p, bytes)
	case reflect.Slice:
		// will be []byte
		bytes := val.Interface().([]byte)
		Escape(p, bytes)
	case reflect.Struct:
		for i, n := 0, val.NumField(); i < n; i++ {
			if f := typ.Field(i); f.Name != "XMLName" && f.PkgPath == "" {
				name := f.Name
				switch tag := f.Tag.Get("xml"); tag {
				case "":
				case "chardata":
					if tk := f.Type.Kind(); tk == reflect.String {
						p.Write([]byte(val.Field(i).String()))
					} else if tk == reflect.Slice {
						if elem, ok := val.Field(i).Interface().([]byte); ok {
							Escape(p, elem)
						}
					}
					continue
				case "innerxml":
					iface := val.Field(i).Interface()
					switch raw := iface.(type) {
					case []byte:
						p.Write(raw)
						continue
					case string:
						p.WriteString(raw)
						continue
					}
				case "attr":
					continue
				default:
					name = tag
				}

				if err := p.marshalValue(val.Field(i), name); err != nil {
					return err
				}
			}
		}
	default:
		return &UnsupportedTypeError{typ}
	}

	p.WriteByte('<')
	p.WriteByte('/')
	p.WriteString(name)
	p.WriteByte('>')

	return nil
}

// A MarshalXMLError is returned when Marshal or MarshalIndent encounter a type
// that cannot be converted into XML.
type UnsupportedTypeError struct {
	Type reflect.Type
}

func (e *UnsupportedTypeError) String() string {
	return "xml: unsupported type: " + e.Type.String()
}
<|endoftext|>


<commit_before>package imp

import "github.com/qlova/ilang/src"
import "os"
import "text/scanner"
import "os/user"

func init() {
	ilang.RegisterToken([]string{"import"}, ScanImport)
}

//Messy.
func ScanImport(ic *ilang.Compiler) {
	pkg := ic.Scan(ilang.Name)
	ic.Scan('\n')

	var filename = ""

	retry:
	file, err := os.Open(pkg+".i")
	if err != nil {
		if file, err = os.Open(pkg+"/"+pkg+".i"); err != nil {

			//Search through parent folders?
			dir, _ := os.Getwd()
			if ic.FileDepth > 0 {
				ic.FileDepth--
				os.Chdir(ic.Dirs[len(ic.Dirs)-1])
				ic.Dirs = ic.Dirs[:len(ic.Dirs)-1]
				goto retry
			}

			//Search in ~/.ilang.
			if ic.FileDepth == 0 {
				usr, err := user.Current()
				if err == nil {
					os.Chdir(usr.HomeDir+"/.ilang/imports/")
					ic.Dirs = append(ic.Dirs, usr.HomeDir+"/.ilang/imports/")
					goto retry
				}
			}

			ic.RaiseError("Cannot import "+pkg+", does not exist!", dir)
		} else {
			 filename = pkg+"/"+pkg+".i"

			 dir, _ := os.Getwd()

			ic.Dirs = append(ic.Dirs, dir)

			os.Chdir("./"+pkg)
			ic.FileDepth++
		}
	} else {
		filename = pkg+".i"
	}
	ic.Scanners = append(ic.Scanners, ic.Scanner)

	ic.Scanner = &scanner.Scanner{}
	ic.Scanner.Init(file)
	ic.Scanner.Position.Filename = filename
	ic.Scanner.Whitespace= 1<<'\t' | 1<<'\r' | 1<<' '
}
<commit_msg>Don't hang when importing.<commit_after>package imp

import "github.com/qlova/ilang/src"
import "os"
import "text/scanner"
import "os/user"

func init() {
	ilang.RegisterToken([]string{"import"}, ScanImport)
}

//Messy.
func ScanImport(ic *ilang.Compiler) {
	pkg := ic.Scan(ilang.Name)
	ic.Scan('\n')

	var filename = ""

	retry:
	file, err := os.Open(pkg+".i")
	if err != nil {
		if file, err = os.Open(pkg+"/"+pkg+".i"); err != nil {

			//Search through parent folders?
			dir, _ := os.Getwd()
			if ic.FileDepth > 0 {
				ic.FileDepth--
				os.Chdir(ic.Dirs[len(ic.Dirs)-1])
				ic.Dirs = ic.Dirs[:len(ic.Dirs)-1]
				goto retry
			}

			//Search in ~/.ilang.
			if ic.FileDepth == 0 {
				ic.FileDepth--
				usr, err := user.Current()
				if err == nil {
					os.Chdir(usr.HomeDir+"/.ilang/imports/")
					ic.Dirs = append(ic.Dirs, usr.HomeDir+"/.ilang/imports/")
					goto retry
				}
			}

			ic.RaiseError("Cannot import "+pkg+", does not exist!", dir)
		} else {
			 filename = pkg+"/"+pkg+".i"

			 dir, _ := os.Getwd()

			ic.Dirs = append(ic.Dirs, dir)

			os.Chdir("./"+pkg)
			ic.FileDepth++
		}
	} else {
		filename = pkg+".i"
	}
	ic.Scanners = append(ic.Scanners, ic.Scanner)

	ic.Scanner = &scanner.Scanner{}
	ic.Scanner.Init(file)
	ic.Scanner.Position.Filename = filename
	ic.Scanner.Whitespace= 1<<'\t' | 1<<'\r' | 1<<' '
}
<|endoftext|>


<commit_before>// Copyright 2013 tsuru 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 api

import (
	"encoding/json"
	"github.com/globocom/config"
	"github.com/globocom/tsuru/auth"
	"net/http"
	"net/http"
)

// schema represents a json schema.
type schema struct {
	Title      string              `json:"title"`
	Properties map[string]property `json:"properties"`
	Required   []string            `json:"required"`
	Links      []link              `json:"links"`
}

// link represents a json schema link.
type link map[string]string

// property represents a json schema property.
type property map[string]interface{}

// appSchema returns a json schema for app.
func appSchema(w http.ResponseWriter, r *http.Request, t *auth.Token) error {
	host, err := config.GetString("host")
	if err != nil {
		return err
	}
	l := []link{
		{"href": host + "/apps/{name}/log", "method": "GET", "rel": "log"},
		{"href": host + "/apps/{name}/env", "method": "GET", "rel": "get_env"},
		{"href": host + "/apps/{name}/env", "method": "POST", "rel": "set_env"},
		{"href": host + "/apps/{name}/env", "method": "DELETE", "rel": "unset_env"},
		{"href": host + "/apps/{name}/restart", "method": "GET", "rel": "restart"},
		{"href": host + "/apps/{name}", "method": "POST", "rel": "update"},
		{"href": host + "/apps/{name}", "method": "DELETE", "rel": "delete"},
		{"href": host + "/apps/{name}/run", "method": "POST", "rel": "run"},
	}
	s := schema{
		Title:    "app schema",
		Links:    l,
		Required: []string{"framework", "name"},
		Properties: map[string]property{
			"name": {
				"type": "string",
			},
			"platform": {
				"type": "string",
			},
			"ip": {
				"type": "string",
			},
			"cname": {
				"type": "string",
			},
		},
	}
	return json.NewEncoder(w).Encode(s)
}
<commit_msg>fixed import.<commit_after>// Copyright 2013 tsuru 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 api

import (
	"encoding/json"
	"github.com/globocom/config"
	"github.com/globocom/tsuru/auth"
	"net/http"
)

// schema represents a json schema.
type schema struct {
	Title      string              `json:"title"`
	Properties map[string]property `json:"properties"`
	Required   []string            `json:"required"`
	Links      []link              `json:"links"`
}

// link represents a json schema link.
type link map[string]string

// property represents a json schema property.
type property map[string]interface{}

// appSchema returns a json schema for app.
func appSchema(w http.ResponseWriter, r *http.Request, t *auth.Token) error {
	host, err := config.GetString("host")
	if err != nil {
		return err
	}
	l := []link{
		{"href": host + "/apps/{name}/log", "method": "GET", "rel": "log"},
		{"href": host + "/apps/{name}/env", "method": "GET", "rel": "get_env"},
		{"href": host + "/apps/{name}/env", "method": "POST", "rel": "set_env"},
		{"href": host + "/apps/{name}/env", "method": "DELETE", "rel": "unset_env"},
		{"href": host + "/apps/{name}/restart", "method": "GET", "rel": "restart"},
		{"href": host + "/apps/{name}", "method": "POST", "rel": "update"},
		{"href": host + "/apps/{name}", "method": "DELETE", "rel": "delete"},
		{"href": host + "/apps/{name}/run", "method": "POST", "rel": "run"},
	}
	s := schema{
		Title:    "app schema",
		Links:    l,
		Required: []string{"framework", "name"},
		Properties: map[string]property{
			"name": {
				"type": "string",
			},
			"platform": {
				"type": "string",
			},
			"ip": {
				"type": "string",
			},
			"cname": {
				"type": "string",
			},
		},
	}
	return json.NewEncoder(w).Encode(s)
}
<|endoftext|>