<commit_before>package orm

import (
	"context"
	"database/sql"
	"errors"
	"fmt"
	"github.com/rbastic/dyndao/object"
	"github.com/rbastic/dyndao/schema"
	"strings"
)

var (
	crossJoinSQL = "SELECT %s FROM %s p, %s c WHERE p.%s = %s AND p.%s = c.%s"
)

func (o *ORM) crossJoinHelper(ctx context.Context, tx *sql.Tx, parentTbl, childTbl, queryField string, queryVal interface{}, linkField string, sqlStr string, bindArgs []interface{}, allAliases []string, parentSchTbl *schema.Table, childSchTbl *schema.Table) (*object.Array, error) {
	sg := o.GetSQLBuilder()

	// Determines whether we are running inside a transaction or not,
	// returning stmt either way
	stmt, err := stmtFromDbOrTx(ctx, o, tx, sqlStr)
	if err != nil {
		return nil, err
	}

	defer func() {
		stmtErr := stmt.Close()
		if stmtErr != nil {
			o.Debug("%s", err)
			err = stmtErr
		}
	}()

	var res *sql.Rows
	if len(bindArgs) > 0 {
		res, err = stmt.Query(bindArgs...)
		if err != nil {
			return nil, err
		}
	} else {
		res, err = stmt.Query()
		if err != nil {
			return nil, err
		}
	}

	defer func() {
		resErr := res.Close()
		if resErr != nil {
			sg.Debug("%s", err)
			err = resErr
		}
	}()

	columnTypes, err := res.ColumnTypes()
	if err != nil {
		return nil, err
	}

	// TODO: Do I need to call MakeColumnPointers twice, once for each set of columns, then append?
	columnPointers, err := sg.MakeColumnPointers(sg, parentSchTbl, allAliases, columnTypes)
	if err != nil {
		return nil, err
	}

	var objectArray object.Array
	for res.Next() {
		if err := res.Scan(columnPointers...); err != nil {
			if sg.Tracing {
				o.Debug("CrossJoin/res.Scan err= "+err.Error()+" columnPointers=%s\n", columnPointers...)
			}

			return nil, err
		}

		// Bind the main response object object
		obj := object.New("INTERIM")
		err = sg.BindObject(sg, parentSchTbl, allAliases, columnPointers, columnTypes, obj)
		if err != nil {
			return nil, err
		}

		obj.MarkDirty(false)
		obj.ResetChangedColumns()

		topObj, err := o.mapFromInterim(ctx, tx, obj, parentSchTbl, childSchTbl)
		if err != nil {

			return nil, err
		}
		objectArray = append(objectArray, topObj)
	}

	err = res.Err()
	if err != nil {
		return nil, err
	}

	return &objectArray, nil
}

func (o *ORM) mapFromInterim(ctx context.Context, tx *sql.Tx, input *object.Object, parentSchTbl, childSchTbl *schema.Table) (*object.Object, error) {
	parent := object.New(parentSchTbl.Name)
	child := object.New(childSchTbl.Name)

	for k, v := range input.KV {
		if strings.HasPrefix(k, "P_") {
			realK := strings.TrimPrefix(k, "P_")
			parent.Set(realK, v)
		} else if strings.HasPrefix(k, "C_") {
			realK := strings.TrimPrefix(k, "C_")
			child.Set(realK, v)
		} else {
			return nil, errors.New("mapFromInterim: unknown prefix on key: " + k)
		}
	}

	// Call after retrieve hook
	err := o.CallAfterRetrieveHookIfNeeded(ctx, tx, parent)
	if err != nil {
		o.Error("%s %s %s", "dyndao", "AfterRetrieveHookError", err)
		return nil, err
	}

	// Call after retrieve hook
	err = o.CallAfterRetrieveHookIfNeeded(ctx, tx, child)
	if err != nil {
		o.Error("%s %s %s", "dyndao", "AfterRetrieveHookError", err)
		return nil, err
	}

	parent.Children[childSchTbl.Name] = object.NewArray(child)
	return parent, nil
}

func (o *ORM) CrossJoin(ctx context.Context, tx *sql.Tx, parentTbl, childTbl, queryField string, queryVal interface{}, linkField string) (*object.Array, error) {
	sch := o.GetSchema()
	parentSchTbl := sch.GetTable(parentTbl)
	queryCol := parentSchTbl.GetColumn(queryField)
	if queryCol == nil {
		return nil, errors.New("CrossJoin: schema is missing column definition for queryField")
	}

	childSchTbl := sch.GetTable(childTbl)
	allCols, allAliases := o.JoinEssentialColumns(sch, parentSchTbl, childSchTbl, parentTbl, "p", childTbl, "c")
	allColsStr := strings.Join(allCols, ",")

	bindingQueryVal := o.GenPlaceholder(queryCol, 1)
	fmtSql := fmt.Sprintf(crossJoinSQL, allColsStr, parentTbl, childTbl, queryField, bindingQueryVal, linkField, linkField)

	bindArgs := make([]interface{}, 1)
	bindArgs[0] = queryVal

	o.Debug("CrossJoin SQL='%s' bindArgs=%v allAliases=%v", fmtSql, bindArgs, allAliases)

	return o.crossJoinHelper(ctx, tx, parentTbl, childTbl, queryField, queryVal, linkField, fmtSql, bindArgs, allAliases, parentSchTbl, childSchTbl)
}

func (o *ORM) JoinEssentialColumns(sch *schema.Schema, parentSchTbl *schema.Table, childSchTbl *schema.Table, parentTbl, parentAlias, childTbl, childAlias string) ([]string, []string) {
	b := o.GetSQLBuilder()
	parentCols, parentAliasNames := b.ColumnsAliasedJoin(parentSchTbl.EssentialColumns, parentAlias)

	childCols, childAliasNames := b.ColumnsAliasedJoin(childSchTbl.EssentialColumns, childAlias)

	var allCols []string
	var aliasNames []string
	allCols = append(allCols, parentCols...)
	allCols = append(allCols, childCols...)
	aliasNames = append(aliasNames, parentAliasNames...)
	aliasNames = append(aliasNames, childAliasNames...)
	return allCols, aliasNames
}
<commit_msg>CrossJoins: complete for now.<commit_after>package orm

import (
	"context"
	"database/sql"
	"errors"
	"fmt"
	"github.com/rbastic/dyndao/object"
	"github.com/rbastic/dyndao/schema"
	"strings"
)

var (
	crossJoinSQL = "SELECT %s FROM %s p, %s c WHERE p.%s = %s AND p.%s = c.%s"
)

func (o *ORM) crossJoinHelper(ctx context.Context, tx *sql.Tx, parentTbl, childTbl, queryField string, queryVal interface{}, linkField string, sqlStr string, bindArgs []interface{}, allAliases []string, parentSchTbl *schema.Table, childSchTbl *schema.Table) (*object.Array, error) {
	sg := o.GetSQLBuilder()

	// Determines whether we are running inside a transaction or not,
	// returning stmt either way
	stmt, err := stmtFromDbOrTx(ctx, o, tx, sqlStr)
	if err != nil {
		return nil, err
	}

	defer func() {
		stmtErr := stmt.Close()
		if stmtErr != nil {
			o.Debug("%s", err)
			err = stmtErr
		}
	}()

	var res *sql.Rows
	if len(bindArgs) > 0 {
		res, err = stmt.Query(bindArgs...)
		if err != nil {
			return nil, err
		}
	} else {
		res, err = stmt.Query()
		if err != nil {
			return nil, err
		}
	}

	defer func() {
		resErr := res.Close()
		if resErr != nil {
			sg.Debug("%s", err)
			err = resErr
		}
	}()

	columnTypes, err := res.ColumnTypes()
	if err != nil {
		return nil, err
	}

	columnPointers, err := sg.MakeColumnPointers(sg, parentSchTbl, allAliases, columnTypes)
	if err != nil {
		return nil, err
	}

	var objectArray object.Array
	for res.Next() {
		if err := res.Scan(columnPointers...); err != nil {
			if sg.Tracing {
				o.Debug("CrossJoin/res.Scan err= "+err.Error()+" columnPointers=%s\n", columnPointers...)
			}

			return nil, err
		}

		// Bind the main response object object
		obj := object.New("INTERIM")
		err = sg.BindObject(sg, parentSchTbl, allAliases, columnPointers, columnTypes, obj)
		if err != nil {
			return nil, err
		}

		obj.MarkDirty(false)
		obj.ResetChangedColumns()

		topObj, err := o.mapFromInterim(ctx, tx, obj, parentSchTbl, childSchTbl)
		if err != nil {

			return nil, err
		}
		objectArray = append(objectArray, topObj)
	}

	err = res.Err()
	if err != nil {
		return nil, err
	}

	return &objectArray, nil
}

func (o *ORM) mapFromInterim(ctx context.Context, tx *sql.Tx, input *object.Object, parentSchTbl, childSchTbl *schema.Table) (*object.Object, error) {
	parent := object.New(parentSchTbl.Name)
	child := object.New(childSchTbl.Name)

	for k, v := range input.KV {
		// -HACK- Use P_ and C_ column alias prefixes internally
		if strings.HasPrefix(k, "P_") {
			realK := strings.TrimPrefix(k, "P_")
			parent.Set(realK, v)
		} else if strings.HasPrefix(k, "C_") {
			realK := strings.TrimPrefix(k, "C_")
			child.Set(realK, v)
		} else {
			return nil, errors.New("mapFromInterim: unknown prefix on key: " + k)
		}
	}

	// Call after retrieve hook
	err := o.CallAfterRetrieveHookIfNeeded(ctx, tx, parent)
	if err != nil {
		o.Error("%s %s %s", "dyndao", "AfterRetrieveHookError", err)
		return nil, err
	}

	// Call after retrieve hook
	err = o.CallAfterRetrieveHookIfNeeded(ctx, tx, child)
	if err != nil {
		o.Error("%s %s %s", "dyndao", "AfterRetrieveHookError", err)
		return nil, err
	}

	parent.Children[childSchTbl.Name] = object.NewArray(child)
	return parent, nil
}

func (o *ORM) CrossJoin(ctx context.Context, tx *sql.Tx, parentTbl, childTbl, queryField string, queryVal interface{}, linkField string) (*object.Array, error) {
	sch := o.GetSchema()
	parentSchTbl := sch.GetTable(parentTbl)
	queryCol := parentSchTbl.GetColumn(queryField)
	if queryCol == nil {
		return nil, errors.New("CrossJoin: schema is missing column definition for queryField")
	}

	childSchTbl := sch.GetTable(childTbl)
	allCols, allAliases := o.JoinEssentialColumns(sch, parentSchTbl, childSchTbl, parentTbl, "p", childTbl, "c")
	allColsStr := strings.Join(allCols, ",")

	bindingQueryVal := o.GenPlaceholder(queryCol, 1)
	fmtSql := fmt.Sprintf(crossJoinSQL, allColsStr, parentTbl, childTbl, queryField, bindingQueryVal, linkField, linkField)

	bindArgs := make([]interface{}, 1)
	bindArgs[0] = queryVal

	o.Debug("CrossJoin SQL='%s' bindArgs=%v allAliases=%v", fmtSql, bindArgs, allAliases)

	return o.crossJoinHelper(ctx, tx, parentTbl, childTbl, queryField, queryVal, linkField, fmtSql, bindArgs, allAliases, parentSchTbl, childSchTbl)
}

func (o *ORM) JoinEssentialColumns(sch *schema.Schema, parentSchTbl *schema.Table, childSchTbl *schema.Table, parentTbl, parentAlias, childTbl, childAlias string) ([]string, []string) {
	b := o.GetSQLBuilder()
	parentCols, parentAliasNames := b.ColumnsAliasedJoin(parentSchTbl.EssentialColumns, parentAlias)

	childCols, childAliasNames := b.ColumnsAliasedJoin(childSchTbl.EssentialColumns, childAlias)

	var allCols []string
	var aliasNames []string
	allCols = append(allCols, parentCols...)
	allCols = append(allCols, childCols...)
	aliasNames = append(aliasNames, parentAliasNames...)
	aliasNames = append(aliasNames, childAliasNames...)
	return allCols, aliasNames
}
<|endoftext|>


<commit_before>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 fs_test

import (
	"github.com/jacobsa/comeback/fs"
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
	"io"
	"os"
	"path"
	"testing"
)

func TestCreate(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

type CreateFileTest struct {
	fileSystemTest

	path  string
	perms os.FileMode

	w io.WriteCloser
	err error
}

func init() { RegisterTestSuite(&CreateFileTest{}) }

func (t *CreateFileTest) SetUp(i *TestInfo) {
	// Common
	t.fileSystemTest.SetUp(i)

	// Set up defaults.
	t.path = path.Join(t.baseDir, "taco")
	t.perms = 0644
}

func (t *CreateFileTest) call() {
	t.w, t.err = t.fileSystem.CreateFile(t.path, t.perms)
}

func (t *CreateFileTest) list() []*fs.DirectoryEntry {
	entries, err := t.fileSystem.ReadDir(t.baseDir)
	AssertEq(nil, err)
	return entries
}

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *CreateFileTest) NonExistentParent() {
	t.path = "/foo/bar/baz/qux"

	// Call
	t.call()

	ExpectThat(t.err, Error(HasSubstr("qux")))
	ExpectThat(t.err, Error(HasSubstr("no such")))
}

func (t *CreateFileTest) NoPermissionsForParent() {
	ExpectEq("TODO", "")
}

func (t *CreateFileTest) FileAlreadyExists() {
	ExpectEq("TODO", "")
}

func (t *CreateFileTest) SetsPermissions() {
	ExpectEq("TODO", "")
}

