<commit_before>package db

import (
	"database/sql"
	"encoding/json"
	"errors"
	"log"
	"os"
	"time"
	//driver for sqlite
	_ "github.com/mattn/go-sqlite3"
)

//SQLDB database
var SQLDB *sql.DB

//SQLPath path do db
var SQLPath string

//Query type
type Query struct {
	Key      int64     `json:"key"`
	Text     string    `json:"text"`
	Type     string    `json:"type"`
	Answer   string    `json:"answer"`
	List     []string  `json:"list"`
	Position int64     `json:"-"`
	Token    string    `json:"token"`
	Priority time.Time `json:"-"`
}

//Charge type
type Charge struct {
	ID    string `json:"charge"`
	Query int64  `json:"query"`
}

//InitDB init sql
func Init() {
	var err error
	var created = false
	//check for the sqlite file
	if _, err := os.Stat("./db.sqlite"); os.IsNotExist(err) {
		log.Println("Creating database file")
		_, err := os.Create("./db.sqlite")
		if err != nil {
			log.Fatal("Failed to create SQLite file")
		}
		created = true
	}
	//Prepare DB
	SQLPath = "./db.sqlite"
	SQLDB, err = sql.Open("sqlite3", SQLPath)
	if err != nil {
		log.Fatal(err)
		log.Fatal("Database setup failed.")
	}
	//create tables if necessary
	if created {
		CreateTables()
	}
	//load links
	initLinks()
}

//ResetDB remove existing database and recreate tables
func ResetDB() {
	//remove existing dataBasePath file
	os.Remove("./db.sqlite")
	Init()
}

//CreateTables create the user and posts tables
func CreateTables() {
	createTables := `
	CREATE TABLE queries (
		key integer primary key autoincrement,
		text varchar(255) not null,
		type varchar(20) not null,
		priority timestamp
	);
	CREATE TABLE resolved (
		key integer primary key not null,
		text varchar(255) not null,
		type varchar(20) not null,
		answer varchar(800) null,
		list varchar(2400) null
	);
	CREATE TABLE charges (
		key varchar(255) primary key
	);
	DELETE from queries;
  DELETE from resolved;
	DELETE from charges;
	`
	//Create the users table
	_, err := SQLDB.Exec(createTables)
	if err != nil {
		log.Println(err)
		log.Fatal("Unable to create database")
	}
	log.Println("Created SQL Tables")
}

//AddQuery add a new query to the db
func AddQuery(q Query) (int64, error) {
	//prepare the insert statement for adding a user
	insert, err := SQLDB.Prepare("INSERT into queries(text, type, priority) values(?, ?, ?)")
	if err != nil {
		return 0, errors.New("Error creating Query insert")
	}
	//insert
	result, err := insert.Exec(q.Text, q.Type, nil)
	if err != nil {
		return 0, errors.New("Failed to add Query")
	}
	//get ID to return
	id, err := result.LastInsertId()
	return id, nil
}

//GetQueue get the n top queries in the queue
func GetQueue(num int) ([]Query, error) {
	queries := []Query{}
	q := Query{}
	//create sql query
	rows, err := SQLDB.Query("SELECT key,text,type FROM queries ORDER BY datetime(priority) DESC LIMIT (?)", num)
	defer rows.Close() //close query connection when function returns
	if err != nil {
		return queries, errors.New("Error getting queue")
	}
	for rows.Next() {
		err = rows.Scan(&q.Key, &q.Text, &q.Type)
		if err != nil {
			return queries, errors.New("Error scanning row")
		}
		queries = append(queries, q)
	}

	return queries, nil
}

//AnswerQuery move a query to the resolved table with jimmy's answer
func AnswerQuery(key int64, answer string, list string) error {
	q := Query{}

	tx, err := SQLDB.Begin() //start transaction
	if err != nil {
		return errors.New("Could not establish transaction")
	}
	//get the query
	err = tx.QueryRow("SELECT text,type FROM queries WHERE key=(?)", key).Scan(&q.Text, &q.Type)
	if err != nil {
		tx.Rollback()
		return errors.New("Could not find query")
	}
	//add to resolved
	insert, err := tx.Prepare("INSERT into resolved(key, text, type, answer, list) values(?, ?, ?, ?, ?)")
	if err != nil {
		tx.Rollback()
		return errors.New("Error creating Resolved insert")
	}
	_, err = insert.Exec(key, q.Text, q.Type, answer, list)
	if err != nil {
		tx.Rollback()
		return errors.New("Failed to add to resolved")
	}
	//delete from queries
	delete, err := tx.Prepare("DELETE from queries WHERE key=(?)")
	_, err = delete.Exec(key)
	if err != nil {
		tx.Rollback()
		return errors.New("Failed to delete query")
	}
	tx.Commit()
	return nil
}

//AddCharge adds a charge to the database and errors if charge exists
func AddCharge(key string) error {
	var c Charge
	err := SQLDB.QueryRow("SELECT key FROM charges WHERE key=?", key, 1).Scan(&c.ID)

	if err == nil {
		return errors.New("Charge already exists")
	}

	insert, err := SQLDB.Prepare("INSERT into charges(key) values(?)")
	if err != nil {
		return errors.New("Error creating Charge insert")
	}
	//insert
	_, err = insert.Exec(key)
	if err != nil {
		return errors.New("Failed to add Charge")
	}

	return nil
}

//MoveToFront moves a query to the front of the queue
func MoveToFront(key int64) error {
	update, err := SQLDB.Prepare("UPDATE queries SET priority=? WHERE key=?")
	if err != nil {
		return err
	}

	timestamp := time.Now()
	_, err = update.Exec(timestamp, key)
	log.Println("A user has paid.")

	if err != nil {
		return errors.New("Failed to move query to the pront of the queue")
	}

	return nil
}

//getQueuePosition return the queue position of a query
func getQueuePosition(key int64) (int64, error) {
	var err error
	var count int64
	var priority sql.NullString

	SQLDB.QueryRow("SELECT priority FROM queries WHERE key = (?)", key).Scan(&priority)

	if priority.Valid {
		// This is a paid query and can be compared as such
		err = SQLDB.QueryRow("SELECT COUNT(1) FROM queries WHERE datetime(priority) > datetime((?))", priority).Scan(&count)
	} else {
		// This is an unpaid query and need to be
		err = SQLDB.QueryRow("SELECT COUNT(1) FROM queries WHERE priority IS NOT NULL OR key < (?)", key).Scan(&count)
	}

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

	return count, nil
}

//CheckQuery see if a query is resolved and return the answer
func CheckQuery(key int64) (Query, error) {
	var list string
	q := Query{}
	//select from resolved
	err := SQLDB.QueryRow("SELECT * FROM resolved WHERE key=(?)", key).Scan(&q.Key, &q.Text, &q.Type, &q.Answer, &list)
	if err != nil {
		//get position
		q.Position, err = getQueuePosition(key)
		if err != nil {
			//we did not get the position
			return q, errors.New("Error getting queue position")
		}
		return q, errors.New("Query is not resolved")
	}
	//convert list to actual list
	err = json.Unmarshal([]byte(list), &q.List)
	if err != nil {
		q.List = nil
	}
	return q, nil
}

//GetRecent get the recently resolved posts
func GetRecent(num int) ([]Query, error) {
	resolved := []Query{}
	r := Query{}
	//create sql query
	rows, err := SQLDB.Query("SELECT key,text,type,answer FROM resolved ORDER BY key DESC LIMIT (?)", num)
	defer rows.Close() //close query connection when function returns
	if err != nil {
		return resolved, errors.New("Error getting recently resolved")
	}
	for rows.Next() {
		err = rows.Scan(&r.Key, &r.Text, &r.Type, &r.Answer)
		if err != nil {
			return resolved, errors.New("Error scanning row")
		}
		resolved = append(resolved, r)
	}

	return resolved, nil
}

//GetQuestion get a question by query id
func GetQuestion(key int64) (Query, error) {
	q := Query{}
	//get the query
	err := SQLDB.QueryRow("SELECT key,text,type FROM queries WHERE key=(?)", key).Scan(&q.Key, &q.Text, &q.Type)
	if err != nil {
		//not found in queries table so check resolved table
		err := SQLDB.QueryRow("SELECT key,text,type FROM resolved WHERE key=(?)", key).Scan(&q.Key, &q.Text, &q.Type)
		if err != nil {
			//the query is not in either table
			return q, errors.New("Could not find question")
		}
	}
	return q, nil
}
<commit_msg>Including URL lists with api/recents endpoint response<commit_after>package db

import (
	"database/sql"
	"encoding/json"
	"errors"
	"log"
	"os"
	"time"
	//driver for sqlite
	_ "github.com/mattn/go-sqlite3"
)

//SQLDB database
var SQLDB *sql.DB

//SQLPath path do db
var SQLPath string

//Query type
type Query struct {
	Key      int64     `json:"key"`
	Text     string    `json:"text"`
	Type     string    `json:"type"`
	Answer   string    `json:"answer"`
	List     []string  `json:"list"`
	Position int64     `json:"-"`
	Token    string    `json:"token"`
	Priority time.Time `json:"-"`
}

//Charge type
type Charge struct {
	ID    string `json:"charge"`
	Query int64  `json:"query"`
}

//InitDB init sql
func Init() {
	var err error
	var created = false
	//check for the sqlite file
	if _, err := os.Stat("./db.sqlite"); os.IsNotExist(err) {
		log.Println("Creating database file")
		_, err := os.Create("./db.sqlite")
		if err != nil {
			log.Fatal("Failed to create SQLite file")
		}
		created = true
	}
	//Prepare DB
	SQLPath = "./db.sqlite"
	SQLDB, err = sql.Open("sqlite3", SQLPath)
	if err != nil {
		log.Fatal(err)
		log.Fatal("Database setup failed.")
	}
	//create tables if necessary
	if created {
		CreateTables()
	}
	//load links
	initLinks()
}

//ResetDB remove existing database and recreate tables
func ResetDB() {
	//remove existing dataBasePath file
	os.Remove("./db.sqlite")
	Init()
}

//CreateTables create the user and posts tables
func CreateTables() {
	createTables := `
	CREATE TABLE queries (
		key integer primary key autoincrement,
		text varchar(255) not null,
		type varchar(20) not null,
		priority timestamp
	);
	CREATE TABLE resolved (
		key integer primary key not null,
		text varchar(255) not null,
		type varchar(20) not null,
		answer varchar(800) null,
		list varchar(2400) null
	);
	CREATE TABLE charges (
		key varchar(255) primary key
	);
	DELETE from queries;
  DELETE from resolved;
	DELETE from charges;
	`
	//Create the users table
	_, err := SQLDB.Exec(createTables)
	if err != nil {
		log.Println(err)
		log.Fatal("Unable to create database")
	}
	log.Println("Created SQL Tables")
}

//AddQuery add a new query to the db
func AddQuery(q Query) (int64, error) {
	//prepare the insert statement for adding a user
	insert, err := SQLDB.Prepare("INSERT into queries(text, type, priority) values(?, ?, ?)")
	if err != nil {
		return 0, errors.New("Error creating Query insert")
	}
	//insert
	result, err := insert.Exec(q.Text, q.Type, nil)
	if err != nil {
		return 0, errors.New("Failed to add Query")
	}
	//get ID to return
	id, err := result.LastInsertId()
	return id, nil
}

//GetQueue get the n top queries in the queue
func GetQueue(num int) ([]Query, error) {
	queries := []Query{}
	q := Query{}
	//create sql query
	rows, err := SQLDB.Query("SELECT key,text,type FROM queries ORDER BY datetime(priority) DESC LIMIT (?)", num)
	defer rows.Close() //close query connection when function returns
	if err != nil {
		return queries, errors.New("Error getting queue")
	}
	for rows.Next() {
		err = rows.Scan(&q.Key, &q.Text, &q.Type)
		if err != nil {
			return queries, errors.New("Error scanning row")
		}
		queries = append(queries, q)
	}

	return queries, nil
}

//AnswerQuery move a query to the resolved table with jimmy's answer
func AnswerQuery(key int64, answer string, list string) error {
	q := Query{}

	tx, err := SQLDB.Begin() //start transaction
	if err != nil {
		return errors.New("Could not establish transaction")
	}
	//get the query
	err = tx.QueryRow("SELECT text,type FROM queries WHERE key=(?)", key).Scan(&q.Text, &q.Type)
	if err != nil {
		tx.Rollback()
		return errors.New("Could not find query")
	}
	//add to resolved
	insert, err := tx.Prepare("INSERT into resolved(key, text, type, answer, list) values(?, ?, ?, ?, ?)")
	if err != nil {
		tx.Rollback()
		return errors.New("Error creating Resolved insert")
	}
	_, err = insert.Exec(key, q.Text, q.Type, answer, list)
	if err != nil {
		tx.Rollback()
		return errors.New("Failed to add to resolved")
	}
	//delete from queries
	delete, err := tx.Prepare("DELETE from queries WHERE key=(?)")
	_, err = delete.Exec(key)
	if err != nil {
		tx.Rollback()
		return errors.New("Failed to delete query")
	}
	tx.Commit()
	return nil
}

