<commit_before>package character

import (
	"net/http"
	"sort"

	"github.com/aerogo/aero"
	"github.com/animenotifier/arn"
	"github.com/animenotifier/notify.moe/components"
	"github.com/animenotifier/notify.moe/utils"
)

// Get character.
func Get(ctx *aero.Context) string {
	user := utils.GetUser(ctx)
	id := ctx.Get("id")
	character, err := arn.GetCharacter(id)

	if err != nil {
		return ctx.Error(http.StatusNotFound, "Character not found", err)
	}

	characterAnime := character.Anime()

	sort.Slice(characterAnime, func(i, j int) bool {
		if characterAnime[i].StartDate == "" {
			return false
		}

		if characterAnime[j].StartDate == "" {
			return true
		}

		return characterAnime[i].StartDate < characterAnime[j].StartDate
	})

	// Set OpenGraph attributes
	ctx.Data = &arn.OpenGraph{
		Tags: map[string]string{
			"og:title":       character.Name,
			"og:image":       character.Image,
			"og:url":         "https://" + ctx.App.Config.Domain + character.Link(),
			"og:site_name":   "notify.moe",
			"og:description": character.Description,
		},
		Meta: map[string]string{
			"description": character.Description,
			"keywords":    character.Name + ",anime,character",
		},
	}

	return ctx.HTML(components.CharacterDetails(character, characterAnime, user))
}
<commit_msg>Improved character OG data<commit_after>package character

import (
	"net/http"
	"sort"

	"github.com/aerogo/aero"
	"github.com/animenotifier/arn"
	"github.com/animenotifier/notify.moe/components"
	"github.com/animenotifier/notify.moe/utils"
)

const maxDescriptionLength = 170

// Get character.
func Get(ctx *aero.Context) string {
	user := utils.GetUser(ctx)
	id := ctx.Get("id")
	character, err := arn.GetCharacter(id)

	if err != nil {
		return ctx.Error(http.StatusNotFound, "Character not found", err)
	}

	characterAnime := character.Anime()

	sort.Slice(characterAnime, func(i, j int) bool {
		if characterAnime[i].StartDate == "" {
			return false
		}

		if characterAnime[j].StartDate == "" {
			return true
		}

		return characterAnime[i].StartDate < characterAnime[j].StartDate
	})

	// Set OpenGraph attributes
	description := character.Description

	if len(description) > maxDescriptionLength {
		description = description[:maxDescriptionLength-3] + "..."
	}

	ctx.Data = &arn.OpenGraph{
		Tags: map[string]string{
			"og:title":       character.Name,
			"og:image":       character.Image,
			"og:url":         "https://" + ctx.App.Config.Domain + character.Link(),
			"og:site_name":   "notify.moe",
			"og:description": description,

			// The OpenGraph type "profile" is meant for real-life persons but I think it's okay in this context.
			// An alternative would be to use "article" which is mostly used for blog posts and news.
			"og:type": "profile",
		},
		Meta: map[string]string{
			"description": description,
			"keywords":    character.Name + ",anime,character",
		},
	}

	return ctx.HTML(components.CharacterDetails(character, characterAnime, user))
}
<|endoftext|>


<commit_before>package api

import (
	"encoding/base64"
	"fmt"
	"github.com/danjac/podbaby/api/Godeps/_workspace/src/github.com/labstack/echo"
	"github.com/danjac/podbaby/config"
	"net/http"
	"time"

	"github.com/danjac/podbaby/api/Godeps/_workspace/src/github.com/gorilla/securecookie"
)

const sessionTimeout = 24 * 30

type session interface {
	write(*echo.Context, string, interface{}) error
	read(*echo.Context, string, interface{}) (bool, error)
	readInt(*echo.Context, string) (int, bool, error)
}

type secureCookieSession struct {
	*securecookie.SecureCookie
	isSecure bool
}

func (s *secureCookieSession) write(c *echo.Context, key string, value interface{}) error {
	encoded, err := s.Encode(key, value)
	if err == nil {
		cookie := &http.Cookie{
			Name:     key,
			Value:    encoded,
			Expires:  time.Now().Add(time.Hour * sessionTimeout),
			Secure:   s.isSecure,
			HttpOnly: true,
			Path:     "/",
		}
		http.SetCookie(c.Response(), cookie)
	}
	return err
}

func (s *secureCookieSession) read(c *echo.Context, key string, dst interface{}) (bool, error) {
	cookie, err := c.Request().Cookie(key)
	if err == http.ErrNoCookie {
		return false, nil
	}
	if err != nil {
		return false, err
	}
	err = s.Decode(key, cookie.Value, dst)
	fmt.Println("ERROR", err)
	return err != nil, err
}

func (s *secureCookieSession) readInt(c *echo.Context, key string) (int, bool, error) {
	var rv int
	ok, err := s.read(c, key, &rv)
	return rv, ok, err
}

func newSession(cfg *config.Config) session {
	secureCookieKey, _ := base64.StdEncoding.DecodeString(cfg.SecureCookieKey)
	cookie := securecookie.New(
		[]byte(cfg.SecretKey),
		secureCookieKey,
	)
	return &secureCookieSession{
		SecureCookie: cookie,
		isSecure:     !cfg.IsDev(),
	}
}
<commit_msg>Test fixes<commit_after>package api

import (
	"encoding/base64"
	"github.com/danjac/podbaby/api/Godeps/_workspace/src/github.com/labstack/echo"
	"github.com/danjac/podbaby/config"
	"net/http"
	"time"

	"github.com/danjac/podbaby/api/Godeps/_workspace/src/github.com/gorilla/securecookie"
)

const sessionTimeout = 24 * 30

type session interface {
	write(*echo.Context, string, interface{}) error
	read(*echo.Context, string, interface{}) (bool, error)
	readInt(*echo.Context, string) (int, bool, error)
}

type secureCookieSession struct {
	*securecookie.SecureCookie
	isSecure bool
}

func (s *secureCookieSession) write(c *echo.Context, key string, value interface{}) error {
	encoded, err := s.Encode(key, value)
	if err == nil {
		cookie := &http.Cookie{
			Name:     key,
			Value:    encoded,
			Expires:  time.Now().Add(time.Hour * sessionTimeout),
			Secure:   s.isSecure,
			HttpOnly: true,
			Path:     "/",
		}
		http.SetCookie(c.Response(), cookie)
	}
	return err
}

func (s *secureCookieSession) read(c *echo.Context, key string, dst interface{}) (bool, error) {
	cookie, err := c.Request().Cookie(key)
	if err == http.ErrNoCookie {
		return false, nil
	}
	if err != nil {
		return false, err
	}
	err = s.Decode(key, cookie.Value, dst)
	return err == nil, err
}

func (s *secureCookieSession) readInt(c *echo.Context, key string) (int, bool, error) {
	var rv int
	ok, err := s.read(c, key, &rv)
	return rv, ok, err
}

func newSession(cfg *config.Config) session {
	secureCookieKey, _ := base64.StdEncoding.DecodeString(cfg.SecureCookieKey)
	cookie := securecookie.New(
		[]byte(cfg.SecretKey),
		secureCookieKey,
	)
	return &secureCookieSession{
		SecureCookie: cookie,
		isSecure:     !cfg.IsDev(),
	}
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"log"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/ssoadmin"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
	"github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags"
)

func resourceAwsSsoPermissionSet() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsSsoPermissionSetCreate,
		Read:   resourceAwsSsoPermissionSetRead,
		Update: resourceAwsSsoPermissionSetUpdate,
		Delete: resourceAwsSsoPermissionSetDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Schema: map[string]*schema.Schema{
			"instance_arn": {
				Type: schema.TypeString,
			},

			"permission_set_arn": {
				Type: schema.TypeString,
			},

			"created_date": {
				Type: schema.TypeString,
			},

			"description": {
				Type: schema.TypeString,
			},

			"name": {
				Type: schema.TypeString,
			},

			"relay_state": {
				Type: schema.TypeString,
			},

			"session_duration": {
				Type: schema.TypeString,
			},

			"inline_policy": {
				Type: schema.TypeString,
			},

			"managed_policies": {
				Type: schema.TypeList,
				Elem: &schema.Schema{
					Type: schema.TypeString
				},
			},

			"tags": tagsSchema(),
		},
	}
}

func resourceAwsSsoPermissionSetCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ssoadminconn
	// TODO
	// d.SetId(*resp.PermissionSetArn)
	return resourceAwsSsoPermissionSetRead(d, meta)
}

func resourceAwsSsoPermissionSetRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ssoadminconn
	// TODO
	return nil
}

func resourceAwsSsoPermissionSetUpdate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ssoadminconn
	// TODO
	return resourceAwsSsoPermissionSetRead(d, meta)
}

func resourceAwsSsoPermissionSetDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ssoadminconn
	// TODO
	return nil
}

func waitForPermissionSetProvisioning(conn *identitystore.IdentityStore, arn string) error {

}
<commit_msg>update schema<commit_after>package aws

import (
	"fmt"
	"log"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/ssoadmin"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
	"github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags"
)

func resourceAwsSsoPermissionSet() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsSsoPermissionSetCreate,
		Read:   resourceAwsSsoPermissionSetRead,
		Update: resourceAwsSsoPermissionSetUpdate,
		Delete: resourceAwsSsoPermissionSetDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},
		Schema: map[string]*schema.Schema{
			"arn": {
				Type:     schema.TypeString,
				Computed: true,
			},

			"created_date": {
				Type:     schema.TypeString,
				Computed: true,
			},

			"instance_arn": {
				Type:         schema.TypeString,
				Required:     true,
				ForceNew:     true,
				ValidateFunc: validation.All(
					validation.StringLenBetween(10, 1224),
					validation.StringMatch(regexp.MustCompile(`^arn:aws:sso:::instance/(sso)?ins-[a-zA-Z0-9-.]{16}$`), "must match arn:aws:sso:::instance/(sso)?ins-[a-zA-Z0-9-.]{16}"),
				),
			},

			"name": {
				Type:         schema.TypeString,
				Required:     true,
				ForceNew:     true,
				ValidateFunc: validation.All(
					validation.StringLenBetween(1, 32),
					validation.StringMatch(regexp.MustCompile(`^[\w+=,.@-]+$`), "must match [\\w+=,.@-]"),
				),
			},

			"description": {
				Type:     schema.TypeString,
				Optional: true,
				ValidateFunc: validation.All(
					validation.StringLenBetween(1, 700),
					validation.StringMatch(regexp.MustCompile(`^[\p{L}\p{M}\p{Z}\p{S}\p{N}\p{P}]*$`), "must match [\\p{L}\\p{M}\\p{Z}\\p{S}\\p{N}\\p{P}]"),
				),
			},

			"session_duration": {
				Type:     schema.TypeString,
				Optional: true,
				ValidateFunc: validation.StringLenBetween(1, 100),
			},

			"relay_state": {
				Type:     schema.TypeString,
				Optional: true,
				ValidateFunc: validation.All(
					validation.StringLenBetween(1, 240),
					validation.StringMatch(regexp.MustCompile(`^[a-zA-Z0-9&$@#\\\/%?=~\-_'"|!:,.;*+\[\]\(\)\{\} ]+$`), "must match [a-zA-Z0-9&$@#\\\\\\/%?=~\\-_'\"|!:,.;*+\\[\\]\\(\\)\\{\\} ]"),
				),
			},

			"inline_policy": {
				Type:             schema.TypeString,
				Optional:         true,
				ValidateFunc:     validateIAMPolicyJson,
				DiffSuppressFunc: suppressEquivalentAwsPolicyDiffs,
			},

			"managed_policies": {
				Type:     schema.TypeSet,
				Optional: true,
				Elem:     &schema.Schema{
					Type: schema.TypeString,
					ValidateFunc: validateArn,
				},
			},

			"tags": tagsSchema(),
		},
	}
}

func resourceAwsSsoPermissionSetCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ssoadminconn

	// d.SetId(*resp.PermissionSetArn)
	return resourceAwsSsoPermissionSetRead(d, meta)
}

func resourceAwsSsoPermissionSetRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ssoadminconn
	// TODO
	return nil
}

func resourceAwsSsoPermissionSetUpdate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ssoadminconn
	// TODO
	return resourceAwsSsoPermissionSetRead(d, meta)
}

func resourceAwsSsoPermissionSetDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ssoadminconn
	// TODO
	return nil
}

// func waitForPermissionSetProvisioning(conn *identitystore.IdentityStore, arn string) error {
// }
<|endoftext|>


<commit_before>package solr

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
)

func HTTPPost(path string, data *[]byte, headers [][]string) ([]byte, error) {
	client := &http.Client{}
	req, err := http.NewRequest("POST", path, bytes.NewReader(*data))
	if len(headers) > 0 {
		for i := range headers {
			req.Header.Add(headers[i][0], headers[i][1])
		}
	}

	resp, err := client.Do(req)

	if err != nil {
		return nil, err
	}

	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	return body, nil
}

func HTTPGet(url string) ([]byte, error) {
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}

	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	return body, nil
}

func bytes2Json(data *[]byte) (*interface{}, error) {
	var container interface{}
	err := json.Unmarshal(*data, &container)

	if err != nil {
		return nil, fmt.Errorf("Response decode error")
	}

	return &container, nil
}

func json2Bytes(data map[string]interface{}) (*[]byte, error) {
	b, err := json.Marshal(data)
	if err != nil {
		return nil, fmt.Errorf("Failed to encode JSON")
	}

	return &b, nil
}

type SelectResponse struct {
	results *Collection
	status  int
	qtime   int
}

type UpdateResponse struct {
	success bool
}

type ErrorResponse struct {
	message string
	status  int
}

type Connection struct {
	url *url.URL
}

func NewConnection(solrUrl string) (*Connection, error) {
	u, err := url.Parse(solrUrl)
	if err != nil {
		return nil, err
	}

	return &Connection{url: u}, nil
}

func (c *Connection) Select(selectUrl string) (*SelectResponse, error) {
	return nil, nil
}

