<commit_before>// Copyright (c) 2014 Jason Goecke
// entities_test.go

package wit

import (
	"fmt"
	"math/rand"
	"net/http"
	"os"
	"testing"
	"time"
)

var entityName string

func findEntityValue(e *Entity, v string) (value EntityValue, err error) {
	for _, val := range e.Values {
		if val.Value == v {
			return val, nil
		}
	}
	return value, fmt.Errorf("not found")
}

func findStringInArray(a []string, v string) (s string, err error) {
	for _, val := range a {
		if val == v {
			return val, nil
		}
	}
	return s, fmt.Errorf("not found")
}

func TestWitEntitiesParsing(t *testing.T) {
	data := `
	[
	   "wit$amount_of_money",
	   "wit$contact",
	   "wit$datetime",
	   "wit$on_off",
	   "wit$phrase_to_translate",
	   "wit$temperature"
	]`

	entities, err := parseEntities([]byte(data))
	if err != nil {
		t.Error(err.Error())
	}

	for cnt, value := range *entities {
		switch cnt {
		case 0:
			if value != "wit$amount_of_money" {
				t.Error("Entities JSON did not parse properly.")
			}
		case 3:
			if value != "wit$on_off" {
				t.Error("Entities JSON did not parse properly.")
			}
		case 5:
			if value != "wit$temperature" {
				t.Error("Entities JSON did not parse properly.")
			}
		}
	}
}

func TestWitEntityParsing(t *testing.T) {
	data := `
	{
	  "builtin": true,
	  "doc": "Temperature in degrees Celcius or Fahrenheit",
	  "id": "wit$temperature"
	}`

	entity, err := parseEntity([]byte(data))
	if err != nil {
		t.Error(err.Error())
	}

	if entity.Builtin != true ||
		entity.Doc != "Temperature in degrees Celcius or Fahrenheit" ||
		entity.Id != "wit$temperature" {
		t.Error("Message JSON did not parse properly.")
	}
}

func TestWitEntities(t *testing.T) {
	client := NewClient(os.Getenv("WIT_ACCESS_TOKEN"))
	entities, err := client.Entities()
	if err != nil {
		t.Error("Did not fetch entities properly")
	}

	ageOfPerson := false
	for _, value := range *entities {
		if value == "wit$age_of_person" {
			ageOfPerson = true
		}
	}
	if ageOfPerson != true {
		t.Error("Entities returned not expected")
	}
}

func TestWitEntity(t *testing.T) {
	client := NewClient(os.Getenv("WIT_ACCESS_TOKEN"))
	entity, err := client.Entity("wit$age_of_person")
	if err != nil {
		t.Error(err)
	}
	if entity.Name != "age_of_person" ||
		entity.Builtin != true {
		t.Error("Did not parse entity properly")
	}

	// Now test for when the entity is not present
	_, err = client.Entity("age_of_person")
	if err.Error() != http.StatusText(404) {
		t.Error("Should have returned a not found error")
	}

}

func TestCreateEntity(t *testing.T) {
	// Create random string for testing
	rand.Seed(time.Now().UTC().UnixNano())
	alpha := "abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789"
	buf := make([]byte, 10)
	for i := 0; i < 10; i++ {
		buf[i] = alpha[rand.Intn(len(alpha))]
	}
	entityName = "favorite_city" + string(buf)

	data := `
	{
	  "doc": "A city that I like",
	  "id": "favorite_city",
	  "values": [
	    {
	      "value": "Paris",
	      "expressions": ["Paris", "City of Light", "Capital of France"]
	    }
	  ]
	}`

	client := NewClient(os.Getenv("WIT_ACCESS_TOKEN"))
	entity, err := parseEntity([]byte(data))
	if err != nil {
		t.Error("Did not parse entity properly")
	}
	entity.Id = entityName
	entity, err = client.CreateEntity(entity)
	if entity.Doc != "A city that I like" {
		t.Error("Entity was not created properly, doc not set")
	}
	if entity.Values[0].Value != "Paris" {
		t.Error("Entity was not created properly, values not set")
	}
	_, err = client.CreateEntity(entity)
	if err.Error() != http.StatusText(409) {
		t.Error("Expected a 409 since the entity already exists")
	}
}

func TestUpdateEntity(t *testing.T) {
	data := `
	{
	  "id": "favorite_city",
	  "doc": "These are cities worth going to",
	  "values": [
	    {
	      "value": "Paris",
	      "expressions": ["Paris", "City of Light", "Capital of France"]
	    },
	    {
	      "value": "Seoul",
	      "expressions": ["Seoul", "서울", "Kimchi paradise"]
	    }
	  ]
	}`

	client := NewClient(os.Getenv("WIT_ACCESS_TOKEN"))
	entity, err := parseEntity([]byte(data))
	entity.Id = entityName
	_, err = client.UpdateEntity(entity)
	if err != nil {
		t.Error("Did not update entity properly")
	}
}

func TestCreateEntityValue(t *testing.T) {
	client := NewClient(os.Getenv("WIT_ACCESS_TOKEN"))
	entityValue := &EntityValue{}
	entityValue.Value = "Barcelona"
	entityValue.Expressions = []string{"Med", "Sagrada Familia", "Gaudi"}
	entity, err := client.CreateEntityValue(entityName, entityValue)
	if err != nil {
		t.Error(err)
	}
	barcelona, err := findEntityValue(entity, "Barcelona")
	if err != nil ||
		barcelona.Value != "Barcelona" {
		t.Error("Did not add Barcelona to entity's value properly")
	}
	_, err = findStringInArray(barcelona.Expressions, "Sagrada Familia")
	if err != nil {
		t.Error("Did not add Sagrada Familia to entity's value expression properly")
	}
}

func TestCreateEntityValueExp(t *testing.T) {
	client := NewClient(os.Getenv("WIT_ACCESS_TOKEN"))
	entity, err := client.CreateEntityValueExp(entityName, "Barcelona", "Paella")
	if err != nil {
		t.Error(err)
	}
	barcelona, err := findEntityValue(entity, "Barcelona")
	if err != nil || barcelona.Value != "Barcelona" {
		t.Error("Did not add Barcelona to entity's value properly")
	}
	_, err = findStringInArray(barcelona.Expressions, "Paella")
	if err != nil {
		t.Error("Did not add Sagrada Familia to entity's value expression properly")
	}
}

func TestDeleteEntityValueExp(t *testing.T) {
	client := NewClient(os.Getenv("WIT_ACCESS_TOKEN"))
	_, err := client.DeleteEntityValueExp(entityName, "Paris", "City of Light")
	if err != nil {
		t.Error(err)
	}
}

func TestDeleteEntityValue(t *testing.T) {
	client := NewClient(os.Getenv("WIT_ACCESS_TOKEN"))
	_, err := client.DeleteEntityValue(entityName, "Paris")
	if err != nil {
		t.Error("Did not delete entity value properly")
	}
}

func TestDeleteEntity(t *testing.T) {
	client := NewClient(os.Getenv("WIT_ACCESS_TOKEN"))
	err := client.DeleteEntity("favorite_city")
	if err.Error() != http.StatusText(404) {
		t.Error("Delete should have returned 'Entity not found'")
	}
	err = client.DeleteEntity(entityName)
	if err != nil {
		t.Error(err)
	}
}
<commit_msg>Change error into bool<commit_after>// Copyright (c) 2014 Jason Goecke
// entities_test.go

package wit

import (
	"math/rand"
	"net/http"
	"os"
	"testing"
	"time"
)

var entityName string

func findEntityValue(e *Entity, v string) (value EntityValue, b bool) {
	for _, val := range e.Values {
		if val.Value == v {
			return val, true
		}
	}
	return value, false
}

func findStringInArray(a []string, v string) (s string, b bool) {
	for _, val := range a {
		if val == v {
			return val, true
		}
	}
	return s, false
}

func TestWitEntitiesParsing(t *testing.T) {
	data := `
	[
	   "wit$amount_of_money",
	   "wit$contact",
	   "wit$datetime",
	   "wit$on_off",
	   "wit$phrase_to_translate",
	   "wit$temperature"
	]`

	entities, err := parseEntities([]byte(data))
	if err != nil {
		t.Error(err.Error())
	}

	for cnt, value := range *entities {
		switch cnt {
		case 0:
			if value != "wit$amount_of_money" {
				t.Error("Entities JSON did not parse properly.")
			}
		case 3:
			if value != "wit$on_off" {
				t.Error("Entities JSON did not parse properly.")
			}
		case 5:
			if value != "wit$temperature" {
				t.Error("Entities JSON did not parse properly.")
			}
		}
	}
}

func TestWitEntityParsing(t *testing.T) {
	data := `
	{
	  "builtin": true,
	  "doc": "Temperature in degrees Celcius or Fahrenheit",
	  "id": "wit$temperature"
	}`

	entity, err := parseEntity([]byte(data))
	if err != nil {
		t.Error(err.Error())
	}

	if entity.Builtin != true ||
		entity.Doc != "Temperature in degrees Celcius or Fahrenheit" ||
		entity.Id != "wit$temperature" {
		t.Error("Message JSON did not parse properly.")
	}
}

func TestWitEntities(t *testing.T) {
	client := NewClient(os.Getenv("WIT_ACCESS_TOKEN"))
	entities, err := client.Entities()
	if err != nil {
		t.Error("Did not fetch entities properly")
	}

	ageOfPerson := false
	for _, value := range *entities {
		if value == "wit$age_of_person" {
			ageOfPerson = true
		}
	}
	if ageOfPerson != true {
		t.Error("Entities returned not expected")
	}
}

func TestWitEntity(t *testing.T) {
	client := NewClient(os.Getenv("WIT_ACCESS_TOKEN"))
	entity, err := client.Entity("wit$age_of_person")
	if err != nil {
		t.Error(err)
	}
	if entity.Name != "age_of_person" ||
		entity.Builtin != true {
		t.Error("Did not parse entity properly")
	}

	// Now test for when the entity is not present
	_, err = client.Entity("age_of_person")
	if err.Error() != http.StatusText(404) {
		t.Error("Should have returned a not found error")
	}

}

func TestCreateEntity(t *testing.T) {
	// Create random string for testing
	rand.Seed(time.Now().UTC().UnixNano())
	alpha := "abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789"
	buf := make([]byte, 10)
	for i := 0; i < 10; i++ {
		buf[i] = alpha[rand.Intn(len(alpha))]
	}
	entityName = "favorite_city" + string(buf)

	data := `
	{
	  "doc": "A city that I like",
	  "id": "favorite_city",
	  "values": [
	    {
	      "value": "Paris",
	      "expressions": ["Paris", "City of Light", "Capital of France"]
	    }
	  ]
	}`

	client := NewClient(os.Getenv("WIT_ACCESS_TOKEN"))
	entity, err := parseEntity([]byte(data))
	if err != nil {
		t.Error("Did not parse entity properly")
	}
	entity.Id = entityName
	entity, err = client.CreateEntity(entity)
	if entity.Doc != "A city that I like" {
		t.Error("Entity was not created properly, doc not set")
	}
	if entity.Values[0].Value != "Paris" {
		t.Error("Entity was not created properly, values not set")
	}
	_, err = client.CreateEntity(entity)
	if err.Error() != http.StatusText(409) {
		t.Error("Expected a 409 since the entity already exists")
	}
}

func TestUpdateEntity(t *testing.T) {
	data := `
	{
	  "id": "favorite_city",
	  "doc": "These are cities worth going to",
	  "values": [
	    {
	      "value": "Paris",
	      "expressions": ["Paris", "City of Light", "Capital of France"]
	    },
	    {
	      "value": "Seoul",
	      "expressions": ["Seoul", "서울", "Kimchi paradise"]
	    }
	  ]
	}`

	client := NewClient(os.Getenv("WIT_ACCESS_TOKEN"))
	entity, err := parseEntity([]byte(data))
	entity.Id = entityName
	_, err = client.UpdateEntity(entity)
	if err != nil {
		t.Error("Did not update entity properly")
	}
}

func TestCreateEntityValue(t *testing.T) {
	client := NewClient(os.Getenv("WIT_ACCESS_TOKEN"))
	entityValue := &EntityValue{}
	entityValue.Value = "Barcelona"
	entityValue.Expressions = []string{"Med", "Sagrada Familia", "Gaudi"}
	entity, err := client.CreateEntityValue(entityName, entityValue)
	if err != nil {
		t.Error(err)
	}
	barcelona, found := findEntityValue(entity, "Barcelona")
	if !found || barcelona.Value != "Barcelona" {
		t.Error("Did not add Barcelona to entity's value properly")
	}
	_, found = findStringInArray(barcelona.Expressions, "Sagrada Familia")
	if !found {
		t.Error("Did not add Sagrada Familia to entity's value expression properly")
	}
}

