<commit_before>package schema

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"reflect"
	"strings"

	"github.com/cupcake/jsonschema"
	ct "github.com/flynn/flynn/controller/types"
)

var schemaCache map[string]*jsonschema.Schema

func Load(schemaRoot string) error {
	if schemaCache != nil {
		return nil
	}

	var schemaPaths []string
	walkFn := func(path string, info os.FileInfo, err error) error {
		if !info.IsDir() && filepath.Ext(path) == ".json" {
			schemaPaths = append(schemaPaths, path)
		}
		return nil
	}
	filepath.Walk(schemaRoot, walkFn)

	schemaCache = make(map[string]*jsonschema.Schema, len(schemaPaths))
	for _, path := range schemaPaths {
		file, err := os.Open(path)
		if err != nil {
			return err
		}
		schema := &jsonschema.Schema{Cache: schemaCache}
		err = schema.ParseWithoutRefs(file)
		if err != nil {
			return fmt.Errorf("schema: Error loading schema %s: %s", path, err)
		}
		cacheKey := "https://flynn.io/schema" + strings.TrimSuffix(filepath.Base(path), ".json")
		schemaCache[cacheKey] = schema
		file.Close()
	}
	for _, schema := range schemaCache {
		schema.ResolveRefs(false)
	}

	return nil
}

func schemaForType(thing interface{}) *jsonschema.Schema {
	name := strings.ToLower(reflect.Indirect(reflect.ValueOf(thing)).Type().Name())
	if name == "newjob" {
		name = "new_job"
	}
	if name == "appupdate" {
		name = "app"
	}
	if name == "route" {
		return schemaCache["https://flynn.io/schema/router/route"]
	}
	cacheKey := "https://flynn.io/schema/controller/" + name
	return schemaCache[cacheKey]
}

func Validate(thing interface{}) error {
	schema := schemaForType(thing)
	if schema == nil {
		return errors.New(fmt.Sprintf("schema: Unknown resource: %T %v", thing, thing))
	}

	var data []byte
	var err error
	if data, err = json.Marshal(thing); err != nil {
		return err
	}
	decoder := json.NewDecoder(bytes.NewReader(data))
	decoder.UseNumber()
	var validateData map[string]interface{}
	if err := decoder.Decode(&validateData); err != nil {
		return err
	}

	schemaErrs := schema.Validate(nil, validateData)
	if len(schemaErrs) > 0 {
		err := schemaErrs[0]
		return ct.ValidationError{
			Message: err.Description,
			Field:   err.DotNotation(),
		}
	}

	return nil
}
<commit_msg>controller: avoid fd leak if JSON schema parse fails (#3907)<commit_after>package schema

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"reflect"
	"strings"

	"github.com/cupcake/jsonschema"
	ct "github.com/flynn/flynn/controller/types"
)

var schemaCache map[string]*jsonschema.Schema

func Load(schemaRoot string) error {
	if schemaCache != nil {
		return nil
	}

	var schemaPaths []string
	walkFn := func(path string, info os.FileInfo, err error) error {
		if !info.IsDir() && filepath.Ext(path) == ".json" {
			schemaPaths = append(schemaPaths, path)
		}
		return nil
	}
	filepath.Walk(schemaRoot, walkFn)

	schemaCache = make(map[string]*jsonschema.Schema, len(schemaPaths))
	for _, path := range schemaPaths {
		file, err := os.Open(path)
		if err != nil {
			return err
		}
		schema := &jsonschema.Schema{Cache: schemaCache}
		err = schema.ParseWithoutRefs(file)
		file.Close()
		if err != nil {
			return fmt.Errorf("schema: Error loading schema %s: %s", path, err)
		}
		cacheKey := "https://flynn.io/schema" + strings.TrimSuffix(filepath.Base(path), ".json")
		schemaCache[cacheKey] = schema
	}
	for _, schema := range schemaCache {
		schema.ResolveRefs(false)
	}

	return nil
}

func schemaForType(thing interface{}) *jsonschema.Schema {
	name := strings.ToLower(reflect.Indirect(reflect.ValueOf(thing)).Type().Name())
	if name == "newjob" {
		name = "new_job"
	}
	if name == "appupdate" {
		name = "app"
	}
	if name == "route" {
		return schemaCache["https://flynn.io/schema/router/route"]
	}
	cacheKey := "https://flynn.io/schema/controller/" + name
	return schemaCache[cacheKey]
}