func (t *CreateFileTest) SavesDataToCorrectPlace() {
	ExpectEq("TODO", "")
}
<commit_msg>CreateFileTest.NoPermissionsForParent<commit_after>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 fs_test

import (
	"github.com/jacobsa/comeback/fs"
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
	"io"
	"os"
	"path"
	"testing"
)

func TestCreate(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

type CreateFileTest struct {
	fileSystemTest

	path  string
	perms os.FileMode

	w io.WriteCloser
	err error
}

func init() { RegisterTestSuite(&CreateFileTest{}) }

func (t *CreateFileTest) SetUp(i *TestInfo) {
	// Common
	t.fileSystemTest.SetUp(i)

	// Set up defaults.
	t.path = path.Join(t.baseDir, "taco")
	t.perms = 0644
}

func (t *CreateFileTest) call() {
	t.w, t.err = t.fileSystem.CreateFile(t.path, t.perms)
}

func (t *CreateFileTest) list() []*fs.DirectoryEntry {
	entries, err := t.fileSystem.ReadDir(t.baseDir)
	AssertEq(nil, err)
	return entries
}

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *CreateFileTest) NonExistentParent() {
	t.path = "/foo/bar/baz/qux"

	// Call
	t.call()

	ExpectThat(t.err, Error(HasSubstr("qux")))
	ExpectThat(t.err, Error(HasSubstr("no such")))
}

func (t *CreateFileTest) NoPermissionsForParent() {
	dirpath := path.Join(t.baseDir, "foo")
	t.path = path.Join(dirpath, "taco")

	// Parent
	err := os.Mkdir(dirpath, 0100)
	AssertEq(nil, err)

	// Call
	t.call()

	ExpectThat(t.err, Error(HasSubstr("TODO")))
}

func (t *CreateFileTest) FileAlreadyExists() {
	ExpectEq("TODO", "")
}

func (t *CreateFileTest) SetsPermissions() {
	ExpectEq("TODO", "")
}

func (t *CreateFileTest) SavesDataToCorrectPlace() {
	ExpectEq("TODO", "")
}
<|endoftext|>


<commit_before>package vagrant

import (
	"fmt"
	"path/filepath"
	"strings"

	"github.com/hashicorp/packer/packer"
)

type LibVirtProvider struct{}

func (p *LibVirtProvider) KeepInputArtifact() bool {
	return false
}
func (p *LibVirtProvider) Process(ui packer.Ui, artifact packer.Artifact, dir string) (vagrantfile string, metadata map[string]interface{}, err error) {
	diskName := artifact.State("diskName").(string)

	// Copy the disk image into the temporary directory (as box.img)
	for _, path := range artifact.Files() {
		if strings.HasSuffix(path, "/"+diskName) {
			ui.Message(fmt.Sprintf("Copying from artifact: %s", path))
			dstPath := filepath.Join(dir, "box.img")
			if err = CopyContents(dstPath, path); err != nil {
				return
			}
		}
	}

	format := artifact.State("diskType").(string)
	origSize := artifact.State("diskSize").(uint64)
	size := origSize / 1024 // In MB, want GB
	if origSize%1024 > 0 {
		// Make sure we don't make the size smaller
		size++
	}
	domainType := artifact.State("domainType").(string)

	// Convert domain type to libvirt driver
	var driver string
	switch domainType {
	case "none", "tcg":
		driver = "qemu"
	case "kvm":
		driver = domainType
	default:
		return "", nil, fmt.Errorf("Unknown libvirt domain type: %s", domainType)
	}

	// Create the metadata
	metadata = map[string]interface{}{
		"provider":     "libvirt",
		"format":       format,
		"virtual_size": size,
	}

	vagrantfile = fmt.Sprintf(libvirtVagrantfile, driver)
	return
}

var libvirtVagrantfile = `
Vagrant.configure("2") do |config|
  config.vm.provider :libvirt do |libvirt|
    libvirt.driver = "%s"
  end
end
`
<commit_msg>qemu: Add "hvf" as a libvirt driver<commit_after>package vagrant

import (
	"fmt"
	"path/filepath"
	"strings"

	"github.com/hashicorp/packer/packer"
)

type LibVirtProvider struct{}

func (p *LibVirtProvider) KeepInputArtifact() bool {
	return false
}
func (p *LibVirtProvider) Process(ui packer.Ui, artifact packer.Artifact, dir string) (vagrantfile string, metadata map[string]interface{}, err error) {
	diskName := artifact.State("diskName").(string)

	// Copy the disk image into the temporary directory (as box.img)
	for _, path := range artifact.Files() {
		if strings.HasSuffix(path, "/"+diskName) {
			ui.Message(fmt.Sprintf("Copying from artifact: %s", path))
			dstPath := filepath.Join(dir, "box.img")
			if err = CopyContents(dstPath, path); err != nil {
				return
			}
		}
	}

	format := artifact.State("diskType").(string)
	origSize := artifact.State("diskSize").(uint64)
	size := origSize / 1024 // In MB, want GB
	if origSize%1024 > 0 {
		// Make sure we don't make the size smaller
		size++
	}
	domainType := artifact.State("domainType").(string)

	// Convert domain type to libvirt driver
	var driver string
	switch domainType {
	case "none", "tcg", "hvf":
		driver = "qemu"
	case "kvm":
		driver = domainType
	default:
		return "", nil, fmt.Errorf("Unknown libvirt domain type: %s", domainType)
	}

	// Create the metadata
	metadata = map[string]interface{}{
		"provider":     "libvirt",
		"format":       format,
		"virtual_size": size,
	}

	vagrantfile = fmt.Sprintf(libvirtVagrantfile, driver)
	return
}

var libvirtVagrantfile = `
Vagrant.configure("2") do |config|
  config.vm.provider :libvirt do |libvirt|
    libvirt.driver = "%s"
  end
end
`
<|endoftext|>


<commit_before>//
// Copyright (c) 2015 The heketi 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 rest

import (
	"github.com/gorilla/mux"
	"github.com/heketi/utils"
	"github.com/lpabon/godbc"
	"net/http"
	"sync"
	"time"
)

var (
	logger = utils.NewLogger("[asynchttp]", utils.LEVEL_INFO)
)

// Contains information about the asynchronous operation
type AsyncHttpHandler struct {
	err          error
	completed    bool
	manager      *AsyncHttpManager
	location, id string
}

// Manager of asynchronous operations
type AsyncHttpManager struct {
	lock     sync.RWMutex
	route    string
	handlers map[string]*AsyncHttpHandler
}

// Creates a new manager
func NewAsyncHttpManager(route string) *AsyncHttpManager {
	return &AsyncHttpManager{
		route:    route,
		handlers: make(map[string]*AsyncHttpHandler),
	}
}

// Use to create a new asynchronous operation handler.
// Only use this function if you need to do every step by hand.
// It is recommended to use AsyncHttpRedirectFunc() instead
func (a *AsyncHttpManager) NewHandler() *AsyncHttpHandler {
	handler := &AsyncHttpHandler{
		manager: a,
		id:      utils.GenUUID(),
	}

	a.lock.Lock()
	defer a.lock.Unlock()

	a.handlers[handler.id] = handler

	return handler
}

// Create an asynchronous operation handler and return the appropiate
// information the caller.
// This function will call handlerfunc() in a new go routine, then
// return to the caller a HTTP status 202 setting up the `Location` header
// to point to the new asynchronous handler.
//
// If handlerfunc() returns failure, the asynchronous handler will return
// an http status of 500 and save the error string in the body.
// If handlerfunc() is successful and returns a location url path in "string",
// the asynchronous handler will return 303 (See Other) with the Location
// header set to the value returned in the string.
// If handlerfunc() is successful and returns an empty string, then the
// asynchronous handler will return 204 to the caller.
//
// Example:
//      package rest
//		import (
//			"github.com/gorilla/mux"
//          "github.com/heketi/heketi/rest"
//			"net/http"
//			"net/http/httptest"
//			"time"
//		)
//
//		// Setup asynchronous manager
//		route := "/x"
//		manager := rest.NewAsyncHttpManager(route)
//
//		// Setup the route
//		router := mux.NewRouter()
//	 	router.HandleFunc(route+"/{id}", manager.HandlerStatus).Methods("GET")
//		router.HandleFunc("/result", func(w http.ResponseWriter, r *http.Request) {
//			w.Header().Set("Content-Type", "text/plain; charset=UTF-8")
//			w.WriteHeader(http.StatusOK)
//			fmt.Fprint(w, "HelloWorld")
//		}).Methods("GET")
//
//		router.HandleFunc("/app", func(w http.ResponseWriter, r *http.Request) {
//			manager.AsyncHttpRedirectFunc(w, r, func() (string, error) {
//				time.Sleep(100 * time.Millisecond)
//				return "/result", nil
//			})
//		}).Methods("GET")
//
//		// Setup the server
//		ts := httptest.NewServer(router)
//		defer ts.Close()
//
func (a *AsyncHttpManager) AsyncHttpRedirectFunc(w http.ResponseWriter,
	r *http.Request,
	handlerfunc func() (string, error)) {

	handler := a.NewHandler()
	go func() {
		logger.Info("Started job %v", handler.id)

		ts := time.Now()
		url, err := handlerfunc()
		logger.Info("Completed job %v in %v", handler.id, time.Since(ts))

		if err != nil {
			handler.CompletedWithError(err)
		} else if url != "" {
			handler.CompletedWithLocation(url)
		} else {
			handler.Completed()
		}
	}()
	http.Redirect(w, r, handler.Url(), http.StatusAccepted)
}

// Handler for asynchronous operation status
// Register this handler with a router like Gorilla Mux
//
// Returns the following HTTP status codes
// 		200 Operation is still pending
//		404 Id requested does not exist
//		500 Operation finished and has failed.  Body will be filled in with the
//			error in plain text.
//		303 Operation finished and has setup a new location to retreive data.
//		204 Operation finished and has no data to return
//
// Example:
//      package rest
//		import (
//			"github.com/gorilla/mux"
//          "github.com/heketi/heketi/rest"
//			"net/http"
//			"net/http/httptest"
//			"time"
//		)
//
//		// Setup asynchronous manager
//		route := "/x"
//		manager := rest.NewAsyncHttpManager(route)
//
//		// Setup the route
//		router := mux.NewRouter()
//	 	router.HandleFunc(route+"/{id:[A-Fa-f0-9]+}", manager.HandlerStatus).Methods("GET")
//
//		// Setup the server
//		ts := httptest.NewServer(router)
//		defer ts.Close()
//
func (a *AsyncHttpManager) HandlerStatus(w http.ResponseWriter, r *http.Request) {
	// Get the id from the URL
	vars := mux.Vars(r)
	id := vars["id"]

	a.lock.Lock()
	defer a.lock.Unlock()

	// Check the id is in the map
	if handler, ok := a.handlers[id]; ok {

		if handler.completed {
			if handler.err != nil {

				// Return 500 status
				http.Error(w, handler.err.Error(), http.StatusInternalServerError)
			} else {
				if handler.location != "" {

					// Redirect to new location
					http.Redirect(w, r, handler.location, http.StatusSeeOther)
				} else {

					// Return 204 status
					w.WriteHeader(http.StatusNoContent)
				}
			}

			// It has been completed, we can now remove it from the map
			delete(a.handlers, id)
		} else {
			// Still pending
			// Could add a JSON body here later
			w.Header().Add("X-Pending", "true")
			w.WriteHeader(http.StatusOK)
		}

	} else {
		http.Error(w, "Id not found", http.StatusNotFound)
	}
}

// Returns the url for the specified asynchronous handler
func (h *AsyncHttpHandler) Url() string {
	h.manager.lock.RLock()
	defer h.manager.lock.RUnlock()

	return h.manager.route + "/" + h.id
}

// Registers that the handler has completed with an error
func (h *AsyncHttpHandler) CompletedWithError(err error) {

	h.manager.lock.RLock()
	defer h.manager.lock.RUnlock()

	godbc.Require(h.completed == false)

	h.err = err
	h.completed = true

	godbc.Ensure(h.completed == true)
}

// Registers that the handler has completed and has provided a location
// where information can be retreived
func (h *AsyncHttpHandler) CompletedWithLocation(location string) {

	h.manager.lock.RLock()
	defer h.manager.lock.RUnlock()

	godbc.Require(h.completed == false)

	h.location = location
	h.completed = true

	godbc.Ensure(h.completed == true)
	godbc.Ensure(h.location == location)
	godbc.Ensure(h.err == nil)
}

// Registers that the handler has completed and no data needs to be returned
func (h *AsyncHttpHandler) Completed() {

	h.manager.lock.RLock()
	defer h.manager.lock.RUnlock()

	godbc.Require(h.completed == false)

	h.completed = true

	godbc.Ensure(h.completed == true)
	godbc.Ensure(h.location == "")
	godbc.Ensure(h.err == nil)
}
<commit_msg>Updated comments<commit_after>//
// Copyright (c) 2015 The heketi 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 rest

import (
	"github.com/gorilla/mux"
	"github.com/heketi/utils"
	"github.com/lpabon/godbc"
	"net/http"
	"sync"
	"time"
)

var (
	logger = utils.NewLogger("[asynchttp]", utils.LEVEL_INFO)
)

// Contains information about the asynchronous operation
type AsyncHttpHandler struct {
	err          error
	completed    bool
	manager      *AsyncHttpManager
	location, id string
}

// Manager of asynchronous operations
type AsyncHttpManager struct {
	lock     sync.RWMutex
	route    string
	handlers map[string]*AsyncHttpHandler
}