func TestCreateEntityValueExp(t *testing.T) {
	client := NewClient(os.Getenv("WIT_ACCESS_TOKEN"))
	entity, err := client.CreateEntityValueExp(entityName, "Barcelona", "Paella")
	if err != nil {
		t.Error(err)
	}
	barcelona, found := findEntityValue(entity, "Barcelona")
	if !found || barcelona.Value != "Barcelona" {
		t.Error("Did not add Barcelona to entity's value properly")
	}
	_, found = findStringInArray(barcelona.Expressions, "Paella")
	if !found {
		t.Error("Did not add Sagrada Familia to entity's value expression properly")
	}
}

func TestDeleteEntityValueExp(t *testing.T) {
	client := NewClient(os.Getenv("WIT_ACCESS_TOKEN"))
	_, err := client.DeleteEntityValueExp(entityName, "Paris", "City of Light")
	if err != nil {
		t.Error(err)
	}
}

func TestDeleteEntityValue(t *testing.T) {
	client := NewClient(os.Getenv("WIT_ACCESS_TOKEN"))
	_, err := client.DeleteEntityValue(entityName, "Paris")
	if err != nil {
		t.Error("Did not delete entity value properly")
	}
}

func TestDeleteEntity(t *testing.T) {
	client := NewClient(os.Getenv("WIT_ACCESS_TOKEN"))
	err := client.DeleteEntity("favorite_city")
	if err.Error() != http.StatusText(404) {
		t.Error("Delete should have returned 'Entity not found'")
	}
	err = client.DeleteEntity(entityName)
	if err != nil {
		t.Error(err)
	}
}
<|endoftext|>


<commit_before>package core

import (
	"bufio"
	"fmt"
	"os"
	"os/exec"
	"strings"

	"github.com/fatih/color"
)

func Valid(filename string) bool {
	if Exists(filename) {
		if IsSymbolic(filename) {
			return false
		}
		return true
	}
	return false
}

func IsSymbolic(filename string) bool {
	fi, err := os.Lstat(filename)
	if err != nil {
		return true
	}
	if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
		print(filename + " is a symbolic link.")
		return true
	} else {
		return false
	}
}

func Exists(filename string) bool {
	if _, err := os.Stat(filename); os.IsNotExist(err) {
		return false
	}
	return true
}

func CreateDir(directory string) bool {
	err := os.Mkdir(directory, 0755)
	if err != nil {
		return false
	}

	return true
}

func Ask(message string, value bool) bool {
	g := color.New(color.FgGreen).SprintFunc()
	r := color.New(color.FgRed).SprintFunc()

	if value {
		fmt.Print(message + g(" [Y/n]") + ": ")
	} else {
		fmt.Print(message + r(" [y/N]") + ": ")
	}

	var response string
	fmt.Scanln(&response)

	yesResponses := []string{"y", "Y", "yes", "Yes", "YES"}
	noResponses := []string{"n", "N", "no", "No", "NO"}
	if contains(yesResponses, response) {
		return true
	} else if contains(noResponses, response) {
		return false
	} else {
		return value
	}
}

func IsInstalled(command string) bool {
	_, err := exec.LookPath(command)
	if err != nil {
		return false
	}
	return true
}

func contains(s []string, e string) bool {
	for _, a := range s {
		if a == e {
			return true
		}
	}
	return false
}

type PrintFunc func(...interface{})

func Printer(plugin string) PrintFunc {
	g := color.New(color.FgGreen).SprintfFunc()
	p := g("[%s] ", plugin)

	print := func(a ...interface{}) {
		fmt.Print(p)
		fmt.Println(a...)
	}
	return print
}

type Output struct {
}

func (o Output) Write(p []byte) (int, error) {
	//reader, writer := io.Pipe()
	s := string(p)
	a := strings.Split(s, "\n")
	a = a[:len(a)-1]
	for _, v := range a {
		fmt.Println("Test", v)
	}

	f := bufio.NewWriter(os.Stderr)
	//n, err := writer.Write(p)

	//fmt.Print("test " + b.String())
	fmt.Fprint(f, "Test")
	n, err := f.Write(p)
	//f.Flush()
	return n, err
}
<commit_msg>Improved Printer and included Ask.<commit_after>package core

import (
	"fmt"
	"os"
	"os/exec"
	"strings"

	"github.com/fatih/color"
)

func Valid(filename string) bool {
	if Exists(filename) {
		if IsSymbolic(filename) {
			return false
		}
		return true
	}
	return false
}

func IsSymbolic(filename string) bool {
	fi, err := os.Lstat(filename)
	if err != nil {
		return true
	}
	if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
		out.Print(filename + " is a symbolic link.")
		return true
	} else {
		return false
	}
}

func Exists(filename string) bool {
	if _, err := os.Stat(filename); os.IsNotExist(err) {
		return false
	}
	return true
}

func CreateDir(directory string) bool {
	err := os.Mkdir(directory, 0755)
	if err != nil {
		return false
	}

	return true
}

func IsInstalled(command string) bool {
	_, err := exec.LookPath(command)
	if err != nil {
		return false
	}
	return true
}

func contains(s []string, e string) bool {
	for _, a := range s {
		if a == e {
			return true
		}
	}
	return false
}

type Printer struct {
	name    string
	errname string
}

func NewPrinter(name string) Printer {
	g := color.New(color.FgGreen).SprintfFunc()
	r := color.New(color.FgGreen).SprintfFunc()

	gn := g("[%s] ", name)
	rn := r("[%s] ", name)
	return Printer{gn, rn}
}

func (p Printer) Print(a ...interface{}) {
	fmt.Print(p.name)
	fmt.Println(a...)
}

func (p Printer) Printf(format string, a ...interface{}) {
	fmt.Print(p.name)
	fmt.Printf(format, a...)
}

func (p Printer) Error(a ...interface{}) {
	fmt.Print(p.errname)
	fmt.Println(a...)
}

func (p Printer) Write(b []byte) (int, error) {
	//reader, writer := io.Pipe()
	s := string(b)
	a := strings.Split(s, "\n")
	a = a[:len(a)-1]

	for _, v := range a {
		fmt.Println(p.name, v)
	}

	return 0, nil
}

func (p Printer) Ask(message string, value bool) bool {
	g := color.New(color.FgGreen).SprintFunc()
	r := color.New(color.FgRed).SprintFunc()

	if value {
		p.Print(message + g(" [Y/n]") + ": ")
	} else {
		p.Print(message + r(" [y/N]") + ": ")
	}

	var response string
	fmt.Scanln(&response)

	yesResponses := []string{"y", "Y", "yes", "Yes", "YES"}
	noResponses := []string{"n", "N", "no", "No", "NO"}

	if contains(yesResponses, response) {
		return true
	} else if contains(noResponses, response) {
		return false
	} else {
		return value
	}
}
<|endoftext|>


<commit_before>// Copyright 2012 Dorival de Moraes Pedroso. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package rnd

import "math"

type LogNormal struct {
	Mu  float64 // μ: location
	Sig float64 // σ: scale

	// auxiliary
	vari2 float64 // 2 * σ²: 2 times variance
	den   float64 // σ * sqrt(2 * π)
}

// derived compute derived/auxiliary quantities
func (o *LogNormal) derived() {
	o.vari2 = 2.0 * o.Sig * o.Sig
	o.den = o.Sig * math.Sqrt(2.0*math.Pi)
}

// InitNonlog initialise lognormal distribution with non-log parameters
//  m -- non-logarithmised mean: μ
//  s -- non-logarithmised standard deviation: σ
func (o *LogNormal) InitStd(m, s float64) {
	o.Sig = math.Sqrt(math.Log(1.0 + s*s/(m*m)))
	o.Mu = math.Log(m / o.Sig)
	o.derived()
}

// Init initialises lognormal distribution
func (o *LogNormal) Init(μ, σ float64) {
	o.Mu, o.Sig = μ, σ
	o.derived()
}

// Pdf computes the probability density function @ x
func (o LogNormal) Pdf(x float64) float64 {
	if x < 1e-16 {
		return 0
	}
	return math.Exp(-math.Pow(math.Log(x)-o.Mu, 2.0)/o.vari2) / o.den / x
}

// Cdf computes the cumulative probability function @ x
func (o LogNormal) Cdf(x float64) float64 {
	if x < 1e-16 {
		return 0
	}
	return math.Erfc((o.Mu-math.Log(x))/(o.Sig*math.Sqrt2)) / 2.0
}
<commit_msg>derived => CalcDerived in lognorm dist<commit_after>// Copyright 2012 Dorival de Moraes Pedroso. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package rnd

import "math"

type LogNormal struct {
	Mu  float64 // μ: location
	Sig float64 // σ: scale

	// auxiliary
	vari2 float64 // 2 * σ²: 2 times variance
	den   float64 // σ * sqrt(2 * π)
}

// CalcDerived compute derived/auxiliary quantities
func (o *LogNormal) CalcDerived() {
	o.vari2 = 2.0 * o.Sig * o.Sig
	o.den = o.Sig * math.Sqrt(2.0*math.Pi)
}

// InitNonlog initialise lognormal distribution with non-log parameters
//  m -- non-logarithmised mean: μ
//  s -- non-logarithmised standard deviation: σ
func (o *LogNormal) InitStd(m, s float64) {
	o.Sig = math.Sqrt(math.Log(1.0 + s*s/(m*m)))
	o.Mu = math.Log(m / o.Sig)
	o.CalcDerived()
}

// Init initialises lognormal distribution
func (o *LogNormal) Init(μ, σ float64) {
	o.Mu, o.Sig = μ, σ
	o.CalcDerived()
}

// Pdf computes the probability density function @ x
func (o LogNormal) Pdf(x float64) float64 {
	if x < 1e-16 {
		return 0
	}
	return math.Exp(-math.Pow(math.Log(x)-o.Mu, 2.0)/o.vari2) / o.den / x
}

// Cdf computes the cumulative probability function @ x
func (o LogNormal) Cdf(x float64) float64 {
	if x < 1e-16 {
		return 0
	}
	return math.Erfc((o.Mu-math.Log(x))/(o.Sig*math.Sqrt2)) / 2.0
}
<|endoftext|>


<commit_before>// +build linux

package linux

import (
	"testing"
)

func TestMemoryKey(t *testing.T) {
	g := &MemoryGenerator{}

	if g.Key() != "memory" {
		t.Error("key should be memory")
	}
}

func TestMemoryGenerator(t *testing.T) {
	g := &MemoryGenerator{}
	value, err := g.Generate()
	if err != nil {
		t.Errorf("should not raise error: %v", err)
	}

	memory, typeOk := value.(map[string]interface{})
	if !typeOk {
		t.Errorf("value should be map. %+v", value)
	}

	memItemKeys := []string{
		"total",
		"free",
		"buffers",
		"cached",
		"active",
		"inactive",
		"dirty",
		"writeback",
		"anon_pages",
		"mapped",
		"slab",
		"slab_reclaimable",
		"slab_unreclaim",
		"page_tables",
		"nfs_unstable",
		"bounce",
		"commit_limit",
		"committed_as",
		"vmalloc_total",
		"vmalloc_used",
		"vmalloc_chunk",
		"swap_cached",
		"swap_total",
		"swap_free",
	}

	for _, key := range memItemKeys {
		if _, ok := memory[key]; !ok {
			t.Errorf("memory spec should have %s", key)
		}
	}
}
<commit_msg>add more precise test for memory spec on linux<commit_after>// +build linux

package linux

import (
	"reflect"
	"strings"
	"testing"
)

func TestMemoryKey(t *testing.T) {
	g := &MemoryGenerator{}

	if g.Key() != "memory" {
		t.Error("key should be memory")
	}
}

func TestMemoryGenerator(t *testing.T) {
	g := &MemoryGenerator{}
	value, err := g.Generate()
	if err != nil {
		t.Errorf("should not raise error: %v", err)
	}

	memory, typeOk := value.(map[string]string)
	if !typeOk {
		t.Errorf("value should be map. %+v", value)
	}

	memItemKeys := []string{
		"total",
		"free",
		"buffers",
		"cached",
		"active",
		"inactive",
		"dirty",
		"writeback",
		"anon_pages",
		"mapped",
		"slab",
		"slab_reclaimable",
		"slab_unreclaim",
		"page_tables",
		"nfs_unstable",
		"bounce",
		"commit_limit",
		"committed_as",
		"vmalloc_total",
		"vmalloc_used",
		"vmalloc_chunk",
		"swap_cached",
		"swap_total",
		"swap_free",
	}

	for _, key := range memItemKeys {
		if _, ok := memory[key]; !ok {
			t.Errorf("memory spec should have %s", key)
		}
	}
}