func Validate(thing interface{}) error {
	schema := schemaForType(thing)
	if schema == nil {
		return errors.New(fmt.Sprintf("schema: Unknown resource: %T %v", thing, thing))
	}

	var data []byte
	var err error
	if data, err = json.Marshal(thing); err != nil {
		return err
	}
	decoder := json.NewDecoder(bytes.NewReader(data))
	decoder.UseNumber()
	var validateData map[string]interface{}
	if err := decoder.Decode(&validateData); err != nil {
		return err
	}

	schemaErrs := schema.Validate(nil, validateData)
	if len(schemaErrs) > 0 {
		err := schemaErrs[0]
		return ct.ValidationError{
			Message: err.Description,
			Field:   err.DotNotation(),
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package controllers

import (
	"github.com/astaxie/beego"
	"github.com/citycloud/citycloud.cf-deploy-ui/entity"
)

type CloudFoundryController struct {
	beego.Controller
}

func (this *CloudFoundryController) Get() {
	action := this.GetString("action")
	this.Layout = "index.tpl"
	this.Data["NavBarFocus"] = "cloudfoundry"
	if action == "config" {
		this.ConfigCloudFoundry()
	} else if action == "deploy" {
		this.DeployCloudFoundry()
	}else {
		this.IndexCloudFoundry()
	}
}

func (this *CloudFoundryController) Post() {
	cloudfoundry := entity.NewCloudFoundry(this.GetString("name"))
	this.CommitData(cloudfoundry)
	this.Get()
}

func (this *CloudFoundryController) DeployCloudFoundry(){
	this.LoadData()
	this.TplNames = "cloudfoundry/config.tpl"
}

func (this *CloudFoundryController) IndexCloudFoundry(){
	this.LoadData()
	this.TplNames = "cloudfoundry/index.tpl"
}

func (this *CloudFoundryController) ConfigCloudFoundry(){
	this.LoadData()
	this.TplNames = "cloudfoundry/config.tpl"
}

//read data from const or database
func (this *CloudFoundryController) LoadData(){
	this.Data["CloudFoundry"] = cf
}

//write data to const or database
func (this *CloudFoundryController) CommitData(cloudfoundry entity.CloudFoundry){
	cf = cloudfoundry
}

var cf entity.CloudFoundry = entity.NewCloudFoundry("deployment-cloudfoundry")

<commit_msg>update logger<commit_after>package controllers

import (
	"github.com/astaxie/beego"
	"github.com/citycloud/citycloud.cf-deploy-ui/entity"
	"github.com/citycloud/citycloud.cf-deploy-ui/logger"
)

type CloudFoundryController struct {
	beego.Controller
}

func (this *CloudFoundryController) Get() {
	action := this.GetString("action")
	this.Layout = "index.tpl"
	this.Data["NavBarFocus"] = "cloudfoundry"
	if action == "config" {
		this.ConfigCloudFoundry()
	} else if action == "deploy" {
		this.DeployCloudFoundry()
	}else {
		this.IndexCloudFoundry()
	}
}

func (this *CloudFoundryController) Post() {
	cloudfoundry := entity.NewCloudFoundry(this.GetString("name"))
	this.CommitData(cloudfoundry)
	this.Get()
}

func (this *CloudFoundryController) DeployCloudFoundry(){
	logger.Debug("%s","Deploy CloudFoundry")
	this.LoadData()
	this.TplNames = "cloudfoundry/config.tpl"
}

func (this *CloudFoundryController) IndexCloudFoundry(){
	this.LoadData()
	this.TplNames = "cloudfoundry/index.tpl"
}

func (this *CloudFoundryController) ConfigCloudFoundry(){
	logger.Debug("%s","Config CloudFoundry")
	this.LoadData()
	this.TplNames = "cloudfoundry/config.tpl"
}

//read data from const or database
func (this *CloudFoundryController) LoadData(){
	this.Data["CloudFoundry"] = cf
}

//write data to const or database
func (this *CloudFoundryController) CommitData(cloudfoundry entity.CloudFoundry){
	cf = cloudfoundry
}

var cf entity.CloudFoundry = entity.NewCloudFoundry("deployment-cloudfoundry")

<|endoftext|>


<commit_before>// Package api makes api calls to Reddit.
package api

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"
	"strings"

	"github.com/turnage/redditproto"
)

const (
	// maxLinks is the amount of posts reddit will return for a scrape
	// query.
	maxLinks = 100
	// deletedAuthor is the author value if a post or comment was deleted.
	deletedAuthor = "[deleted]"
)

var (
	// formEncoding is the encoding format of parameters in the body of
	// requests sent to Reddit.
	formEncoding = map[string][]string{
		"content-type": {"application/x-www-form-urlencoded"},
	}
	// domain is the domain Reddit lives on.
	domain = "reddit.com"
	// oauth2Host is the hostname of Reddit's OAuth2 server.
	oauth2Host = "oauth." + domain
	// baseURL is the url all requests extend from.
	baseURL = "https://" + oauth2Host
)

// Requester executes and http.Request and returns the bytes in the body of the
// response.
type Requester func(*http.Request) ([]byte, error)

// SetTestDomain is a test hook for end to end tests to specify an alternate,
// test instance of Reddit to run against.
func SetTestDomain(domain string) {
	oauth2Host = "oauth." + domain
	baseURL = "https://" + domain
}

// Scrape returns slices with the content of a listing endpoint.
func Scrape(
	r Requester,
	path,
	after string,
	limit int,
) (
	[]*redditproto.Link,
	[]*redditproto.Comment,
	[]*redditproto.Message,
	error,
) {
	if limit <= 0 {
		limit = maxLinks
	}

	bytes, err := r(
		&http.Request{
			Method: "GET",
			Close:  true,
			URL: &url.URL{
				Scheme: "https",
				Host:   oauth2Host,
				Path:   path,
				RawQuery: url.Values{
					"limit": []string{strconv.Itoa(int(limit))},
					// This looks like a mistake but it
					// isn't. Reddit thinks of listings
					// reverse-chronologically. What graw
					// calls "after" refers to things posted
					// at a time later than the reference
					// point. What Reddit calls "after"
					// refers to things that come up in the
					// listing later, assuming the head is
					// the latest post. I don't think the
					// Reddit naming makes sense so I hide
					// it except for this line.
					"before":   []string{after},
					"raw_json": []string{"1"},
				}.Encode(),
			},
			Host: oauth2Host,
		},
	)
	if err != nil {
		return nil, nil, nil, err
	}

	return redditproto.ParseListing(bytes)
}

// IsThereThing returns whether a thing by the given id exists.
func IsThereThing(r Requester, id string) (bool, error) {
	path := "/api/info.json"

	// api/info doesn't provide message types; these need to be fetched from
	// a different url.
	if strings.HasPrefix(id, "t4_") {
		id := strings.TrimPrefix(id, "t4_")
		path = fmt.Sprintf("/message/messages/%s", id)
	}

	bytes, err := r(
		&http.Request{
			Method: "GET",
			Close:  true,
			URL: &url.URL{
				Scheme: "https",
				Host:   oauth2Host,
				Path:   path,
				RawQuery: url.Values{
					"id":       []string{id},
					"raw_json": []string{"1"},
				}.Encode(),
			},
			Host: oauth2Host,
		},
	)

	if err != nil {
		return false, err
	}

	links, comments, messages, err := redditproto.ParseListing(bytes)
	if err != nil {
		return false, err
	}

	if len(links) == 1 {
		return links[0].GetAuthor() != deletedAuthor, nil
	}

	if len(comments) == 1 {
		return comments[0].GetAuthor() != deletedAuthor, nil
	}

	if len(messages) == 1 {
		return true, nil
	}

	return false, nil
}

// Thread returns a link; the Comments field will be filled with the comment
// tree. Browse each comment's reply tree from the ReplyTree field.
func Thread(r Requester, permalink string) (*redditproto.Link, error) {
	bytes, err := r(
		&http.Request{
			Method: "GET",
			Close:  true,
			URL: &url.URL{
				Scheme:   "https",
				Host:     oauth2Host,
				Path:     fmt.Sprintf("%s.json", permalink),
				RawQuery: "raw_json=1",
			},
			Host: oauth2Host,
		},
	)
	if err != nil {
		return nil, err
	}

	return redditproto.ParseThread(bytes)
}

// Reply replies to a post, message, or comment.
func Reply(r Requester, parent, content string) error {
	_, err := r(
		&http.Request{
			Method: "POST",
			Close:  true,
			URL: &url.URL{
				Scheme: "https",
				Host:   oauth2Host,
				Path:   "/api/comment",
			},
			Header: formEncoding,
			Body: ioutil.NopCloser(
				bytes.NewBufferString(
					url.Values{
						"thing_id": []string{parent},
						"text":     []string{content},
					}.Encode(),
				),
			),
			Host: oauth2Host,
		},
	)
	return err
}

// Compose sends a private message to a user.
func Compose(r Requester, user, subject, content string) error {
	_, err := r(
		&http.Request{
			Method: "POST",
			Close:  true,
			URL: &url.URL{
				Scheme: "https",
				Host:   oauth2Host,
				Path:   "/api/compose",
			},
			Header: formEncoding,
			Body: ioutil.NopCloser(
				bytes.NewBufferString(
					url.Values{
						"to":      []string{user},
						"subject": []string{subject},
						"text":    []string{content},
					}.Encode(),
				),
			),
			Host: oauth2Host,
		},
	)
	return err
}

// Submit submits a post.
func Submit(r Requester, subreddit, kind, title, content string) error {
	_, err := r(
		&http.Request{
			Method: "POST",
			Close:  true,
			URL: &url.URL{
				Scheme: "https",
				Host:   oauth2Host,
				Path:   "/api/submit",
			},
			Header: formEncoding,
			Body: ioutil.NopCloser(
				bytes.NewBufferString(
					url.Values{
						"sr":    []string{subreddit},
						"kind":  []string{kind},
						"title": []string{title},
						"url":   []string{content},
						"text":  []string{content},
					}.Encode(),
				),
			),
			Host: oauth2Host,
		},
	)
	return err
}
<commit_msg>Request HTTP/2 in client requests.<commit_after>// Package api makes api calls to Reddit.
package api

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"
	"strings"

	"github.com/turnage/redditproto"
)

const (
	// maxLinks is the amount of posts reddit will return for a scrape
	// query.
	maxLinks = 100
	// deletedAuthor is the author value if a post or comment was deleted.
	deletedAuthor = "[deleted]"
)

var (
	// formEncoding is the encoding format of parameters in the body of
	// requests sent to Reddit.
	formEncoding = map[string][]string{
		"content-type": {"application/x-www-form-urlencoded"},
	}
	// domain is the domain Reddit lives on.
	domain = "reddit.com"
	// oauth2Host is the hostname of Reddit's OAuth2 server.
	oauth2Host = "oauth." + domain
	// baseURL is the url all requests extend from.
	baseURL = "https://" + oauth2Host
)

// Requester executes and http.Request and returns the bytes in the body of the
// response.
type Requester func(*http.Request) ([]byte, error)

// SetTestDomain is a test hook for end to end tests to specify an alternate,
// test instance of Reddit to run against.
func SetTestDomain(domain string) {
	oauth2Host = "oauth." + domain
	baseURL = "https://" + domain
}

// Scrape returns slices with the content of a listing endpoint.
func Scrape(
	r Requester,
	path,
	after string,
	limit int,
) (
	[]*redditproto.Link,
	[]*redditproto.Comment,
	[]*redditproto.Message,
	error,
) {
	if limit <= 0 {
		limit = maxLinks
	}

	bytes, err := r(
		&http.Request{
			Method:     "GET",
			ProtoMajor: 2,
			ProtoMinor: 0,
			URL: &url.URL{
				Scheme: "https",
				Host:   oauth2Host,
				Path:   path,
				RawQuery: url.Values{
					"limit": []string{strconv.Itoa(int(limit))},
					// This looks like a mistake but it
					// isn't. Reddit thinks of listings
					// reverse-chronologically. What graw
					// calls "after" refers to things posted
					// at a time later than the reference
					// point. What Reddit calls "after"
					// refers to things that come up in the
					// listing later, assuming the head is
					// the latest post. I don't think the
					// Reddit naming makes sense so I hide
					// it except for this line.
					"before":   []string{after},
					"raw_json": []string{"1"},
				}.Encode(),
			},
			Host: oauth2Host,
		},
	)
	if err != nil {
		return nil, nil, nil, err
	}

	return redditproto.ParseListing(bytes)
}

// IsThereThing returns whether a thing by the given id exists.
func IsThereThing(r Requester, id string) (bool, error) {
	path := "/api/info.json"

	// api/info doesn't provide message types; these need to be fetched from
	// a different url.
	if strings.HasPrefix(id, "t4_") {
		id := strings.TrimPrefix(id, "t4_")
		path = fmt.Sprintf("/message/messages/%s", id)
	}

	bytes, err := r(
		&http.Request{
			Method:     "GET",
			ProtoMajor: 2,
			ProtoMinor: 0,
			URL: &url.URL{
				Scheme: "https",
				Host:   oauth2Host,
				Path:   path,
				RawQuery: url.Values{
					"id":       []string{id},
					"raw_json": []string{"1"},
				}.Encode(),
			},
			Host: oauth2Host,
		},
	)

	if err != nil {
		return false, err
	}

	links, comments, messages, err := redditproto.ParseListing(bytes)
	if err != nil {
		return false, err
	}

	if len(links) == 1 {
		return links[0].GetAuthor() != deletedAuthor, nil
	}

	if len(comments) == 1 {
		return comments[0].GetAuthor() != deletedAuthor, nil
	}

	if len(messages) == 1 {
		return true, nil
	}

	return false, nil
}

// Thread returns a link; the Comments field will be filled with the comment
// tree. Browse each comment's reply tree from the ReplyTree field.
func Thread(r Requester, permalink string) (*redditproto.Link, error) {
	bytes, err := r(
		&http.Request{
			Method:     "GET",
			ProtoMajor: 2,
			ProtoMinor: 0,
			URL: &url.URL{
				Scheme:   "https",
				Host:     oauth2Host,
				Path:     fmt.Sprintf("%s.json", permalink),
				RawQuery: "raw_json=1",
			},
			Host: oauth2Host,
		},
	)
	if err != nil {
		return nil, err
	}

	return redditproto.ParseThread(bytes)
}

// Reply replies to a post, message, or comment.
func Reply(r Requester, parent, content string) error {
	_, err := r(
		&http.Request{
			Method:     "POST",
			ProtoMajor: 2,
			ProtoMinor: 0,
			URL: &url.URL{
				Scheme: "https",
				Host:   oauth2Host,
				Path:   "/api/comment",
			},
			Header: formEncoding,
			Body: ioutil.NopCloser(
				bytes.NewBufferString(
					url.Values{
						"thing_id": []string{parent},
						"text":     []string{content},
					}.Encode(),
				),
			),
			Host: oauth2Host,
		},
	)
	return err
}

// Compose sends a private message to a user.
func Compose(r Requester, user, subject, content string) error {
	_, err := r(
		&http.Request{
			Method:     "POST",
			ProtoMajor: 2,
			ProtoMinor: 0,
			URL: &url.URL{
				Scheme: "https",
				Host:   oauth2Host,
				Path:   "/api/compose",
			},
			Header: formEncoding,
			Body: ioutil.NopCloser(
				bytes.NewBufferString(
					url.Values{
						"to":      []string{user},
						"subject": []string{subject},
						"text":    []string{content},
					}.Encode(),
				),
			),
			Host: oauth2Host,
		},
	)
	return err
}

// Submit submits a post.
func Submit(r Requester, subreddit, kind, title, content string) error {
	_, err := r(
		&http.Request{
			Method:     "POST",
			ProtoMajor: 2,
			ProtoMinor: 0,
			URL: &url.URL{
				Scheme: "https",
				Host:   oauth2Host,
				Path:   "/api/submit",
			},
			Header: formEncoding,
			Body: ioutil.NopCloser(
				bytes.NewBufferString(
					url.Values{
						"sr":    []string{subreddit},
						"kind":  []string{kind},
						"title": []string{title},
						"url":   []string{content},
						"text":  []string{content},
					}.Encode(),
				),
			),
			Host: oauth2Host,
		},
	)
	return err
}
<|endoftext|>


<commit_before>// Copyright 2016 Hajime Hoshi
//
// 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.

// +build android

package ui

import (
	"errors"
	"time"

	"github.com/hajimehoshi/ebiten/internal/graphics/opengl"
)

func initialize() (*opengl.Context, error) {
	return opengl.NewContext()
}

func Main() error {
	return errors.New("ui: don't call this: use RunWithoutMainLoop instead of Run")
}

func Render(chError <-chan error) error {
	if chError == nil {
		return errors.New("ui: chError must not be nil")
	}
	// TODO: Check this is called on the rendering thread
	select {
	case <-chResumeStart:
		if err := doGLWorks(chError, chResumeEnd); err != nil {
			return err
		}
		return nil
	case chRender <- struct{}{}:
		return doGLWorks(chError, chRenderEnd)
	case <-time.After(500 * time.Millisecond):
		// This function must not be blocked. We need to break for timeout.
		return nil
	}
}

func doGLWorks(chError <-chan error, chDone <-chan struct{}) error {
	// TODO: Check this is called on the rendering thread
	worker := glContext.Worker()
loop:
	for {
		select {
		case err := <-chError:
			return err
		case <-worker.WorkAvailable():
			worker.DoWork()
		default:
			select {
			case <-chDone:
				break loop
			default:
			}
		}
	}
	return nil
}

type userInterface struct {
	width       int
	height      int
	scale       int
	sizeChanged bool
}

var (
	chRender      = make(chan struct{})
	chRenderEnd   = make(chan struct{})
	chResume      = make(chan struct{})
	chResumeStart = make(chan struct{})
	chResumeEnd   = make(chan struct{})
	currentUI     = &userInterface{
		sizeChanged: true,
	}
)

func CurrentUI() UserInterface {
	return currentUI
}

func (u *userInterface) Start(width, height, scale int, title string) error {
	u.width = width
	u.height = height
	u.scale = scale
	// title is ignored?
	return nil
}

func (u *userInterface) Terminate() error {
	return nil
}

func (u *userInterface) Update() (interface{}, error) {
	// TODO: Need lock?
	if u.sizeChanged {
		u.sizeChanged = false
		e := ScreenSizeEvent{
			Width:       u.width,
			Height:      u.height,
			Scale:       u.scale,
			ActualScale: u.actualScreenScale(),
		}
		return e, nil
	}
	select {
	case <-chRender:
		return RenderEvent{chRenderEnd}, nil
	case <-chResume:
		chResumeStart <- struct{}{}
		return ResumeEvent{chResumeEnd}, nil
	}
}

func (u *userInterface) SwapBuffers() error {
	return nil
}

func (u *userInterface) SetScreenSize(width, height int) bool {
	// TODO: Implement
	return false
}

func (u *userInterface) SetScreenScale(scale int) bool {
	// TODO: Implement
	return false
}

func (u *userInterface) ScreenScale() int {
	return u.scale
}

func (u *userInterface) actualScreenScale() int {
	return u.scale
}

func Resume() error {
	chResume <- struct{}{}
	// Don't have to wait for resumeing done.
	return nil
}

func UpdateTouches(touches []Touch) {
	currentInput.updateTouches(touches)
}
<commit_msg>mobile: Add a comment<commit_after>// Copyright 2016 Hajime Hoshi
//
// 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.

// +build android

package ui

import (
	"errors"
	"time"

	"github.com/hajimehoshi/ebiten/internal/graphics/opengl"
)

func initialize() (*opengl.Context, error) {
	return opengl.NewContext()
}

func Main() error {
	return errors.New("ui: don't call this: use RunWithoutMainLoop instead of Run")
}

func Render(chError <-chan error) error {
	if chError == nil {
		return errors.New("ui: chError must not be nil")
	}
	// TODO: Check this is called on the rendering thread
	select {
	case <-chResumeStart:
		if err := doGLWorks(chError, chResumeEnd); err != nil {
			return err
		}
		return nil
	case chRender <- struct{}{}:
		return doGLWorks(chError, chRenderEnd)
	case <-time.After(500 * time.Millisecond):
		// This function must not be blocked. We need to break for timeout.
		return nil
	}
}

func doGLWorks(chError <-chan error, chDone <-chan struct{}) error {
	// TODO: Check this is called on the rendering thread
	worker := glContext.Worker()
loop:
	for {
		select {
		case err := <-chError:
			return err
		case <-worker.WorkAvailable():
			worker.DoWork()
		default:
			select {
			case <-chDone:
				break loop
			default:
			}
		}
	}
	return nil
}

type userInterface struct {
	width       int
	height      int
	scale       int
	sizeChanged bool
}

var (
	chRender      = make(chan struct{})
	chRenderEnd   = make(chan struct{})
	chResume      = make(chan struct{})
	chResumeStart = make(chan struct{})
	chResumeEnd   = make(chan struct{})
	currentUI     = &userInterface{
		sizeChanged: true,
	}
)

func CurrentUI() UserInterface {
	return currentUI
}

func (u *userInterface) Start(width, height, scale int, title string) error {
	u.width = width
	u.height = height
	u.scale = scale
	// title is ignored?
	return nil
}

func (u *userInterface) Terminate() error {
	return nil
}

func (u *userInterface) Update() (interface{}, error) {
	// TODO: Need lock?
	if u.sizeChanged {
		u.sizeChanged = false
		e := ScreenSizeEvent{
			Width:       u.width,
			Height:      u.height,
			Scale:       u.scale,
			ActualScale: u.actualScreenScale(),
		}
		return e, nil
	}
	select {
	case <-chRender:
		return RenderEvent{chRenderEnd}, nil
	case <-chResume:
		chResumeStart <- struct{}{}
		return ResumeEvent{chResumeEnd}, nil
	}
}

func (u *userInterface) SwapBuffers() error {
	return nil
}

func (u *userInterface) SetScreenSize(width, height int) bool {
	// TODO: Implement
	return false
}

func (u *userInterface) SetScreenScale(scale int) bool {
	// TODO: Implement
	return false
}

func (u *userInterface) ScreenScale() int {
	return u.scale
}

func (u *userInterface) actualScreenScale() int {
	return u.scale
}

// TODO: Remove Resume() and do resuming in Update instead.
// In Update, we'd be able to detect GL context lost by glIsTexture or something,
// and we can do resuming when detecting it.

func Resume() error {
	chResume <- struct{}{}
	// Don't have to wait for resumeing done.
	return nil
}

func UpdateTouches(touches []Touch) {
	currentInput.updateTouches(touches)
}
<|endoftext|>


<commit_before>package reporting

import (
	"encoding/json"
	"fmt"
	"runtime"
	"strings"

	"github.com/smartystreets/goconvey/convey/gotest"
)

////////////////// ScopeReport ////////////////////

type ScopeReport struct {
	Title string
	ID    string
	File  string
	Line  int
}

func NewScopeReport(title, name string) *ScopeReport {
	file, line, _ := gotest.ResolveExternalCaller()
	self := new(ScopeReport)
	self.Title = title
	self.ID = fmt.Sprintf("%s|%s", title, name)
	self.File = file
	self.Line = line
	return self
}

////////////////// ScopeResult ////////////////////

type ScopeResult struct {
	Title      string
	File       string
	Line       int
	Depth      int
	Assertions []*AssertionResult
}

func newScopeResult(title string, depth int, file string, line int) *ScopeResult {
	self := new(ScopeResult)
	self.Title = title
	self.Depth = depth
	self.File = file
	self.Line = line
	self.Assertions = []*AssertionResult{}
	return self
}

/////////////////// StoryReport /////////////////////

type StoryReport struct {
	Test T
	Name string
	File string
	Line int
}

func NewStoryReport(test T) *StoryReport {
	file, line, name := gotest.ResolveExternalCaller()
	name = removePackagePath(name)
	self := new(StoryReport)
	self.Test = test
	self.Name = name
	self.File = file
	self.Line = line
	return self
}

// name comes in looking like "github.com/smartystreets/goconvey/examples.TestName".
// We only want the stuff after the last '.', which is the name of the test function.
func removePackagePath(name string) string {
	parts := strings.Split(name, ".")
	return parts[len(parts)-1]
}

/////////////////// FailureView ////////////////////////

type FailureView struct {
	Message  string
	Expected string
	Actual   string
}

////////////////////AssertionResult //////////////////////

type AssertionResult struct {
	File       string
	Line       int
	Expected   string
	Actual     string
	Failure    string
	Error      interface{}
	StackTrace string
	Skipped    bool
}

func NewFailureReport(failure string) *AssertionResult {
	report := new(AssertionResult)
	report.File, report.Line = caller()
	report.StackTrace = stackTrace()
	parseFailure(failure, report)
	return report
}
func parseFailure(failure string, report *AssertionResult) {
	view := new(FailureView)
	err := json.Unmarshal([]byte(failure), view)
	if err == nil {
		report.Failure = view.Message
		report.Expected = view.Expected
		report.Actual = view.Actual
	} else {
		report.Failure = failure
	}
}
func NewErrorReport(err interface{}) *AssertionResult {
	report := new(AssertionResult)
	report.File, report.Line = caller()
	report.StackTrace = fullStackTrace()
	report.Error = fmt.Sprintf("%v", err)
	return report
}
func NewSuccessReport() *AssertionResult {
	report := new(AssertionResult)
	report.File, report.Line = caller()
	report.StackTrace = fullStackTrace()
	return report
}
func NewSkipReport() *AssertionResult {
	report := new(AssertionResult)
	report.File, report.Line = caller()
	report.StackTrace = fullStackTrace()
	report.Skipped = true
	return report
}

func caller() (file string, line int) {
	file, line, _ = gotest.ResolveExternalCaller()
	return
}
func stackTrace() string {
	buffer := make([]byte, 1024*64)
	runtime.Stack(buffer, false)
	formatted := strings.Trim(string(buffer), string([]byte{0}))
	return removeInternalEntries(formatted)
}
func fullStackTrace() string {
	buffer := make([]byte, 1024*64)
	runtime.Stack(buffer, true)
	formatted := strings.Trim(string(buffer), string([]byte{0}))
	return removeInternalEntries(formatted)
}
func removeInternalEntries(stack string) string {
	lines := strings.Split(stack, newline)
	filtered := []string{}
	for _, line := range lines {
		if !isExternal(line) {
			filtered = append(filtered, line)
		}
	}
	return strings.Join(filtered, newline)
}
func isExternal(line string) bool {
	for _, p := range internalPackages {
		if strings.Contains(line, p) {
			return true
		}
	}
	return false
}

// NOTE: any new packages that host goconvey packages will need to be added here!
// An alternative is to scan the goconvey directory and then exclude stuff like
// the examples package but that's nasty too.
var internalPackages = []string{
	"goconvey/assertions",
	"goconvey/convey",
	"goconvey/execution",
	"goconvey/gotest",
	"goconvey/reporting",
}
<commit_msg>Use return value of runtime.Stack to trim stack trace.<commit_after>package reporting

import (
	"encoding/json"
	"fmt"
	"runtime"
	"strings"

	"github.com/smartystreets/goconvey/convey/gotest"
)

////////////////// ScopeReport ////////////////////

type ScopeReport struct {
	Title string
	ID    string
	File  string
	Line  int
}

func NewScopeReport(title, name string) *ScopeReport {
	file, line, _ := gotest.ResolveExternalCaller()
	self := new(ScopeReport)
	self.Title = title
	self.ID = fmt.Sprintf("%s|%s", title, name)
	self.File = file
	self.Line = line
	return self
}

////////////////// ScopeResult ////////////////////

type ScopeResult struct {
	Title      string
	File       string
	Line       int
	Depth      int
	Assertions []*AssertionResult
}

func newScopeResult(title string, depth int, file string, line int) *ScopeResult {
	self := new(ScopeResult)
	self.Title = title
	self.Depth = depth
	self.File = file
	self.Line = line
	self.Assertions = []*AssertionResult{}
	return self
}

/////////////////// StoryReport /////////////////////

type StoryReport struct {
	Test T
	Name string
	File string
	Line int
}

func NewStoryReport(test T) *StoryReport {
	file, line, name := gotest.ResolveExternalCaller()
	name = removePackagePath(name)
	self := new(StoryReport)
	self.Test = test
	self.Name = name
	self.File = file
	self.Line = line
	return self
}

// name comes in looking like "github.com/smartystreets/goconvey/examples.TestName".
// We only want the stuff after the last '.', which is the name of the test function.
func removePackagePath(name string) string {
	parts := strings.Split(name, ".")
	return parts[len(parts)-1]
}

/////////////////// FailureView ////////////////////////

type FailureView struct {
	Message  string
	Expected string
	Actual   string
}

////////////////////AssertionResult //////////////////////

type AssertionResult struct {
	File       string
	Line       int
	Expected   string
	Actual     string
	Failure    string
	Error      interface{}
	StackTrace string
	Skipped    bool
}

func NewFailureReport(failure string) *AssertionResult {
	report := new(AssertionResult)
	report.File, report.Line = caller()
	report.StackTrace = stackTrace()
	parseFailure(failure, report)
	return report
}
func parseFailure(failure string, report *AssertionResult) {
	view := new(FailureView)
	err := json.Unmarshal([]byte(failure), view)
	if err == nil {
		report.Failure = view.Message
		report.Expected = view.Expected
		report.Actual = view.Actual
	} else {
		report.Failure = failure
	}
}
func NewErrorReport(err interface{}) *AssertionResult {
	report := new(AssertionResult)
	report.File, report.Line = caller()
	report.StackTrace = fullStackTrace()
	report.Error = fmt.Sprintf("%v", err)
	return report
}
func NewSuccessReport() *AssertionResult {
	report := new(AssertionResult)
	report.File, report.Line = caller()
	report.StackTrace = fullStackTrace()
	return report
}
func NewSkipReport() *AssertionResult {
	report := new(AssertionResult)
	report.File, report.Line = caller()
	report.StackTrace = fullStackTrace()
	report.Skipped = true
	return report
}

func caller() (file string, line int) {
	file, line, _ = gotest.ResolveExternalCaller()
	return
}

func stackTrace() string {
	buffer := make([]byte, 1024*64)
	n := runtime.Stack(buffer, false)
	return removeInternalEntries(string(buffer[:n]))
}
func fullStackTrace() string {
	buffer := make([]byte, 1024*64)
	n := runtime.Stack(buffer, true)
	return removeInternalEntries(string(buffer[:n]))
}
func removeInternalEntries(stack string) string {
	lines := strings.Split(stack, newline)
	filtered := []string{}
	for _, line := range lines {
		if !isExternal(line) {
			filtered = append(filtered, line)
		}
	}
	return strings.Join(filtered, newline)
}
func isExternal(line string) bool {
	for _, p := range internalPackages {
		if strings.Contains(line, p) {
			return true
		}
	}
	return false
}

// NOTE: any new packages that host goconvey packages will need to be added here!
// An alternative is to scan the goconvey directory and then exclude stuff like
// the examples package but that's nasty too.
var internalPackages = []string{
	"goconvey/assertions",
	"goconvey/convey",
	"goconvey/execution",
	"goconvey/gotest",
	"goconvey/reporting",
}
<|endoftext|>


<commit_before>// Generic problem solving library with algorithms like A*, IDA*, Depth-first etc.
package solve

import (
	"math"
)

// The State representing a state in the search tree
//
// An implementation of this interface represents the problem. It tells the algorithm how
// to get from one state to another, how much it costs to reach the state etc.
type State interface {
	// The costs to reach this state
	Cost() float64

	// Returns true if this is a goal state
	IsGoal() bool

	// Expands this state in zero or more child states
	Expand() []State

	// Estimated costs to reach a goal. Use 0 for no heuristic. Most algorithms will
	// find the optimal solution if the heuristic is admissable, meaning it will never
	// over-estimate the costs to reach a goal
	Heuristic() float64

	// Returns an id that is used in constraints to reduce the search tree by
	// eliminating identical states. Can be nil if no constraint is used.
	//
	// Symmetrical states may return the same Id to eliminate even more branches of the
	// search tree
	//
	// The result must be comparable (like go map keys)
	Id() interface{}
}

// The result of the search
type Result struct {
	// The list of states leading from the root state to the goal state. If no solution
	// is found this list will be empty
	Solution []State

	// Number of nodes visited (dequeued) by the algorithm
	Visited  int

	// Number of nodes expanded (enqueued) by the algorithm
	Expanded int
}

type node struct {
	parent *node
	state  State
	value  float64
}

type result struct {
	node     *node
	contour  float64
	visited  int
	expanded int
}

func generalSearch(queue strategy, visited int, expanded int, constr iconstraint, limit float64) result {
	contour := math.Inf(1)

	for {
		n := queue.Take()
		if n == nil {
			return result{nil, contour, visited, expanded}
		}
		visited++
		if constr.onVisit(n) {
			continue
		}
		if n.state.IsGoal() {
			return result{n, contour, visited, expanded}
		}
		for _, child := range n.state.Expand() {
			childNode := &node{n, child, math.Max(n.value, child.Cost() + child.Heuristic())}
			if constr.onExpand(childNode) {
				continue
			}
			if childNode.value > limit {
				contour = math.Min(contour, childNode.value)
				continue
			}
			queue.Add(childNode)
			expanded++

		}

	}
	return result{nil, contour, visited, expanded}
}

func idaStar(rootState State, constraint Constraint, limit float64) result {
	visited := 0
	expanded := 0
	contour := 0.0
	for true {
		s := depthFirst()
		s.Add(&node{nil, rootState, rootState.Cost() + rootState.Heuristic()})
		lastResult := generalSearch(s, visited, expanded, createConstraint(constraint), contour)
		if lastResult.node != nil || lastResult.contour > limit || math.IsInf(lastResult.contour, 1) || math.IsNaN(lastResult.contour) {
			return lastResult
		}
		visited = lastResult.visited
		expanded = lastResult.expanded
		contour = lastResult.contour
	}
	panic("Shouldn't be reached")
}

func toSlice(node *node) []State {
	if node == nil {
		return make([]State, 0)
	}
	return append(toSlice(node.parent), node.state)
}

func solve(ss solver) Result {
	if ss.algorithm == IDAstar {
		result := idaStar(ss.rootState, ss.constraint, ss.limit)
		return Result{toSlice(result.node), result.visited, result.expanded}
	}
	var s strategy
	switch ss.algorithm {
	case Astar: s = aStar()
	case DepthFirst: s = depthFirst()
	case BreadthFirst: s = breadthFirst()
	}
	s.Add(&node{nil, ss.rootState, ss.rootState.Cost() + ss.rootState.Heuristic()})

	result := generalSearch(s, 0, 0, createConstraint(ss.constraint), ss.limit)
	return Result{toSlice(result.node), result.visited, result.expanded}
}

// Solver to solve the problem.
//
// Usage example:
//  result := solve.NewSolver(puzzle).
//          Algorithm(solve.IDAstar).
//          Constraint(solve.NO_LOOP).
//          Solve()
type Solver interface {
	// The algorithm to use, defaults to IDAstar
	Algorithm(algorithm Algorithm) Solver

	// The constraint to use, defaults to NONE
	Constraint(constraint Constraint) Solver

	// The limit to use. The problem will not be exanded beyond this limit. Defaults
	// to math.Inf(1).
	Limit(limit float64) Solver

	// Solves the problem returning the result
	Solve() Result
}
type solver struct {
	rootState  State
	algorithm  Algorithm
	constraint Constraint
	limit      float64
}

func (s *solver) Algorithm(algorithm Algorithm) Solver {
	s.algorithm = algorithm
	return s
}

func (s *solver) Constraint(constraint Constraint) Solver {
	s.constraint = constraint
	return s
}

func (s *solver) Limit(limit float64) Solver {
	s.limit = limit
	return s
}

func (s *solver) Solve() Result {
	return solve(*s)
}

// Creates a new solver
func NewSolver(rootState State) Solver {
	return &solver{rootState, Astar, NONE, math.MaxFloat64}
}
<commit_msg>Default limit of +infinity seems more appropriate than MaxFloat64<commit_after>// Generic problem solving library with algorithms like A*, IDA*, Depth-first etc.
package solve

import (
	"math"
)

// The State representing a state in the search tree
//
// An implementation of this interface represents the problem. It tells the algorithm how
// to get from one state to another, how much it costs to reach the state etc.
type State interface {
	// The costs to reach this state
	Cost() float64

	// Returns true if this is a goal state
	IsGoal() bool

	// Expands this state in zero or more child states
	Expand() []State

	// Estimated costs to reach a goal. Use 0 for no heuristic. Most algorithms will
	// find the optimal solution if the heuristic is admissable, meaning it will never
	// over-estimate the costs to reach a goal
	Heuristic() float64

	// Returns an id that is used in constraints to reduce the search tree by
	// eliminating identical states. Can be nil if no constraint is used.
	//
	// Symmetrical states may return the same Id to eliminate even more branches of the
	// search tree
	//
	// The result must be comparable (like go map keys)
	Id() interface{}
}

// The result of the search
type Result struct {
	// The list of states leading from the root state to the goal state. If no solution
	// is found this list will be empty
	Solution []State

	// Number of nodes visited (dequeued) by the algorithm
	Visited  int

	// Number of nodes expanded (enqueued) by the algorithm
	Expanded int
}

type node struct {
	parent *node
	state  State
	value  float64
}

type result struct {
	node     *node
	contour  float64
	visited  int
	expanded int
}

func generalSearch(queue strategy, visited int, expanded int, constr iconstraint, limit float64) result {
	contour := math.Inf(1)

	for {
		n := queue.Take()
		if n == nil {
			return result{nil, contour, visited, expanded}
		}
		visited++
		if constr.onVisit(n) {
			continue
		}
		if n.state.IsGoal() {
			return result{n, contour, visited, expanded}
		}
		for _, child := range n.state.Expand() {
			childNode := &node{n, child, math.Max(n.value, child.Cost() + child.Heuristic())}
			if constr.onExpand(childNode) {
				continue
			}
			if childNode.value > limit {
				contour = math.Min(contour, childNode.value)
				continue
			}
			queue.Add(childNode)
			expanded++

		}

	}
	return result{nil, contour, visited, expanded}
}

func idaStar(rootState State, constraint Constraint, limit float64) result {
	visited := 0
	expanded := 0
	contour := 0.0
	for true {
		s := depthFirst()
		s.Add(&node{nil, rootState, rootState.Cost() + rootState.Heuristic()})
		lastResult := generalSearch(s, visited, expanded, createConstraint(constraint), contour)
		if lastResult.node != nil || lastResult.contour > limit || math.IsInf(lastResult.contour, 1) || math.IsNaN(lastResult.contour) {
			return lastResult
		}
		visited = lastResult.visited
		expanded = lastResult.expanded
		contour = lastResult.contour
	}
	panic("Shouldn't be reached")
}

func toSlice(node *node) []State {
	if node == nil {
		return make([]State, 0)
	}
	return append(toSlice(node.parent), node.state)
}

func solve(ss solver) Result {
	if ss.algorithm == IDAstar {
		result := idaStar(ss.rootState, ss.constraint, ss.limit)
		return Result{toSlice(result.node), result.visited, result.expanded}
	}
	var s strategy
	switch ss.algorithm {
	case Astar: s = aStar()
	case DepthFirst: s = depthFirst()
	case BreadthFirst: s = breadthFirst()
	}
	s.Add(&node{nil, ss.rootState, ss.rootState.Cost() + ss.rootState.Heuristic()})

	result := generalSearch(s, 0, 0, createConstraint(ss.constraint), ss.limit)
	return Result{toSlice(result.node), result.visited, result.expanded}
}

// Solver to solve the problem.
//
// Usage example:
//  result := solve.NewSolver(puzzle).
//          Algorithm(solve.IDAstar).
//          Constraint(solve.NO_LOOP).
//          Solve()
type Solver interface {
	// The algorithm to use, defaults to IDAstar
	Algorithm(algorithm Algorithm) Solver

	// The constraint to use, defaults to NONE
	Constraint(constraint Constraint) Solver

	// The limit to use. The problem will not be exanded beyond this limit. Defaults
	// to math.Inf(1).
	Limit(limit float64) Solver

	// Solves the problem returning the result
	Solve() Result
}
type solver struct {
	rootState  State
	algorithm  Algorithm
	constraint Constraint
	limit      float64
}

func (s *solver) Algorithm(algorithm Algorithm) Solver {
	s.algorithm = algorithm
	return s
}

func (s *solver) Constraint(constraint Constraint) Solver {
	s.constraint = constraint
	return s
}

func (s *solver) Limit(limit float64) Solver {
	s.limit = limit
	return s
}

func (s *solver) Solve() Result {
	return solve(*s)
}

// Creates a new solver
func NewSolver(rootState State) Solver {
	return &solver{rootState, Astar, NONE, math.Inf(1)}
}
<|endoftext|>


<commit_before>// Package stack is a go implementation of the generic stack using slices.
//
// This is general implementation of the stack using slices and empty interface (interface{}) elements. This is convenient as one
// can use elements of any type to build a stack as long as one is carefull. It is advisable to use elements of the same type,
// though...
// Example usage is seen from the commented main function.
package forest

// Miran R., Jan2015

/*
package main

import (
    "fmt"
)
*/

// Stack is a generic implementation of the stack.
type Stack []interface{}

// IsEmpty checks if stack is empty.
func (s Stack) IsEmpty() bool { return len(s) == 0 }

// Len returns the length of the stack.
func (s Stack) Len() int { return len(s) }

// Peek  peeks into stack and returns the last value (value is not removed from stack).
func (s Stack) Peek() interface{} { return s[len(s)-1] }

// Push pushes the new value onto a stack.
func (s *Stack) Push(i interface{}) { *s = append(*s, i) }

// Pop pops the last value from the stack.
func (s *Stack) Pop() interface{} {
	d := (*s)[len(*s)-1]
	*s = (*s)[:len(*s)-1]
	return d
}

/*
func main() {

    var s Stack
    fmt.Printf("Is stack empty? %t\n", s.IsEmpty())
    fmt.Println(">> Pushing")
    s.Push("something")
    fmt.Printf("Is stack empty? %t\n", s.IsEmpty())
    fmt.Printf("Stack length: %d\n", s.Len())
    str := s.Peek()
    fmt.Printf("Peek element: %v\n", str)
    fmt.Println(">> Pushing")
    s.Push(0)
    elem := s.Peek()
    fmt.Printf("Stack length: %d\n", s.Len())
    fmt.Printf("Peek element: %v\n", elem)
    fmt.Println(">> Pushing")
    s.Push(3)
    s.Push(4)
    s.Push(5)
    fmt.Printf("Stack length: %d\n", s.Len())
    fmt.Printf("Peek element: %v\n", s.Peek())
    fmt.Println(">> Popping")
    elem = s.Pop()
    fmt.Printf("Stack length: %d\n", s.Len())
    fmt.Printf("Popped element: %d\n", elem)
    fmt.Printf("Peek element: %v\n", s.Peek())
    fmt.Println(">> Popping")
    elem = s.Pop()
    elem = s.Pop()
    elem = s.Pop()
    fmt.Printf("Stack length: %d\n", s.Len())
    fmt.Printf("Popped element: %d\n", elem)
    fmt.Printf("Peek element: %v\n", s.Peek())
    fmt.Println(">> Popping")
    elem = s.Pop()
    fmt.Printf("Popped element: %q\n", elem)
    if !s.IsEmpty() {
        fmt.Printf("Peek element: %v\n", s.Peek())
    } else {
        fmt.Printf("Stack IS empty!\n")
    }
}
*/
<commit_msg>nothing important, just comments<commit_after>package forest

// This is general implementation of the stack using slices and empty interface (interface{}) elements. This is convenient as one
// can use elements of any type to build a stack as long as one is carefull. It is advisable to use elements of the same type,
// though...
// Example usage is seen from the commented main function.

// Miran R., Jan2015

/*
package main

import (
    "fmt"
)
*/

// Stack is a generic implementation of the stack.
type Stack []interface{}

// IsEmpty checks if stack is empty.
func (s Stack) IsEmpty() bool { return len(s) == 0 }

// Len returns the length of the stack.
func (s Stack) Len() int { return len(s) }

// Peek  peeks into stack and returns the last value (value is not removed from stack).
func (s Stack) Peek() interface{} { return s[len(s)-1] }

// Push pushes the new value onto a stack.
func (s *Stack) Push(i interface{}) { *s = append(*s, i) }

// Pop pops the last value from the stack.
func (s *Stack) Pop() interface{} {
	d := (*s)[len(*s)-1]
	*s = (*s)[:len(*s)-1]
	return d
}

/*
func main() {

    var s Stack
    fmt.Printf("Is stack empty? %t\n", s.IsEmpty())
    fmt.Println(">> Pushing")
    s.Push("something")
    fmt.Printf("Is stack empty? %t\n", s.IsEmpty())
    fmt.Printf("Stack length: %d\n", s.Len())
    str := s.Peek()
    fmt.Printf("Peek element: %v\n", str)
    fmt.Println(">> Pushing")
    s.Push(0)
    elem := s.Peek()
    fmt.Printf("Stack length: %d\n", s.Len())
    fmt.Printf("Peek element: %v\n", elem)
    fmt.Println(">> Pushing")
    s.Push(3)
    s.Push(4)
    s.Push(5)
    fmt.Printf("Stack length: %d\n", s.Len())
    fmt.Printf("Peek element: %v\n", s.Peek())
    fmt.Println(">> Popping")
    elem = s.Pop()
    fmt.Printf("Stack length: %d\n", s.Len())
    fmt.Printf("Popped element: %d\n", elem)
    fmt.Printf("Peek element: %v\n", s.Peek())
    fmt.Println(">> Popping")
    elem = s.Pop()
    elem = s.Pop()
    elem = s.Pop()
    fmt.Printf("Stack length: %d\n", s.Len())
    fmt.Printf("Popped element: %d\n", elem)
    fmt.Printf("Peek element: %v\n", s.Peek())
    fmt.Println(">> Popping")
    elem = s.Pop()
    fmt.Printf("Popped element: %q\n", elem)
    if !s.IsEmpty() {
        fmt.Printf("Peek element: %v\n", s.Peek())
    } else {
        fmt.Printf("Stack IS empty!\n")
    }
}
*/
<|endoftext|>


<commit_before>// Package registry is the micro registry
package registry

import (
	"context"
	"fmt"
	"os"
	"strings"
	"sync"
	"time"

	"github.com/google/uuid"
	"github.com/micro/cli"
	"github.com/micro/go-micro"
	"github.com/micro/go-micro/client"
	"github.com/micro/go-micro/registry"
	"github.com/micro/go-micro/registry/handler"
	pb "github.com/micro/go-micro/registry/proto"
	"github.com/micro/go-micro/registry/service"
	"github.com/micro/go-micro/util/log"
	rcli "github.com/micro/micro/cli"
)

var (
	// Name of the registry
	Name = "go.micro.registry"
	// The address of the registry
	Address = ":8000"
	// Topic to publish registry events to
	Topic = "go.micro.registry.events"
	// SyncTime defines time interval to periodically sync registries
	SyncTime = 5 * time.Second
)

func ActionToEventType(action string) registry.EventType {
	switch action {
	case "create":
		return registry.Create
	case "delete":
		return registry.Delete
	default:
		return registry.Update
	}
}

// Sub processes registry events
type sub struct {
	// id is registry id
	id string
	// registry is service registry
	registry registry.Registry
}

// Process processes registry events
func (s *sub) Process(ctx context.Context, event *pb.Event) error {
	log.Logf("[registry] received %s event from: %s for: %s", registry.EventType(event.Type), event.Id, event.Service.Name)
	if event.Id == s.id {
		log.Logf("[registry] skipping event")
		return nil
	}

	// decode protobuf to registry.Service
	svc := service.ToService(event.Service)

	switch registry.EventType(event.Type) {
	case registry.Create, registry.Update:
		log.Logf("[registry] registering service: %s", svc.Name)
		if err := s.registry.Register(svc); err != nil {
			log.Logf("[registry] failed to register service: %s", svc.Name)
			return err
		}
	case registry.Delete:
		log.Logf("[registry] deregistering service: %s", svc.Name)
		if err := s.registry.Deregister(svc); err != nil {
			log.Logf("[registry] failed to deregister service: %s", svc.Name)
			return err
		}
	}

	return nil
}

// reg is micro registry
type reg struct {
	// registry is micro registry
	registry.Registry
	// id is registry id
	id string
	// client is service client
	client client.Client
	// exit stops the registry
	exit chan bool
}

// newRegsitry creates new micro registry and returns it
func newRegistry(service micro.Service, registry registry.Registry) *reg {
	id := uuid.New().String()
	s := &sub{
		id:       id,
		registry: registry,
	}

	// register subscriber
	if err := micro.RegisterSubscriber(Topic, service.Server(), s); err != nil {
		log.Logf("[registry] failed to subscribe to events: %s", err)
		os.Exit(1)
	}

	return &reg{
		Registry: registry,
		id:       id,
		client:   service.Client(),
		exit:     make(chan bool),
	}
}

// Publish publishes registry events to other registries to consume
func (r *reg) PublishEvents(w registry.Watcher) error {
	defer w.Stop()

	// create a publisher
	p := micro.NewPublisher(Topic, r.client)
	// track watcher errors
	var watchErr error

	for {
		res, err := w.Next()
		if err != nil {
			if err != registry.ErrWatcherStopped {
				watchErr = err
			}
			break
		}

		// encode *registry.Service into protobuf messag
		svc := service.ToProto(res.Service)

		// TODO: timestamp should be read from received event
		// Right now registry.Result does not contain timestamp
		event := &pb.Event{
			Id:        r.id,
			Type:      pb.EventType(ActionToEventType(res.Action)),
			Timestamp: time.Now().UnixNano(),
			Service:   svc,
		}

		log.Logf("[registry] publishing event %s for action %s", event.Id, res.Action)

		if err := p.Publish(context.Background(), event); err != nil {
			log.Logf("[registry] error publishing event: %v", err)
			return fmt.Errorf("error publishing event: %v", err)
		}
	}

	return watchErr
}

func (r *reg) syncRecords(nodes []string) error {
	if len(nodes) == 0 {
		log.Logf("[rgistry] no nodes to sync with. skipping")
		return nil
	}

	c := pb.NewRegistryService(Name, r.client)
	resp, err := c.ListServices(context.Background(), &pb.ListRequest{}, client.WithAddress(nodes...))
	if err != nil {
		log.Logf("[registry] failed sync: %v", err)
		return err
	}

	for _, pbService := range resp.Services {
		svc := service.ToService(pbService)
		log.Logf("[registry] registering service: %s", svc.Name)
		if err := r.Register(svc); err != nil {
			log.Logf("[registry] failed to register service: %v", svc.Name)
			return err
		}
	}

	return nil
}

func (r *reg) Sync(nodes []string) error {
	sync := time.NewTicker(SyncTime)
	defer sync.Stop()

	for {
		select {
		case <-r.exit:
			return nil
		case <-sync.C:
			log.Logf("[registry] syncing records")
			if err := r.syncRecords(nodes); err != nil {
				log.Logf("[registry] failed to sync registry records: %v", err)
				continue
			}
		}
	}

	return nil
}

func run(ctx *cli.Context, srvOpts ...micro.Option) {
	if len(ctx.GlobalString("server_name")) > 0 {
		Name = ctx.GlobalString("server_name")
	}
	if len(ctx.String("address")) > 0 {
		Address = ctx.String("address")
	}

	// Init plugins
	for _, p := range Plugins() {
		p.Init(ctx)
	}

	// service opts
	srvOpts = append(srvOpts, micro.Name(Name))
	if i := time.Duration(ctx.GlobalInt("register_ttl")); i > 0 {
		srvOpts = append(srvOpts, micro.RegisterTTL(i*time.Second))
	}
	if i := time.Duration(ctx.GlobalInt("register_interval")); i > 0 {
		srvOpts = append(srvOpts, micro.RegisterInterval(i*time.Second))
	}
	var nodes []string
	if len(ctx.String("nodes")) > 0 {
		nodes = strings.Split(ctx.String("nodes"), ",")
	}

	// set address
	if len(Address) > 0 {
		srvOpts = append(srvOpts, micro.Address(Address))
	}

	// new service
	service := micro.NewService(srvOpts...)

	pb.RegisterRegistryHandler(service.Server(), &handler.Registry{
		// using the mdns registry
		Registry: service.Options().Registry,
	})

	reg := newRegistry(service, service.Options().Registry)

	// create registry watcher
	watcher, err := service.Options().Registry.Watch()
	if err != nil {
		log.Logf("[registry] failed creating watcher: %v", err)
		os.Exit(1)
	}

	var wg sync.WaitGroup
	errChan := make(chan error, 3)

	wg.Add(1)
	go func() {
		defer wg.Done()
		errChan <- reg.PublishEvents(watcher)
	}()

	wg.Add(1)
	go func() {
		defer wg.Done()
		errChan <- reg.Sync(nodes)
	}()

	wg.Add(1)
	go func() {
		defer wg.Done()
		errChan <- service.Run()
	}()

	// we block here until either service or server fails
	if err := <-errChan; err != nil {
		log.Logf("[registry] error running the registry: %v", err)
		if err != registry.ErrWatcherStopped {
			watcher.Stop()
			close(reg.exit)
			os.Exit(1)
		}
		os.Exit(1)
	}

	// stop registry watcher
	watcher.Stop()
	close(reg.exit)

	wg.Wait()

	log.Logf("[registry] successfully stopped")
}

func Commands(options ...micro.Option) []cli.Command {
	command := cli.Command{
		Name:  "registry",
		Usage: "Run the service registry",
		Flags: []cli.Flag{
			cli.StringFlag{
				Name:   "address",
				Usage:  "Set the registry http address e.g 0.0.0.0:8080",
				EnvVar: "MICRO_REGISTRY_ADDRESS",
			},
			cli.StringFlag{
				Name:   "nodes",
				Usage:  "Set the micro registry nodes to connect to. This can be a comma separated list.",
				EnvVar: "MICRO_REGISTRY_NODES",
			},
		},
		Action: func(ctx *cli.Context) {
			run(ctx, options...)
		},
		Subcommands: rcli.RegistryCommands(),
	}

	for _, p := range Plugins() {
		if cmds := p.Commands(); len(cmds) > 0 {
			command.Subcommands = append(command.Subcommands, cmds...)
		}

		if flags := p.Flags(); len(flags) > 0 {
			command.Flags = append(command.Flags, flags...)
		}
	}

	return []cli.Command{command}
}
<commit_msg>Added Publish deadline, fixed log typo.<commit_after>// Package registry is the micro registry
package registry

import (
	"context"
	"fmt"
	"os"
	"strings"
	"sync"
	"time"

	"github.com/google/uuid"
	"github.com/micro/cli"
	"github.com/micro/go-micro"
	"github.com/micro/go-micro/client"
	"github.com/micro/go-micro/registry"
	"github.com/micro/go-micro/registry/handler"
	pb "github.com/micro/go-micro/registry/proto"
	"github.com/micro/go-micro/registry/service"
	"github.com/micro/go-micro/util/log"
	rcli "github.com/micro/micro/cli"
)

var (
	// Name of the registry
	Name = "go.micro.registry"
	// The address of the registry
	Address = ":8000"
	// Topic to publish registry events to
	Topic = "go.micro.registry.events"
	// SyncTime defines time interval to periodically sync registries
	SyncTime = 5 * time.Second
)

func ActionToEventType(action string) registry.EventType {
	switch action {
	case "create":
		return registry.Create
	case "delete":
		return registry.Delete
	default:
		return registry.Update
	}
}

// Sub processes registry events
type sub struct {
	// id is registry id
	id string
	// registry is service registry
	registry registry.Registry
}

// Process processes registry events
func (s *sub) Process(ctx context.Context, event *pb.Event) error {
	log.Logf("[registry] received %s event from: %s for: %s", registry.EventType(event.Type), event.Id, event.Service.Name)
	if event.Id == s.id {
		log.Logf("[registry] skipping event")
		return nil
	}

	// decode protobuf to registry.Service
	svc := service.ToService(event.Service)

	switch registry.EventType(event.Type) {
	case registry.Create, registry.Update:
		log.Logf("[registry] registering service: %s", svc.Name)
		if err := s.registry.Register(svc); err != nil {
			log.Logf("[registry] failed to register service: %s", svc.Name)
			return err
		}
	case registry.Delete:
		log.Logf("[registry] deregistering service: %s", svc.Name)
		if err := s.registry.Deregister(svc); err != nil {
			log.Logf("[registry] failed to deregister service: %s", svc.Name)
			return err
		}
	}

	return nil
}

// reg is micro registry
type reg struct {
	// registry is micro registry
	registry.Registry
	// id is registry id
	id string
	// client is service client
	client client.Client
	// exit stops the registry
	exit chan bool
}

// newRegsitry creates new micro registry and returns it
func newRegistry(service micro.Service, registry registry.Registry) *reg {
	id := uuid.New().String()
	s := &sub{
		id:       id,
		registry: registry,
	}

	// register subscriber
	if err := micro.RegisterSubscriber(Topic, service.Server(), s); err != nil {
		log.Logf("[registry] failed to subscribe to events: %s", err)
		os.Exit(1)
	}

	return &reg{
		Registry: registry,
		id:       id,
		client:   service.Client(),
		exit:     make(chan bool),
	}
}

// Publish publishes registry events to other registries to consume
func (r *reg) PublishEvents(w registry.Watcher) error {
	defer w.Stop()

	// create a publisher
	p := micro.NewPublisher(Topic, r.client)
	// track watcher errors
	var watchErr error

	for {
		res, err := w.Next()
		if err != nil {
			if err != registry.ErrWatcherStopped {
				watchErr = err
			}
			break
		}

		// encode *registry.Service into protobuf messag
		svc := service.ToProto(res.Service)

		// TODO: timestamp should be read from received event
		// Right now registry.Result does not contain timestamp
		event := &pb.Event{
			Id:        r.id,
			Type:      pb.EventType(ActionToEventType(res.Action)),
			Timestamp: time.Now().UnixNano(),
			Service:   svc,
		}

		log.Logf("[registry] publishing event %s for action %s", event.Id, res.Action)

		select {
		case <-r.exit:
			return nil
		default:
			ctx, _ := context.WithTimeout(context.Background(), 5*time.Second)
			if err := p.Publish(ctx, event); err != nil {
				log.Logf("[registry] error publishing event: %v", err)
				return fmt.Errorf("error publishing event: %v", err)
			}
		}
	}

	return watchErr
}

func (r *reg) syncRecords(nodes []string) error {
	if len(nodes) == 0 {
		log.Logf("[registry] no nodes to sync with. skipping")
		return nil
	}

	c := pb.NewRegistryService(Name, r.client)
	resp, err := c.ListServices(context.Background(), &pb.ListRequest{}, client.WithAddress(nodes...))
	if err != nil {
		log.Logf("[registry] failed sync: %v", err)
		return err
	}

	for _, pbService := range resp.Services {
		svc := service.ToService(pbService)
		log.Logf("[registry] registering service: %s", svc.Name)
		if err := r.Register(svc); err != nil {
			log.Logf("[registry] failed to register service: %v", svc.Name)
			return err
		}
	}

	return nil
}

func (r *reg) Sync(nodes []string) error {
	sync := time.NewTicker(SyncTime)
	defer sync.Stop()

	for {
		select {
		case <-r.exit:
			return nil
		case <-sync.C:
			log.Logf("[registry] syncing records")
			if err := r.syncRecords(nodes); err != nil {
				log.Logf("[registry] failed to sync registry records: %v", err)
				continue
			}
		}
	}

	return nil
}

func run(ctx *cli.Context, srvOpts ...micro.Option) {
	if len(ctx.GlobalString("server_name")) > 0 {
		Name = ctx.GlobalString("server_name")
	}
	if len(ctx.String("address")) > 0 {
		Address = ctx.String("address")
	}

	// Init plugins
	for _, p := range Plugins() {
		p.Init(ctx)
	}

	// service opts
	srvOpts = append(srvOpts, micro.Name(Name))
	if i := time.Duration(ctx.GlobalInt("register_ttl")); i > 0 {
		srvOpts = append(srvOpts, micro.RegisterTTL(i*time.Second))
	}
	if i := time.Duration(ctx.GlobalInt("register_interval")); i > 0 {
		srvOpts = append(srvOpts, micro.RegisterInterval(i*time.Second))
	}
	var nodes []string
	if len(ctx.String("nodes")) > 0 {
		nodes = strings.Split(ctx.String("nodes"), ",")
	}

	// set address
	if len(Address) > 0 {
		srvOpts = append(srvOpts, micro.Address(Address))
	}

	// new service
	service := micro.NewService(srvOpts...)

	pb.RegisterRegistryHandler(service.Server(), &handler.Registry{
		// using the mdns registry
		Registry: service.Options().Registry,
	})

	reg := newRegistry(service, service.Options().Registry)

	// create registry watcher
	watcher, err := service.Options().Registry.Watch()
	if err != nil {
		log.Logf("[registry] failed creating watcher: %v", err)
		os.Exit(1)
	}

	var wg sync.WaitGroup
	errChan := make(chan error, 3)

	wg.Add(1)
	go func() {
		defer wg.Done()
		errChan <- reg.PublishEvents(watcher)
	}()

	wg.Add(1)
	go func() {
		defer wg.Done()
		errChan <- reg.Sync(nodes)
	}()

	wg.Add(1)
	go func() {
		defer wg.Done()
		errChan <- service.Run()
	}()

	// we block here until either service or server fails
	if err := <-errChan; err != nil {
		log.Logf("[registry] error running the registry: %v", err)
		if err != registry.ErrWatcherStopped {
			watcher.Stop()
			close(reg.exit)
			os.Exit(1)
		}
		os.Exit(1)
	}

	// stop registry watcher
	watcher.Stop()
	close(reg.exit)

	wg.Wait()

	log.Logf("[registry] successfully stopped")
}

func Commands(options ...micro.Option) []cli.Command {
	command := cli.Command{
		Name:  "registry",
		Usage: "Run the service registry",
		Flags: []cli.Flag{
			cli.StringFlag{
				Name:   "address",
				Usage:  "Set the registry http address e.g 0.0.0.0:8080",
				EnvVar: "MICRO_REGISTRY_ADDRESS",
			},
			cli.StringFlag{
				Name:   "nodes",
				Usage:  "Set the micro registry nodes to connect to. This can be a comma separated list.",
				EnvVar: "MICRO_REGISTRY_NODES",
			},
		},
		Action: func(ctx *cli.Context) {
			run(ctx, options...)
		},
		Subcommands: rcli.RegistryCommands(),
	}

	for _, p := range Plugins() {
		if cmds := p.Commands(); len(cmds) > 0 {
			command.Subcommands = append(command.Subcommands, cmds...)
		}

		if flags := p.Flags(); len(flags) > 0 {
			command.Flags = append(command.Flags, flags...)
		}
	}

	return []cli.Command{command}
}
<|endoftext|>


<commit_before>package handlers

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

	"io/ioutil"

	"github.com/alexellis/faas/gateway/metrics"
	"github.com/alexellis/faas/gateway/requests"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/filters"
	"github.com/docker/docker/api/types/swarm"
	"github.com/docker/docker/client"
	"github.com/prometheus/client_golang/prometheus"
	io_prometheus_client "github.com/prometheus/client_model/go"
)