// Creates a new manager
func NewAsyncHttpManager(route string) *AsyncHttpManager {
	return &AsyncHttpManager{
		route:    route,
		handlers: make(map[string]*AsyncHttpHandler),
	}
}

// Use to create a new asynchronous operation handler.
// Only use this function if you need to do every step by hand.
// It is recommended to use AsyncHttpRedirectFunc() instead
func (a *AsyncHttpManager) NewHandler() *AsyncHttpHandler {
	handler := &AsyncHttpHandler{
		manager: a,
		id:      utils.GenUUID(),
	}

	a.lock.Lock()
	defer a.lock.Unlock()

	a.handlers[handler.id] = handler

	return handler
}

// Create an asynchronous operation handler and return the appropiate
// information the caller.
// This function will call handlerfunc() in a new go routine, then
// return to the caller a HTTP status 202 setting up the `Location` header
// to point to the new asynchronous handler.
//
// If handlerfunc() returns failure, the asynchronous handler will return
// an http status of 500 and save the error string in the body.
// If handlerfunc() is successful and returns a location url path in "string",
// the asynchronous handler will return 303 (See Other) with the Location
// header set to the value returned in the string.
// If handlerfunc() is successful and returns an empty string, then the
// asynchronous handler will return 204 to the caller.
//
// Example:
//      package rest
//		import (
//			"github.com/gorilla/mux"
//          "github.com/heketi/rest"
//			"net/http"
//			"net/http/httptest"
//			"time"
//		)
//
//		// Setup asynchronous manager
//		route := "/x"
//		manager := rest.NewAsyncHttpManager(route)
//
//		// Setup the route
//		router := mux.NewRouter()
//	 	router.HandleFunc(route+"/{id}", manager.HandlerStatus).Methods("GET")
//		router.HandleFunc("/result", func(w http.ResponseWriter, r *http.Request) {
//			w.Header().Set("Content-Type", "text/plain; charset=UTF-8")
//			w.WriteHeader(http.StatusOK)
//			fmt.Fprint(w, "HelloWorld")
//		}).Methods("GET")
//
//		router.HandleFunc("/app", func(w http.ResponseWriter, r *http.Request) {
//			manager.AsyncHttpRedirectFunc(w, r, func() (string, error) {
//				time.Sleep(100 * time.Millisecond)
//				return "/result", nil
//			})
//		}).Methods("GET")
//
//		// Setup the server
//		ts := httptest.NewServer(router)
//		defer ts.Close()
//
func (a *AsyncHttpManager) AsyncHttpRedirectFunc(w http.ResponseWriter,
	r *http.Request,
	handlerfunc func() (string, error)) {

	handler := a.NewHandler()
	go func() {
		logger.Info("Started job %v", handler.id)

		ts := time.Now()
		url, err := handlerfunc()
		logger.Info("Completed job %v in %v", handler.id, time.Since(ts))

		if err != nil {
			handler.CompletedWithError(err)
		} else if url != "" {
			handler.CompletedWithLocation(url)
		} else {
			handler.Completed()
		}
	}()
	http.Redirect(w, r, handler.Url(), http.StatusAccepted)
}

// Handler for asynchronous operation status
// Register this handler with a router like Gorilla Mux
//
// Returns the following HTTP status codes
// 		200 Operation is still pending
//		404 Id requested does not exist
//		500 Operation finished and has failed.  Body will be filled in with the
//			error in plain text.
//		303 Operation finished and has setup a new location to retreive data.
//		204 Operation finished and has no data to return
//
// Example:
//      package rest
//		import (
//			"github.com/gorilla/mux"
//          "github.com/heketi/rest"
//			"net/http"
//			"net/http/httptest"
//			"time"
//		)
//
//		// Setup asynchronous manager
//		route := "/x"
//		manager := rest.NewAsyncHttpManager(route)
//
//		// Setup the route
//		router := mux.NewRouter()
//	 	router.HandleFunc(route+"/{id:[A-Fa-f0-9]+}", manager.HandlerStatus).Methods("GET")
//
//		// Setup the server
//		ts := httptest.NewServer(router)
//		defer ts.Close()
//
func (a *AsyncHttpManager) HandlerStatus(w http.ResponseWriter, r *http.Request) {
	// Get the id from the URL
	vars := mux.Vars(r)
	id := vars["id"]

	a.lock.Lock()
	defer a.lock.Unlock()

	// Check the id is in the map
	if handler, ok := a.handlers[id]; ok {

		if handler.completed {
			if handler.err != nil {

				// Return 500 status
				http.Error(w, handler.err.Error(), http.StatusInternalServerError)
			} else {
				if handler.location != "" {

					// Redirect to new location
					http.Redirect(w, r, handler.location, http.StatusSeeOther)
				} else {

					// Return 204 status
					w.WriteHeader(http.StatusNoContent)
				}
			}

			// It has been completed, we can now remove it from the map
			delete(a.handlers, id)
		} else {
			// Still pending
			// Could add a JSON body here later
			w.Header().Add("X-Pending", "true")
			w.WriteHeader(http.StatusOK)
		}

	} else {
		http.Error(w, "Id not found", http.StatusNotFound)
	}
}

// Returns the url for the specified asynchronous handler
func (h *AsyncHttpHandler) Url() string {
	h.manager.lock.RLock()
	defer h.manager.lock.RUnlock()

	return h.manager.route + "/" + h.id
}

// Registers that the handler has completed with an error
func (h *AsyncHttpHandler) CompletedWithError(err error) {

	h.manager.lock.RLock()
	defer h.manager.lock.RUnlock()

	godbc.Require(h.completed == false)

	h.err = err
	h.completed = true

	godbc.Ensure(h.completed == true)
}

// Registers that the handler has completed and has provided a location
// where information can be retreived
func (h *AsyncHttpHandler) CompletedWithLocation(location string) {

	h.manager.lock.RLock()
	defer h.manager.lock.RUnlock()

	godbc.Require(h.completed == false)

	h.location = location
	h.completed = true

	godbc.Ensure(h.completed == true)
	godbc.Ensure(h.location == location)
	godbc.Ensure(h.err == nil)
}

// Registers that the handler has completed and no data needs to be returned
func (h *AsyncHttpHandler) Completed() {

	h.manager.lock.RLock()
	defer h.manager.lock.RUnlock()

	godbc.Require(h.completed == false)

	h.completed = true

	godbc.Ensure(h.completed == true)
	godbc.Ensure(h.location == "")
	godbc.Ensure(h.err == nil)
}
<|endoftext|>


<commit_before>package tinylfu

// list implements a doubly linked list. It is based on Go's built-in list.List,
// but simplified for TinyLFU to reduce size per element and to remove the need
// for allocations when moving elements between lists. Unlike the built-in list,
// this struct must be initialized prior to use.
type list struct {
	// To simplify the implementation, internally a list l is implemented as a
	// ring, such that root is both the next element of the l.Back() and the
	// previous element of l.Front()
	root element

	// Current list length excluding the root.
	len int
}

// newList returns an initialized list.
func newList() *list { return new(list).Init() }

// Init initializes or clears the list.
func (l *list) Init() *list {
	l.root.next = &l.root
	l.root.prev = &l.root
	l.len = 0
	return l
}

// Len returns the number of elements in the list.
func (l *list) Len() int { return l.len }

// Front returns the first element of the list or nil if the list is empty.
func (l *list) Front() *element {
	if l.len == 0 {
		return nil
	}
	return l.root.next
}

// Back returns the last element of the list or nil if the list is empty.
func (l *list) Back() *element {
	if l.len == 0 {
		return nil
	}
	return l.root.prev
}

// PushFront inserts an element into a list.
func (l *list) PushFront(e *element) {
	if e.list != nil {
		e.Remove()
	}
	e.next = l.root.next
	e.prev = &l.root
	l.root.next = e
	e.next.prev = e
	e.list = l
	l.len++
}

func (l *list) PushBack(e *element) {
	if e.list != nil {
		e.Remove()
	}
	e.prev = l.root.prev
	e.next = &l.root
	l.root.prev = e
	e.prev.next = e
	e.list = l
	l.len++
}

// element is a node within a linked list.
type element struct {
	next, prev *element
	list       *list

	Value uint64
}

// Next returns the next list element or nil.
func (e *element) Next() *element {
	if p := e.next; e.list != nil && p != &e.list.root {
		return p
	}
	return nil
}

// Prev returns the previous list element or nil.
func (e *element) Prev() *element {
	if p := e.prev; e.list != nil && p != &e.list.root {
		return p
	}
	return nil
}

// List returns the list containing the element or nil.
func (e *element) List() *list {
	return e.list
}

// Remove removes an element from its list.
func (e *element) Remove() {
	if e.list == nil {
		return
	}

	e.list.len--
	e.prev.next = e.next
	e.next.prev = e.prev
	e.next = nil
	e.prev = nil
	e.list = nil
}

// MoveToFront moves an element to the front of its list. The element must be
// initialized and inserted into a list.
func (e *element) MoveToFront() {
	root := &e.list.root
	if root.next == e {
		return
	}

	e.prev.next = e.next
	e.next.prev = e.prev
	e.prev = root
	e.next = root.next
	root.next.prev = e
	root.next = e
}
<commit_msg>Clarify root sentinel comment<commit_after>package tinylfu

// list implements a doubly linked list. It is based on Go's built-in list.List,
// but simplified for TinyLFU to reduce size per element and to remove the need
// for allocations when moving elements between lists. Unlike the built-in list,
// this struct must be initialized prior to use.
type list struct {
	// To simplify the implementation, internally a list l is implemented as a
	// ring, such that root is both the next element of the l.Back() and the
	// previous element of l.Front(). This sentinel is neither included in the
	// list count nor enumerable via e.Next() and e.Back().
	root element

	// Current list length excluding the root.
	len int
}

// newList returns an initialized list.
func newList() *list { return new(list).Init() }

// Init initializes or clears the list.
func (l *list) Init() *list {
	l.root.next = &l.root
	l.root.prev = &l.root
	l.len = 0
	return l
}

// Len returns the number of elements in the list.
func (l *list) Len() int { return l.len }

// Front returns the first element of the list or nil if the list is empty.
func (l *list) Front() *element {
	if l.len == 0 {
		return nil
	}
	return l.root.next
}

// Back returns the last element of the list or nil if the list is empty.
func (l *list) Back() *element {
	if l.len == 0 {
		return nil
	}
	return l.root.prev
}

// PushFront inserts an element into a list.
func (l *list) PushFront(e *element) {
	if e.list != nil {
		e.Remove()
	}
	e.next = l.root.next
	e.prev = &l.root
	l.root.next = e
	e.next.prev = e
	e.list = l
	l.len++
}

func (l *list) PushBack(e *element) {
	if e.list != nil {
		e.Remove()
	}
	e.prev = l.root.prev
	e.next = &l.root
	l.root.prev = e
	e.prev.next = e
	e.list = l
	l.len++
}

// element is a node within a linked list.
type element struct {
	next, prev *element
	list       *list

	Value uint64
}

// Next returns the next list element or nil.
func (e *element) Next() *element {
	if p := e.next; e.list != nil && p != &e.list.root {
		return p
	}
	return nil
}

// Prev returns the previous list element or nil.
func (e *element) Prev() *element {
	if p := e.prev; e.list != nil && p != &e.list.root {
		return p
	}
	return nil
}

// List returns the list containing the element or nil.
func (e *element) List() *list {
	return e.list
}

// Remove removes an element from its list.
func (e *element) Remove() {
	if e.list == nil {
		return
	}

	e.list.len--
	e.prev.next = e.next
	e.next.prev = e.prev
	e.next = nil
	e.prev = nil
	e.list = nil
}

// MoveToFront moves an element to the front of its list. The element must be
// initialized and inserted into a list.
func (e *element) MoveToFront() {
	root := &e.list.root
	if root.next == e {
		return
	}

	e.prev.next = e.next
	e.next.prev = e.prev
	e.prev = root
	e.next = root.next
	root.next.prev = e
	root.next = e
}
<|endoftext|>


<commit_before>package todolist

import (
	"fmt"
	"regexp"
	"strconv"
	"time"
)

type App struct {
	TodoStore *FileStore
	TodoList  *TodoList
}

func NewApp() *App {
	app := &App{TodoList: &TodoList{}, TodoStore: NewFileStore()}
	return app
}

func (a *App) InitializeRepo() {
	a.TodoStore.Initialize()
}

func (a *App) AddTodo(input string) {
	a.load()
	parser := &Parser{}
	todo := parser.ParseNewTodo(input)

	a.TodoList.Add(todo)
	a.save()
	fmt.Println("Todo added.")
}

func (a *App) DeleteTodo(input string) {
	a.load()
	id := a.getId(input)
	if id != -1 {
		a.TodoList.Delete(id)
		a.save()
		fmt.Println("Todo deleted.")
	} else {
		fmt.Println("Could not find id.")
	}
}

func (a *App) CompleteTodo(input string) {
	a.load()
	id := a.getId(input)
	if id != -1 {
		a.TodoList.Complete(id)
		a.save()
		fmt.Println("Todo completed.")
	} else {
		fmt.Println("Could not find id.")
	}
}

func (a *App) UncompleteTodo(input string) {
	a.load()
	id := a.getId(input)
	if id != -1 {
		a.TodoList.Uncomplete(id)
		a.save()
		fmt.Println("Todo uncompleted.")
	} else {
		fmt.Println("Could not find id.")
	}
}

func (a *App) ArchiveTodo(input string) {
	a.load()
	id := a.getId(input)
	if id != -1 {
		a.TodoList.Archive(id)
		a.save()
		fmt.Println("Todo archived.")
	} else {
		fmt.Println("Could not find id.")
	}
}