func (c *Connection) Update(data map[string]interface{}) (*UpdateResponse, error) {
	b, err := json2Bytes(data)
	if err != nil {
		return nil, err
	}
	r, err := HTTPPost(c.url.String(), b, nil)
	if err != nil || r == nil {
		return nil, err
	}
	//resp, err := bytes2Json(&r)
	if err != nil {
		return nil, err
	}
	// check error in resp

	return &UpdateResponse{true}, nil
}

func (c *Connection) Commit() (*UpdateResponse, error) {
	return nil, nil
}

func (c *Connection) Optimize() (*UpdateResponse, error) {
	return nil, nil
}

func (c *Connection) Rollback() (*UpdateResponse, error) {
	return nil, nil
}
<commit_msg>Temporary \"use\" resp<commit_after>package solr

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
)

func HTTPPost(path string, data *[]byte, headers [][]string) ([]byte, error) {
	client := &http.Client{}
	req, err := http.NewRequest("POST", path, bytes.NewReader(*data))
	if len(headers) > 0 {
		for i := range headers {
			req.Header.Add(headers[i][0], headers[i][1])
		}
	}

	resp, err := client.Do(req)

	if err != nil {
		return nil, err
	}

	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	return body, nil
}

func HTTPGet(url string) ([]byte, error) {
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}

	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	return body, nil
}

func bytes2Json(data *[]byte) (*interface{}, error) {
	var container interface{}
	err := json.Unmarshal(*data, &container)

	if err != nil {
		return nil, fmt.Errorf("Response decode error")
	}

	return &container, nil
}

func json2Bytes(data map[string]interface{}) (*[]byte, error) {
	b, err := json.Marshal(data)
	if err != nil {
		return nil, fmt.Errorf("Failed to encode JSON")
	}

	return &b, nil
}

type SelectResponse struct {
	results *Collection
	status  int
	qtime   int
}

type UpdateResponse struct {
	success bool
}

type ErrorResponse struct {
	message string
	status  int
}

type Connection struct {
	url *url.URL
}

func NewConnection(solrUrl string) (*Connection, error) {
	u, err := url.Parse(solrUrl)
	if err != nil {
		return nil, err
	}

	return &Connection{url: u}, nil
}

func (c *Connection) Select(selectUrl string) (*SelectResponse, error) {
	return nil, nil
}

func (c *Connection) Update(data map[string]interface{}) (*UpdateResponse, error) {
	b, err := json2Bytes(data)
	if err != nil {
		return nil, err
	}
	r, err := HTTPPost(c.url.String(), b, nil)
	if err != nil || r == nil {
		return nil, err
	}
	resp, err := bytes2Json(&r)
	if err != nil {
		return nil, err
	}
	// check error in resp
	_ = resp

	return &UpdateResponse{true}, nil
}

func (c *Connection) Commit() (*UpdateResponse, error) {
	return nil, nil
}

func (c *Connection) Optimize() (*UpdateResponse, error) {
	return nil, nil
}

func (c *Connection) Rollback() (*UpdateResponse, error) {
	return nil, nil
}
<|endoftext|>


<commit_before>// Copyright 2017 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 app

import (
	"bytes"
	"errors"
	"fmt"
	"html/template"
	"io/ioutil"
	"net/http"
	"path/filepath"
	"sort"
	"strconv"
	"strings"
	"unicode"

	"golang.org/x/perf/benchstat"
	"golang.org/x/perf/storage/benchfmt"
	"golang.org/x/perf/storage/query"
)

// A resultGroup holds a list of results and tracks the distinct labels found in that list.
type resultGroup struct {
	// The (partial) query string that resulted in this group.
	Q string
	// Raw list of results.
	results []*benchfmt.Result
	// LabelValues is the count of results found with each distinct (key, value) pair found in labels.
	// A value of "" counts results missing that key.
	LabelValues map[string]valueSet
}

// add adds res to the resultGroup.
func (g *resultGroup) add(res *benchfmt.Result) {
	g.results = append(g.results, res)
	if g.LabelValues == nil {
		g.LabelValues = make(map[string]valueSet)
	}
	for k, v := range res.Labels {
		if g.LabelValues[k] == nil {
			g.LabelValues[k] = make(valueSet)
			if len(g.results) > 1 {
				g.LabelValues[k][""] = len(g.results) - 1
			}
		}
		g.LabelValues[k][v]++
	}
	for k := range g.LabelValues {
		if res.Labels[k] == "" {
			g.LabelValues[k][""]++
		}
	}
}

// splitOn returns a new set of groups sharing a common value for key.
func (g *resultGroup) splitOn(key string) []*resultGroup {
	groups := make(map[string]*resultGroup)
	var values []string
	for _, res := range g.results {
		value := res.Labels[key]
		if groups[value] == nil {
			groups[value] = &resultGroup{Q: key + ":" + value}
			values = append(values, value)
		}
		groups[value].add(res)
	}

	sort.Strings(values)
	var out []*resultGroup
	for _, value := range values {
		out = append(out, groups[value])
	}
	return out
}

// valueSet is a set of values and the number of results with each value.
type valueSet map[string]int

// valueCount and byCount are used for sorting a valueSet
type valueCount struct {
	Value string
	Count int
}
type byCount []valueCount

func (s byCount) Len() int      { return len(s) }
func (s byCount) Swap(i, j int) { s[i], s[j] = s[j], s[i] }

func (s byCount) Less(i, j int) bool {
	if s[i].Count != s[j].Count {
		return s[i].Count > s[j].Count
	}
	return s[i].Value < s[j].Value
}

// TopN returns a slice containing n valueCount entries, and if any labels were omitted, an extra entry with value "…".
func (vs valueSet) TopN(n int) []valueCount {
	var s []valueCount
	var total int
	for v, count := range vs {
		s = append(s, valueCount{v, count})
		total += count
	}
	sort.Sort(byCount(s))
	out := s
	if len(out) > n {
		out = s[:n]
	}
	if len(out) < len(s) {
		var outTotal int
		for _, vc := range out {
			outTotal += vc.Count
		}
		out = append(out, valueCount{"…", total - outTotal})
	}
	return out
}