func getCounterValue(service string, code string, metricsOptions *metrics.MetricOptions) float64 {

	metric, err := metricsOptions.GatewayFunctionInvocation.
		GetMetricWith(prometheus.Labels{"function_name": service, "code": code})

	if err != nil {
		return 0
	}

	// Get the metric's value from ProtoBuf interface (idea via Julius Volz)
	var protoMetric io_prometheus_client.Metric
	metric.Write(&protoMetric)
	invocations := protoMetric.GetCounter().GetValue()
	return invocations
}

// MakeFunctionReader gives a summary of Function structs with Docker service stats overlaid with Prometheus counters.
func MakeFunctionReader(metricsOptions metrics.MetricOptions, c *client.Client) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {

		serviceFilter := filters.NewArgs()

		options := types.ServiceListOptions{
			Filters: serviceFilter,
		}

		services, err := c.ServiceList(context.Background(), options)
		if err != nil {
			fmt.Println(err)
		}

		// TODO: Filter only "faas" functions (via metadata?)
		var functions []requests.Function

		for _, service := range services {

			if len(service.Spec.TaskTemplate.ContainerSpec.Labels["function"]) > 0 {
				invocations := getCounterValue(service.Spec.Name, "200", &metricsOptions) +
					getCounterValue(service.Spec.Name, "500", &metricsOptions)

				f := requests.Function{
					Name:            service.Spec.Name,
					Image:           service.Spec.TaskTemplate.ContainerSpec.Image,
					InvocationCount: invocations,
					Replicas:        *service.Spec.Mode.Replicated.Replicas,
				}
				functions = append(functions, f)
			}
		}

		functionBytes, _ := json.Marshal(functions)
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(200)
		w.Write(functionBytes)
	}
}