func (a *App) UnarchiveTodo(input string) {
	a.load()
	id := a.getId(input)
	if id != -1 {
		a.TodoList.Unarchive(id)
		a.save()
		fmt.Println("Todo unarchived.")
	} else {
		fmt.Println("Could not find id.")
	}
}

func (a *App) EditTodoDue(input string) {
	a.load()
	id := a.getId(input)
	if id != -1 {
		todo := a.TodoList.FindById(id)
		parser := &Parser{}
		todo.Due = parser.Due(input, time.Now())
		a.save()
		fmt.Println("Todo due date updated.")
	} else {
		fmt.Println("Could not find id.")
	}
}

func (a *App) ArchiveCompleted() {
	a.load()
	for _, todo := range a.TodoList.Todos() {
		if todo.Completed {
			todo.Archived = true
		}
	}
	a.save()
	fmt.Println("All archived todos completed.")
}

func (a *App) ListTodos(input string) {
	a.load()
	filtered := NewFilter(a.TodoList.Todos()).Filter(input)
	grouped := a.getGroups(input, filtered)

	formatter := NewFormatter(grouped)
	formatter.Print()
}

func (a *App) getId(input string) int {

	re, _ := regexp.Compile("\\d+")
	if re.MatchString(input) {
		id, _ := strconv.Atoi(re.FindString(input))
		return id
	} else {
		return -1
	}
}

func (a *App) getGroups(input string, todos []*Todo) *GroupedTodos {
	grouper := &Grouper{}
	contextRegex, _ := regexp.Compile(`by c.*$`)
	projectRegex, _ := regexp.Compile(`by p.*$`)

	var grouped *GroupedTodos

	if contextRegex.MatchString(input) {
		grouped = grouper.GroupByContext(todos)
	} else if projectRegex.MatchString(input) {
		grouped = grouper.GroupByProject(todos)
	} else {
		grouped = grouper.GroupByNothing(todos)
	}
	return grouped
}

func (a *App) save() {
	a.TodoStore.Save(a.TodoList.Data)
}
func (a *App) load() {
	a.TodoList.Load(a.TodoStore.Load())
}
<commit_msg>Promote save/load to be public<commit_after>package todolist

import (
	"fmt"
	"regexp"
	"strconv"
	"time"
)

type App struct {
	TodoStore *FileStore
	TodoList  *TodoList
}

func NewApp() *App {
	app := &App{TodoList: &TodoList{}, TodoStore: NewFileStore()}
	return app
}

func (a *App) InitializeRepo() {
	a.TodoStore.Initialize()
}

func (a *App) AddTodo(input string) {
	a.Load()
	parser := &Parser{}
	todo := parser.ParseNewTodo(input)

	a.TodoList.Add(todo)
	a.Save()
	fmt.Println("Todo added.")
}

func (a *App) DeleteTodo(input string) {
	a.Load()
	id := a.getId(input)
	if id != -1 {
		a.TodoList.Delete(id)
		a.Save()
		fmt.Println("Todo deleted.")
	} else {
		fmt.Println("Could not find id.")
	}
}

func (a *App) CompleteTodo(input string) {
	a.Load()
	id := a.getId(input)
	if id != -1 {
		a.TodoList.Complete(id)
		a.Save()
		fmt.Println("Todo completed.")
	} else {
		fmt.Println("Could not find id.")
	}
}

func (a *App) UncompleteTodo(input string) {
	a.Load()
	id := a.getId(input)
	if id != -1 {
		a.TodoList.Uncomplete(id)
		a.Save()
		fmt.Println("Todo uncompleted.")
	} else {
		fmt.Println("Could not find id.")
	}
}

func (a *App) ArchiveTodo(input string) {
	a.Load()
	id := a.getId(input)
	if id != -1 {
		a.TodoList.Archive(id)
		a.Save()
		fmt.Println("Todo archived.")
	} else {
		fmt.Println("Could not find id.")
	}
}

func (a *App) UnarchiveTodo(input string) {
	a.Load()
	id := a.getId(input)
	if id != -1 {
		a.TodoList.Unarchive(id)
		a.Save()
		fmt.Println("Todo unarchived.")
	} else {
		fmt.Println("Could not find id.")
	}
}

func (a *App) EditTodoDue(input string) {
	a.Load()
	id := a.getId(input)
	if id != -1 {
		todo := a.TodoList.FindById(id)
		parser := &Parser{}
		todo.Due = parser.Due(input, time.Now())
		a.Save()
		fmt.Println("Todo due date updated.")
	} else {
		fmt.Println("Could not find id.")
	}
}

func (a *App) ArchiveCompleted() {
	a.Load()
	for _, todo := range a.TodoList.Todos() {
		if todo.Completed {
			todo.Archived = true
		}
	}
	a.Save()
	fmt.Println("All archived todos completed.")
}

func (a *App) ListTodos(input string) {
	a.Load()
	filtered := NewFilter(a.TodoList.Todos()).Filter(input)
	grouped := a.getGroups(input, filtered)

	formatter := NewFormatter(grouped)
	formatter.Print()
}

func (a *App) getId(input string) int {

	re, _ := regexp.Compile("\\d+")
	if re.MatchString(input) {
		id, _ := strconv.Atoi(re.FindString(input))
		return id
	} else {
		return -1
	}
}

func (a *App) getGroups(input string, todos []*Todo) *GroupedTodos {
	grouper := &Grouper{}
	contextRegex, _ := regexp.Compile(`by c.*$`)
	projectRegex, _ := regexp.Compile(`by p.*$`)

	var grouped *GroupedTodos

	if contextRegex.MatchString(input) {
		grouped = grouper.GroupByContext(todos)
	} else if projectRegex.MatchString(input) {
		grouped = grouper.GroupByProject(todos)
	} else {
		grouped = grouper.GroupByNothing(todos)
	}
	return grouped
}

func (a *App) Load() {
	a.TodoList.Load(a.TodoStore.Load())
}

func (a *App) Save() {
	a.TodoStore.Save(a.TodoList.Data)
}
<|endoftext|>


<commit_before>package gosom

