<commit_before>package ember

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"
)

var e = New()

type routeTest struct {
	method   string
	path     string
	expected string
}

func init() {
	// Register a route for index.html file.
	e.Index("./example/dist/index.html")

	// Register a route for assets.
	e.Assets("/assets", "./example/dist/assets")

	// Create a model and register a route for /stats
	e.Model("stats").FindAll(responce)

	// Register a namespace.
	api := e.Namespace("/api/v1")

	// Create routes for a model.
	people := api.Model("people")

	// GET /api/v1/people
	people.FindAll(responce)

	// GET /api/v1/people/{id}
	people.Find(responce)

	// POST /api/v1/people
	people.Create(responce)

	// PUT /api/v1/people/{id}
	people.Update(responce)

	// DELETE /api/v1/people/{id}
	people.Delete(responce)
}

func responce(w http.ResponseWriter, req *http.Request) {
	fmt.Fprintf(w, "%v %v", req.Method, req.URL)
}

func TestIndex(t *testing.T) {
	server := httptest.NewServer(e.Router)
	defer server.Close()

	testFile(t, server, "/")
}

func TestAssets(t *testing.T) {
	server := httptest.NewServer(e.Router)
	defer server.Close()

	tests := []string{
		"/assets/example.css",
		"/assets/example.js",
	}

	for _, test := range tests {
		testFile(t, server, test)
	}
}

func TestNotFound(t *testing.T) {
	server := httptest.NewServer(e.Router)
	defer server.Close()

	testFile(t, server, "/devnull")
}

func TestGetModel(t *testing.T) {
	server := httptest.NewServer(e.Router)
	defer server.Close()

	tests := []routeTest{
		{
			method:   "GET",
			path:     "/stats",
			expected: "GET /stats",
		},
	}

	for _, test := range tests {
		testRoute(t, server, test)
	}
}

func TestNamespace(t *testing.T) {
	server := httptest.NewServer(e.Router)
	defer server.Close()

	tests := []routeTest{
		{
			method:   "GET",
			path:     "/api/v1/people",
			expected: "GET /api/v1/people",
		},
		{
			method:   "GET",
			path:     "/api/v1/people/1",
			expected: "GET /api/v1/people/1",
		},
		{
			method:   "PUT",
			path:     "/api/v1/people/1",
			expected: "PUT /api/v1/people/1",
		},
		{
			method:   "POST",
			path:     "/api/v1/people",
			expected: "POST /api/v1/people",
		},
		{
			method:   "DELETE",
			path:     "/api/v1/people/1",
			expected: "DELETE /api/v1/people/1",
		},
	}

	for _, test := range tests {
		testRoute(t, server, test)
	}
}

func testRoute(t *testing.T, server *httptest.Server, test routeTest) {
	res, err := sendRequest(test.method, server.URL+test.path)
	if err != nil {
		panic(err)
	}

	data, err := ioutil.ReadAll(res.Body)
	if err != nil {
		panic(err)
	}

	actual := strings.Trim(string(data), "\n")

	if test.expected == actual {
		return
	}

	t.Errorf(
		"[%v %v] expected: [%v], got: [%v]\n",
		test.method,
		test.path,
		test.expected,
		actual,
	)
}

func testFile(t *testing.T, server *httptest.Server, path string) {
	res, err := sendRequest("GET", server.URL+path)
	if err != nil {
		panic(err)
	}

	if res.StatusCode == http.StatusOK {
		return
	}

	t.Errorf("[%v] expected: [%d], got: [%d]\n", path, http.StatusOK, res.StatusCode)
}

func sendRequest(method string, url string) (res *http.Response, err error) {
	req, err := http.NewRequest(method, url, nil)
	if err != nil {
		return nil, err
	}

	client := &http.Client{}
	return client.Do(req)
}
<commit_msg>Refactoring & Typos Inc.<commit_after>package ember

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"
)

var e = New()

type routeTest struct {
	method   string
	path     string
	expected string
}

func init() {
	// Register a route for index.html file.
	e.Index("./example/dist/index.html")

	// Register a route for assets.
	e.Assets("/assets", "./example/dist/assets")

	// Create a model and register a route for /stats
	e.Model("stats").FindAll(sendResponse)

	// Register a namespace.
	api := e.Namespace("/api/v1")

	// Create routes for a model.
	people := api.Model("people")

	// GET /api/v1/people
	people.FindAll(sendResponse)

	// GET /api/v1/people/{id}
	people.Find(sendResponse)

	// POST /api/v1/people
	people.Create(sendResponse)

	// PUT /api/v1/people/{id}
	people.Update(sendResponse)

	// DELETE /api/v1/people/{id}
	people.Delete(sendResponse)
}

func TestIndex(t *testing.T) {
	server := httptest.NewServer(e.Router)
	defer server.Close()

	testFile(t, server, "/")
}

func TestAssets(t *testing.T) {
	server := httptest.NewServer(e.Router)
	defer server.Close()

	tests := []string{
		"/assets/example.css",
		"/assets/example.js",
	}

	for _, test := range tests {
		testFile(t, server, test)
	}
}

func TestNotFound(t *testing.T) {
	server := httptest.NewServer(e.Router)
	defer server.Close()

	testFile(t, server, "/devnull")
}

func TestGetModel(t *testing.T) {
	server := httptest.NewServer(e.Router)
	defer server.Close()

	tests := []routeTest{
		{
			method:   "GET",
			path:     "/stats",
			expected: "GET /stats",
		},
	}

	for _, test := range tests {
		testRoute(t, server, test)
	}
}

func TestNamespace(t *testing.T) {
	server := httptest.NewServer(e.Router)
	defer server.Close()

	tests := []routeTest{
		{
			method:   "GET",
			path:     "/api/v1/people",
			expected: "GET /api/v1/people",
		},
		{
			method:   "GET",
			path:     "/api/v1/people/1",
			expected: "GET /api/v1/people/1",
		},
		{
			method:   "PUT",
			path:     "/api/v1/people/1",
			expected: "PUT /api/v1/people/1",
		},
		{
			method:   "POST",
			path:     "/api/v1/people",
			expected: "POST /api/v1/people",
		},
		{
			method:   "DELETE",
			path:     "/api/v1/people/1",
			expected: "DELETE /api/v1/people/1",
		},
	}

	for _, test := range tests {
		testRoute(t, server, test)
	}
}

func testRoute(t *testing.T, server *httptest.Server, test routeTest) {
	res, err := sendRequest(test.method, server.URL+test.path)
	if err != nil {
		panic(err)
	}

	data, err := ioutil.ReadAll(res.Body)
	if err != nil {
		panic(err)
	}

	actual := strings.Trim(string(data), "\n")

	if test.expected == actual {
		return
	}

	t.Errorf(
		"[%v %v] expected: [%v], got: [%v]\n",
		test.method,
		test.path,
		test.expected,
		actual,
	)
}

func testFile(t *testing.T, server *httptest.Server, path string) {
	res, err := sendRequest("GET", server.URL+path)
	if err != nil {
		panic(err)
	}

	if res.StatusCode == http.StatusOK {
		return
	}

	t.Errorf("[%v] expected: [%d], got: [%d]\n", path, http.StatusOK, res.StatusCode)
}

func sendRequest(method string, url string) (res *http.Response, err error) {
	req, err := http.NewRequest(method, url, nil)
	if err != nil {
		return nil, err
	}

	client := &http.Client{}
	return client.Do(req)
}

func sendResponse(w http.ResponseWriter, req *http.Request) {
	fmt.Fprintf(w, "%v %v", req.Method, req.URL)
}
<|endoftext|>


<commit_before>// +build !gtk_3_6,!gtk_3_8,!gtk_3_10,!gtk_3_12,!gtk_3_14
// Supports building with gtk 3.16+

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

package gtk

// #include <gtk/gtk.h>
// #include "gtk_since_3_16.go.h"
import "C"
import (
	"errors"
	"unsafe"

	"github.com/gotk3/gotk3/gdk"
	"github.com/gotk3/gotk3/glib"
)

func init() {

	tm := []glib.TypeMarshaler{
		{glib.Type(C.gtk_gl_area_get_type()), marshalGLArea},
	}

	glib.RegisterGValueMarshalers(tm)

	WrapMap["GtkGLArea"] = wrapGLArea
}

/*
 * GtkGLArea
 */

// GLArea is a representation of GTK's GtkGLArea.
type GLArea struct {
	Widget
}

// native returns a pointer to the underlying GtkGLArea.
func (v *GLArea) native() *C.GtkGLArea {
	if v == nil || v.GObject == nil {
		return nil
	}
	p := unsafe.Pointer(v.GObject)
	return C.toGtkGLArea(p)
}

func marshalGLArea(p uintptr) (interface{}, error) {
	c := C.g_value_get_object((*C.GValue)(unsafe.Pointer(p)))
	obj := glib.Take(unsafe.Pointer(c))
	return wrapGLArea(obj), nil
}

func wrapGLArea(obj *glib.Object) *GLArea {
	return &GLArea{Widget{glib.InitiallyUnowned{obj}}}
}

func WidgetToGLArea(widget *Widget) (interface{}, error) {
	obj := glib.Take(unsafe.Pointer(widget.GObject))
	return wrapGLArea(obj), nil
}

// GLAreaNew is a wrapper around gtk_gl_area_new().
func GLAreaNew() (*GLArea, error) {
	c := C.gtk_gl_area_new()
	if c == nil {
		return nil, nilPtrErr
	}
	obj := glib.Take(unsafe.Pointer(c))

	return wrapGLArea(obj), nil
}

// GetUseES is a wrapper around gtk_gl_area_get_use_es().
func (v *GLArea) GetUseES() bool {
	return gobool(C.gtk_gl_area_get_use_es(v.native()))
}

// SetUseES is a wrapper around gtk_gl_area_set_use_es().
func (v *GLArea) SetUseES(es bool) {
	C.gtk_gl_area_set_use_es(v.native(), gbool(es))
}

// MajorVersion is a representation of OpenGL major version.
type MajorVersion int

// MinorVersion is a representation of OpenGL minor version.
type MinorVersion int

// GetRequiredVersion is a wrapper around gtk_gl_area_get_required_version().
func (v *GLArea) GetRequiredVersion() (MajorVersion, MinorVersion) {
	var major, minor int
	C.gtk_gl_area_get_required_version(v.native(),
		(*C.int)(unsafe.Pointer(&major)), (*C.int)(unsafe.Pointer(&minor)))

	return MajorVersion(major), MinorVersion(minor)
}

// SetRequiredVersion is a wrapper around gtk_gl_area_set_required_version().
func (v *GLArea) SetRequiredVersion(major, minor int) {
	C.gtk_gl_area_set_required_version(v.native(), (C.int)(major), (C.int)(minor))
}

// HasDepthBuffer is a wrapper around gtk_gl_area_get_has_depth_buffer().
func (v *GLArea) HasDepthBuffer() bool {
	return gobool(C.gtk_gl_area_get_has_depth_buffer(v.native()))
}

// SetHasDepthBuffer is a wrapper around gtk_gl_area_set_has_depth_buffer().
func (v *GLArea) SetHasDepthBuffer(hasDepthBuffer bool) {
	C.gtk_gl_area_set_has_depth_buffer(v.native(), gbool(hasDepthBuffer))
}

// HasStencilBuffer is a wrapper around gtk_gl_area_get_has_stencil_buffer().
func (v *GLArea) HasStencilBuffer() bool {
	return gobool(C.gtk_gl_area_get_has_stencil_buffer(v.native()))
}

// SetHasStencilBuffer is a wrapper around gtk_gl_area_set_has_stencil_buffer().
func (v *GLArea) SetHasStencilBuffer(hasStencilBuffer bool) {
	C.gtk_gl_area_set_has_stencil_buffer(v.native(), gbool(hasStencilBuffer))
}

// GetAutoRender is a wrapper around gtk_gl_area_get_auto_render().
func (v *GLArea) GetAutoRender() bool {
	return gobool(C.gtk_gl_area_get_auto_render(v.native()))
}

// SetAutoRender is a wrapper around gtk_gl_area_set_has_stencil_buffer().
func (v *GLArea) SetAutoRender(autoRender bool) {
	C.gtk_gl_area_set_auto_render(v.native(), gbool(autoRender))
}

// QueueRender is a wrapper around gtk_gl_area_queue_render().
func (v *GLArea) QueueRender() {
	C.gtk_gl_area_queue_render(v.native())
}

// GetContext is a wrapper around gtk_gl_area_get_context().
func (v *GLArea) GetContext() (*gdk.GLContext, error) {
	c := C.gtk_gl_area_get_context(v.native())
	if c == nil {
		return nil, nilPtrErr
	}
	obj := &glib.Object{glib.ToGObject(unsafe.Pointer(c))}
	return &(gdk.GLContext{obj}), nil
}

// MakeCurrent is a wrapper around gtk_gl_area_make_current().
func (v *GLArea) MakeCurrent() {
	C.gtk_gl_area_make_current(v.native())
}

// AttachBuffers is a wrapper around gtk_gl_area_attach_buffers().
func (v *GLArea) AttachBuffers() {
	C.gtk_gl_area_attach_buffers(v.native())
}

// GError* gtk_gl_area_get_error (GtkGLArea *area);
func (v *GLArea) GetError() error {
	var err *C.GError = nil
	err = C.gtk_gl_area_get_error(v.native())
	if err != nil {
		defer C.g_error_free(err)
		return errors.New(goString(err.message))
	}
	return nil
}

// void gtk_gl_area_set_error (GtkGLArea *area, const GError *error);
<commit_msg>Fixed WidgetToGLArea function<commit_after>// +build !gtk_3_6,!gtk_3_8,!gtk_3_10,!gtk_3_12,!gtk_3_14
// Supports building with gtk 3.16+

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