func TestGenerateMemorySpec(t *testing.T) {
	got, err := generateMemorySpec(strings.NewReader(
		`MemTotal:       15434208 kB
MemFree:         3009856 kB
MemAvailable:   10008916 kB
Buffers:          443104 kB
Cached:          6305168 kB
SwapCached:            0 kB
Active:          7662608 kB
Inactive:        3375044 kB
Active(anon):    4474764 kB
Inactive(anon):   276180 kB
Active(file):    3187844 kB
Inactive(file):  3098864 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Dirty:               516 kB
Writeback:             0 kB
AnonPages:       4289480 kB
Mapped:           258168 kB
Shmem:            461560 kB
Slab:            1169796 kB
SReclaimable:     965756 kB
SUnreclaim:       204040 kB
KernelStack:       42688 kB
PageTables:        61024 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     7717104 kB
Committed_AS:   23796544 kB
VmallocTotal:   34359738367 kB
VmallocUsed:       42608 kB
VmallocChunk:   34359578580 kB
HardwareCorrupted:     0 kB
AnonHugePages:         0 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:       65536 kB
DirectMap2M:     3211264 kB
DirectMap1G:    12582912 kB
`))
	if err != nil {
		t.Errorf("should not raise error: %v", err)
	}
	expected := map[string]string{
		"total":            "15434208kB",
		"free":             "3009856kB",
		"buffers":          "443104kB",
		"cached":           "6305168kB",
		"active":           "7662608kB",
		"inactive":         "3375044kB",
		"dirty":            "516kB",
		"writeback":        "0kB",
		"anon_pages":       "4289480kB",
		"mapped":           "258168kB",
		"slab":             "1169796kB",
		"slab_reclaimable": "965756kB",
		"slab_unreclaim":   "204040kB",
		"page_tables":      "61024kB",
		"nfs_unstable":     "0kB",
		"bounce":           "0kB",
		"commit_limit":     "7717104kB",
		"committed_as":     "23796544kB",
		"vmalloc_total":    "34359738367kB",
		"vmalloc_used":     "42608kB",
		"vmalloc_chunk":    "34359578580kB",
		"swap_cached":      "0kB",
		"swap_total":       "0kB",
		"swap_free":        "0kB",
	}
	if !reflect.DeepEqual(got, expected) {
		t.Errorf("invalid memory stat: %+v (expected: %+v)", got, expected)
	}
}
<|endoftext|>


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

// +build appengine

package build

import (
	"net/http"
	"strings"

	"appengine"
)

func handleFunc(path string, h http.HandlerFunc) {
	for _, d := range dashboards {
		http.HandleFunc(d.Prefix+path, h)
	}
}

// Dashboard describes a unique build dashboard.
type Dashboard struct {
	Name     string     // This dashboard's name and namespace
	Prefix   string     // The path prefix (no trailing /)
	Packages []*Package // The project's packages to build
}

// dashboardForRequest returns the appropriate dashboard for a given URL path.
func dashboardForRequest(r *http.Request) *Dashboard {
	if strings.HasPrefix(r.URL.Path, gccgoDash.Prefix) {
		return gccgoDash
	}
	if strings.HasPrefix(r.URL.Path, gitDash.Prefix) {
		return gitDash
	}
	return goDash
}

// Context returns a namespaced context for this dashboard, or panics if it
// fails to create a new context.
func (d *Dashboard) Context(c appengine.Context) appengine.Context {
	// No namespace needed for the original Go dashboard.
	if d.Name == "Go" {
		return c
	}
	n, err := appengine.Namespace(c, d.Name)
	if err != nil {
		panic(err)
	}
	return n
}

// the currently known dashboards.
var dashboards = []*Dashboard{goDash, gitDash, gccgoDash}

// goDash is the dashboard for the main go repository.
var goDash = &Dashboard{
	Name:     "Go",
	Prefix:   "",
	Packages: goPackages,
}

// goPackages is a list of all of the packages built by the main go repository.
var goPackages = []*Package{
	{
		Kind: "go",
		Name: "Go",
	},
	{
		Kind: "subrepo",
		Name: "go.blog",
		Path: "code.google.com/p/go.blog",
	},
	{
		Kind: "subrepo",
		Name: "go.codereview",
		Path: "code.google.com/p/go.codereview",
	},
	{
		Kind: "subrepo",
		Name: "go.crypto",
		Path: "code.google.com/p/go.crypto",
	},
	{
		Kind: "subrepo",
		Name: "go.exp",
		Path: "code.google.com/p/go.exp",
	},
	{
		Kind: "subrepo",
		Name: "go.image",
		Path: "code.google.com/p/go.image",
	},
	{
		Kind: "subrepo",
		Name: "go.net",
		Path: "code.google.com/p/go.net",
	},
	{
		Kind: "subrepo",
		Name: "go.sys",
		Path: "code.google.com/p/go.sys",
	},
	{
		Kind: "subrepo",
		Name: "go.talks",
		Path: "code.google.com/p/go.talks",
	},
	{
		Kind: "subrepo",
		Name: "go.tools",
		Path: "code.google.com/p/go.tools",
	},
}

// gitDash is the dashboard for the main go repository on git.
var gitDash = &Dashboard{
	Name:     "Git",
	Prefix:   "/git",
	Packages: gitPackages,
}

// gitPackages is a list of all of the packages built by the main go repository
// on git.
var gitPackages = []*Package{
	{
		Kind: "go",
		Name: "Go",
	},
	{
		Kind: "subrepo",
		Name: "blog",
		Path: "golang.org/x/blog",
	},
	{
		Kind: "subrepo",
		Name: "codereview",
		Path: "golang.org/x/codereview",
	},
	{
		Kind: "subrepo",
		Name: "crypto",
		Path: "golang.org/x/crypto",
	},
	{
		Kind: "subrepo",
		Name: "exp",
		Path: "golang.org/x/exp",
	},
	{
		Kind: "subrepo",
		Name: "image",
		Path: "golang.org/x/image",
	},
	{
		Kind: "subrepo",
		Name: "net",
		Path: "golang.org/x/net",
	},
	{
		Kind: "subrepo",
		Name: "sys",
		Path: "golang.org/x/sys",
	},
	{
		Kind: "subrepo",
		Name: "talks",
		Path: "golang.org/x/talks",
	},
	{
		Kind: "subrepo",
		Name: "tools",
		Path: "golang.org/x/tools",
	},
}

// gccgoDash is the dashboard for gccgo.
var gccgoDash = &Dashboard{
	Name:   "Gccgo",
	Prefix: "/gccgo",
	Packages: []*Package{
		{
			Kind: "gccgo",
			Name: "Gccgo",
		},
	},
}
<commit_msg>x/dashboard/app: update sub-repo list (+mobile, +text, -codereview)<commit_after>// Copyright 2013 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.

// +build appengine

package build

import (
	"net/http"
	"strings"

	"appengine"
)

func handleFunc(path string, h http.HandlerFunc) {
	for _, d := range dashboards {
		http.HandleFunc(d.Prefix+path, h)
	}
}

// Dashboard describes a unique build dashboard.
type Dashboard struct {
	Name     string     // This dashboard's name and namespace
	Prefix   string     // The path prefix (no trailing /)
	Packages []*Package // The project's packages to build
}

// dashboardForRequest returns the appropriate dashboard for a given URL path.
func dashboardForRequest(r *http.Request) *Dashboard {
	if strings.HasPrefix(r.URL.Path, gccgoDash.Prefix) {
		return gccgoDash
	}
	if strings.HasPrefix(r.URL.Path, gitDash.Prefix) {
		return gitDash
	}
	return goDash
}

// Context returns a namespaced context for this dashboard, or panics if it
// fails to create a new context.
func (d *Dashboard) Context(c appengine.Context) appengine.Context {
	// No namespace needed for the original Go dashboard.
	if d.Name == "Go" {
		return c
	}
	n, err := appengine.Namespace(c, d.Name)
	if err != nil {
		panic(err)
	}
	return n
}

// the currently known dashboards.
var dashboards = []*Dashboard{goDash, gitDash, gccgoDash}

// goDash is the dashboard for the main go repository.
var goDash = &Dashboard{
	Name:     "Go",
	Prefix:   "",
	Packages: goPackages,
}

// goPackages is a list of all of the packages built by the main go repository.
var goPackages = []*Package{
	{
		Kind: "go",
		Name: "Go",
	},
	{
		Kind: "subrepo",
		Name: "go.blog",
		Path: "code.google.com/p/go.blog",
	},
	{
		Kind: "subrepo",
		Name: "go.codereview",
		Path: "code.google.com/p/go.codereview",
	},
	{
		Kind: "subrepo",
		Name: "go.crypto",
		Path: "code.google.com/p/go.crypto",
	},
	{
		Kind: "subrepo",
		Name: "go.exp",
		Path: "code.google.com/p/go.exp",
	},
	{
		Kind: "subrepo",
		Name: "go.image",
		Path: "code.google.com/p/go.image",
	},
	{
		Kind: "subrepo",
		Name: "go.net",
		Path: "code.google.com/p/go.net",
	},
	{
		Kind: "subrepo",
		Name: "go.sys",
		Path: "code.google.com/p/go.sys",
	},
	{
		Kind: "subrepo",
		Name: "go.talks",
		Path: "code.google.com/p/go.talks",
	},
	{
		Kind: "subrepo",
		Name: "go.tools",
		Path: "code.google.com/p/go.tools",
	},
}

// gitDash is the dashboard for the main go repository on git.
var gitDash = &Dashboard{
	Name:     "Git",
	Prefix:   "/git",
	Packages: gitPackages,
}

// gitPackages is a list of all of the packages built by the main go repository
// on git.
var gitPackages = []*Package{
	{
		Kind: "go",
		Name: "Go",
	},
	{
		Kind: "subrepo",
		Name: "blog",
		Path: "golang.org/x/blog",
	},
	{
		Kind: "subrepo",
		Name: "crypto",
		Path: "golang.org/x/crypto",
	},
	{
		Kind: "subrepo",
		Name: "exp",
		Path: "golang.org/x/exp",
	},
	{
		Kind: "subrepo",
		Name: "image",
		Path: "golang.org/x/image",
	},
	{
		Kind: "subrepo",
		Name: "mobile",
		Path: "golang.org/x/mobile",
	},
	{
		Kind: "subrepo",
		Name: "net",
		Path: "golang.org/x/net",
	},
	{
		Kind: "subrepo",
		Name: "sys",
		Path: "golang.org/x/sys",
	},
	{
		Kind: "subrepo",
		Name: "talks",
		Path: "golang.org/x/talks",
	},
	{
		Kind: "subrepo",
		Name: "text",
		Path: "golang.org/x/text",
	},
	{
		Kind: "subrepo",
		Name: "tools",
		Path: "golang.org/x/tools",
	},
}

// gccgoDash is the dashboard for gccgo.
var gccgoDash = &Dashboard{
	Name:   "Gccgo",
	Prefix: "/gccgo",
	Packages: []*Package{
		{
			Kind: "gccgo",
			Name: "Gccgo",
		},
	},
}
<|endoftext|>


<commit_before>// Copyright 2014 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.

// +build appengine

package build

import (
	"fmt"
	"sort"
	"strconv"
	"strings"

	"appengine"
	"appengine/datastore"
)

var knownTags = map[string]string{
	"go1":   "0051c7442fed9c888de6617fa9239a913904d96e",
	"go1.1": "d29da2ced72ba2cf48ed6a8f1ec4abc01e4c5bf1",
	"go1.2": "b1edf8faa5d6cbc50c6515785df9df9c19296564",
}

var lastRelease = "go1.2"

func splitBench(benchProcs string) (string, int) {
	ss := strings.Split(benchProcs, "-")
	procs, _ := strconv.Atoi(ss[1])
	return ss[0], procs
}

func dashPerfCommits(c appengine.Context, page int) ([]*Commit, error) {
	q := datastore.NewQuery("Commit").
		Ancestor((&Package{}).Key(c)).
		Order("-Num").
		Filter("NeedsBenchmarking =", true).
		Limit(commitsPerPage).
		Offset(page * commitsPerPage)
	var commits []*Commit
	_, err := q.GetAll(c, &commits)
	if err == nil && len(commits) == 0 {
		err = fmt.Errorf("no commits")
	}
	return commits, err
}

func perfChangeStyle(pc *PerfConfig, v float64, builder, benchmark, metric string) string {
	noise := pc.NoiseLevel(builder, benchmark, metric)
	if isNoise(v, noise) {
		return "noise"
	}
	if v > 0 {
		return "bad"
	}
	return "good"
}

func isNoise(diff, noise float64) bool {
	rnoise := -100 * noise / (noise + 100)
	return diff < noise && diff > rnoise
}

func perfDiff(old, new uint64) float64 {
	return 100*float64(new)/float64(old) - 100
}

func isPerfFailed(res *PerfResult, builder string) bool {
	data := res.ParseData()[builder]
	return data != nil && data["meta-done"] != nil && !data["meta-done"].OK
}

// PerfResultCache caches a set of PerfResults so that it's easy to access them
// without lots of duplicate accesses to datastore.
// It allows to iterate over newer or older results for some base commit.
type PerfResultCache struct {
	c       appengine.Context
	newer   bool
	iter    *datastore.Iterator
	results map[int]*PerfResult
}