import (
	"testing"
	"math"

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

func TestEuclideanDistance(t *testing.T) {
	a := []float64{1.0, 1.0}
	b := []float64{0.0, 0.0}

	require.Equal(t, math.Sqrt(2), EuclideanDistance(a, b))
}

func TestManhattanDistance(t *testing.T) {
	a := []float64{1.0, 1.0}
	b := []float64{0.0, 0.0}

	require.Equal(t, 2.0, ManhattanDistance(a, b))
}

// other functions are tested using the plot
<commit_msg>update tests<commit_after>package gosom

import (
	"testing"
	"math"

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

func TestEuclideanDistance(t *testing.T) {
	require.Equal(t, math.Sqrt(2), EuclideanDistance(
		[]float64{1.0, 1.0},
		[]float64{0.0, 0.0},
	))

	require.Equal(t, 1.0, EuclideanDistance(
		[]float64{0.0, 1.0},
		[]float64{0.0, 0.0},
	))
}

func TestManhattanDistance(t *testing.T) {
	require.Equal(t, 2.0, ManhattanDistance(
		[]float64{1.0, 1.0},
		[]float64{0.0, 0.0},
	))

	require.Equal(t, 1.0, ManhattanDistance(
		[]float64{0.0, 1.0},
		[]float64{0.0, 0.0},
	))
}

// other functions are tested using the plot
<|endoftext|>


<commit_before>package logging

import "github.com/open-gtd/server/logging"

var logger = logging.NullLogger{}

func RegisterLogger(l logging.Logger) {
	logger = logger
}
<commit_msg>Update logger.go<commit_after>package logging

import "github.com/open-gtd/server/logging"

var logger = logging.NullLogger{}

func RegisterLogger(l logging.Logger) {
	logger = l
}
<|endoftext|>


<commit_before>package gocsv

import (
	"reflect"
	"strings"
	"sync"
)

// --------------------------------------------------------------------------
// Reflection helpers

type structInfo struct {
	Fields []fieldInfo
	Zero   reflect.Value
}

type fieldInfo struct {
	Key       string
	Num       int
	OmitEmpty bool
}

var structMap = make(map[reflect.Type]*structInfo)
var structMapMutex sync.RWMutex

func getStructInfo(rType reflect.Type) *structInfo {
	structMapMutex.RLock()
	stInfo, ok := structMap[rType]
	structMapMutex.RUnlock()
	if ok {
		return stInfo
	}
	fieldsCount := rType.NumField()
	fieldsList := make([]fieldInfo, 0, fieldsCount)
	for i := 0; i < fieldsCount; i++ {
		field := rType.Field(i)
		if field.PkgPath != "" {
			continue
		}
		fieldInfo := fieldInfo{Num: i}
		fieldTag := field.Tag.Get("csv")
		fieldTags := strings.Split(fieldTag, ",")
		for _, fieldTagEntry := range fieldTags {
			if fieldTagEntry == "omitempty" {
				fieldInfo.OmitEmpty = true
			} else {
				fieldTag = fieldTagEntry
			}
		}
		if fieldTag == "-" {
			continue
		} else if fieldTag != "" {
			fieldInfo.Key = fieldTag
		} else {
			fieldInfo.Key = field.Name
		}
		fieldsList = append(fieldsList, fieldInfo)
	}
	stInfo = &structInfo{fieldsList, reflect.New(rType).Elem()}
	return stInfo
}

func getConcreteContainerInnerType(in reflect.Type) (inInnerWasPointer bool, inInnerType reflect.Type) {
	inInnerType = in.Elem()
	inInnerWasPointer = false
	if inInnerType.Kind() == reflect.Ptr {
		inInnerWasPointer = true
		inInnerType = inInnerType.Elem()
	}
	return inInnerWasPointer, inInnerType
}

func getConcreteReflectValueAndType(in interface{}) (reflect.Value, reflect.Type) {
	value := reflect.ValueOf(in)
	if value.Kind() == reflect.Ptr {
		value = value.Elem()
	}
	return value, value.Type()
}
<commit_msg>Remove unused 'Zero' and 'OmitEmpty' struct info fields<commit_after>package gocsv

import (
	"reflect"
	"strings"
	"sync"
)

// --------------------------------------------------------------------------
// Reflection helpers

type structInfo struct {
	Fields []fieldInfo
}

type fieldInfo struct {
	Key string
	Num int
}

var structMap = make(map[reflect.Type]*structInfo)
var structMapMutex sync.RWMutex

func getStructInfo(rType reflect.Type) *structInfo {
	structMapMutex.RLock()
	stInfo, ok := structMap[rType]
	structMapMutex.RUnlock()
	if ok {
		return stInfo
	}
	fieldsCount := rType.NumField()
	fieldsList := make([]fieldInfo, 0, fieldsCount)
	for i := 0; i < fieldsCount; i++ {
		field := rType.Field(i)
		if field.PkgPath != "" {
			continue
		}
		fieldInfo := fieldInfo{Num: i}
		fieldTag := field.Tag.Get("csv")
		fieldTags := strings.Split(fieldTag, ",")
		for _, fieldTagEntry := range fieldTags {
			if fieldTagEntry != "omitempty" {
				fieldTag = fieldTagEntry
			}
		}
		if fieldTag == "-" {
			continue
		} else if fieldTag != "" {
			fieldInfo.Key = fieldTag
		} else {
			fieldInfo.Key = field.Name
		}
		fieldsList = append(fieldsList, fieldInfo)
	}
	stInfo = &structInfo{fieldsList}
	return stInfo
}

func getConcreteContainerInnerType(in reflect.Type) (inInnerWasPointer bool, inInnerType reflect.Type) {
	inInnerType = in.Elem()
	inInnerWasPointer = false
	if inInnerType.Kind() == reflect.Ptr {
		inInnerWasPointer = true
		inInnerType = inInnerType.Elem()
	}
	return inInnerWasPointer, inInnerType
}

func getConcreteReflectValueAndType(in interface{}) (reflect.Value, reflect.Type) {
	value := reflect.ValueOf(in)
	if value.Kind() == reflect.Ptr {
		value = value.Elem()
	}
	return value, value.Type()
}
<|endoftext|>


<commit_before>package fileutils

import (
	"bytes"
	"io"
	"os"
	"path/filepath"
)

func Open(path string) (file *os.File, err error) {
	err = os.MkdirAll(filepath.Dir(path), os.ModeDir|os.ModePerm)
	if err != nil {
		return
	}

	return os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
}

func Create(path string) (file *os.File, err error) {
	err = os.MkdirAll(filepath.Dir(path), os.ModeDir|os.ModePerm)
	if err != nil {
		return
	}

	return os.Create(path)
}

func Read(file *os.File) string {
	buf := &bytes.Buffer{}
	_, err := io.Copy(buf, file)

	if err != nil {
		return ""
	}

	return string(buf.Bytes())
}

func CopyPathToPath(fromPath, toPath string) (err error) {
	dst, err := Create(toPath)
	if err != nil {
		return
	}
	defer dst.Close()

	return CopyPathToWriter(fromPath, dst)
}

func IsDirEmpty(dir string) (isEmpty bool, err error) {
	dirFile, err := os.Open(dir)
	if err != nil {
		return
	}

	_, readErr := dirFile.Readdirnames(1)
	if readErr != nil {
		isEmpty = true
	} else {
		isEmpty = false
	}
	return
}

func CopyPathToWriter(originalFilePath string, targetWriter io.Writer) (err error) {
	originalFile, err := os.Open(originalFilePath)
	if err != nil {
		return
	}
	defer originalFile.Close()

	_, err = io.Copy(targetWriter, originalFile)
	if err != nil {
		return
	}

	return
}

func CopyReaderToPath(src io.Reader, targetPath string) (err error) {
	destFile, err := Create(targetPath)
	if err != nil {
		return
	}
	defer destFile.Close()

	_, err = io.Copy(destFile, src)
	return
}

func SetMode(dest string, fileMode os.FileMode) (err error) {
	err = os.Chmod(dest, fileMode)
	return
}

func SetModeFromPath(dest string, src string) (err error) {
	fileInfo, err := os.Stat(src)
	if err != nil {
		return
	}

	return SetMode(dest, fileInfo.Mode())
}
<commit_msg>Reorganize code<commit_after>package fileutils

import (
	"bytes"
	"io"
	"os"
	"path/filepath"
)

func Open(path string) (file *os.File, err error) {
	err = os.MkdirAll(filepath.Dir(path), os.ModeDir|os.ModePerm)
	if err != nil {
		return
	}

	return os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
}

func Create(path string) (file *os.File, err error) {
	err = os.MkdirAll(filepath.Dir(path), os.ModeDir|os.ModePerm)
	if err != nil {
		return
	}

	return os.Create(path)
}

func Read(file *os.File) string {
	buf := &bytes.Buffer{}
	_, err := io.Copy(buf, file)

	if err != nil {
		return ""
	}

	return string(buf.Bytes())
}

func CopyPathToPath(fromPath, toPath string) (err error) {
	dst, err := Create(toPath)
	if err != nil {
		return
	}
	defer dst.Close()

	return CopyPathToWriter(fromPath, dst)
}

func CopyPathToWriter(originalFilePath string, targetWriter io.Writer) (err error) {
	originalFile, err := os.Open(originalFilePath)
	if err != nil {
		return
	}
	defer originalFile.Close()

	_, err = io.Copy(targetWriter, originalFile)
	if err != nil {
		return
	}

	return
}

func CopyReaderToPath(src io.Reader, targetPath string) (err error) {
	destFile, err := Create(targetPath)
	if err != nil {
		return
	}
	defer destFile.Close()

	_, err = io.Copy(destFile, src)
	return
}

func IsDirEmpty(dir string) (isEmpty bool, err error) {
	dirFile, err := os.Open(dir)
	if err != nil {
		return
	}

	_, readErr := dirFile.Readdirnames(1)
	if readErr != nil {
		isEmpty = true
	} else {
		isEmpty = false
	}
	return
}

func SetMode(dest string, fileMode os.FileMode) (err error) {
	err = os.Chmod(dest, fileMode)
	return
}

func SetModeFromPath(dest string, src string) (err error) {
	fileInfo, err := os.Stat(src)
	if err != nil {
		return
	}

	return SetMode(dest, fileInfo.Mode())
}
<|endoftext|>


<commit_before>package youtubeinviteplugin

import "github.com/iopred/bruxism"

// messageFunc is a command for accepting an YouTubeInvite to a channel.
func messageFunc(bot *bruxism.Bot, service bruxism.Service, message bruxism.Message) {
	if service.IsMe(message) || !bruxism.MatchesCommand(service, "youtubeinvite", message) {
		return
	}

	_, parts := bruxism.ParseCommand(service, message)

	if len(parts) == 1 {
		join := parts[0]

		ytservice := bot.Services[bruxism.YouTubeServiceName]
		if ytservice == nil {
			return
		}

		if err := ytservice.Join(join); err != nil {
			service.SendMessage(message.Channel(), err.Error())
		}
	}
}

func helpFunc(bot *bruxism.Bot, service bruxism.Service, message bruxism.Message, detailed bool) []string {
	return bruxism.CommandHelp(service, "youtubeinvite", "<videoid>", "Joins the provided YouTube live stream.")
}

func New() bruxism.Plugin {
	p := bruxism.NewSimplePlugin("YouTubeInvite")
	p.MessageFunc = messageFunc
	p.HelpFunc = helpFunc
	return p
}
<commit_msg>Remove help for youtube invite.<commit_after>package youtubeinviteplugin

import "github.com/iopred/bruxism"

// messageFunc is a command for accepting an YouTubeInvite to a channel.
func messageFunc(bot *bruxism.Bot, service bruxism.Service, message bruxism.Message) {
	if service.IsMe(message) || !bruxism.MatchesCommand(service, "youtubeinvite", message) {
		return
	}

	_, parts := bruxism.ParseCommand(service, message)

	if len(parts) == 1 {
		join := parts[0]

		ytservice := bot.Services[bruxism.YouTubeServiceName]
		if ytservice == nil {
			return
		}

		if err := ytservice.Join(join); err != nil {
			service.SendMessage(message.Channel(), err.Error())
		}
	}
}

func helpFunc(bot *bruxism.Bot, service bruxism.Service, message bruxism.Message, detailed bool) []string {
	return bruxism.CommandHelp(service, "youtubeinvite", "<videoid>", "Joins the provided YouTube live stream.")
}

func New() bruxism.Plugin {
	p := bruxism.NewSimplePlugin("YouTubeInvite")
	p.MessageFunc = messageFunc
	//p.HelpFunc = helpFunc
	return p
}
<|endoftext|>


<commit_before>package fixtures

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

// Handler returns an http.Handler that is capable of handling a variety of mock
// Bitbucket requests and returning mock responses.
func Handler() http.Handler {
	gin.SetMode(gin.TestMode)

	e := gin.New()
	e.GET("/api/v1/repos/:owner/:name", getRepo)
	e.GET("/api/v1/repos/:owner/:name/raw/:commit/:file", getRepoFile)
	e.POST("/api/v1/repos/:owner/:name/hooks", createRepoHook)
	e.POST("/api/v1/repos/:owner/:name/statuses/:commit", createRepoCommitStatus)
	e.GET("/api/v1/user/repos", getUserRepos)

	return e
}

func getRepo(c *gin.Context) {
	switch c.Param("name") {
	case "repo_not_found":
		c.String(404, "")
	default:
		c.String(200, repoPayload)
	}
}

func createRepoCommitStatus(c *gin.Context) {
	if c.Param("commit") == "v1.0.0" || c.Param("commit") == "9ecad50" {
		c.String(200, repoPayload)
	}
	c.String(404, "")
}

func getRepoFile(c *gin.Context) {
	if c.Param("file") == "file_not_found" {
		c.String(404, "")
	}
	if c.Param("commit") == "v1.0.0" || c.Param("commit") == "9ecad50" {
		c.String(200, repoFilePayload)
	}
	c.String(404, "")
}

func createRepoHook(c *gin.Context) {
	in := struct {
		Type string `json:"type"`
		Conf struct {
			Type string `json:"content_type"`
			URL  string `json:"url"`
		} `json:"config"`
	}{}
	c.BindJSON(&in)
	if in.Type != "gogs" ||
		in.Conf.Type != "json" ||
		in.Conf.URL != "http://localhost" {
		c.String(500, "")
		return
	}

	c.String(200, "{}")
}

func getUserRepos(c *gin.Context) {
	switch c.Request.Header.Get("Authorization") {
	case "token repos_not_found":
		c.String(404, "")
	default:
		c.String(200, userRepoPayload)
	}
}

const repoPayload = `
{
  "owner": {
    "login": "test_name",
    "email": "octocat@github.com",
    "avatar_url": "https:\/\/secure.gravatar.com\/avatar\/8c58a0be77ee441bb8f8595b7f1b4e87"
  },
  "full_name": "test_name\/repo_name",
  "private": true,
  "html_url": "http:\/\/localhost\/test_name\/repo_name",
  "clone_url": "http:\/\/localhost\/test_name\/repo_name.git",
  "permissions": {
    "admin": true,
    "push": true,
    "pull": true
  }
}
`

const repoFilePayload = `{ platform: linux/amd64 }`

const userRepoPayload = `
[
  {
    "owner": {
      "login": "test_name",
      "email": "octocat@github.com",
      "avatar_url": "https:\/\/secure.gravatar.com\/avatar\/8c58a0be77ee441bb8f8595b7f1b4e87"
    },
    "full_name": "test_name\/repo_name",
    "private": true,
    "html_url": "http:\/\/localhost\/test_name\/repo_name",
    "clone_url": "http:\/\/localhost\/test_name\/repo_name.git",
    "permissions": {
      "admin": true,
      "push": true,
      "pull": true
    }
  }
]
`
<commit_msg>fix: [ci skip] update comment.<commit_after>package fixtures

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

// Handler returns an http.Handler that is capable of handling a variety of mock
// Gitea requests and returning mock responses.
func Handler() http.Handler {
	gin.SetMode(gin.TestMode)

	e := gin.New()
	e.GET("/api/v1/repos/:owner/:name", getRepo)
	e.GET("/api/v1/repos/:owner/:name/raw/:commit/:file", getRepoFile)
	e.POST("/api/v1/repos/:owner/:name/hooks", createRepoHook)
	e.POST("/api/v1/repos/:owner/:name/statuses/:commit", createRepoCommitStatus)
	e.GET("/api/v1/user/repos", getUserRepos)

	return e
}

func getRepo(c *gin.Context) {
	switch c.Param("name") {
	case "repo_not_found":
		c.String(404, "")
	default:
		c.String(200, repoPayload)
	}
}

func createRepoCommitStatus(c *gin.Context) {
	if c.Param("commit") == "v1.0.0" || c.Param("commit") == "9ecad50" {
		c.String(200, repoPayload)
	}
	c.String(404, "")
}

func getRepoFile(c *gin.Context) {
	if c.Param("file") == "file_not_found" {
		c.String(404, "")
	}
	if c.Param("commit") == "v1.0.0" || c.Param("commit") == "9ecad50" {
		c.String(200, repoFilePayload)
	}
	c.String(404, "")
}

func createRepoHook(c *gin.Context) {
	in := struct {
		Type string `json:"type"`
		Conf struct {
			Type string `json:"content_type"`
			URL  string `json:"url"`
		} `json:"config"`
	}{}
	c.BindJSON(&in)
	if in.Type != "gogs" ||
		in.Conf.Type != "json" ||
		in.Conf.URL != "http://localhost" {
		c.String(500, "")
		return
	}

	c.String(200, "{}")
}

func getUserRepos(c *gin.Context) {
	switch c.Request.Header.Get("Authorization") {
	case "token repos_not_found":
		c.String(404, "")
	default:
		c.String(200, userRepoPayload)
	}
}

const repoPayload = `
{
  "owner": {
    "login": "test_name",
    "email": "octocat@github.com",
    "avatar_url": "https:\/\/secure.gravatar.com\/avatar\/8c58a0be77ee441bb8f8595b7f1b4e87"
  },
  "full_name": "test_name\/repo_name",
  "private": true,
  "html_url": "http:\/\/localhost\/test_name\/repo_name",
  "clone_url": "http:\/\/localhost\/test_name\/repo_name.git",
  "permissions": {
    "admin": true,
    "push": true,
    "pull": true
  }
}
`

const repoFilePayload = `{ platform: linux/amd64 }`

const userRepoPayload = `
[
  {
    "owner": {
      "login": "test_name",
      "email": "octocat@github.com",
      "avatar_url": "https:\/\/secure.gravatar.com\/avatar\/8c58a0be77ee441bb8f8595b7f1b4e87"
    },
    "full_name": "test_name\/repo_name",
    "private": true,
    "html_url": "http:\/\/localhost\/test_name\/repo_name",
    "clone_url": "http:\/\/localhost\/test_name\/repo_name.git",
    "permissions": {
      "admin": true,
      "push": true,
      "pull": true
    }
  }
]
`
<|endoftext|>


<commit_before>// Copyright (c) Alex Ellis 2017. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

package main

import (
	"fmt"
	"log"
	"net/http"
	"time"

	"github.com/gorilla/mux"
	"github.com/openfaas/faas/gateway/handlers"

	"github.com/openfaas/faas-provider/auth"
	"github.com/openfaas/faas/gateway/metrics"
	"github.com/openfaas/faas/gateway/plugin"
	"github.com/openfaas/faas/gateway/types"
	natsHandler "github.com/openfaas/nats-queue-worker/handler"
)

func main() {

	osEnv := types.OsEnv{}
	readConfig := types.ReadConfig{}
	config := readConfig.Read(osEnv)

	log.Printf("HTTP Read Timeout: %s", config.ReadTimeout)
	log.Printf("HTTP Write Timeout: %s", config.WriteTimeout)

	if !config.UseExternalProvider() {
		log.Fatalln("You must provide an external provider via 'functions_provider_url' env-var.")
	}

	log.Printf("Binding to external function provider: %s", config.FunctionsProviderURL)

	var credentials *auth.BasicAuthCredentials

	if config.UseBasicAuth {
		var readErr error
		reader := auth.ReadBasicAuthFromDisk{
			SecretMountPath: config.SecretMountPath,
		}
		credentials, readErr = reader.Read()

		if readErr != nil {
			log.Panicf(readErr.Error())
		}
	}

	var faasHandlers types.HandlerSet

	servicePollInterval := time.Second * 5

	metricsOptions := metrics.BuildMetricsOptions()
	exporter := metrics.NewExporter(metricsOptions)
	exporter.StartServiceWatcher(*config.FunctionsProviderURL, metricsOptions, "func", servicePollInterval)
	metrics.RegisterExporter(exporter)

	reverseProxy := types.NewHTTPClientReverseProxy(config.FunctionsProviderURL, config.UpstreamTimeout)

	loggingNotifier := handlers.LoggingNotifier{}
	prometheusNotifier := handlers.PrometheusFunctionNotifier{
		Metrics: &metricsOptions,
	}
	functionNotifiers := []handlers.HTTPNotifier{loggingNotifier, prometheusNotifier}
	forwardingNotifiers := []handlers.HTTPNotifier{loggingNotifier}

	urlResolver := handlers.SingleHostBaseURLResolver{BaseURL: config.FunctionsProviderURL.String()}
	var functionURLResolver handlers.BaseURLResolver

	if config.DirectFunctions {
		functionURLResolver = handlers.FunctionAsHostBaseURLResolver{FunctionSuffix: config.DirectFunctionsSuffix}
	} else {
		functionURLResolver = urlResolver
	}

	nilURLTransformer := handlers.TransparentURLPathTransformer{}
	functionURLTransformer := handlers.FunctionPrefixTrimmingURLPathTransformer{}

	faasHandlers.Proxy = handlers.MakeForwardingProxyHandler(reverseProxy, functionNotifiers, functionURLResolver, functionURLTransformer)

	faasHandlers.RoutelessProxy = handlers.MakeForwardingProxyHandler(reverseProxy, forwardingNotifiers, urlResolver, nilURLTransformer)
	faasHandlers.ListFunctions = handlers.MakeForwardingProxyHandler(reverseProxy, forwardingNotifiers, urlResolver, nilURLTransformer)
	faasHandlers.DeployFunction = handlers.MakeForwardingProxyHandler(reverseProxy, forwardingNotifiers, urlResolver, nilURLTransformer)
	faasHandlers.DeleteFunction = handlers.MakeForwardingProxyHandler(reverseProxy, forwardingNotifiers, urlResolver, nilURLTransformer)
	faasHandlers.UpdateFunction = handlers.MakeForwardingProxyHandler(reverseProxy, forwardingNotifiers, urlResolver, nilURLTransformer)
	faasHandlers.QueryFunction = handlers.MakeForwardingProxyHandler(reverseProxy, forwardingNotifiers, urlResolver, nilURLTransformer)
	faasHandlers.InfoHandler = handlers.MakeInfoHandler(handlers.MakeForwardingProxyHandler(reverseProxy, forwardingNotifiers, urlResolver, nilURLTransformer))

	alertHandler := plugin.NewExternalServiceQuery(*config.FunctionsProviderURL)
	faasHandlers.Alert = handlers.MakeAlertHandler(alertHandler)

	if config.UseNATS() {
		log.Println("Async enabled: Using NATS Streaming.")
		natsQueue, queueErr := natsHandler.CreateNatsQueue(*config.NATSAddress, *config.NATSPort, natsHandler.DefaultNatsConfig{})
		if queueErr != nil {
			log.Fatalln(queueErr)
		}

		faasHandlers.QueuedProxy = handlers.MakeCallIDMiddleware(handlers.MakeQueuedProxy(metricsOptions, true, natsQueue, functionURLTransformer))
		faasHandlers.AsyncReport = handlers.MakeAsyncReport(metricsOptions)
	}

	prometheusQuery := metrics.NewPrometheusQuery(config.PrometheusHost, config.PrometheusPort, &http.Client{})
	faasHandlers.ListFunctions = metrics.AddMetricsHandler(faasHandlers.ListFunctions, prometheusQuery)
	faasHandlers.Proxy = handlers.MakeCallIDMiddleware(faasHandlers.Proxy)

	faasHandlers.ScaleFunction = handlers.MakeForwardingProxyHandler(reverseProxy, forwardingNotifiers, urlResolver, nilURLTransformer)

	if credentials != nil {
		faasHandlers.UpdateFunction =
			auth.DecorateWithBasicAuth(faasHandlers.UpdateFunction, credentials)
		faasHandlers.DeleteFunction =
			auth.DecorateWithBasicAuth(faasHandlers.DeleteFunction, credentials)
		faasHandlers.DeployFunction =
			auth.DecorateWithBasicAuth(faasHandlers.DeployFunction, credentials)
		faasHandlers.ListFunctions =
			auth.DecorateWithBasicAuth(faasHandlers.ListFunctions, credentials)
		faasHandlers.ScaleFunction =
			auth.DecorateWithBasicAuth(faasHandlers.ScaleFunction, credentials)
		faasHandlers.QueryFunction = auth.DecorateWithBasicAuth(faasHandlers.QueryFunction, credentials)
		faasHandlers.InfoHandler = auth.DecorateWithBasicAuth(faasHandlers.InfoHandler, credentials)
	}

	r := mux.NewRouter()
	// max wait time to start a function = maxPollCount * functionPollInterval

	functionProxy := faasHandlers.Proxy

	if config.ScaleFromZero {
		scalingConfig := handlers.ScalingConfig{
			MaxPollCount:         uint(1000),
			FunctionPollInterval: time.Millisecond * 10,
			CacheExpiry:          time.Second * 5, // freshness of replica values before going stale
			ServiceQuery:         alertHandler,
		}

		functionProxy = handlers.MakeScalingHandler(faasHandlers.Proxy, faasHandlers.QueryFunction, scalingConfig)
	}
	// r.StrictSlash(false)	// This didn't work, so register routes twice.
	r.HandleFunc("/function/{name:[-a-zA-Z_0-9]+}", functionProxy)
	r.HandleFunc("/function/{name:[-a-zA-Z_0-9]+}/", functionProxy)
	r.HandleFunc("/function/{name:[-a-zA-Z_0-9]+}/{params:.*}", functionProxy)

	r.HandleFunc("/system/info", faasHandlers.InfoHandler).Methods(http.MethodGet)
	r.HandleFunc("/system/alert", faasHandlers.Alert).Methods(http.MethodPost)

	r.HandleFunc("/system/function/{name:[-a-zA-Z_0-9]+}", faasHandlers.QueryFunction).Methods(http.MethodGet)
	r.HandleFunc("/system/functions", faasHandlers.ListFunctions).Methods(http.MethodGet)
	r.HandleFunc("/system/functions", faasHandlers.DeployFunction).Methods(http.MethodPost)
	r.HandleFunc("/system/functions", faasHandlers.DeleteFunction).Methods(http.MethodDelete)
	r.HandleFunc("/system/functions", faasHandlers.UpdateFunction).Methods(http.MethodPut)
	r.HandleFunc("/system/scale-function/{name:[-a-zA-Z_0-9]+}", faasHandlers.ScaleFunction).Methods(http.MethodPost)

	if faasHandlers.QueuedProxy != nil {
		r.HandleFunc("/async-function/{name:[-a-zA-Z_0-9]+}/", faasHandlers.QueuedProxy).Methods(http.MethodPost)
		r.HandleFunc("/async-function/{name:[-a-zA-Z_0-9]+}", faasHandlers.QueuedProxy).Methods(http.MethodPost)
		r.HandleFunc("/async-function/{name:[-a-zA-Z_0-9]+}/{params:.*}", faasHandlers.QueuedProxy).Methods(http.MethodPost)

		r.HandleFunc("/system/async-report", faasHandlers.AsyncReport)
	}

	fs := http.FileServer(http.Dir("./assets/"))

	// This URL allows access from the UI to the OpenFaaS store
	allowedCORSHost := "raw.githubusercontent.com"
	fsCORS := handlers.DecorateWithCORS(fs, allowedCORSHost)

	uiHandler := http.StripPrefix("/ui", fsCORS)
	if credentials != nil {
		r.PathPrefix("/ui/").Handler(auth.DecorateWithBasicAuth(uiHandler.ServeHTTP, credentials)).Methods(http.MethodGet)
	} else {
		r.PathPrefix("/ui/").Handler(uiHandler).Methods(http.MethodGet)
	}

	metricsHandler := metrics.PrometheusHandler()
	r.Handle("/metrics", metricsHandler)
	r.HandleFunc("/healthz", handlers.MakeForwardingProxyHandler(reverseProxy, forwardingNotifiers, urlResolver, nilURLTransformer)).Methods(http.MethodGet)

	r.Handle("/", http.RedirectHandler("/ui/", http.StatusMovedPermanently)).Methods(http.MethodGet)

	tcpPort := 8080

	s := &http.Server{
		Addr:           fmt.Sprintf(":%d", tcpPort),
		ReadTimeout:    config.ReadTimeout,
		WriteTimeout:   config.WriteTimeout,
		MaxHeaderBytes: http.DefaultMaxHeaderBytes, // 1MB - can be overridden by setting Server.MaxHeaderBytes.
		Handler:        r,
	}

	log.Fatal(s.ListenAndServe())
}
<commit_msg>Add basic auth support for /system/async-report<commit_after>// Copyright (c) Alex Ellis 2017. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

package main

import (
	"fmt"
	"log"
	"net/http"
	"time"

	"github.com/gorilla/mux"
	"github.com/openfaas/faas/gateway/handlers"

	"github.com/openfaas/faas-provider/auth"
	"github.com/openfaas/faas/gateway/metrics"
	"github.com/openfaas/faas/gateway/plugin"
	"github.com/openfaas/faas/gateway/types"
	natsHandler "github.com/openfaas/nats-queue-worker/handler"
)

func main() {

	osEnv := types.OsEnv{}
	readConfig := types.ReadConfig{}
	config := readConfig.Read(osEnv)

	log.Printf("HTTP Read Timeout: %s", config.ReadTimeout)
	log.Printf("HTTP Write Timeout: %s", config.WriteTimeout)

	if !config.UseExternalProvider() {
		log.Fatalln("You must provide an external provider via 'functions_provider_url' env-var.")
	}

	log.Printf("Binding to external function provider: %s", config.FunctionsProviderURL)

	var credentials *auth.BasicAuthCredentials

	if config.UseBasicAuth {
		var readErr error
		reader := auth.ReadBasicAuthFromDisk{
			SecretMountPath: config.SecretMountPath,
		}
		credentials, readErr = reader.Read()

		if readErr != nil {
			log.Panicf(readErr.Error())
		}
	}

	var faasHandlers types.HandlerSet

	servicePollInterval := time.Second * 5

	metricsOptions := metrics.BuildMetricsOptions()
	exporter := metrics.NewExporter(metricsOptions)
	exporter.StartServiceWatcher(*config.FunctionsProviderURL, metricsOptions, "func", servicePollInterval)
	metrics.RegisterExporter(exporter)

	reverseProxy := types.NewHTTPClientReverseProxy(config.FunctionsProviderURL, config.UpstreamTimeout)

	loggingNotifier := handlers.LoggingNotifier{}
	prometheusNotifier := handlers.PrometheusFunctionNotifier{
		Metrics: &metricsOptions,
	}
	functionNotifiers := []handlers.HTTPNotifier{loggingNotifier, prometheusNotifier}
	forwardingNotifiers := []handlers.HTTPNotifier{loggingNotifier}

	urlResolver := handlers.SingleHostBaseURLResolver{BaseURL: config.FunctionsProviderURL.String()}
	var functionURLResolver handlers.BaseURLResolver

	if config.DirectFunctions {
		functionURLResolver = handlers.FunctionAsHostBaseURLResolver{FunctionSuffix: config.DirectFunctionsSuffix}
	} else {
		functionURLResolver = urlResolver
	}

	nilURLTransformer := handlers.TransparentURLPathTransformer{}
	functionURLTransformer := handlers.FunctionPrefixTrimmingURLPathTransformer{}

	faasHandlers.Proxy = handlers.MakeForwardingProxyHandler(reverseProxy, functionNotifiers, functionURLResolver, functionURLTransformer)

	faasHandlers.RoutelessProxy = handlers.MakeForwardingProxyHandler(reverseProxy, forwardingNotifiers, urlResolver, nilURLTransformer)
	faasHandlers.ListFunctions = handlers.MakeForwardingProxyHandler(reverseProxy, forwardingNotifiers, urlResolver, nilURLTransformer)
	faasHandlers.DeployFunction = handlers.MakeForwardingProxyHandler(reverseProxy, forwardingNotifiers, urlResolver, nilURLTransformer)
	faasHandlers.DeleteFunction = handlers.MakeForwardingProxyHandler(reverseProxy, forwardingNotifiers, urlResolver, nilURLTransformer)
	faasHandlers.UpdateFunction = handlers.MakeForwardingProxyHandler(reverseProxy, forwardingNotifiers, urlResolver, nilURLTransformer)
	faasHandlers.QueryFunction = handlers.MakeForwardingProxyHandler(reverseProxy, forwardingNotifiers, urlResolver, nilURLTransformer)
	faasHandlers.InfoHandler = handlers.MakeInfoHandler(handlers.MakeForwardingProxyHandler(reverseProxy, forwardingNotifiers, urlResolver, nilURLTransformer))

	alertHandler := plugin.NewExternalServiceQuery(*config.FunctionsProviderURL)
	faasHandlers.Alert = handlers.MakeAlertHandler(alertHandler)

	if config.UseNATS() {
		log.Println("Async enabled: Using NATS Streaming.")
		natsQueue, queueErr := natsHandler.CreateNatsQueue(*config.NATSAddress, *config.NATSPort, natsHandler.DefaultNatsConfig{})
		if queueErr != nil {
			log.Fatalln(queueErr)
		}

		faasHandlers.QueuedProxy = handlers.MakeCallIDMiddleware(handlers.MakeQueuedProxy(metricsOptions, true, natsQueue, functionURLTransformer))
		faasHandlers.AsyncReport = handlers.MakeAsyncReport(metricsOptions)
	}

	prometheusQuery := metrics.NewPrometheusQuery(config.PrometheusHost, config.PrometheusPort, &http.Client{})
	faasHandlers.ListFunctions = metrics.AddMetricsHandler(faasHandlers.ListFunctions, prometheusQuery)
	faasHandlers.Proxy = handlers.MakeCallIDMiddleware(faasHandlers.Proxy)

	faasHandlers.ScaleFunction = handlers.MakeForwardingProxyHandler(reverseProxy, forwardingNotifiers, urlResolver, nilURLTransformer)

	if credentials != nil {
		faasHandlers.UpdateFunction =
			auth.DecorateWithBasicAuth(faasHandlers.UpdateFunction, credentials)
		faasHandlers.DeleteFunction =
			auth.DecorateWithBasicAuth(faasHandlers.DeleteFunction, credentials)
		faasHandlers.DeployFunction =
			auth.DecorateWithBasicAuth(faasHandlers.DeployFunction, credentials)
		faasHandlers.ListFunctions =
			auth.DecorateWithBasicAuth(faasHandlers.ListFunctions, credentials)
		faasHandlers.ScaleFunction =
			auth.DecorateWithBasicAuth(faasHandlers.ScaleFunction, credentials)
		faasHandlers.QueryFunction =
			auth.DecorateWithBasicAuth(faasHandlers.QueryFunction, credentials)
		faasHandlers.InfoHandler =
			auth.DecorateWithBasicAuth(faasHandlers.InfoHandler, credentials)
		faasHandlers.AsyncReport =
			auth.DecorateWithBasicAuth(faasHandlers.AsyncReport, credentials)
	}

	r := mux.NewRouter()
	// max wait time to start a function = maxPollCount * functionPollInterval

	functionProxy := faasHandlers.Proxy

	if config.ScaleFromZero {
		scalingConfig := handlers.ScalingConfig{
			MaxPollCount:         uint(1000),
			FunctionPollInterval: time.Millisecond * 10,
			CacheExpiry:          time.Second * 5, // freshness of replica values before going stale
			ServiceQuery:         alertHandler,
		}

		functionProxy = handlers.MakeScalingHandler(faasHandlers.Proxy, faasHandlers.QueryFunction, scalingConfig)
	}
	// r.StrictSlash(false)	// This didn't work, so register routes twice.
	r.HandleFunc("/function/{name:[-a-zA-Z_0-9]+}", functionProxy)
	r.HandleFunc("/function/{name:[-a-zA-Z_0-9]+}/", functionProxy)
	r.HandleFunc("/function/{name:[-a-zA-Z_0-9]+}/{params:.*}", functionProxy)

	r.HandleFunc("/system/info", faasHandlers.InfoHandler).Methods(http.MethodGet)
	r.HandleFunc("/system/alert", faasHandlers.Alert).Methods(http.MethodPost)

	r.HandleFunc("/system/function/{name:[-a-zA-Z_0-9]+}", faasHandlers.QueryFunction).Methods(http.MethodGet)
	r.HandleFunc("/system/functions", faasHandlers.ListFunctions).Methods(http.MethodGet)
	r.HandleFunc("/system/functions", faasHandlers.DeployFunction).Methods(http.MethodPost)
	r.HandleFunc("/system/functions", faasHandlers.DeleteFunction).Methods(http.MethodDelete)
	r.HandleFunc("/system/functions", faasHandlers.UpdateFunction).Methods(http.MethodPut)
	r.HandleFunc("/system/scale-function/{name:[-a-zA-Z_0-9]+}", faasHandlers.ScaleFunction).Methods(http.MethodPost)

	if faasHandlers.QueuedProxy != nil {
		r.HandleFunc("/async-function/{name:[-a-zA-Z_0-9]+}/", faasHandlers.QueuedProxy).Methods(http.MethodPost)
		r.HandleFunc("/async-function/{name:[-a-zA-Z_0-9]+}", faasHandlers.QueuedProxy).Methods(http.MethodPost)
		r.HandleFunc("/async-function/{name:[-a-zA-Z_0-9]+}/{params:.*}", faasHandlers.QueuedProxy).Methods(http.MethodPost)

		r.HandleFunc("/system/async-report", faasHandlers.AsyncReport)
	}

	fs := http.FileServer(http.Dir("./assets/"))

	// This URL allows access from the UI to the OpenFaaS store
	allowedCORSHost := "raw.githubusercontent.com"
	fsCORS := handlers.DecorateWithCORS(fs, allowedCORSHost)

	uiHandler := http.StripPrefix("/ui", fsCORS)
	if credentials != nil {
		r.PathPrefix("/ui/").Handler(auth.DecorateWithBasicAuth(uiHandler.ServeHTTP, credentials)).Methods(http.MethodGet)
	} else {
		r.PathPrefix("/ui/").Handler(uiHandler).Methods(http.MethodGet)
	}

	metricsHandler := metrics.PrometheusHandler()
	r.Handle("/metrics", metricsHandler)
	r.HandleFunc("/healthz", handlers.MakeForwardingProxyHandler(reverseProxy, forwardingNotifiers, urlResolver, nilURLTransformer)).Methods(http.MethodGet)

	r.Handle("/", http.RedirectHandler("/ui/", http.StatusMovedPermanently)).Methods(http.MethodGet)

	tcpPort := 8080

	s := &http.Server{
		Addr:           fmt.Sprintf(":%d", tcpPort),
		ReadTimeout:    config.ReadTimeout,
		WriteTimeout:   config.WriteTimeout,
		MaxHeaderBytes: http.DefaultMaxHeaderBytes, // 1MB - can be overridden by setting Server.MaxHeaderBytes.
		Handler:        r,
	}

	log.Fatal(s.ListenAndServe())
}
<|endoftext|>


<commit_before>package control

import (
	"encoding/json"
	"errors"
	"net/http"
)

// response -- wraps http.Response
type response struct {
	resp *http.Response
	err  error
}

// Close -- cleans up response resources
func (r response) Close() error {
	if r.resp != nil && r.resp.Body != nil {
		return r.resp.Body.Close()
	}
	return r.err
}

// Error -- returns any errors happening when running the request
func (r response) Error() error {
	return r.err
}

// ParseJSON -- parses the response as JSON and closes the response body
func (r response) ReadJSON(tgt interface{}) error {
	if r.resp == nil {
		return errors.New("request failed, can't unmarshal response")
	}
	defer r.resp.Body.Close()

	var decoder = json.NewDecoder(r.resp.Body)
	return decoder.Decode(&tgt)
}
<commit_msg>control.response: added Read() and ReadString() methods<commit_after>package control

import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"net/http"
)

// response -- wraps http.Response
type response struct {
	resp *http.Response
	err  error
}

// Close -- cleans up response resources
func (r response) Close() error {
	if r.resp != nil && r.resp.Body != nil {
		return r.resp.Body.Close()
	}
	return r.err
}

// Error -- returns any errors happening when running the request
func (r response) Error() error {
	return r.err
}

// ParseJSON -- parses the response as JSON and closes the response body
func (r response) ReadJSON(tgt interface{}) error {
	if r.resp == nil {
		return errors.New("request failed, can't unmarshal response")
	}
	defer r.resp.Body.Close()

	var decoder = json.NewDecoder(r.resp.Body)
	return decoder.Decode(&tgt)
}

// Read -- reads the response data
func (r response) Read(buffer []byte) (int, error) {
	return r.resp.Body.Read(buffer)
}

// ReadString
func (r response) ReadString() (string, error) {
	var data, err = ioutil.ReadAll(r.resp.Body)
	if err != nil {
		return "", err
	}
	return string(data), nil
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2016 Red Hat, Inc.
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 topology

import (
	"github.com/nu7hatch/gouuid"

	"github.com/skydive-project/skydive/logging"
	"github.com/skydive-project/skydive/topology/graph"
)

type TIDMapper struct {
	graph.DefaultGraphListener
	Graph  *graph.Graph
	hostID graph.Identifier
}

func (t *TIDMapper) Start() {
	t.Graph.AddEventListener(t)
}

func (t *TIDMapper) Stop() {
	t.Graph.RemoveEventListener(t)
}

func (t *TIDMapper) setTID(parent, child *graph.Node) {
	tp, _ := child.GetFieldString("Type")
	if tp == "" {
		return
	}

	name, _ := child.GetFieldString("Name")
	if name == "" {
		return
	}

	if tid, _ := parent.GetFieldString("TID"); tid != "" {
		tid = tid + name + tp
		u, _ := uuid.NewV5(uuid.NamespaceOID, []byte(tid))
		t.Graph.AddMetadata(child, "TID", u.String())
	}
}

func (t *TIDMapper) setChildrenTID(parent *graph.Node) {
	children := t.Graph.LookupChildren(parent, graph.Metadata{}, graph.Metadata{"RelationType": "ownership"})
	for _, child := range children {
		t.setTID(parent, child)
	}
}

// onNodeEvent set TID
// TID is UUIDV5(ID/UUID) of "root" node like host, netns, ovsport, fabric
// for other nodes TID is UUIDV5(rootTID + Name + Type)
func (t *TIDMapper) onNodeEvent(n *graph.Node) {
	if _, err := n.GetFieldString("TID"); err != nil {
		if tp, err := n.GetFieldString("Type"); err == nil {
			switch tp {
			case "host":
				if name, err := n.GetFieldString("Name"); err == nil {
					u, _ := uuid.NewV5(uuid.NamespaceOID, []byte(name))
					t.hostID = graph.Identifier(u.String())
					t.Graph.AddMetadata(n, "TID", u.String())
				}

				t.setChildrenTID(n)
			case "netns":
				if path, _ := n.GetFieldString("Path"); path != "" {
					tid := string(t.hostID) + path + tp
					u, _ := uuid.NewV5(uuid.NamespaceOID, []byte(tid))
					t.Graph.AddMetadata(n, "TID", u.String())

					t.setChildrenTID(n)
				}
			case "ovsport":
				if u, _ := n.GetFieldString("UUID"); u != "" {
					tid := string(t.hostID) + u + tp
					u, _ := uuid.NewV5(uuid.NamespaceOID, []byte(tid))
					t.Graph.AddMetadata(n, "TID", u.String())

					t.setChildrenTID(n)
				}
			default:
				if probe, _ := n.GetFieldString("Probe"); probe == "fabric" {
					t.Graph.AddMetadata(n, "TID", string(n.ID))
				} else {
					parents := t.Graph.LookupParents(n, graph.Metadata{}, graph.Metadata{"RelationType": "ownership"})
					if len(parents) > 1 {
						logging.GetLogger().Errorf("A should always only have one ownership parent: %v", n)
					} else if len(parents) == 1 {
						t.setTID(parents[0], n)
					}
				}
			}
		}
	}
}

func (t *TIDMapper) OnNodeUpdated(n *graph.Node) {
	t.onNodeEvent(n)
}

func (t *TIDMapper) OnNodeAdded(n *graph.Node) {
	t.onNodeEvent(n)
}

// onEdgeEvent set TID for child TID nodes which is composed of the name
// the TID of the parent node and the type.
func (t *TIDMapper) onEdgeEvent(e *graph.Edge) {
	if rl, _ := e.GetFieldString("RelationType"); rl != "ownership" {
		return
	}

	parents, children := t.Graph.GetEdgeNodes(e, graph.Metadata{}, graph.Metadata{})
	if len(parents) == 0 || len(children) == 0 {
		return
	}

	t.setTID(parents[0], children[0])
}

func (t *TIDMapper) OnEdgeUpdated(e *graph.Edge) {
	t.onEdgeEvent(e)
}

func (t *TIDMapper) OnEdgeAdded(e *graph.Edge) {
	t.onEdgeEvent(e)
}

func NewTIDMapper(g *graph.Graph) *TIDMapper {
	return &TIDMapper{
		Graph: g,
	}
}
<commit_msg>tid: use consistant key for NetNS<commit_after>/*
 * Copyright (C) 2016 Red Hat, Inc.
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 topology

import (
	"github.com/nu7hatch/gouuid"

	"github.com/skydive-project/skydive/logging"
	"github.com/skydive-project/skydive/topology/graph"
)

type TIDMapper struct {
	graph.DefaultGraphListener
	Graph  *graph.Graph
	hostID graph.Identifier
}

func (t *TIDMapper) Start() {
	t.Graph.AddEventListener(t)
}

func (t *TIDMapper) Stop() {
	t.Graph.RemoveEventListener(t)
}

func (t *TIDMapper) setTID(parent, child *graph.Node) {
	tp, _ := child.GetFieldString("Type")
	if tp == "" {
		return
	}

	var key string
	switch tp {
	case "netns":
		key, _ = child.GetFieldString("Path")
	default:
		key, _ = child.GetFieldString("Name")
	}

	if key == "" {
		return
	}

	if tid, _ := parent.GetFieldString("TID"); tid != "" {
		tid = tid + key + tp
		u, _ := uuid.NewV5(uuid.NamespaceOID, []byte(tid))
		t.Graph.AddMetadata(child, "TID", u.String())
	}
}

func (t *TIDMapper) setChildrenTID(parent *graph.Node) {
	children := t.Graph.LookupChildren(parent, graph.Metadata{}, graph.Metadata{"RelationType": "ownership"})
	for _, child := range children {
		t.setTID(parent, child)
	}
}

// onNodeEvent set TID
// TID is UUIDV5(ID/UUID) of "root" node like host, netns, ovsport, fabric
// for other nodes TID is UUIDV5(rootTID + Name + Type)
func (t *TIDMapper) onNodeEvent(n *graph.Node) {
	if _, err := n.GetFieldString("TID"); err != nil {
		if tp, err := n.GetFieldString("Type"); err == nil {
			switch tp {
			case "host":
				if name, err := n.GetFieldString("Name"); err == nil {
					u, _ := uuid.NewV5(uuid.NamespaceOID, []byte(name))
					t.hostID = graph.Identifier(u.String())
					t.Graph.AddMetadata(n, "TID", u.String())
				}

				t.setChildrenTID(n)
			case "netns":
				if path, _ := n.GetFieldString("Path"); path != "" {
					tid := string(t.hostID) + path + tp
					u, _ := uuid.NewV5(uuid.NamespaceOID, []byte(tid))
					t.Graph.AddMetadata(n, "TID", u.String())

					t.setChildrenTID(n)
				}
			case "ovsport":
				if u, _ := n.GetFieldString("UUID"); u != "" {
					tid := string(t.hostID) + u + tp
					u, _ := uuid.NewV5(uuid.NamespaceOID, []byte(tid))
					t.Graph.AddMetadata(n, "TID", u.String())

					t.setChildrenTID(n)
				}
			default:
				if probe, _ := n.GetFieldString("Probe"); probe == "fabric" {
					t.Graph.AddMetadata(n, "TID", string(n.ID))
				} else {
					parents := t.Graph.LookupParents(n, graph.Metadata{}, graph.Metadata{"RelationType": "ownership"})
					if len(parents) > 1 {
						logging.GetLogger().Errorf("A should always only have one ownership parent: %v", n)
					} else if len(parents) == 1 {
						t.setTID(parents[0], n)
					}
				}
			}
		}
	}
}

func (t *TIDMapper) OnNodeUpdated(n *graph.Node) {
	t.onNodeEvent(n)
}

func (t *TIDMapper) OnNodeAdded(n *graph.Node) {
	t.onNodeEvent(n)
}

// onEdgeEvent set TID for child TID nodes which is composed of the name
// the TID of the parent node and the type.
func (t *TIDMapper) onEdgeEvent(e *graph.Edge) {
	if rl, _ := e.GetFieldString("RelationType"); rl != "ownership" {
		return
	}

	parents, children := t.Graph.GetEdgeNodes(e, graph.Metadata{}, graph.Metadata{})
	if len(parents) == 0 || len(children) == 0 {
		return
	}

	t.setTID(parents[0], children[0])
}

func (t *TIDMapper) OnEdgeUpdated(e *graph.Edge) {
	t.onEdgeEvent(e)
}

func (t *TIDMapper) OnEdgeAdded(e *graph.Edge) {
	t.onEdgeEvent(e)
}

func NewTIDMapper(g *graph.Graph) *TIDMapper {
	return &TIDMapper{
		Graph: g,
	}
}
<|endoftext|>


<commit_before>// Copyright © 2015 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

package components

import (
	"fmt"

	"github.com/TheThingsNetwork/ttn/core"
	"github.com/apex/log"
)

var ErrNotImplemented = fmt.Errorf("Ilegal call on non implemented method")

type Handler struct {
	ctx log.Interface
	db  handlerStorage
}

type handlerStorage interface {
	store(data interface{}) error
}

func NewHandler(db handlerStorage, ctx log.Interface) (*Handler, error) {
	return &Handler{
		ctx: ctx,
		db:  db,
	}, nil
}

func (h *Handler) Register(reg core.Registration, an core.AckNacker) error {
	return nil
}

func (h *Handler) HandleUp(p core.Packet, an core.AckNacker, upAdapter core.Adapter) error {
	return nil
}

func (h *Handler) HandleDown(p core.Packet, an core.AckNacker, downAdapter core.Adapter) error {
	return ErrNotImplemented
}
<commit_msg>[handler] Draft handler buffering mechanism<commit_after>// Copyright © 2015 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

package components

import (
	"fmt"
	"time"

	"github.com/TheThingsNetwork/ttn/core"
	"github.com/apex/log"
	//"github.com/brocaar/lorawan"
)

var ErrNotImplemented = fmt.Errorf("Ilegal call on non implemented method")

type Handler struct {
	ctx log.Interface
	db  handlerStorage
	set chan<- uplinkBundle
}

type handlerStorage interface {
}

type bundleId [20]byte

type uplinkBundle struct {
	id     bundleId
	an     core.AckNacker
	packet core.Packet
}

func NewHandler(db handlerStorage, ctx log.Interface) (*Handler, error) {
	h := Handler{
		ctx: ctx,
		db:  db,
	}

	bundles := make(chan []uplinkBundle)
	set := make(chan uplinkBundle)

	go h.consumeBundles(bundles)
	go h.manageBuffers(bundles, set)
	h.set = set

	return &h, nil
}

func (h *Handler) Register(reg core.Registration, an core.AckNacker) error {
	return nil
}

func (h *Handler) HandleUp(p core.Packet, an core.AckNacker, upAdapter core.Adapter) error {
	return nil
}

func (h *Handler) HandleDown(p core.Packet, an core.AckNacker, downAdapter core.Adapter) error {
	return ErrNotImplemented
}

func (h *Handler) consumeBundles(bundles <-chan []uplinkBundle) {
	//for bundle := range bundles {
	// Deduplicate
	// DecryptPayload
	// AddMeta
	// AckOrNack each packets
	// Store into mongo
	//}
}

// manageBuffers gather new incoming bundles that possess the same id
// It then flushs them once a given delay has passed since the reception of the first bundle.
func (h *Handler) manageBuffers(bundles chan<- []uplinkBundle, set <-chan uplinkBundle) {
	buffers := make(map[bundleId][]uplinkBundle)
	alarm := make(chan bundleId)

	for {
		select {
		case id := <-alarm:
			b := buffers[id]
			delete(buffers, id)
			go func(b []uplinkBundle) { bundles <- b }(b)
		case bundle := <-set:
			b := append(buffers[bundle.id], bundle)
			if len(b) == 1 {
				go setAlarm(alarm, bundle.id, time.Millisecond*300)
			}
			buffers[bundle.id] = b
		}
	}
}

// setAlarm will trigger a message on the given channel after a given delay.
func setAlarm(alarm chan<- bundleId, id bundleId, delay time.Duration) {
	<-time.After(delay)
	alarm <- id
}
<|endoftext|>


<commit_before>// Copyright 2015 tsuru-client 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 (
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"

	"github.com/tsuru/tsuru/cmd"
	"github.com/tsuru/tsuru/exec"
)

type pluginInstall struct{}

func (pluginInstall) Info() *cmd.Info {
	return &cmd.Info{
		Name:    "plugin-install",
		Usage:   "plugin-install <plugin-name> <plugin-url>",
		Desc:    `Downloads the plugin file. It will be copied to [[$HOME/.tsuru/plugins]].`,
		MinArgs: 2,
	}
}

func (c *pluginInstall) Run(context *cmd.Context, client *cmd.Client) error {
	pluginsDir := cmd.JoinWithUserDir(".tsuru", "plugins")
	err := filesystem().MkdirAll(pluginsDir, 0755)
	if err != nil {
		return err
	}
	pluginName := context.Args[0]
	pluginUrl := context.Args[1]
	pluginPath := cmd.JoinWithUserDir(".tsuru", "plugins", pluginName)
	file, err := filesystem().OpenFile(pluginPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755)
	if err != nil {
		return err
	}
	resp, err := http.Get(pluginUrl)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	n, err := file.Write(data)
	if err != nil {
		return err
	}
	if n != len(data) {
		return errors.New("Failed to install plugin.")
	}
	fmt.Fprintf(context.Stdout, `Plugin "%s" successfully installed!`+"\n", pluginName)
	return nil
}

type plugin struct{}

func (plugin) Info() *cmd.Info {
	return &cmd.Info{
		Name:    "plugin",
		Usage:   "plugin <plugin-name> [<args>]",
		Desc:    "Execute tsuru plugins.",
		MinArgs: 1,
	}
}

func (c *plugin) Run(context *cmd.Context, client *cmd.Client) error {
	pluginName := context.Args[0]
	pluginPath := cmd.JoinWithUserDir(".tsuru", "plugins", pluginName)
	target, err := cmd.GetURL("/")
	if err != nil {
		return err
	}
	token, err := cmd.ReadToken()
	if err != nil {
		return err
	}
	envs := os.Environ()
	tsuruEnvs := []string{
		"TSURU_TARGET=" + target,
		"TSURU_TOKEN=" + token,
		"TSURU_PLUGIN_NAME=" + pluginName,
	}
	envs = append(envs, tsuruEnvs...)
	opts := exec.ExecuteOptions{
		Cmd:    pluginPath,
		Args:   context.Args[1:],
		Stdout: context.Stdout,
		Stderr: context.Stderr,
		Stdin:  context.Stdin,
		Envs:   envs,
	}
	return executor().Execute(opts)
}

type pluginRemove struct{}

func (pluginRemove) Info() *cmd.Info {
	return &cmd.Info{
		Name:    "plugin-remove",
		Usage:   "plugin-remove <plugin-name>",
		Desc:    "Removes a previously installed tsuru plugin.",
		MinArgs: 1,
	}
}

func (c *pluginRemove) Run(context *cmd.Context, client *cmd.Client) error {
	pluginName := context.Args[0]
	pluginPath := cmd.JoinWithUserDir(".tsuru", "plugins", pluginName)
	err := filesystem().Remove(pluginPath)
	if err != nil {
		return err
	}
	fmt.Fprintf(context.Stdout, `Plugin "%s" successfully removed!`+"\n", pluginName)
	return nil
}

type pluginList struct{}

func (pluginList) Info() *cmd.Info {
	return &cmd.Info{
		Name:    "plugin-list",
		Usage:   "plugin-list",
		Desc:    "List installed tsuru plugins.",
		MinArgs: 0,
	}
}

func (c *pluginList) Run(context *cmd.Context, client *cmd.Client) error {
	pluginsPath := cmd.JoinWithUserDir(".tsuru", "plugins")
	plugins, _ := ioutil.ReadDir(pluginsPath)
	for _, p := range plugins {
		fmt.Println(p.Name())
	}
	return nil
}
<commit_msg>plugin context using raw output<commit_after>// Copyright 2015 tsuru-client 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 (
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"

	"github.com/tsuru/tsuru/cmd"
	"github.com/tsuru/tsuru/exec"
)

type pluginInstall struct{}

func (pluginInstall) Info() *cmd.Info {
	return &cmd.Info{
		Name:    "plugin-install",
		Usage:   "plugin-install <plugin-name> <plugin-url>",
		Desc:    `Downloads the plugin file. It will be copied to [[$HOME/.tsuru/plugins]].`,
		MinArgs: 2,
	}
}

func (c *pluginInstall) Run(context *cmd.Context, client *cmd.Client) error {
	context.RawOutput()
	pluginsDir := cmd.JoinWithUserDir(".tsuru", "plugins")
	err := filesystem().MkdirAll(pluginsDir, 0755)
	if err != nil {
		return err
	}
	pluginName := context.Args[0]
	pluginUrl := context.Args[1]
	pluginPath := cmd.JoinWithUserDir(".tsuru", "plugins", pluginName)
	file, err := filesystem().OpenFile(pluginPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755)
	if err != nil {
		return err
	}
	resp, err := http.Get(pluginUrl)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	n, err := file.Write(data)
	if err != nil {
		return err
	}
	if n != len(data) {
		return errors.New("Failed to install plugin.")
	}
	fmt.Fprintf(context.Stdout, `Plugin "%s" successfully installed!`+"\n", pluginName)
	return nil
}

type plugin struct{}

func (plugin) Info() *cmd.Info {
	return &cmd.Info{
		Name:    "plugin",
		Usage:   "plugin <plugin-name> [<args>]",
		Desc:    "Execute tsuru plugins.",
		MinArgs: 1,
	}
}

func (c *plugin) Run(context *cmd.Context, client *cmd.Client) error {
	pluginName := context.Args[0]
	pluginPath := cmd.JoinWithUserDir(".tsuru", "plugins", pluginName)
	target, err := cmd.GetURL("/")
	if err != nil {
		return err
	}
	token, err := cmd.ReadToken()
	if err != nil {
		return err
	}
	envs := os.Environ()
	tsuruEnvs := []string{
		"TSURU_TARGET=" + target,
		"TSURU_TOKEN=" + token,
		"TSURU_PLUGIN_NAME=" + pluginName,
	}
	envs = append(envs, tsuruEnvs...)
	opts := exec.ExecuteOptions{
		Cmd:    pluginPath,
		Args:   context.Args[1:],
		Stdout: context.Stdout,
		Stderr: context.Stderr,
		Stdin:  context.Stdin,
		Envs:   envs,
	}
	return executor().Execute(opts)
}

type pluginRemove struct{}

func (pluginRemove) Info() *cmd.Info {
	return &cmd.Info{
		Name:    "plugin-remove",
		Usage:   "plugin-remove <plugin-name>",
		Desc:    "Removes a previously installed tsuru plugin.",
		MinArgs: 1,
	}
}

func (c *pluginRemove) Run(context *cmd.Context, client *cmd.Client) error {
	pluginName := context.Args[0]
	pluginPath := cmd.JoinWithUserDir(".tsuru", "plugins", pluginName)
	err := filesystem().Remove(pluginPath)
	if err != nil {
		return err
	}
	fmt.Fprintf(context.Stdout, `Plugin "%s" successfully removed!`+"\n", pluginName)
	return nil
}

type pluginList struct{}

func (pluginList) Info() *cmd.Info {
	return &cmd.Info{
		Name:    "plugin-list",
		Usage:   "plugin-list",
		Desc:    "List installed tsuru plugins.",
		MinArgs: 0,
	}
}

func (c *pluginList) Run(context *cmd.Context, client *cmd.Client) error {
	pluginsPath := cmd.JoinWithUserDir(".tsuru", "plugins")
	plugins, _ := ioutil.ReadDir(pluginsPath)
	for _, p := range plugins {
		fmt.Println(p.Name())
	}
	return nil
}
<|endoftext|>