package gtk

// #include <gtk/gtk.h>
// #include "gtk_since_3_16.go.h"
import "C"
import (
	"errors"
	"unsafe"

	"github.com/gotk3/gotk3/gdk"
	"github.com/gotk3/gotk3/glib"
)

func init() {

	tm := []glib.TypeMarshaler{
		{glib.Type(C.gtk_gl_area_get_type()), marshalGLArea},
	}

	glib.RegisterGValueMarshalers(tm)

	WrapMap["GtkGLArea"] = wrapGLArea
}

/*
 * GtkGLArea
 */

// GLArea is a representation of GTK's GtkGLArea.
type GLArea struct {
	Widget
}

// native returns a pointer to the underlying GtkGLArea.
func (v *GLArea) native() *C.GtkGLArea {
	if v == nil || v.GObject == nil {
		return nil
	}
	p := unsafe.Pointer(v.GObject)
	return C.toGtkGLArea(p)
}

func marshalGLArea(p uintptr) (interface{}, error) {
	c := C.g_value_get_object((*C.GValue)(unsafe.Pointer(p)))
	obj := glib.Take(unsafe.Pointer(c))
	return wrapGLArea(obj), nil
}

func wrapGLArea(obj *glib.Object) *GLArea {
	return &GLArea{Widget{glib.InitiallyUnowned{obj}}}
}

func WidgetToGLArea(widget *Widget) (*GLArea, error) {
	obj := glib.Take(unsafe.Pointer(widget.GObject))
	return wrapGLArea(obj), nil
}

// GLAreaNew is a wrapper around gtk_gl_area_new().
func GLAreaNew() (*GLArea, error) {
	c := C.gtk_gl_area_new()
	if c == nil {
		return nil, nilPtrErr
	}
	obj := glib.Take(unsafe.Pointer(c))

	return wrapGLArea(obj), nil
}

// GetUseES is a wrapper around gtk_gl_area_get_use_es().
func (v *GLArea) GetUseES() bool {
	return gobool(C.gtk_gl_area_get_use_es(v.native()))
}

// SetUseES is a wrapper around gtk_gl_area_set_use_es().
func (v *GLArea) SetUseES(es bool) {
	C.gtk_gl_area_set_use_es(v.native(), gbool(es))
}

// MajorVersion is a representation of OpenGL major version.
type MajorVersion int

// MinorVersion is a representation of OpenGL minor version.
type MinorVersion int

// GetRequiredVersion is a wrapper around gtk_gl_area_get_required_version().
func (v *GLArea) GetRequiredVersion() (MajorVersion, MinorVersion) {
	var major, minor int
	C.gtk_gl_area_get_required_version(v.native(),
		(*C.int)(unsafe.Pointer(&major)), (*C.int)(unsafe.Pointer(&minor)))

	return MajorVersion(major), MinorVersion(minor)
}

// SetRequiredVersion is a wrapper around gtk_gl_area_set_required_version().
func (v *GLArea) SetRequiredVersion(major, minor int) {
	C.gtk_gl_area_set_required_version(v.native(), (C.int)(major), (C.int)(minor))
}

// HasDepthBuffer is a wrapper around gtk_gl_area_get_has_depth_buffer().
func (v *GLArea) HasDepthBuffer() bool {
	return gobool(C.gtk_gl_area_get_has_depth_buffer(v.native()))
}

// SetHasDepthBuffer is a wrapper around gtk_gl_area_set_has_depth_buffer().
func (v *GLArea) SetHasDepthBuffer(hasDepthBuffer bool) {
	C.gtk_gl_area_set_has_depth_buffer(v.native(), gbool(hasDepthBuffer))
}

// HasStencilBuffer is a wrapper around gtk_gl_area_get_has_stencil_buffer().
func (v *GLArea) HasStencilBuffer() bool {
	return gobool(C.gtk_gl_area_get_has_stencil_buffer(v.native()))
}

// SetHasStencilBuffer is a wrapper around gtk_gl_area_set_has_stencil_buffer().
func (v *GLArea) SetHasStencilBuffer(hasStencilBuffer bool) {
	C.gtk_gl_area_set_has_stencil_buffer(v.native(), gbool(hasStencilBuffer))
}

// GetAutoRender is a wrapper around gtk_gl_area_get_auto_render().
func (v *GLArea) GetAutoRender() bool {
	return gobool(C.gtk_gl_area_get_auto_render(v.native()))
}

// SetAutoRender is a wrapper around gtk_gl_area_set_has_stencil_buffer().
func (v *GLArea) SetAutoRender(autoRender bool) {
	C.gtk_gl_area_set_auto_render(v.native(), gbool(autoRender))
}

// QueueRender is a wrapper around gtk_gl_area_queue_render().
func (v *GLArea) QueueRender() {
	C.gtk_gl_area_queue_render(v.native())
}

// GetContext is a wrapper around gtk_gl_area_get_context().
func (v *GLArea) GetContext() (*gdk.GLContext, error) {
	c := C.gtk_gl_area_get_context(v.native())
	if c == nil {
		return nil, nilPtrErr
	}
	obj := &glib.Object{glib.ToGObject(unsafe.Pointer(c))}
	return &(gdk.GLContext{obj}), nil
}

// MakeCurrent is a wrapper around gtk_gl_area_make_current().
func (v *GLArea) MakeCurrent() {
	C.gtk_gl_area_make_current(v.native())
}

// AttachBuffers is a wrapper around gtk_gl_area_attach_buffers().
func (v *GLArea) AttachBuffers() {
	C.gtk_gl_area_attach_buffers(v.native())
}

// GError* gtk_gl_area_get_error (GtkGLArea *area);
func (v *GLArea) GetError() error {
	var err *C.GError = nil
	err = C.gtk_gl_area_get_error(v.native())
	if err != nil {
		defer C.g_error_free(err)
		return errors.New(goString(err.message))
	}
	return nil
}

// void gtk_gl_area_set_error (GtkGLArea *area, const GError *error);
<|endoftext|>


<commit_before>package ipfs

import (
	"sync"
	"crypto/sha256"
	"encoding/hex"
	"github.com/ipfs/go-ipfs/core"
	"gx/ipfs/QmYgaiNVVL7f2nydijAwpDRunRkmxfu3PoK87Y3pH84uAW/go-libp2p/p2p/host"
	routing "github.com/ipfs/go-ipfs/routing/dht"
	pb "github.com/ipfs/go-ipfs/routing/dht/pb"
	multihash "gx/ipfs/QmYf7ng2hG5XBtJA3tN34DQ2GUN5HNksEw1rLDkmr6vGku/go-multihash"
	ma "gx/ipfs/QmcobAGsCjYt5DXoq9et9L8yR8er7o7Cu3DTvpaq12jYSz/go-multiaddr"
	peer "gx/ipfs/QmZwZjMVGss5rqYsJVGy18gNbkTJffFyq2x1uJ4e4p3ZAt/go-libp2p-peer"
	context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
	ctxio "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-context/io"
	ggio "gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/io"
	key "github.com/ipfs/go-ipfs/blocks/key"
)

const MAGIC string = "0000000000000000000000000000000000000000000000000000000000000000"

// A pointer is a custom provider inserted into the dht which points to a location of a file.
// For offline messaging purposes we use a hash of the recipient's ID as the key and set the
// provider to the location of the ciphertext. We set the Peer ID of the provider object to
// a magic number so we distinguish it from regular providers and use a longer ttl.
// Note this will only be compatible with the OpenBazaar/go-ipfs fork.
func AddPointer(node *core.IpfsNode, ctx context.Context, skey string, addr ma.Multiaddr) error {
	keyhash := hashStringToKey(skey)
	k := key.B58KeyDecode(keyhash.B58String())
	dht := node.Routing.(*routing.IpfsDHT)
	peerHosts := node.PeerHost
	peers, err := dht.GetClosestPeers(ctx, k)
	if err != nil {
		return err
	}
	wg := sync.WaitGroup{}
	for p := range peers {
		wg.Add(1)
		go func(p peer.ID) {
			defer wg.Done()
			err := putPointer(ctx, peerHosts, p, string(k), addr)
			if err != nil {
				log.Debug(err)
			}
		}(p)
	}
	wg.Wait()
	return nil
}

// Fetch pointers from the dht. They will be returned asynchronously.
func FindPointersAsync(dht *routing.IpfsDHT, ctx context.Context, skey string) <-chan peer.PeerInfo {
	keyhash := hashStringToKey(skey)
	peerout := dht.FindProvidersAsync(ctx, key.Key(keyhash.B58String()), 100000)
	return peerout
}

func putPointer(ctx context.Context, peerHosts host.Host, p peer.ID, skey string, addr ma.Multiaddr) error{
	magicID, err := getMagicID()
	if err != nil {
		return err
	}
	pi := peer.PeerInfo{
		ID:    magicID,
		Addrs: []ma.Multiaddr{addr},
	}

	pmes := pb.NewMessage(pb.Message_ADD_PROVIDER, skey, 0)
	pmes.ProviderPeers = pb.RawPeerInfosToPBPeers([]peer.PeerInfo{pi})
	log.Debugf("Sending PutProvider message to %s", p)
	err = sendMessage(ctx, peerHosts, p, pmes)
	if err != nil {
		return err
	}

	return nil
}

func sendMessage(ctx context.Context, host host.Host, p peer.ID, pmes *pb.Message) error {
	s, err := host.NewStream(ctx, routing.ProtocolDHT, p)
	if err != nil {
		return err
	}
	defer s.Close()

	cw := ctxio.NewWriter(ctx, s)
	w := ggio.NewDelimitedWriter(cw)

	if err := w.WriteMsg(pmes); err != nil {
		return err
	}
	return nil
}

func hashStringToKey(s string) multihash.Multihash {
	hash := sha256.New()
	hash.Write([]byte(s))
	md := hash.Sum(nil)
	keyHash, _ := multihash.Encode(md, multihash.SHA2_256)
	var mhKey multihash.Multihash = keyHash
	return mhKey
}

func getMagicID() (peer.ID, error){
	magicBytes, err := hex.DecodeString(MAGIC)
	if err != nil {
		return "", err
	}
	h, err := multihash.Encode(magicBytes, multihash.SHA2_256)
	if err != nil {
		return "", err
	}
	id, err := peer.IDFromBytes(h)
	if err != nil {
		return "", err
	}
	return id, nil
}<commit_msg>Implement prefix filtering for dht pointers<commit_after>package ipfs

import (
	"sync"
	"crypto/sha256"
	"encoding/hex"
	"strconv"
	"github.com/ipfs/go-ipfs/core"
	"gx/ipfs/QmYgaiNVVL7f2nydijAwpDRunRkmxfu3PoK87Y3pH84uAW/go-libp2p/p2p/host"
	routing "github.com/ipfs/go-ipfs/routing/dht"
	pb "github.com/ipfs/go-ipfs/routing/dht/pb"
	multihash "gx/ipfs/QmYf7ng2hG5XBtJA3tN34DQ2GUN5HNksEw1rLDkmr6vGku/go-multihash"
	ma "gx/ipfs/QmcobAGsCjYt5DXoq9et9L8yR8er7o7Cu3DTvpaq12jYSz/go-multiaddr"
	peer "gx/ipfs/QmZwZjMVGss5rqYsJVGy18gNbkTJffFyq2x1uJ4e4p3ZAt/go-libp2p-peer"
	context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
	ctxio "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-context/io"
	ggio "gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/io"
	key "github.com/ipfs/go-ipfs/blocks/key"
	"encoding/binary"
)

const MAGIC string = "0000000000000000000000000000000000000000000000000000000000000000"

// A pointer is a custom provider inserted into the dht which points to a location of a file.
// For offline messaging purposes we use a hash of the recipient's ID as the key and set the
// provider to the location of the ciphertext. We set the Peer ID of the provider object to
// a magic number so we distinguish it from regular providers and use a longer ttl.
// Note this will only be compatible with the OpenBazaar/go-ipfs fork.
func AddPointer(node *core.IpfsNode, ctx context.Context, mhKey multihash.Multihash, prefixLen int, addr ma.Multiaddr) error {
	keyhash := createKey(mhKey, prefixLen)
	k := key.B58KeyDecode(keyhash.B58String())
	dht := node.Routing.(*routing.IpfsDHT)
	peerHosts := node.PeerHost
	peers, err := dht.GetClosestPeers(ctx, k)
	if err != nil {
		return err
	}
	wg := sync.WaitGroup{}
	for p := range peers {
		wg.Add(1)
		go func(p peer.ID) {
			defer wg.Done()
			err := putPointer(ctx, peerHosts, p, string(k), addr)
			if err != nil {
				log.Debug(err)
			}
		}(p)
	}
	wg.Wait()
	return nil
}

// Fetch pointers from the dht. They will be returned asynchronously.
func FindPointersAsync(dht *routing.IpfsDHT, ctx context.Context, mhKey multihash.Multihash, prefixLen int) <-chan peer.PeerInfo {
	keyhash := createKey(mhKey, prefixLen)
	peerout := dht.FindProvidersAsync(ctx, key.Key(keyhash.B58String()), 100000)
	return peerout
}

func putPointer(ctx context.Context, peerHosts host.Host, p peer.ID, skey string, addr ma.Multiaddr) error{
	magicID, err := getMagicID()
	if err != nil {
		return err
	}
	pi := peer.PeerInfo{
		ID:    magicID,
		Addrs: []ma.Multiaddr{addr},
	}

	pmes := pb.NewMessage(pb.Message_ADD_PROVIDER, skey, 0)
	pmes.ProviderPeers = pb.RawPeerInfosToPBPeers([]peer.PeerInfo{pi})
	err = sendMessage(ctx, peerHosts, p, pmes)
	if err != nil {
		return err
	}

	return nil
}