//AddCharge adds a charge to the database and errors if charge exists
func AddCharge(key string) error {
	var c Charge
	err := SQLDB.QueryRow("SELECT key FROM charges WHERE key=?", key, 1).Scan(&c.ID)

	if err == nil {
		return errors.New("Charge already exists")
	}

	insert, err := SQLDB.Prepare("INSERT into charges(key) values(?)")
	if err != nil {
		return errors.New("Error creating Charge insert")
	}
	//insert
	_, err = insert.Exec(key)
	if err != nil {
		return errors.New("Failed to add Charge")
	}

	return nil
}

//MoveToFront moves a query to the front of the queue
func MoveToFront(key int64) error {
	update, err := SQLDB.Prepare("UPDATE queries SET priority=? WHERE key=?")
	if err != nil {
		return err
	}

	timestamp := time.Now()
	_, err = update.Exec(timestamp, key)
	log.Println("A user has paid.")

	if err != nil {
		return errors.New("Failed to move query to the pront of the queue")
	}

	return nil
}

//getQueuePosition return the queue position of a query
func getQueuePosition(key int64) (int64, error) {
	var err error
	var count int64
	var priority sql.NullString

	SQLDB.QueryRow("SELECT priority FROM queries WHERE key = (?)", key).Scan(&priority)

	if priority.Valid {
		// This is a paid query and can be compared as such
		err = SQLDB.QueryRow("SELECT COUNT(1) FROM queries WHERE datetime(priority) > datetime((?))", priority).Scan(&count)
	} else {
		// This is an unpaid query and need to be
		err = SQLDB.QueryRow("SELECT COUNT(1) FROM queries WHERE priority IS NOT NULL OR key < (?)", key).Scan(&count)
	}

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

	return count, nil
}

//CheckQuery see if a query is resolved and return the answer
func CheckQuery(key int64) (Query, error) {
	var list string
	q := Query{}
	//select from resolved
	err := SQLDB.QueryRow("SELECT * FROM resolved WHERE key=(?)", key).Scan(&q.Key, &q.Text, &q.Type, &q.Answer, &list)
	if err != nil {
		//get position
		q.Position, err = getQueuePosition(key)
		if err != nil {
			//we did not get the position
			return q, errors.New("Error getting queue position")
		}
		return q, errors.New("Query is not resolved")
	}
	//convert list to actual list
	err = json.Unmarshal([]byte(list), &q.List)
	if err != nil {
		q.List = nil
	}
	return q, nil
}

//GetRecent get the recently resolved posts
func GetRecent(num int) ([]Query, error) {
	var list string
	resolved := []Query{}
	r := Query{}
	//create sql query
	rows, err := SQLDB.Query("SELECT key,text,type,answer,list FROM resolved ORDER BY key DESC LIMIT (?)", num)
	defer rows.Close() //close query connection when function returns
	if err != nil {
		return resolved, errors.New("Error getting recently resolved")
	}
	for rows.Next() {
		r = Query{}
		err = rows.Scan(&r.Key, &r.Text, &r.Type, &r.Answer, &list)
		if err != nil {
			return resolved, errors.New("Error scanning row")
		}
		//convert list to actual list
		err = json.Unmarshal([]byte(list), &r.List)
		if err != nil {
			r.List = nil
		}
		resolved = append(resolved, r)
	}

	return resolved, nil
}

//GetQuestion get a question by query id
func GetQuestion(key int64) (Query, error) {
	q := Query{}
	//get the query
	err := SQLDB.QueryRow("SELECT key,text,type FROM queries WHERE key=(?)", key).Scan(&q.Key, &q.Text, &q.Type)
	if err != nil {
		//not found in queries table so check resolved table
		err := SQLDB.QueryRow("SELECT key,text,type FROM resolved WHERE key=(?)", key).Scan(&q.Key, &q.Text, &q.Type)
		if err != nil {
			//the query is not in either table
			return q, errors.New("Could not find question")
		}
	}
	return q, nil
}
<|endoftext|>


<commit_before>package bigregion

import (
	"math/big"
	"testing"
	"github.com/johnny-morrice/godelbrot/base"
	"github.com/johnny-morrice/godelbrot/bigbase"
	"github.com/johnny-morrice/godelbrot/region"
	"github.com/johnny-morrice/godelbrot/nativeregion"
	"github.com/johnny-morrice/godelbrot/nativebase"
)

const prec = 53

func TestRegionSplitPos(t *testing.T) {
	helper := bigRegionSplitHelper{
		left:   bigbase.MakeBigFloat(1.0, prec),
		right:  bigbase.MakeBigFloat(3.0, prec),
		top:    bigbase.MakeBigFloat(3.0, prec),
		bottom: bigbase.MakeBigFloat(1.0, prec),
		midR:   bigbase.MakeBigFloat(2.0, prec),
		midI:   bigbase.MakeBigFloat(2.0, prec),
	}

	testRegionSplit(helper, t)
}

func TestRegionSplitNeg(t *testing.T) {
	helper := bigRegionSplitHelper{
		left:   bigbase.MakeBigFloat(-100.0, prec),
		right:  bigbase.MakeBigFloat(-24.0, prec),
		top:    bigbase.MakeBigFloat(-10.0, prec),
		bottom: bigbase.MakeBigFloat(-340.0, prec),
		midR:   bigbase.MakeBigFloat(-62.0, prec),
		midI:   bigbase.MakeBigFloat(-175.0, prec),
	}

	testRegionSplit(helper, t)
}

func TestRegionSplitNegPos(t *testing.T) {
	helper := bigRegionSplitHelper{
		left:   bigbase.MakeBigFloat(-100.0, prec),
		right:  bigbase.MakeBigFloat(24.0, prec),
		top:    bigbase.MakeBigFloat(10.0, prec),
		bottom: bigbase.MakeBigFloat(-340.0, prec),
		midR:   bigbase.MakeBigFloat(-38.0, prec),
		midI:   bigbase.MakeBigFloat(-165.0, prec),
	}

	testRegionSplit(helper, t)
}

func TestChildrenPopulated(t *testing.T) {
	const childCount = 4

	numerics := BigRegionNumerics{
		subregion: bigSubregion{
			populated: true,
			// We are not inspecting the children here
			children: make([]bigRegion, childCount),
		},
	}
	children := numerics.Children()

	actualChildren := len(children)
	if actualChildren != childCount {
		t.Error("Expected", childCount, "but received", actualChildren)
	}
}

func TestChildrenEmpty(t *testing.T) {
	numerics := BigRegionNumerics{}

	recovered := false
	triggerPanic := func() {
		defer func() {
			r := recover()
			recovered = r != nil
		}()
		numerics.Children()
	}

	triggerPanic()

	if !recovered {
		t.Error("Expected panic e.g. \"Error when raising error\"")
	}
}

func TestMandelbrotPoints(t *testing.T) {
	numerics := BigRegionNumerics{}

	points := numerics.MandelbrotPoints()

	expectedPoints := 5
	actualPoints := len(points)

	if expectedPoints != actualPoints {
		t.Error("Expected to receive", expectedPoints, "but received", actualPoints)
	}
}

func TestRect(t *testing.T) {
	left := -1.0
	bottom := -1.0
	right := 1.0
	top := 1.0

	app := &MockRenderApplication{}
	app.UserMin = bigbase.MakeBigComplex(left, bottom, prec)
	app.UserMax = bigbase.MakeBigComplex(right, top, prec)
	app.Prec = 53
	app.PictureWidth = 2
	app.PictureHeight = 2

	numerics := Make(app)

	expectMinX := 0
	expectMaxX := 2
	expectMinY := 0
	expectMaxY := 2

	r := numerics.Rect()

	okay := expectMinX == r.Min.X
	okay = okay && expectMaxX == r.Max.X
	okay = okay && expectMinY == r.Min.Y
	okay = okay && expectMaxY == r.Max.Y
	if !okay {
		t.Error("Rectangle had unexpected bounds", r)
	}
}

func testRegionSplit(helper bigRegionSplitHelper, t *testing.T) {
	const iterlim = 255
	parent := bigbase.BigBaseNumerics{}
	parent.Precision = prec
	parent.SqrtDivergeLimit = parent.MakeBigFloat(2.0)
	parent.IterateLimit = iterlim

	initMin := bigbase.BigComplex{helper.left, helper.bottom}
	initMax := bigbase.BigComplex{helper.right, helper.top}

	topLeftMin := bigbase.BigComplex{helper.left, helper.midI}
	topLeftMax := bigbase.BigComplex{helper.midR, helper.top}

	topRightMin := bigbase.BigComplex{helper.midR, helper.midI}
	topRightMax := bigbase.BigComplex{helper.right, helper.top}

	bottomLeftMin := bigbase.BigComplex{helper.left, helper.bottom}
	bottomLeftMax := bigbase.BigComplex{helper.midR, helper.midI}

	bottomRightMin := bigbase.BigComplex{helper.midR, helper.bottom}
	bottomRightMax := bigbase.BigComplex{helper.right, helper.midI}

	subjectRegion := createBigRegion(parent, initMin, initMax)

	expected := []bigRegion{
		createBigRegion(parent, topLeftMin, topLeftMax),
		createBigRegion(parent, topRightMin, topRightMax),
		createBigRegion(parent, bottomLeftMin, bottomLeftMax),
		createBigRegion(parent, bottomRightMin, bottomRightMax),
	}

	numerics := BigRegionNumerics{}
	numerics.BigBaseNumerics = parent
	numerics.Region = subjectRegion
	numerics.Split()
	actualChildren := numerics.subregion.children

	for i, expectReg := range expected {
		actReg := actualChildren[i]
		exPoints := expectReg.points()
		acPoints := actReg.points()

		fail := false
		for j, ep := range exPoints {
			ap := acPoints[j]
			okay := bigbase.BigComplexEq(ep.C, ap.C)
			if !okay {
				fail = true
				t.Log("Region", i, "error at point", j,
					"\nexpected\t", bigbase.DbgC(*ep.C),
					"\nbut received\t", bigbase.DbgC(*ap.C))
			}
		}
		if fail {
			t.Fail()
		}
	}
}

type bigRegionSplitHelper struct {
	left   big.Float
	right  big.Float
	bottom big.Float
	top    big.Float
	midR   big.Float
	midI   big.Float
}

type fRegFactory func() region.RegionNumerics

var _ region.RegionNumericsFactory = fRegFactory(func () region.RegionNumerics { return nil })

func (f fRegFactory) Build() region.RegionNumerics {
	return f()
}

func TestSampleDivs(t *testing.T) {
	const pWidth = 100
	const pHeight = 100
	const iLimit = 255
	const dLimit = 1.42
	const maxRegSz = 10
	const samples = 100
	const natMin = complex(-2.0, -2.0)
	const natMax = complex(2.0, 2.0)
	const prec = 53

	bigMin := bigbase.MakeBigComplex(real(natMin), imag(natMax), prec)
	bigMax := bigbase.MakeBigComplex(real(natMax), imag(natMax), prec)

	mockBase := base.MockRenderApplication{}
	mockBase.PictureWidth = pWidth
	mockBase.PictureHeight = pHeight
	mockBase.Base.IterateLimit = iLimit
	mockBase.Base.DivergeLimit = dLimit
	mockBase.Base.FixAspect = true

	regConfig := region.RegionConfig{}
	regConfig.CollapseSize = maxRegSz
	regConfig.Samples = samples

	bigCoords := bigbase.MockBigCoordProvider{}
	bigCoords.UserMin = bigMin
	bigCoords.UserMax = bigMax
	bigCoords.Prec = prec

	bigProvider := region.MockRegionProvider{}
	bigProvider.RegConfig = regConfig
	bigProvider.RegionFactory = fRegFactory(func () region.RegionNumerics {
		app := &MockRenderApplication{}
		app.MockRegionProvider = bigProvider
		app.MockRenderApplication = mockBase
		app.MockBigCoordProvider = bigCoords
		bignums := Make(app)
		return &bignums
	})

	nativeCoords := nativebase.MockNativeCoordProvider{}
	nativeCoords.PlaneMin = natMin
	nativeCoords.PlaneMax = natMax

	nativeProvider := region.MockRegionProvider{}
	nativeProvider.RegConfig = regConfig
	nativeProvider.RegionFactory = fRegFactory(func () region.RegionNumerics {
		app := &nativeregion.MockRenderApplication{}
		app.MockNativeCoordProvider = nativeCoords
		app.MockRegionProvider = nativeProvider
		app.MockRenderApplication = mockBase
		natnums := nativeregion.Make(app)
		return &natnums
	})

	bReg := bigProvider.RegionFactory.Build()
	nReg := bigProvider.RegionFactory.Build()

	bich, _ := bReg.SampleDivs()
	nich, _ := nReg.SampleDivs()
	bs := slurp(bich)
	ns := slurp(nich)

	for i, bInvDiv := range bs {
		nInvDiv := ns[i]
		if bInvDiv != nInvDiv {
			t.Error("Mismatch InvDiv at sample ", i,
				"native was", nInvDiv, "but big was", bInvDiv)
		}
	}
}

func slurp(idivch <-chan uint8) []uint8 {
	out := []uint8{}
	for idiv := range idivch {
		out = append(out, idiv)
	}
	return out
}<commit_msg>Add comment<commit_after>package bigregion