// MakeNewFunctionHandler creates a new function (service) inside the swarm network.
func MakeNewFunctionHandler(metricsOptions metrics.MetricOptions, c *client.Client) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		defer r.Body.Close()
		body, _ := ioutil.ReadAll(r.Body)

		request := requests.CreateFunctionRequest{}
		err := json.Unmarshal(body, &request)
		if err != nil {
			w.WriteHeader(http.StatusBadRequest)
			return
		}

		fmt.Println(request)

		// TODO: review why this was here... debugging?
		// w.WriteHeader(http.StatusNotImplemented)

		options := types.ServiceCreateOptions{}
		spec := makeSpec(&request)

		response, err := c.ServiceCreate(context.Background(), spec, options)
		if err != nil {
			log.Println(err)
		}
		log.Println(response.ID, response.Warnings)
	}
}

func makeSpec(request *requests.CreateFunctionRequest) swarm.ServiceSpec {
	max := uint64(1)

	nets := []swarm.NetworkAttachmentConfig{
		swarm.NetworkAttachmentConfig{Target: request.Network},
	}

	spec := swarm.ServiceSpec{
		TaskTemplate: swarm.TaskSpec{
			RestartPolicy: &swarm.RestartPolicy{
				MaxAttempts: &max,
				Condition:   swarm.RestartPolicyConditionNone,
			},
			ContainerSpec: swarm.ContainerSpec{
				Image:  request.Image,
				Env:    []string{fmt.Sprintf("fprocess=%s", request.EnvProcess)},
				Labels: map[string]string{"function": "true"},
			},
			Networks: nets,
		},
		Annotations: swarm.Annotations{
			Name: request.Service,
		},
	}
	return spec
}
<commit_msg>Add comment<commit_after>package handlers

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

	"io/ioutil"

	"github.com/alexellis/faas/gateway/metrics"
	"github.com/alexellis/faas/gateway/requests"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/filters"
	"github.com/docker/docker/api/types/swarm"
	"github.com/docker/docker/client"
	"github.com/prometheus/client_golang/prometheus"
	io_prometheus_client "github.com/prometheus/client_model/go"
)