func sendMessage(ctx context.Context, host host.Host, p peer.ID, pmes *pb.Message) error {
	s, err := host.NewStream(ctx, routing.ProtocolDHT, p)
	if err != nil {
		return err
	}
	defer s.Close()

	cw := ctxio.NewWriter(ctx, s)
	w := ggio.NewDelimitedWriter(cw)

	if err := w.WriteMsg(pmes); err != nil {
		return err
	}
	return nil
}

func createKey(mh multihash.Multihash, prefixLen int) multihash.Multihash {
	// Grab the first 8 bytes from the multihash digest
	m, _ := multihash.Decode(mh)
	prefix64 := binary.BigEndian.Uint64(m.Digest[:8])

	// Convert to binary string
	bin := strconv.FormatUint(prefix64, 2)

	// Pad with leading zeros
	leadingZeros := 64 - len(bin)
	for i := 0; i < leadingZeros; i++ {
		bin = "0" + bin
	}

	// Grab the bits corresponding to the prefix length and convert to int
	intPrefix, _ := strconv.ParseUint(bin[:prefixLen], 2, 64)

	// Convert to 8 byte array
	bs := make([]byte, 8)
	binary.BigEndian.PutUint64(bs, intPrefix)

	// Hash the array
	hash := sha256.New()
	hash.Write(bs)
	md := hash.Sum(nil)

	// Encode as multihash
	keyHash, _ := multihash.Encode(md, multihash.SHA2_256)
	return keyHash
}

func getMagicID() (peer.ID, error){
	magicBytes, err := hex.DecodeString(MAGIC)
	if err != nil {
		return "", err
	}
	h, err := multihash.Encode(magicBytes, multihash.SHA2_256)
	if err != nil {
		return "", err
	}
	id, err := peer.IDFromBytes(h)
	if err != nil {
		return "", err
	}
	return id, nil
}<|endoftext|>


<commit_before>package memory

import (
	"fmt"
	"strconv"
	"testing"

	"github.com/raintank/metrictank/idx"
	"gopkg.in/raintank/schema.v1"
)

var (
	ix      idx.MetricIndex
	queries []query
)

type query struct {
	Pattern         string
	ExpectedResults int
}

func cpuMetrics(dcCount, hostCount, hostOffset, cpuCount int, prefix string) []string {
	series := make([]string, 0)
	for dc := 0; dc < dcCount; dc++ {
		for host := hostOffset; host < hostCount+hostOffset; host++ {
			for cpu := 0; cpu < cpuCount; cpu++ {
				p := prefix + ".dc" + strconv.Itoa(dc) + ".host" + strconv.Itoa(host) + ".cpu." + strconv.Itoa(cpu)
				for _, metric := range []string{"idle", "interrupt", "nice", "softirq", "steal", "system", "user", "wait"} {
					series = append(series, p+"."+metric)
				}
			}
		}
	}
	return series
}

func diskMetrics(dcCount, hostCount, hostOffset, diskCount int, prefix string) []string {
	series := make([]string, 0)
	for dc := 0; dc < dcCount; dc++ {
		for host := hostOffset; host < hostCount+hostOffset; host++ {
			for disk := 0; disk < diskCount; disk++ {
				p := prefix + ".dc" + strconv.Itoa(dc) + ".host" + strconv.Itoa(host) + ".disk.disk" + strconv.Itoa(disk)
				for _, metric := range []string{"disk_merged", "disk_octets", "disk_ops", "disk_time"} {
					series = append(series, p+"."+metric+".read", p+"."+metric+".write")
				}
			}
		}
	}
	return series
}

func Init() {
	ix = New()
	ix.Init()

	var data *schema.MetricData

	for _, series := range cpuMetrics(5, 1000, 0, 32, "collectd") {
		data = &schema.MetricData{
			Name:     series,
			Metric:   series,
			Interval: 10,
			OrgId:    1,
		}
		data.SetId()
		ix.AddOrUpdate(data, 1)
	}
	for _, series := range diskMetrics(5, 1000, 0, 10, "collectd") {
		data = &schema.MetricData{
			Name:     series,
			Metric:   series,
			Interval: 10,
			OrgId:    1,
		}
		data.SetId()
		ix.AddOrUpdate(data, 1)
	}
	// orgId has 1,680,000 series

	for _, series := range cpuMetrics(5, 100, 950, 32, "collectd") {
		data = &schema.MetricData{
			Name:     series,
			Metric:   series,
			Interval: 10,
			OrgId:    2,
		}
		data.SetId()
		ix.AddOrUpdate(data, 1)
	}
	for _, series := range diskMetrics(5, 100, 950, 10, "collectd") {
		data = &schema.MetricData{
			Name:     series,
			Metric:   series,
			Interval: 10,
			OrgId:    2,
		}
		data.SetId()
		ix.AddOrUpdate(data, 1)
	}
	//orgId 2 has 168,000 mertics

	queries = []query{
		//LEAF queries
		{Pattern: "collectd.dc1.host960.disk.disk1.disk_ops.read", ExpectedResults: 1},
		{Pattern: "collectd.dc1.host960.disk.disk1.disk_ops.*", ExpectedResults: 2},
		{Pattern: "collectd.*.host960.disk.disk1.disk_ops.read", ExpectedResults: 5},
		{Pattern: "collectd.*.host960.disk.disk1.disk_ops.*", ExpectedResults: 10},
		{Pattern: "collectd.d*.host960.disk.disk1.disk_ops.*", ExpectedResults: 10},
		{Pattern: "collectd.[abcd]*.host960.disk.disk1.disk_ops.*", ExpectedResults: 10},
		{Pattern: "collectd.{dc1,dc50}.host960.disk.disk1.disk_ops.*", ExpectedResults: 2},

		{Pattern: "collectd.dc3.host960.cpu.1.idle", ExpectedResults: 1},
		{Pattern: "collectd.dc30.host960.cpu.1.idle", ExpectedResults: 0},
		{Pattern: "collectd.dc3.host960.*.*.idle", ExpectedResults: 32},
		{Pattern: "collectd.dc3.host960.*.*.idle", ExpectedResults: 32},

		{Pattern: "collectd.dc3.host96[0-9].cpu.1.idle", ExpectedResults: 10},
		{Pattern: "collectd.dc30.host96[0-9].cpu.1.idle", ExpectedResults: 0},
		{Pattern: "collectd.dc3.host96[0-9].*.*.idle", ExpectedResults: 320},
		{Pattern: "collectd.dc3.host96[0-9].*.*.idle", ExpectedResults: 320},

		{Pattern: "collectd.{dc1,dc2,dc3}.host960.cpu.1.idle", ExpectedResults: 3},
		{Pattern: "collectd.{dc*, a*}.host960.cpu.1.idle", ExpectedResults: 5},

		//Branch queries
		{Pattern: "collectd.dc1.host960.*", ExpectedResults: 2},
		{Pattern: "collectd.*.host960.disk.disk1.*", ExpectedResults: 20},
		{Pattern: "collectd.[abcd]*.host960.disk.disk1.*", ExpectedResults: 20},

		{Pattern: "collectd.*.host960.disk.*.*", ExpectedResults: 200},
		{Pattern: "*.dc3.host960.cpu.1.*", ExpectedResults: 8},
		{Pattern: "*.dc3.host96{1,3}.cpu.1.*", ExpectedResults: 16},
		{Pattern: "*.dc3.{host,server}96{1,3}.cpu.1.*", ExpectedResults: 16},
	}
}

func ixFind(org, q int) {
	nodes, err := ix.Find(org, queries[q].Pattern, 0)
	if err != nil {
		panic(err)
	}
	if len(nodes) != queries[q].ExpectedResults {
		for _, n := range nodes {
			fmt.Println(n.Path)
		}
		panic(fmt.Sprintf("%s expected %d got %d results instead", queries[q].Pattern, queries[q].ExpectedResults, len(nodes)))
	}
}

func BenchmarkFind(b *testing.B) {
	if ix == nil {
		Init()
	}
	queryCount := len(queries)
	org := 1
	b.ReportAllocs()
	b.ResetTimer()
	for n := 0; n < b.N; n++ {
		q := n % queryCount
		org = (n % 2) + 1
		ixFind(org, q)
	}
}

type testQ struct {
	q   int
	org int
}

func BenchmarkConcurrent4Find(b *testing.B) {
	if ix == nil {
		Init()
	}

	queryCount := len(queries)
	if ix == nil {
		Init()
	}
	org := 1

	ch := make(chan testQ)
	for i := 0; i < 4; i++ {
		go func() {
			for q := range ch {
				ixFind(q.org, q.q)
			}
		}()
	}
	b.ReportAllocs()
	b.ResetTimer()
	for n := 0; n < b.N; n++ {
		q := n % queryCount
		org = (n % 2) + 1
		ch <- testQ{q: q, org: org}
	}
	close(ch)
}

func BenchmarkConcurrent8Find(b *testing.B) {
	if ix == nil {
		Init()
	}

	queryCount := len(queries)
	if ix == nil {
		Init()
	}
	org := 1

	ch := make(chan testQ)
	for i := 0; i < 8; i++ {
		go func() {
			for q := range ch {
				ixFind(q.org, q.q)
			}
		}()
	}
	b.ReportAllocs()
	b.ResetTimer()
	for n := 0; n < b.N; n++ {
		q := n % queryCount
		org = (n % 2) + 1
		ch <- testQ{q: q, org: org}
	}
	close(ch)
}
<commit_msg>fix `ineffectual assignment to org`<commit_after>package memory

import (
	"fmt"
	"strconv"
	"testing"

	"github.com/raintank/metrictank/idx"
	"gopkg.in/raintank/schema.v1"
)

var (
	ix      idx.MetricIndex
	queries []query
)

type query struct {
	Pattern         string
	ExpectedResults int
}

func cpuMetrics(dcCount, hostCount, hostOffset, cpuCount int, prefix string) []string {
	series := make([]string, 0)
	for dc := 0; dc < dcCount; dc++ {
		for host := hostOffset; host < hostCount+hostOffset; host++ {
			for cpu := 0; cpu < cpuCount; cpu++ {
				p := prefix + ".dc" + strconv.Itoa(dc) + ".host" + strconv.Itoa(host) + ".cpu." + strconv.Itoa(cpu)
				for _, metric := range []string{"idle", "interrupt", "nice", "softirq", "steal", "system", "user", "wait"} {
					series = append(series, p+"."+metric)
				}
			}
		}
	}
	return series
}

func diskMetrics(dcCount, hostCount, hostOffset, diskCount int, prefix string) []string {
	series := make([]string, 0)
	for dc := 0; dc < dcCount; dc++ {
		for host := hostOffset; host < hostCount+hostOffset; host++ {
			for disk := 0; disk < diskCount; disk++ {
				p := prefix + ".dc" + strconv.Itoa(dc) + ".host" + strconv.Itoa(host) + ".disk.disk" + strconv.Itoa(disk)
				for _, metric := range []string{"disk_merged", "disk_octets", "disk_ops", "disk_time"} {
					series = append(series, p+"."+metric+".read", p+"."+metric+".write")
				}
			}
		}
	}
	return series
}

func Init() {
	ix = New()
	ix.Init()

	var data *schema.MetricData

	for _, series := range cpuMetrics(5, 1000, 0, 32, "collectd") {
		data = &schema.MetricData{
			Name:     series,
			Metric:   series,
			Interval: 10,
			OrgId:    1,
		}
		data.SetId()
		ix.AddOrUpdate(data, 1)
	}
	for _, series := range diskMetrics(5, 1000, 0, 10, "collectd") {
		data = &schema.MetricData{
			Name:     series,
			Metric:   series,
			Interval: 10,
			OrgId:    1,
		}
		data.SetId()
		ix.AddOrUpdate(data, 1)
	}
	// orgId has 1,680,000 series

	for _, series := range cpuMetrics(5, 100, 950, 32, "collectd") {
		data = &schema.MetricData{
			Name:     series,
			Metric:   series,
			Interval: 10,
			OrgId:    2,
		}
		data.SetId()
		ix.AddOrUpdate(data, 1)
	}
	for _, series := range diskMetrics(5, 100, 950, 10, "collectd") {
		data = &schema.MetricData{
			Name:     series,
			Metric:   series,
			Interval: 10,
			OrgId:    2,
		}
		data.SetId()
		ix.AddOrUpdate(data, 1)
	}
	//orgId 2 has 168,000 mertics

	queries = []query{
		//LEAF queries
		{Pattern: "collectd.dc1.host960.disk.disk1.disk_ops.read", ExpectedResults: 1},
		{Pattern: "collectd.dc1.host960.disk.disk1.disk_ops.*", ExpectedResults: 2},
		{Pattern: "collectd.*.host960.disk.disk1.disk_ops.read", ExpectedResults: 5},
		{Pattern: "collectd.*.host960.disk.disk1.disk_ops.*", ExpectedResults: 10},
		{Pattern: "collectd.d*.host960.disk.disk1.disk_ops.*", ExpectedResults: 10},
		{Pattern: "collectd.[abcd]*.host960.disk.disk1.disk_ops.*", ExpectedResults: 10},
		{Pattern: "collectd.{dc1,dc50}.host960.disk.disk1.disk_ops.*", ExpectedResults: 2},

		{Pattern: "collectd.dc3.host960.cpu.1.idle", ExpectedResults: 1},
		{Pattern: "collectd.dc30.host960.cpu.1.idle", ExpectedResults: 0},
		{Pattern: "collectd.dc3.host960.*.*.idle", ExpectedResults: 32},
		{Pattern: "collectd.dc3.host960.*.*.idle", ExpectedResults: 32},

		{Pattern: "collectd.dc3.host96[0-9].cpu.1.idle", ExpectedResults: 10},
		{Pattern: "collectd.dc30.host96[0-9].cpu.1.idle", ExpectedResults: 0},
		{Pattern: "collectd.dc3.host96[0-9].*.*.idle", ExpectedResults: 320},
		{Pattern: "collectd.dc3.host96[0-9].*.*.idle", ExpectedResults: 320},

		{Pattern: "collectd.{dc1,dc2,dc3}.host960.cpu.1.idle", ExpectedResults: 3},
		{Pattern: "collectd.{dc*, a*}.host960.cpu.1.idle", ExpectedResults: 5},

		//Branch queries
		{Pattern: "collectd.dc1.host960.*", ExpectedResults: 2},
		{Pattern: "collectd.*.host960.disk.disk1.*", ExpectedResults: 20},
		{Pattern: "collectd.[abcd]*.host960.disk.disk1.*", ExpectedResults: 20},

		{Pattern: "collectd.*.host960.disk.*.*", ExpectedResults: 200},
		{Pattern: "*.dc3.host960.cpu.1.*", ExpectedResults: 8},
		{Pattern: "*.dc3.host96{1,3}.cpu.1.*", ExpectedResults: 16},
		{Pattern: "*.dc3.{host,server}96{1,3}.cpu.1.*", ExpectedResults: 16},
	}
}