// addToQuery returns a new query string with add applied as a filter.
func addToQuery(query, add string) string {
	if strings.ContainsAny(add, " \t\\\"") {
		add = strings.Replace(add, `\`, `\\`, -1)
		add = strings.Replace(add, `"`, `\"`, -1)
		add = `"` + add + `"`
	}
	if strings.Contains(query, "|") {
		return add + " " + query
	}
	return add + " | " + query
}

// compare handles queries that require comparison of the groups in the query.
func (a *App) compare(w http.ResponseWriter, r *http.Request) {
	if err := r.ParseForm(); err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	q := r.Form.Get("q")

	tmpl, err := ioutil.ReadFile(filepath.Join(a.BaseDir, "template/compare.html"))
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	t, err := template.New("main").Funcs(template.FuncMap{
		"addToQuery": addToQuery,
	}).Parse(string(tmpl))
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	data := a.compareQuery(q)

	w.Header().Set("Content-Type", "text/html; charset=utf-8")
	if err := t.Execute(w, data); err != nil {
		http.Error(w, err.Error(), 500)
		return
	}
}

type compareData struct {
	Q            string
	Error        string
	Benchstat    template.HTML
	Groups       []*resultGroup
	Labels       map[string]bool
	CommonLabels benchfmt.Labels
}

// queryKeys returns the keys that are exact-matched by q.
func queryKeys(q string) map[string]bool {
	out := make(map[string]bool)
	for _, part := range query.SplitWords(q) {
		// TODO(quentin): This func is shared with db.go; refactor?
		i := strings.IndexFunc(part, func(r rune) bool {
			return r == ':' || r == '>' || r == '<' || unicode.IsSpace(r) || unicode.IsUpper(r)
		})
		if i >= 0 && part[i] == ':' {
			out[part[:i]] = true
		}
	}
	return out
}

// elideKeyValues returns content, a benchmark format line, with the
// values of any keys in keys elided.
func elideKeyValues(content string, keys map[string]bool) string {
	var end string
	if i := strings.IndexFunc(content, unicode.IsSpace); i >= 0 {
		content, end = content[:i], content[i:]
	}
	// Check for gomaxprocs value
	if i := strings.LastIndex(content, "-"); i >= 0 {
		_, err := strconv.Atoi(content[i+1:])
		if err == nil {
			if keys["gomaxprocs"] {
				content, end = content[:i], "-*"+end
			} else {
				content, end = content[:i], content[i:]+end
			}
		}
	}
	parts := strings.Split(content, "/")
	for i, part := range parts {
		if equals := strings.Index(part, "="); equals >= 0 {
			if keys[part[:equals]] {
				parts[i] = part[:equals] + "=*"
			}
		} else if i == 0 {
			if keys["name"] {
				parts[i] = "Benchmark*"
			}
		} else if keys[fmt.Sprintf("sub%d", i)] {
			parts[i] = "*"
		}
	}
	return strings.Join(parts, "/") + end
}

// fetchCompareResults fetches the matching results for a given query string.
// The results will be grouped into one or more groups based on either the query string or heuristics.
func (a *App) fetchCompareResults(q string) ([]*resultGroup, error) {
	// Parse query
	prefix, queries := parseQueryString(q)

	// Send requests
	// TODO(quentin): Issue requests in parallel?
	var groups []*resultGroup
	var found int
	for _, qPart := range queries {
		keys := queryKeys(qPart)
		group := &resultGroup{Q: qPart}
		if prefix != "" {
			qPart = prefix + " " + qPart
		}
		res := a.StorageClient.Query(qPart)
		for res.Next() {
			result := res.Result()
			result.Content = elideKeyValues(result.Content, keys)
			group.add(result)
			found++
		}
		err := res.Err()
		res.Close()
		if err != nil {
			// TODO: If the query is invalid, surface that to the user.
			return nil, err
		}
		groups = append(groups, group)
	}

	if found == 0 {
		return nil, errors.New("no results matched the query string")
	}

	// Attempt to automatically split results.
	if len(groups) == 1 {
		group := groups[0]
		// Matching a single upload with multiple files -> split by file
		if len(group.LabelValues["upload"]) == 1 && len(group.LabelValues["upload-part"]) > 1 {
			groups = group.splitOn("upload-part")
		}
	}

	return groups, nil
}

func (a *App) compareQuery(q string) *compareData {
	if len(q) == 0 {
		return &compareData{}
	}

	groups, err := a.fetchCompareResults(q)
	if err != nil {
		return &compareData{
			Q:     q,
			Error: err.Error(),
		}
	}

	var buf bytes.Buffer
	// Compute benchstat
	c := new(benchstat.Collection)
	for _, g := range groups {
		c.AddResults(g.Q, g.results)
	}
	benchstat.FormatHTML(&buf, c.Tables())

	// Prepare struct for template.
	labels := make(map[string]bool)
	// commonLabels are the key: value of every label that has an
	// identical value on every result.
	commonLabels := make(benchfmt.Labels)
	// Scan the first group for common labels.
	for k, vs := range groups[0].LabelValues {
		if len(vs) == 1 {
			for v := range vs {
				commonLabels[k] = v
			}
		}
	}
	// Remove any labels not common in later groups.
	for _, g := range groups[1:] {
		for k, v := range commonLabels {
			if len(g.LabelValues[k]) != 1 || g.LabelValues[k][v] == 0 {
				delete(commonLabels, k)
			}
		}
	}
	// List all labels present and not in commonLabels.
	for _, g := range groups {
		for k := range g.LabelValues {
			if commonLabels[k] != "" {
				continue
			}
			labels[k] = true
		}
	}
	data := &compareData{
		Q:            q,
		Benchstat:    template.HTML(buf.String()),
		Groups:       groups,
		Labels:       labels,
		CommonLabels: commonLabels,
	}
	return data
}

// textCompare is called if benchsave is requesting a text-only analysis.
func (a *App) textCompare(w http.ResponseWriter, r *http.Request) {
	if err := r.ParseForm(); err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	w.Header().Set("Content-Type", "text/plain; charset=utf-8")

	q := r.Form.Get("q")

	groups, err := a.fetchCompareResults(q)
	if err != nil {
		// TODO(quentin): Should we serve this with a 500 or 404? This means the query was invalid or had no results.
		fmt.Fprintf(w, "unable to analyze results: %v", err)
	}

	// Compute benchstat
	c := new(benchstat.Collection)
	for _, g := range groups {
		c.AddResults(g.Q, g.results)
	}
	benchstat.FormatText(w, c.Tables())
}
<commit_msg>analysis/app: show the geomean<commit_after>// Copyright 2017 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 app

import (
	"bytes"
	"errors"
	"fmt"
	"html/template"
	"io/ioutil"
	"net/http"
	"path/filepath"
	"sort"
	"strconv"
	"strings"
	"unicode"

	"golang.org/x/perf/benchstat"
	"golang.org/x/perf/storage/benchfmt"
	"golang.org/x/perf/storage/query"
)

// A resultGroup holds a list of results and tracks the distinct labels found in that list.
type resultGroup struct {
	// The (partial) query string that resulted in this group.
	Q string
	// Raw list of results.
	results []*benchfmt.Result
	// LabelValues is the count of results found with each distinct (key, value) pair found in labels.
	// A value of "" counts results missing that key.
	LabelValues map[string]valueSet
}

// add adds res to the resultGroup.
func (g *resultGroup) add(res *benchfmt.Result) {
	g.results = append(g.results, res)
	if g.LabelValues == nil {
		g.LabelValues = make(map[string]valueSet)
	}
	for k, v := range res.Labels {
		if g.LabelValues[k] == nil {
			g.LabelValues[k] = make(valueSet)
			if len(g.results) > 1 {
				g.LabelValues[k][""] = len(g.results) - 1
			}
		}
		g.LabelValues[k][v]++
	}
	for k := range g.LabelValues {
		if res.Labels[k] == "" {
			g.LabelValues[k][""]++
		}
	}
}

// splitOn returns a new set of groups sharing a common value for key.
func (g *resultGroup) splitOn(key string) []*resultGroup {
	groups := make(map[string]*resultGroup)
	var values []string
	for _, res := range g.results {
		value := res.Labels[key]
		if groups[value] == nil {
			groups[value] = &resultGroup{Q: key + ":" + value}
			values = append(values, value)
		}
		groups[value].add(res)
	}

	sort.Strings(values)
	var out []*resultGroup
	for _, value := range values {
		out = append(out, groups[value])
	}
	return out
}

// valueSet is a set of values and the number of results with each value.
type valueSet map[string]int

// valueCount and byCount are used for sorting a valueSet
type valueCount struct {
	Value string
	Count int
}
type byCount []valueCount

func (s byCount) Len() int      { return len(s) }
func (s byCount) Swap(i, j int) { s[i], s[j] = s[j], s[i] }

func (s byCount) Less(i, j int) bool {
	if s[i].Count != s[j].Count {
		return s[i].Count > s[j].Count
	}
	return s[i].Value < s[j].Value
}

// TopN returns a slice containing n valueCount entries, and if any labels were omitted, an extra entry with value "…".
func (vs valueSet) TopN(n int) []valueCount {
	var s []valueCount
	var total int
	for v, count := range vs {
		s = append(s, valueCount{v, count})
		total += count
	}
	sort.Sort(byCount(s))
	out := s
	if len(out) > n {
		out = s[:n]
	}
	if len(out) < len(s) {
		var outTotal int
		for _, vc := range out {
			outTotal += vc.Count
		}
		out = append(out, valueCount{"…", total - outTotal})
	}
	return out
}

// addToQuery returns a new query string with add applied as a filter.
func addToQuery(query, add string) string {
	if strings.ContainsAny(add, " \t\\\"") {
		add = strings.Replace(add, `\`, `\\`, -1)
		add = strings.Replace(add, `"`, `\"`, -1)
		add = `"` + add + `"`
	}
	if strings.Contains(query, "|") {
		return add + " " + query
	}
	return add + " | " + query
}

// compare handles queries that require comparison of the groups in the query.
func (a *App) compare(w http.ResponseWriter, r *http.Request) {
	if err := r.ParseForm(); err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	q := r.Form.Get("q")

	tmpl, err := ioutil.ReadFile(filepath.Join(a.BaseDir, "template/compare.html"))
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	t, err := template.New("main").Funcs(template.FuncMap{
		"addToQuery": addToQuery,
	}).Parse(string(tmpl))
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	data := a.compareQuery(q)

	w.Header().Set("Content-Type", "text/html; charset=utf-8")
	if err := t.Execute(w, data); err != nil {
		http.Error(w, err.Error(), 500)
		return
	}
}

type compareData struct {
	Q            string
	Error        string
	Benchstat    template.HTML
	Groups       []*resultGroup
	Labels       map[string]bool
	CommonLabels benchfmt.Labels
}

// queryKeys returns the keys that are exact-matched by q.
func queryKeys(q string) map[string]bool {
	out := make(map[string]bool)
	for _, part := range query.SplitWords(q) {
		// TODO(quentin): This func is shared with db.go; refactor?
		i := strings.IndexFunc(part, func(r rune) bool {
			return r == ':' || r == '>' || r == '<' || unicode.IsSpace(r) || unicode.IsUpper(r)
		})
		if i >= 0 && part[i] == ':' {
			out[part[:i]] = true
		}
	}
	return out
}

// elideKeyValues returns content, a benchmark format line, with the
// values of any keys in keys elided.
func elideKeyValues(content string, keys map[string]bool) string {
	var end string
	if i := strings.IndexFunc(content, unicode.IsSpace); i >= 0 {
		content, end = content[:i], content[i:]
	}
	// Check for gomaxprocs value
	if i := strings.LastIndex(content, "-"); i >= 0 {
		_, err := strconv.Atoi(content[i+1:])
		if err == nil {
			if keys["gomaxprocs"] {
				content, end = content[:i], "-*"+end
			} else {
				content, end = content[:i], content[i:]+end
			}
		}
	}
	parts := strings.Split(content, "/")
	for i, part := range parts {
		if equals := strings.Index(part, "="); equals >= 0 {
			if keys[part[:equals]] {
				parts[i] = part[:equals] + "=*"
			}
		} else if i == 0 {
			if keys["name"] {
				parts[i] = "Benchmark*"
			}
		} else if keys[fmt.Sprintf("sub%d", i)] {
			parts[i] = "*"
		}
	}
	return strings.Join(parts, "/") + end
}

// fetchCompareResults fetches the matching results for a given query string.
// The results will be grouped into one or more groups based on either the query string or heuristics.
func (a *App) fetchCompareResults(q string) ([]*resultGroup, error) {
	// Parse query
	prefix, queries := parseQueryString(q)

	// Send requests
	// TODO(quentin): Issue requests in parallel?
	var groups []*resultGroup
	var found int
	for _, qPart := range queries {
		keys := queryKeys(qPart)
		group := &resultGroup{Q: qPart}
		if prefix != "" {
			qPart = prefix + " " + qPart
		}
		res := a.StorageClient.Query(qPart)
		for res.Next() {
			result := res.Result()
			result.Content = elideKeyValues(result.Content, keys)
			group.add(result)
			found++
		}
		err := res.Err()
		res.Close()
		if err != nil {
			// TODO: If the query is invalid, surface that to the user.
			return nil, err
		}
		groups = append(groups, group)
	}

	if found == 0 {
		return nil, errors.New("no results matched the query string")
	}

	// Attempt to automatically split results.
	if len(groups) == 1 {
		group := groups[0]
		// Matching a single upload with multiple files -> split by file
		if len(group.LabelValues["upload"]) == 1 && len(group.LabelValues["upload-part"]) > 1 {
			groups = group.splitOn("upload-part")
		}
	}

	return groups, nil
}

func (a *App) compareQuery(q string) *compareData {
	if len(q) == 0 {
		return &compareData{}
	}

	groups, err := a.fetchCompareResults(q)
	if err != nil {
		return &compareData{
			Q:     q,
			Error: err.Error(),
		}
	}

	var buf bytes.Buffer
	// Compute benchstat
	c := &benchstat.Collection{
		AddGeoMean: true,
	}
	for _, g := range groups {
		c.AddResults(g.Q, g.results)
	}
	benchstat.FormatHTML(&buf, c.Tables())

	// Prepare struct for template.
	labels := make(map[string]bool)
	// commonLabels are the key: value of every label that has an
	// identical value on every result.
	commonLabels := make(benchfmt.Labels)
	// Scan the first group for common labels.
	for k, vs := range groups[0].LabelValues {
		if len(vs) == 1 {
			for v := range vs {
				commonLabels[k] = v
			}
		}
	}
	// Remove any labels not common in later groups.
	for _, g := range groups[1:] {
		for k, v := range commonLabels {
			if len(g.LabelValues[k]) != 1 || g.LabelValues[k][v] == 0 {
				delete(commonLabels, k)
			}
		}
	}
	// List all labels present and not in commonLabels.
	for _, g := range groups {
		for k := range g.LabelValues {
			if commonLabels[k] != "" {
				continue
			}
			labels[k] = true
		}
	}
	data := &compareData{
		Q:            q,
		Benchstat:    template.HTML(buf.String()),
		Groups:       groups,
		Labels:       labels,
		CommonLabels: commonLabels,
	}
	return data
}

// textCompare is called if benchsave is requesting a text-only analysis.
func (a *App) textCompare(w http.ResponseWriter, r *http.Request) {
	if err := r.ParseForm(); err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	w.Header().Set("Content-Type", "text/plain; charset=utf-8")

	q := r.Form.Get("q")

	groups, err := a.fetchCompareResults(q)
	if err != nil {
		// TODO(quentin): Should we serve this with a 500 or 404? This means the query was invalid or had no results.
		fmt.Fprintf(w, "unable to analyze results: %v", err)
	}

	// Compute benchstat
	c := new(benchstat.Collection)
	for _, g := range groups {
		c.AddResults(g.Q, g.results)
	}
	benchstat.FormatText(w, c.Tables())
}
<|endoftext|>


<commit_before><commit_msg>added function to return Ints from an interface<commit_after><|endoftext|>


<commit_before>package goFlags

import (
	"fmt"
	"os"
	"testing"
)

type testStruct struct {
	A int    `flag:"A" flagDefault:"100"`
	B string `flag:"B" flagDefault:"200"`
	C string
	N string `flag:"-"`
	p string
	S testSub `flag:"S"`
}

type testSub struct {
	A int        `flag:"A" flagDefault:"300"`
	B string     `flag:"C" flagDefault:"400"`
	S testSubSub `flag:"S"`
}
type testSubSub struct {
	A int    `flag:"A" flagDefault:"500"`
	B string `flag:"S" flagDefault:"600"`
}

func TestParse(t *testing.T) {

	//os.Args = []string{"noop", "-flag1=val1", "arg1", "arg2"}
	//os.Args = []string{"program", "-h"}

	os.Args = []string{
		"program",
		"-a=8888",
		"-b=TEST",
		"-s_s_a=9999",
	}

	s := &testStruct{A: 1, S: testSub{A: 1, B: "2"}}

	err := Parse(s)
	if err != nil {
		t.Fatal(err)
	}

	fmt.Printf("\n\nTestParseTags: %#v\n\n", s)

}
<commit_msg>test preset function<commit_after>package goFlags

import (
	"fmt"
	"os"
	"testing"
)

type testStruct struct {
	A int    `flag:"A" flagDefault:"100"`
	B string `flag:"B" flagDefault:"200"`
	C string
	N string `flag:"-"`
	p string
	S testSub `flag:"S"`
}

type testSub struct {
	A int        `flag:"A" flagDefault:"300"`
	B string     `flag:"C" flagDefault:"400"`
	S testSubSub `flag:"S"`
}
type testSubSub struct {
	A int    `flag:"A" flagDefault:"500"`
	B string `flag:"S" flagDefault:"600"`
}

func TestParse(t *testing.T) {

	//os.Args = []string{"noop", "-flag1=val1", "arg1", "arg2"}
	//os.Args = []string{"program", "-h"}

	os.Args = []string{
		"program",
		"-a=8888",
		"-b=TEST",
		"-s_s_a=9999",
	}

	s := &testStruct{A: 1, S: testSub{A: 1, B: "2"}}

	Preserve = false
	err := Parse(s)
	if err != nil {
		t.Fatal(err)
	}

	fmt.Printf("\n\nTestParseTags: %#v\n\n", s)

	Reset()
	err = Parse(s)
	if err != nil {
		t.Fatal(err)
	}

	fmt.Printf("\n\nTestParseTags: %#v\n\n", s)
}

func TestPreserve(t *testing.T) {

	//os.Args = []string{"noop", "-flag1=val1", "arg1", "arg2"}
	//os.Args = []string{"program", "-h"}

	os.Args = []string{
		"program",
		"-a=8888",
		"-b=TEST",
		"-s_s_a=9999",
	}

	s := &testStruct{A: 1, S: testSub{A: 1, B: "2"}}

	Reset()
	Preserve = true
	err := Parse(s)
	if err != nil {
		t.Fatal(err)
	}

	fmt.Printf("\n\nTestPreserve: %#v\n\n", s)
}
<|endoftext|>


<commit_before>package graph

// Copyright ©2012 Dan Kortschak <dan.kortschak@adelaide.edu.au>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

import (
	"math"
	"runtime"
	"sync"
)

// FIXME Use Index() instead of ID() on edges and nodes - this requires a change to node.go

const sqrt2 = 1.4142135623730950488016887242096980785696718753769480

var MaxProcs = runtime.GOMAXPROCS(0)

func FastRandMinCut(g *Undirected, iter int) (c []*Edge, w float64) {
	k := newKargerR(g)
	k.init()
	w = math.Inf(1)
	for i := 0; i < iter; i++ {
		k.fastRandMinCut()
		if k.w < w {
			w = k.w
			c = k.c
		}
	}

	return
}

// parallelised outside the recursion tree

func FastRandMinCutPar(g *Undirected, iter, thread int) (c []*Edge, w float64) {
	if thread > MaxProcs {
		thread = MaxProcs
	}
	if thread > iter {
		thread = iter
	}
	iter, rem := iter/thread+1, iter%thread

	type r struct {
		c []*Edge
		w float64
	}
	rs := make([]*r, thread)

	wg := &sync.WaitGroup{}
	for j := 0; j < thread; j++ {
		if rem == 0 {
			iter--
		}
		if rem >= 0 {
			rem--
		}
		wg.Add(1)
		go func(j, iter int) {
			defer wg.Done()
			k := newKargerR(g)
			k.init()
			var (
				w = math.Inf(1)
				c []*Edge
			)
			for i := 0; i < iter; i++ {
				k.fastRandMinCut()
				if k.w < w {
					w = k.w
					c = k.c
				}
			}

			rs[j] = &r{c, w}
		}(j, iter)
	}

	w = math.Inf(1)
	wg.Wait()
	for _, subr := range rs {
		if subr.w < w {
			w = subr.w
			c = subr.c
		}
	}

	return
}

type kargerR struct {
	g     *Undirected
	order int
	ind   []super
	sel   Selector
	c     []*Edge
	w     float64
}

func newKargerR(g *Undirected) *kargerR {
	return &kargerR{
		g:   g,
		ind: make([]super, g.NextNodeID()),
		sel: make(Selector, g.Size()),
	}
}

func (self *kargerR) init() {
	self.order = self.g.Order()
	for i := range self.ind {
		self.ind[i].label = -1
		self.ind[i].nodes = nil
	}
	for _, n := range self.g.Nodes() {
		id := n.ID()
		self.ind[id].label = id
	}
	for i, e := range self.g.Edges() {
		self.sel[i] = WeightedItem{Index: e.ID(), Weight: e.Weight()}
	}
	self.sel.Init()
}

func (self *kargerR) copy(t *kargerR) {
	self.order = t.order
	copy(self.sel, t.sel)
	for i, n := range t.ind {
		s := &self.ind[i]
		s.label = n.label
		if n.nodes != nil {
			s.nodes = make([]int, len(n.nodes))
			copy(s.nodes, n.nodes)
		}
	}
}

func (self *kargerR) fastRandMinCut() {
	if self.order <= 6 {
		self.randCompact(2)
		return
	}

	t := int(math.Ceil(float64(self.order)/sqrt2 + 1))

	sub := []*kargerR{self, newKargerR(self.g)}
	sub[1].copy(self)
	for i := range sub {
		sub[i].randContract(t)
		sub[i].fastRandMinCut()
	}

	if sub[0].w < sub[1].w {
		*self = *sub[0]
		return
	}
	*self = *sub[1]
}

func (self *kargerR) randContract(k int) {
	for self.order > k {
		id, err := self.sel.Select()
		if err != nil {
			break
		}

		e := self.g.Edge(id)
		if self.loop(e) {
			continue
		}

		hid, tid := e.Head().ID(), e.Tail().ID()
		hl, tl := self.ind[hid].label, self.ind[tid].label
		if len(self.ind[hl].nodes) < len(self.ind[tl].nodes) {
			hid, tid = tid, hid
			hl, tl = tl, hl
		}

		if self.ind[hl].nodes == nil {
			self.ind[hl].nodes = []int{hid}
		}
		if self.ind[tl].nodes == nil {
			self.ind[hl].nodes = append(self.ind[hl].nodes, tid)
		} else {
			self.ind[hl].nodes = append(self.ind[hl].nodes, self.ind[tl].nodes...)
			self.ind[tl].nodes = nil
		}
		for _, i := range self.ind[hl].nodes {
			self.ind[i].label = self.ind[hid].label
		}

		self.order--
	}
}

func (self *kargerR) randCompact(k int) {
	for self.order > k {
		id, err := self.sel.Select()
		if err != nil {
			break
		}

		e := self.g.Edge(id)
		if self.loop(e) {
			continue
		}

		hid, tid := e.Head().ID(), e.Tail().ID()
		hl, tl := self.ind[hid].label, self.ind[tid].label
		if len(self.ind[hl].nodes) < len(self.ind[tl].nodes) {
			hid, tid = tid, hid
			hl, tl = tl, hl
		}

		if self.ind[hl].nodes == nil {
			self.ind[hl].nodes = []int{hid}
		}
		if self.ind[tl].nodes == nil {
			self.ind[hl].nodes = append(self.ind[hl].nodes, tid)
		} else {
			self.ind[hl].nodes = append(self.ind[hl].nodes, self.ind[tl].nodes...)
			self.ind[tl].nodes = nil
		}
		for _, i := range self.ind[hl].nodes {
			self.ind[i].label = self.ind[hid].label
		}

		self.order--
	}

	self.c, self.w = []*Edge{}, 0
	for _, e := range self.g.Edges() {
		if self.loop(e) {
			continue
		}
		self.c = append(self.c, e)
		self.w += e.Weight()
	}
}

func (self *kargerR) loop(e *Edge) bool {
	return self.ind[e.Head().ID()].label == self.ind[e.Tail().ID()].label
}

// parallelised within the recursion tree

func ParFastRandMinCut(g *Undirected, iter, threads int) (c []*Edge, w float64) {
	k := newKargerRP(g)
	k.split = bits(threads)
	if k.split == 0 {
		k.split = -1
	}
	k.init()
	w = math.Inf(1)
	for i := 0; i < iter; i++ {
		k.fastRandMinCut()
		if k.w < w {
			w = k.w
			c = k.c
		}
	}

	return
}

type kargerRP struct {
	g     *Undirected
	order int
	ind   []super
	sel   Selector
	c     []*Edge
	w     float64
	depth int
	split int
}

func bits(i int) (b int) {
	for ; i > 1; i >>= 1 {
		b++
	}
	return
}

func newKargerRP(g *Undirected) *kargerRP {
	return &kargerRP{
		g:   g,
		ind: make([]super, g.NextNodeID()),
		sel: make(Selector, g.Size()),
	}
}

func (self *kargerRP) init() {
	self.order = self.g.Order()
	for i := range self.ind {
		self.ind[i].label = -1
		self.ind[i].nodes = nil
	}
	for _, n := range self.g.Nodes() {
		id := n.ID()
		self.ind[id].label = id
	}
	for i, e := range self.g.Edges() {
		self.sel[i] = WeightedItem{Index: e.ID(), Weight: e.Weight()}
	}
	self.sel.Init()
}

func (self *kargerRP) copy(t *kargerRP) {
	self.order = t.order
	self.depth = t.depth
	self.split = t.split
	copy(self.sel, t.sel)
	for i, n := range t.ind {
		s := &self.ind[i]
		s.label = n.label
		if n.nodes != nil {
			s.nodes = make([]int, len(n.nodes))
			copy(s.nodes, n.nodes)
		}
	}
}

func (self *kargerRP) fastRandMinCut() {
	self.depth++
	if self.order <= 6 {
		self.randCompact(2)
		return
	}

	t := int(math.Ceil(float64(self.order)/sqrt2 + 1))

	var wg *sync.WaitGroup
	if self.depth < self.split {
		wg = &sync.WaitGroup{}
	}

	sub := []*kargerRP{self, newKargerRP(self.g)}
	sub[1].copy(self)
	for i := range sub {
		if wg != nil {
			wg.Add(1)
			go func(i int) {
				defer wg.Done()
				sub[i].randContract(t)
				sub[i].fastRandMinCut()
			}(i)
		} else {
			sub[i].randContract(t)
			sub[i].fastRandMinCut()
		}
	}

	if wg != nil {
		wg.Wait()
	}

	if sub[0].w < sub[1].w {
		*self = *sub[0]
		return
	}
	*self = *sub[1]
}

func (self *kargerRP) randContract(k int) {
	for self.order > k {
		id, err := self.sel.Select()
		if err != nil {
			break
		}

		e := self.g.Edge(id)
		if self.loop(e) {
			continue
		}

		hid, tid := e.Head().ID(), e.Tail().ID()
		hl, tl := self.ind[hid].label, self.ind[tid].label
		if len(self.ind[hl].nodes) < len(self.ind[tl].nodes) {
			hid, tid = tid, hid
			hl, tl = tl, hl
		}

		if self.ind[hl].nodes == nil {
			self.ind[hl].nodes = []int{hid}
		}
		if self.ind[tl].nodes == nil {
			self.ind[hl].nodes = append(self.ind[hl].nodes, tid)
		} else {
			self.ind[hl].nodes = append(self.ind[hl].nodes, self.ind[tl].nodes...)
			self.ind[tl].nodes = nil
		}
		for _, i := range self.ind[hl].nodes {
			self.ind[i].label = self.ind[hid].label
		}

		self.order--
	}
}

func (self *kargerRP) randCompact(k int) {
	for self.order > k {
		id, err := self.sel.Select()
		if err != nil {
			break
		}

		e := self.g.Edge(id)
		if self.loop(e) {
			continue
		}

		hid, tid := e.Head().ID(), e.Tail().ID()
		hl, tl := self.ind[hid].label, self.ind[tid].label
		if len(self.ind[hl].nodes) < len(self.ind[tl].nodes) {
			hid, tid = tid, hid
			hl, tl = tl, hl
		}

		if self.ind[hl].nodes == nil {
			self.ind[hl].nodes = []int{hid}
		}
		if self.ind[tl].nodes == nil {
			self.ind[hl].nodes = append(self.ind[hl].nodes, tid)
		} else {
			self.ind[hl].nodes = append(self.ind[hl].nodes, self.ind[tl].nodes...)
			self.ind[tl].nodes = nil
		}
		for _, i := range self.ind[hl].nodes {
			self.ind[i].label = self.ind[hid].label
		}

		self.order--
	}

	self.c, self.w = []*Edge{}, 0
	for _, e := range self.g.Edges() {
		if self.loop(e) {
			continue
		}
		self.c = append(self.c, e)
		self.w += e.Weight()
	}
}

func (self *kargerRP) loop(e *Edge) bool {
	return self.ind[e.Head().ID()].label == self.ind[e.Tail().ID()].label
}
<commit_msg>Performance egression due to previous commit<commit_after>package graph

// Copyright ©2012 Dan Kortschak <dan.kortschak@adelaide.edu.au>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

import (
	"math"
	"runtime"
	"sync"
)

// FIXME Use Index() instead of ID() on edges and nodes - this requires a change to node.go

const sqrt2 = 1.4142135623730950488016887242096980785696718753769480

var MaxProcs = runtime.GOMAXPROCS(0)

func FastRandMinCut(g *Undirected, iter int) (c []*Edge, w float64) {
	k := newKargerR(g)
	k.init()
	w = math.Inf(1)
	for i := 0; i < iter; i++ {
		k.fastRandMinCut()
		if k.w < w {
			w = k.w
			c = k.c
		}
	}

	return
}

// parallelised outside the recursion tree

func FastRandMinCutPar(g *Undirected, iter, thread int) (c []*Edge, w float64) {
	if thread > MaxProcs {
		thread = MaxProcs
	}
	if thread > iter {
		thread = iter
	}
	iter, rem := iter/thread+1, iter%thread

	type r struct {
		c []*Edge
		w float64
	}
	rs := make([]*r, thread)

	wg := &sync.WaitGroup{}
	for j := 0; j < thread; j++ {
		if rem == 0 {
			iter--
		}
		if rem >= 0 {
			rem--
		}
		wg.Add(1)
		go func(j, iter int) {
			defer wg.Done()
			k := newKargerR(g)
			k.init()
			var (
				w = math.Inf(1)
				c []*Edge
			)
			for i := 0; i < iter; i++ {
				k.fastRandMinCut()
				if k.w < w {
					w = k.w
					c = k.c
				}
			}

			rs[j] = &r{c, w}
		}(j, iter)
	}

	w = math.Inf(1)
	wg.Wait()
	for _, subr := range rs {
		if subr.w < w {
			w = subr.w
			c = subr.c
		}
	}

	return
}

type kargerR struct {
	g     *Undirected
	order int
	ind   []super
	sel   Selector
	c     []*Edge
	w     float64
}

func newKargerR(g *Undirected) *kargerR {
	return &kargerR{
		g:   g,
		ind: make([]super, g.NextNodeID()),
		sel: make(Selector, g.Size()),
	}
}

func (self *kargerR) init() {
	self.order = self.g.Order()
	for i := range self.ind {
		self.ind[i].label = -1
		self.ind[i].nodes = nil
	}
	for _, n := range self.g.Nodes() {
		id := n.ID()
		self.ind[id].label = id
	}
	for i, e := range self.g.Edges() {
		self.sel[i] = WeightedItem{Index: e.ID(), Weight: e.Weight()}
	}
	self.sel.Init()
}

func (self *kargerR) clone() (c *kargerR) {
	c = &kargerR{
		g:     self.g,
		ind:   make([]super, self.g.NextNodeID()),
		sel:   make(Selector, self.g.Size()),
		order: self.order,
	}

	copy(c.sel, self.sel)
	for i, n := range self.ind {
		s := &c.ind[i]
		s.label = n.label
		if n.nodes != nil {
			s.nodes = make([]int, len(n.nodes))
			copy(s.nodes, n.nodes)
		}
	}

	return
}

func (self *kargerR) fastRandMinCut() {
	if self.order <= 6 {
		self.randCompact(2)
		return
	}

	t := int(math.Ceil(float64(self.order)/sqrt2 + 1))

	sub := []*kargerR{self, self.clone()}
	for i := range sub {
		sub[i].randContract(t)
		sub[i].fastRandMinCut()
	}

	if sub[0].w < sub[1].w {
		*self = *sub[0]
		return
	}
	*self = *sub[1]
}

func (self *kargerR) randContract(k int) {
	for self.order > k {
		id, err := self.sel.Select()
		if err != nil {
			break
		}

		e := self.g.Edge(id)
		if self.loop(e) {
			continue
		}

		hid, tid := e.Head().ID(), e.Tail().ID()
		hl, tl := self.ind[hid].label, self.ind[tid].label
		if len(self.ind[hl].nodes) < len(self.ind[tl].nodes) {
			hid, tid = tid, hid
			hl, tl = tl, hl
		}

		if self.ind[hl].nodes == nil {
			self.ind[hl].nodes = []int{hid}
		}
		if self.ind[tl].nodes == nil {
			self.ind[hl].nodes = append(self.ind[hl].nodes, tid)
		} else {
			self.ind[hl].nodes = append(self.ind[hl].nodes, self.ind[tl].nodes...)
			self.ind[tl].nodes = nil
		}
		for _, i := range self.ind[hl].nodes {
			self.ind[i].label = self.ind[hid].label
		}

		self.order--
	}
}

func (self *kargerR) randCompact(k int) {
	for self.order > k {
		id, err := self.sel.Select()
		if err != nil {
			break
		}

		e := self.g.Edge(id)
		if self.loop(e) {
			continue
		}

		hid, tid := e.Head().ID(), e.Tail().ID()
		hl, tl := self.ind[hid].label, self.ind[tid].label
		if len(self.ind[hl].nodes) < len(self.ind[tl].nodes) {
			hid, tid = tid, hid
			hl, tl = tl, hl
		}

		if self.ind[hl].nodes == nil {
			self.ind[hl].nodes = []int{hid}
		}
		if self.ind[tl].nodes == nil {
			self.ind[hl].nodes = append(self.ind[hl].nodes, tid)
		} else {
			self.ind[hl].nodes = append(self.ind[hl].nodes, self.ind[tl].nodes...)
			self.ind[tl].nodes = nil
		}
		for _, i := range self.ind[hl].nodes {
			self.ind[i].label = self.ind[hid].label
		}

		self.order--
	}

	self.c, self.w = []*Edge{}, 0
	for _, e := range self.g.Edges() {
		if self.loop(e) {
			continue
		}
		self.c = append(self.c, e)
		self.w += e.Weight()
	}
}

func (self *kargerR) loop(e *Edge) bool {
	return self.ind[e.Head().ID()].label == self.ind[e.Tail().ID()].label
}

// parallelised within the recursion tree

func ParFastRandMinCut(g *Undirected, iter, threads int) (c []*Edge, w float64) {
	k := newKargerRP(g)
	k.split = threads
	if k.split == 0 {
		k.split = -1
	}
	k.init()
	w = math.Inf(1)
	for i := 0; i < iter; i++ {
		k.fastRandMinCut()
		if k.w < w {
			w = k.w
			c = k.c
		}
	}

	return
}

type kargerRP struct {
	g     *Undirected
	order int
	ind   []super
	sel   Selector
	c     []*Edge
	w     float64
	count int
	split int
}

func newKargerRP(g *Undirected) *kargerRP {
	return &kargerRP{
		g:   g,
		ind: make([]super, g.NextNodeID()),
		sel: make(Selector, g.Size()),
	}
}

func (self *kargerRP) init() {
	self.order = self.g.Order()
	for i := range self.ind {
		self.ind[i].label = -1
		self.ind[i].nodes = nil
	}
	for _, n := range self.g.Nodes() {
		id := n.ID()
		self.ind[id].label = id
	}
	for i, e := range self.g.Edges() {
		self.sel[i] = WeightedItem{Index: e.ID(), Weight: e.Weight()}
	}
	self.sel.Init()
}

func (self *kargerRP) clone() (c *kargerRP) {
	c = &kargerRP{
		g:     self.g,
		ind:   make([]super, self.g.NextNodeID()),
		sel:   make(Selector, self.g.Size()),
		order: self.order,
		count: self.count,
	}

	copy(c.sel, self.sel)
	for i, n := range self.ind {
		s := &c.ind[i]
		s.label = n.label
		if n.nodes != nil {
			s.nodes = make([]int, len(n.nodes))
			copy(s.nodes, n.nodes)
		}
	}

	return
}

func (self *kargerRP) fastRandMinCut() {
	if self.order <= 6 {
		self.randCompact(2)
		return
	}

	t := int(math.Ceil(float64(self.order)/sqrt2 + 1))

	var wg *sync.WaitGroup
	if self.count < self.split {
		wg = &sync.WaitGroup{}
	}
	self.count++

	sub := []*kargerRP{self, self.clone()}
	for i := range sub {
		if wg != nil {
			wg.Add(1)
			go func(i int) {
				runtime.LockOSThread()
				defer wg.Done()
				sub[i].randContract(t)
				sub[i].fastRandMinCut()
			}(i)
		} else {
			sub[i].randContract(t)
			sub[i].fastRandMinCut()
		}
	}

	if wg != nil {
		wg.Wait()
	}

	if sub[0].w < sub[1].w {
		*self = *sub[0]
		return
	}
	*self = *sub[1]
}

func (self *kargerRP) randContract(k int) {
	for self.order > k {
		id, err := self.sel.Select()
		if err != nil {
			break
		}

		e := self.g.Edge(id)
		if self.loop(e) {
			continue
		}

		hid, tid := e.Head().ID(), e.Tail().ID()
		hl, tl := self.ind[hid].label, self.ind[tid].label
		if len(self.ind[hl].nodes) < len(self.ind[tl].nodes) {
			hid, tid = tid, hid
			hl, tl = tl, hl
		}

		if self.ind[hl].nodes == nil {
			self.ind[hl].nodes = []int{hid}
		}
		if self.ind[tl].nodes == nil {
			self.ind[hl].nodes = append(self.ind[hl].nodes, tid)
		} else {
			self.ind[hl].nodes = append(self.ind[hl].nodes, self.ind[tl].nodes...)
			self.ind[tl].nodes = nil
		}
		for _, i := range self.ind[hl].nodes {
			self.ind[i].label = self.ind[hid].label
		}

		self.order--
	}
}

func (self *kargerRP) randCompact(k int) {
	for self.order > k {
		id, err := self.sel.Select()
		if err != nil {
			break
		}

		e := self.g.Edge(id)
		if self.loop(e) {
			continue
		}

		hid, tid := e.Head().ID(), e.Tail().ID()
		hl, tl := self.ind[hid].label, self.ind[tid].label
		if len(self.ind[hl].nodes) < len(self.ind[tl].nodes) {
			hid, tid = tid, hid
			hl, tl = tl, hl
		}

		if self.ind[hl].nodes == nil {
			self.ind[hl].nodes = []int{hid}
		}
		if self.ind[tl].nodes == nil {
			self.ind[hl].nodes = append(self.ind[hl].nodes, tid)
		} else {
			self.ind[hl].nodes = append(self.ind[hl].nodes, self.ind[tl].nodes...)
			self.ind[tl].nodes = nil
		}
		for _, i := range self.ind[hl].nodes {
			self.ind[i].label = self.ind[hid].label
		}

		self.order--
	}

	self.c, self.w = []*Edge{}, 0
	for _, e := range self.g.Edges() {
		if self.loop(e) {
			continue
		}
		self.c = append(self.c, e)
		self.w += e.Weight()
	}
}

func (self *kargerRP) loop(e *Edge) bool {
	return self.ind[e.Head().ID()].label == self.ind[e.Tail().ID()].label
}
<|endoftext|>


<commit_before>package spdy

import (
  "bufio"
  "crypto/tls"
  "fmt"
  "log"
  "net/http"
  "runtime"
  "sync"
  "time"
)

type connection struct {
  sync.RWMutex
  remoteAddr         string // network address of remote side
  server             *http.Server
  conn               *tls.Conn
  buf                *bufio.Reader
  tlsState           *tls.ConnectionState
  tlsConfig          *tls.Config
  streams            map[uint32]*stream
  streamInputs       map[uint32]chan<- []byte
  buffer             []Frame
  queue              []Frame
  nextServerStreamID uint32 // even
  nextClientStreamID uint32 // odd
  goaway             bool
  version            int
}

func (conn *connection) newStream(frame *SynStreamFrame, input <-chan []byte) *stream {
  newStream := new(stream)
  newStream.conn = conn
  newStream.streamID = frame.StreamID
  newStream.state = STATE_OPEN
  newStream.priority = frame.Priority
  newStream.input = input
  newStream.request = new(Request)
  newStream.certificates = make([]Certificate, 1)
  newStream.headers = frame.Headers
  newStream.settings = make([]*Setting, 1)
  newStream.unidirectional = frame.Flags&FLAG_UNIDIRECTIONAL != 0

  return newStream
}

func (conn *connection) WriteFrame(frame Frame) error {
  return nil
}

func (conn *connection) handleSynStream(frame *SynStreamFrame) {
  // Check stream creation is allowed.
  conn.RLock()
  defer conn.RUnlock()

  if conn.goaway {
    return
  }

  // Check version.
  if frame.Version != uint16(conn.version) {
    log.Printf("Warning: Received frame with SPDY version %d on connection with version %d.\n",
      frame.Version, conn.version)
    if frame.Version > SPDY_VERSION {
      log.Printf("Error: Received frame with SPDY version %d, which is not supported.\n",
        frame.Version)
      reply := new(RstStreamFrame)
      reply.Version = SPDY_VERSION
      reply.StreamID = frame.StreamID
      reply.StatusCode = RST_STREAM_UNSUPPORTED_VERSION
      conn.WriteFrame(reply)
      return
    }
  }

  // Check Stream ID is odd.
  if frame.StreamID&1 == 0 {
    log.Printf("Error: Received SYN_STREAM with Stream ID %d, which should be odd.\n",
      frame.StreamID)
    reply := new(RstStreamFrame)
    reply.Version = SPDY_VERSION
    reply.StreamID = frame.StreamID
    reply.StatusCode = RST_STREAM_PROTOCOL_ERROR
    conn.WriteFrame(reply)
    return
  }

  // Check Stream ID is the right number.
  if frame.StreamID != conn.nextClientStreamID+2 && frame.StreamID != 1 &&
    conn.nextClientStreamID != 0 {
    log.Printf("Error: Received SYN_STREAM with Stream ID %d, which should be %d.\n",
      frame.StreamID, conn.nextClientStreamID+2)
    reply := new(RstStreamFrame)
    reply.Version = SPDY_VERSION
    reply.StreamID = frame.StreamID
    reply.StatusCode = RST_STREAM_PROTOCOL_ERROR
    conn.WriteFrame(reply)
    return
  }

  // Check Stream ID is not too large.
  if frame.StreamID > MAX_STREAM_ID {
    log.Printf("Error: Received SYN_STREAM with Stream ID %d, which is too large.\n",
      frame.StreamID)
    reply := new(RstStreamFrame)
    reply.Version = SPDY_VERSION
    reply.StreamID = frame.StreamID
    reply.StatusCode = RST_STREAM_PROTOCOL_ERROR
    conn.WriteFrame(reply)
    return
  }

  // Stream ID is fine.

  // Create and start new stream.
  conn.RUnlock()
  conn.Lock()
  input := make(chan []byte)
  conn.streamInputs[frame.StreamID] = input
  conn.streams[frame.StreamID] = conn.newStream(frame, input)
  conn.Unlock()
  conn.RLock()

  go conn.streams[frame.StreamID].run()

  return
}

func (conn *connection) readFrames() {
  if d := conn.server.ReadTimeout; d != 0 {
    conn.conn.SetReadDeadline(time.Now().Add(d))
  }
  if d := conn.server.WriteTimeout; d != 0 {
    defer func() {
      conn.conn.SetWriteDeadline(time.Now().Add(d))
    }()
  }

  for {
    frame, err := ReadFrame(conn.buf)
    if err != nil {
      // TODO: handle error
      panic(err)
    }

  FrameHandling:
    switch frame := frame.(type) {
    default:
      panic(fmt.Sprintf("unexpected frame type %T", frame))

    /******************
     *** SYN_STREAM ***
     ******************/
    case *SynStreamFrame:
      conn.handleSynStream(frame)

    case *SynReplyFrame:
      //

    case *RstStreamFrame:
      //

    case *SettingsFrame:
      //

    case *PingFrame:
      //

    case *GoawayFrame:
      // Check version.
      if frame.Version != uint16(conn.version) {
        log.Printf("Warning: Received frame with SPDY version %d on connection with version %d.\n",
          frame.Version, conn.version)
        if frame.Version > SPDY_VERSION {
          log.Printf("Error: Received frame with SPDY version %d, which is not supported.\n",
            frame.Version)
          reply := new(RstStreamFrame)
          reply.Version = SPDY_VERSION
          reply.StatusCode = RST_STREAM_UNSUPPORTED_VERSION
          conn.WriteFrame(reply)
          break FrameHandling
        }
      }

      conn.Lock()
      conn.goaway = true
      conn.Unlock()

    case *HeadersFrame:
      //

    case *WindowUpdateFrame:
      //

    case *CredentialFrame:
      //

    case *DataFrame:
      //
    }
  }
}

func (conn *connection) serve() {
  defer func() {
    if err := recover(); err != nil {
      const size = 4096
      buf := make([]byte, size)
      buf = buf[:runtime.Stack(buf, false)]
      log.Printf("spdy: panic serving %v: %v\n%s", conn.remoteAddr, err, buf)
    }
  }()

  conn.readFrames()
}

func acceptSPDYVersion2(server *http.Server, tlsConn *tls.Conn, _ http.Handler) {
  conn := newConn(tlsConn)
  conn.server = server
  conn.tlsConfig = server.TLSConfig
  conn.version = 2

  conn.serve()
}

func acceptSPDYVersion3(server *http.Server, tlsConn *tls.Conn, _ http.Handler) {
  conn := newConn(tlsConn)
  conn.server = server
  conn.tlsConfig = server.TLSConfig
  conn.version = 3

  conn.serve()
}

func newConn(tlsConn *tls.Conn) *connection {
  conn := new(connection)
  conn.remoteAddr = tlsConn.RemoteAddr().String()
  conn.conn = tlsConn
  conn.buf = bufio.NewReader(tlsConn)
  *conn.tlsState = tlsConn.ConnectionState()
  conn.streams = make(map[uint32]*stream)
  conn.streamInputs = make(map[uint32]chan<- []byte)
  conn.buffer = make([]Frame, 0, 10)
  conn.queue = make([]Frame, 0, 10)

  return conn
}
<commit_msg>Added further frame handling<commit_after>package spdy

import (
  "bufio"
  "crypto/tls"
  "fmt"
  "log"
  "net/http"
  "runtime"
  "sync"
  "time"
)

type connection struct {
  sync.RWMutex
  remoteAddr          string // network address of remote side
  server              *http.Server
  conn                *tls.Conn
  buf                 *bufio.Reader
  tlsState            *tls.ConnectionState
  tlsConfig           *tls.Config
  streams             map[uint32]*stream
  streamInputs        map[uint32]chan<- []byte
  buffer              []Frame
  queue               []Frame
  nextServerStreamID  uint32 // even
  nextClientStreamID  uint32 // odd
  goaway              bool
  version             int
  numInvalidStreamIDs int
}

func (conn *connection) newStream(frame *SynStreamFrame, input <-chan []byte) *stream {
  newStream := new(stream)
  newStream.conn = conn
  newStream.streamID = frame.StreamID
  newStream.state = STATE_OPEN
  newStream.priority = frame.Priority
  newStream.input = input
  newStream.request = new(Request)
  newStream.certificates = make([]Certificate, 1)
  newStream.headers = frame.Headers
  newStream.settings = make([]*Setting, 1)
  newStream.unidirectional = frame.Flags&FLAG_UNIDIRECTIONAL != 0

  return newStream
}

func (conn *connection) WriteFrame(frame Frame) error {
  return nil
}

func (conn *connection) handleSynStream(frame *SynStreamFrame) {
  conn.RLock()
  defer conn.RUnlock()

  // Check stream creation is allowed.
  if conn.goaway {
    return
  }

  // Check version.
  if frame.Version != uint16(conn.version) {
    log.Printf("Warning: Received frame with SPDY version %d on connection with version %d.\n",
      frame.Version, conn.version)
    if frame.Version > SPDY_VERSION {
      log.Printf("Error: Received frame with SPDY version %d, which is not supported.\n",
        frame.Version)
      reply := new(RstStreamFrame)
      reply.Version = SPDY_VERSION
      reply.StreamID = frame.StreamID
      reply.StatusCode = RST_STREAM_UNSUPPORTED_VERSION
      conn.WriteFrame(reply)
      return
    }
  }

  // Check Stream ID is odd.
  if frame.StreamID&1 == 0 {
    log.Printf("Error: Received SYN_STREAM with Stream ID %d, which should be odd.\n",
      frame.StreamID)
    reply := new(RstStreamFrame)
    reply.Version = SPDY_VERSION
    reply.StreamID = frame.StreamID
    reply.StatusCode = RST_STREAM_PROTOCOL_ERROR
    conn.WriteFrame(reply)
    return
  }

  // Check Stream ID is the right number.
  if frame.StreamID != conn.nextClientStreamID+2 && frame.StreamID != 1 &&
    conn.nextClientStreamID != 0 {
    log.Printf("Error: Received SYN_STREAM with Stream ID %d, which should be %d.\n",
      frame.StreamID, conn.nextClientStreamID+2)
    reply := new(RstStreamFrame)
    reply.Version = SPDY_VERSION
    reply.StreamID = frame.StreamID
    reply.StatusCode = RST_STREAM_PROTOCOL_ERROR
    conn.WriteFrame(reply)
    return
  }

  // Check Stream ID is not too large.
  if frame.StreamID > MAX_STREAM_ID {
    log.Printf("Error: Received SYN_STREAM with Stream ID %d, which is too large.\n",
      frame.StreamID)
    reply := new(RstStreamFrame)
    reply.Version = SPDY_VERSION
    reply.StreamID = frame.StreamID
    reply.StatusCode = RST_STREAM_PROTOCOL_ERROR
    conn.WriteFrame(reply)
    return
  }

  // Stream ID is fine.

  // Create and start new stream.
  conn.RUnlock()
  conn.Lock()
  input := make(chan []byte)
  conn.streamInputs[frame.StreamID] = input
  conn.streams[frame.StreamID] = conn.newStream(frame, input)
  conn.Unlock()
  conn.RLock()

  go conn.streams[frame.StreamID].run()

  return
}

func (conn *connection) handleDataFrame(frame *DataFrame) {
  conn.RLock()
  defer conn.RUnlock()

  // Check Stream ID is odd.
  if frame.StreamID&1 == 0 {
    log.Printf("Error: Received DATA with Stream ID %d, which should be odd.\n",
      frame.StreamID)
    reply := new(RstStreamFrame)
    reply.Version = SPDY_VERSION
    reply.StreamID = frame.StreamID
    reply.StatusCode = RST_STREAM_PROTOCOL_ERROR
    conn.WriteFrame(reply)
    return
  }

  // Check stream is open.
  if frame.StreamID != conn.nextClientStreamID+2 && frame.StreamID != 1 &&
    conn.nextClientStreamID != 0 {
    log.Printf("Error: Received SYN_STREAM with Stream ID %d, which should be %d.\n",
      frame.StreamID, conn.nextClientStreamID+2)
    reply := new(RstStreamFrame)
    reply.Version = SPDY_VERSION
    reply.StreamID = frame.StreamID
    reply.StatusCode = RST_STREAM_PROTOCOL_ERROR
    conn.WriteFrame(reply)
    return
  }

  // Stream ID is fine.

  // Handle flags.
  if frame.Flags&FLAG_FIN != 0 {
    stream := conn.streams[frame.StreamID]
    stream.Lock()
    stream.state = STATE_HALF_CLOSED_THERE
    stream.Unlock()
  }

  // Send data to stream.
  conn.streamInputs[frame.StreamID] <- frame.Data

  return
}

func (conn *connection) readFrames() {
  if d := conn.server.ReadTimeout; d != 0 {
    conn.conn.SetReadDeadline(time.Now().Add(d))
  }
  if d := conn.server.WriteTimeout; d != 0 {
    defer func() {
      conn.conn.SetWriteDeadline(time.Now().Add(d))
    }()
  }

  for {
    frame, err := ReadFrame(conn.buf)
    if err != nil {
      // TODO: handle error
      panic(err)
    }

  FrameHandling:
    switch frame := frame.(type) {
    default:
      panic(fmt.Sprintf("unexpected frame type %T", frame))

    /*** COMPLETE! ***/
    case *SynStreamFrame:
      conn.handleSynStream(frame)

    case *SynReplyFrame:
      log.Println("Got SYN_REPLY")

    case *RstStreamFrame:
      log.Printf("Received RST_STREAM on stream %d with status %q.\n", frame.StreamID,
        StatusCodeText(int(frame.StatusCode)))

    case *SettingsFrame:
      log.Println("Received SETTINGS. Ignoring...")

      /*** COMPLETE! ***/
    case *PingFrame:
      // Check Ping ID is odd.
      if frame.PingID&1 == 0 {
        log.Printf("Error: Received PING with Stream ID %d, which should be odd.\n", frame.PingID)
        reply := new(RstStreamFrame)
        reply.Version = SPDY_VERSION
        reply.StatusCode = RST_STREAM_PROTOCOL_ERROR
        conn.WriteFrame(reply)
        break FrameHandling
      }
      log.Println("Received PING. Replying...")
      conn.WriteFrame(frame)

    case *GoawayFrame:
      // Check version.
      if frame.Version != uint16(conn.version) {
        log.Printf("Warning: Received frame with SPDY version %d on connection with version %d.\n",
          frame.Version, conn.version)
        if frame.Version > SPDY_VERSION {
          log.Printf("Error: Received frame with SPDY version %d, which is not supported.\n",
            frame.Version)
          reply := new(RstStreamFrame)
          reply.Version = SPDY_VERSION
          reply.StatusCode = RST_STREAM_UNSUPPORTED_VERSION
          conn.WriteFrame(reply)
          break FrameHandling
        }
      }

      // TODO: inform push streams that they haven't been processed if
      // the last good stream ID is less than their ID.

      conn.Lock()
      conn.goaway = true
      conn.Unlock()

    case *HeadersFrame:
      log.Println("Got HEADERS")

    case *WindowUpdateFrame:
      log.Println("Got WINDOW_UPDATE")

    case *CredentialFrame:
      log.Println("Got CREDENTIAL")

      /*** COMPLETE! ***/
    case *DataFrame:
      conn.handleDataFrame(frame)
    }
  }
}

func (conn *connection) serve() {
  defer func() {
    if err := recover(); err != nil {
      const size = 4096
      buf := make([]byte, size)
      buf = buf[:runtime.Stack(buf, false)]
      log.Printf("spdy: panic serving %v: %v\n%s", conn.remoteAddr, err, buf)
    }
  }()

  conn.readFrames()
}

func acceptSPDYVersion2(server *http.Server, tlsConn *tls.Conn, _ http.Handler) {
  conn := newConn(tlsConn)
  conn.server = server
  conn.tlsConfig = server.TLSConfig
  conn.version = 2

  conn.serve()
}

func acceptSPDYVersion3(server *http.Server, tlsConn *tls.Conn, _ http.Handler) {
  conn := newConn(tlsConn)
  conn.server = server
  conn.tlsConfig = server.TLSConfig
  conn.version = 3

  conn.serve()
}

func newConn(tlsConn *tls.Conn) *connection {
  conn := new(connection)
  conn.remoteAddr = tlsConn.RemoteAddr().String()
  conn.conn = tlsConn
  conn.buf = bufio.NewReader(tlsConn)
  conn.tlsState = new(tls.ConnectionState)
  *conn.tlsState = tlsConn.ConnectionState()
  conn.streams = make(map[uint32]*stream)
  conn.streamInputs = make(map[uint32]chan<- []byte)
  conn.buffer = make([]Frame, 0, 10)
  conn.queue = make([]Frame, 0, 10)

  return conn
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
	"github.com/google/gopacket/pcapgo"
	"golang.org/x/sync/errgroup"
	"os"
	"regexp"
	"strconv"
	"strings"
)

// reconstructOptions represents all options for reconstruction
type reconstructOptions struct {
	bpP    int
	limitX int
}

func createPacket(ch chan<- []byte, packet []int, bpP int) error {
	var buf []byte
	var tmp int
	switch bpP {
	case 24:
		for _, i := range packet {
			buf = append(buf, byte(i))
		}
	case 3, 6, 9, 12, 15, 18, 21:
		var slice []int
		for i := 0; i < len(packet); i = i + 1 {
			if i%(bpP*8) == 0 && i != 0 {
				bytes := createBytes(slice, bpP/3)
				buf = append(buf, bytes...)
				slice = slice[:0]
			}
			slice = append(slice, packet[i])
		}
		bytes := createBytes(slice, bpP/3)
		buf = append(buf, bytes...)
	case 1:
		var j int
		for i := 0; i < len(packet); i = i + 3 {
			if j%8 == 0 && j != 0 {
				buf = append(buf, byte(tmp))
				tmp = 0
			}
			if packet[i] != 0 {
				tmp = tmp | (1 << uint8(7-j%8))
			}
			j = j + 1
		}
		if tmp != 0 {
			buf = append(buf, byte(tmp))
		}
	default:
		return fmt.Errorf("This format is not supported so far")
	}

	ch <- buf

	return nil
}

func compareVersion(variant, minimalVersion string) (bool, error) {
	versionIs := strings.Split(variant, ".")
	versionShould := strings.Split(minimalVersion, ".")

	if len(versionIs) != len(versionShould) {
		return false, fmt.Errorf("Versions don't have the same length")
	}

	for i := range versionShould {
		if versionIs[i] < versionShould[i] {
			return false, fmt.Errorf("At least version %s is needed", minimalVersion)
		} else if versionIs[i] > versionShould[i] {
			break
		}
	}
	return true, nil
}

func checkHeader(svg *bufio.Scanner) (reconstructOptions, error) {
	var options reconstructOptions
	var limitX, limitY, bpP int
	var variant string
	var header bool = false

	limits, err := regexp.Compile("^<svg width=\"(\\d+)\" height=\"(\\d+)\">$")
	if err != nil {
		return options, err
	}
	headerStart, err := regexp.Compile("^<!--$")
	if err != nil {
		return options, err
	}
	headerEnd, err := regexp.Compile("^-->$")
	if err != nil {
		return options, err
	}
	version, err := regexp.Compile("\\s+goNetViz \"([0-9.]+)\"$")
	if err != nil {
		return options, err
	}
	bpPconfig, err := regexp.Compile("\\s+BitsPerPixel=(\\d+)$")
	if err != nil {
		return options, err
	}

	for svg.Scan() {
		switch {
		case limitX == 0 && limitY == 0 && header == false:
			matches := limits.FindStringSubmatch(svg.Text())
			if len(matches) == 3 {
				limitX, _ = strconv.Atoi(matches[1])
				limitY, _ = strconv.Atoi(matches[2])
			}
		case header == false:
			matches := headerStart.FindStringSubmatch(svg.Text())
			if len(matches) == 2 {
				header = true
			}
		case header == true:
			matches := headerEnd.FindStringSubmatch(svg.Text())
			if len(matches) == 2 {
				return options, nil
			}
		case len(variant) == 0:
			matches := version.FindStringSubmatch(svg.Text())
			if len(matches) == 2 {
				variant = matches[1]
			}
		case bpP == 0:
			matches := bpPconfig.FindStringSubmatch(svg.Text())
			if len(matches) == 2 {
				bpP, _ = strconv.Atoi(matches[1])
			}
		}
	}
	return options, fmt.Errorf("No end of header found")
}

func extractInformation(g *errgroup.Group, ch chan []byte, cfg configs) error {
	inputfile, err := os.Open(cfg.file)
	if err != nil {
		return fmt.Errorf("Could not open file %s: %s\n", cfg.file, err.Error())
	}
	defer inputfile.Close()
	svg := bufio.NewScanner(inputfile)
	var yLast int
	var packet []int
	defer close(ch)

	opt, err := checkHeader(svg)
	if err != nil {
		return err
	}

	pixel, err := regexp.Compile("^<rect x=\"(\\d+)\" y=\"(\\d+)\" width=\"\\d+\" height=\"\\d+\" style=\"fill:rgb\\((\\d+),(\\d+),(\\d+)\\)\" />$")
	if err != nil {
		return err
	}
	svgEnd, err := regexp.Compile("^</svg>$")
	if err != nil {
		return err
	}

	for svg.Scan() {
		matches := pixel.FindStringSubmatch(svg.Text())
		if len(matches) == 6 {
			pixelX, _ := strconv.Atoi(matches[1])
			pixelY, _ := strconv.Atoi(matches[2])
			if pixelY != yLast {
				yLast = pixelY
				if err := createPacket(ch, packet, opt.bpP); err != nil {
					return err
				}
				packet = packet[:0]
			}
			if pixelX >= opt.limitX {
				return fmt.Errorf("x-coordinate (%d) is bigger than the limit (%d)\n", pixelX, opt.limitX)
			}
			r, _ := strconv.Atoi(matches[3])
			g, _ := strconv.Atoi(matches[4])
			b, _ := strconv.Atoi(matches[5])
			packet = append(packet, r, g, b)
		} else {
			end := svgEnd.FindStringSubmatch(svg.Text())
			if len(end) == 1 && len(packet) != 0 {
				return createPacket(ch, packet, opt.bpP)
			}
		}
	}
	return nil
}

func createPcap(g *errgroup.Group, ch chan []byte, cfg configs) error {
	filename := cfg.prefix
	filename += ".pcap"
	output, err := os.Create(filename)
	if err != nil {
		return fmt.Errorf("Could not create file %s: %s\n", filename, err.Error())
	}
	defer output.Close()
	w := pcapgo.NewWriter(output)
	w.WriteFileHeader(65536, layers.LinkTypeEthernet)

	for i, ok := <-ch; ok; i, ok = <-ch {
		w.WritePacket(gopacket.CaptureInfo{CaptureLength: len(i), Length: len(i), InterfaceIndex: 0}, i)
	}

	return nil
}

func reconstruct(g *errgroup.Group, cfg configs) error {
	ch := make(chan []byte)

	go extractInformation(g, ch, cfg)

	g.Go(func() error {
		return createPcap(g, ch, cfg)
	})

	return g.Wait()
}
<commit_msg>Introduce reconstruct options<commit_after>package main

import (
	"bufio"
	"fmt"
	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
	"github.com/google/gopacket/pcapgo"
	"golang.org/x/sync/errgroup"
	"os"
	"reflect"
	"regexp"
	"strconv"
	"strings"
)

// reconstructOptions represents all options for reconstruction
type reconstructOptions struct {
	BpP    int
	LimitX int
	Scale  int
	Dtg    string
	Source string
	Filter string
}

// svgOptions represents various options for reconstruction
type svgOptions struct {
	regex             string
	expectedType      string
	reconstructOption string
}

func createPacket(ch chan<- []byte, packet []int, bpP int) error {
	var buf []byte
	var tmp int
	switch bpP {
	case 24:
		for _, i := range packet {
			buf = append(buf, byte(i))
		}
	case 3, 6, 9, 12, 15, 18, 21:
		var slice []int
		for i := 0; i < len(packet); i = i + 1 {
			if i%(bpP*8) == 0 && i != 0 {
				bytes := createBytes(slice, bpP/3)
				buf = append(buf, bytes...)
				slice = slice[:0]
			}
			slice = append(slice, packet[i])
		}
		bytes := createBytes(slice, bpP/3)
		buf = append(buf, bytes...)
	case 1:
		var j int
		for i := 0; i < len(packet); i = i + 3 {
			if j%8 == 0 && j != 0 {
				buf = append(buf, byte(tmp))
				tmp = 0
			}
			if packet[i] != 0 {
				tmp = tmp | (1 << uint8(7-j%8))
			}
			j = j + 1
		}
		if tmp != 0 {
			buf = append(buf, byte(tmp))
		}
	default:
		return fmt.Errorf("This format is not supported so far")
	}

	ch <- buf

	return nil
}

func compareVersion(variant, minimalVersion string) (bool, error) {
	versionIs := strings.Split(variant, ".")
	versionShould := strings.Split(minimalVersion, ".")

	if len(versionIs) != len(versionShould) {
		return false, fmt.Errorf("Versions don't have the same length")
	}

	for i := range versionShould {
		if versionIs[i] < versionShould[i] {
			return false, fmt.Errorf("At least version %s is needed", minimalVersion)
		} else if versionIs[i] > versionShould[i] {
			break
		}
	}
	return true, nil
}

func checkHeader(svg *bufio.Scanner) (reconstructOptions, error) {
	var options reconstructOptions
	var limitX, limitY int
	var variant string
	var header bool = false
	var parseOptions []svgOptions
	var optionIndex int

	limits, err := regexp.Compile("^<svg width=\"(\\d+)\" height=\"(\\d+)\">$")
	if err != nil {
		return options, err
	}
	headerStart, err := regexp.Compile("^<!--$")
	if err != nil {
		return options, err
	}
	headerEnd, err := regexp.Compile("^-->$")
	if err != nil {
		return options, err
	}
	version, err := regexp.Compile("\\s+goNetViz \"([0-9.]+)\"$")
	if err != nil {
		return options, err
	}

	scale := svgOptions{regex: "\\s+Scale=(\\d+)$", expectedType: "int", reconstructOption: "Scale"}
	parseOptions = append(parseOptions, scale)
	bpP := svgOptions{regex: "\\s+BitsPerPixel=(\\d+)$", expectedType: "int", reconstructOption: "BpP"}
	parseOptions = append(parseOptions, bpP)
	dtg := svgOptions{regex: "\\s+DTG=(\\w+)$", expectedType: "string", reconstructOption: "dtg"}
	parseOptions = append(parseOptions, dtg)
	source := svgOptions{regex: "\\s+Source=(\\w+)$", expectedType: "string", reconstructOption: "source"}
	parseOptions = append(parseOptions, source)
	filter := svgOptions{regex: "\\s+Filter=(\\w+)$", expectedType: "string", reconstructOption: "filter"}
	parseOptions = append(parseOptions, filter)

	for svg.Scan() {
		switch {
		case limitX == 0 && limitY == 0 && header == false:
			matches := limits.FindStringSubmatch(svg.Text())
			if len(matches) == 3 {
				limitX, _ = strconv.Atoi(matches[1])
				limitY, _ = strconv.Atoi(matches[2])
			}
		case header == false:
			if headerStart.MatchString(svg.Text()) {
				header = true
			}
		case len(variant) == 0:
			matches := version.FindStringSubmatch(svg.Text())
			if len(matches) == 2 {
				variant = matches[1]
			}
		default:
			if optionIndex > len(parseOptions) {
				return options, fmt.Errorf("Option index is out of range")
			}
			regex, err := regexp.Compile(parseOptions[optionIndex].regex)
			if err != nil {
				return options, err
			}
			matches := regex.FindStringSubmatch(svg.Text())
			if len(matches) == 2 {
				if parseOptions[optionIndex].expectedType == "int" {
					new, _ := strconv.Atoi(matches[1])
					reflect.ValueOf(&options).Elem().FieldByName(parseOptions[optionIndex].reconstructOption).SetInt(int64(new))
				} else if parseOptions[optionIndex].expectedType == "string" {
					reflect.ValueOf(&options).Elem().FieldByName(parseOptions[optionIndex].reconstructOption).SetString(matches[1])
				}
				optionIndex += 1
			} else {
				if headerEnd.MatchString(svg.Text()) {
					return options, nil
				}
			}
		}
	}
	return options, fmt.Errorf("No end of header found")
}

func extractInformation(g *errgroup.Group, ch chan []byte, cfg configs) error {
	inputfile, err := os.Open(cfg.file)
	if err != nil {
		return fmt.Errorf("Could not open file %s: %s\n", cfg.file, err.Error())
	}
	defer inputfile.Close()
	svg := bufio.NewScanner(inputfile)
	var yLast int
	var packet []int
	defer close(ch)

	opt, err := checkHeader(svg)
	if err != nil {
		return err
	}

	pixel, err := regexp.Compile("^<rect x=\"(\\d+)\" y=\"(\\d+)\" width=\"\\d+\" height=\"\\d+\" style=\"fill:rgb\\((\\d+),(\\d+),(\\d+)\\)\" />$")
	if err != nil {
		return err
	}
	svgEnd, err := regexp.Compile("</svg>")
	if err != nil {
		return err
	}

	for svg.Scan() {
		matches := pixel.FindStringSubmatch(svg.Text())
		if len(matches) == 6 {
			pixelX, _ := strconv.Atoi(matches[1])
			pixelY, _ := strconv.Atoi(matches[2])
			if pixelY != yLast {
				yLast = pixelY
				if err := createPacket(ch, packet, opt.BpP); err != nil {
					return err
				}
				packet = packet[:0]
			}
			if pixelX >= opt.LimitX {
				return fmt.Errorf("x-coordinate (%d) is bigger than the limit (%d)\n", pixelX, opt.LimitX)
			}
			r, _ := strconv.Atoi(matches[3])
			g, _ := strconv.Atoi(matches[4])
			b, _ := strconv.Atoi(matches[5])
			packet = append(packet, r, g, b)
		} else if svgEnd.MatchString(svg.Text()) {
			fmt.Println("End matches")
			if len(packet) != 0 {
				return createPacket(ch, packet, opt.BpP)
			}
		}
	}
	return nil
}

func createPcap(g *errgroup.Group, ch chan []byte, cfg configs) error {
	filename := cfg.prefix
	filename += ".pcap"
	output, err := os.Create(filename)
	if err != nil {
		return fmt.Errorf("Could not create file %s: %s\n", filename, err.Error())
	}
	defer output.Close()
	w := pcapgo.NewWriter(output)
	w.WriteFileHeader(65536, layers.LinkTypeEthernet)

	for i, ok := <-ch; ok; i, ok = <-ch {
		w.WritePacket(gopacket.CaptureInfo{CaptureLength: len(i), Length: len(i), InterfaceIndex: 0}, i)
	}

	return nil
}

func reconstruct(g *errgroup.Group, cfg configs) error {
	ch := make(chan []byte)

	go extractInformation(g, ch, cfg)

	g.Go(func() error {
		return createPcap(g, ch, cfg)
	})

	return g.Wait()
}
<|endoftext|>


<commit_before>// +build linux,cgo,!agent

package db

import (
	"database/sql"
	"encoding/json"
	"fmt"

	"github.com/pkg/errors"

	"github.com/lxc/lxd/shared/api"
)

// GetNetworkACLs returns the names of existing Network ACLs.
func (c *Cluster) GetNetworkACLs(project string) ([]string, error) {
	q := `SELECT name FROM networks_acls
		WHERE project_id = (SELECT id FROM projects WHERE name = ? LIMIT 1)
		ORDER BY id
	`
	inargs := []interface{}{project}

	var name string
	outfmt := []interface{}{name}
	result, err := queryScan(c, q, inargs, outfmt)
	if err != nil {
		return nil, err
	}

	response := []string{}
	for _, r := range result {
		response = append(response, r[0].(string))
	}

	return response, nil
}

// GetNetworkACL returns the Network ACL with the given name in the given project.
func (c *Cluster) GetNetworkACL(projectName string, name string) (int64, *api.NetworkACL, error) {
	var id int64 = int64(-1)
	var ingressJSON string
	var egressJSON string

	acl := api.NetworkACL{
		NetworkACLPost: api.NetworkACLPost{
			Name: name,
		},
	}

	q := `
		SELECT id, description, ingress, egress
		FROM networks_acls
		WHERE project_id = (SELECT id FROM projects WHERE name = ? LIMIT 1) AND name=?
		LIMIT 1
	`
	arg1 := []interface{}{projectName, name}
	arg2 := []interface{}{&id, &acl.Description, &ingressJSON, &egressJSON}

	err := dbQueryRowScan(c, q, arg1, arg2)
	if err != nil {
		if err == sql.ErrNoRows {
			return -1, nil, ErrNoSuchObject
		}

		return -1, nil, err
	}

	acl.Ingress = []api.NetworkACLRule{}
	if ingressJSON != "" {
		err = json.Unmarshal([]byte(ingressJSON), &acl.Ingress)
		if err != nil {
			return -1, nil, errors.Wrapf(err, "Failed unmarshalling ingress rules")
		}
	}

	acl.Egress = []api.NetworkACLRule{}
	if egressJSON != "" {
		err = json.Unmarshal([]byte(egressJSON), &acl.Egress)
		if err != nil {
			return -1, nil, errors.Wrapf(err, "Failed unmarshalling egress rules")
		}
	}

	acl.Config, err = c.networkACLConfig(id)
	if err != nil {
		return -1, nil, errors.Wrapf(err, "Failed loading config")
	}

	return id, &acl, nil
}

// networkACLConfig returns the config map of the Network ACL with the given ID.
func (c *Cluster) networkACLConfig(id int64) (map[string]string, error) {
	var key, value string
	query := `
		SELECT key, value
		FROM networks_acls_config
		WHERE network_acl_id=?
	`
	inargs := []interface{}{id}
	outfmt := []interface{}{key, value}
	results, err := queryScan(c, query, inargs, outfmt)
	if err != nil {
		return nil, err
	}

	config := make(map[string]string, len(results))

	for _, r := range results {
		key = r[0].(string)
		value = r[1].(string)

		_, found := config[key]
		if found {
			return nil, fmt.Errorf("Duplicate config row found for key %q for network ACL ID %d", key, id)
		}

		config[key] = value
	}

	return config, nil
}

// CreateNetworkACL creates a new Network ACL.
func (c *Cluster) CreateNetworkACL(projectName string, info *api.NetworkACLsPost) (int64, error) {
	var id int64
	var err error
	var ingressJSON, egressJSON []byte

	if info.Ingress != nil {
		ingressJSON, err = json.Marshal(info.Ingress)
		if err != nil {
			return -1, errors.Wrapf(err, "Failed marshalling ingress rules")
		}
	}

	if info.Egress != nil {
		egressJSON, err = json.Marshal(info.Egress)
		if err != nil {
			return -1, errors.Wrapf(err, "Failed marshalling egress rules")
		}
	}

	err = c.Transaction(func(tx *ClusterTx) error {
		// Insert a new Network ACL record.
		result, err := tx.tx.Exec(`
			INSERT INTO networks_acls (project_id, name, description, ingress, egress)
			VALUES ((SELECT id FROM projects WHERE name = ? LIMIT 1), ?, ?, ?, ?)
		`, projectName, info.Name, info.Description, string(ingressJSON), string(egressJSON))
		if err != nil {
			return err
		}

		id, err := result.LastInsertId()
		if err != nil {
			return err
		}

		err = networkACLConfigAdd(tx.tx, id, info.Config)
		if err != nil {
			return err
		}

		return nil
	})
	if err != nil {
		id = -1
	}

	return id, err
}

// networkACLConfigAdd inserts Network ACL config keys.
func networkACLConfigAdd(tx *sql.Tx, id int64, config map[string]string) error {
	sql := "INSERT INTO networks_acls_config (network_acl_id, key, value) VALUES(?, ?, ?)"
	stmt, err := tx.Prepare(sql)
	if err != nil {
		return err
	}
	defer stmt.Close()

	for k, v := range config {
		if v == "" {
			continue
		}

		_, err = stmt.Exec(id, k, v)
		if err != nil {
			return errors.Wrapf(err, "Failed inserting config")
		}
	}

	return nil
}
<commit_msg>lxd/db/network/acls: Adds UpdateNetworkACL function<commit_after>// +build linux,cgo,!agent

package db

import (
	"database/sql"
	"encoding/json"
	"fmt"

	"github.com/pkg/errors"

	"github.com/lxc/lxd/shared/api"
)

// GetNetworkACLs returns the names of existing Network ACLs.
func (c *Cluster) GetNetworkACLs(project string) ([]string, error) {
	q := `SELECT name FROM networks_acls
		WHERE project_id = (SELECT id FROM projects WHERE name = ? LIMIT 1)
		ORDER BY id
	`
	inargs := []interface{}{project}

	var name string
	outfmt := []interface{}{name}
	result, err := queryScan(c, q, inargs, outfmt)
	if err != nil {
		return nil, err
	}

	response := []string{}
	for _, r := range result {
		response = append(response, r[0].(string))
	}

	return response, nil
}

// GetNetworkACL returns the Network ACL with the given name in the given project.
func (c *Cluster) GetNetworkACL(projectName string, name string) (int64, *api.NetworkACL, error) {
	var id int64 = int64(-1)
	var ingressJSON string
	var egressJSON string

	acl := api.NetworkACL{
		NetworkACLPost: api.NetworkACLPost{
			Name: name,
		},
	}

	q := `
		SELECT id, description, ingress, egress
		FROM networks_acls
		WHERE project_id = (SELECT id FROM projects WHERE name = ? LIMIT 1) AND name=?
		LIMIT 1
	`
	arg1 := []interface{}{projectName, name}
	arg2 := []interface{}{&id, &acl.Description, &ingressJSON, &egressJSON}

	err := dbQueryRowScan(c, q, arg1, arg2)
	if err != nil {
		if err == sql.ErrNoRows {
			return -1, nil, ErrNoSuchObject
		}

		return -1, nil, err
	}

	acl.Ingress = []api.NetworkACLRule{}
	if ingressJSON != "" {
		err = json.Unmarshal([]byte(ingressJSON), &acl.Ingress)
		if err != nil {
			return -1, nil, errors.Wrapf(err, "Failed unmarshalling ingress rules")
		}
	}

	acl.Egress = []api.NetworkACLRule{}
	if egressJSON != "" {
		err = json.Unmarshal([]byte(egressJSON), &acl.Egress)
		if err != nil {
			return -1, nil, errors.Wrapf(err, "Failed unmarshalling egress rules")
		}
	}

	acl.Config, err = c.networkACLConfig(id)
	if err != nil {
		return -1, nil, errors.Wrapf(err, "Failed loading config")
	}

	return id, &acl, nil
}

// networkACLConfig returns the config map of the Network ACL with the given ID.
func (c *Cluster) networkACLConfig(id int64) (map[string]string, error) {
	var key, value string
	query := `
		SELECT key, value
		FROM networks_acls_config
		WHERE network_acl_id=?
	`
	inargs := []interface{}{id}
	outfmt := []interface{}{key, value}
	results, err := queryScan(c, query, inargs, outfmt)
	if err != nil {
		return nil, err
	}

	config := make(map[string]string, len(results))

	for _, r := range results {
		key = r[0].(string)
		value = r[1].(string)

		_, found := config[key]
		if found {
			return nil, fmt.Errorf("Duplicate config row found for key %q for network ACL ID %d", key, id)
		}

		config[key] = value
	}

	return config, nil
}

// CreateNetworkACL creates a new Network ACL.
func (c *Cluster) CreateNetworkACL(projectName string, info *api.NetworkACLsPost) (int64, error) {
	var id int64
	var err error
	var ingressJSON, egressJSON []byte

	if info.Ingress != nil {
		ingressJSON, err = json.Marshal(info.Ingress)
		if err != nil {
			return -1, errors.Wrapf(err, "Failed marshalling ingress rules")
		}
	}

	if info.Egress != nil {
		egressJSON, err = json.Marshal(info.Egress)
		if err != nil {
			return -1, errors.Wrapf(err, "Failed marshalling egress rules")
		}
	}

	err = c.Transaction(func(tx *ClusterTx) error {
		// Insert a new Network ACL record.
		result, err := tx.tx.Exec(`
			INSERT INTO networks_acls (project_id, name, description, ingress, egress)
			VALUES ((SELECT id FROM projects WHERE name = ? LIMIT 1), ?, ?, ?, ?)
		`, projectName, info.Name, info.Description, string(ingressJSON), string(egressJSON))
		if err != nil {
			return err
		}

		id, err := result.LastInsertId()
		if err != nil {
			return err
		}

		err = networkACLConfigAdd(tx.tx, id, info.Config)
		if err != nil {
			return err
		}

		return nil
	})
	if err != nil {
		id = -1
	}

	return id, err
}

// networkACLConfigAdd inserts Network ACL config keys.
func networkACLConfigAdd(tx *sql.Tx, id int64, config map[string]string) error {
	sql := "INSERT INTO networks_acls_config (network_acl_id, key, value) VALUES(?, ?, ?)"
	stmt, err := tx.Prepare(sql)
	if err != nil {
		return err
	}
	defer stmt.Close()

	for k, v := range config {
		if v == "" {
			continue
		}

		_, err = stmt.Exec(id, k, v)
		if err != nil {
			return errors.Wrapf(err, "Failed inserting config")
		}
	}

	return nil
}

// UpdateNetworkACL updates the Network ACL with the given ID.
func (c *Cluster) UpdateNetworkACL(id int64, config *api.NetworkACLPut) error {
	var err error
	var ingressJSON, egressJSON []byte

	if config.Ingress != nil {
		ingressJSON, err = json.Marshal(config.Ingress)
		if err != nil {
			return errors.Wrapf(err, "Failed marshalling ingress rules")
		}
	}

	if config.Egress != nil {
		egressJSON, err = json.Marshal(config.Egress)
		if err != nil {
			return errors.Wrapf(err, "Failed marshalling egress rules")
		}
	}

	return c.Transaction(func(tx *ClusterTx) error {
		_, err := tx.tx.Exec(`
			UPDATE networks_acls
			SET description=?, ingress = ?, egress = ?
			WHERE id=?
		`, config.Description, ingressJSON, egressJSON, id)
		if err != nil {
			return err
		}

		err = networkACLConfigUpdate(tx.tx, id, config.Config)
		if err != nil {
			return err
		}

		return nil
	})
}

// networkACLConfigUpdate updates Network ACL config keys.
func networkACLConfigUpdate(tx *sql.Tx, id int64, config map[string]string) error {
	_, err := tx.Exec("DELETE FROM networks_acls_config WHERE network_acl_id=?", id)
	if err != nil {
		return err
	}

	str := fmt.Sprintf("INSERT INTO networks_acls_config (network_acl_id, key, value) VALUES(?, ?, ?)")
	stmt, err := tx.Prepare(str)
	if err != nil {
		return err
	}
	defer stmt.Close()

	for k, v := range config {
		if v == "" {
			continue
		}

		_, err = stmt.Exec(id, k, v)
		if err != nil {
			return err
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
	"log"
)

type mongoEngine struct {
	session *mgo.Session
	dbName  string
}

func (eng mongoEngine) Close() {
	// TODO
}

// NewMongoEngine returns an Engine based on a mongodb batabase backend
func NewMongoEngine(dbName string, hostPorts string) Engine {
	log.Printf("connecting to mongodb '%s'\n", hostPorts)
	s, err := mgo.Dial(hostPorts)
	if err != nil {
		panic(err)
	}
	s.SetMode(mgo.Monotonic, true)
	eng := &mongoEngine{
		session: s,
		dbName:  dbName,
	}

	eng.EnsureIndexes("organisations") //TODOL parameterise this

	return eng
}

func (eng *mongoEngine) EnsureIndexes(collection string) {
	c := eng.session.DB(eng.dbName).C(collection)

	eng.session.ResetIndexCache()

	// create collection if it's not there
	c.Create(&mgo.CollectionInfo{})

	err := c.EnsureIndex(mgo.Index{
		Key:        []string{"uuid"}, //TODO: parameterise this
		Unique:     true,
		DropDups:   true,
		Background: false,
		Sparse:     false,
	})
	if err != nil {
		panic(err)
	}

}

func (eng *mongoEngine) Drop(collection string) {
	err := eng.session.DB("ftindex").C(collection).DropCollection()
	if err != nil {
		log.Printf("failed to drop collection")
	}
	eng.EnsureIndexes(collection)
}

func (eng *mongoEngine) Write(collection string, id string, cont Document) error {
	coll := eng.session.DB(eng.dbName).C(collection)
	if id == "" {
		panic("missing id")
	}
	_, err := coll.Upsert(bson.D{{"uuid", id}}, cont) //TODO: parameterise uuid
	if err != nil {
		log.Printf("insert failed: %v\n", err)
	}
	return nil
}

func (eng *mongoEngine) Count(collection string) int {
	coll := eng.session.DB(eng.dbName).C(collection)
	count, err := coll.Count()
	if err != nil {
		panic(err)
	}
	return count
}

func (eng *mongoEngine) Load(collection, id string) (bool, Document, error) {
	c := eng.session.DB(eng.dbName).C(collection)
	var content Document
	err := c.Find(bson.M{"uuid": id}).One(&content)
	if err == mgo.ErrNotFound {
		return false, Document{}, nil
	}
	if err != nil {
		return false, Document{}, err
	}
	return true, content, nil
}

func (eng mongoEngine) All(collection string, stopchan chan struct{}) (chan Document, error) {
	cont := make(chan Document)

	go func() {
		defer close(cont)
		coll := eng.session.DB(eng.dbName).C(collection)
		iter := coll.Find(nil).Iter()
		var result Document
		for iter.Next(&result) {
			select {
			case <-stopchan:
				break
			case cont <- result:
			}
		}
		if err := iter.Close(); err != nil {
			panic(err)
		}
	}()

	return cont, nil
}
<commit_msg>fix hardcoded db name<commit_after>package main

import (
	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
	"log"
)

type mongoEngine struct {
	session *mgo.Session
	dbName  string
}

func (eng mongoEngine) Close() {
	// TODO
}

// NewMongoEngine returns an Engine based on a mongodb batabase backend
func NewMongoEngine(dbName string, hostPorts string) Engine {
	log.Printf("connecting to mongodb '%s'\n", hostPorts)
	s, err := mgo.Dial(hostPorts)
	if err != nil {
		panic(err)
	}
	s.SetMode(mgo.Monotonic, true)
	eng := &mongoEngine{
		session: s,
		dbName:  dbName,
	}

	eng.EnsureIndexes("organisations") //TODOL parameterise this

	return eng
}

func (eng *mongoEngine) EnsureIndexes(collection string) {
	c := eng.session.DB(eng.dbName).C(collection)

	eng.session.ResetIndexCache()

	// create collection if it's not there
	c.Create(&mgo.CollectionInfo{})

	err := c.EnsureIndex(mgo.Index{
		Key:        []string{"uuid"}, //TODO: parameterise this
		Unique:     true,
		DropDups:   true,
		Background: false,
		Sparse:     false,
	})
	if err != nil {
		panic(err)
	}

}

func (eng *mongoEngine) Drop(collection string) {
	err := eng.session.DB(eng.dbName).C(collection).DropCollection()
	if err != nil {
		log.Printf("failed to drop collection")
	}
	eng.EnsureIndexes(collection)
}

func (eng *mongoEngine) Write(collection string, id string, cont Document) error {
	coll := eng.session.DB(eng.dbName).C(collection)
	if id == "" {
		panic("missing id")
	}
	_, err := coll.Upsert(bson.D{{"uuid", id}}, cont) //TODO: parameterise uuid
	if err != nil {
		log.Printf("insert failed: %v\n", err)
	}
	return nil
}

func (eng *mongoEngine) Count(collection string) int {
	coll := eng.session.DB(eng.dbName).C(collection)
	count, err := coll.Count()
	if err != nil {
		panic(err)
	}
	return count
}

func (eng *mongoEngine) Load(collection, id string) (bool, Document, error) {
	c := eng.session.DB(eng.dbName).C(collection)
	var content Document
	err := c.Find(bson.M{"uuid": id}).One(&content)
	if err == mgo.ErrNotFound {
		return false, Document{}, nil
	}
	if err != nil {
		return false, Document{}, err
	}
	return true, content, nil
}

func (eng mongoEngine) All(collection string, stopchan chan struct{}) (chan Document, error) {
	cont := make(chan Document)

	go func() {
		defer close(cont)
		coll := eng.session.DB(eng.dbName).C(collection)
		iter := coll.Find(nil).Iter()
		var result Document
		for iter.Next(&result) {
			select {
			case <-stopchan:
				break
			case cont <- result:
			}
		}
		if err := iter.Close(); err != nil {
			panic(err)
		}
	}()

	return cont, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"ppd/gpubsub"
	//"time"
)

func main() {
	b := gpubsub.Broker{}
	port := ":8999"
	fmt.Printf("Server listening on %s\n", port);

	/*go func(b *gpubsub.Broker) {
		for {
			time.Sleep(5*time.Second)
			b.PrintTopics();
		}
	}(&b)*/

	b.Start(port, 10, 20)

}<commit_msg>Passing parameters to Broker<commit_after>package main

import (
	"fmt"
	"ppd/gpubsub"
	"os"
	"strconv"
)

func main() {

	if len(os.Args) < 2 {
		fmt.Printf("Informe a porta e o tamanho do buffer em cada topico.\n");
		return;
	}

	b := gpubsub.Broker{}
	port := os.Args[1]
	fmt.Printf("Server listening on %s\n", port);

	/*go func(b *gpubsub.Broker) {
		for {
			time.Sleep(5*time.Second)
			b.PrintTopics();
		}
	}(&b)*/

	k, _ := strconv.Atoi(os.Args[2])
	b.Start(port, k, 20)

}<|endoftext|>


<commit_before>package diag

// Ranger wraps the Range method.
type Ranger interface {
	// Range returns the range associated with the value.
	Range() Ranging
}

// Ranging represents a range [From, To) within an indexable sequence. Structs
// can embed Ranging to satisfy the Ranger interface.
type Ranging struct {
	From int
	To   int
}

// Ranging returns itself.
func (r Ranging) Range() Ranging { return r }
<commit_msg>diag: Fix a godoc.<commit_after>package diag

// Ranger wraps the Range method.
type Ranger interface {
	// Range returns the range associated with the value.
	Range() Ranging
}

// Ranging represents a range [From, To) within an indexable sequence. Structs
// can embed Ranging to satisfy the Ranger interface.
type Ranging struct {
	From int
	To   int
}

// Range returns the Ranging itself.
func (r Ranging) Range() Ranging { return r }
<|endoftext|>