func getCounterValue(service string, code string, metricsOptions *metrics.MetricOptions) float64 {

	metric, err := metricsOptions.GatewayFunctionInvocation.
		GetMetricWith(prometheus.Labels{"function_name": service, "code": code})

	if err != nil {
		return 0
	}

	// Get the metric's value from ProtoBuf interface (idea via Julius Volz)
	var protoMetric io_prometheus_client.Metric
	metric.Write(&protoMetric)
	invocations := protoMetric.GetCounter().GetValue()
	return invocations
}

// MakeFunctionReader gives a summary of Function structs with Docker service stats overlaid with Prometheus counters.
func MakeFunctionReader(metricsOptions metrics.MetricOptions, c *client.Client) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {

		serviceFilter := filters.NewArgs()

		options := types.ServiceListOptions{
			Filters: serviceFilter,
		}

		services, err := c.ServiceList(context.Background(), options)
		if err != nil {
			fmt.Println(err)
		}

		// TODO: Filter only "faas" functions (via metadata?)
		var functions []requests.Function

		for _, service := range services {

			if len(service.Spec.TaskTemplate.ContainerSpec.Labels["function"]) > 0 {
				invocations := getCounterValue(service.Spec.Name, "200", &metricsOptions) +
					getCounterValue(service.Spec.Name, "500", &metricsOptions)

				f := requests.Function{
					Name:            service.Spec.Name,
					Image:           service.Spec.TaskTemplate.ContainerSpec.Image,
					InvocationCount: invocations,
					Replicas:        *service.Spec.Mode.Replicated.Replicas,
				}
				functions = append(functions, f)
			}
		}

		functionBytes, _ := json.Marshal(functions)
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(200)
		w.Write(functionBytes)
	}
}