func ixFind(org, q int) {
	nodes, err := ix.Find(org, queries[q].Pattern, 0)
	if err != nil {
		panic(err)
	}
	if len(nodes) != queries[q].ExpectedResults {
		for _, n := range nodes {
			fmt.Println(n.Path)
		}
		panic(fmt.Sprintf("%s expected %d got %d results instead", queries[q].Pattern, queries[q].ExpectedResults, len(nodes)))
	}
}

func BenchmarkFind(b *testing.B) {
	if ix == nil {
		Init()
	}
	queryCount := len(queries)
	b.ReportAllocs()
	b.ResetTimer()
	for n := 0; n < b.N; n++ {
		q := n % queryCount
		org := (n % 2) + 1
		ixFind(org, q)
	}
}

type testQ struct {
	q   int
	org int
}

func BenchmarkConcurrent4Find(b *testing.B) {
	if ix == nil {
		Init()
	}

	queryCount := len(queries)
	if ix == nil {
		Init()
	}

	ch := make(chan testQ)
	for i := 0; i < 4; i++ {
		go func() {
			for q := range ch {
				ixFind(q.org, q.q)
			}
		}()
	}
	b.ReportAllocs()
	b.ResetTimer()
	for n := 0; n < b.N; n++ {
		q := n % queryCount
		org := (n % 2) + 1
		ch <- testQ{q: q, org: org}
	}
	close(ch)
}

func BenchmarkConcurrent8Find(b *testing.B) {
	if ix == nil {
		Init()
	}

	queryCount := len(queries)
	if ix == nil {
		Init()
	}

	ch := make(chan testQ)
	for i := 0; i < 8; i++ {
		go func() {
			for q := range ch {
				ixFind(q.org, q.q)
			}
		}()
	}
	b.ReportAllocs()
	b.ResetTimer()
	for n := 0; n < b.N; n++ {
		q := n % queryCount
		org := (n % 2) + 1
		ch <- testQ{q: q, org: org}
	}
	close(ch)
}
<|endoftext|>


<commit_before>// Create Json Streams in Go.
// Chanson makes easy to fetch data from a channel and encode it.
// It is not an encoder it self, by default it relies on json.Encoder but its flexible enough to let you use whatever you want.
package chanson

import (
	"encoding/json"
	"io"
)

type Chanson struct {
	w io.Writer
}

// New returns a new json stream.
// The stream will use w for write the output
func New(w io.Writer) Chanson {
	cs := Chanson{w: w}
	return cs
}

// Object will execute the callback inside an object context
// this is: "{" f() "}"
func (cs *Chanson) Object(f func(obj Object)) {
	cs.w.Write([]byte("{"))
	if f != nil {
		f(Object{cs: cs, empty: true})
	}
	cs.w.Write([]byte("}"))
}

// Object will execute the callback inside an array context
// this is: "[" f() "]"
func (cs *Chanson) Array(f func(a Array)) {
	cs.w.Write([]byte("["))
	if f != nil {
		f(Array{cs: cs, empty: true})
	}
	cs.w.Write([]byte("]"))
}

type Object struct {
	cs    *Chanson
	empty bool
}

// Sets an element into the object
func (obj *Object) Set(key string, val interface{}) {
	if !obj.empty {
		obj.cs.w.Write([]byte(","))
	} else {
		obj.empty = false
	}

	obj.cs.w.Write([]byte(`"` + key + `":`))
	handleValue(obj.cs, val)
}

type Array struct {
	cs    *Chanson
	empty bool
}

// Pushes an item into the array
func (a *Array) Push(val interface{}) {
	if !a.empty {
		a.cs.w.Write([]byte(","))
	} else {
		a.empty = false
	}

	handleValue(a.cs, val)
}

func handleValue(cs *Chanson, val interface{}) {
	switch t := val.(type) {
	case func(io.Writer):
		t(cs.w)
	case func(*json.Encoder):
		t(json.NewEncoder(cs.w))
	case func(*Chanson):
		t(cs)
	default:
		json.NewEncoder(cs.w).Encode(val)
	}
}<commit_msg>Add a custom type for values<commit_after>// Create Json Streams in Go.
// Chanson makes easy to fetch data from a channel and encode it.
// It is not an encoder it self, by default it relies on json.Encoder but its flexible enough to let you use whatever you want.
package chanson

import (
	"encoding/json"
	"io"
)

type Chanson struct {
	w io.Writer
}

// Value is the types that functions like Array.Push() or Object.Set() can accepts as values.
// Custom Value types are:
//	- func(io.Writer)
//	- func(*json.Encoder)
//	- func(*Chanson)
// If Value is none of the above, it will be encoded using json.Encoder
type Value interface{}

// New returns a new json stream.
// The stream will use w for write the output
func New(w io.Writer) Chanson {
	cs := Chanson{w: w}
	return cs
}

// Object will execute the callback inside an object context
// this is: "{" f() "}"
func (cs *Chanson) Object(f func(obj Object)) {
	cs.w.Write([]byte("{"))
	if f != nil {
		f(Object{cs: cs, empty: true})
	}
	cs.w.Write([]byte("}"))
}

// Object will execute the callback inside an array context
// this is: "[" f() "]"
func (cs *Chanson) Array(f func(a Array)) {
	cs.w.Write([]byte("["))
	if f != nil {
		f(Array{cs: cs, empty: true})
	}
	cs.w.Write([]byte("]"))
}

type Object struct {
	cs    *Chanson
	empty bool
}

// Sets an element into the object
func (obj *Object) Set(key string, val Value) {
	if !obj.empty {
		obj.cs.w.Write([]byte(","))
	} else {
		obj.empty = false
	}

	obj.cs.w.Write([]byte(`"` + key + `":`))
	handleValue(obj.cs, val)
}

type Array struct {
	cs    *Chanson
	empty bool
}

// Pushes an item into the array
func (a *Array) Push(val Value) {
	if !a.empty {
		a.cs.w.Write([]byte(","))
	} else {
		a.empty = false
	}

	handleValue(a.cs, val)
}

func handleValue(cs *Chanson, val Value) {
	switch t := val.(type) {
	case func(io.Writer):
		t(cs.w)
	case func(*json.Encoder):
		t(json.NewEncoder(cs.w))
	case func(*Chanson):
		t(cs)
	default:
		json.NewEncoder(cs.w).Encode(val)
	}
}
<|endoftext|>


<commit_before>package service

import (
	"log"
	"os"
	"strings"

	"github.com/coreos/go-etcd/etcd"
)

var (
	logger          *log.Logger
	clientSingleton *etcd.Client
	hostname        string
)

func Client() *etcd.Client {
	if clientSingleton == nil {
		host := "http://localhost:4001"
		if len(os.Getenv("ETCD_HOST")) != 0 {
			host = os.Getenv("ETCD_HOST")
		}

		cacert := os.Getenv("ETCD_CACERT")
		tlskey := os.Getenv("ETCD_TLS_KEY")
		tlscert := os.Getenv("ETCD_TLS_CERT")
		if len(cacert) != 0 && len(tlskey) != 0 && len(tlscert) != 0 {
			if !strings.Contains(host, "https://") {
				host = strings.Replace(host, "http", "https", 1)
			}
			c, err := etcd.NewTLSClient([]string{host}, tlscert, tlskey, cacert)
			if err != nil {
				panic(err)
			}
			clientSingleton = c
		} else {
			clientSingleton = etcd.NewClient([]string{host})
		}
	}
	return clientSingleton
}

func init() {
	if len(os.Getenv("HOSTNAME")) != 0 {
		hostname = os.Getenv("HOSTNAME")
	} else {
		h, err := os.Hostname()
		if err != nil {
			panic(err)
		}
		hostname = h
	}

	logger = log.New(os.Stderr, "[etcd-discovery]", log.LstdFlags)
}
<commit_msg>Fix little data race on client initialization<commit_after>package service

import (
	"log"
	"os"
	"strings"
	"sync"

	"github.com/coreos/go-etcd/etcd"
)

var (
	logger           *log.Logger
	clientSingleton  *etcd.Client
	clientSingletonO = &sync.Once{}
	hostname         string
)

func Client() *etcd.Client {
	clientSingletonO.Do(func() {
		host := "http://localhost:4001"
		if len(os.Getenv("ETCD_HOST")) != 0 {
			host = os.Getenv("ETCD_HOST")
		}

		cacert := os.Getenv("ETCD_CACERT")
		tlskey := os.Getenv("ETCD_TLS_KEY")
		tlscert := os.Getenv("ETCD_TLS_CERT")
		if len(cacert) != 0 && len(tlskey) != 0 && len(tlscert) != 0 {
			if !strings.Contains(host, "https://") {
				host = strings.Replace(host, "http", "https", 1)
			}
			c, err := etcd.NewTLSClient([]string{host}, tlscert, tlskey, cacert)
			if err != nil {
				panic(err)
			}
			clientSingleton = c
		} else {
			clientSingleton = etcd.NewClient([]string{host})
		}
	})
	return clientSingleton
}

func init() {
	if len(os.Getenv("HOSTNAME")) != 0 {
		hostname = os.Getenv("HOSTNAME")
	} else {
		h, err := os.Hostname()
		if err != nil {
			panic(err)
		}
		hostname = h
	}

	logger = log.New(os.Stderr, "[etcd-discovery]", log.LstdFlags)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/binary"
	"fmt"
)

type Class struct {
	magic             uint32
	minorVersion      uint16
	majorVersion      uint16
	constantPoolCount uint16
	constantPoolItems []interface{}
}

type NameAndType struct {
	NameIndex       uint16
	DescriptorIndex uint16
}

func (m NameAndType) String() string {
	return fmt.Sprintf("NameAndType: %v, %v", m.NameIndex, m.DescriptorIndex)
}

type UTF8String struct {
	Length uint16
	Bytes  []uint8
}

func (m UTF8String) String() string {
	return fmt.Sprintf("UTF8: %v", string(m.Bytes))
}

type ClassInfo struct {
	NameIndex uint16
}

func (m ClassInfo) String() string {
	return fmt.Sprintf("Class: %v", m.NameIndex)
}

type MethodRef struct {
	ClassIndex       uint16
	NameAndTypeIndex uint16
}

func (m MethodRef) String() string {
	return fmt.Sprintf("Method: %v, %v", m.ClassIndex, m.NameAndTypeIndex)
}

type FieldRef struct {
	ClassIndex       uint16
	NameAndTypeIndex uint16
}

func (m FieldRef) String() string {
	return fmt.Sprintf("Field: %v, %v", m.ClassIndex, m.NameAndTypeIndex)
}

type StringConstant struct {
	UTF8Index uint16
}

func (m StringConstant) String() string {
	return fmt.Sprintf("String: %v", m.UTF8Index)
}

type ParseError struct {
	reason string
}

func (e ParseError) Error() string {
	return e.reason
}

func parseMethodRef(buf *bytes.Reader) (m MethodRef, err error) {
	err = binary.Read(buf, binary.BigEndian, &m)
	return
}

func parseFieldRef(buf *bytes.Reader) (m FieldRef, err error) {
	err = binary.Read(buf, binary.BigEndian, &m)
	return
}

func parseStringConstant(buf *bytes.Reader) (s StringConstant, err error) {
	err = binary.Read(buf, binary.BigEndian, &s)
	return
}

func parseClassInfo(buf *bytes.Reader) (c ClassInfo, err error) {
	err = binary.Read(buf, binary.BigEndian, &c)
	return
}

func parseNameAndType(buf *bytes.Reader) (c NameAndType, err error) {
	err = binary.Read(buf, binary.BigEndian, &c)
	return
}

func parseUTF8String(buf *bytes.Reader) (c UTF8String, err error) {
	err = binary.Read(buf, binary.BigEndian, &c.Length)
	if err != nil {
		return
	}
	c.Bytes = make([]byte, c.Length)
	var i uint16
	for i = 0; i < c.Length; i++ {
		c.Bytes[i], err = buf.ReadByte()
		if err != nil {
			return
		}
	}
	return
}

func parseConstantPoolItem(buf *bytes.Reader) (interface{}, error) {
	tag, err := buf.ReadByte()
	if err != nil {
		return nil, err
	}
	if tag == 10 {
		return parseMethodRef(buf)
	} else if tag == 9 {
		return parseFieldRef(buf)
	} else if tag == 8 {
		return parseStringConstant(buf)
	} else if tag == 7 {
		return parseClassInfo(buf)
	} else if tag == 1 {
		return parseUTF8String(buf)
	} else if tag == 12 {
		return parseNameAndType(buf)
	}
	return tag, nil
}