func MakePerfResultCache(c appengine.Context, com *Commit, newer bool) *PerfResultCache {
	p := &Package{}
	q := datastore.NewQuery("PerfResult").Ancestor(p.Key(c)).Limit(100)
	if newer {
		q = q.Filter("CommitNum >=", com.Num).Order("CommitNum")
	} else {
		q = q.Filter("CommitNum <=", com.Num).Order("-CommitNum")
	}
	rc := &PerfResultCache{c: c, newer: newer, iter: q.Run(c), results: make(map[int]*PerfResult)}
	return rc
}

func (rc *PerfResultCache) Get(commitNum int) *PerfResult {
	rc.Next(commitNum) // fetch the commit, if necessary
	return rc.results[commitNum]
}

// Next returns the next PerfResult for the commit commitNum.
// It does not care whether the result has any data, failed or whatever.
func (rc *PerfResultCache) Next(commitNum int) (*PerfResult, error) {
	// See if we have next result in the cache.
	next := -1
	for ci := range rc.results {
		if rc.newer {
			if ci > commitNum && (next == -1 || ci < next) {
				next = ci
			}
		} else {
			if ci < commitNum && (next == -1 || ci > next) {
				next = ci
			}
		}
	}
	//rc.c.Errorf("PerfResultCache.Next: num=%v next=%v", commitNum, next)
	if next != -1 {
		return rc.results[next], nil
	}
	// Fetch next result from datastore.
	res := new(PerfResult)
	_, err := rc.iter.Next(res)
	//rc.c.Errorf("PerfResultCache.Next: fetched %v %+v", err, res)
	if err == datastore.Done {
		return nil, nil
	}
	if err != nil {
		return nil, fmt.Errorf("fetching perf results: %v", err)
	}
	if (rc.newer && res.CommitNum < commitNum) || (!rc.newer && res.CommitNum > commitNum) {
		rc.c.Errorf("PerfResultCache.Next: bad commit num")
	}
	rc.results[res.CommitNum] = res
	return res, nil
}

// NextForComparison returns PerfResult which we need to use for performance comprison.
// It skips failed results, but does not skip results with no data.
func (rc *PerfResultCache) NextForComparison(commitNum int, builder string) (*PerfResult, error) {
	for {
		res, err := rc.Next(commitNum)
		if err != nil {
			return nil, err
		}
		if res == nil {
			return nil, nil
		}
		if res.CommitNum == commitNum {
			continue
		}
		parsed := res.ParseData()
		if builder != "" {
			// Comparing for a particular builder.
			// This is used in perf_changes and in email notifications.
			b := parsed[builder]
			if b == nil || b["meta-done"] == nil {
				// No results yet, must not do the comparison.
				return nil, nil
			}
			if b["meta-done"].OK {
				// Have complete results, compare.
				return res, nil
			}
		} else {
			// Comparing for all builders, find a result with at least
			// one successful meta-done.
			// This is used in perf_detail.
			for _, benchs := range parsed {
				if data := benchs["meta-done"]; data != nil && data.OK {
					return res, nil
				}
			}
		}
		// Failed, try next result.
		commitNum = res.CommitNum
	}
}

type PerfChange struct {
	builder string
	bench   string
	metric  string
	old     uint64
	new     uint64
	diff    float64
}

func significantPerfChanges(pc *PerfConfig, builder string, prevRes, res *PerfResult) (changes []*PerfChange) {
	// First, collect all significant changes.
	for builder1, benchmarks1 := range res.ParseData() {
		if builder != "" && builder != builder1 {
			// This is not the builder you're looking for, Luke.
			continue
		}
		benchmarks0 := prevRes.ParseData()[builder1]
		if benchmarks0 == nil {
			continue
		}
		for benchmark, data1 := range benchmarks1 {
			data0 := benchmarks0[benchmark]
			if data0 == nil {
				continue
			}
			for metric, val := range data1.Metrics {
				val0 := data0.Metrics[metric]
				if val0 == 0 {
					continue
				}
				diff := perfDiff(val0, val)
				noise := pc.NoiseLevel(builder, benchmark, metric)
				if isNoise(diff, noise) {
					continue
				}
				ch := &PerfChange{builder: builder, bench: benchmark, metric: metric, old: val0, new: val, diff: diff}
				changes = append(changes, ch)
			}
		}
	}
	// Then, strip non-repeatable changes (flakes).
	// The hypothesis is that a real change must show up with at least
	// 2 different values of GOMAXPROCS.
	cnt := make(map[string]int)
	for _, ch := range changes {
		b, _ := splitBench(ch.bench)
		name := b + "|" + ch.metric
		inc := 1
		if ch.diff < 0 {
			inc = -1
		}
		cnt[name] = cnt[name] + inc
	}
	for i := 0; i < len(changes); i++ {
		ch := changes[i]
		b, _ := splitBench(ch.bench)
		name := b + "|" + ch.metric
		if n := cnt[name]; n <= -2 || n >= 2 {
			continue
		}
		last := len(changes) - 1
		changes[i] = changes[last]
		changes = changes[:last]
		i--
	}
	return changes
}

// orderPrefTodo reorders commit nums for benchmarking todo.
// The resulting order is somewhat tricky. We want 2 things:
// 1. benchmark sequentially backwards (this provides information about most
// recent changes, and allows to estimate noise levels)
// 2. benchmark old commits in "scatter" order (this allows to quickly gather
// brief information about thousands of old commits)
// So this function interleaves the two orders.
func orderPrefTodo(nums []int) []int {
	sort.Ints(nums)
	n := len(nums)
	pow2 := uint32(0) // next power-of-two that is >= n
	npow2 := 0
	for npow2 <= n {
		pow2++
		npow2 = 1 << pow2
	}
	res := make([]int, n)
	resPos := n - 1            // result array is filled backwards
	present := make([]bool, n) // denotes values that already present in result array
	for i0, i1 := n-1, 0; i0 >= 0 || i1 < npow2; {
		// i0 represents "benchmark sequentially backwards" sequence
		// find the next commit that is not yet present and add it
		for cnt := 0; cnt < 2; cnt++ {
			for ; i0 >= 0; i0-- {
				if !present[i0] {
					present[i0] = true
					res[resPos] = nums[i0]
					resPos--
					i0--
					break
				}
			}
		}
		// i1 represents "scatter order" sequence
		// find the next commit that is not yet present and add it
		for ; i1 < npow2; i1++ {
			// do the "recursive split-ordering" trick
			idx := 0 // bitwise reverse of i1
			for j := uint32(0); j <= pow2; j++ {
				if (i1 & (1 << j)) != 0 {
					idx = idx | (1 << (pow2 - j - 1))
				}
			}
			if idx < n && !present[idx] {
				present[idx] = true
				res[resPos] = nums[idx]
				resPos--
				i1++
				break
			}
		}
	}
	// The above can't possibly be correct. Do dump check.
	res2 := make([]int, n)
	copy(res2, res)
	sort.Ints(res2)
	for i := range res2 {
		if res2[i] != nums[i] {
			panic(fmt.Sprintf("diff at %v: expect %v, want %v\nwas: %v\n become: %v",
				i, nums[i], res2[i], nums, res2))
		}
	}
	return res
}
<commit_msg>dashboard/app: tag 1.3 release<commit_after>// Copyright 2014 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.

// +build appengine

package build

import (
	"fmt"
	"sort"
	"strconv"
	"strings"

	"appengine"
	"appengine/datastore"
)

var knownTags = map[string]string{
	"go1":   "0051c7442fed9c888de6617fa9239a913904d96e",
	"go1.1": "d29da2ced72ba2cf48ed6a8f1ec4abc01e4c5bf1",
	"go1.2": "b1edf8faa5d6cbc50c6515785df9df9c19296564",
	"go1.3": "f153208c0a0e306bfca14f71ef11f09859ccabc8",
}

var lastRelease = "go1.3"

func splitBench(benchProcs string) (string, int) {
	ss := strings.Split(benchProcs, "-")
	procs, _ := strconv.Atoi(ss[1])
	return ss[0], procs
}

func dashPerfCommits(c appengine.Context, page int) ([]*Commit, error) {
	q := datastore.NewQuery("Commit").
		Ancestor((&Package{}).Key(c)).
		Order("-Num").
		Filter("NeedsBenchmarking =", true).
		Limit(commitsPerPage).
		Offset(page * commitsPerPage)
	var commits []*Commit
	_, err := q.GetAll(c, &commits)
	if err == nil && len(commits) == 0 {
		err = fmt.Errorf("no commits")
	}
	return commits, err
}

func perfChangeStyle(pc *PerfConfig, v float64, builder, benchmark, metric string) string {
	noise := pc.NoiseLevel(builder, benchmark, metric)
	if isNoise(v, noise) {
		return "noise"
	}
	if v > 0 {
		return "bad"
	}
	return "good"
}

func isNoise(diff, noise float64) bool {
	rnoise := -100 * noise / (noise + 100)
	return diff < noise && diff > rnoise
}

func perfDiff(old, new uint64) float64 {
	return 100*float64(new)/float64(old) - 100
}

func isPerfFailed(res *PerfResult, builder string) bool {
	data := res.ParseData()[builder]
	return data != nil && data["meta-done"] != nil && !data["meta-done"].OK
}

// PerfResultCache caches a set of PerfResults so that it's easy to access them
// without lots of duplicate accesses to datastore.
// It allows to iterate over newer or older results for some base commit.
type PerfResultCache struct {
	c       appengine.Context
	newer   bool
	iter    *datastore.Iterator
	results map[int]*PerfResult
}

func MakePerfResultCache(c appengine.Context, com *Commit, newer bool) *PerfResultCache {
	p := &Package{}
	q := datastore.NewQuery("PerfResult").Ancestor(p.Key(c)).Limit(100)
	if newer {
		q = q.Filter("CommitNum >=", com.Num).Order("CommitNum")
	} else {
		q = q.Filter("CommitNum <=", com.Num).Order("-CommitNum")
	}
	rc := &PerfResultCache{c: c, newer: newer, iter: q.Run(c), results: make(map[int]*PerfResult)}
	return rc
}

func (rc *PerfResultCache) Get(commitNum int) *PerfResult {
	rc.Next(commitNum) // fetch the commit, if necessary
	return rc.results[commitNum]
}

// Next returns the next PerfResult for the commit commitNum.
// It does not care whether the result has any data, failed or whatever.
func (rc *PerfResultCache) Next(commitNum int) (*PerfResult, error) {
	// See if we have next result in the cache.
	next := -1
	for ci := range rc.results {
		if rc.newer {
			if ci > commitNum && (next == -1 || ci < next) {
				next = ci
			}
		} else {
			if ci < commitNum && (next == -1 || ci > next) {
				next = ci
			}
		}
	}
	//rc.c.Errorf("PerfResultCache.Next: num=%v next=%v", commitNum, next)
	if next != -1 {
		return rc.results[next], nil
	}
	// Fetch next result from datastore.
	res := new(PerfResult)
	_, err := rc.iter.Next(res)
	//rc.c.Errorf("PerfResultCache.Next: fetched %v %+v", err, res)
	if err == datastore.Done {
		return nil, nil
	}
	if err != nil {
		return nil, fmt.Errorf("fetching perf results: %v", err)
	}
	if (rc.newer && res.CommitNum < commitNum) || (!rc.newer && res.CommitNum > commitNum) {
		rc.c.Errorf("PerfResultCache.Next: bad commit num")
	}
	rc.results[res.CommitNum] = res
	return res, nil
}

// NextForComparison returns PerfResult which we need to use for performance comprison.
// It skips failed results, but does not skip results with no data.
func (rc *PerfResultCache) NextForComparison(commitNum int, builder string) (*PerfResult, error) {
	for {
		res, err := rc.Next(commitNum)
		if err != nil {
			return nil, err
		}
		if res == nil {
			return nil, nil
		}
		if res.CommitNum == commitNum {
			continue
		}
		parsed := res.ParseData()
		if builder != "" {
			// Comparing for a particular builder.
			// This is used in perf_changes and in email notifications.
			b := parsed[builder]
			if b == nil || b["meta-done"] == nil {
				// No results yet, must not do the comparison.
				return nil, nil
			}
			if b["meta-done"].OK {
				// Have complete results, compare.
				return res, nil
			}
		} else {
			// Comparing for all builders, find a result with at least
			// one successful meta-done.
			// This is used in perf_detail.
			for _, benchs := range parsed {
				if data := benchs["meta-done"]; data != nil && data.OK {
					return res, nil
				}
			}
		}
		// Failed, try next result.
		commitNum = res.CommitNum
	}
}

type PerfChange struct {
	builder string
	bench   string
	metric  string
	old     uint64
	new     uint64
	diff    float64
}