// MakeNewFunctionHandler creates a new function (service) inside the swarm network.
func MakeNewFunctionHandler(metricsOptions metrics.MetricOptions, c *client.Client) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		defer r.Body.Close()
		body, _ := ioutil.ReadAll(r.Body)

		request := requests.CreateFunctionRequest{}
		err := json.Unmarshal(body, &request)
		if err != nil {
			w.WriteHeader(http.StatusBadRequest)
			return
		}

		fmt.Println(request)

		// TODO: review why this was here... debugging?
		// w.WriteHeader(http.StatusNotImplemented)

		options := types.ServiceCreateOptions{}
		spec := makeSpec(&request)

		response, err := c.ServiceCreate(context.Background(), spec, options)
		if err != nil {
			log.Println(err)
		}
		log.Println(response.ID, response.Warnings)
	}
}

func makeSpec(request *requests.CreateFunctionRequest) swarm.ServiceSpec {
	max := uint64(1)

	nets := []swarm.NetworkAttachmentConfig{
		swarm.NetworkAttachmentConfig{Target: request.Network},
	}

	// TODO: request.EnvProcess should only be set if it's not nil, otherwise we override anything in the Docker image already

	spec := swarm.ServiceSpec{
		TaskTemplate: swarm.TaskSpec{
			RestartPolicy: &swarm.RestartPolicy{
				MaxAttempts: &max,
				Condition:   swarm.RestartPolicyConditionNone,
			},
			ContainerSpec: swarm.ContainerSpec{
				Image:  request.Image,
				Env:    []string{fmt.Sprintf("fprocess=%s", request.EnvProcess)},
				Labels: map[string]string{"function": "true"},
			},
			Networks: nets,
		},
		Annotations: swarm.Annotations{
			Name: request.Service,
		},
	}
	return spec
}
<|endoftext|>