import (
	"math/big"
	"testing"
	"github.com/johnny-morrice/godelbrot/base"
	"github.com/johnny-morrice/godelbrot/bigbase"
	"github.com/johnny-morrice/godelbrot/region"
	"github.com/johnny-morrice/godelbrot/nativeregion"
	"github.com/johnny-morrice/godelbrot/nativebase"
)

const prec = 53

func TestRegionSplitPos(t *testing.T) {
	helper := bigRegionSplitHelper{
		left:   bigbase.MakeBigFloat(1.0, prec),
		right:  bigbase.MakeBigFloat(3.0, prec),
		top:    bigbase.MakeBigFloat(3.0, prec),
		bottom: bigbase.MakeBigFloat(1.0, prec),
		midR:   bigbase.MakeBigFloat(2.0, prec),
		midI:   bigbase.MakeBigFloat(2.0, prec),
	}

	testRegionSplit(helper, t)
}

func TestRegionSplitNeg(t *testing.T) {
	helper := bigRegionSplitHelper{
		left:   bigbase.MakeBigFloat(-100.0, prec),
		right:  bigbase.MakeBigFloat(-24.0, prec),
		top:    bigbase.MakeBigFloat(-10.0, prec),
		bottom: bigbase.MakeBigFloat(-340.0, prec),
		midR:   bigbase.MakeBigFloat(-62.0, prec),
		midI:   bigbase.MakeBigFloat(-175.0, prec),
	}

	testRegionSplit(helper, t)
}

func TestRegionSplitNegPos(t *testing.T) {
	helper := bigRegionSplitHelper{
		left:   bigbase.MakeBigFloat(-100.0, prec),
		right:  bigbase.MakeBigFloat(24.0, prec),
		top:    bigbase.MakeBigFloat(10.0, prec),
		bottom: bigbase.MakeBigFloat(-340.0, prec),
		midR:   bigbase.MakeBigFloat(-38.0, prec),
		midI:   bigbase.MakeBigFloat(-165.0, prec),
	}

	testRegionSplit(helper, t)
}

func TestChildrenPopulated(t *testing.T) {
	const childCount = 4

	numerics := BigRegionNumerics{
		subregion: bigSubregion{
			populated: true,
			// We are not inspecting the children here
			children: make([]bigRegion, childCount),
		},
	}
	children := numerics.Children()

	actualChildren := len(children)
	if actualChildren != childCount {
		t.Error("Expected", childCount, "but received", actualChildren)
	}
}

func TestChildrenEmpty(t *testing.T) {
	numerics := BigRegionNumerics{}

	recovered := false
	triggerPanic := func() {
		defer func() {
			r := recover()
			recovered = r != nil
		}()
		numerics.Children()
	}

	triggerPanic()

	if !recovered {
		t.Error("Expected panic e.g. \"Error when raising error\"")
	}
}

func TestMandelbrotPoints(t *testing.T) {
	numerics := BigRegionNumerics{}

	points := numerics.MandelbrotPoints()

	expectedPoints := 5
	actualPoints := len(points)

	if expectedPoints != actualPoints {
		t.Error("Expected to receive", expectedPoints, "but received", actualPoints)
	}
}

func TestRect(t *testing.T) {
	left := -1.0
	bottom := -1.0
	right := 1.0
	top := 1.0

	app := &MockRenderApplication{}
	app.UserMin = bigbase.MakeBigComplex(left, bottom, prec)
	app.UserMax = bigbase.MakeBigComplex(right, top, prec)
	app.Prec = 53
	app.PictureWidth = 2
	app.PictureHeight = 2

	numerics := Make(app)

	expectMinX := 0
	expectMaxX := 2
	expectMinY := 0
	expectMaxY := 2

	r := numerics.Rect()

	okay := expectMinX == r.Min.X
	okay = okay && expectMaxX == r.Max.X
	okay = okay && expectMinY == r.Min.Y
	okay = okay && expectMaxY == r.Max.Y
	if !okay {
		t.Error("Rectangle had unexpected bounds", r)
	}
}

func testRegionSplit(helper bigRegionSplitHelper, t *testing.T) {
	const iterlim = 255
	parent := bigbase.BigBaseNumerics{}
	parent.Precision = prec
	parent.SqrtDivergeLimit = parent.MakeBigFloat(2.0)
	parent.IterateLimit = iterlim

	initMin := bigbase.BigComplex{helper.left, helper.bottom}
	initMax := bigbase.BigComplex{helper.right, helper.top}

	topLeftMin := bigbase.BigComplex{helper.left, helper.midI}
	topLeftMax := bigbase.BigComplex{helper.midR, helper.top}

	topRightMin := bigbase.BigComplex{helper.midR, helper.midI}
	topRightMax := bigbase.BigComplex{helper.right, helper.top}

	bottomLeftMin := bigbase.BigComplex{helper.left, helper.bottom}
	bottomLeftMax := bigbase.BigComplex{helper.midR, helper.midI}

	bottomRightMin := bigbase.BigComplex{helper.midR, helper.bottom}
	bottomRightMax := bigbase.BigComplex{helper.right, helper.midI}

	subjectRegion := createBigRegion(parent, initMin, initMax)

	expected := []bigRegion{
		createBigRegion(parent, topLeftMin, topLeftMax),
		createBigRegion(parent, topRightMin, topRightMax),
		createBigRegion(parent, bottomLeftMin, bottomLeftMax),
		createBigRegion(parent, bottomRightMin, bottomRightMax),
	}

	numerics := BigRegionNumerics{}
	numerics.BigBaseNumerics = parent
	numerics.Region = subjectRegion
	numerics.Split()
	actualChildren := numerics.subregion.children

	for i, expectReg := range expected {
		actReg := actualChildren[i]
		exPoints := expectReg.points()
		acPoints := actReg.points()

		fail := false
		for j, ep := range exPoints {
			ap := acPoints[j]
			okay := bigbase.BigComplexEq(ep.C, ap.C)
			if !okay {
				fail = true
				t.Log("Region", i, "error at point", j,
					"\nexpected\t", bigbase.DbgC(*ep.C),
					"\nbut received\t", bigbase.DbgC(*ap.C))
			}
		}
		if fail {
			t.Fail()
		}
	}
}

type bigRegionSplitHelper struct {
	left   big.Float
	right  big.Float
	bottom big.Float
	top    big.Float
	midR   big.Float
	midI   big.Float
}

type fRegFactory func() region.RegionNumerics

var _ region.RegionNumericsFactory = fRegFactory(func () region.RegionNumerics { return nil })

func (f fRegFactory) Build() region.RegionNumerics {
	return f()
}

func TestSampleDivs(t *testing.T) {
	const pWidth = 100
	const pHeight = 100
	const iLimit = 255
	const dLimit = 1.42
	const maxRegSz = 10
	const samples = 100
	const natMin = complex(-2.0, -2.0)
	const natMax = complex(2.0, 2.0)
	const prec = 53

	bigMin := bigbase.MakeBigComplex(real(natMin), imag(natMax), prec)
	bigMax := bigbase.MakeBigComplex(real(natMax), imag(natMax), prec)

	mockBase := base.MockRenderApplication{}
	mockBase.PictureWidth = pWidth
	mockBase.PictureHeight = pHeight
	mockBase.Base.IterateLimit = iLimit
	mockBase.Base.DivergeLimit = dLimit
	mockBase.Base.FixAspect = true

	regConfig := region.RegionConfig{}
	regConfig.CollapseSize = maxRegSz
	regConfig.Samples = samples

	bigCoords := bigbase.MockBigCoordProvider{}
	bigCoords.UserMin = bigMin
	bigCoords.UserMax = bigMax
	bigCoords.Prec = prec

	// This business is over complicated
	bigProvider := region.MockRegionProvider{}
	bigProvider.RegConfig = regConfig
	bigProvider.RegionFactory = fRegFactory(func () region.RegionNumerics {
		app := &MockRenderApplication{}
		app.MockRegionProvider = bigProvider
		app.MockRenderApplication = mockBase
		app.MockBigCoordProvider = bigCoords
		bignums := Make(app)
		return &bignums
	})

	nativeCoords := nativebase.MockNativeCoordProvider{}
	nativeCoords.PlaneMin = natMin
	nativeCoords.PlaneMax = natMax

	nativeProvider := region.MockRegionProvider{}
	nativeProvider.RegConfig = regConfig
	nativeProvider.RegionFactory = fRegFactory(func () region.RegionNumerics {
		app := &nativeregion.MockRenderApplication{}
		app.MockNativeCoordProvider = nativeCoords
		app.MockRegionProvider = nativeProvider
		app.MockRenderApplication = mockBase
		natnums := nativeregion.Make(app)
		return &natnums
	})

	bReg := bigProvider.RegionFactory.Build()
	nReg := bigProvider.RegionFactory.Build()

	bich, _ := bReg.SampleDivs()
	nich, _ := nReg.SampleDivs()
	bs := slurp(bich)
	ns := slurp(nich)

	for i, bInvDiv := range bs {
		nInvDiv := ns[i]
		if bInvDiv != nInvDiv {
			t.Error("Mismatch InvDiv at sample ", i,
				"native was", nInvDiv, "but big was", bInvDiv)
		}
	}
}

func slurp(idivch <-chan uint8) []uint8 {
	out := []uint8{}
	for idiv := range idivch {
		out = append(out, idiv)
	}
	return out
}<|endoftext|>


<commit_before>package main

import (
	"flag"
	"os"
	"runtime/pprof"

	"github.com/AsynkronIT/protoactor-go/actor"

	"log"
	"sync"

	"runtime"
	"time"
)

type Msg struct {
	replyTo *actor.PID
}
type Start struct {
	Sender *actor.PID
}
type Started struct{}

type clientActor struct {
	count        int
	wgStop       *sync.WaitGroup
	messageCount int
}

func (state *clientActor) Receive(context actor.Context) {
	switch msg := context.Message().(type) {
	case *Start:
		sender := msg.Sender
		m := &Msg{
			replyTo: context.Self(),
		}
		for i := 0; i < state.messageCount; i++ {
			sender.Tell(m)
		}
	case *Msg:
		state.count++
		// if state.count%500000 == 0 {
		// 	log.Println(state.count)
		// }
		if state.count == state.messageCount {
			state.wgStop.Done()
		}
	}
}

func newLocalActor(stop *sync.WaitGroup, messageCount int) actor.Producer {
	return func() actor.Actor {
		return &clientActor{
			wgStop:       stop,
			messageCount: messageCount,
		}
	}
}

var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
var blockProfile = flag.String("blockprof", "", "execute contention profiling and save results here")

func main() {
	flag.Parse()
	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	// Check for lock contention profiling
	if *blockProfile != "" {
		prof, err := os.Create(*blockProfile)
		if err != nil {
			log.Fatal(err)
		}
		runtime.SetBlockProfileRate(1)
		defer func() {
			pprof.Lookup("block").WriteTo(prof, 0)
		}()
	}

	runtime.GOMAXPROCS(runtime.NumCPU())
	runtime.GC()

	var wg sync.WaitGroup

	messageCount := 1000000
	tps := []int{300, 400, 500, 600, 700, 800, 900}
	log.Println("Dispatcher Throughput			Elapsed Time			Messages per sec")
	for _, tp := range tps {

		d := actor.NewDefaultDispatcher(tp)

		clientProps := actor.
			FromProducer(newLocalActor(&wg, messageCount)).
			WithMailbox(actor.NewUnboundedMailbox()).
			WithDispatcher(d)

		echoProps := actor.
			FromFunc(
				func(context actor.Context) {
					switch msg := context.Message().(type) {
					case *Msg:
						msg.replyTo.Tell(msg)
					}
				}).
			WithMailbox(actor.NewUnboundedMailbox()).
			WithDispatcher(d)

		clients := make([]*actor.PID, 0)
		echos := make([]*actor.PID, 0)
		clientCount := runtime.NumCPU() * 2
		for i := 0; i < clientCount; i++ {
			client := actor.Spawn(clientProps)
			echo := actor.Spawn(echoProps)
			clients = append(clients, client)
			echos = append(echos, echo)
			wg.Add(1)
		}
		start := time.Now()

		for i := 0; i < clientCount; i++ {
			client := clients[i]
			echo := echos[i]

			client.Tell(&Start{
				Sender: echo,
			})
		}

		wg.Wait()
		elapsed := time.Since(start)
		x := int(float32(messageCount*2*clientCount) / (float32(elapsed) / float32(time.Second)))
		log.Printf("			%v			%s			%v", tp, elapsed, x)
		for i := 0; i < clientCount; i++ {
			client := clients[i]
			client.StopFuture().Wait()
			echo := echos[i]
			echo.StopFuture().Wait()
		}
		runtime.GC()
		time.Sleep(2 * time.Second)
	}

	// f, err := os.Create("memprofile")
	// if err != nil {
	// 	log.Fatal(err)
	// }
	// pprof.WriteHeapProfile(f)
	// f.Close()
}
<commit_msg>tweak to in-process benchmark to send in smaller batches<commit_after>package main