func significantPerfChanges(pc *PerfConfig, builder string, prevRes, res *PerfResult) (changes []*PerfChange) {
	// First, collect all significant changes.
	for builder1, benchmarks1 := range res.ParseData() {
		if builder != "" && builder != builder1 {
			// This is not the builder you're looking for, Luke.
			continue
		}
		benchmarks0 := prevRes.ParseData()[builder1]
		if benchmarks0 == nil {
			continue
		}
		for benchmark, data1 := range benchmarks1 {
			data0 := benchmarks0[benchmark]
			if data0 == nil {
				continue
			}
			for metric, val := range data1.Metrics {
				val0 := data0.Metrics[metric]
				if val0 == 0 {
					continue
				}
				diff := perfDiff(val0, val)
				noise := pc.NoiseLevel(builder, benchmark, metric)
				if isNoise(diff, noise) {
					continue
				}
				ch := &PerfChange{builder: builder, bench: benchmark, metric: metric, old: val0, new: val, diff: diff}
				changes = append(changes, ch)
			}
		}
	}
	// Then, strip non-repeatable changes (flakes).
	// The hypothesis is that a real change must show up with at least
	// 2 different values of GOMAXPROCS.
	cnt := make(map[string]int)
	for _, ch := range changes {
		b, _ := splitBench(ch.bench)
		name := b + "|" + ch.metric
		inc := 1
		if ch.diff < 0 {
			inc = -1
		}
		cnt[name] = cnt[name] + inc
	}
	for i := 0; i < len(changes); i++ {
		ch := changes[i]
		b, _ := splitBench(ch.bench)
		name := b + "|" + ch.metric
		if n := cnt[name]; n <= -2 || n >= 2 {
			continue
		}
		last := len(changes) - 1
		changes[i] = changes[last]
		changes = changes[:last]
		i--
	}
	return changes
}

// orderPrefTodo reorders commit nums for benchmarking todo.
// The resulting order is somewhat tricky. We want 2 things:
// 1. benchmark sequentially backwards (this provides information about most
// recent changes, and allows to estimate noise levels)
// 2. benchmark old commits in "scatter" order (this allows to quickly gather
// brief information about thousands of old commits)
// So this function interleaves the two orders.
func orderPrefTodo(nums []int) []int {
	sort.Ints(nums)
	n := len(nums)
	pow2 := uint32(0) // next power-of-two that is >= n
	npow2 := 0
	for npow2 <= n {
		pow2++
		npow2 = 1 << pow2
	}
	res := make([]int, n)
	resPos := n - 1            // result array is filled backwards
	present := make([]bool, n) // denotes values that already present in result array
	for i0, i1 := n-1, 0; i0 >= 0 || i1 < npow2; {
		// i0 represents "benchmark sequentially backwards" sequence
		// find the next commit that is not yet present and add it
		for cnt := 0; cnt < 2; cnt++ {
			for ; i0 >= 0; i0-- {
				if !present[i0] {
					present[i0] = true
					res[resPos] = nums[i0]
					resPos--
					i0--
					break
				}
			}
		}
		// i1 represents "scatter order" sequence
		// find the next commit that is not yet present and add it
		for ; i1 < npow2; i1++ {
			// do the "recursive split-ordering" trick
			idx := 0 // bitwise reverse of i1
			for j := uint32(0); j <= pow2; j++ {
				if (i1 & (1 << j)) != 0 {
					idx = idx | (1 << (pow2 - j - 1))
				}
			}
			if idx < n && !present[idx] {
				present[idx] = true
				res[resPos] = nums[idx]
				resPos--
				i1++
				break
			}
		}
	}
	// The above can't possibly be correct. Do dump check.
	res2 := make([]int, n)
	copy(res2, res)
	sort.Ints(res2)
	for i := range res2 {
		if res2[i] != nums[i] {
			panic(fmt.Sprintf("diff at %v: expect %v, want %v\nwas: %v\n become: %v",
				i, nums[i], res2[i], nums, res2))
		}
	}
	return res
}
<|endoftext|>


<commit_before>package gopher

import (
	"github.com/gopherlabs/gopher-services/providers"
)

func RegisterProviders() {
	GetContext().Logger = providers.Logger{}
	GetContext().Router = providers.RouteProvider{}
}
<commit_msg>Added Parameter to bindings<commit_after>package gopher

import (
	"github.com/gopherlabs/gopher-services/providers"
)