<commit_before>// parsing mathematical expressions
//
//go:generate nex lexer.nex
//go:generate go tool yacc -o parser.y.go parser.y
package parser

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"math/rand"
	"os"
	"os/exec"
	"sort"
	"strconv"
	"strings"
	"text/template"
)

// don't name any varibles like this prefix in your expressions:
const private = "x_a8b32499"

var formula string = Formula(3)

func Formula(n int) string {
	var terms []string
	for i := 0; i < n; i++ {
		term := fmt.Sprintf("%f * x%d", rand.Float64(), i)
		terms = append(terms, term)
	}
	return fmt.Sprintf("f := sqrt(x) + pow(a,b) + a-b+c/d + log(1 + exp(-y * (%s)))", strings.Join(terms, "+"))
}

func computeDerivatives(w io.Writer, steps []Step) {
	n := len(steps)
	for i := 0; i < n; i++ {
		j := n - i - 1
		step := steps[j]
		x0 := 0.0
		if i == 0 {
			x0 = 1.0
		}
		fmt.Fprintf(w, "b%s := %f\n", step.lhs, x0)
		for k := j + 1; k < n; k++ {
			s3 := steps[k]
			if d := derivative(s3, step); len(d) > 0 {
				fmt.Fprintf(w, "b%s += b%s * %s\n", step.lhs, s3.lhs, d)
			}
		}
		if step.decl {
			fmt.Fprintf(w, "grad_%s[\"%s\"] = b%s\n", private, step.rhs, step.lhs)
		}
	}
}

type Step struct {
	decl bool
	lhs  string
	rhs  string
	f    string
	args []string
}

func derivative(num, denom Step) string {
	var args []int
	for i, a := range num.args {
		if a == denom.lhs {
			args = append(args, i)
		}
	}
	if len(args) == 0 {
		return ""
	}
	var list []string
	for _, a := range args {
		list = append(list, fmt.Sprintf("d_%s_%s(%d,%s)", private, num.f, a, strings.Join(num.args, ",")))
	}
	return strings.Join(list, "+")
}

type NodeType string

const (
	numberNT     NodeType = "NUM"
	identifierNT NodeType = "IDENT"
	functionNT   NodeType = "FUNC"
)

type Node struct {
	Type     NodeType `json:"T,omitempty"`
	S        string   `json:",omitempty"`
	F        float64  `json:",omitempty"`
	Children []*Node  `json:"C,omitempty"`
	Name     string   `json:"N,omitempty"`
}

func (n Node) String() string {
	buf, err := json.Marshal(n)
	check(err)
	return string(buf)
}

func Run(args []string) {
	lex := NewContext(NewLexer(strings.NewReader(formula)))
	yyParse(lex)
	vars := make(map[string]string)
	vp := &VarParser{vars: vars}
	sp := &StepParser{vars: vars}
	var steps []Step
	steps = append(steps, vp.getVars(lex.rhs)...)
	steps = append(steps, sp.program(lex.rhs)...)
	y := steps[len(steps)-1].lhs

	checker := new(bytes.Buffer)
	if true {
		dx := 0.00001
		fmt.Fprintf(checker, "delta_%s := %f\n", private, dx)
		fmt.Fprintf(checker, `calc_%s := func() float64 {
%s
return %s
}
`, private, formula, lex.lhs.S)
		fmt.Fprintf(checker, "tmp1_%s := calc_%s()\n", private, private)
		for k := range vars {
			fmt.Fprintln(checker, "{")
			fmt.Fprintf(checker, "%s += delta_%s\n", k, private)
			fmt.Fprintf(checker, "tmp2_%s := calc_%s()\n", private, private)
			fmt.Fprintf(checker, "%s -= delta_%s\n", k, private)
			fmt.Fprintf(checker, "grad_%s[%q] = (tmp2_%s - tmp1_%s)/delta_%s\n", private, k, private, private, private)
			fmt.Fprintln(checker, "}")
		}
	}

	pgm := new(bytes.Buffer)
	for _, s := range steps {
		fmt.Fprintln(pgm, s)
	}
	computeDerivatives(pgm, steps)
	var list []string
	for v := range vars {
		list = append(list, v)
	}
	sort.Strings(list)

	f, err := os.Create("compute.go")
	check(err)

	decls := new(bytes.Buffer)
	for _, v := range list {
		fmt.Fprintf(decls, "%s := rand.Float64();\n", v)
		fmt.Fprintf(decls, "fmt.Printf(\"%s = %%f\\n\",%s)\n", v, v)
	}

	t := template.Must(template.New("compute.go").Parse(`package main
import (
"fmt"
"math"
"time"
"math/rand"
)
func main() {
fmt.Println("running compute.go");
rand.Seed(time.Now().UTC().UnixNano())
{{.decls}}

	c1, grad1 := ComputeAD({{.vars}})
	fmt.Printf("ad value: %f\n", c1)
	fmt.Printf("ad grad : %v\n", grad1)

	c2, grad2 := ComputeNumerical({{.vars}})
	fmt.Printf("num value: %f\n", c2)
	fmt.Printf("num grad : %v\n", grad2)

	var total float64
	add := func(n string, x float64) {
		fmt.Printf("diff %s: %f\n", n, x)
		total += math.Abs(x)
	}
	add("value", c1-c2)
	for k, v := range grad2 {
		add(fmt.Sprintf("grad[%3s]", k), grad1[k]-v)
	}
fmt.Printf("*** total diffs: %f\n",total);
}

{{.funcs}}

func ComputeAD({{.vars}} float64) (float64,map[string]float64) {
grad_{{.private}} := make(map[string]float64)
{{.program}} return {{.y}},grad_{{.private}};
}

func ComputeNumerical({{.vars}} float64) (float64,map[string]float64) {
grad_{{.private}} := make(map[string]float64)
{{.checker}} return tmp1_{{.private}},grad_{{.private}};
}

`))

	t.Execute(f, map[string]interface{}{
		"decls":   decls.String(),
		"formula": formula,
		"lhs":     lex.lhs.S,
		"vars":    strings.Join(list, ", "),
		"program": pgm.String(),
		"checker": checker.String(),
		"y":       y,
		"funcs":   Functions(private),
		"private": private,
	})

	f.Close()
	cmd := exec.Command("gofmt", "-w", "compute.go")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		log.Fatalf("oops: %v\n", err)
	}
}