func parse(b []byte) (c Class, err error) {
	buf := bytes.NewReader(b)
	err = binary.Read(buf, binary.BigEndian, &c.magic)
	if err != nil {
		return
	}
	err = binary.Read(buf, binary.BigEndian, &c.minorVersion)
	if err != nil {
		return
	}
	err = binary.Read(buf, binary.BigEndian, &c.majorVersion)
	if err != nil {
		return
	}
	err = binary.Read(buf, binary.BigEndian, &c.constantPoolCount)
	if err != nil {
		return
	}
	c.constantPoolItems = make([]interface{}, c.constantPoolCount)
	var i uint16
	for i = 0; i < c.constantPoolCount; i++ {
		c.constantPoolItems[i], err = parseConstantPoolItem(buf)
		if err != nil {
			return
		}
	}
	return
}
<commit_msg>Change UTF8String to be a simple wrapper around a plain go string<commit_after>package main

import (
	"bytes"
	"encoding/binary"
	"fmt"
)

type Class struct {
	magic             uint32
	minorVersion      uint16
	majorVersion      uint16
	constantPoolCount uint16
	constantPoolItems []interface{}
}

type NameAndType struct {
	NameIndex       uint16
	DescriptorIndex uint16
}

func (m NameAndType) String() string {
	return fmt.Sprintf("NameAndType: %v, %v", m.NameIndex, m.DescriptorIndex)
}

type UTF8String struct {
	Contents string
}

func (m UTF8String) String() string {
	return fmt.Sprintf("UTF8: %v", m.Contents)
}

type ClassInfo struct {
	NameIndex uint16
}

func (m ClassInfo) String() string {
	return fmt.Sprintf("Class: %v", m.NameIndex)
}

type MethodRef struct {
	ClassIndex       uint16
	NameAndTypeIndex uint16
}

func (m MethodRef) String() string {
	return fmt.Sprintf("Method: %v, %v", m.ClassIndex, m.NameAndTypeIndex)
}

type FieldRef struct {
	ClassIndex       uint16
	NameAndTypeIndex uint16
}

func (m FieldRef) String() string {
	return fmt.Sprintf("Field: %v, %v", m.ClassIndex, m.NameAndTypeIndex)
}

type StringConstant struct {
	UTF8Index uint16
}

func (m StringConstant) String() string {
	return fmt.Sprintf("String: %v", m.UTF8Index)
}

type ParseError struct {
	reason string
}

func (e ParseError) Error() string {
	return e.reason
}

func parseMethodRef(buf *bytes.Reader) (m MethodRef, err error) {
	err = binary.Read(buf, binary.BigEndian, &m)
	return
}

func parseFieldRef(buf *bytes.Reader) (m FieldRef, err error) {
	err = binary.Read(buf, binary.BigEndian, &m)
	return
}

func parseStringConstant(buf *bytes.Reader) (s StringConstant, err error) {
	err = binary.Read(buf, binary.BigEndian, &s)
	return
}

func parseClassInfo(buf *bytes.Reader) (c ClassInfo, err error) {
	err = binary.Read(buf, binary.BigEndian, &c)
	return
}

func parseNameAndType(buf *bytes.Reader) (c NameAndType, err error) {
	err = binary.Read(buf, binary.BigEndian, &c)
	return
}

func parseUTF8String(buf *bytes.Reader) (c UTF8String, err error) {
	var length uint16
	err = binary.Read(buf, binary.BigEndian, &length)
	if err != nil {
		return
	}
	bytes := make([]byte, length)
	var i uint16
	for i = 0; i < length; i++ {
		bytes[i], err = buf.ReadByte()
		if err != nil {
			return
		}
	}
	c.Contents = string(bytes)
	return
}

func parseConstantPoolItem(buf *bytes.Reader) (interface{}, error) {
	tag, err := buf.ReadByte()
	if err != nil {
		return nil, err
	}
	if tag == 10 {
		return parseMethodRef(buf)
	} else if tag == 9 {
		return parseFieldRef(buf)
	} else if tag == 8 {
		return parseStringConstant(buf)
	} else if tag == 7 {
		return parseClassInfo(buf)
	} else if tag == 1 {
		return parseUTF8String(buf)
	} else if tag == 12 {
		return parseNameAndType(buf)
	}
	return tag, nil
}

func parse(b []byte) (c Class, err error) {
	buf := bytes.NewReader(b)
	err = binary.Read(buf, binary.BigEndian, &c.magic)
	if err != nil {
		return
	}
	err = binary.Read(buf, binary.BigEndian, &c.minorVersion)
	if err != nil {
		return
	}
	err = binary.Read(buf, binary.BigEndian, &c.majorVersion)
	if err != nil {
		return
	}
	err = binary.Read(buf, binary.BigEndian, &c.constantPoolCount)
	if err != nil {
		return
	}
	c.constantPoolItems = make([]interface{}, c.constantPoolCount)
	var i uint16
	for i = 0; i < c.constantPoolCount; i++ {
		c.constantPoolItems[i], err = parseConstantPoolItem(buf)
		if err != nil {
			return
		}
	}
	return
}
<|endoftext|>


<commit_before>/* Copyright (c) 2014-2015, Daniel Martí <mvdan@mvdan.cc> */
/* See LICENSE for licensing information */

package jutgelint

import (
	"bufio"
	"io"
	"os/exec"
	"regexp"
	"strconv"
)

var (
	checkOpts = []string{"/home/mvdan/output.json", "--dead-assign", "--fors", "--local-decl", "--variable-init"}

	lineRegex = regexp.MustCompile(`LINE: ([0-9]+)`)
	funcRegex = regexp.MustCompile(`FUNCTION: (.+)`)
	errDescRegex = regexp.MustCompile(`ERROR: ([^-]+) - (.+)`)
)

type Result struct {
	Line  int
	Func  string
	Short string
	Long  string
}

func RunChecker(i io.Reader) ([]Result, error) {
	//cmd := exec.Command("printer")
	cmd := exec.Command("check", checkOpts...)
	//stdin, err := cmd.StdinPipe()
	//if err != nil {
	//return nil, err
	//}
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return nil, err
	}
	if err := cmd.Start(); err != nil {
		return nil, err
	}
	//io.Copy(stdin, i)
	//stdin.Close()
	scanner := bufio.NewScanner(stdout)
	var results []Result
	var cur *Result
	for scanner.Scan() {
		line := scanner.Text()
		if s := lineRegex.FindStringSubmatch(line); s != nil {
			if cur != nil {
				results = append(results, *cur)
			}
			cur = &Result{}
			i, err := strconv.Atoi(s[1])
			if err != nil {
				return nil, err
			}
			cur.Line = i
		} else if s := funcRegex.FindStringSubmatch(line); s != nil {
			cur.Func = s[1]
		} else if s := errDescRegex.FindStringSubmatch(line); s != nil {
			cur.Short = s[1]
			cur.Long = s[2]
		}

	}
	return results, nil
}
<commit_msg>Clean up checker vars a bit<commit_after>/* Copyright (c) 2014-2015, Daniel Martí <mvdan@mvdan.cc> */
/* See LICENSE for licensing information */

package jutgelint

import (
	"bufio"
	"io"
	"os/exec"
	"regexp"
	"strconv"
)

var (
	checkOpts = []string{
		"/home/mvdan/output.json",
		"--dead-assign",
		"--fors",
		"--local-decl",
		"--variable-init",
	}

	lineRegex    = regexp.MustCompile(`LINE: ([0-9]+)`)
	funcRegex    = regexp.MustCompile(`FUNCTION: (.+)`)
	errDescRegex = regexp.MustCompile(`ERROR: ([^-]+) - (.+)`)
)

type Result struct {
	Line  int
	Func  string
	Short string
	Long  string
}

func RunChecker(i io.Reader) ([]Result, error) {
	//cmd := exec.Command("printer")
	cmd := exec.Command("check", checkOpts...)
	//stdin, err := cmd.StdinPipe()
	//if err != nil {
		//return nil, err
	//}
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return nil, err
	}
	if err := cmd.Start(); err != nil {
		return nil, err
	}
	//io.Copy(stdin, i)
	//stdin.Close()
	scanner := bufio.NewScanner(stdout)
	var results []Result
	var cur *Result
	for scanner.Scan() {
		line := scanner.Text()
		if s := lineRegex.FindStringSubmatch(line); s != nil {
			if cur != nil {
				results = append(results, *cur)
			}
			cur = &Result{}
			i, err := strconv.Atoi(s[1])
			if err != nil {
				return nil, err
			}
			cur.Line = i
		} else if s := funcRegex.FindStringSubmatch(line); s != nil {
			cur.Func = s[1]
		} else if s := errDescRegex.FindStringSubmatch(line); s != nil {
			cur.Short = s[1]
			cur.Long = s[2]
		}

	}
	return results, nil
}
<|endoftext|>


<commit_before>package somatree

import (
	"crypto/sha512"
	"encoding/base64"
	"io"
	"sort"

	"github.com/satori/go.uuid"
)

type Checker interface {
	SetCheck(c Check)

	inheritCheck(c Check)
	inheritCheckDeep(c Check)
	storeCheck(c Check)
	syncCheck(childId string)
	checkCheck(checkId string) bool
}

type CheckGetter interface {
	GetCheckId() string
	GetSourceCheckId() string
	GetCheckConfigId() string
	GetSourceType() string
	GetIsInherited() bool
	GetInheritedFrom() string
	GetInheritance() bool
	GetChildrenOnly() bool
	GetView() string
	GetCapabilityId() string
	GetInterval() uint64
	GetItemId(objType string, objId uuid.UUID) uuid.UUID
}

type Check struct {
	Id            uuid.UUID
	SourceId      uuid.UUID
	SourceType    string
	Inherited     bool
	InheritedFrom uuid.UUID
	CapabilityId  uuid.UUID
	ConfigId      uuid.UUID
	Inheritance   bool
	ChildrenOnly  bool
	View          string
	Interval      uint64
	Thresholds    []CheckThreshold
	Constraints   []CheckConstraint
	Items         []CheckItem
}

type CheckItem struct {
	ObjectId   uuid.UUID
	ObjectType string
	ItemId     uuid.UUID
}

type CheckThreshold struct {
	Predicate string
	Level     uint8
	Value     int64
}

type CheckConstraint struct {
	Type  string
	Key   string
	Value string
}

type CheckInstance struct {
	InstanceId            uuid.UUID
	CheckId               uuid.UUID
	ConfigId              uuid.UUID
	Version               uint32
	ConstraintHash        string
	ConstraintValHash     string
	ConstraintOncall      string                         // Ids
	ConstraintService     map[string]string              // Id->value
	ConstraintSystem      map[string]string              // Id->value
	ConstraintCustom      map[string]string              // Id->value
	ConstraintNative      map[string]string              // prop->value
	ConstraintAttribute   map[string]map[string][]string // svcId->attr->[ value, value, ... ]
	InstanceServiceConfig map[string]string              // attr->value
	InstanceService       uuid.UUID
	InstanceSvcCfgHash    string
}

func (c *Check) GetItemId(objType string, objId uuid.UUID) uuid.UUID {
	if !uuid.Equal(c.Id, uuid.Nil) {
		return c.Id
	}
	for _, item := range c.Items {
		if objType == item.ObjectType && uuid.Equal(item.ObjectId, objId) {
			return item.ItemId
		}
	}
	return uuid.Nil
}

func (c *Check) GetCheckId() string {
	return c.Id.String()
}

func (c *Check) GetSourceCheckId() string {
	return c.SourceId.String()
}

func (c *Check) GetCheckConfigId() string {
	return c.ConfigId.String()
}

func (c *Check) GetSourceType() string {
	return c.SourceType
}

func (c *Check) GetIsInherited() bool {
	return c.Inherited
}

func (c *Check) GetInheritedFrom() string {
	return c.InheritedFrom.String()
}

func (c *Check) GetInheritance() bool {
	return c.Inheritance
}

func (c *Check) GetChildrenOnly() bool {
	return c.ChildrenOnly
}

func (c *Check) GetView() string {
	return c.View
}

func (c *Check) GetCapabilityId() string {
	return c.CapabilityId.String()
}

func (c *Check) GetInterval() uint64 {
	return c.Interval
}

func (c *Check) MakeAction() Action {
	return Action{
		Check: somaproto.TreeCheck{
			CheckId:       c.GetCheckId(),
			SourceCheckId: c.GetSourceCheckId(),
			CheckConfigId: c.GetCheckConfigId(),
			SourceType:    c.GetSourceType(),
			IsInherited:   c.GetIsInherited(),
			InheritedFrom: c.GetInheritedFrom(),
			Inheritance:   c.GetInheritance(),
			ChildrenOnly:  c.GetChildrenOnly(),
			CapabilityId:  c.GetCapabilityId(),
		},
	}
}