import (
	"flag"
	"os"
	"runtime/pprof"

	"github.com/AsynkronIT/protoactor-go/actor"

	"log"
	"sync"

	"runtime"
	"time"
)

type Msg struct {
	replyTo *actor.PID
}
type Start struct {
	Sender *actor.PID
}
type Started struct{}

type clientActor struct {
	count        int
	wgStop       *sync.WaitGroup
	messageCount int
	batch        int
	batchSize    int
}

func (state *clientActor) sendBatch(context actor.Context, sender *actor.PID) bool {
	if state.messageCount == 0 {
		return false
	}

	m := &Msg{
		replyTo: context.Self(),
	}
	for i := 0; i < state.batchSize; i++ {
		sender.Tell(m)
	}

	state.messageCount -= state.batchSize
	state.batch = state.batchSize
	return true
}

func (state *clientActor) Receive(context actor.Context) {
	switch msg := context.Message().(type) {
	case *Start:
		state.sendBatch(context, msg.Sender)

	case *Msg:
		state.batch--
		if state.batch > 0 {
			return
		}

		if !state.sendBatch(context, msg.replyTo) {
			state.wgStop.Done()
		}
	}
}

func newLocalActor(stop *sync.WaitGroup, messageCount int, batchSize int) actor.Producer {
	return func() actor.Actor {
		return &clientActor{
			wgStop:       stop,
			messageCount: messageCount,
			batchSize:    batchSize,
		}
	}
}

var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
var blockProfile = flag.String("blockprof", "", "execute contention profiling and save results here")

func main() {
	flag.Parse()
	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	// Check for lock contention profiling
	if *blockProfile != "" {
		prof, err := os.Create(*blockProfile)
		if err != nil {
			log.Fatal(err)
		}
		runtime.SetBlockProfileRate(1)
		defer func() {
			pprof.Lookup("block").WriteTo(prof, 0)
		}()
	}

	runtime.GOMAXPROCS(runtime.NumCPU())
	runtime.GC()

	var wg sync.WaitGroup

	messageCount := 1000000
	batchSize := 100
	tps := []int{300, 400, 500, 600, 700, 800, 900}
	log.Println("Dispatcher Throughput			Elapsed Time			Messages per sec")
	for _, tp := range tps {

		d := actor.NewDefaultDispatcher(tp)

		clientProps := actor.
			FromProducer(newLocalActor(&wg, messageCount, batchSize)).
			WithMailbox(actor.NewUnboundedMailbox()).
			WithDispatcher(d)

		echoProps := actor.
			FromFunc(
				func(context actor.Context) {
					switch msg := context.Message().(type) {
					case *Msg:
						msg.replyTo.Tell(msg)
					}
				}).
			WithMailbox(actor.NewUnboundedMailbox()).
			WithDispatcher(d)

		clients := make([]*actor.PID, 0)
		echos := make([]*actor.PID, 0)
		clientCount := runtime.NumCPU() * 2
		for i := 0; i < clientCount; i++ {
			client := actor.Spawn(clientProps)
			echo := actor.Spawn(echoProps)
			clients = append(clients, client)
			echos = append(echos, echo)
			wg.Add(1)
		}
		start := time.Now()

		for i := 0; i < clientCount; i++ {
			client := clients[i]
			echo := echos[i]

			client.Tell(&Start{
				Sender: echo,
			})
		}

		wg.Wait()
		elapsed := time.Since(start)
		x := int(float32(messageCount*2*clientCount) / (float32(elapsed) / float32(time.Second)))
		log.Printf("			%v			%s			%v", tp, elapsed, x)
		for i := 0; i < clientCount; i++ {
			client := clients[i]
			client.StopFuture().Wait()
			echo := echos[i]
			echo.StopFuture().Wait()
		}
		runtime.GC()
		time.Sleep(2 * time.Second)
	}

	// f, err := os.Create("memprofile")
	// if err != nil {
	// 	log.Fatal(err)
	// }
	// pprof.WriteHeapProfile(f)
	// f.Close()
}
<|endoftext|>


<commit_before>// +build linux