type VarParser struct {
	i    int
	vars map[string]string
}

// gets all the vars and names them in tree
func (v *VarParser) getVars(rhs *Node) (out []Step) {
	switch rhs.Type {
	case identifierNT:
		if _, ok := v.vars[rhs.S]; !ok {
			rhs.Name = fmt.Sprintf("v_%d_%s", v.i, private)
			v.vars[rhs.S] = rhs.Name
			v.i++
			step := Step{
				decl: true,
				lhs:  rhs.Name,
				rhs:  rhs.S,
			}
			out = append(out, step)
		} else {
			rhs.Name = v.vars[rhs.S]
		}
	case functionNT:
		for _, n := range rhs.Children {
			out = append(out, v.getVars(n)...)
		}
	}
	return
}

type StepParser struct {
	i    int
	vars map[string]string
}

func (s Step) String() string {
	return fmt.Sprintf("%s := %s;", s.lhs, s.rhs)
}

func (s *StepParser) program(rhs *Node) (out []Step) {
	switch rhs.Type {
	case numberNT:
		rhs.Name = fmt.Sprintf("%f", rhs.F)
	case functionNT:
		var args []string
		for _, n := range rhs.Children {
			steps := s.program(n)
			out = append(out, steps...)
			args = append(args, n.Name)
		}
		step := Step{
			lhs:  fmt.Sprintf("s_%d_%s", s.i, private),
			rhs:  fmt.Sprintf("%s_%s(%s)", private, rhs.S, strings.Join(args, ",")),
			f:    rhs.S,
			args: args,
		}
		out = append(out, step)
		rhs.Name = step.lhs
		s.i++
	}
	return out
}

func Function(ident string, args ...*Node) *Node {
	return &Node{
		Type:     functionNT,
		S:        ident,
		Children: args,
	}
}

func Number(n float64) *Node {
	return &Node{
		Type: numberNT,
		F:    n,
	}
}

func LexIdentifier(s string) *Node {
	return &Node{
		Type: identifierNT,
		S:    s,
	}
}

func LexNumber(s string) *Node {
	n, err := strconv.ParseFloat(s, 64)
	check(err)
	return Number(n)
}

func Negate(a *Node) *Node {
	return Function("multiply", Number(-1), a)
}

type context struct {
	lhs *Node
	rhs *Node
	yyLexer
}

func NewContext(y yyLexer) *context {
	return &context{yyLexer: y}
}

func (context) Error(e string) {
	log.Printf("oops: %v\n", e)
	os.Exit(1)
}

func check(e error) {
	if e != nil {
		panic(e)
	}
}
<commit_msg>bug seems to be in square root<commit_after>// parsing mathematical expressions
//
//go:generate nex lexer.nex
//go:generate go tool yacc -o parser.y.go parser.y
package parser

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"math/rand"
	"os"
	"os/exec"
	"sort"
	"strconv"
	"strings"
	"text/template"
)

// don't name any varibles like this prefix in your expressions:
const private = "x_a8b32499"

var formula string = Formula(3)

func Formula(n int) string {
	var terms []string
	for i := 0; i < n; i++ {
		term := fmt.Sprintf("%f * x%d", rand.Float64(), i)
		terms = append(terms, term)
	}
	return fmt.Sprintf("f := sqrt(a) + pow(a,b) + a-b+c/d + log(1 + exp(-y * (%s)))", strings.Join(terms, "+"))
}

func computeDerivatives(w io.Writer, steps []Step) {
	n := len(steps)
	for i := 0; i < n; i++ {
		j := n - i - 1
		step := steps[j]
		x0 := 0.0
		if i == 0 {
			x0 = 1.0
		}
		fmt.Fprintf(w, "b%s := %f\n", step.lhs, x0)
		for k := j + 1; k < n; k++ {
			s3 := steps[k]
			if d := derivative(s3, step); len(d) > 0 {
				fmt.Fprintf(w, "b%s += b%s * %s\n", step.lhs, s3.lhs, d)
			}
		}
		if step.decl {
			fmt.Fprintf(w, "grad_%s[\"%s\"] = b%s\n", private, step.rhs, step.lhs)
		}
	}
}

type Step struct {
	decl bool
	lhs  string
	rhs  string
	f    string
	args []string
}

func derivative(num, denom Step) string {
	var args []int
	for i, a := range num.args {
		if a == denom.lhs {
			args = append(args, i)
		}
	}
	if len(args) == 0 {
		return ""
	}
	var list []string
	for _, a := range args {
		list = append(list, fmt.Sprintf("d_%s_%s(%d,%s)", private, num.f, a, strings.Join(num.args, ",")))
	}
	return strings.Join(list, "+")
}

type NodeType string

const (
	numberNT     NodeType = "NUM"
	identifierNT NodeType = "IDENT"
	functionNT   NodeType = "FUNC"
)

type Node struct {
	Type     NodeType `json:"T,omitempty"`
	S        string   `json:",omitempty"`
	F        float64  `json:",omitempty"`
	Children []*Node  `json:"C,omitempty"`
	Name     string   `json:"N,omitempty"`
}

func (n Node) String() string {
	buf, err := json.Marshal(n)
	check(err)
	return string(buf)
}

func Run(args []string) {
	lex := NewContext(NewLexer(strings.NewReader(formula)))
	yyParse(lex)
	vars := make(map[string]string)
	vp := &VarParser{vars: vars}
	sp := &StepParser{vars: vars}
	var steps []Step
	steps = append(steps, vp.getVars(lex.rhs)...)
	steps = append(steps, sp.program(lex.rhs)...)
	y := steps[len(steps)-1].lhs

	checker := new(bytes.Buffer)
	if true {
		dx := 0.00001
		fmt.Fprintf(checker, "delta_%s := %f\n", private, dx)
		fmt.Fprintf(checker, `calc_%s := func() float64 {
%s
return %s
}
`, private, formula, lex.lhs.S)
		fmt.Fprintf(checker, "tmp1_%s := calc_%s()\n", private, private)
		for k := range vars {
			fmt.Fprintln(checker, "{")
			fmt.Fprintf(checker, "%s += delta_%s\n", k, private)
			fmt.Fprintf(checker, "tmp2_%s := calc_%s()\n", private, private)
			fmt.Fprintf(checker, "%s -= delta_%s\n", k, private)
			fmt.Fprintf(checker, "grad_%s[%q] = (tmp2_%s - tmp1_%s)/delta_%s\n", private, k, private, private, private)
			fmt.Fprintln(checker, "}")
		}
	}

	pgm := new(bytes.Buffer)
	for _, s := range steps {
		fmt.Fprintln(pgm, s)
	}
	computeDerivatives(pgm, steps)
	var list []string
	for v := range vars {
		list = append(list, v)
	}
	sort.Strings(list)

	f, err := os.Create("compute.go")
	check(err)

	decls := new(bytes.Buffer)
	for _, v := range list {
		fmt.Fprintf(decls, "%s := rand.Float64();\n", v)
		fmt.Fprintf(decls, "fmt.Printf(\"%s = %%f\\n\",%s)\n", v, v)
	}

	t := template.Must(template.New("compute.go").Parse(`package main
import (
"fmt"
"math"
"time"
"math/rand"
)
func main() {
fmt.Println("running compute.go");
rand.Seed(time.Now().UTC().UnixNano())
{{.decls}}

	c1, grad1 := ComputeAD({{.vars}})
	fmt.Printf("ad value: %f\n", c1)
	fmt.Printf("ad grad : %v\n", grad1)

	c2, grad2 := ComputeNumerical({{.vars}})
	fmt.Printf("num value: %f\n", c2)
	fmt.Printf("num grad : %v\n", grad2)

	var total float64
	add := func(n string, x float64) {
		fmt.Printf("diff %s: %f\n", n, x)
		total += math.Abs(x)
	}
	add("value", c1-c2)
	for k, v := range grad2 {
		add(fmt.Sprintf("grad[%3s]", k), grad1[k]-v)
	}
fmt.Printf("*** total diffs: %f\n",total);
}

{{.funcs}}

func ComputeAD({{.vars}} float64) (float64,map[string]float64) {
grad_{{.private}} := make(map[string]float64)
{{.program}} return {{.y}},grad_{{.private}};
}

func ComputeNumerical({{.vars}} float64) (float64,map[string]float64) {
grad_{{.private}} := make(map[string]float64)
{{.checker}} return tmp1_{{.private}},grad_{{.private}};
}

`))

	t.Execute(f, map[string]interface{}{
		"decls":   decls.String(),
		"formula": formula,
		"lhs":     lex.lhs.S,
		"vars":    strings.Join(list, ", "),
		"program": pgm.String(),
		"checker": checker.String(),
		"y":       y,
		"funcs":   Functions(private),
		"private": private,
	})

	f.Close()
	cmd := exec.Command("gofmt", "-w", "compute.go")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		log.Fatalf("oops: %v\n", err)
	}
}

type VarParser struct {
	i    int
	vars map[string]string
}

// gets all the vars and names them in tree
func (v *VarParser) getVars(rhs *Node) (out []Step) {
	switch rhs.Type {
	case identifierNT:
		if _, ok := v.vars[rhs.S]; !ok {
			rhs.Name = fmt.Sprintf("v_%d_%s", v.i, private)
			v.vars[rhs.S] = rhs.Name
			v.i++
			step := Step{
				decl: true,
				lhs:  rhs.Name,
				rhs:  rhs.S,
			}
			out = append(out, step)
		} else {
			rhs.Name = v.vars[rhs.S]
		}
	case functionNT:
		for _, n := range rhs.Children {
			out = append(out, v.getVars(n)...)
		}
	}
	return
}

type StepParser struct {
	i    int
	vars map[string]string
}

func (s Step) String() string {
	return fmt.Sprintf("%s := %s;", s.lhs, s.rhs)
}

func (s *StepParser) program(rhs *Node) (out []Step) {
	switch rhs.Type {
	case numberNT:
		rhs.Name = fmt.Sprintf("%f", rhs.F)
	case functionNT:
		var args []string
		for _, n := range rhs.Children {
			steps := s.program(n)
			out = append(out, steps...)
			args = append(args, n.Name)
		}
		step := Step{
			lhs:  fmt.Sprintf("s_%d_%s", s.i, private),
			rhs:  fmt.Sprintf("%s_%s(%s)", private, rhs.S, strings.Join(args, ",")),
			f:    rhs.S,
			args: args,
		}
		out = append(out, step)
		rhs.Name = step.lhs
		s.i++
	}
	return out
}

func Function(ident string, args ...*Node) *Node {
	return &Node{
		Type:     functionNT,
		S:        ident,
		Children: args,
	}
}

func Number(n float64) *Node {
	return &Node{
		Type: numberNT,
		F:    n,
	}
}

func LexIdentifier(s string) *Node {
	return &Node{
		Type: identifierNT,
		S:    s,
	}
}

func LexNumber(s string) *Node {
	n, err := strconv.ParseFloat(s, 64)
	check(err)
	return Number(n)
}

func Negate(a *Node) *Node {
	return Function("multiply", Number(-1), a)
}

type context struct {
	lhs *Node
	rhs *Node
	yyLexer
}

func NewContext(y yyLexer) *context {
	return &context{yyLexer: y}
}

func (context) Error(e string) {
	log.Printf("oops: %v\n", e)
	os.Exit(1)
}

func check(e error) {
	if e != nil {
		panic(e)
	}
}
<|endoftext|>