func (tci *CheckInstance) Clone() CheckInstance {
	cl := CheckInstance{
		Version:            tci.Version,
		ConstraintHash:     tci.ConstraintHash,
		ConstraintValHash:  tci.ConstraintValHash,
		ConstraintOncall:   tci.ConstraintOncall,
		InstanceSvcCfgHash: tci.InstanceSvcCfgHash,
	}
	cl.InstanceId, _ = uuid.FromString(tci.InstanceId.String())
	cl.CheckId, _ = uuid.FromString(tci.CheckId.String())
	cl.ConfigId, _ = uuid.FromString(tci.ConfigId.String())
	cl.InstanceService, _ = uuid.FromString(tci.InstanceService.String())
	for k, v := range tci.ConstraintService {
		t := v
		cl.ConstraintService[k] = t
	}
	for k, v := range tci.ConstraintSystem {
		t := v
		cl.ConstraintSystem[k] = t
	}
	for k, v := range tci.ConstraintCustom {
		t := v
		cl.ConstraintCustom[k] = t
	}
	for k, v := range tci.ConstraintNative {
		t := v
		cl.ConstraintNative[k] = t
	}
	for k, v := range tci.InstanceServiceConfig {
		t := v
		cl.InstanceServiceConfig[k] = t
	}
	cl.ConstraintAttribute = make(map[string]map[string][]string, 0)
	for k, _ := range tci.ConstraintAttribute {
		for k2, aVal := range tci.ConstraintAttribute[k] {
			for _, val := range aVal {
				t := val
				cl.ConstraintAttribute[k][k2] = append(cl.ConstraintAttribute[k][k2], t)
			}
		}
	}

	return cl
}

func (tci *CheckInstance) calcConstraintHash() {
	h := sha512.New()
	io.WriteString(h, tci.ConstraintOncall)

	services := []string{}
	for i, _ := range tci.ConstraintService {
		j := i
		services = append(services, j)
	}
	sort.Strings(services)
	for _, i := range services {
		io.WriteString(h, i)
	}

	systems := []string{}
	for i, _ := range tci.ConstraintSystem {
		j := i
		systems = append(systems, j)
	}
	sort.Strings(systems)
	for _, i := range systems {
		io.WriteString(h, i)
	}

	customs := []string{}
	for i, _ := range tci.ConstraintCustom {
		j := i
		customs = append(customs, j)
	}
	sort.Strings(customs)
	for _, i := range customs {
		io.WriteString(h, i)
	}

	natives := []string{}
	for i, _ := range tci.ConstraintNative {
		j := i
		natives = append(natives, j)
	}
	sort.Strings(natives)
	for _, i := range natives {
		io.WriteString(h, i)
	}

	attributes := []string{}
	for i, _ := range tci.ConstraintAttribute {
		j := i
		attributes = append(attributes, j)
	}
	sort.Strings(attributes)
	for _, i := range attributes {
		svcattr := []string{}
		for j, _ := range tci.ConstraintAttribute[i] {
			k := j
			svcattr = append(svcattr, k)
		}
		sort.Strings(svcattr)
		io.WriteString(h, i)
		for _, l := range svcattr {
			io.WriteString(h, l)
		}
	}
	tci.ConstraintHash = base64.URLEncoding.EncodeToString(h.Sum(nil))
}

func (tci *CheckInstance) calcConstraintValHash() {
	h := sha512.New()
	io.WriteString(h, tci.ConstraintOncall)

	services := []string{}
	for i, _ := range tci.ConstraintService {
		j := i
		services = append(services, j)
	}
	sort.Strings(services)
	for _, i := range services {
		io.WriteString(h, i)
		io.WriteString(h, tci.ConstraintService[i])
	}

	systems := []string{}
	for i, _ := range tci.ConstraintSystem {
		j := i
		systems = append(systems, j)
	}
	sort.Strings(systems)
	for _, i := range systems {
		io.WriteString(h, i)
		io.WriteString(h, tci.ConstraintSystem[i])
	}

	customs := []string{}
	for i, _ := range tci.ConstraintCustom {
		j := i
		customs = append(customs, j)
	}
	sort.Strings(customs)
	for _, i := range customs {
		io.WriteString(h, i)
		io.WriteString(h, tci.ConstraintCustom[i])
	}

	natives := []string{}
	for i, _ := range tci.ConstraintNative {
		j := i
		natives = append(natives, j)
	}
	sort.Strings(natives)
	for _, i := range natives {
		io.WriteString(h, i)
		io.WriteString(h, tci.ConstraintNative[i])
	}

	attributes := []string{}
	for i, _ := range tci.ConstraintAttribute {
		j := i
		attributes = append(attributes, j)
	}
	sort.Strings(attributes)
	for _, i := range attributes {
		svcattr := []string{}
		for j, _ := range tci.ConstraintAttribute[i] {
			k := j
			svcattr = append(svcattr, k)
		}
		sort.Strings(svcattr)
		io.WriteString(h, i)
		for _, l := range svcattr {
			io.WriteString(h, l)
			vals := make([]string, len(tci.ConstraintAttribute[i][l]))
			copy(vals, tci.ConstraintAttribute[i][l])
			sort.Strings(vals)
			for _, m := range vals {
				io.WriteString(h, m)
			}
		}
	}
	tci.ConstraintValHash = base64.URLEncoding.EncodeToString(h.Sum(nil))
}

func (tci *CheckInstance) calcInstanceSvcCfgHash() {
	h := sha512.New()

	attributes := []string{}
	for i, _ := range tci.InstanceServiceConfig {
		j := i
		attributes = append(attributes, j)
	}
	sort.Strings(attributes)
	for _, i := range attributes {
		io.WriteString(h, i)
		io.WriteString(h, tci.InstanceServiceConfig[i])
	}
	tci.InstanceSvcCfgHash = base64.URLEncoding.EncodeToString(h.Sum(nil))
}

func (c *Check) clone() Check {
	cl := Check{
		SourceType:   c.SourceType,
		Inherited:    c.Inherited,
		Inheritance:  c.Inheritance,
		ChildrenOnly: c.ChildrenOnly,
		View:         c.View,
		Interval:     c.Interval,
	}
	cl.Id, _ = uuid.FromString(c.Id.String())
	cl.SourceId, _ = uuid.FromString(c.SourceId.String())
	cl.InheritedFrom, _ = uuid.FromString(c.InheritedFrom.String())
	cl.CapabilityId, _ = uuid.FromString(c.CapabilityId.String())
	cl.ConfigId, _ = uuid.FromString(c.ConfigId.String())
	cl.Thresholds = make([]CheckThreshold, len(c.Thresholds))
	for i, thr := range c.Thresholds {
		n := CheckThreshold{
			Predicate: thr.Predicate,
			Level:     thr.Level,
			Value:     thr.Value,
		}
		cl.Thresholds[i] = n
	}
	cl.Constraints = make([]CheckConstraint, len(c.Constraints))
	for i, ctr := range c.Constraints {
		n := CheckConstraint{
			Type:  ctr.Type,
			Key:   ctr.Key,
			Value: ctr.Value,
		}
		cl.Constraints[i] = n
	}
	cl.Items = make([]CheckItem, len(c.Items))
	for i, item := range c.Items {
		n := CheckItem{
			ObjectType: item.ObjectType,
		}
		n.ItemId, _ = uuid.FromString(item.ItemId.String())
		n.ObjectId, _ = uuid.FromString(item.ObjectId.String())
		cl.Items[i] = n
	}
	return cl
}

// vim: ts=4 sw=4 sts=4 noet fenc=utf-8 ffs=unix
<commit_msg>Update CheckInstance<commit_after>package somatree

import (
	"crypto/sha512"
	"encoding/base64"
	"encoding/json"
	"io"
	"sort"

	"github.com/satori/go.uuid"
)

type Checker interface {
	SetCheck(c Check)

	inheritCheck(c Check)
	inheritCheckDeep(c Check)
	storeCheck(c Check)
	syncCheck(childId string)
	checkCheck(checkId string) bool
}

type CheckGetter interface {
	GetCheckId() string
	GetSourceCheckId() string
	GetCheckConfigId() string
	GetSourceType() string
	GetIsInherited() bool
	GetInheritedFrom() string
	GetInheritance() bool
	GetChildrenOnly() bool
	GetView() string
	GetCapabilityId() string
	GetInterval() uint64
	GetItemId(objType string, objId uuid.UUID) uuid.UUID
}

type Check struct {
	Id            uuid.UUID
	SourceId      uuid.UUID
	SourceType    string
	Inherited     bool
	InheritedFrom uuid.UUID
	CapabilityId  uuid.UUID
	ConfigId      uuid.UUID
	Inheritance   bool
	ChildrenOnly  bool
	View          string
	Interval      uint64
	Thresholds    []CheckThreshold
	Constraints   []CheckConstraint
	Items         []CheckItem
}

type CheckItem struct {
	ObjectId   uuid.UUID
	ObjectType string
	ItemId     uuid.UUID
}

type CheckThreshold struct {
	Predicate string
	Level     uint8
	Value     int64
}

type CheckConstraint struct {
	Type  string
	Key   string
	Value string
}

type CheckInstance struct {
	InstanceId            uuid.UUID
	CheckId               uuid.UUID
	ConfigId              uuid.UUID
	InstanceConfigId      uuid.UUID
	Version               uint64
	ConstraintHash        string
	ConstraintValHash     string
	ConstraintOncall      string                         // Ids
	ConstraintService     map[string]string              // svcName->value
	ConstraintSystem      map[string]string              // Id->value
	ConstraintCustom      map[string]string              // Id->value
	ConstraintNative      map[string]string              // prop->value
	ConstraintAttribute   map[string]map[string][]string // svcId->attr->[ value, value, ... ]
	InstanceServiceConfig map[string]string              // attr->value
	InstanceService       string
	InstanceSvcCfgHash    string
}

func (c *Check) GetItemId(objType string, objId uuid.UUID) uuid.UUID {
	if !uuid.Equal(c.Id, uuid.Nil) {
		return c.Id
	}
	for _, item := range c.Items {
		if objType == item.ObjectType && uuid.Equal(item.ObjectId, objId) {
			return item.ItemId
		}
	}
	return uuid.Nil
}

func (c *Check) GetCheckId() string {
	return c.Id.String()
}

func (c *Check) GetSourceCheckId() string {
	return c.SourceId.String()
}

func (c *Check) GetCheckConfigId() string {
	return c.ConfigId.String()
}

func (c *Check) GetSourceType() string {
	return c.SourceType
}

func (c *Check) GetIsInherited() bool {
	return c.Inherited
}

func (c *Check) GetInheritedFrom() string {
	return c.InheritedFrom.String()
}

func (c *Check) GetInheritance() bool {
	return c.Inheritance
}

func (c *Check) GetChildrenOnly() bool {
	return c.ChildrenOnly
}

func (c *Check) GetView() string {
	return c.View
}

func (c *Check) GetCapabilityId() string {
	return c.CapabilityId.String()
}

func (c *Check) GetInterval() uint64 {
	return c.Interval
}

func (c *Check) MakeAction() Action {
	return Action{
		Check: somaproto.TreeCheck{
			CheckId:       c.GetCheckId(),
			SourceCheckId: c.GetSourceCheckId(),
			CheckConfigId: c.GetCheckConfigId(),
			SourceType:    c.GetSourceType(),
			IsInherited:   c.GetIsInherited(),
			InheritedFrom: c.GetInheritedFrom(),
			Inheritance:   c.GetInheritance(),
			ChildrenOnly:  c.GetChildrenOnly(),
			CapabilityId:  c.GetCapabilityId(),
		},
	}
}

func (tci *CheckInstance) Clone() CheckInstance {
	cl := CheckInstance{
		Version:            tci.Version,
		ConstraintHash:     tci.ConstraintHash,
		ConstraintValHash:  tci.ConstraintValHash,
		ConstraintOncall:   tci.ConstraintOncall,
		InstanceSvcCfgHash: tci.InstanceSvcCfgHash,
		InstanceService:    tci.InstanceService,
	}
	cl.InstanceConfigId, _ = uuid.FromString(tci.InstanceConfigId.String())
	cl.InstanceId, _ = uuid.FromString(tci.InstanceId.String())
	cl.CheckId, _ = uuid.FromString(tci.CheckId.String())
	cl.ConfigId, _ = uuid.FromString(tci.ConfigId.String())
	for k, v := range tci.ConstraintService {
		t := v
		cl.ConstraintService[k] = t
	}
	for k, v := range tci.ConstraintSystem {
		t := v
		cl.ConstraintSystem[k] = t
	}
	for k, v := range tci.ConstraintCustom {
		t := v
		cl.ConstraintCustom[k] = t
	}
	for k, v := range tci.ConstraintNative {
		t := v
		cl.ConstraintNative[k] = t
	}
	for k, v := range tci.InstanceServiceConfig {
		t := v
		cl.InstanceServiceConfig[k] = t
	}
	cl.ConstraintAttribute = make(map[string]map[string][]string, 0)
	for k, _ := range tci.ConstraintAttribute {
		for k2, aVal := range tci.ConstraintAttribute[k] {
			for _, val := range aVal {
				t := val
				cl.ConstraintAttribute[k][k2] = append(cl.ConstraintAttribute[k][k2], t)
			}
		}
	}

	return cl
}

func (tci *CheckInstance) calcConstraintHash() {
	h := sha512.New()
	io.WriteString(h, tci.ConstraintOncall)

	services := []string{}
	for i, _ := range tci.ConstraintService {
		j := i
		services = append(services, j)
	}
	sort.Strings(services)
	for _, i := range services {
		io.WriteString(h, i)
	}

	systems := []string{}
	for i, _ := range tci.ConstraintSystem {
		j := i
		systems = append(systems, j)
	}
	sort.Strings(systems)
	for _, i := range systems {
		io.WriteString(h, i)
	}

	customs := []string{}
	for i, _ := range tci.ConstraintCustom {
		j := i
		customs = append(customs, j)
	}
	sort.Strings(customs)
	for _, i := range customs {
		io.WriteString(h, i)
	}

	natives := []string{}
	for i, _ := range tci.ConstraintNative {
		j := i
		natives = append(natives, j)
	}
	sort.Strings(natives)
	for _, i := range natives {
		io.WriteString(h, i)
	}

	attributes := []string{}
	for i, _ := range tci.ConstraintAttribute {
		j := i
		attributes = append(attributes, j)
	}
	sort.Strings(attributes)
	for _, i := range attributes {
		svcattr := []string{}
		for j, _ := range tci.ConstraintAttribute[i] {
			k := j
			svcattr = append(svcattr, k)
		}
		sort.Strings(svcattr)
		io.WriteString(h, i)
		for _, l := range svcattr {
			io.WriteString(h, l)
		}
	}
	tci.ConstraintHash = base64.URLEncoding.EncodeToString(h.Sum(nil))
}