func RegisterProviders() {
	GetContext().Logger = providers.Logger{}
	GetContext().Router = providers.RouteProvider{}
	GetContext().Parameters = providers.ParameterProvider{}
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013 Dave Collins <dave@davec.name>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package spew_test

import (
	"fmt"
	"github.com/davecgh/go-spew/spew"
	"reflect"
	"testing"
)

// custom type to test Stinger interface on non-pointer receiver.
type stringer string

// String implements the Stringer interface for testing invocation of custom
// stringers on types with non-pointer receivers.
func (s stringer) String() string {
	return "stringer " + string(s)
}

// custom type to test Stinger interface on pointer receiver.
type pstringer string

// String implements the Stringer interface for testing invocation of custom
// stringers on types with only pointer receivers.
func (s *pstringer) String() string {
	return "stringer " + string(*s)
}

// xref1 and xref2 are cross referencing structs for testing circular reference
// detection.
type xref1 struct {
	ps2 *xref2
}
type xref2 struct {
	ps1 *xref1
}

// indirCir1, indirCir2, and indirCir3 are used to generate an indirect circular
// reference for testing detection.
type indirCir1 struct {
	ps2 *indirCir2
}
type indirCir2 struct {
	ps3 *indirCir3
}
type indirCir3 struct {
	ps1 *indirCir1
}

// embed is used to test embedded structures.
type embed struct {
	a string
}

// embedwrap is used to test embedded structures.
type embedwrap struct {
	*embed
	e *embed
}

// panicer is used to intentionally cause a panic for testing spew properly
// handles them
type panicer int

func (p panicer) String() string {
	panic("test panic")
}

// customError is used to test custom error interface invocation.
type customError int

func (e customError) Error() string {
	return fmt.Sprintf("error: %d", int(e))
}

// stringizeWants converts a slice of wanted test output into a format suitable
// for a test error message.
func stringizeWants(wants []string) string {
	s := ""
	for i, want := range wants {
		if i > 0 {
			s += fmt.Sprintf("want%d: %s", i+1, want)
		} else {
			s += "want: " + want
		}
	}
	return s
}

// testFailed returns whether or not a test failed by checking if the result
// of the test is in the slice of wanted strings.
func testFailed(result string, wants []string) bool {
	for _, want := range wants {
		if result == want {
			return false
		}
	}
	return true
}

// TestSortValues ensures the sort functionality for relect.Value based sorting
// works as intended.
func TestSortValues(t *testing.T) {
	v := reflect.ValueOf

	a := v("a")
	b := v("b")
	c := v("c")
	embedA := v(embed{"a"})
	embedB := v(embed{"b"})
	embedC := v(embed{"c"})
	tests := []struct {
		input    []reflect.Value
		expected []reflect.Value
	}{
		// No values.
		{
			[]reflect.Value{},
			[]reflect.Value{},
		},
		// Bools.
		{
			[]reflect.Value{v(false), v(true), v(false)},
			[]reflect.Value{v(false), v(false), v(true)},
		},
		// Ints.
		{
			[]reflect.Value{v(2), v(1), v(3)},
			[]reflect.Value{v(1), v(2), v(3)},
		},
		// Uints.
		{
			[]reflect.Value{v(uint8(2)), v(uint8(1)), v(uint8(3))},
			[]reflect.Value{v(uint8(1)), v(uint8(2)), v(uint8(3))},
		},
		// Floats.
		{
			[]reflect.Value{v(2.0), v(1.0), v(3.0)},
			[]reflect.Value{v(1.0), v(2.0), v(3.0)},
		},
		// Strings.
		{
			[]reflect.Value{b, a, c},
			[]reflect.Value{a, b, c},
		},
		// Uintptrs.
		{
			[]reflect.Value{v(uintptr(2)), v(uintptr(1)), v(uintptr(3))},
			[]reflect.Value{v(uintptr(1)), v(uintptr(2)), v(uintptr(3))},
		},
		// Invalid.
		{
			[]reflect.Value{embedB, embedA, embedC},
			[]reflect.Value{embedB, embedA, embedC},
		},
	}
	for _, test := range tests {
		spew.SortValues(test.input)
		if !reflect.DeepEqual(test.input, test.expected) {
			t.Errorf("Sort mismatch:\n %v != %v", test.input, test.expected)
		}
	}
}
<commit_msg>tests: fix TestSortValues on 32-bits platforms<commit_after>/*
 * Copyright (c) 2013 Dave Collins <dave@davec.name>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package spew_test

import (
	"fmt"
	"github.com/davecgh/go-spew/spew"
	"reflect"
	"testing"
)

// custom type to test Stinger interface on non-pointer receiver.
type stringer string

// String implements the Stringer interface for testing invocation of custom
// stringers on types with non-pointer receivers.
func (s stringer) String() string {
	return "stringer " + string(s)
}

// custom type to test Stinger interface on pointer receiver.
type pstringer string

// String implements the Stringer interface for testing invocation of custom
// stringers on types with only pointer receivers.
func (s *pstringer) String() string {
	return "stringer " + string(*s)
}

// xref1 and xref2 are cross referencing structs for testing circular reference
// detection.
type xref1 struct {
	ps2 *xref2
}
type xref2 struct {
	ps1 *xref1
}

// indirCir1, indirCir2, and indirCir3 are used to generate an indirect circular
// reference for testing detection.
type indirCir1 struct {
	ps2 *indirCir2
}
type indirCir2 struct {
	ps3 *indirCir3
}
type indirCir3 struct {
	ps1 *indirCir1
}

// embed is used to test embedded structures.
type embed struct {
	a string
}

// embedwrap is used to test embedded structures.
type embedwrap struct {
	*embed
	e *embed
}

// panicer is used to intentionally cause a panic for testing spew properly
// handles them
type panicer int

func (p panicer) String() string {
	panic("test panic")
}

// customError is used to test custom error interface invocation.
type customError int

func (e customError) Error() string {
	return fmt.Sprintf("error: %d", int(e))
}

// stringizeWants converts a slice of wanted test output into a format suitable
// for a test error message.
func stringizeWants(wants []string) string {
	s := ""
	for i, want := range wants {
		if i > 0 {
			s += fmt.Sprintf("want%d: %s", i+1, want)
		} else {
			s += "want: " + want
		}
	}
	return s
}

// testFailed returns whether or not a test failed by checking if the result
// of the test is in the slice of wanted strings.
func testFailed(result string, wants []string) bool {
	for _, want := range wants {
		if result == want {
			return false
		}
	}
	return true
}

// TestSortValues ensures the sort functionality for relect.Value based sorting
// works as intended.
func TestSortValues(t *testing.T) {
	getInterfaces := func(values []reflect.Value) []interface{} {
		interfaces := []interface{}{}
		for _, v := range values {
			interfaces = append(interfaces, v.Interface())
		}
		return interfaces
	}

	v := reflect.ValueOf

	a := v("a")
	b := v("b")
	c := v("c")
	embedA := v(embed{"a"})
	embedB := v(embed{"b"})
	embedC := v(embed{"c"})
	tests := []struct {
		input    []reflect.Value
		expected []reflect.Value
	}{
		// No values.
		{
			[]reflect.Value{},
			[]reflect.Value{},
		},
		// Bools.
		{
			[]reflect.Value{v(false), v(true), v(false)},
			[]reflect.Value{v(false), v(false), v(true)},
		},
		// Ints.
		{
			[]reflect.Value{v(2), v(1), v(3)},
			[]reflect.Value{v(1), v(2), v(3)},
		},
		// Uints.
		{
			[]reflect.Value{v(uint8(2)), v(uint8(1)), v(uint8(3))},
			[]reflect.Value{v(uint8(1)), v(uint8(2)), v(uint8(3))},
		},
		// Floats.
		{
			[]reflect.Value{v(2.0), v(1.0), v(3.0)},
			[]reflect.Value{v(1.0), v(2.0), v(3.0)},
		},
		// Strings.
		{
			[]reflect.Value{b, a, c},
			[]reflect.Value{a, b, c},
		},
		// Uintptrs.
		{
			[]reflect.Value{v(uintptr(2)), v(uintptr(1)), v(uintptr(3))},
			[]reflect.Value{v(uintptr(1)), v(uintptr(2)), v(uintptr(3))},
		},
		// Invalid.
		{
			[]reflect.Value{embedB, embedA, embedC},
			[]reflect.Value{embedB, embedA, embedC},
		},
	}
	for _, test := range tests {
		spew.SortValues(test.input)
		// reflect.DeepEqual cannot really make sense of reflect.Value,
		// probably because of all the pointer tricks. For instance,
		// v(2.0) != v(2.0) on a 32-bits system. Turn them into interface{}
		// instead.
		input := getInterfaces(test.input)
		expected := getInterfaces(test.expected)
		if !reflect.DeepEqual(input, expected) {
			t.Errorf("Sort mismatch:\n %v != %v", input, expected)
		}
	}
}
<|endoftext|>


<commit_before>package termite

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

	"github.com/hanwen/go-fuse/fuse"
	"github.com/hanwen/go-fuse/fuse/pathfs"
	"github.com/hanwen/termite/attr"
	"github.com/hanwen/termite/fs"
)

type workerFuseFs struct {
	rwDir  string
	tmpDir string
	mount  string

	// without leading /
	writableRoot string
	*fuse.MountState
	fsConnector *fuse.FileSystemConnector
	unionFs     *fs.MemUnionFs
	procFs      *fs.ProcFs
	rpcNodeFs   *pathfs.PathNodeFs
	unionNodeFs *pathfs.PathNodeFs

	// Protected by Mirror.fsMutex
	id      string
	reaping bool

	// When this reaches zero, we reap the filesystem.
	tasks map[*WorkerTask]bool

	// Task ids that have results pending in this FS.
	taskIds []int
}

func (me *workerFuseFs) Status() (s FuseFsStatus) {
	s.Id = me.id
	s.Mem = me.BufferPoolStats()
	for t := range me.tasks {
		s.Tasks = append(s.Tasks, t.taskInfo)
	}
	return s
}

func (me *workerFuseFs) addTask(task *WorkerTask) {
	me.taskIds = append(me.taskIds, task.req.TaskId)
	me.tasks[task] = true
}

func (me *workerFuseFs) Stop() {
	if err := me.MountState.Unmount(); err != nil {
		// If the unmount fails, the RemoveAll will stat all
		// of the FUSE file system, so we have to exit.
		log.Panic("unmount fail in workerFuseFs.Stop:", err)
	}

	os.RemoveAll(me.tmpDir)
}

func (me *workerFuseFs) SetDebug(debug bool) {
	me.MountState.SetDebug(debug)
	me.fsConnector.SetDebug(debug)
	me.rpcNodeFs.SetDebug(debug)
}

func newWorkerFuseFs(tmpDir string, rpcFs pathfs.FileSystem, writableRoot string, nobody *User) (*workerFuseFs, error) {
	tmpDir, err := ioutil.TempDir(tmpDir, "termite-task")
	if err != nil {
		return nil, err
	}
	me := &workerFuseFs{
		tmpDir:       tmpDir,
		writableRoot: strings.TrimLeft(writableRoot, "/"),
		tasks:        map[*WorkerTask]bool{},
	}

	type dirInit struct {
		dst *string
		val string
	}

	tmpBacking := ""
	for _, v := range []dirInit{
		{&me.rwDir, "rw"},
		{&me.mount, "mnt"},
		{&tmpBacking, "tmp-backing"},
	} {
		*v.dst = filepath.Join(me.tmpDir, v.val)
		err = os.Mkdir(*v.dst, 0700)
		if err != nil {
			return nil, err
		}
	}

	fuseOpts := fuse.MountOptions{}
	if os.Geteuid() == 0 {
		fuseOpts.AllowOther = true
	}

	me.rpcNodeFs = pathfs.NewPathNodeFs(rpcFs, nil)
	ttl := 30 * time.Second
	mOpts := fuse.FileSystemOptions{
		EntryTimeout:    ttl,
		AttrTimeout:     ttl,
		NegativeTimeout: ttl,

		// 32-bit programs have trouble with 64-bit inode
		// numbers.
		PortableInodes: true,
	}

	me.fsConnector = fuse.NewFileSystemConnector(me.rpcNodeFs, &mOpts)
	me.MountState = fuse.NewMountState(me.fsConnector.RawFS())
	err = me.MountState.Mount(me.mount, &fuseOpts)
	if err != nil {
		return nil, err
	}
	go me.MountState.Loop()

	me.unionFs, err = fs.NewMemUnionFs(
		me.rwDir, pathfs.NewPrefixFileSystem(rpcFs, me.writableRoot))
	if err != nil {
		return nil, err
	}

	me.procFs = fs.NewProcFs()
	me.procFs.StripPrefix = me.mount
	if nobody != nil {
		me.procFs.Uid = nobody.Uid
	}
	type submount struct {
		mountpoint string
		fs         fuse.NodeFileSystem
	}

	mounts := []submount{
		{"proc", pathfs.NewPathNodeFs(me.procFs, nil)},
		{"sys", pathfs.NewPathNodeFs(&pathfs.ReadonlyFileSystem{pathfs.NewLoopbackFileSystem("/sys")}, nil)},
		{"tmp", fuse.NewMemNodeFs(tmpBacking + "/tmp")},
		{"dev", fs.NewDevFs()},
		{"var/tmp", fuse.NewMemNodeFs(tmpBacking + "/vartmp")},
	}
	for _, s := range mounts {
		subOpts := &mOpts
		if s.mountpoint == "proc" {
			subOpts = nil
		}

		code := me.rpcNodeFs.Mount(s.mountpoint, s.fs, subOpts)
		if !code.Ok() {
			if err := me.MountState.Unmount(); err != nil {
				log.Fatal("FUSE unmount error during cleanup:", err)
			}
			return nil, errors.New(fmt.Sprintf("submount error for %s: %v", s.mountpoint, code))
		}
	}
	if strings.HasPrefix(me.writableRoot, "tmp/") {
		parent, _ := filepath.Split(me.writableRoot)
		err := os.MkdirAll(filepath.Join(me.mount, parent), 0755)
		if err != nil {
			if err := me.MountState.Unmount(); err != nil {
				log.Fatal("FUSE unmount error during cleanup:", err)
			}
			return nil, errors.New(fmt.Sprintf("Mkdir of %q in /tmp fail: %v", parent, err))
		}
		// This is hackish, but we don't want rpcfs/fsserver
		// getting confused by asking for tmp/foo/bar
		// directly.
		rpcFs.GetAttr("tmp", nil)
		rpcFs.GetAttr(me.writableRoot, nil)
	}
	code := me.rpcNodeFs.Mount(me.writableRoot, me.unionFs, &mOpts)
	if !code.Ok() {
		if err := me.MountState.Unmount(); err != nil {
			log.Fatal("FUSE unmount error during cleanup:", err)
		}
		return nil, errors.New(fmt.Sprintf("submount error for %s: %v", me.writableRoot, code))
	}

	return me, nil
}

func (me *workerFuseFs) update(attrs []*attr.FileAttr) {
	updates := map[string]*fs.Result{}
	for _, attr := range attrs {
		path := strings.TrimLeft(attr.Path, "/")
		if !strings.HasPrefix(path, me.writableRoot) {
			me.rpcNodeFs.Notify(path)
			continue
		}
		path = strings.TrimLeft(path[len(me.writableRoot):], "/")

		if attr.Deletion() {
			updates[path] = &fs.Result{}
		} else {
			r := fs.Result{
				Original: "",
				Backing:  "",
				Link:     attr.Link,
				Attr:     &fuse.Attr{},
			}
			a := *attr.Attr
			r.Attr = &a
			updates[path] = &r
		}
	}
	me.unionFs.Update(updates)
}

func (fs *workerFuseFs) reap() (dir string, yield map[string]*fs.Result) {
	yield = fs.unionFs.Reap()
	backingStoreFiles := map[string]string{}
	dir, err := ioutil.TempDir(fs.tmpDir, "reap")
	if err != nil {
		log.Fatalf("ioutil.TempDir: %v", err)
	}

	i := 0
	for _, v := range yield {
		if v.Backing == "" {
			continue
		}
		newBacking := backingStoreFiles[v.Backing]
		if newBacking == "" {
			newBacking = fmt.Sprintf("%s/%d", dir, i)
			i++

			err := os.Rename(v.Backing, newBacking)
			if err != nil {
				log.Panicf("reapFiles rename failed: %v", err)
			}
			log.Printf("created %q", newBacking)
			backingStoreFiles[v.Backing] = newBacking
		}
		v.Backing = newBacking
	}

	// We saved the backing store files, so we don't need the file system anymore.
	fs.unionFs.Reset()
	return dir, yield
}
<commit_msg>Update for NewReadonlyFileSystem API.<commit_after>package termite

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

	"github.com/hanwen/go-fuse/fuse"
	"github.com/hanwen/go-fuse/fuse/pathfs"
	"github.com/hanwen/termite/attr"
	"github.com/hanwen/termite/fs"
)

type workerFuseFs struct {
	rwDir  string
	tmpDir string
	mount  string

	// without leading /
	writableRoot string
	*fuse.MountState
	fsConnector *fuse.FileSystemConnector
	unionFs     *fs.MemUnionFs
	procFs      *fs.ProcFs
	rpcNodeFs   *pathfs.PathNodeFs
	unionNodeFs *pathfs.PathNodeFs

	// Protected by Mirror.fsMutex
	id      string
	reaping bool

	// When this reaches zero, we reap the filesystem.
	tasks map[*WorkerTask]bool

	// Task ids that have results pending in this FS.
	taskIds []int
}

func (me *workerFuseFs) Status() (s FuseFsStatus) {
	s.Id = me.id
	s.Mem = me.BufferPoolStats()
	for t := range me.tasks {
		s.Tasks = append(s.Tasks, t.taskInfo)
	}
	return s
}

func (me *workerFuseFs) addTask(task *WorkerTask) {
	me.taskIds = append(me.taskIds, task.req.TaskId)
	me.tasks[task] = true
}

func (me *workerFuseFs) Stop() {
	if err := me.MountState.Unmount(); err != nil {
		// If the unmount fails, the RemoveAll will stat all
		// of the FUSE file system, so we have to exit.
		log.Panic("unmount fail in workerFuseFs.Stop:", err)
	}

	os.RemoveAll(me.tmpDir)
}

func (me *workerFuseFs) SetDebug(debug bool) {
	me.MountState.SetDebug(debug)
	me.fsConnector.SetDebug(debug)
	me.rpcNodeFs.SetDebug(debug)
}

func newWorkerFuseFs(tmpDir string, rpcFs pathfs.FileSystem, writableRoot string, nobody *User) (*workerFuseFs, error) {
	tmpDir, err := ioutil.TempDir(tmpDir, "termite-task")
	if err != nil {
		return nil, err
	}
	me := &workerFuseFs{
		tmpDir:       tmpDir,
		writableRoot: strings.TrimLeft(writableRoot, "/"),
		tasks:        map[*WorkerTask]bool{},
	}

	type dirInit struct {
		dst *string
		val string
	}

	tmpBacking := ""
	for _, v := range []dirInit{
		{&me.rwDir, "rw"},
		{&me.mount, "mnt"},
		{&tmpBacking, "tmp-backing"},
	} {
		*v.dst = filepath.Join(me.tmpDir, v.val)
		err = os.Mkdir(*v.dst, 0700)
		if err != nil {
			return nil, err
		}
	}

	fuseOpts := fuse.MountOptions{}
	if os.Geteuid() == 0 {
		fuseOpts.AllowOther = true
	}

	me.rpcNodeFs = pathfs.NewPathNodeFs(rpcFs, nil)
	ttl := 30 * time.Second
	mOpts := fuse.FileSystemOptions{
		EntryTimeout:    ttl,
		AttrTimeout:     ttl,
		NegativeTimeout: ttl,

		// 32-bit programs have trouble with 64-bit inode
		// numbers.
		PortableInodes: true,
	}

	me.fsConnector = fuse.NewFileSystemConnector(me.rpcNodeFs, &mOpts)
	me.MountState = fuse.NewMountState(me.fsConnector.RawFS())
	err = me.MountState.Mount(me.mount, &fuseOpts)
	if err != nil {
		return nil, err
	}
	go me.MountState.Loop()

	me.unionFs, err = fs.NewMemUnionFs(
		me.rwDir, pathfs.NewPrefixFileSystem(rpcFs, me.writableRoot))
	if err != nil {
		return nil, err
	}

	me.procFs = fs.NewProcFs()
	me.procFs.StripPrefix = me.mount
	if nobody != nil {
		me.procFs.Uid = nobody.Uid
	}
	type submount struct {
		mountpoint string
		fs         fuse.NodeFileSystem
	}

	mounts := []submount{
		{"proc", pathfs.NewPathNodeFs(me.procFs, nil)},
		{"sys", pathfs.NewPathNodeFs(pathfs.NewReadonlyFileSystem(pathfs.NewLoopbackFileSystem("/sys")), nil)},
		{"tmp", fuse.NewMemNodeFs(tmpBacking + "/tmp")},
		{"dev", fs.NewDevFs()},
		{"var/tmp", fuse.NewMemNodeFs(tmpBacking + "/vartmp")},
	}
	for _, s := range mounts {
		subOpts := &mOpts
		if s.mountpoint == "proc" {
			subOpts = nil
		}

		code := me.rpcNodeFs.Mount(s.mountpoint, s.fs, subOpts)
		if !code.Ok() {
			if err := me.MountState.Unmount(); err != nil {
				log.Fatal("FUSE unmount error during cleanup:", err)
			}
			return nil, errors.New(fmt.Sprintf("submount error for %s: %v", s.mountpoint, code))
		}
	}
	if strings.HasPrefix(me.writableRoot, "tmp/") {
		parent, _ := filepath.Split(me.writableRoot)
		err := os.MkdirAll(filepath.Join(me.mount, parent), 0755)
		if err != nil {
			if err := me.MountState.Unmount(); err != nil {
				log.Fatal("FUSE unmount error during cleanup:", err)
			}
			return nil, errors.New(fmt.Sprintf("Mkdir of %q in /tmp fail: %v", parent, err))
		}
		// This is hackish, but we don't want rpcfs/fsserver
		// getting confused by asking for tmp/foo/bar
		// directly.
		rpcFs.GetAttr("tmp", nil)
		rpcFs.GetAttr(me.writableRoot, nil)
	}
	code := me.rpcNodeFs.Mount(me.writableRoot, me.unionFs, &mOpts)
	if !code.Ok() {
		if err := me.MountState.Unmount(); err != nil {
			log.Fatal("FUSE unmount error during cleanup:", err)
		}
		return nil, errors.New(fmt.Sprintf("submount error for %s: %v", me.writableRoot, code))
	}

	return me, nil
}

func (me *workerFuseFs) update(attrs []*attr.FileAttr) {
	updates := map[string]*fs.Result{}
	for _, attr := range attrs {
		path := strings.TrimLeft(attr.Path, "/")
		if !strings.HasPrefix(path, me.writableRoot) {
			me.rpcNodeFs.Notify(path)
			continue
		}
		path = strings.TrimLeft(path[len(me.writableRoot):], "/")

		if attr.Deletion() {
			updates[path] = &fs.Result{}
		} else {
			r := fs.Result{
				Original: "",
				Backing:  "",
				Link:     attr.Link,
				Attr:     &fuse.Attr{},
			}
			a := *attr.Attr
			r.Attr = &a
			updates[path] = &r
		}
	}
	me.unionFs.Update(updates)
}

func (fs *workerFuseFs) reap() (dir string, yield map[string]*fs.Result) {
	yield = fs.unionFs.Reap()
	backingStoreFiles := map[string]string{}
	dir, err := ioutil.TempDir(fs.tmpDir, "reap")
	if err != nil {
		log.Fatalf("ioutil.TempDir: %v", err)
	}

	i := 0
	for _, v := range yield {
		if v.Backing == "" {
			continue
		}
		newBacking := backingStoreFiles[v.Backing]
		if newBacking == "" {
			newBacking = fmt.Sprintf("%s/%d", dir, i)
			i++

			err := os.Rename(v.Backing, newBacking)
			if err != nil {
				log.Panicf("reapFiles rename failed: %v", err)
			}
			log.Printf("created %q", newBacking)
			backingStoreFiles[v.Backing] = newBacking
		}
		v.Backing = newBacking
	}

	// We saved the backing store files, so we don't need the file system anymore.
	fs.unionFs.Reset()
	return dir, yield
}
<|endoftext|>


<commit_before>package main

import (
	"appstax-cli/appstax/account"
	"appstax-cli/appstax/apiclient"
	"appstax-cli/appstax/config"
	"appstax-cli/appstax/fail"
	"appstax-cli/appstax/hosting"
	"appstax-cli/appstax/log"
	"appstax-cli/appstax/session"
	"appstax-cli/appstax/term"
	"fmt"
	"github.com/codegangsta/cli"
	"github.com/skratchdot/open-golang/open"
	"io/ioutil"
	"net/http"
	"os"
	"os/signal"
	"strings"
)

func main() {
	setupSignals()
	commands := setupCommands()
	log.Infof("Command to execute: %s", strings.Join(os.Args, " "))
	term.Section()
	commands.Run(os.Args)
	term.Section()
}

func setupCommands() *cli.App {
	app := cli.NewApp()
	app.Name = "appstax"
	app.Usage = "command line interface for appstax.com"
	app.Version = "0.9.0"

	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "verbose",
			Usage: "enable verbose output",
		},
		cli.StringFlag{
			Name:  "baseurl",
			Usage: "set api base url",
		},
	}

	app.Commands = []cli.Command{
		{
			Name:   "login",
			Usage:  "Login",
			Action: DoLogin,
			Flags:  app.Flags,
		},
		{
			Name:   "init",
			Usage:  "Initialize current directory as an appstax app",
			Action: DoInit,
			Flags:  app.Flags,
		},
		{
			Name:   "info",
			Usage:  "Info about app configured in current directory",
			Action: DoInfo,
			Flags:  app.Flags,
		},
		{
			Name:   "deploy",
			Usage:  "Deploy local files to <yourapp>.appstax.io",
			Action: DoDeploy,
			Flags:  app.Flags,
		},
		{
			Name:   "open",
			Usage:  "Open your browser to the specified destination",
			Action: DoOpen,
			Flags:  app.Flags,
		},
		{
			Name:   "logout",
			Usage:  "Logout of current app session",
			Action: DoLogout,
			Flags:  app.Flags,
		},
		{
			Name:   "serve",
			Usage:  "Run development http server",
			Action: DoServe,
			Flags:  app.Flags,
		},
	}

	return app
}

func setupSignals() {
	c := make(chan os.Signal, 10)
	signal.Notify(c, os.Interrupt)
	go func() {
		for _ = range c {
			fmt.Print("\n")
			os.Exit(-1)
		}
	}()
}

func DoInit(c *cli.Context) {
	useOptions(c)
	loginIfNeeded()
	app := selectApp()
	pub := selectPublicDir()
	writeConfig(app, pub)
	selectSubdomain(app.AppID)
	createPublicDir()
	term.Section()
	term.Println("Now run 'appstax deploy' when you are ready to upload your public files.")
}

func DoInfo(c *cli.Context) {
	useOptions(c)
	loginIfNeeded()
	if !config.Exists() {
		term.Println("No app configured in current directory. (Missing appstax.conf)")
	} else {
		app, err := account.GetCurrentApp()
		fail.Handle(err)
		term.Println("App name:    " + app.AppName)
		term.Println("Description: " + app.AppDescription)
		term.Println("App key:     " + app.AppKey)
		term.Println("Hosting:     " + account.FormatHostingUrl(app))
		term.Section()
	}
	user, err := account.GetUser()
	fail.Handle(err)
	term.Printf("Logged in as %s %s (%s)\n", user.FirstName, user.LastName, user.Email)
}

func DoLogin(c *cli.Context) {
	useOptions(c)
	login()
}

func DoDeploy(c *cli.Context) {
	useOptions(c)
	if !config.Exists() {
		term.Println("Can't find appstax.conf. Run 'appstax init' to initialize before deploying.")
		return
	}
	loginIfNeeded()
	dir := config.Read().PublicDir
	term.Println("Packaging files for upload...")
	archive, bytes := hosting.PrepareArchive(dir)
	term.Printf("Uploading %.2f MB...\n", float64(bytes)/(1024.0*1024.0))
	progress := term.ShowProgressBar(bytes)
	err := hosting.UploadStatic(archive, progress)
	if err != nil {
		term.Section()
		term.Println(err.Error())
	} else {
		progress.Finish()
		term.Section()
		term.Println("Deploy completed!")
	}
}

func DoLogout(c *cli.Context) {
	session.Delete()
	term.Println("Logged out.")
}

func DoOpen(c *cli.Context) {
	useOptions(c)
	dest := c.Args().First()
	log.Debugf("Open destination: %s", dest)
	url := ""
	message := ""

	switch dest {

	case "deployed":
		app, err := account.GetCurrentApp()
		if err != nil {
			message = "Sorry, could not find a deployed app to open."
		}
		url = "http://" + app.HostingSubdomain + ".appstax.io"
		break

	case "admin":
		url = "http://appstax.com/admin/#/dashboard"
		break

	case "local":
		url = "http://localhost:9000/"
		break
	}

	if url != "" {
		term.Printf("Opening %s in your browser.\n", url)
		err := open.Start(url)
		if err != nil {
			message = "Ooops! Something went wrong."
		}
	}

	if message != "" {
		term.Section()
		term.Println(message)
	}
}

func DoServe(c *cli.Context) {
	useOptions(c)
	publicDir := config.Read().PublicDir
	term.Println("Serving your public directory at http://localhost:9000/")
	term.Println("Press Ctrl-C to stop.")
	term.Section()

	http.Handle("/", http.FileServer(http.Dir(publicDir)))
	http.ListenAndServe(":9000", nil)
}

func useOptions(c *cli.Context) {
	log.SetStdoutEnabled(c.GlobalBool("verbose") || c.Bool("verbose"))
	fail.SetPanicMode(c.GlobalBool("verbose") || c.Bool("verbose"))
	apiclient.SetBaseUrl(c.GlobalString("baseurl") + c.String("baseurl"))
}

func loginIfNeeded() {
	if session.ReadSessionID() == "" {
		term.Section()
		term.Println("Please log in:")
		login()
	}
}

func login() {
	for {
		email := term.GetString("Email")
		password := term.GetPassword("Password")
		sessionID, userID, accountID, err := account.Login(email, password)
		if err != nil {
			term.Section()
			term.Println(err.Error())
		} else {
			writeSession(sessionID, userID, accountID)
			term.Section()
			term.Println(fmt.Sprintf("Successfully logged in as '%s'", email))
			return
		}
	}
}

func selectApp() account.App {
	apps, _ := account.GetUserApps()
	selected := 0
	if len(apps) > 1 {
		term.Section()
		term.Println("Choose which app app to configure:")
		for i, app := range apps {
			term.Printf("  %d) %s\n", i+1, app.AppName)
		}
		term.Section()
		selected = -1 + term.GetInt(fmt.Sprintf("Please select app (1-%d)", len(apps)))
	}
	return apps[selected]
}

func selectPublicDir() string {
	dir := term.GetString("Select deployable directory [default: ./public]")
	if dir == "" {
		dir = "./public"
	}
	return dir
}

func selectSubdomain(appID string) {
	app, _ := account.GetAppByID(appID)
	log.Debugf("Subdomain app: %v", app)
	for {
		app.HostingSubdomain = term.GetString("Choose a *.appstax.io subdomain")
		err1 := account.SaveApp(app)
		if err1 != nil {
			term.Println(err1.Error())
		}
		err2 := account.AddCorsOrigin(appID, fmt.Sprintf("http://%s.appstax.io", app.HostingSubdomain))
		if err2 != nil {
			term.Println(err2.Error())
		}
		if err1 == nil && err2 == nil {
			term.Printf("Successfully configured %s.appstax.io\n", app.HostingSubdomain)
			return
		}
	}
}

func createPublicDir() {
	dir := config.Read().PublicDir
	if _, err := os.Stat(dir); os.IsNotExist(err) {
		err = os.MkdirAll(dir, 0700)
		fail.Handle(err)
		ioutil.WriteFile(dir+"/index.html", []byte("<!DOCTYPE html>\n
Your hosting is up and running
\n
Now go make something amazing!
"), 0644)
		log.Debugf("Created public directory '%s'", dir)
	} else {
		log.Debugf("Not creating public directory. '%s' already exists.", dir)
	}
}

func writeConfig(app account.App, publicDir string) {
	config.Write(map[string]string{"AppKey": app.AppKey, "PublicDir": publicDir})
}

func writeSession(sessionID string, userID string, accountID string) {
	session.WriteSessionID(sessionID)
	session.WriteUserID(userID)
	session.WriteAccountID(accountID)
}
<commit_msg>Version 0.9.1 - pre-release<commit_after>package main

import (
	"appstax-cli/appstax/account"
	"appstax-cli/appstax/apiclient"
	"appstax-cli/appstax/config"
	"appstax-cli/appstax/fail"
	"appstax-cli/appstax/hosting"
	"appstax-cli/appstax/log"
	"appstax-cli/appstax/session"
	"appstax-cli/appstax/term"
	"fmt"
	"github.com/codegangsta/cli"
	"github.com/skratchdot/open-golang/open"
	"io/ioutil"
	"net/http"
	"os"
	"os/signal"
	"strings"
)

func main() {
	setupSignals()
	commands := setupCommands()
	log.Infof("Command to execute: %s", strings.Join(os.Args, " "))
	term.Section()
	commands.Run(os.Args)
	term.Section()
}

func setupCommands() *cli.App {
	app := cli.NewApp()
	app.Name = "appstax"
	app.Usage = "command line interface for appstax.com"
	app.Version = "0.9.1"

	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "verbose",
			Usage: "enable verbose output",
		},
		cli.StringFlag{
			Name:  "baseurl",
			Usage: "set api base url",
		},
	}

	app.Commands = []cli.Command{
		{
			Name:   "login",
			Usage:  "Login",
			Action: DoLogin,
			Flags:  app.Flags,
		},
		{
			Name:   "init",
			Usage:  "Initialize current directory as an appstax app",
			Action: DoInit,
			Flags:  app.Flags,
		},
		{
			Name:   "info",
			Usage:  "Info about app configured in current directory",
			Action: DoInfo,
			Flags:  app.Flags,
		},
		{
			Name:   "deploy",
			Usage:  "Deploy local files to <yourapp>.appstax.io",
			Action: DoDeploy,
			Flags:  app.Flags,
		},
		{
			Name:   "open",
			Usage:  "Open your browser to the specified destination",
			Action: DoOpen,
			Flags:  app.Flags,
		},
		{
			Name:   "logout",
			Usage:  "Logout of current app session",
			Action: DoLogout,
			Flags:  app.Flags,
		},
		{
			Name:   "serve",
			Usage:  "Run development http server",
			Action: DoServe,
			Flags:  app.Flags,
		},
	}

	return app
}

func setupSignals() {
	c := make(chan os.Signal, 10)
	signal.Notify(c, os.Interrupt)
	go func() {
		for _ = range c {
			fmt.Print("\n")
			os.Exit(-1)
		}
	}()
}

func DoInit(c *cli.Context) {
	useOptions(c)
	loginIfNeeded()
	app := selectApp()
	pub := selectPublicDir()
	writeConfig(app, pub)
	selectSubdomain(app.AppID)
	createPublicDir()
	term.Section()
	term.Println("Now run 'appstax deploy' when you are ready to upload your public files.")
}

func DoInfo(c *cli.Context) {
	useOptions(c)
	loginIfNeeded()
	if !config.Exists() {
		term.Println("No app configured in current directory. (Missing appstax.conf)")
	} else {
		app, err := account.GetCurrentApp()
		fail.Handle(err)
		term.Println("App name:    " + app.AppName)
		term.Println("Description: " + app.AppDescription)
		term.Println("App key:     " + app.AppKey)
		term.Println("Hosting:     " + account.FormatHostingUrl(app))
		term.Section()
	}
	user, err := account.GetUser()
	fail.Handle(err)
	term.Printf("Logged in as %s %s (%s)\n", user.FirstName, user.LastName, user.Email)
}

func DoLogin(c *cli.Context) {
	useOptions(c)
	login()
}

func DoDeploy(c *cli.Context) {
	useOptions(c)
	if !config.Exists() {
		term.Println("Can't find appstax.conf. Run 'appstax init' to initialize before deploying.")
		return
	}
	loginIfNeeded()
	dir := config.Read().PublicDir
	term.Println("Packaging files for upload...")
	archive, bytes := hosting.PrepareArchive(dir)
	term.Printf("Uploading %.2f MB...\n", float64(bytes)/(1024.0*1024.0))
	progress := term.ShowProgressBar(bytes)
	err := hosting.UploadStatic(archive, progress)
	if err != nil {
		term.Section()
		term.Println(err.Error())
	} else {
		progress.Finish()
		term.Section()
		term.Println("Deploy completed!")
	}
}

func DoLogout(c *cli.Context) {
	session.Delete()
	term.Println("Logged out.")
}

func DoOpen(c *cli.Context) {
	useOptions(c)
	dest := c.Args().First()
	log.Debugf("Open destination: %s", dest)
	url := ""
	message := ""

	switch dest {

	case "deployed":
		app, err := account.GetCurrentApp()
		if err != nil {
			message = "Sorry, could not find a deployed app to open."
		}
		url = "http://" + app.HostingSubdomain + ".appstax.io"
		break

	case "admin":
		url = "http://appstax.com/admin/#/dashboard"
		break

	case "local":
		url = "http://localhost:9000/"
		break
	}

	if url != "" {
		term.Printf("Opening %s in your browser.\n", url)
		err := open.Start(url)
		if err != nil {
			message = "Ooops! Something went wrong."
		}
	}

	if message != "" {
		term.Section()
		term.Println(message)
	}
}

func DoServe(c *cli.Context) {
	useOptions(c)
	publicDir := config.Read().PublicDir
	term.Println("Serving your public directory at http://localhost:9000/")
	term.Println("Press Ctrl-C to stop.")
	term.Section()

	http.Handle("/", http.FileServer(http.Dir(publicDir)))
	http.ListenAndServe(":9000", nil)
}

func useOptions(c *cli.Context) {
	log.SetStdoutEnabled(c.GlobalBool("verbose") || c.Bool("verbose"))
	fail.SetPanicMode(c.GlobalBool("verbose") || c.Bool("verbose"))
	apiclient.SetBaseUrl(c.GlobalString("baseurl") + c.String("baseurl"))
}

func loginIfNeeded() {
	if session.ReadSessionID() == "" {
		term.Section()
		term.Println("Please log in:")
		login()
	}
}

func login() {
	for {
		email := term.GetString("Email")
		password := term.GetPassword("Password")
		sessionID, userID, accountID, err := account.Login(email, password)
		if err != nil {
			term.Section()
			term.Println(err.Error())
		} else {
			writeSession(sessionID, userID, accountID)
			term.Section()
			term.Println(fmt.Sprintf("Successfully logged in as '%s'", email))
			return
		}
	}
}

func selectApp() account.App {
	apps, _ := account.GetUserApps()
	selected := 0
	if len(apps) > 1 {
		term.Section()
		term.Println("Choose which app app to configure:")
		for i, app := range apps {
			term.Printf("  %d) %s\n", i+1, app.AppName)
		}
		term.Section()
		selected = -1 + term.GetInt(fmt.Sprintf("Please select app (1-%d)", len(apps)))
	}
	return apps[selected]
}

func selectPublicDir() string {
	dir := term.GetString("Select deployable directory [default: ./public]")
	if dir == "" {
		dir = "./public"
	}
	return dir
}

func selectSubdomain(appID string) {
	app, _ := account.GetAppByID(appID)
	log.Debugf("Subdomain app: %v", app)
	for {
		app.HostingSubdomain = term.GetString("Choose a *.appstax.io subdomain")
		err1 := account.SaveApp(app)
		if err1 != nil {
			term.Println(err1.Error())
		}
		err2 := account.AddCorsOrigin(appID, fmt.Sprintf("http://%s.appstax.io", app.HostingSubdomain))
		if err2 != nil {
			term.Println(err2.Error())
		}
		if err1 == nil && err2 == nil {
			term.Printf("Successfully configured %s.appstax.io\n", app.HostingSubdomain)
			return
		}
	}
}

func createPublicDir() {
	dir := config.Read().PublicDir
	if _, err := os.Stat(dir); os.IsNotExist(err) {
		err = os.MkdirAll(dir, 0700)
		fail.Handle(err)
		ioutil.WriteFile(dir+"/index.html", []byte("<!DOCTYPE html>\n
Your hosting is up and running
\n
Now go make something amazing!
"), 0644)
		log.Debugf("Created public directory '%s'", dir)
	} else {
		log.Debugf("Not creating public directory. '%s' already exists.", dir)
	}
}

func writeConfig(app account.App, publicDir string) {
	config.Write(map[string]string{"AppKey": app.AppKey, "PublicDir": publicDir})
}

func writeSession(sessionID string, userID string, accountID string) {
	session.WriteSessionID(sessionID)
	session.WriteUserID(userID)
	session.WriteAccountID(accountID)
}
<|endoftext|>


<commit_before>/**********************************************************\
|                                                          |
|                          hprose                          |
|                                                          |
| Official WebSite: http://www.hprose.com/                 |
|                   http://www.hprose.org/                 |
|                                                          |
\**********************************************************/
/**********************************************************\
 *                                                        *
 * rpc/stream_service.go                                  *
 *                                                        *
 * hprose stream service for Go.                          *
 *                                                        *
 * LastModified: Sep 13, 2016                             *
 * Author: Ma Bingyao <andot@hprose.com>                  *
 *                                                        *
\**********************************************************/

package rpc

import (
	"bufio"
	"net"
)

// StreamContext is the hprose stream context for service
type StreamContext struct {
	*ServiceContext
	net.Conn
}

type packet struct {
	fullDuplex bool
	id         [4]byte
	body       []byte
	context    *ServiceContext
}

// StreamService is the base service for TcpService and UnixService
type StreamService struct {
	BaseService
}

func (service *StreamService) initSendQueue(
	sendQueue chan packet, conn net.Conn) {
	var data packet
	var err error
	var ok bool
	for {
		data, ok = <-sendQueue
		if !ok {
			conn.Close()
			return
		}
		err = sendDataOverStream(conn, data.body, data.id, data.fullDuplex)
		if err != nil {
			break
		}
	}
	service.fireErrorEvent(err, data.context)
	close(sendQueue)
	conn.Close()
}

func (service *StreamService) onReceived(
	conn net.Conn, data packet, sendQueue chan packet) {
	resp, err := service.Handle(data.body, data.context)
	if err == nil {
		data.body = resp
	} else {
		data.body = service.endError(err, data.context)
	}
	if data.fullDuplex {
		sendQueue <- data
	} else {
		sendDataOverStream(conn, data.body, data.id, data.fullDuplex)
	}
}

func bytesToInt(b [4]byte) int {
	return int(b[0])<<24 | int(b[1])<<16 | int(b[2])<<8 | int(b[3])
}

// ServeConn runs on a single connection. ServeConn blocks, serving the
// connection until the client hangs up. The caller typically invokes ServeConn // in a go statement.
func (service *StreamService) ServeConn(conn net.Conn) {
	var header [4]byte
	var size int
	var data packet
	var err error
	reader := bufio.NewReader(conn)
	sendQueue := make(chan packet, 10)
	go service.initSendQueue(sendQueue, conn)
	for {
		context := &StreamContext{NewServiceContext(nil), conn}
		context.TransportContext = context
		data.context = context.ServiceContext
		if _, err = reader.Read(header[:]); err != nil {
			break
		}
		size = bytesToInt(header)
		data.fullDuplex = (size&0x8000000 != 0)
		if data.fullDuplex {
			size &= 0x7FFFFFF
			data.fullDuplex = true
			if _, err = reader.Read(data.id[:]); err != nil {
				break
			}
		}
		data.body = make([]byte, size)
		if _, err = reader.Read(data.body); err != nil {
			break
		}
		if data.fullDuplex {
			go service.onReceived(conn, data, sendQueue)
		} else {
			service.onReceived(conn, data, sendQueue)
		}
	}
	service.fireErrorEvent(err, data.context)
	close(sendQueue)
	conn.Close()
}
<commit_msg>Improved initSendQueue<commit_after>/**********************************************************\
|                                                          |
|                          hprose                          |
|                                                          |
| Official WebSite: http://www.hprose.com/                 |
|                   http://www.hprose.org/                 |
|                                                          |
\**********************************************************/
/**********************************************************\
 *                                                        *
 * rpc/stream_service.go                                  *
 *                                                        *
 * hprose stream service for Go.                          *
 *                                                        *
 * LastModified: Sep 13, 2016                             *
 * Author: Ma Bingyao <andot@hprose.com>                  *
 *                                                        *
\**********************************************************/

package rpc

import (
	"bufio"
	"net"
)

// StreamContext is the hprose stream context for service
type StreamContext struct {
	*ServiceContext
	net.Conn
}

type packet struct {
	fullDuplex bool
	id         [4]byte
	body       []byte
	context    *ServiceContext
}

// StreamService is the base service for TcpService and UnixService
type StreamService struct {
	BaseService
}

func (service *StreamService) initSendQueue(
	sendQueue chan packet, conn net.Conn) {
	for {
		data, ok := <-sendQueue
		if !ok {
			conn.Close()
			return
		}
		err := sendDataOverStream(conn, data.body, data.id, data.fullDuplex)
		if err != nil {
			service.fireErrorEvent(err, data.context)
			break
		}
	}
	close(sendQueue)
	conn.Close()
}

func (service *StreamService) onReceived(
	conn net.Conn, data packet, sendQueue chan packet) {
	resp, err := service.Handle(data.body, data.context)
	if err == nil {
		data.body = resp
	} else {
		data.body = service.endError(err, data.context)
	}
	if data.fullDuplex {
		sendQueue <- data
	} else {
		sendDataOverStream(conn, data.body, data.id, data.fullDuplex)
	}
}

func bytesToInt(b [4]byte) int {
	return int(b[0])<<24 | int(b[1])<<16 | int(b[2])<<8 | int(b[3])
}

// ServeConn runs on a single connection. ServeConn blocks, serving the
// connection until the client hangs up. The caller typically invokes ServeConn // in a go statement.
func (service *StreamService) ServeConn(conn net.Conn) {
	var header [4]byte
	var size int
	var data packet
	var err error
	reader := bufio.NewReader(conn)
	sendQueue := make(chan packet, 10)
	go service.initSendQueue(sendQueue, conn)
	for {
		context := &StreamContext{NewServiceContext(nil), conn}
		context.TransportContext = context
		data.context = context.ServiceContext
		if _, err = reader.Read(header[:]); err != nil {
			break
		}
		size = bytesToInt(header)
		data.fullDuplex = (size&0x8000000 != 0)
		if data.fullDuplex {
			size &= 0x7FFFFFF
			data.fullDuplex = true
			if _, err = reader.Read(data.id[:]); err != nil {
				break
			}
		}
		data.body = make([]byte, size)
		if _, err = reader.Read(data.body); err != nil {
			break
		}
		if data.fullDuplex {
			go service.onReceived(conn, data, sendQueue)
		} else {
			service.onReceived(conn, data, sendQueue)
		}
	}
	service.fireErrorEvent(err, data.context)
	close(sendQueue)
	conn.Close()
}
<|endoftext|>