/*
Copyright 2017 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package cm

import (
	"fmt"
	"strings"
	"time"

	"k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/resource"
	"k8s.io/apimachinery/pkg/types"
	"k8s.io/klog"
	"k8s.io/kubernetes/pkg/kubelet/events"
	"k8s.io/kubernetes/pkg/kubelet/stats/pidlimit"
	kubetypes "k8s.io/kubernetes/pkg/kubelet/types"
)

const (
	defaultNodeAllocatableCgroupName = "kubepods"
)

//createNodeAllocatableCgroups creates Node Allocatable Cgroup when CgroupsPerQOS flag is specified as true
func (cm *containerManagerImpl) createNodeAllocatableCgroups() error {
	cgroupConfig := &CgroupConfig{
		Name: cm.cgroupRoot,
		// The default limits for cpu shares can be very low which can lead to CPU starvation for pods.
		ResourceParameters: getCgroupConfig(cm.internalCapacity),
	}
	if cm.cgroupManager.Exists(cgroupConfig.Name) {
		return nil
	}
	if err := cm.cgroupManager.Create(cgroupConfig); err != nil {
		klog.Errorf("Failed to create %q cgroup", cm.cgroupRoot)
		return err
	}
	return nil
}

// enforceNodeAllocatableCgroups enforce Node Allocatable Cgroup settings.
func (cm *containerManagerImpl) enforceNodeAllocatableCgroups() error {
	nc := cm.NodeConfig.NodeAllocatableConfig

	// We need to update limits on node allocatable cgroup no matter what because
	// default cpu shares on cgroups are low and can cause cpu starvation.
	nodeAllocatable := cm.internalCapacity
	// Use Node Allocatable limits instead of capacity if the user requested enforcing node allocatable.
	if cm.CgroupsPerQOS && nc.EnforceNodeAllocatable.Has(kubetypes.NodeAllocatableEnforcementKey) {
		nodeAllocatable = cm.getNodeAllocatableInternalAbsolute()
	}

	klog.V(4).Infof("Attempting to enforce Node Allocatable with config: %+v", nc)

	cgroupConfig := &CgroupConfig{
		Name:               cm.cgroupRoot,
		ResourceParameters: getCgroupConfig(nodeAllocatable),
	}

	// Using ObjectReference for events as the node maybe not cached; refer to #42701 for detail.
	nodeRef := &v1.ObjectReference{
		Kind:      "Node",
		Name:      cm.nodeInfo.Name,
		UID:       types.UID(cm.nodeInfo.Name),
		Namespace: "",
	}

	// If Node Allocatable is enforced on a node that has not been drained or is updated on an existing node to a lower value,
	// existing memory usage across pods might be higher than current Node Allocatable Memory Limits.
	// Pod Evictions are expected to bring down memory usage to below Node Allocatable limits.
	// Until evictions happen retry cgroup updates.
	// Update limits on non root cgroup-root to be safe since the default limits for CPU can be too low.
	// Check if cgroupRoot is set to a non-empty value (empty would be the root container)
	if len(cm.cgroupRoot) > 0 {
		go func() {
			for {
				err := cm.cgroupManager.Update(cgroupConfig)
				if err == nil {
					cm.recorder.Event(nodeRef, v1.EventTypeNormal, events.SuccessfulNodeAllocatableEnforcement, "Updated Node Allocatable limit across pods")
					return
				}
				message := fmt.Sprintf("Failed to update Node Allocatable Limits %q: %v", cm.cgroupRoot, err)
				cm.recorder.Event(nodeRef, v1.EventTypeWarning, events.FailedNodeAllocatableEnforcement, message)
				time.Sleep(time.Minute)
			}
		}()
	}
	// Now apply kube reserved and system reserved limits if required.
	if nc.EnforceNodeAllocatable.Has(kubetypes.SystemReservedEnforcementKey) {
		klog.V(2).Infof("Enforcing System reserved on cgroup %q with limits: %+v", nc.SystemReservedCgroupName, nc.SystemReserved)
		if err := enforceExistingCgroup(cm.cgroupManager, cm.cgroupManager.CgroupName(nc.SystemReservedCgroupName), nc.SystemReserved); err != nil {
			message := fmt.Sprintf("Failed to enforce System Reserved Cgroup Limits on %q: %v", nc.SystemReservedCgroupName, err)
			cm.recorder.Event(nodeRef, v1.EventTypeWarning, events.FailedNodeAllocatableEnforcement, message)
			return fmt.Errorf(message)
		}
		cm.recorder.Eventf(nodeRef, v1.EventTypeNormal, events.SuccessfulNodeAllocatableEnforcement, "Updated limits on system reserved cgroup %v", nc.SystemReservedCgroupName)
	}
	if nc.EnforceNodeAllocatable.Has(kubetypes.KubeReservedEnforcementKey) {
		klog.V(2).Infof("Enforcing kube reserved on cgroup %q with limits: %+v", nc.KubeReservedCgroupName, nc.KubeReserved)
		if err := enforceExistingCgroup(cm.cgroupManager, cm.cgroupManager.CgroupName(nc.KubeReservedCgroupName), nc.KubeReserved); err != nil {
			message := fmt.Sprintf("Failed to enforce Kube Reserved Cgroup Limits on %q: %v", nc.KubeReservedCgroupName, err)
			cm.recorder.Event(nodeRef, v1.EventTypeWarning, events.FailedNodeAllocatableEnforcement, message)
			return fmt.Errorf(message)
		}
		cm.recorder.Eventf(nodeRef, v1.EventTypeNormal, events.SuccessfulNodeAllocatableEnforcement, "Updated limits on kube reserved cgroup %v", nc.KubeReservedCgroupName)
	}
	return nil
}

// enforceExistingCgroup updates the limits `rl` on existing cgroup `cName` using `cgroupManager` interface.
func enforceExistingCgroup(cgroupManager CgroupManager, cName CgroupName, rl v1.ResourceList) error {
	cgroupConfig := &CgroupConfig{
		Name:               cName,
		ResourceParameters: getCgroupConfig(rl),
	}
	if cgroupConfig.ResourceParameters == nil {
		return fmt.Errorf("%q cgroup is not config properly", cgroupConfig.Name)
	}
	klog.V(4).Infof("Enforcing limits on cgroup %q with %d cpu shares, %d bytes of memory, and %d processes", cName, cgroupConfig.ResourceParameters.CpuShares, cgroupConfig.ResourceParameters.Memory, cgroupConfig.ResourceParameters.PidsLimit)
	if !cgroupManager.Exists(cgroupConfig.Name) {
		return fmt.Errorf("%q cgroup does not exist", cgroupConfig.Name)
	}
	if err := cgroupManager.Update(cgroupConfig); err != nil {
		return err
	}
	return nil
}

// getCgroupConfig returns a ResourceConfig object that can be used to create or update cgroups via CgroupManager interface.
func getCgroupConfig(rl v1.ResourceList) *ResourceConfig {
	// TODO(vishh): Set CPU Quota if necessary.
	if rl == nil {
		return nil
	}
	var rc ResourceConfig
	if q, exists := rl[v1.ResourceMemory]; exists {
		// Memory is defined in bytes.
		val := q.Value()
		rc.Memory = &val
	}
	if q, exists := rl[v1.ResourceCPU]; exists {
		// CPU is defined in milli-cores.
		val := MilliCPUToShares(q.MilliValue())
		rc.CpuShares = &val
	}
	if q, exists := rl[pidlimit.PIDs]; exists {
		val := q.Value()
		rc.PidsLimit = &val
	}
	rc.HugePageLimit = HugePageLimits(rl)

	return &rc
}

// getNodeAllocatableAbsolute returns the absolute value of Node Allocatable which is primarily useful for enforcement.
// Note that not all resources that are available on the node are included in the returned list of resources.
// Returns a ResourceList.
func (cm *containerManagerImpl) getNodeAllocatableAbsolute() v1.ResourceList {
	return cm.getNodeAllocatableAbsoluteImpl(cm.capacity)
}

func (cm *containerManagerImpl) getNodeAllocatableAbsoluteImpl(capacity v1.ResourceList) v1.ResourceList {
	result := make(v1.ResourceList)
	for k, v := range capacity {
		value := v.DeepCopy()
		if cm.NodeConfig.SystemReserved != nil {
			value.Sub(cm.NodeConfig.SystemReserved[k])
		}
		if cm.NodeConfig.KubeReserved != nil {
			value.Sub(cm.NodeConfig.KubeReserved[k])
		}
		if value.Sign() < 0 {
			// Negative Allocatable resources don't make sense.
			value.Set(0)
		}
		result[k] = value
	}
	return result
}

// getNodeAllocatableInternalAbsolute is similar to getNodeAllocatableAbsolute except that
// it also includes internal resources (currently process IDs).  It is intended for setting
// up top level cgroups only.
func (cm *containerManagerImpl) getNodeAllocatableInternalAbsolute() v1.ResourceList {
	return cm.getNodeAllocatableAbsoluteImpl(cm.internalCapacity)
}

// GetNodeAllocatableReservation returns amount of compute or storage resource that have to be reserved on this node from scheduling.
func (cm *containerManagerImpl) GetNodeAllocatableReservation() v1.ResourceList {
	evictionReservation := hardEvictionReservation(cm.HardEvictionThresholds, cm.capacity)
	result := make(v1.ResourceList)
	for k := range cm.capacity {
		value := resource.NewQuantity(0, resource.DecimalSI)
		if cm.NodeConfig.SystemReserved != nil {
			value.Add(cm.NodeConfig.SystemReserved[k])
		}
		if cm.NodeConfig.KubeReserved != nil {
			value.Add(cm.NodeConfig.KubeReserved[k])
		}
		if evictionReservation != nil {
			value.Add(evictionReservation[k])
		}
		if !value.IsZero() {
			result[k] = *value
		}
	}
	return result
}

// validateNodeAllocatable ensures that the user specified Node Allocatable Configuration doesn't reserve more than the node capacity.
// Returns error if the configuration is invalid, nil otherwise.
func (cm *containerManagerImpl) validateNodeAllocatable() error {
	var errors []string
	nar := cm.GetNodeAllocatableReservation()
	for k, v := range nar {
		value := cm.capacity[k].DeepCopy()
		value.Sub(v)

		if value.Sign() < 0 {
			errors = append(errors, fmt.Sprintf("Resource %q has an allocatable of %v, capacity of %v", k, v, value))
		}
	}

	if len(errors) > 0 {
		return fmt.Errorf("invalid Node Allocatable configuration. %s", strings.Join(errors, " "))
	}
	return nil
}
<commit_msg>UPSTREAM: 88251: Partially fix incorrect configuration of kubepods.slice unit by kubelet<commit_after>// +build linux

/*
Copyright 2017 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package cm

import (
	"fmt"
	"strings"
	"time"

	"k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/resource"
	"k8s.io/apimachinery/pkg/types"
	"k8s.io/klog"
	"k8s.io/kubernetes/pkg/kubelet/events"
	"k8s.io/kubernetes/pkg/kubelet/stats/pidlimit"
	kubetypes "k8s.io/kubernetes/pkg/kubelet/types"
)

const (
	defaultNodeAllocatableCgroupName = "kubepods"
)

//createNodeAllocatableCgroups creates Node Allocatable Cgroup when CgroupsPerQOS flag is specified as true
func (cm *containerManagerImpl) createNodeAllocatableCgroups() error {
	nodeAllocatable := cm.internalCapacity
	// Use Node Allocatable limits instead of capacity if the user requested enforcing node allocatable.
	nc := cm.NodeConfig.NodeAllocatableConfig
	if cm.CgroupsPerQOS && nc.EnforceNodeAllocatable.Has(kubetypes.NodeAllocatableEnforcementKey) {
		nodeAllocatable = cm.getNodeAllocatableInternalAbsolute()
	}

	cgroupConfig := &CgroupConfig{
		Name: cm.cgroupRoot,
		// The default limits for cpu shares can be very low which can lead to CPU starvation for pods.
		ResourceParameters: getCgroupConfig(nodeAllocatable),
	}
	if cm.cgroupManager.Exists(cgroupConfig.Name) {
		return nil
	}
	if err := cm.cgroupManager.Create(cgroupConfig); err != nil {
		klog.Errorf("Failed to create %q cgroup", cm.cgroupRoot)
		return err
	}
	return nil
}

// enforceNodeAllocatableCgroups enforce Node Allocatable Cgroup settings.
func (cm *containerManagerImpl) enforceNodeAllocatableCgroups() error {
	nc := cm.NodeConfig.NodeAllocatableConfig

	// We need to update limits on node allocatable cgroup no matter what because
	// default cpu shares on cgroups are low and can cause cpu starvation.
	nodeAllocatable := cm.internalCapacity
	// Use Node Allocatable limits instead of capacity if the user requested enforcing node allocatable.
	if cm.CgroupsPerQOS && nc.EnforceNodeAllocatable.Has(kubetypes.NodeAllocatableEnforcementKey) {
		nodeAllocatable = cm.getNodeAllocatableInternalAbsolute()
	}

	klog.V(4).Infof("Attempting to enforce Node Allocatable with config: %+v", nc)

	cgroupConfig := &CgroupConfig{
		Name:               cm.cgroupRoot,
		ResourceParameters: getCgroupConfig(nodeAllocatable),
	}

	// Using ObjectReference for events as the node maybe not cached; refer to #42701 for detail.
	nodeRef := &v1.ObjectReference{
		Kind:      "Node",
		Name:      cm.nodeInfo.Name,
		UID:       types.UID(cm.nodeInfo.Name),
		Namespace: "",
	}

	// If Node Allocatable is enforced on a node that has not been drained or is updated on an existing node to a lower value,
	// existing memory usage across pods might be higher than current Node Allocatable Memory Limits.
	// Pod Evictions are expected to bring down memory usage to below Node Allocatable limits.
	// Until evictions happen retry cgroup updates.
	// Update limits on non root cgroup-root to be safe since the default limits for CPU can be too low.
	// Check if cgroupRoot is set to a non-empty value (empty would be the root container)
	if len(cm.cgroupRoot) > 0 {
		go func() {
			for {
				err := cm.cgroupManager.Update(cgroupConfig)
				if err == nil {
					cm.recorder.Event(nodeRef, v1.EventTypeNormal, events.SuccessfulNodeAllocatableEnforcement, "Updated Node Allocatable limit across pods")
					return
				}
				message := fmt.Sprintf("Failed to update Node Allocatable Limits %q: %v", cm.cgroupRoot, err)
				cm.recorder.Event(nodeRef, v1.EventTypeWarning, events.FailedNodeAllocatableEnforcement, message)
				time.Sleep(time.Minute)
			}
		}()
	}
	// Now apply kube reserved and system reserved limits if required.
	if nc.EnforceNodeAllocatable.Has(kubetypes.SystemReservedEnforcementKey) {
		klog.V(2).Infof("Enforcing System reserved on cgroup %q with limits: %+v", nc.SystemReservedCgroupName, nc.SystemReserved)
		if err := enforceExistingCgroup(cm.cgroupManager, cm.cgroupManager.CgroupName(nc.SystemReservedCgroupName), nc.SystemReserved); err != nil {
			message := fmt.Sprintf("Failed to enforce System Reserved Cgroup Limits on %q: %v", nc.SystemReservedCgroupName, err)
			cm.recorder.Event(nodeRef, v1.EventTypeWarning, events.FailedNodeAllocatableEnforcement, message)
			return fmt.Errorf(message)
		}
		cm.recorder.Eventf(nodeRef, v1.EventTypeNormal, events.SuccessfulNodeAllocatableEnforcement, "Updated limits on system reserved cgroup %v", nc.SystemReservedCgroupName)
	}
	if nc.EnforceNodeAllocatable.Has(kubetypes.KubeReservedEnforcementKey) {
		klog.V(2).Infof("Enforcing kube reserved on cgroup %q with limits: %+v", nc.KubeReservedCgroupName, nc.KubeReserved)
		if err := enforceExistingCgroup(cm.cgroupManager, cm.cgroupManager.CgroupName(nc.KubeReservedCgroupName), nc.KubeReserved); err != nil {
			message := fmt.Sprintf("Failed to enforce Kube Reserved Cgroup Limits on %q: %v", nc.KubeReservedCgroupName, err)
			cm.recorder.Event(nodeRef, v1.EventTypeWarning, events.FailedNodeAllocatableEnforcement, message)
			return fmt.Errorf(message)
		}
		cm.recorder.Eventf(nodeRef, v1.EventTypeNormal, events.SuccessfulNodeAllocatableEnforcement, "Updated limits on kube reserved cgroup %v", nc.KubeReservedCgroupName)
	}
	return nil
}

// enforceExistingCgroup updates the limits `rl` on existing cgroup `cName` using `cgroupManager` interface.
func enforceExistingCgroup(cgroupManager CgroupManager, cName CgroupName, rl v1.ResourceList) error {
	cgroupConfig := &CgroupConfig{
		Name:               cName,
		ResourceParameters: getCgroupConfig(rl),
	}
	if cgroupConfig.ResourceParameters == nil {
		return fmt.Errorf("%q cgroup is not config properly", cgroupConfig.Name)
	}
	klog.V(4).Infof("Enforcing limits on cgroup %q with %d cpu shares, %d bytes of memory, and %d processes", cName, cgroupConfig.ResourceParameters.CpuShares, cgroupConfig.ResourceParameters.Memory, cgroupConfig.ResourceParameters.PidsLimit)
	if !cgroupManager.Exists(cgroupConfig.Name) {
		return fmt.Errorf("%q cgroup does not exist", cgroupConfig.Name)
	}
	if err := cgroupManager.Update(cgroupConfig); err != nil {
		return err
	}
	return nil
}

// getCgroupConfig returns a ResourceConfig object that can be used to create or update cgroups via CgroupManager interface.
func getCgroupConfig(rl v1.ResourceList) *ResourceConfig {
	// TODO(vishh): Set CPU Quota if necessary.
	if rl == nil {
		return nil
	}
	var rc ResourceConfig
	if q, exists := rl[v1.ResourceMemory]; exists {
		// Memory is defined in bytes.
		val := q.Value()
		rc.Memory = &val
	}
	if q, exists := rl[v1.ResourceCPU]; exists {
		// CPU is defined in milli-cores.
		val := MilliCPUToShares(q.MilliValue())
		rc.CpuShares = &val
	}
	if q, exists := rl[pidlimit.PIDs]; exists {
		val := q.Value()
		rc.PidsLimit = &val
	}
	rc.HugePageLimit = HugePageLimits(rl)

	return &rc
}

// getNodeAllocatableAbsolute returns the absolute value of Node Allocatable which is primarily useful for enforcement.
// Note that not all resources that are available on the node are included in the returned list of resources.
// Returns a ResourceList.
func (cm *containerManagerImpl) getNodeAllocatableAbsolute() v1.ResourceList {
	return cm.getNodeAllocatableAbsoluteImpl(cm.capacity)
}

func (cm *containerManagerImpl) getNodeAllocatableAbsoluteImpl(capacity v1.ResourceList) v1.ResourceList {
	result := make(v1.ResourceList)
	for k, v := range capacity {
		value := v.DeepCopy()
		if cm.NodeConfig.SystemReserved != nil {
			value.Sub(cm.NodeConfig.SystemReserved[k])
		}
		if cm.NodeConfig.KubeReserved != nil {
			value.Sub(cm.NodeConfig.KubeReserved[k])
		}
		if value.Sign() < 0 {
			// Negative Allocatable resources don't make sense.
			value.Set(0)
		}
		result[k] = value
	}
	return result
}

// getNodeAllocatableInternalAbsolute is similar to getNodeAllocatableAbsolute except that
// it also includes internal resources (currently process IDs).  It is intended for setting
// up top level cgroups only.
func (cm *containerManagerImpl) getNodeAllocatableInternalAbsolute() v1.ResourceList {
	return cm.getNodeAllocatableAbsoluteImpl(cm.internalCapacity)
}

// GetNodeAllocatableReservation returns amount of compute or storage resource that have to be reserved on this node from scheduling.
func (cm *containerManagerImpl) GetNodeAllocatableReservation() v1.ResourceList {
	evictionReservation := hardEvictionReservation(cm.HardEvictionThresholds, cm.capacity)
	result := make(v1.ResourceList)
	for k := range cm.capacity {
		value := resource.NewQuantity(0, resource.DecimalSI)
		if cm.NodeConfig.SystemReserved != nil {
			value.Add(cm.NodeConfig.SystemReserved[k])
		}
		if cm.NodeConfig.KubeReserved != nil {
			value.Add(cm.NodeConfig.KubeReserved[k])
		}
		if evictionReservation != nil {
			value.Add(evictionReservation[k])
		}
		if !value.IsZero() {
			result[k] = *value
		}
	}
	return result
}

// validateNodeAllocatable ensures that the user specified Node Allocatable Configuration doesn't reserve more than the node capacity.
// Returns error if the configuration is invalid, nil otherwise.
func (cm *containerManagerImpl) validateNodeAllocatable() error {
	var errors []string
	nar := cm.GetNodeAllocatableReservation()
	for k, v := range nar {
		value := cm.capacity[k].DeepCopy()
		value.Sub(v)

		if value.Sign() < 0 {
			errors = append(errors, fmt.Sprintf("Resource %q has an allocatable of %v, capacity of %v", k, v, value))
		}
	}

	if len(errors) > 0 {
		return fmt.Errorf("invalid Node Allocatable configuration. %s", strings.Join(errors, " "))
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2016 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package description

import (
	"github.com/juju/errors"
	"github.com/juju/schema"
)

type cloudimagemetadataset struct {
	Version             int                   `yaml:"version"`
	CloudImageMetadata_ []*cloudimagemetadata `yaml:"cloudimagemetadata"`
}

type cloudimagemetadata struct {
	Stream_          string  `yaml:"stream"`
	Region_          string  `yaml:"region"`
	Version_         string  `yaml:"version"`
	Series_          string  `yaml:"series"`
	Arch_            string  `yaml:"arch"`
	VirtType_        string  `yaml:"virttype"`
	RootStorageType_ string  `yaml:"rootstoragetype"`
	RootStorageSize_ *uint64 `yaml:"rootstoragesize,omitempty"`
	DateCreated_     int64   `yaml:"datecreated"`
	Source_          string  `yaml:"source"`
	Priority_        int     `yaml:"priority"`
	ImageId_         string  `yaml:"imageid"`
}

// Stream implements CloudImageMetadata.
func (i *cloudimagemetadata) Stream() string {
	return i.Stream_
}

// Region implements CloudImageMetadata.
func (i *cloudimagemetadata) Region() string {
	return i.Region_
}

// Version implements CloudImageMetadata.
func (i *cloudimagemetadata) Version() string {
	return i.Version_
}

// Series implements CloudImageMetadata.
func (i *cloudimagemetadata) Series() string {
	return i.Series_
}

// Arch implements CloudImageMetadata.
func (i *cloudimagemetadata) Arch() string {
	return i.Arch_
}

// VirtType implements CloudImageMetadata.
func (i *cloudimagemetadata) VirtType() string {
	return i.VirtType_
}

// RootStorageType implements CloudImageMetadata.
func (i *cloudimagemetadata) RootStorageType() string {
	return i.RootStorageType_
}

// RootStorageSize implements CloudImageMetadata.
func (i *cloudimagemetadata) RootStorageSize() *uint64 {
	return i.RootStorageSize_
}

// DateCreated implements CloudImageMetadata.
func (i *cloudimagemetadata) DateCreated() int64 {
	return i.DateCreated_
}

// Source implements CloudImageMetadata.
func (i *cloudimagemetadata) Source() string {
	return i.Source_
}

// Priority implements CloudImageMetadata.
func (i *cloudimagemetadata) Priority() int {
	return i.Priority_
}

//ImageId implements CloudImageMetadata.
func (i *cloudimagemetadata) ImageId() string {
	return i.ImageId_
}

// CloudImageMetadataArgs is an argument struct used to create a
// new internal cloudimagemetadata type that supports the CloudImageMetadata interface.
type CloudImageMetadataArgs struct {
	Stream          string
	Region          string
	Version         string
	Series          string
	Arch            string
	VirtType        string
	RootStorageType string
	RootStorageSize uint64
	DateCreated     int64
	Source          string
	Priority        int
	ImageId         string
}

func newCloudImageMetadata(args CloudImageMetadataArgs) *cloudimagemetadata {
	cloudimagemetadata := &cloudimagemetadata{
		Stream_:          args.Stream,
		Region_:          args.Region,
		Version_:         args.Version,
		Series_:          args.Series,
		Arch_:            args.Arch,
		VirtType_:        args.VirtType,
		RootStorageType_: args.RootStorageType,
		RootStorageSize_: &args.RootStorageSize,
		DateCreated_:     args.DateCreated,
		Source_:          args.Source,
		Priority_:        args.Priority,
		ImageId_:         args.ImageId,
	}
	return cloudimagemetadata
}

func importCloudImageMetadata(source map[string]interface{}) ([]*cloudimagemetadata, error) {
	checker := versionedChecker("cloudimagemetadata")
	coerced, err := checker.Coerce(source, nil)
	if err != nil {
		return nil, errors.Annotatef(err, "cloudimagemetadata version schema check failed")
	}
	valid := coerced.(map[string]interface{})

	version := int(valid["version"].(int64))
	importFunc, ok := cloudimagemetadataDeserializationFuncs[version]
	if !ok {
		return nil, errors.NotValidf("version %d", version)
	}
	sourceList := valid["cloudimagemetadata"].([]interface{})
	return importCloudImageMetadataList(sourceList, importFunc)
}

func importCloudImageMetadataList(sourceList []interface{}, importFunc cloudimagemetadataDeserializationFunc) ([]*cloudimagemetadata, error) {
	result := make([]*cloudimagemetadata, 0, len(sourceList))
	for i, value := range sourceList {
		source, ok := value.(map[string]interface{})
		if !ok {
			return nil, errors.Errorf("unexpected value for cloudimagemetadata %d, %T", i, value)
		}
		cloudimagemetadata, err := importFunc(source)
		if err != nil {
			return nil, errors.Annotatef(err, "cloudimagemetadata %d", i)
		}
		result = append(result, cloudimagemetadata)
	}
	return result, nil
}

type cloudimagemetadataDeserializationFunc func(map[string]interface{}) (*cloudimagemetadata, error)

var cloudimagemetadataDeserializationFuncs = map[int]cloudimagemetadataDeserializationFunc{
	1: importCloudImageMetadataV1,
}

func importCloudImageMetadataV1(source map[string]interface{}) (*cloudimagemetadata, error) {
	fields := schema.Fields{
		"stream":          schema.String(),
		"region":          schema.String(),
		"version":         schema.String(),
		"series":          schema.String(),
		"arch":            schema.String(),
		"virttype":        schema.String(),
		"rootstoragetype": schema.String(),
		"rootstoragesize": schema.Uint(),
		"datecreated":     schema.Int(),
		"source":          schema.String(),
		"priority":        schema.Int(),
		"imageid":         schema.String(),
	}
	// Some values don't have to be there.
	defaults := schema.Defaults{
		"RootStorageSize": nil,
	}
	checker := schema.FieldMap(fields, defaults)

	coerced, err := checker.Coerce(source, nil)
	if err != nil {
		return nil, errors.Annotatef(err, "cloudimagemetadata v1 schema check failed")
	}
	valid := coerced.(map[string]interface{})
	rootstoragesize := valid["rootstoragesize"].(uint64)

	cloudimagemetadata := &cloudimagemetadata{
		Stream_:          valid["stream"].(string),
		Region_:          valid["region"].(string),
		Version_:         valid["version"].(string),
		Series_:          valid["series"].(string),
		Arch_:            valid["arch"].(string),
		VirtType_:        valid["virttype"].(string),
		RootStorageType_: valid["rootstoragetype"].(string),
		RootStorageSize_: &rootstoragesize,
		DateCreated_:     valid["datecreated"].(int64),
		Source_:          valid["source"].(string),
		Priority_:        valid["priority"].(int),
		ImageId_:         valid["imageid"].(string),
	}

	return cloudimagemetadata, nil
}
<commit_msg>Moar fix<commit_after>// Copyright 2016 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package description

import (
	"github.com/juju/errors"
	"github.com/juju/schema"
)

type cloudimagemetadataset struct {
	Version             int                   `yaml:"version"`
	CloudImageMetadata_ []*cloudimagemetadata `yaml:"cloudimagemetadata"`
}

type cloudimagemetadata struct {
	Stream_          string  `yaml:"stream"`
	Region_          string  `yaml:"region"`
	Version_         string  `yaml:"version"`
	Series_          string  `yaml:"series"`
	Arch_            string  `yaml:"arch"`
	VirtType_        string  `yaml:"virttype"`
	RootStorageType_ string  `yaml:"rootstoragetype"`
	RootStorageSize_ *uint64 `yaml:"rootstoragesize,omitempty"`
	DateCreated_     int64   `yaml:"datecreated"`
	Source_          string  `yaml:"source"`
	Priority_        int     `yaml:"priority"`
	ImageId_         string  `yaml:"imageid"`
}

// Stream implements CloudImageMetadata.
func (i *cloudimagemetadata) Stream() string {
	return i.Stream_
}

// Region implements CloudImageMetadata.
func (i *cloudimagemetadata) Region() string {
	return i.Region_
}

// Version implements CloudImageMetadata.
func (i *cloudimagemetadata) Version() string {
	return i.Version_
}

// Series implements CloudImageMetadata.
func (i *cloudimagemetadata) Series() string {
	return i.Series_
}

// Arch implements CloudImageMetadata.
func (i *cloudimagemetadata) Arch() string {
	return i.Arch_
}

// VirtType implements CloudImageMetadata.
func (i *cloudimagemetadata) VirtType() string {
	return i.VirtType_
}

// RootStorageType implements CloudImageMetadata.
func (i *cloudimagemetadata) RootStorageType() string {
	return i.RootStorageType_
}

// RootStorageSize implements CloudImageMetadata.
func (i *cloudimagemetadata) RootStorageSize() *uint64 {
	return i.RootStorageSize_
}

// DateCreated implements CloudImageMetadata.
func (i *cloudimagemetadata) DateCreated() int64 {
	return i.DateCreated_
}

// Source implements CloudImageMetadata.
func (i *cloudimagemetadata) Source() string {
	return i.Source_
}

// Priority implements CloudImageMetadata.
func (i *cloudimagemetadata) Priority() int {
	return i.Priority_
}

//ImageId implements CloudImageMetadata.
func (i *cloudimagemetadata) ImageId() string {
	return i.ImageId_
}

// CloudImageMetadataArgs is an argument struct used to create a
// new internal cloudimagemetadata type that supports the CloudImageMetadata interface.
type CloudImageMetadataArgs struct {
	Stream          string
	Region          string
	Version         string
	Series          string
	Arch            string
	VirtType        string
	RootStorageType string
	RootStorageSize uint64
	DateCreated     int64
	Source          string
	Priority        int
	ImageId         string
}

func newCloudImageMetadata(args CloudImageMetadataArgs) *cloudimagemetadata {
	cloudimagemetadata := &cloudimagemetadata{
		Stream_:          args.Stream,
		Region_:          args.Region,
		Version_:         args.Version,
		Series_:          args.Series,
		Arch_:            args.Arch,
		VirtType_:        args.VirtType,
		RootStorageType_: args.RootStorageType,
		RootStorageSize_: &args.RootStorageSize,
		DateCreated_:     args.DateCreated,
		Source_:          args.Source,
		Priority_:        args.Priority,
		ImageId_:         args.ImageId,
	}
	return cloudimagemetadata
}

func importCloudImageMetadata(source map[string]interface{}) ([]*cloudimagemetadata, error) {
	checker := versionedChecker("cloudimagemetadata")
	coerced, err := checker.Coerce(source, nil)
	if err != nil {
		return nil, errors.Annotatef(err, "cloudimagemetadata version schema check failed")
	}
	valid := coerced.(map[string]interface{})

	version := int(valid["version"].(int64))
	importFunc, ok := cloudimagemetadataDeserializationFuncs[version]
	if !ok {
		return nil, errors.NotValidf("version %d", version)
	}
	sourceList := valid["cloudimagemetadata"].([]interface{})
	return importCloudImageMetadataList(sourceList, importFunc)
}

func importCloudImageMetadataList(sourceList []interface{}, importFunc cloudimagemetadataDeserializationFunc) ([]*cloudimagemetadata, error) {
	result := make([]*cloudimagemetadata, 0, len(sourceList))
	for i, value := range sourceList {
		source, ok := value.(map[string]interface{})
		if !ok {
			return nil, errors.Errorf("unexpected value for cloudimagemetadata %d, %T", i, value)
		}
		cloudimagemetadata, err := importFunc(source)
		if err != nil {
			return nil, errors.Annotatef(err, "cloudimagemetadata %d", i)
		}
		result = append(result, cloudimagemetadata)
	}
	return result, nil
}

type cloudimagemetadataDeserializationFunc func(map[string]interface{}) (*cloudimagemetadata, error)

var cloudimagemetadataDeserializationFuncs = map[int]cloudimagemetadataDeserializationFunc{
	1: importCloudImageMetadataV1,
}

func importCloudImageMetadataV1(source map[string]interface{}) (*cloudimagemetadata, error) {
	fields := schema.Fields{
		"stream":          schema.String(),
		"region":          schema.String(),
		"version":         schema.String(),
		"series":          schema.String(),
		"arch":            schema.String(),
		"virttype":        schema.String(),
		"rootstoragetype": schema.String(),
		"rootstoragesize": schema.Uint(),
		"datecreated":     schema.Int(),
		"source":          schema.String(),
		"priority":        schema.Int(),
		"imageid":         schema.String(),
	}
	// Some values don't have to be there.
	defaults := schema.Defaults{
		"rootstoragesize": nil,
	}
	checker := schema.FieldMap(fields, defaults)

	coerced, err := checker.Coerce(source, nil)
	if err != nil {
		return nil, errors.Annotatef(err, "cloudimagemetadata v1 schema check failed")
	}
	valid := coerced.(map[string]interface{})
	rootstoragesize := valid["rootstoragesize"].(uint64)

	cloudimagemetadata := &cloudimagemetadata{
		Stream_:          valid["stream"].(string),
		Region_:          valid["region"].(string),
		Version_:         valid["version"].(string),
		Series_:          valid["series"].(string),
		Arch_:            valid["arch"].(string),
		VirtType_:        valid["virttype"].(string),
		RootStorageType_: valid["rootstoragetype"].(string),
		RootStorageSize_: &rootstoragesize,
		DateCreated_:     valid["datecreated"].(int64),
		Source_:          valid["source"].(string),
		Priority_:        valid["priority"].(int),
		ImageId_:         valid["imageid"].(string),
	}

	return cloudimagemetadata, nil
}
<|endoftext|>


<commit_before><commit_msg>compiler/natives: Regenerate.<commit_after><|endoftext|>


<commit_before>// Copyright 2020 The Chromium 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 main

import (
	"context"
	"errors"
	"flag"
	"fmt"
	"time"

	"cloud.google.com/go/datastore"

	"go.skia.org/infra/autoroll/go/manual"
	"go.skia.org/infra/go/auth"
	"go.skia.org/infra/go/firestore"
	"go.skia.org/infra/go/skerr"
	"go.skia.org/infra/task_driver/go/lib/auth_steps"
	"go.skia.org/infra/task_driver/go/lib/checkout"
	"go.skia.org/infra/task_driver/go/td"
)

const (
	MinWaitDuration = 4 * time.Minute
)

func main() {
	var (
		projectId = flag.String("project_id", "", "ID of the Google Cloud project.")
		taskId    = flag.String("task_id", "", "ID of this task.")
		taskName  = flag.String("task_name", "", "Name of the task.")
		output    = flag.String("o", "", "If provided, dump a JSON blob of step data to the given file. Prints to stdout if '-' is given.")
		local     = flag.Bool("local", true, "True if running locally (as opposed to on the bots)")

		checkoutFlags = checkout.SetupFlags(nil)

		rollerName = flag.String("roller_name", "", "The roller we will use to create the canary with.")
	)
	ctx := td.StartRun(projectId, taskId, taskName, output, local)
	defer td.EndRun(ctx)
	if *rollerName == "" {
		td.Fatalf(ctx, "--roller_name must be specified")
	}

	rs, err := checkout.GetRepoState(checkoutFlags)
	if err != nil {
		td.Fatal(ctx, skerr.Wrap(err))
	}
	if rs.Issue == "" || rs.Patchset == "" {
		td.Fatalf(ctx, "This task driver should be run only as a try bot")
	}

	// Create token source with scope for datastore access.
	ts, err := auth_steps.Init(ctx, *local, auth.SCOPE_USERINFO_EMAIL, datastore.ScopeDatastore)
	if err != nil {
		td.Fatal(ctx, skerr.Wrap(err))
	}

	manualRollDB, err := manual.NewDBWithParams(ctx, firestore.FIRESTORE_PROJECT, "production", ts)
	if err != nil {
		td.Fatal(ctx, skerr.Wrap(err))
	}

	req := manual.ManualRollRequest{
		Requester:  *rollerName,
		RollerName: *rollerName,
		Status:     manual.STATUS_PENDING,
		Timestamp:  firestore.FixTimestamp(time.Now()),
		Revision:   rs.GetPatchRef(),

		DryRun:            true,
		NoEmail:           true,
		NoResolveRevision: true,
	}
	if err := td.Do(ctx, td.Props("Trigger canary roll").Infra(), func(ctx context.Context) error {
		return manualRollDB.Put(&req)
	}); err != nil {
		td.Fatal(ctx, skerr.Wrap(err))
	}

	// Add documentation link for canary rolls.
	td.StepText(ctx, "Canary roll doc", "https://goto.google.com/autoroller-canary-bots")

	if err := waitForCanaryRoll(ctx, manualRollDB, req.Id); err != nil {
		td.Fatal(ctx, skerr.Wrap(err))
	}
}

func waitForCanaryRoll(parentCtx context.Context, manualRollDB manual.DB, rollId string) error {
	ctx := td.StartStep(parentCtx, td.Props("Wait for canary roll"))
	defer td.EndStep(ctx)
	startTime := time.Now()

	// For writing to the step's log stream.
	stdout := td.NewLogStream(ctx, "stdout", td.Info)
	// Lets add the roll link only once to step data.
	addedRollLinkStepData := false
	for {
		roll, err := manualRollDB.Get(ctx, rollId)
		if err != nil {
			return td.FailStep(ctx, fmt.Errorf("Could not find canary roll with ID: %s", rollId))
		}
		cl := roll.Url
		var rollStatus string
		if cl == "" {
			rollStatus = fmt.Sprintf("Canary roll has status %s", roll.Status)
		} else {
			if !addedRollLinkStepData {
				// Add the roll link to both the current step and it's parent.
				td.StepText(ctx, "Canary roll CL", cl)
				td.StepText(parentCtx, "Canary roll CL", cl)
				addedRollLinkStepData = true
			}
			rollStatus = fmt.Sprintf("Canary roll [ %s ] has status %s", roll.Url, roll.Status)
		}
		if _, err := stdout.Write([]byte(rollStatus)); err != nil {
			return td.FailStep(ctx, fmt.Errorf("Could not write to stdout: %s", err))
		}

		if roll.Status == manual.STATUS_COMPLETE {
			if roll.Result == manual.RESULT_SUCCESS {
				// This is a hopefully temperory workaround for skbug.com/10563. Sometimes
				// Canary-Chromium returns success immediately after creating a change and
				// before the tryjobs have a chance to run. If we have waited
				// for < MinWaitDuration then be cautious and assume failure.
				if time.Now().Before(startTime.Add(MinWaitDuration)) {
					return td.FailStep(ctx, fmt.Errorf("Canary roll [ %s ] returned success in less than %s. Failing canary due to skbug.com/10563. Please retry the Canary.", cl, MinWaitDuration))
				}
				return nil
			} else if roll.Result == manual.RESULT_FAILURE {
				if cl == "" {
					return td.FailStep(ctx, errors.New("Canary roll could not be created. Please retry the Canary. Ask the trooper to investigate (or directly ping rmistry@) if this happens consistently."))
				}
				return td.FailStep(ctx, fmt.Errorf("Canary roll [ %s ] failed", cl))
			} else if roll.Result == manual.RESULT_UNKNOWN {
				return td.FailStep(ctx, fmt.Errorf("Canary roll [ %s ] completed with an unknown result", cl))
			}
		}
		time.Sleep(30 * time.Second)
	}
}
<commit_msg>Add Retries to Canaries<commit_after>// Copyright 2020 The Chromium 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 main

import (
	"context"
	"errors"
	"flag"
	"fmt"
	"time"

	"cloud.google.com/go/datastore"

	"go.skia.org/infra/autoroll/go/manual"
	"go.skia.org/infra/go/auth"
	"go.skia.org/infra/go/firestore"
	"go.skia.org/infra/go/skerr"
	"go.skia.org/infra/task_driver/go/lib/auth_steps"
	"go.skia.org/infra/task_driver/go/lib/checkout"
	"go.skia.org/infra/task_driver/go/td"
)

const (
	MinWaitDuration = 4 * time.Minute
)

var (
	canaryRollNotCreatedErr        = errors.New("Canary roll could not be created. Ask the trooper to investigate (or directly ping rmistry@) if this happens consistently.")
	canaryRollSuccessTooQuicklyErr = fmt.Errorf("Canary roll returned success in less than %s. Failing canary due to skbug.com/10563.", MinWaitDuration)

	// Lets add the roll link only once to step data.
	addedRollLinkStepData = false
)

func main() {
	var (
		projectId = flag.String("project_id", "", "ID of the Google Cloud project.")
		taskId    = flag.String("task_id", "", "ID of this task.")
		taskName  = flag.String("task_name", "", "Name of the task.")
		output    = flag.String("o", "", "If provided, dump a JSON blob of step data to the given file. Prints to stdout if '-' is given.")
		local     = flag.Bool("local", true, "True if running locally (as opposed to on the bots)")

		checkoutFlags = checkout.SetupFlags(nil)

		rollerName = flag.String("roller_name", "", "The roller we will use to create the canary with.")
	)
	ctx := td.StartRun(projectId, taskId, taskName, output, local)
	defer td.EndRun(ctx)
	if *rollerName == "" {
		td.Fatalf(ctx, "--roller_name must be specified")
	}

	rs, err := checkout.GetRepoState(checkoutFlags)
	if err != nil {
		td.Fatal(ctx, skerr.Wrap(err))
	}
	if rs.Issue == "" || rs.Patchset == "" {
		td.Fatalf(ctx, "This task driver should be run only as a try bot")
	}

	// Create token source with scope for datastore access.
	ts, err := auth_steps.Init(ctx, *local, auth.SCOPE_USERINFO_EMAIL, datastore.ScopeDatastore)
	if err != nil {
		td.Fatal(ctx, skerr.Wrap(err))
	}

	// Add documentation link for canary rolls.
	td.StepText(ctx, "Canary roll doc", "https://goto.google.com/autoroller-canary-bots")

	// Instantiate firestore DB.
	manualRollDB, err := manual.NewDBWithParams(ctx, firestore.FIRESTORE_PROJECT, "production", ts)
	if err != nil {
		td.Fatal(ctx, skerr.Wrap(err))
	}

	// Retry if canary roll could not be created or if canary roll returned
	// success too quickly (skbug.com/10563).
	retryAttempts := 3
	for retry := 0; ; retry++ {
		retryText := ""
		if retry > 0 {
			retryText = fmt.Sprintf(" (Retry #%d)", retry)
		}

		req := manual.ManualRollRequest{
			Requester:  *rollerName,
			RollerName: *rollerName,
			Status:     manual.STATUS_PENDING,
			Timestamp:  firestore.FixTimestamp(time.Now()),
			Revision:   rs.GetPatchRef(),

			DryRun:            true,
			NoEmail:           true,
			NoResolveRevision: true,
		}
		if err := td.Do(ctx, td.Props(fmt.Sprintf("Trigger canary roll%s", retryText)).Infra(), func(ctx context.Context) error {
			return manualRollDB.Put(&req)
		}); err != nil {
			// Immediately fail for errors in triggering.
			td.Fatal(ctx, skerr.Wrap(err))
		}

		if err := waitForCanaryRoll(ctx, manualRollDB, req.Id, fmt.Sprintf("Wait for canary roll%s", retryText)); err != nil {
			// Retry these errors.
			if err == canaryRollNotCreatedErr || err == canaryRollSuccessTooQuicklyErr {
				if retry >= (retryAttempts - 1) {
					td.Fatal(ctx, skerr.Wrapf(err, "failed inspite of 3 retries"))
				}
				time.Sleep(time.Minute)
				continue
			}
			// Immediately fail for all other errors.
			td.Fatal(ctx, skerr.Wrap(err))
		} else {
			// The canary roll was successful, break out of the
			// retry loop.
			break
		}
	}
}

func waitForCanaryRoll(parentCtx context.Context, manualRollDB manual.DB, rollId, stepName string) error {
	ctx := td.StartStep(parentCtx, td.Props(stepName))
	defer td.EndStep(ctx)
	startTime := time.Now()

	// For writing to the step's log stream.
	stdout := td.NewLogStream(ctx, "stdout", td.Info)
	for {
		roll, err := manualRollDB.Get(ctx, rollId)
		if err != nil {
			return td.FailStep(ctx, fmt.Errorf("Could not find canary roll with ID: %s", rollId))
		}
		cl := roll.Url
		var rollStatus string
		if cl == "" {
			rollStatus = fmt.Sprintf("Canary roll has status %s", roll.Status)
		} else {
			if !addedRollLinkStepData {
				// Add the roll link to both the current step and it's parent.
				td.StepText(ctx, "Canary roll CL", cl)
				td.StepText(parentCtx, "Canary roll CL", cl)
				addedRollLinkStepData = true
			}
			rollStatus = fmt.Sprintf("Canary roll [ %s ] has status %s", roll.Url, roll.Status)
		}
		if _, err := stdout.Write([]byte(rollStatus)); err != nil {
			return td.FailStep(ctx, fmt.Errorf("Could not write to stdout: %s", err))
		}

		if roll.Status == manual.STATUS_COMPLETE {
			if roll.Result == manual.RESULT_SUCCESS {
				// This is a hopefully temperory workaround for skbug.com/10563. Sometimes
				// Canary-Chromium returns success immediately after creating a change and
				// before the tryjobs have a chance to run. If we have waited
				// for < MinWaitDuration then be cautious and assume failure.
				if time.Now().Before(startTime.Add(MinWaitDuration)) {
					return td.FailStep(ctx, canaryRollSuccessTooQuicklyErr)
				}
				return nil
			} else if roll.Result == manual.RESULT_FAILURE {
				if cl == "" {
					return td.FailStep(ctx, canaryRollNotCreatedErr)
				}
				return td.FailStep(ctx, fmt.Errorf("Canary roll [ %s ] failed", cl))
			} else if roll.Result == manual.RESULT_UNKNOWN {
				return td.FailStep(ctx, fmt.Errorf("Canary roll [ %s ] completed with an unknown result", cl))
			}
		}
		time.Sleep(30 * time.Second)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"time"

	dns "github.com/miekg/godns"
	"github.com/davecheney/zeroconf"
)

var (
	zone = zeroconf.NewLocalZone()
	questions = []dns.Question {
		{ "_ssh._tcp.local.", dns.TypeANY, dns.ClassINET },
	}
)

func printer() {
	results := make (chan *zeroconf.Entry, 16)
	zone.Subscribe <- &zeroconf.Query {
		Question: dns.Question {
			"",
			dns.TypeDNSKEY,
			dns.ClassINET,
		},
		Result: results,
	}
	for result := range results {
		fmt.Printf("%#v\n", result)
	}
}

func main() {
	go printer()

	for {
		<- time.After(2e9)
	}
}
<commit_msg>Subscribe now works<commit_after>package main

import (
	"fmt"
	"time"

	dns "github.com/miekg/godns"
	"github.com/davecheney/zeroconf"
)

var (
	zone = zeroconf.NewLocalZone()
	questions = []dns.Question {
		{ "_ssh._tcp.local.", dns.TypeANY, dns.ClassINET },
	}
)

func printer() {
	results := make (chan *zeroconf.Entry, 16)
	zone.Subscribe <- &zeroconf.Query {
		Question: dns.Question {
			"", // fake
			dns.TypeANY,
			dns.ClassINET,
		},
		Result: results,
	}
	for result := range results {
		fmt.Printf("%s\n", result.RR)
	}
}

func main() {
	go printer()

	for {
		for _, q := range questions {
			zone.Query <- &zeroconf.Query {
				Question: q,
				Result: make(chan *zeroconf.Entry, 16), // ignored
			}
		}
		<- time.After(2e9)
	}
}
<|endoftext|>


<commit_before>package main

import (
    "fmt"
    "bytes"
    "net/http"
    "io/ioutil"
    "github.com/andlabs/ui"
)

func main() {
    err := ui.Main(func() {
        vBox := ui.NewVerticalBox()
        hBox := ui.NewHorizontalBox()

        urlEntry := ui.NewEntry()
        jsonLabel := ui.NewLabel("Input json:")
        jsonEntry := ui.NewEntry()
        goButton := ui.NewButton("Go")
        resLabel := ui.NewLabel("")
        selectCombobox := ui.NewCombobox()

        hBox.Append(selectCombobox, false)
        hBox.Append(urlEntry, true)
        hBox.Append(goButton, false)
        hBox.SetPadded(true)

        vBox.Append(hBox, false)

        vBox.Append(jsonLabel, false)
        vBox.Append(jsonEntry, false)
        vBox.Append(resLabel, false)

        vBox.SetPadded(true)

        jsonLabel.Hide()
        jsonEntry.Hide()

        selectCombobox.Append("Get")
        selectCombobox.Append("Post")

        selectCombobox.SetSelected(0)

        window := ui.NewWindow("doreq - do request", 800, 600, false)
        window.SetChild(vBox)
        window.SetMargined(true)

        selectCombobox.OnSelected(func(*ui.Combobox) {
            selectedIndex := selectCombobox.Selected()
            fmt.Println("selectedIndex:", selectedIndex)
            switch selectedIndex {
                case 1:
                    jsonLabel.Show()
                    jsonEntry.Show()
                default:
                    jsonLabel.Hide()
                    jsonEntry.Hide()
            }
        })

        goButton.OnClicked(func(*ui.Button) {
            fmt.Printf("goButton pressed\n")
            selectedIndex := selectCombobox.Selected()
            switch selectedIndex {
                case 0:
                    resp, err := http.Get(urlEntry.Text())
                    if err != nil {
                        resLabel.SetText(err.Error())
                        return
                    }
                    if resp.StatusCode == 200 {
                        bodyBytes, err := ioutil.ReadAll(resp.Body)
                        if err != nil {
                            return
                        }
                        bodyString := string(bodyBytes)
                        fmt.Printf(bodyString)
                        resLabel.SetText(bodyString)
                    }
                case 1:
                    url := urlEntry.Text()
                    fmt.Println("URL:", url)
                    jsonStr := jsonEntry.Text()

                    var jsonBytes = []byte(jsonStr)
                    req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonBytes))
                    req.Header.Set("Content-Type", "application/json")

                    client := &http.Client{}
                    resp, err := client.Do(req)
                    if err != nil {
                        panic(err)
                    }
                    defer resp.Body.Close()

                    fmt.Println("response Status:", resp.Status)
                    fmt.Println("response Headers:", resp.Header)
                    body, _ := ioutil.ReadAll(resp.Body)
                    resLabel.SetText(string(body))
                    fmt.Println("response Body:", string(body))
                default:
                    fmt.Printf("no selected")
            }

        })
        window.OnClosing(func(*ui.Window) bool {
            ui.Quit()
            return true
        })
        window.Show()
    })
    if err != nil {
        panic(err)
    }
}<commit_msg>add isJSON and handleResp<commit_after>package main

import (
    "fmt"
    "bytes"
    "strconv"
    "net/http"
    "io/ioutil"
    "encoding/json"
    "github.com/andlabs/ui"
)

func main() {
    err := ui.Main(func() {
        vBox := ui.NewVerticalBox()
        hBox := ui.NewHorizontalBox()

        urlEntry := ui.NewEntry()
        jsonLabel := ui.NewLabel("Input json:")
        jsonEntry := ui.NewEntry()
        goButton := ui.NewButton("Go")
        resLabel := ui.NewLabel("")
        selectCombobox := ui.NewCombobox()

        hBox.Append(selectCombobox, false)
        hBox.Append(urlEntry, true)
        hBox.Append(goButton, false)
        hBox.SetPadded(true)

        vBox.Append(hBox, false)

        vBox.Append(jsonLabel, false)
        vBox.Append(jsonEntry, false)
        vBox.Append(resLabel, false)

        vBox.SetPadded(true)

        jsonLabel.Hide()
        jsonEntry.Hide()

        selectCombobox.Append("Get")
        selectCombobox.Append("Post")

        selectCombobox.SetSelected(0)

        window := ui.NewWindow("doreq - do request", 800, 600, false)
        window.SetChild(vBox)
        window.SetMargined(true)

        selectCombobox.OnSelected(func(*ui.Combobox) {
            selectedIndex := selectCombobox.Selected()
            fmt.Println("selectedIndex:", selectedIndex)
            switch selectedIndex {
                case 1:
                    jsonLabel.Show()
                    jsonEntry.Show()
                default:
                    jsonLabel.Hide()
                    jsonEntry.Hide()
            }
        })

        goButton.OnClicked(func(*ui.Button) {
            fmt.Printf("goButton pressed\n")
            selectedIndex := selectCombobox.Selected()
            switch selectedIndex {
                case 0:
                    resp, err := http.Get(urlEntry.Text())
                    if err != nil {
                        resLabel.SetText(err.Error())
                        return
                    }
                    handleResp(resp, resLabel)
                case 1:
                    url := urlEntry.Text()
                    fmt.Println("URL:", url)
                    jsonStr := jsonEntry.Text()

                    var jsonBytes = []byte(jsonStr)
                    req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonBytes))
                    req.Header.Set("Content-Type", "application/json")

                    client := &http.Client{}
                    resp, err := client.Do(req)
                    if err != nil {
                        panic(err)
                    }
                    handleResp(resp, resLabel)
                default:
                    fmt.Printf("no selected")
            }

        })
        window.OnClosing(func(*ui.Window) bool {
            ui.Quit()
            return true
        })
        window.Show()
    })
    if err != nil {
        panic(err)
    }
}

func isJSON(s string) bool {
    var js map[string]interface{}
    return json.Unmarshal([]byte(s), &js) == nil
}

func handleResp(resp *http.Response, label *ui.Label) {
    defer resp.Body.Close()
    fmt.Println("response Status:", resp.Status)
    fmt.Println("response Headers:", resp.Header)

    if resp.StatusCode == 200 {
        bodyBytes, err := ioutil.ReadAll(resp.Body)
        if err != nil {
            return
        }
        bodyString := string(bodyBytes)
        if !isJSON(bodyString) {
            bodyString = "Response is not json."
        }
        label.SetText(bodyString)
    } else {
        label.SetText("Error with code " + strconv.Itoa(resp.StatusCode))
    }
}<|endoftext|>


<commit_before>package hci

import (
	"github.com/currantlabs/ble/linux/hci/cmd"
)

// An Option is a configuration function, which configures the device.
type Option func(*HCI) error

// OptScanParams sets scanning parameters.
func OptScanParams(p ScanParams) Option {
	return func(h *HCI) error {
		h.states.scanParams = cmd.LESetScanParameters(p)
		return nil
	}
}

// OptAdvParams sets advertising parameters.
func OptAdvParams(p AdvParams) Option {
	return func(h *HCI) error {
		h.states.advParams = cmd.LESetAdvertisingParameters(p)
		return nil
	}
}

// OptConnParams ...
func OptConnParams(p ConnParams) Option {
	return func(h *HCI) error {
		h.states.connParams = cmd.LECreateConnection(p)
		return nil
	}
}
<commit_msg>linux: add dialer and listener timeout options<commit_after>package hci

import (
	"time"

	"github.com/currantlabs/ble/linux/hci/cmd"
)

// An Option is a configuration function, which configures the device.
type Option func(*HCI) error

// OptDeviceID sets HCI device ID.
func OptDeviceID(id int) Option {
	return func(h *HCI) error {
		h.id = id
		return nil
	}
}

// OptDialerTimeout sets dialing timeout for Dialer.
func OptDialerTimeout(d time.Duration) Option {
	return func(h *HCI) error {
		h.dialerTmo = d
		return nil
	}
}

// OptListenerTimeout sets dialing timeout for Listener.
func OptListenerTimeout(d time.Duration) Option {
	return func(h *HCI) error {
		h.listenerTmo = d
		return nil
	}
}

// OptScanParams sets scanning parameters.
func OptScanParams(p ScanParams) Option {
	return func(h *HCI) error {
		h.states.scanParams = cmd.LESetScanParameters(p)
		return nil
	}
}

// OptAdvParams sets advertising parameters.
func OptAdvParams(p AdvParams) Option {
	return func(h *HCI) error {
		h.states.advParams = cmd.LESetAdvertisingParameters(p)
		return nil
	}
}

// OptConnParams sets connection parameters.
func OptConnParams(p ConnParams) Option {
	return func(h *HCI) error {
		h.states.connParams = cmd.LECreateConnection(p)
		return nil
	}
}
<|endoftext|>


<commit_before>package strlit

import (
	"github.com/reiver/go-buffers"
	"github.com/reiver/go-whitespace"

	"fmt"
	"io"
	"unicode/utf8"
)

// Bare provides methods to decode, and encode Bare String Literals
type Bare struct {}

// Decode decodes a Bare String Literal.
func (receiver Bare) Decode(dst interface{}, src []byte) (bytesWritten int, bytesRead int, err error) {

	if nil == dst {
		return 0, 0, errNilDestination
	}

	var writer io.Writer
	{
		switch casted := dst.(type) {
		case io.Writer:
			writer = casted
		case []byte:
			writer = buffers.NewWriter(casted)
		default:
			return 0, 0, fmt.Errorf("strlit: Unsupport Destination Type: %T", dst)
		}
	}

	if nil == src {
		return 0, 0, errNilSource
	}
	if 0 == len(src) {
		return 0, 0, nil
	}

	var pSrc []byte = src

	Loop: for {
		r, size := utf8.DecodeRune(pSrc)
		if utf8.RuneError == r && 0 == size {
			break Loop
		}
		if utf8.RuneError == r {
			return bytesWritten, bytesRead, errUTF8RuneError
		}

		switch {
		case whitespace.IsWhitespace(r):
			break Loop
		}

		n, err := writer.Write(pSrc[:size])
		bytesWritten += size
		if nil != err {
			return bytesWritten, bytesRead, err
		}

		bytesRead += size
		pSrc = pSrc[size:]

		if expected, actual := size, n; expected != actual {
			return bytesWritten, bytesRead, fmt.Errorf("strlit: Internal Error: wrong number of bytes copied; expected=%d actual=%d", expected, actual)
		}
	}

	return
}
<commit_msg>strlit.Bare.Decode(dst []byte, src []byte) (bytesWritten int, bytesRead int, err error) -> strlit.Bare.Decode(dst interface{}, src []byte) (bytesWritten int, bytesRead int, err error)—i.e., dst changed from []byte to interface{}<commit_after>package strlit

import (
	"github.com/reiver/go-buffers"
	"github.com/reiver/go-whitespace"

	"fmt"
	"io"
	"unicode/utf8"
)

// Bare provides methods to decode, and encode Bare String Literals
type Bare struct {}

// Decode decodes a Bare String Literal.
//
// ‘dst’ can be a []byte, or an io.Writer.
func (receiver Bare) Decode(dst interface{}, src []byte) (bytesWritten int, bytesRead int, err error) {

	if nil == dst {
		return 0, 0, errNilDestination
	}

	var writer io.Writer
	{
		switch casted := dst.(type) {
		case io.Writer:
			writer = casted
		case []byte:
			writer = buffers.NewWriter(casted)
		default:
			return 0, 0, fmt.Errorf("strlit: Unsupport Destination Type: %T", dst)
		}
	}

	if nil == src {
		return 0, 0, errNilSource
	}
	if 0 == len(src) {
		return 0, 0, nil
	}

	var pSrc []byte = src

	Loop: for {
		r, size := utf8.DecodeRune(pSrc)
		if utf8.RuneError == r && 0 == size {
			break Loop
		}
		if utf8.RuneError == r {
			return bytesWritten, bytesRead, errUTF8RuneError
		}

		switch {
		case whitespace.IsWhitespace(r):
			break Loop
		}

		n, err := writer.Write(pSrc[:size])
		bytesWritten += size
		if nil != err {
			return bytesWritten, bytesRead, err
		}

		bytesRead += size
		pSrc = pSrc[size:]

		if expected, actual := size, n; expected != actual {
			return bytesWritten, bytesRead, fmt.Errorf("strlit: Internal Error: wrong number of bytes copied; expected=%d actual=%d", expected, actual)
		}
	}

	return
}
<|endoftext|>