func (tci *CheckInstance) calcConstraintValHash() {
	h := sha512.New()
	io.WriteString(h, tci.ConstraintOncall)

	services := []string{}
	for i, _ := range tci.ConstraintService {
		j := i
		services = append(services, j)
	}
	sort.Strings(services)
	for _, i := range services {
		io.WriteString(h, i)
		io.WriteString(h, tci.ConstraintService[i])
	}

	systems := []string{}
	for i, _ := range tci.ConstraintSystem {
		j := i
		systems = append(systems, j)
	}
	sort.Strings(systems)
	for _, i := range systems {
		io.WriteString(h, i)
		io.WriteString(h, tci.ConstraintSystem[i])
	}

	customs := []string{}
	for i, _ := range tci.ConstraintCustom {
		j := i
		customs = append(customs, j)
	}
	sort.Strings(customs)
	for _, i := range customs {
		io.WriteString(h, i)
		io.WriteString(h, tci.ConstraintCustom[i])
	}

	natives := []string{}
	for i, _ := range tci.ConstraintNative {
		j := i
		natives = append(natives, j)
	}
	sort.Strings(natives)
	for _, i := range natives {
		io.WriteString(h, i)
		io.WriteString(h, tci.ConstraintNative[i])
	}

	attributes := []string{}
	for i, _ := range tci.ConstraintAttribute {
		j := i
		attributes = append(attributes, j)
	}
	sort.Strings(attributes)
	for _, i := range attributes {
		svcattr := []string{}
		for j, _ := range tci.ConstraintAttribute[i] {
			k := j
			svcattr = append(svcattr, k)
		}
		sort.Strings(svcattr)
		io.WriteString(h, i)
		for _, l := range svcattr {
			io.WriteString(h, l)
			vals := make([]string, len(tci.ConstraintAttribute[i][l]))
			copy(vals, tci.ConstraintAttribute[i][l])
			sort.Strings(vals)
			for _, m := range vals {
				io.WriteString(h, m)
			}
		}
	}
	tci.ConstraintValHash = base64.URLEncoding.EncodeToString(h.Sum(nil))
}

func (tci *CheckInstance) calcInstanceSvcCfgHash() {
	h := sha512.New()

	attributes := []string{}
	for i, _ := range tci.InstanceServiceConfig {
		j := i
		attributes = append(attributes, j)
	}
	sort.Strings(attributes)
	for _, i := range attributes {
		io.WriteString(h, i)
		io.WriteString(h, tci.InstanceServiceConfig[i])
	}
	tci.InstanceSvcCfgHash = base64.URLEncoding.EncodeToString(h.Sum(nil))
}

func (c *Check) clone() Check {
	cl := Check{
		SourceType:   c.SourceType,
		Inherited:    c.Inherited,
		Inheritance:  c.Inheritance,
		ChildrenOnly: c.ChildrenOnly,
		View:         c.View,
		Interval:     c.Interval,
	}
	cl.Id, _ = uuid.FromString(c.Id.String())
	cl.SourceId, _ = uuid.FromString(c.SourceId.String())
	cl.InheritedFrom, _ = uuid.FromString(c.InheritedFrom.String())
	cl.CapabilityId, _ = uuid.FromString(c.CapabilityId.String())
	cl.ConfigId, _ = uuid.FromString(c.ConfigId.String())
	cl.Thresholds = make([]CheckThreshold, len(c.Thresholds))
	for i, thr := range c.Thresholds {
		n := CheckThreshold{
			Predicate: thr.Predicate,
			Level:     thr.Level,
			Value:     thr.Value,
		}
		cl.Thresholds[i] = n
	}
	cl.Constraints = make([]CheckConstraint, len(c.Constraints))
	for i, ctr := range c.Constraints {
		n := CheckConstraint{
			Type:  ctr.Type,
			Key:   ctr.Key,
			Value: ctr.Value,
		}
		cl.Constraints[i] = n
	}
	cl.Items = make([]CheckItem, len(c.Items))
	for i, item := range c.Items {
		n := CheckItem{
			ObjectType: item.ObjectType,
		}
		n.ItemId, _ = uuid.FromString(item.ItemId.String())
		n.ObjectId, _ = uuid.FromString(item.ObjectId.String())
		cl.Items[i] = n
	}
	return cl
}

func (ci CheckInstance) MakeAction() Action {
	serviceCfg, err := json.Marshal(ci.InstanceServiceConfig)
	if err != nil {
		serviceCfg = []byte{}
	}

	return Action{
		CheckInstance: somaproto.TreeCheckInstance{
			InstanceId:            ci.InstanceId.String(),
			CheckId:               ci.CheckId.String(),
			ConfigId:              ci.ConfigId.String(),
			InstanceConfigId:      ci.InstanceConfigId.String(),
			Version:               ci.Version,
			ConstraintHash:        ci.ConstraintHash,
			ConstraintValHash:     ci.ConstraintValHash,
			InstanceSvcCfgHash:    ci.InstanceSvcCfgHash,
			InstanceService:       ci.InstanceService,
			InstanceServiceConfig: string(serviceCfg),
		},
	}
}

// vim: ts=4 sw=4 sts=4 noet fenc=utf-8 ffs=unix
<|endoftext|>


<commit_before>// Copyright 2017-2019 The Prometheus 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.

// +build linux
// +build !noinfiniband

package collector

import (
	"fmt"
	"strconv"

	"github.com/go-kit/kit/log"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/procfs/sysfs"
)

type infinibandCollector struct {
	fs          sysfs.FS
	metricDescs map[string]*prometheus.Desc
	logger      log.Logger
}

func init() {
	registerCollector("infiniband", defaultEnabled, NewInfiniBandCollector)
}

// NewInfiniBandCollector returns a new Collector exposing InfiniBand stats.
func NewInfiniBandCollector(logger log.Logger) (Collector, error) {
	var i infinibandCollector
	var err error

	i.fs, err = sysfs.NewFS(*sysPath)
	if err != nil {
		return nil, fmt.Errorf("failed to open sysfs: %w", err)
	}
	i.logger = logger

	// Detailed description for all metrics.
	descriptions := map[string]string{
		"legacy_multicast_packets_received_total":    "Number of multicast packets received",
		"legacy_multicast_packets_transmitted_total": "Number of multicast packets transmitted",
		"legacy_data_received_bytes_total":           "Number of data octets received on all links",
		"legacy_packets_received_total":              "Number of data packets received on all links",
		"legacy_unicast_packets_received_total":      "Number of unicast packets received",
		"legacy_unicast_packets_transmitted_total":   "Number of unicast packets transmitted",
		"legacy_data_transmitted_bytes_total":        "Number of data octets transmitted on all links",
		"legacy_packets_transmitted_total":           "Number of data packets received on all links",
		"link_downed_total":                          "Number of times the link failed to recover from an error state and went down",
		"link_error_recovery_total":                  "Number of times the link successfully recovered from an error state",
		"multicast_packets_received_total":           "Number of multicast packets received (including errors)",
		"multicast_packets_transmitted_total":        "Number of multicast packets transmitted (including errors)",
		"physical_state_id":                          "Physical state of the InfiniBand port (0: no change, 1: sleep, 2: polling, 3: disable, 4: shift, 5: link up, 6: link error recover, 7: phytest)",
		"port_constraint_errors_received_total":      "Number of packets received on the switch physical port that are discarded",
		"port_constraint_errors_transmitted_total":   "Number of packets not transmitted from the switch physical port",
		"port_data_received_bytes_total":             "Number of data octets received on all links",
		"port_data_transmitted_bytes_total":          "Number of data octets transmitted on all links",
		"port_discards_received_total":               "Number of inbound packets discarded by the port because the port is down or congested",
		"port_discards_transmitted_total":            "Number of outbound packets discarded by the port because the port is down or congested",
		"port_errors_received_total":                 "Number of packets containing an error that were received on this port",
		"port_packets_received_total":                "Number of packets received on all VLs by this port (including errors)",
		"port_packets_transmitted_total":             "Number of packets transmitted on all VLs from this port (including errors)",
		"port_transmit_wait_total":                   "Number of ticks during which the port had data to transmit but no data was sent during the entire tick",
		"rate_bytes_per_second":                      "Maximum signal transfer rate",
		"state_id":                                   "State of the InfiniBand port (0: no change, 1: down, 2: init, 3: armed, 4: active, 5: act defer)",
		"unicast_packets_received_total":             "Number of unicast packets received (including errors)",
		"unicast_packets_transmitted_total":          "Number of unicast packets transmitted (including errors)",
	}

	i.metricDescs = make(map[string]*prometheus.Desc)

	for metricName, description := range descriptions {
		i.metricDescs[metricName] = prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "infiniband", metricName),
			description,
			[]string{"device", "port"},
			nil,
		)
	}

	return &i, nil
}

func (c *infinibandCollector) pushMetric(ch chan<- prometheus.Metric, name string, value uint64, deviceName string, port string, valueType prometheus.ValueType) {
	ch <- prometheus.MustNewConstMetric(c.metricDescs[name], valueType, float64(value), deviceName, port)
}

func (c *infinibandCollector) pushCounter(ch chan<- prometheus.Metric, name string, value *uint64, deviceName string, port string) {
	if value != nil {
		c.pushMetric(ch, name, *value, deviceName, port, prometheus.CounterValue)
	}
}

func (c *infinibandCollector) Update(ch chan<- prometheus.Metric) error {
	devices, err := c.fs.InfiniBandClass()
	if err != nil {
		return fmt.Errorf("error obtaining InfiniBand class info: %s", err)
	}

	for _, device := range devices {
		for _, port := range device.Ports {
			portStr := strconv.FormatUint(uint64(port.Port), 10)

			c.pushMetric(ch, "state_id", uint64(port.StateID), port.Name, portStr, prometheus.GaugeValue)
			c.pushMetric(ch, "physical_state_id", uint64(port.PhysStateID), port.Name, portStr, prometheus.GaugeValue)
			c.pushMetric(ch, "rate_bytes_per_second", port.Rate, port.Name, portStr, prometheus.GaugeValue)

			c.pushCounter(ch, "legacy_multicast_packets_received_total", port.Counters.LegacyPortMulticastRcvPackets, port.Name, portStr)
			c.pushCounter(ch, "legacy_multicast_packets_transmitted_total", port.Counters.LegacyPortMulticastXmitPackets, port.Name, portStr)
			c.pushCounter(ch, "legacy_data_received_bytes_total", port.Counters.LegacyPortRcvData64, port.Name, portStr)
			c.pushCounter(ch, "legacy_packets_received_total", port.Counters.LegacyPortRcvPackets64, port.Name, portStr)
			c.pushCounter(ch, "legacy_unicast_packets_received_total", port.Counters.LegacyPortUnicastRcvPackets, port.Name, portStr)
			c.pushCounter(ch, "legacy_unicast_packets_transmitted_total", port.Counters.LegacyPortUnicastXmitPackets, port.Name, portStr)
			c.pushCounter(ch, "legacy_data_transmitted_bytes_total", port.Counters.LegacyPortXmitData64, port.Name, portStr)
			c.pushCounter(ch, "legacy_packets_transmitted_total", port.Counters.LegacyPortXmitPackets64, port.Name, portStr)
			c.pushCounter(ch, "link_downed_total", port.Counters.LinkDowned, port.Name, portStr)
			c.pushCounter(ch, "link_error_recovery_total", port.Counters.LinkErrorRecovery, port.Name, portStr)
			c.pushCounter(ch, "multicast_packets_received_total", port.Counters.MulticastRcvPackets, port.Name, portStr)
			c.pushCounter(ch, "multicast_packets_transmitted_total", port.Counters.MulticastXmitPackets, port.Name, portStr)
			c.pushCounter(ch, "port_constraint_errors_received_total", port.Counters.PortRcvConstraintErrors, port.Name, portStr)
			c.pushCounter(ch, "port_constraint_errors_transmitted_total", port.Counters.PortXmitConstraintErrors, port.Name, portStr)
			c.pushCounter(ch, "port_data_received_bytes_total", port.Counters.PortRcvData, port.Name, portStr)
			c.pushCounter(ch, "port_data_transmitted_bytes_total", port.Counters.PortXmitData, port.Name, portStr)
			c.pushCounter(ch, "port_discards_received_total", port.Counters.PortRcvDiscards, port.Name, portStr)
			c.pushCounter(ch, "port_discards_transmitted_total", port.Counters.PortXmitDiscards, port.Name, portStr)
			c.pushCounter(ch, "port_errors_received_total", port.Counters.PortRcvErrors, port.Name, portStr)
			c.pushCounter(ch, "port_packets_received_total", port.Counters.PortRcvPackets, port.Name, portStr)
			c.pushCounter(ch, "port_packets_transmitted_total", port.Counters.PortXmitPackets, port.Name, portStr)
			c.pushCounter(ch, "port_transmit_wait_total", port.Counters.PortXmitWait, port.Name, portStr)
			c.pushCounter(ch, "unicast_packets_received_total", port.Counters.UnicastRcvPackets, port.Name, portStr)
			c.pushCounter(ch, "unicast_packets_transmitted_total", port.Counters.UnicastXmitPackets, port.Name, portStr)
		}
	}

	return nil
}
<commit_msg>Fix inifiband collector log noise (#1599)<commit_after>// Copyright 2017-2019 The Prometheus 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.

// +build linux
// +build !noinfiniband

package collector

import (
	"fmt"
	"os"
	"strconv"

	"github.com/go-kit/kit/log"
	"github.com/go-kit/kit/log/level"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/procfs/sysfs"
)

type infinibandCollector struct {
	fs          sysfs.FS
	metricDescs map[string]*prometheus.Desc
	logger      log.Logger
}

func init() {
	registerCollector("infiniband", defaultEnabled, NewInfiniBandCollector)
}

// NewInfiniBandCollector returns a new Collector exposing InfiniBand stats.
func NewInfiniBandCollector(logger log.Logger) (Collector, error) {
	var i infinibandCollector
	var err error

	i.fs, err = sysfs.NewFS(*sysPath)
	if err != nil {
		return nil, fmt.Errorf("failed to open sysfs: %w", err)
	}
	i.logger = logger

	// Detailed description for all metrics.
	descriptions := map[string]string{
		"legacy_multicast_packets_received_total":    "Number of multicast packets received",
		"legacy_multicast_packets_transmitted_total": "Number of multicast packets transmitted",
		"legacy_data_received_bytes_total":           "Number of data octets received on all links",
		"legacy_packets_received_total":              "Number of data packets received on all links",
		"legacy_unicast_packets_received_total":      "Number of unicast packets received",
		"legacy_unicast_packets_transmitted_total":   "Number of unicast packets transmitted",
		"legacy_data_transmitted_bytes_total":        "Number of data octets transmitted on all links",
		"legacy_packets_transmitted_total":           "Number of data packets received on all links",
		"link_downed_total":                          "Number of times the link failed to recover from an error state and went down",
		"link_error_recovery_total":                  "Number of times the link successfully recovered from an error state",
		"multicast_packets_received_total":           "Number of multicast packets received (including errors)",
		"multicast_packets_transmitted_total":        "Number of multicast packets transmitted (including errors)",
		"physical_state_id":                          "Physical state of the InfiniBand port (0: no change, 1: sleep, 2: polling, 3: disable, 4: shift, 5: link up, 6: link error recover, 7: phytest)",
		"port_constraint_errors_received_total":      "Number of packets received on the switch physical port that are discarded",
		"port_constraint_errors_transmitted_total":   "Number of packets not transmitted from the switch physical port",
		"port_data_received_bytes_total":             "Number of data octets received on all links",
		"port_data_transmitted_bytes_total":          "Number of data octets transmitted on all links",
		"port_discards_received_total":               "Number of inbound packets discarded by the port because the port is down or congested",
		"port_discards_transmitted_total":            "Number of outbound packets discarded by the port because the port is down or congested",
		"port_errors_received_total":                 "Number of packets containing an error that were received on this port",
		"port_packets_received_total":                "Number of packets received on all VLs by this port (including errors)",
		"port_packets_transmitted_total":             "Number of packets transmitted on all VLs from this port (including errors)",
		"port_transmit_wait_total":                   "Number of ticks during which the port had data to transmit but no data was sent during the entire tick",
		"rate_bytes_per_second":                      "Maximum signal transfer rate",
		"state_id":                                   "State of the InfiniBand port (0: no change, 1: down, 2: init, 3: armed, 4: active, 5: act defer)",
		"unicast_packets_received_total":             "Number of unicast packets received (including errors)",
		"unicast_packets_transmitted_total":          "Number of unicast packets transmitted (including errors)",
	}

	i.metricDescs = make(map[string]*prometheus.Desc)

	for metricName, description := range descriptions {
		i.metricDescs[metricName] = prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "infiniband", metricName),
			description,
			[]string{"device", "port"},
			nil,
		)
	}

	return &i, nil
}

func (c *infinibandCollector) pushMetric(ch chan<- prometheus.Metric, name string, value uint64, deviceName string, port string, valueType prometheus.ValueType) {
	ch <- prometheus.MustNewConstMetric(c.metricDescs[name], valueType, float64(value), deviceName, port)
}

func (c *infinibandCollector) pushCounter(ch chan<- prometheus.Metric, name string, value *uint64, deviceName string, port string) {
	if value != nil {
		c.pushMetric(ch, name, *value, deviceName, port, prometheus.CounterValue)
	}
}

func (c *infinibandCollector) Update(ch chan<- prometheus.Metric) error {
	devices, err := c.fs.InfiniBandClass()
	if err != nil {
		if os.IsNotExist(err) {
			level.Debug(c.logger).Log("msg", "IPv4 sockstat statistics not found, skipping")
			return nil
		}
		return fmt.Errorf("error obtaining InfiniBand class info: %s", err)
	}

	for _, device := range devices {
		for _, port := range device.Ports {
			portStr := strconv.FormatUint(uint64(port.Port), 10)

			c.pushMetric(ch, "state_id", uint64(port.StateID), port.Name, portStr, prometheus.GaugeValue)
			c.pushMetric(ch, "physical_state_id", uint64(port.PhysStateID), port.Name, portStr, prometheus.GaugeValue)
			c.pushMetric(ch, "rate_bytes_per_second", port.Rate, port.Name, portStr, prometheus.GaugeValue)

			c.pushCounter(ch, "legacy_multicast_packets_received_total", port.Counters.LegacyPortMulticastRcvPackets, port.Name, portStr)
			c.pushCounter(ch, "legacy_multicast_packets_transmitted_total", port.Counters.LegacyPortMulticastXmitPackets, port.Name, portStr)
			c.pushCounter(ch, "legacy_data_received_bytes_total", port.Counters.LegacyPortRcvData64, port.Name, portStr)
			c.pushCounter(ch, "legacy_packets_received_total", port.Counters.LegacyPortRcvPackets64, port.Name, portStr)
			c.pushCounter(ch, "legacy_unicast_packets_received_total", port.Counters.LegacyPortUnicastRcvPackets, port.Name, portStr)
			c.pushCounter(ch, "legacy_unicast_packets_transmitted_total", port.Counters.LegacyPortUnicastXmitPackets, port.Name, portStr)
			c.pushCounter(ch, "legacy_data_transmitted_bytes_total", port.Counters.LegacyPortXmitData64, port.Name, portStr)
			c.pushCounter(ch, "legacy_packets_transmitted_total", port.Counters.LegacyPortXmitPackets64, port.Name, portStr)
			c.pushCounter(ch, "link_downed_total", port.Counters.LinkDowned, port.Name, portStr)
			c.pushCounter(ch, "link_error_recovery_total", port.Counters.LinkErrorRecovery, port.Name, portStr)
			c.pushCounter(ch, "multicast_packets_received_total", port.Counters.MulticastRcvPackets, port.Name, portStr)
			c.pushCounter(ch, "multicast_packets_transmitted_total", port.Counters.MulticastXmitPackets, port.Name, portStr)
			c.pushCounter(ch, "port_constraint_errors_received_total", port.Counters.PortRcvConstraintErrors, port.Name, portStr)
			c.pushCounter(ch, "port_constraint_errors_transmitted_total", port.Counters.PortXmitConstraintErrors, port.Name, portStr)
			c.pushCounter(ch, "port_data_received_bytes_total", port.Counters.PortRcvData, port.Name, portStr)
			c.pushCounter(ch, "port_data_transmitted_bytes_total", port.Counters.PortXmitData, port.Name, portStr)
			c.pushCounter(ch, "port_discards_received_total", port.Counters.PortRcvDiscards, port.Name, portStr)
			c.pushCounter(ch, "port_discards_transmitted_total", port.Counters.PortXmitDiscards, port.Name, portStr)
			c.pushCounter(ch, "port_errors_received_total", port.Counters.PortRcvErrors, port.Name, portStr)
			c.pushCounter(ch, "port_packets_received_total", port.Counters.PortRcvPackets, port.Name, portStr)
			c.pushCounter(ch, "port_packets_transmitted_total", port.Counters.PortXmitPackets, port.Name, portStr)
			c.pushCounter(ch, "port_transmit_wait_total", port.Counters.PortXmitWait, port.Name, portStr)
			c.pushCounter(ch, "unicast_packets_received_total", port.Counters.UnicastRcvPackets, port.Name, portStr)
			c.pushCounter(ch, "unicast_packets_transmitted_total", port.Counters.UnicastXmitPackets, port.Name, portStr)
		}
	}

	return nil
}
<|endoftext|>


<commit_before>// Copyright 2014 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import "testing"

func TestCurrentBranch(t *testing.T) {
	gt := newGitTest(t)
	defer gt.done()

	t.Logf("on master")
	checkCurrentBranch(t, "master", "origin/master", false, false, "", "")

	t.Logf("on newbranch")
	trun(t, gt.client, "git", "checkout", "-t", "-b", "newbranch", "origin/master")
	checkCurrentBranch(t, "newbranch", "origin/master", true, false, "", "")

	t.Logf("making change")
	write(t, gt.client+"/file", "i made a change")
	trun(t, gt.client, "git", "commit", "-a", "-m", "My change line.\n\nChange-Id: I0123456789abcdef0123456789abcdef\n")
	checkCurrentBranch(t, "newbranch", "origin/master", true, true, "I0123456789abcdef0123456789abcdef", "My change line.")

	t.Logf("on dev.branch")
	trun(t, gt.client, "git", "checkout", "-t", "-b", "dev.branch", "origin/dev.branch")
	checkCurrentBranch(t, "dev.branch", "origin/dev.branch", false, false, "", "")

	t.Logf("on newdev")
	trun(t, gt.client, "git", "checkout", "-t", "-b", "newdev", "origin/dev.branch")
	checkCurrentBranch(t, "newdev", "origin/dev.branch", true, false, "", "")

	t.Logf("making change")
	write(t, gt.client+"/file", "i made another change")
	trun(t, gt.client, "git", "commit", "-a", "-m", "My other change line.\n\nChange-Id: I1123456789abcdef0123456789abcdef\n")
	checkCurrentBranch(t, "newdev", "origin/dev.branch", true, true, "I1123456789abcdef0123456789abcdef", "My other change line.")
}

func checkCurrentBranch(t *testing.T, name, origin string, isLocal, hasPending bool, changeID, subject string) {
	b := CurrentBranch()
	if b.Name != name {
		t.Errorf("b.Name = %q, want %q", b.Name, name)
	}
	if x := b.OriginBranch(); x != origin {
		t.Errorf("b.OriginBranch() = %q, want %q", x, origin)
	}
	if x := b.IsLocalOnly(); x != isLocal {
		t.Errorf("b.IsLocalOnly() = %v, want %v", x, isLocal)
	}
	if x := b.HasPendingCommit(); x != hasPending {
		t.Errorf("b.HasPendingCommit() = %v, want %v", x, isLocal)
	}
	if x := b.ChangeID(); x != changeID {
		t.Errorf("b.ChangeID() = %q, want %q", x, changeID)
	}
	if x := b.Subject(); x != subject {
		t.Errorf("b.Subject() = %q, want %q", x, subject)
	}
}
<commit_msg>Revert "git-codereview: fix TestCurrentBranch"<commit_after>// Copyright 2014 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import "testing"

func TestCurrentBranch(t *testing.T) {
	gt := newGitTest(t)
	defer gt.done()

	t.Logf("on master")
	checkCurrentBranch(t, "master", "origin/master", false, false, "", "")

	t.Logf("on newbranch")
	trun(t, gt.client, "git", "checkout", "-b", "newbranch")
	checkCurrentBranch(t, "newbranch", "origin/master", true, false, "", "")

	t.Logf("making change")
	write(t, gt.client+"/file", "i made a change")
	trun(t, gt.client, "git", "commit", "-a", "-m", "My change line.\n\nChange-Id: I0123456789abcdef0123456789abcdef\n")
	checkCurrentBranch(t, "newbranch", "origin/master", true, true, "I0123456789abcdef0123456789abcdef", "My change line.")

	t.Logf("on dev.branch")
	trun(t, gt.client, "git", "checkout", "-t", "-b", "dev.branch", "origin/dev.branch")
	checkCurrentBranch(t, "dev.branch", "origin/dev.branch", false, false, "", "")

	t.Logf("on newdev")
	trun(t, gt.client, "git", "checkout", "-t", "-b", "newdev", "origin/dev.branch")
	checkCurrentBranch(t, "newdev", "origin/dev.branch", true, false, "", "")

	t.Logf("making change")
	write(t, gt.client+"/file", "i made another change")
	trun(t, gt.client, "git", "commit", "-a", "-m", "My other change line.\n\nChange-Id: I1123456789abcdef0123456789abcdef\n")
	checkCurrentBranch(t, "newdev", "origin/dev.branch", true, true, "I1123456789abcdef0123456789abcdef", "My other change line.")
}

func checkCurrentBranch(t *testing.T, name, origin string, isLocal, hasPending bool, changeID, subject string) {
	b := CurrentBranch()
	if b.Name != name {
		t.Errorf("b.Name = %q, want %q", b.Name, name)
	}
	if x := b.OriginBranch(); x != origin {
		t.Errorf("b.OriginBranch() = %q, want %q", x, origin)
	}
	if x := b.IsLocalOnly(); x != isLocal {
		t.Errorf("b.IsLocalOnly() = %v, want %v", x, isLocal)
	}
	if x := b.HasPendingCommit(); x != hasPending {
		t.Errorf("b.HasPendingCommit() = %v, want %v", x, isLocal)
	}
	if x := b.ChangeID(); x != changeID {
		t.Errorf("b.ChangeID() = %q, want %q", x, changeID)
	}
	if x := b.Subject(); x != subject {
		t.Errorf("b.Subject() = %q, want %q", x, subject)
	}
}
<|endoftext|>