<commit_before>package main

import (
    "bufio"
    "fmt"
    "os"
    "strings"
    "strconv"
)

type address struct {
    ipv4, mask uint
}

func main() {
    s := bufio.NewScanner(os.Stdin)
    s.Scan() // discard first line
    addresses := make(map[string]address)
    for {
        s.Scan()
        line := s.Text()
        if line == "" {
            break
        }

        key, addr := parseLine(line)
        cidr := addr.ipv4 & addr.mask
        add_key := true
        for k, a := range addresses {
            if a.ipv4 & addr.mask == cidr {
                delete(addresses, k)
            } else if addr.ipv4 & a.mask == a.ipv4 & a.mask {
                add_key = !add_key
                break
            }
        }
        if add_key {
            addresses[key] = addr
        }
    }

    for k := range addresses {
        fmt.Printf("%s\n", k)
    }
}

func parseLine(line string)(key string, addr address) {
    tokens := strings.Split(line, "/")
    key = line

    var ipv4 uint
    for i, v := range strings.Split(key, ".") {
        u64, _ := strconv.ParseUint(v, 10, 32)
        octet := uint(u64)
        octet = octet << uint(8 * (4 - i - 1))
        ipv4 |= octet
    }

    bitmask_bits, _ := strconv.Atoi(tokens[1])
    var mask uint = getMask(bitmask_bits)
    addr = address{ipv4, mask}

    return
}

func getMask(bits int)(mask uint) {
    mask = 2
    for i := 1; i < bits; i++ {
        mask = mask * 2
    }
    mask = mask - 1
    mask = mask << uint(32 - bits)
    return
}
<commit_msg>improvements to challeng3 311 go sln<commit_after>package main

import (
    "bufio"
    "fmt"
    "os"
    "strings"
    "strconv"
)

type address struct {
    cidr, mask uint
}

func main() {
    s := bufio.NewScanner(os.Stdin)
    s.Scan() // discard first line
    addresses := make(map[string]address)
    for s.Scan() {
        line := s.Text()
        if line == "" {
            break
        }

        addr := parseLine(line)
        add_key := true
        for k, a := range addresses {
            if a.cidr & addr.mask == addr.cidr {
                delete(addresses, k)
            } else if addr.cidr & a.mask == a.cidr {
                add_key = !add_key
                break
            }
        }
        if add_key {
            addresses[line] = addr
        }
    }

    for k := range addresses {
        fmt.Printf("%s\n", k)
    }
}

func parseLine(line string)(addr address) {
    tokens := strings.Split(line, "/")

    var ipv4 uint
    for i, v := range strings.Split(tokens[0], ".") {
        u64, _ := strconv.ParseUint(v, 10, 32)
        octet := uint(u64)
        octet = octet << uint(8 * (4 - i - 1))
        ipv4 |= octet
    }

    bit_count, _ := strconv.Atoi(tokens[1])
    mask := getMask(bit_count)
    addr = address{ipv4 & mask, mask}

    return
}

func getMask(bit_count int)(mask uint) {
    mask = 2
    for i := 1; i < bit_count; i++ {
        mask = mask * 2
    }
    mask = mask - 1
    mask = mask << uint(32 - bit_count)
    return
}
<|endoftext|>


<commit_before>// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package snippets

// [START healthcare_delete_resource]
import (
	"context"
	"fmt"
	"io"

	healthcare "google.golang.org/api/healthcare/v1"
)

// deleteFHIRResource deletes an FHIR resource.
func deleteFHIRResource(w io.Writer, projectID, location, datasetID, fhirStoreID, resourceType, fhirResourceID string) error {
	ctx := context.Background()

	healthcareService, err := healthcare.NewService(ctx)
	if err != nil {
		return fmt.Errorf("healthcare.NewService: %v", err)
	}

	fhirService := healthcareService.Projects.Locations.Datasets.FhirStores.Fhir

	name := fmt.Sprintf("projects/%s/locations/%s/datasets/%s/fhirStores/%s/fhir/%s/%s", projectID, location, datasetID, fhirStoreID, resourceType, fhirResourceID)

	if _, err := fhirService.Delete(name).Do(); err != nil {
		return fmt.Errorf("Delete: %v", err)
	}

	fmt.Fprintf(w, "Deleted %q", name)

	return nil
}

// [END healthcare_delete_resource]
<commit_msg>healthcare: add comment to clarify that deleted FHIR resources will return 200 OK whether they exist or not (#1448)<commit_after>// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package snippets

// [START healthcare_delete_resource]
import (
	"context"
	"fmt"
	"io"

	healthcare "google.golang.org/api/healthcare/v1"
)

// deleteFHIRResource deletes an FHIR resource.
// Regardless of whether the operation succeeds or
// fails, the server returns a 200 OK HTTP status code. To check that the
// resource was successfully deleted, search for or get the resource and
// see if it exists.
func deleteFHIRResource(w io.Writer, projectID, location, datasetID, fhirStoreID, resourceType, fhirResourceID string) error {
	ctx := context.Background()

	healthcareService, err := healthcare.NewService(ctx)
	if err != nil {
		return fmt.Errorf("healthcare.NewService: %v", err)
	}

	fhirService := healthcareService.Projects.Locations.Datasets.FhirStores.Fhir

	name := fmt.Sprintf("projects/%s/locations/%s/datasets/%s/fhirStores/%s/fhir/%s/%s", projectID, location, datasetID, fhirStoreID, resourceType, fhirResourceID)

	if _, err := fhirService.Delete(name).Do(); err != nil {
		return fmt.Errorf("Delete: %v", err)
	}

	fmt.Fprintf(w, "Deleted %q", name)

	return nil
}

// [END healthcare_delete_resource]
<|endoftext|>


<commit_before>package templating

import (
	"strings"

	"github.com/SpectoLabs/hoverfly/core/models"
	"github.com/aymerick/raymond"
	"strconv"
	"time"
)

type TemplatingData struct {
	Request Request
	State   map[string]string
}

type Request struct {
	QueryParam map[string][]string
	Path       []string
	Scheme     string
}

type Templator struct {
}

var helpersRegistered = false

func NewTemplator() *Templator {

	if !helpersRegistered {
		raymond.RegisterHelper("iso8601DateTime", func() string {
			return time.Now().UTC().Format("2006-01-02T15:04:05Z07:00")
		})

		raymond.RegisterHelper("iso8601DateTimePlusDays", func(days string) string {
			atoi, _ := strconv.Atoi(days)
			return time.Now().AddDate(0, 0, atoi).UTC().Format("2006-01-02T15:04:05Z07:00")
		})

		helpersRegistered = true
	}

	return &Templator{}
}

func (*Templator) ApplyTemplate(requestDetails *models.RequestDetails, state map[string]string, responseBody string) (string, error) {

	t := NewTemplatingDataFromRequest(requestDetails, state)

	if rendered, err := raymond.Render(responseBody, t); err == nil {
		responseBody = rendered
		return responseBody, nil
	} else {
		return "", err
	}
}

func NewTemplatingDataFromRequest(requestDetails *models.RequestDetails, state map[string]string) *TemplatingData {
	return &TemplatingData{
		Request: Request{
			Path:       strings.Split(requestDetails.Path, "/")[1:],
			QueryParam: requestDetails.Query,
			Scheme:     requestDetails.Scheme,
		},
		State: state,
	}

}
<commit_msg>Adding randomString and randomStringLength templating helpers<commit_after>package templating

import (
	"strings"

	"strconv"
	"time"

	"github.com/SpectoLabs/hoverfly/core/models"
	"github.com/SpectoLabs/hoverfly/core/util"
	"github.com/aymerick/raymond"
)

type TemplatingData struct {
	Request Request
	State   map[string]string
}

type Request struct {
	QueryParam map[string][]string
	Path       []string
	Scheme     string
}

type Templator struct {
}

var helpersRegistered = false

func NewTemplator() *Templator {

	if !helpersRegistered {
		raymond.RegisterHelper("iso8601DateTime", func() string {
			return time.Now().UTC().Format("2006-01-02T15:04:05Z07:00")
		})

		raymond.RegisterHelper("iso8601DateTimePlusDays", func(days string) string {
			atoi, _ := strconv.Atoi(days)
			return time.Now().AddDate(0, 0, atoi).UTC().Format("2006-01-02T15:04:05Z07:00")
		})

		raymond.RegisterHelper("randomString", func() string {
			return util.RandomString()
		})

		raymond.RegisterHelper("randomStringLength", func(length int) string {
			return util.RandomStringWithLength(length)
		})

		helpersRegistered = true
	}

	return &Templator{}
}

func (*Templator) ApplyTemplate(requestDetails *models.RequestDetails, state map[string]string, responseBody string) (string, error) {

	t := NewTemplatingDataFromRequest(requestDetails, state)

	if rendered, err := raymond.Render(responseBody, t); err == nil {
		responseBody = rendered
		return responseBody, nil
	} else {
		return "", err
	}
}

func NewTemplatingDataFromRequest(requestDetails *models.RequestDetails, state map[string]string) *TemplatingData {
	return &TemplatingData{
		Request: Request{
			Path:       strings.Split(requestDetails.Path, "/")[1:],
			QueryParam: requestDetails.Query,
			Scheme:     requestDetails.Scheme,
		},
		State: state,
	}

}
<|endoftext|>


<commit_before>// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
//
// This software (Documize Community Edition) is licensed under
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
//
// You can operate outside the AGPL restrictions by purchasing
// Documize Enterprise Edition and obtaining a commercial license
// by contacting <sales@documize.com>.
//
// https://documize.com

package github

import (
	"bytes"
	"encoding/json"
	"errors"
	"html/template"
	"io/ioutil"
	"net/http"
	"strings"

	"github.com/documize/community/core/log"
	"github.com/documize/community/core/section/provider"

	gogithub "github.com/google/go-github/github"
)

// TODO find a smaller image than the one below
const githubGravatar = "https://i2.wp.com/assets-cdn.github.com/images/gravatars/gravatar-user-420.png"

var meta provider.TypeMeta

func init() {
	meta = provider.TypeMeta{}

	meta.ID = "38c0e4c5-291c-415e-8a4d-262ee80ba5df"
	meta.Title = "GitHub"
	meta.Description = "Link code commits and issues"
	meta.ContentType = "github"
	meta.Callback = Callback
}

// Provider represents GitHub
type Provider struct {
}

// Meta describes us.
func (*Provider) Meta() provider.TypeMeta {
	return meta
}

// Command to run the various functions required...
func (p *Provider) Command(ctx *provider.Context, w http.ResponseWriter, r *http.Request) {
	query := r.URL.Query()
	method := query.Get("method")

	if len(method) == 0 {
		msg := "missing method name"
		log.ErrorString("github: " + msg)
		provider.WriteMessage(w, "gitub", msg)
		return
	}

	if method == "config" {
		var ret struct {
			CID string `json:"clientID"`
			URL string `json:"authorizationCallbackURL"`
		}
		ret.CID = clientID()
		ret.URL = authorizationCallbackURL()
		provider.WriteJSON(w, ret)
		return
	}

	defer r.Body.Close() // ignore error

	body, err := ioutil.ReadAll(r.Body)

	if err != nil {
		msg := "Bad body"
		log.ErrorString("github: " + msg)
		provider.WriteMessage(w, "github", msg)
		return
	}

	if method == "saveSecret" { // secret Token update code

		// write the new one, direct from JS
		if err = ctx.SaveSecrets(string(body)); err != nil {
			log.Error("github settoken configuration", err)
			provider.WriteError(w, "github", err)
			return
		}
		provider.WriteEmpty(w)
		return

	}

	// load the config from the client-side
	config := githubConfig{}
	err = json.Unmarshal(body, &config)

	if err != nil {
		log.Error("github Command Unmarshal", err)
		provider.WriteError(w, "github", err)
		return
	}

	config.Clean()
	// always use DB version of the token
	config.Token = ctx.GetSecrets("token") // get the secret token in the database

	client := p.githubClient(&config)

	switch method {

	case "checkAuth":

		if len(config.Token) == 0 {
			err = errors.New("empty github token")
		} else {
			err = validateToken(config.Token)
		}
		if err != nil {
			// token now invalid, so wipe it
			ctx.SaveSecrets("") // ignore error, already in an error state
			log.Error("github check token validation", err)
			provider.WriteError(w, "github", err)
			return
		}
		provider.WriteEmpty(w)

	default:

		if listFailed(method, config, client, w) {

			gr := githubRender{}
			for _, rep := range reports {
				log.IfErr(rep.refresh(&gr, &config, client))
			}
			provider.WriteJSON(w, &gr)

		}

	}
}

// Refresh ... gets the latest version
func (p *Provider) Refresh(ctx *provider.Context, configJSON, data string) string {
	var c = githubConfig{}

	err := json.Unmarshal([]byte(configJSON), &c)

	if err != nil {
		log.Error("unable to unmarshall github config", err)
		return "internal configuration error '" + err.Error() + "'"
	}

	c.Clean()
	c.Token = ctx.GetSecrets("token")

	client := p.githubClient(&c)

	byts, err := json.Marshal(refreshReportData(&c, client))
	if err != nil {
		log.Error("unable to marshall github data", err)
		return "internal configuration error '" + err.Error() + "'"
	}

	return string(byts)

}

func refreshReportData(c *githubConfig, client *gogithub.Client) *githubRender {
	var gr = githubRender{}
	for _, rep := range reports {
		log.IfErr(rep.refresh(&gr, c, client))
	}
	return &gr
}

// Render ... just returns the data given, suitably formatted
func (p *Provider) Render(ctx *provider.Context, config, data string) string {
	var err error

	payload := githubRender{}
	var c = githubConfig{}

	err = json.Unmarshal([]byte(config), &c)

	if err != nil {
		log.Error("unable to unmarshall github config", err)
		return "Please delete and recreate this Github section."
	}

	c.Clean()
	c.Token = ctx.GetSecrets("token")

	data = strings.TrimSpace(data)
	if len(data) == 0 {
		// TODO review why this error occurs & if it should be reported - seems to occur for new sections
		// log.ErrorString(fmt.Sprintf("Rendered empty github JSON payload as '' for owner %s repos %#v", c.Owner, c.Lists))
		return ""
	}

	err = json.Unmarshal([]byte(data), &payload)
	if err != nil {
		log.Error("unable to unmarshall github data", err)
		return "Please delete and recreate this Github section."
	}

	payload.Config = c
	payload.Limit = c.BranchLines
	payload.List = c.Lists

	ret := ""
	for _, repID := range c.ReportOrder {

		rep, ok := reports[repID]
		if !ok {
			msg := "github report not found for: " + repID
			log.ErrorString(msg)
			return "Documize internal error: " + msg
		}

		if err = rep.render(&payload, &c); err != nil {
			log.Error("unable to render "+repID, err)
			return "Documize internal github render " + repID + " error: " + err.Error() + "
" + data
		}

		t := template.New("github")

		t, err = t.Parse(rep.template)

		if err != nil {
			log.Error("github render template.Parse error:", err)
			for k,v := range strings.Split(resp.template,"\n"){
				fmt.Println("DEBUG",k+1,v)
			}
			return "Documize internal github template.Parse error: " + err.Error()
		}

		buffer := new(bytes.Buffer)
		err = t.Execute(buffer, payload)
		if err != nil {
			log.Error("github render template.Execute error:", err)
			return "Documize internal github template.Execute error: " + err.Error()
		}

		ret += buffer.String()

	}
	return ret
}
<commit_msg>add debug message for github template<commit_after>// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
//
// This software (Documize Community Edition) is licensed under
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
//
// You can operate outside the AGPL restrictions by purchasing
// Documize Enterprise Edition and obtaining a commercial license
// by contacting <sales@documize.com>.
//
// https://documize.com

package github

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"html/template"
	"io/ioutil"
	"net/http"
	"strings"

	"github.com/documize/community/core/log"
	"github.com/documize/community/core/section/provider"

	gogithub "github.com/google/go-github/github"
)

// TODO find a smaller image than the one below
const githubGravatar = "https://i2.wp.com/assets-cdn.github.com/images/gravatars/gravatar-user-420.png"

var meta provider.TypeMeta

func init() {
	meta = provider.TypeMeta{}

	meta.ID = "38c0e4c5-291c-415e-8a4d-262ee80ba5df"
	meta.Title = "GitHub"
	meta.Description = "Link code commits and issues"
	meta.ContentType = "github"
	meta.Callback = Callback
}

// Provider represents GitHub
type Provider struct {
}

// Meta describes us.
func (*Provider) Meta() provider.TypeMeta {
	return meta
}

// Command to run the various functions required...
func (p *Provider) Command(ctx *provider.Context, w http.ResponseWriter, r *http.Request) {
	query := r.URL.Query()
	method := query.Get("method")

	if len(method) == 0 {
		msg := "missing method name"
		log.ErrorString("github: " + msg)
		provider.WriteMessage(w, "gitub", msg)
		return
	}

	if method == "config" {
		var ret struct {
			CID string `json:"clientID"`
			URL string `json:"authorizationCallbackURL"`
		}
		ret.CID = clientID()
		ret.URL = authorizationCallbackURL()
		provider.WriteJSON(w, ret)
		return
	}

	defer r.Body.Close() // ignore error

	body, err := ioutil.ReadAll(r.Body)

	if err != nil {
		msg := "Bad body"
		log.ErrorString("github: " + msg)
		provider.WriteMessage(w, "github", msg)
		return
	}

	if method == "saveSecret" { // secret Token update code

		// write the new one, direct from JS
		if err = ctx.SaveSecrets(string(body)); err != nil {
			log.Error("github settoken configuration", err)
			provider.WriteError(w, "github", err)
			return
		}
		provider.WriteEmpty(w)
		return

	}

	// load the config from the client-side
	config := githubConfig{}
	err = json.Unmarshal(body, &config)

	if err != nil {
		log.Error("github Command Unmarshal", err)
		provider.WriteError(w, "github", err)
		return
	}

	config.Clean()
	// always use DB version of the token
	config.Token = ctx.GetSecrets("token") // get the secret token in the database

	client := p.githubClient(&config)

	switch method {

	case "checkAuth":

		if len(config.Token) == 0 {
			err = errors.New("empty github token")
		} else {
			err = validateToken(config.Token)
		}
		if err != nil {
			// token now invalid, so wipe it
			ctx.SaveSecrets("") // ignore error, already in an error state
			log.Error("github check token validation", err)
			provider.WriteError(w, "github", err)
			return
		}
		provider.WriteEmpty(w)

	default:

		if listFailed(method, config, client, w) {

			gr := githubRender{}
			for _, rep := range reports {
				log.IfErr(rep.refresh(&gr, &config, client))
			}
			provider.WriteJSON(w, &gr)

		}

	}
}

// Refresh ... gets the latest version
func (p *Provider) Refresh(ctx *provider.Context, configJSON, data string) string {
	var c = githubConfig{}

	err := json.Unmarshal([]byte(configJSON), &c)

	if err != nil {
		log.Error("unable to unmarshall github config", err)
		return "internal configuration error '" + err.Error() + "'"
	}

	c.Clean()
	c.Token = ctx.GetSecrets("token")

	client := p.githubClient(&c)

	byts, err := json.Marshal(refreshReportData(&c, client))
	if err != nil {
		log.Error("unable to marshall github data", err)
		return "internal configuration error '" + err.Error() + "'"
	}

	return string(byts)

}

func refreshReportData(c *githubConfig, client *gogithub.Client) *githubRender {
	var gr = githubRender{}
	for _, rep := range reports {
		log.IfErr(rep.refresh(&gr, c, client))
	}
	return &gr
}

// Render ... just returns the data given, suitably formatted
func (p *Provider) Render(ctx *provider.Context, config, data string) string {
	var err error

	payload := githubRender{}
	var c = githubConfig{}

	err = json.Unmarshal([]byte(config), &c)

	if err != nil {
		log.Error("unable to unmarshall github config", err)
		return "Please delete and recreate this Github section."
	}

	c.Clean()
	c.Token = ctx.GetSecrets("token")

	data = strings.TrimSpace(data)
	if len(data) == 0 {
		// TODO review why this error occurs & if it should be reported - seems to occur for new sections
		// log.ErrorString(fmt.Sprintf("Rendered empty github JSON payload as '' for owner %s repos %#v", c.Owner, c.Lists))
		return ""
	}

	err = json.Unmarshal([]byte(data), &payload)
	if err != nil {
		log.Error("unable to unmarshall github data", err)
		return "Please delete and recreate this Github section."
	}

	payload.Config = c
	payload.Limit = c.BranchLines
	payload.List = c.Lists

	ret := ""
	for _, repID := range c.ReportOrder {

		rep, ok := reports[repID]
		if !ok {
			msg := "github report not found for: " + repID
			log.ErrorString(msg)
			return "Documize internal error: " + msg
		}

		if err = rep.render(&payload, &c); err != nil {
			log.Error("unable to render "+repID, err)
			return "Documize internal github render " + repID + " error: " + err.Error() + "
" + data
		}

		t := template.New("github")

		t, err = t.Parse(rep.template)

		if err != nil {
			log.Error("github render template.Parse error:", err)
			for k, v := range strings.Split(rep.template, "\n") {
				fmt.Println("DEBUG", k+1, v)
			}
			return "Documize internal github template.Parse error: " + err.Error()
		}

		buffer := new(bytes.Buffer)
		err = t.Execute(buffer, payload)
		if err != nil {
			log.Error("github render template.Execute error:", err)
			return "Documize internal github template.Execute error: " + err.Error()
		}

		ret += buffer.String()

	}
	return ret
}
<|endoftext|>


<commit_before>package main

import (
	"./arena"
	"fmt"
	"math/rand"
	"time"
	"github.com/nsf/termbox-go"
)

func putString(x, y int, s string) {
	for i, r := range s {
		termbox.SetCell(x+i, y, r, 0, 0)
	}
}

func draw(ox, oy int, s arena.State) {
	str := fmt.Sprintf("Score: %d", len(s.Snake.Segments))
	putString(ox+1, oy+1, str)
	for i := -1; i<=s.Size.X; i++ {
		for j := -1; j<=s.Size.Y; j++ {
			if i == -1 || i == s.Size.X || j == -1 || j == s.Size.Y {
				termbox.SetCell(ox+i, oy+j, '#', 0, 0)
			}
		}
	}
	for _, p := range s.Snake.Segments {
		termbox.SetCell(ox+p.X, oy+p.Y, '#', 0, 0)
	}
	p := s.PointItem
	termbox.SetCell(ox+p.X, oy+p.Y, '*', 0, 0)
	if s.GameIsOver {
		putString(ox+s.Size.X/2 - 8, oy+s.Size.Y/2-2, "   Game Over  ")
		putString(ox+s.Size.X/2 - 8, oy+s.Size.Y/2+0, "Enter: Restart")
		putString(ox+s.Size.X/2 - 8, oy+s.Size.Y/2+1, "ESC: Exit")
	}

}

func eventChannel() <-chan termbox.Event {
	events := make(chan termbox.Event)
	go func() {
		for {
			events <- termbox.PollEvent()
		}
	}()
	return events
}

func main() {
	rand.Seed(time.Now().UnixNano())
	termbox.Init()
	defer termbox.Close()
	x, y := termbox.Size()
	offsetx, offsety := 2, 2
	ax, ay := x - 2*offsetx, y - 2*offsety
	a := arena.New(ax, ay)
	tick := time.Tick(100*time.Millisecond)
	event := eventChannel()
	running := true

	handleKey := map[termbox.Key]func() {
		termbox.KeyEsc: func(){running = false},
		termbox.KeyEnter: func(){a = arena.New(ax, ay)},
		termbox.KeyArrowRight: func(){a.SetSnakeHeading(arena.EAST)},
		termbox.KeyArrowUp: func(){a.SetSnakeHeading(arena.NORTH)},
		termbox.KeyArrowLeft: func(){a.SetSnakeHeading(arena.WEST)},
		termbox.KeyArrowDown: func(){a.SetSnakeHeading(arena.SOUTH)},
	}

	for running {
		termbox.Clear(0, 0)
		draw(offsetx, offsety, a.State())
		termbox.Flush()
		select {
		case ev:=<-event:
			if ev.Type == termbox.EventKey {
				f := handleKey[ev.Key]
				if f != nil {
					f()
				}
			}
		case <-tick:
			a.Tick()
		}
	}
}
<commit_msg>Widgetizing user interface.<commit_after>package main

import (
	"fmt"
	"github.com/dragonfi/go-retro/snake/arena"
	"github.com/nsf/termbox-go"
	"math/rand"
	"time"
)

type Position struct {
	X, Y int
}

func putString(x, y int, s string) {
	for i, r := range s {
		termbox.SetCell(x+i, y, r, 0, 0)
	}
}

type ArenaWidget struct {
	arena  arena.Arena
	offset Position
	size   Position
	state  arena.State
}

func (w *ArenaWidget) Tick() {
	w.arena.Tick()
	w.state = w.arena.State()
}

func (w *ArenaWidget) SetSnakeHeading(direction arena.Direction) {
	w.arena.SetSnakeHeading(direction)
}

func (w ArenaWidget) setCell(x, y int, r rune, fg, bg termbox.Attribute) {
	termbox.SetCell(w.offset.X+x, w.offset.Y+y, r, fg, bg)
}

func (w ArenaWidget) putString(x, y int, str string) {
	putString(w.offset.X+x, w.offset.Y+y, str)
}

func (w ArenaWidget) drawBorder() {
	s := w.state
	for i := -1; i <= s.Size.X; i++ {
		for j := -1; j <= s.Size.Y; j++ {
			if i == -1 || i == s.Size.X || j == -1 || j == s.Size.Y {
				w.setCell(i, j, '#', 0, 0)
			}
		}
	}
}

func (w ArenaWidget) drawSnake() {
	for _, p := range w.state.Snake.Segments {
		w.setCell(p.X, p.Y, '#', 0, 0)
	}
}

func (w ArenaWidget) drawPointItem() {
	p := w.state.PointItem
	w.setCell(p.X, p.Y, '*', 0, 0)
}

func (w ArenaWidget) putGameOverText() {
	s := w.state
	w.putString(s.Size.X/2-9, s.Size.Y/2-3, "##################")
	w.putString(s.Size.X/2-9, s.Size.Y/2-2, "#    Game Over   #")
	w.putString(s.Size.X/2-9, s.Size.Y/2-1, "#                #")
	w.putString(s.Size.X/2-9, s.Size.Y/2+0, "# Enter: Restart #")
	w.putString(s.Size.X/2-9, s.Size.Y/2+1, "# ESC: Exit      #")
	w.putString(s.Size.X/2-9, s.Size.Y/2+2, "##################")
}

func (w ArenaWidget) putScore() {
	s := w.state
	w.putString(1, 1, fmt.Sprintf("Score: %d", len(s.Snake.Segments)))
}

func (w ArenaWidget) Draw() {
	s := w.arena.State()
	w.drawBorder()
	w.putScore()
	w.drawSnake()
	w.drawPointItem()
	if s.GameIsOver {
		w.putGameOverText()
	}
}

func (w *ArenaWidget) ResetArena() {
	w.arena = arena.New(w.size.X, w.size.Y)
}

func NewArenaWidget(ox, oy, x, y int) ArenaWidget {
	w := ArenaWidget{offset: Position{ox, oy}, size: Position{x, y}}
	w.ResetArena()
	return w
}

func eventChannel() <-chan termbox.Event {
	events := make(chan termbox.Event)
	go func() {
		for {
			events <- termbox.PollEvent()
		}
	}()
	return events
}

func main() {
	rand.Seed(time.Now().UnixNano())
	termbox.Init()
	defer termbox.Close()
	x, y := termbox.Size()
	offsetx, offsety := 2, 2
	aw := NewArenaWidget(offsetx, offsety, x-2*offsetx, y-2*offsety)
	tick := time.Tick(100 * time.Millisecond)
	event := eventChannel()
	running := true

	handleKey := map[termbox.Key]func(){
		termbox.KeyEsc:        func() { running = false },
		termbox.KeyEnter:      func() { aw.ResetArena() },
		termbox.KeyArrowRight: func() { aw.SetSnakeHeading(arena.EAST) },
		termbox.KeyArrowUp:    func() { aw.SetSnakeHeading(arena.NORTH) },
		termbox.KeyArrowLeft:  func() { aw.SetSnakeHeading(arena.WEST) },
		termbox.KeyArrowDown:  func() { aw.SetSnakeHeading(arena.SOUTH) },
	}

	for running {
		termbox.Clear(0, 0)
		aw.Draw()
		termbox.Flush()
		select {
		case ev := <-event:
			if ev.Type == termbox.EventKey {
				f := handleKey[ev.Key]
				if f != nil {
					f()
				}
			}
		case <-tick:
			aw.Tick()
		}
	}
}
<|endoftext|>


<commit_before>package redsync

import (
	"crypto/rand"
	"encoding/base64"
	"sync"
	"time"

	"github.com/gomodule/redigo/redis"
)

// A DelayFunc is used to decide the amount of time to wait between retries.
type DelayFunc func(tries int) time.Duration

// A Mutex is a distributed mutual exclusion lock.
type Mutex struct {
	name   string
	expiry time.Duration

	tries     int
	delayFunc DelayFunc

	factor float64

	quorum int

	genValueFunc func() (string, error)
	value        string
	until        time.Time

	nodem sync.Mutex

	pools []Pool
}

// Lock locks m. In case it returns an error on failure, you may retry to acquire the lock by calling this method again.
func (m *Mutex) Lock() error {
	m.nodem.Lock()
	defer m.nodem.Unlock()

	value, err := m.genValueFunc()
	if err != nil {
		return err
	}

	for i := 0; i < m.tries; i++ {
		if i != 0 {
			time.Sleep(m.delayFunc(i))
		}

		start := time.Now()

		n := m.actOnPoolsAsync(func(pool Pool) bool {
			return m.acquire(pool, value)
		})

		until := time.Now().Add(m.expiry - time.Now().Sub(start) - time.Duration(int64(float64(m.expiry)*m.factor)) + 2*time.Millisecond)
		if n >= m.quorum && time.Now().Before(until) {
			m.value = value
			m.until = until
			return nil
		}
		m.actOnPoolsAsync(func(pool Pool) bool {
			return m.release(pool, value)
		})
	}

	return ErrFailed
}

// Unlock unlocks m and returns the status of unlock.
func (m *Mutex) Unlock() bool {
	m.nodem.Lock()
	defer m.nodem.Unlock()

	n := m.actOnPoolsAsync(func(pool Pool) bool {
		return m.release(pool, m.value)
	})
	return n >= m.quorum
}

// Extend resets the mutex's expiry and returns the status of expiry extension.
func (m *Mutex) Extend() bool {
	m.nodem.Lock()
	defer m.nodem.Unlock()

	n := m.actOnPoolsAsync(func(pool Pool) bool {
		return m.touch(pool, m.value, int(m.expiry/time.Millisecond))
	})
	return n >= m.quorum
}

func genValue() (string, error) {
	b := make([]byte, 32)
	_, err := rand.Read(b)
	if err != nil {
		return "", err
	}
	return base64.StdEncoding.EncodeToString(b), nil
}

func (m *Mutex) acquire(pool Pool, value string) bool {
	conn := pool.Get()
	defer conn.Close()
	reply, err := redis.String(conn.Do("SET", m.name, value, "NX", "PX", int(m.expiry/time.Millisecond)))
	return err == nil && reply == "OK"
}

var deleteScript = redis.NewScript(1, `
	if redis.call("GET", KEYS[1]) == ARGV[1] then
		return redis.call("DEL", KEYS[1])
	else
		return 0
	end
`)

func (m *Mutex) release(pool Pool, value string) bool {
	conn := pool.Get()
	defer conn.Close()
	status, err := deleteScript.Do(conn, m.name, value)
	return err == nil && status != 0
}

var touchScript = redis.NewScript(1, `
	if redis.call("GET", KEYS[1]) == ARGV[1] then
		return redis.call("SET", KEYS[1], ARGV[1], "XX", "PX", ARGV[2])
	else
		return "ERR"
	end
`)

func (m *Mutex) touch(pool Pool, value string, expiry int) bool {
	conn := pool.Get()
	defer conn.Close()
	status, err := redis.String(touchScript.Do(conn, m.name, value, expiry))
	return err == nil && status != "ERR"
}

func (m *Mutex) actOnPoolsAsync(actFn func(Pool) bool) int {
	ch := make(chan bool)
	for _, pool := range m.pools {
		go func(pool Pool) {
			ch <- actFn(pool)
		}(pool)
	}
	n := 0
	for range m.pools {
		if <-ch {
			n++
		}
	}
	return n
}
<commit_msg>Updates touch script<commit_after>package redsync

import (
	"crypto/rand"
	"encoding/base64"
	"sync"
	"time"

	"github.com/gomodule/redigo/redis"
)

// A DelayFunc is used to decide the amount of time to wait between retries.
type DelayFunc func(tries int) time.Duration

// A Mutex is a distributed mutual exclusion lock.
type Mutex struct {
	name   string
	expiry time.Duration

	tries     int
	delayFunc DelayFunc

	factor float64

	quorum int

	genValueFunc func() (string, error)
	value        string
	until        time.Time

	nodem sync.Mutex

	pools []Pool
}

// Lock locks m. In case it returns an error on failure, you may retry to acquire the lock by calling this method again.
func (m *Mutex) Lock() error {
	m.nodem.Lock()
	defer m.nodem.Unlock()

	value, err := m.genValueFunc()
	if err != nil {
		return err
	}

	for i := 0; i < m.tries; i++ {
		if i != 0 {
			time.Sleep(m.delayFunc(i))
		}

		start := time.Now()

		n := m.actOnPoolsAsync(func(pool Pool) bool {
			return m.acquire(pool, value)
		})

		until := time.Now().Add(m.expiry - time.Now().Sub(start) - time.Duration(int64(float64(m.expiry)*m.factor)) + 2*time.Millisecond)
		if n >= m.quorum && time.Now().Before(until) {
			m.value = value
			m.until = until
			return nil
		}
		m.actOnPoolsAsync(func(pool Pool) bool {
			return m.release(pool, value)
		})
	}

	return ErrFailed
}

// Unlock unlocks m and returns the status of unlock.
func (m *Mutex) Unlock() bool {
	m.nodem.Lock()
	defer m.nodem.Unlock()

	n := m.actOnPoolsAsync(func(pool Pool) bool {
		return m.release(pool, m.value)
	})
	return n >= m.quorum
}

// Extend resets the mutex's expiry and returns the status of expiry extension.
func (m *Mutex) Extend() bool {
	m.nodem.Lock()
	defer m.nodem.Unlock()

	n := m.actOnPoolsAsync(func(pool Pool) bool {
		return m.touch(pool, m.value, int(m.expiry/time.Millisecond))
	})
	return n >= m.quorum
}

func genValue() (string, error) {
	b := make([]byte, 32)
	_, err := rand.Read(b)
	if err != nil {
		return "", err
	}
	return base64.StdEncoding.EncodeToString(b), nil
}

func (m *Mutex) acquire(pool Pool, value string) bool {
	conn := pool.Get()
	defer conn.Close()
	reply, err := redis.String(conn.Do("SET", m.name, value, "NX", "PX", int(m.expiry/time.Millisecond)))
	return err == nil && reply == "OK"
}

var deleteScript = redis.NewScript(1, `
	if redis.call("GET", KEYS[1]) == ARGV[1] then
		return redis.call("DEL", KEYS[1])
	else
		return 0
	end
`)

func (m *Mutex) release(pool Pool, value string) bool {
	conn := pool.Get()
	defer conn.Close()
	status, err := deleteScript.Do(conn, m.name, value)
	return err == nil && status != 0
}

var touchScript = redis.NewScript(1, `
	if redis.call("GET", KEYS[1]) == ARGV[1] then
		return redis.call("pexpire", KEYS[1], ARGV[2])
	else
		return 0
	end
`)

func (m *Mutex) touch(pool Pool, value string, expiry int) bool {
	conn := pool.Get()
	defer conn.Close()
	status, err := touchScript.Do(conn, m.name, value, expiry)
	return err == nil && status != 0
}

func (m *Mutex) actOnPoolsAsync(actFn func(Pool) bool) int {
	ch := make(chan bool)
	for _, pool := range m.pools {
		go func(pool Pool) {
			ch <- actFn(pool)
		}(pool)
	}
	n := 0
	for range m.pools {
		if <-ch {
			n++
		}
	}
	return n
}
<|endoftext|>


<commit_before>package rules

import (
	"errors"
	"fmt"
	"github.com/matttproud/prometheus/rules/ast"
	"io"
	"os"
	"strings"
)

// NOTE: This parser is non-reentrant due to its dependence on global state.

// GoLex sadly needs these global variables for storing temporary token/parsing information.
var yylval *yySymType // For storing extra token information, like the contents of a string.
var yyline int        // Line number within the current file or buffer.
var yypos int         // Character position within the current line.

type RulesLexer struct {
	errors      []string // Errors encountered during parsing.
	startToken  int      // Dummy token to simulate multiple start symbols (see below).
	parsedRules []*Rule  // Parsed full rules.
	parsedExpr  ast.Node // Parsed single expression.
}

func (lexer *RulesLexer) Lex(lval *yySymType) int {
	yylval = lval

	// We simulate multiple start symbols for closely-related grammars via dummy tokens. See
	// http://www.gnu.org/software/bison/manual/html_node/Multiple-start_002dsymbols.html
	// Reason: we want to be able to parse lists of named rules as well as single expressions.
	if lexer.startToken != 0 {
		startToken := lexer.startToken
		lexer.startToken = 0
		return startToken
	}

	tokenType := yylex()
	return tokenType
}

func (lexer *RulesLexer) Error(errorStr string) {
	err := fmt.Sprintf("Error parsing rules at line %v, char %v: %v", yyline, yypos, errorStr)
	lexer.errors = append(lexer.errors, err)
}

func LoadFromReader(rulesReader io.Reader, singleExpr bool) (interface{}, error) {
	yyin = rulesReader
	yypos = 1
	yyline = 1
	yydata = ""
	yytext = ""

	lexer := &RulesLexer{
		startToken: START_RULES,
	}

	if singleExpr {
		lexer.startToken = START_EXPRESSION
	}

	ret := yyParse(lexer)
	if ret != 0 && len(lexer.errors) == 0 {
		lexer.Error("Unknown parser error")
	}

	if len(lexer.errors) > 0 {
		err := errors.New(strings.Join(lexer.errors, "\n"))
		return nil, err
	}

	if singleExpr {
		return lexer.parsedExpr, nil
	} else {
		return lexer.parsedRules, nil
	}
	panic("")
}

func LoadRulesFromReader(rulesReader io.Reader) ([]*Rule, error) {
	expr, err := LoadFromReader(rulesReader, false)
	if err != nil {
		return nil, err
	}
	return expr.([]*Rule), err
}

func LoadRulesFromString(rulesString string) ([]*Rule, error) {
	rulesReader := strings.NewReader(rulesString)
	return LoadRulesFromReader(rulesReader)
}

func LoadRulesFromFile(fileName string) ([]*Rule, error) {
	rulesReader, err := os.Open(fileName)
	defer rulesReader.Close()
	if err != nil {
		return []*Rule{}, err
	}
	return LoadRulesFromReader(rulesReader)
}

func LoadExprFromReader(exprReader io.Reader) (ast.Node, error) {
	expr, err := LoadFromReader(exprReader, true)
	if err != nil {
		return nil, err
	}
	return expr.(ast.Node), err
}

func LoadExprFromString(exprString string) (ast.Node, error) {
	exprReader := strings.NewReader(exprString)
	return LoadExprFromReader(exprReader)
}

func LoadExprFromFile(fileName string) (ast.Node, error) {
	exprReader, err := os.Open(fileName)
	defer exprReader.Close()
	if err != nil {
		return nil, err
	}
	return LoadExprFromReader(exprReader)
}
<commit_msg>Only close rule file if it could be opened.<commit_after>package rules

import (
	"errors"
	"fmt"
	"github.com/matttproud/prometheus/rules/ast"
	"io"
	"os"
	"strings"
)

// NOTE: This parser is non-reentrant due to its dependence on global state.

// GoLex sadly needs these global variables for storing temporary token/parsing information.
var yylval *yySymType // For storing extra token information, like the contents of a string.
var yyline int        // Line number within the current file or buffer.
var yypos int         // Character position within the current line.

type RulesLexer struct {
	errors      []string // Errors encountered during parsing.
	startToken  int      // Dummy token to simulate multiple start symbols (see below).
	parsedRules []*Rule  // Parsed full rules.
	parsedExpr  ast.Node // Parsed single expression.
}

func (lexer *RulesLexer) Lex(lval *yySymType) int {
	yylval = lval

	// We simulate multiple start symbols for closely-related grammars via dummy tokens. See
	// http://www.gnu.org/software/bison/manual/html_node/Multiple-start_002dsymbols.html
	// Reason: we want to be able to parse lists of named rules as well as single expressions.
	if lexer.startToken != 0 {
		startToken := lexer.startToken
		lexer.startToken = 0
		return startToken
	}

	tokenType := yylex()
	return tokenType
}

func (lexer *RulesLexer) Error(errorStr string) {
	err := fmt.Sprintf("Error parsing rules at line %v, char %v: %v", yyline, yypos, errorStr)
	lexer.errors = append(lexer.errors, err)
}

func LoadFromReader(rulesReader io.Reader, singleExpr bool) (interface{}, error) {
	yyin = rulesReader
	yypos = 1
	yyline = 1
	yydata = ""
	yytext = ""

	lexer := &RulesLexer{
		startToken: START_RULES,
	}

	if singleExpr {
		lexer.startToken = START_EXPRESSION
	}

	ret := yyParse(lexer)
	if ret != 0 && len(lexer.errors) == 0 {
		lexer.Error("Unknown parser error")
	}

	if len(lexer.errors) > 0 {
		err := errors.New(strings.Join(lexer.errors, "\n"))
		return nil, err
	}

	if singleExpr {
		return lexer.parsedExpr, nil
	} else {
		return lexer.parsedRules, nil
	}
	panic("")
}

func LoadRulesFromReader(rulesReader io.Reader) ([]*Rule, error) {
	expr, err := LoadFromReader(rulesReader, false)
	if err != nil {
		return nil, err
	}
	return expr.([]*Rule), err
}

func LoadRulesFromString(rulesString string) ([]*Rule, error) {
	rulesReader := strings.NewReader(rulesString)
	return LoadRulesFromReader(rulesReader)
}

func LoadRulesFromFile(fileName string) ([]*Rule, error) {
	rulesReader, err := os.Open(fileName)
	defer rulesReader.Close()
	if err != nil {
		return []*Rule{}, err
	}
	return LoadRulesFromReader(rulesReader)
}

func LoadExprFromReader(exprReader io.Reader) (ast.Node, error) {
	expr, err := LoadFromReader(exprReader, true)
	if err != nil {
		return nil, err
	}
	return expr.(ast.Node), err
}

func LoadExprFromString(exprString string) (ast.Node, error) {
	exprReader := strings.NewReader(exprString)
	return LoadExprFromReader(exprReader)
}

func LoadExprFromFile(fileName string) (ast.Node, error) {
	exprReader, err := os.Open(fileName)
	if err != nil {
		return nil, err
	}
	defer exprReader.Close()
	return LoadExprFromReader(exprReader)
}
<|endoftext|>


<commit_before>// Copyright 2018 The Hugo Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package hugolib

import (
	"testing"

	qt "github.com/frankban/quicktest"
)

// Just some simple test of the embedded templates to avoid
// https://github.com/gohugoio/hugo/issues/4757 and similar.
// TODO(bep) fix me https://github.com/gohugoio/hugo/issues/5926
func _TestEmbeddedTemplates(t *testing.T) {
	t.Parallel()

	c := qt.New(t)
	c.Assert(true, qt.Equals, true)

	home := []string{"index.html", `
GA:
{{ template "_internal/google_analytics.html" . }}

GA async:

{{ template "_internal/google_analytics_async.html" . }}

Disqus:

{{ template "_internal/disqus.html" . }}

`}

	b := newTestSitesBuilder(t)
	b.WithSimpleConfigFile().WithTemplatesAdded(home...)

	b.Build(BuildCfg{})

	// Gheck GA regular and async
	b.AssertFileContent("public/index.html",
		"'anonymizeIp', true",
		"'script','https://www.google-analytics.com/analytics.js','ga');\n\tga('create', 'ga_id', 'auto')",
		"<script async src='https://www.google-analytics.com/analytics.js'>")

	// Disqus
	b.AssertFileContent("public/index.html", "\"disqus_shortname\" + '.disqus.com/embed.js';")
}
<commit_msg>Add some internal template image tests<commit_after>// Copyright 2018 The Hugo Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package hugolib

import (
	"testing"

	qt "github.com/frankban/quicktest"
)

// Just some simple test of the embedded templates to avoid
// https://github.com/gohugoio/hugo/issues/4757 and similar.
// TODO(bep) fix me https://github.com/gohugoio/hugo/issues/5926
func _TestEmbeddedTemplates(t *testing.T) {
	t.Parallel()

	c := qt.New(t)
	c.Assert(true, qt.Equals, true)

	home := []string{"index.html", `
GA:
{{ template "_internal/google_analytics.html" . }}

GA async:

{{ template "_internal/google_analytics_async.html" . }}

Disqus:

{{ template "_internal/disqus.html" . }}

`}

	b := newTestSitesBuilder(t)
	b.WithSimpleConfigFile().WithTemplatesAdded(home...)

	b.Build(BuildCfg{})

	// Gheck GA regular and async
	b.AssertFileContent("public/index.html",
		"'anonymizeIp', true",
		"'script','https://www.google-analytics.com/analytics.js','ga');\n\tga('create', 'ga_id', 'auto')",
		"<script async src='https://www.google-analytics.com/analytics.js'>")

	// Disqus
	b.AssertFileContent("public/index.html", "\"disqus_shortname\" + '.disqus.com/embed.js';")
}

func TestInternalTemplatesImage(t *testing.T) {
	config := `
baseURL = "https://example.org"

[params]
images=["siteimg1.jpg", "siteimg2.jpg"]

`
	b := newTestSitesBuilder(t).WithConfigFile("toml", config)

	b.WithContent("mybundle/index.md", `---
title: My Bundle
---
`)

	b.WithContent("mypage.md", `---
title: My Page
images: ["pageimg1.jpg", "pageimg2.jpg"]
---
`)

	b.WithContent("mysite.md", `---
title: My Site
---
`)

	b.WithTemplatesAdded("_default/single.html", `

{{ template "_internal/twitter_cards.html" . }}
{{ template "_internal/opengraph.html" . }}
{{ template "_internal/schema.html" . }}

`)

	b.WithSunset("content/mybundle/featured-sunset.jpg")
	b.Build(BuildCfg{})

	b.AssertFileContent("public/mybundle/index.html", `
<meta name="twitter:image" content="https://example.org/mybundle/featured-sunset.jpg"/>
<meta name="twitter:title" content="My Bundle"/>
<meta property="og:title" content="My Bundle" />
<meta property="og:url" content="https://example.org/mybundle/" />
<meta property="og:image" content="https://example.org/mybundle/featured-sunset.jpg"/>
<meta itemprop="name" content="My Bundle">
<meta itemprop="image" content="https://example.org/mybundle/featured-sunset.jpg">

`)
	b.AssertFileContent("public/mypage/index.html", `
<meta name="twitter:image" content="https://example.org/pageimg1.jpg"/>
<meta property="og:image" content="https://example.org/pageimg1.jpg" />
<meta property="og:image" content="https://example.org/pageimg2.jpg" />
<meta itemprop="image" content="https://example.org/pageimg1.jpg">
<meta itemprop="image" content="https://example.org/pageimg2.jpg">
`)
	b.AssertFileContent("public/mysite/index.html", `
<meta name="twitter:image" content="https://example.org/siteimg1.jpg"/>
<meta property="og:image" content="https://example.org/siteimg1.jpg"/>
<meta itemprop="image" content="https://example.org/siteimg1.jpg"/>
`)

}
<|endoftext|>


<commit_before>package sms

import (
	"github.com/kevinburke/twilio-go"
	"log"
	"strings"
	"time"
)

type TwilioSMS struct {
	To string
	Body string
}

func GenerateTwilioErrorSMS(errs []error, service string) []*TwilioSMS {

	var smsArr []*TwilioSMS
	for _, recipient := range conf.To {

		var lines = []string{
			"Dear Admin,",
			"An error with the service " + strings.ToUpper(service) + " occurred:",
			"Timestamp: " + time.Now().Format(timestampFormat),
		}
		if len(errs) > 0 {
			lines = append(lines, "Errors: ")
			for _, e := range errs {
				lines = append(lines, e.Error())
			}
		}
		smsArr = append(smsArr, &TwilioSMS{
			To:      recipient,
			Body: strings.Join(lines, "\n"),
		})
	}

	return smsArr
}

func GenerateTwilioResolvedSMS(service string) []*TwilioSMS {

	var smsArr []*TwilioSMS
	for _, recipient := range conf.To {

		var lines = []string{
			"Dear Admin,",
			"service " + strings.ToUpper(service) + " is back to normal operation",
			"Timestamp: " + time.Now().Format(timestampFormat),
		}
		smsArr = append(smsArr, &TwilioSMS{
			To:      recipient,
			Body: strings.Join(lines, "\n"),
		})
	}

	return smsArr
}

func SendTwilioSMS(sms []*TwilioSMS) {

	client := twilio.NewClient(conf.TwilioSID, conf.TwilioToken, nil)
	for _, s := range sms {

		// Send a message
		_, err := client.Messages.SendMessage(conf.From, s.To, s.Body, nil)
		if err != nil {
			log.Fatal(err)
		}
		//fmt.Println(msg.Status)
	}
}
<commit_msg>dont fatal when sending twilio message fails<commit_after>package sms

import (
	"fmt"
	"github.com/kevinburke/twilio-go"
	"strings"
	"time"
)

type TwilioSMS struct {
	To string
	Body string
}

func GenerateTwilioErrorSMS(errs []error, service string) []*TwilioSMS {

	var smsArr []*TwilioSMS
	for _, recipient := range conf.To {

		var lines = []string{
			"Dear Admin,",
			"An error with the service " + strings.ToUpper(service) + " occurred:",
			"Timestamp: " + time.Now().Format(timestampFormat),
		}
		if len(errs) > 0 {
			lines = append(lines, "Errors: ")
			for _, e := range errs {
				lines = append(lines, e.Error())
			}
		}
		smsArr = append(smsArr, &TwilioSMS{
			To:      recipient,
			Body: strings.Join(lines, "\n"),
		})
	}

	return smsArr
}

func GenerateTwilioResolvedSMS(service string) []*TwilioSMS {

	var smsArr []*TwilioSMS
	for _, recipient := range conf.To {

		var lines = []string{
			"Dear Admin,",
			"service " + strings.ToUpper(service) + " is back to normal operation",
			"Timestamp: " + time.Now().Format(timestampFormat),
		}
		smsArr = append(smsArr, &TwilioSMS{
			To:      recipient,
			Body: strings.Join(lines, "\n"),
		})
	}

	return smsArr
}

func SendTwilioSMS(sms []*TwilioSMS) {

	client := twilio.NewClient(conf.TwilioSID, conf.TwilioToken, nil)
	for _, s := range sms {

		// Send a message
		_, err := client.Messages.SendMessage(conf.From, s.To, s.Body, nil)
		if err != nil {
			fmt.Println(err)
		}
		//fmt.Println(msg.Status)
	}
}
<|endoftext|>


<commit_before>package models

// Message holds message
type Message struct {
	Mid         string       `json:"mid,omitempty"`
	Text        string       `json:"text"`
	Attachments []Attachment `json:"attachments,omitempty"`
	QuickReplay QuickReplay  `json:"quick_reply,omitempty"`
}

// Attachment struct holding attachments
type Attachment struct {
	Type    string  `json:"type"`
	Payload Payload `json:"payload"`
}

// Payload may be multimedia or a location
type Payload struct {
	URL          string   `json:"url,omitempty"`
	Location     Location `json:"location,omitempty"`
	TemplateType string   `json:"template_type,omitempty"`
}

// TODO test this

// Location cordinates
type Location struct {
	Lat  int64 `json:"coridantes.lat"`
	Long int64 `json:"coridantes.long"`
}

//QuickReplay :text provided via QuickReplay
type QuickReplay struct {
	Payload string `json:"payload"`
}
<commit_msg>changed qr to array<commit_after>package models

// Message holds message
type Message struct {
	Mid         string        `json:"mid,omitempty"`
	Text        string        `json:"text"`
	Attachments []Attachment  `json:"attachments,omitempty"`
	QuickReplay []QuickReplay `json:"quick_reply,omitempty"`
}

// Attachment struct holding attachments
type Attachment struct {
	Type    string  `json:"type"`
	Payload Payload `json:"payload"`
}

// Payload may be multimedia or a location
type Payload struct {
	URL          string   `json:"url,omitempty"`
	Location     Location `json:"location,omitempty"`
	TemplateType string   `json:"template_type,omitempty"`
}

// TODO test this

// Location cordinates
type Location struct {
	Lat  int64 `json:"coridantes.lat"`
	Long int64 `json:"coridantes.long"`
}

//QuickReplay :text provided via QuickReplay
type QuickReplay struct {
	Payload string `json:"payload"`
}
<|endoftext|>


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

package rocserv

import (
	"flag"
	"fmt"
	"github.com/shawnfeng/roc/util/service/sla"
	"github.com/shawnfeng/sutil/trace"
	"reflect"

	"github.com/julienschmidt/httprouter"

	"git.apache.org/thrift.git/lib/go/thrift"

	"github.com/shawnfeng/sutil/slog"
	"github.com/shawnfeng/sutil/slog/statlog"
)

const (
	PROCESSOR_HTTP   = "http"
	PROCESSOR_THRIFT = "thrift"
	PROCESSOR_GRPC   = "gprc"
)

type Service struct {
}

var service Service

//func NewService

type cmdArgs struct {
	servLoc string
	logDir  string
	sessKey string
}

func (m *Service) parseFlag() (*cmdArgs, error) {
	var serv, logDir, skey string
	flag.StringVar(&serv, "serv", "", "servic name")
	flag.StringVar(&logDir, "logdir", "", "serice log dir")
	flag.StringVar(&skey, "skey", "", "service session key")

	flag.Parse()

	if len(serv) == 0 {
		return nil, fmt.Errorf("serv args need!")
	}

	if len(skey) == 0 {
		return nil, fmt.Errorf("skey args need!")
	}

	return &cmdArgs{
		servLoc: serv,
		logDir:  logDir,
		sessKey: skey,
	}, nil

}

func (m *Service) loadDriver(sb ServBase, procs map[string]Processor) (map[string]*ServInfo, error) {
	fun := "Service.loadDriver -->"

	infos := make(map[string]*ServInfo)

	// load processor's driver
	for n, p := range procs {
		addr, driver := p.Driver()
		if driver == nil {
			slog.Infof("%s processor:%s no driver", fun, n)
			continue
		}

		slog.Infof("%s processor:%s type:%s addr:%s", fun, n, reflect.TypeOf(driver), addr)

		switch d := driver.(type) {
		case *httprouter.Router:
			sa, err := powerHttp(addr, d)
			if err != nil {
				return nil, err
			}

			slog.Infof("%s load ok processor:%s serv addr:%s", fun, n, sa)
			infos[n] = &ServInfo{
				Type: PROCESSOR_HTTP,
				Addr: sa,
			}

		case thrift.TProcessor:
			sa, err := powerThrift(addr, d)
			if err != nil {
				return nil, err
			}

			slog.Infof("%s load ok processor:%s serv addr:%s", fun, n, sa)
			infos[n] = &ServInfo{
				Type: PROCESSOR_THRIFT,
				Addr: sa,
			}
		case *GrpcServer:
			sa, err := powerGrpc(addr, d)
			if err != nil {
				return nil, err
			}

			slog.Infof("%s load ok processor:%s serv addr:%s", fun, n, sa)
			infos[n] = &ServInfo{
				Type: PROCESSOR_GRPC,
				Addr: sa,
			}
		default:
			return nil, fmt.Errorf("processor:%s driver not recognition", n)

		}

	}

	return infos, nil

}

func (m *Service) Serve(confEtcd configEtcd, initfn func(ServBase) error, procs map[string]Processor) error {
	fun := "Service.Serve -->"

	args, err := m.parseFlag()
	if err != nil {
		slog.Panicf("%s parse arg err:%s", fun, err)
		return err
	}

	return m.Init(confEtcd, args.servLoc, args.sessKey, args.logDir, initfn, procs)
}

func (m *Service) Init(confEtcd configEtcd, servLoc, sessKey, logDir string, initfn func(ServBase) error, procs map[string]Processor) error {
	fun := "Service.Init -->"
	// Init ServBase

	sb, err := NewServBaseV2(confEtcd, servLoc, sessKey)
	if err != nil {
		slog.Panicf("%s init servbase loc:%s key:%s err:%s", fun, servLoc, sessKey, err)
		return err
	}

	// Init slog
	var logConfig struct {
		Log struct {
			Level string
			Dir   string
		}
	}
	// default use level INFO
	logConfig.Log.Level = "INFO"

	err = sb.ServConfig(&logConfig)
	if err != nil {
		slog.Panicf("%s serv config err:%s", fun, err)
		fmt.Sprintf("%s serv config err:%s", fun, err)
		return err
	}

	var logdir string
	if len(logConfig.Log.Dir) > 0 {
		logdir = fmt.Sprintf("%s/%s", logConfig.Log.Dir, sb.Copyname())
	}

	if len(logDir) > 0 {
		logdir = fmt.Sprintf("%s/%s", logDir, sb.Copyname())
	}

	if logDir == "console" {
		logdir = ""
	}

	fmt.Sprintf("%s init log dir:%s name:%s level:%s", fun, logdir, servLoc, logConfig.Log.Level)
	slog.Infof("%s init log dir:%s name:%s level:%s", fun, logdir, servLoc, logConfig.Log.Level)

	slog.Init(logdir, "serv.log", logConfig.Log.Level)
	defer slog.Sync()

	statlog.Init(logdir, "stat.log", servLoc)
	defer statlog.Sync()

	// init tracer
	err = trace.InitDefaultTracer(servLoc)
	if err != nil {
		slog.Warnf("%s init tracer fail:%v", err)
	}

	// init callback
	err = initfn(sb)
	if err != nil {
		slog.Panicf("%s serv init err:%s", fun, err)
		return err
	}

	// init processor
	for n, p := range procs {
		if len(n) == 0 {
			slog.Panicf("%s processor name empty", fun)
			return err
		}

		if n[0] == '_' {
			slog.Panicf("%s processor name can not prefix '_'", fun)
			return err
		}

		if p == nil {
			slog.Panicf("%s processor:%s is nil", fun, n)
			return fmt.Errorf("processor:%s is nil", n)
		} else {
			err := p.Init()
			if err != nil {
				slog.Panicf("%s processor:%s init err:%s", fun, err)
				return err
			}
		}
	}

	infos, err := m.loadDriver(sb, procs)
	if err != nil {
		slog.Panicf("%s load driver err:%s", fun, err)
		return err
	}

	err = sb.RegisterService(infos)
	if err != nil {
		slog.Panicf("%s regist service err:%s", fun, err)
		return err
	}

	// 后门接口 ==================
	backdoor := &backDoorHttp{}
	err = backdoor.Init()
	if err != nil {
		slog.Panicf("%s init backdoor err:%s", fun, err)
		return err
	}

	binfos, err := m.loadDriver(sb, map[string]Processor{"_PROC_BACKDOOR": backdoor})
	if err == nil {
		err = sb.RegisterBackDoor(binfos)
		if err != nil {
			slog.Errorf("%s regist backdoor err:%s", fun, err)
		}

	} else {
		slog.Warnf("%s load backdoor driver err:%s", fun, err)
	}
	//==============================

	// sla metric埋点 ==================
	//init metric
	//user defualt metric opts
	metrics := rocserv.NewMetricsprocessor()
	if err != nil {
		slog.Warnf("init metrics fail:%v", err)
	}
	err = metrics.Init()
	if err != nil {
		slog.Warnf("%s init metrics err:%s", fun, err)
	}

	minfos, err := m.loadDriver(sb, map[string]Processor{"_PROC_METRICS": metrics})
	if err == nil {
		err = sb.RegisterMetrics(minfos)
		if err != nil {
			slog.Warnf("%s regist backdoor err:%s", fun, err)
		}

	} else {
		slog.Warnf("%s load metrics driver err:%s", fun, err)
	}
	//==============================

	// pause here
	var pause chan bool
	pause <- true

	return nil

}
func (m *Service) getMetricOps(sb *ServBaseV2) *rocserv.MetricsOpts {
	fun := "Service.getMetricOps -->"
	var metricConfig struct {
		metric *rocserv.MetricsOpts
	}
	err := sb.ServConfig(&metricConfig)
	if err != nil {
		slog.Panicf("%s serv config err:%s", fun, err)
		fmt.Sprintf("%s serv config err:%s", fun, err)
		return nil
	}
	return metricConfig.metric
}

func Serve(etcds []string, baseLoc string, initfn func(ServBase) error, procs map[string]Processor) error {
	return service.Serve(configEtcd{etcds, baseLoc}, initfn, procs)
}

func Init(etcds []string, baseLoc string, servLoc, servKey string, initfn func(ServBase) error, procs map[string]Processor) error {
	return service.Init(configEtcd{etcds, baseLoc}, servLoc, servKey, "", initfn, procs)
}

func Test(etcds []string, baseLoc string, initfn func(ServBase) error) error {
	return service.Init(configEtcd{etcds, baseLoc}, "test/test", "test", "console", initfn, nil)
}
<commit_msg>MOD:重构service init 函数<commit_after>// Copyright 2014 The roc Author. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package rocserv

import (
	"flag"
	"fmt"
	"github.com/shawnfeng/roc/util/service/sla"
	"github.com/shawnfeng/sutil/trace"
	"reflect"

	"github.com/julienschmidt/httprouter"

	"git.apache.org/thrift.git/lib/go/thrift"

	"github.com/shawnfeng/sutil/slog"
	"github.com/shawnfeng/sutil/slog/statlog"
)

const (
	PROCESSOR_HTTP   = "http"
	PROCESSOR_THRIFT = "thrift"
	PROCESSOR_GRPC   = "gprc"
)

type Service struct {
}

var service Service

//func NewService

type cmdArgs struct {
	logMaxSize    int
	logMaxBackups int
	servLoc       string
	logDir        string
	sessKey       string
}

func (m *Service) parseFlag() (*cmdArgs, error) {
	var serv, logDir, skey string
	var logMaxSize, logMaxBackups int
	flag.IntVar(&logMaxSize, "logmaxsize", 0, "logMaxSize is the maximum size in megabytes of the log file")
	flag.IntVar(&logMaxBackups, "logmaxbackups", 0, "logmaxbackups is the maximum number of old log files to retain")
	flag.StringVar(&serv, "serv", "", "servic name")
	flag.StringVar(&logDir, "logdir", "", "serice log dir")
	flag.StringVar(&skey, "skey", "", "service session key")

	flag.Parse()

	if len(serv) == 0 {
		return nil, fmt.Errorf("serv args need!")
	}

	if len(skey) == 0 {
		return nil, fmt.Errorf("skey args need!")
	}

	return &cmdArgs{
		logMaxSize:    logMaxSize,
		logMaxBackups: logMaxBackups,
		servLoc:       serv,
		logDir:        logDir,
		sessKey:       skey,
	}, nil

}

func (m *Service) loadDriver(sb ServBase, procs map[string]Processor) (map[string]*ServInfo, error) {
	fun := "Service.loadDriver -->"

	infos := make(map[string]*ServInfo)

	for n, p := range procs {
		addr, driver := p.Driver()
		if driver == nil {
			slog.Infof("%s processor:%s no driver", fun, n)
			continue
		}

		slog.Infof("%s processor:%s type:%s addr:%s", fun, n, reflect.TypeOf(driver), addr)

		switch d := driver.(type) {
		case *httprouter.Router:
			sa, err := powerHttp(addr, d)
			if err != nil {
				return nil, err
			}

			slog.Infof("%s load ok processor:%s serv addr:%s", fun, n, sa)
			infos[n] = &ServInfo{
				Type: PROCESSOR_HTTP,
				Addr: sa,
			}

		case thrift.TProcessor:
			sa, err := powerThrift(addr, d)
			if err != nil {
				return nil, err
			}

			slog.Infof("%s load ok processor:%s serv addr:%s", fun, n, sa)
			infos[n] = &ServInfo{
				Type: PROCESSOR_THRIFT,
				Addr: sa,
			}
		case *GrpcServer:
			sa, err := powerGrpc(addr, d)
			if err != nil {
				return nil, err
			}

			slog.Infof("%s load ok processor:%s serv addr:%s", fun, n, sa)
			infos[n] = &ServInfo{
				Type: PROCESSOR_GRPC,
				Addr: sa,
			}
		default:
			return nil, fmt.Errorf("processor:%s driver not recognition", n)

		}
	}

	return infos, nil
}

func (m *Service) Serve(confEtcd configEtcd, initfn func(ServBase) error, procs map[string]Processor) error {
	fun := "Service.Serve -->"

	args, err := m.parseFlag()
	if err != nil {
		slog.Panicf("%s parse arg err:%s", fun, err)
		return err
	}

	return m.Init(confEtcd, args, initfn, procs)
}

func (m *Service) initLog(sb *ServBaseV2, args *cmdArgs) error {
	fun := "Service.initLog -->"

	logDir := args.logDir
	var logConfig struct {
		Log struct {
			Level string
			Dir   string
		}
	}
	logConfig.Log.Level = "INFO"

	err := sb.ServConfig(&logConfig)
	if err != nil {
		slog.Errorf("%s serv config err:%s", fun, err)
		return err
	}

	var logdir string
	if len(logConfig.Log.Dir) > 0 {
		logdir = fmt.Sprintf("%s/%s", logConfig.Log.Dir, sb.Copyname())
	}

	if len(logDir) > 0 {
		logdir = fmt.Sprintf("%s/%s", logDir, sb.Copyname())
	}

	if logDir == "console" {
		logdir = ""
	}

	slog.Infof("%s init log dir:%s name:%s level:%s", fun, logdir, args.servLoc, logConfig.Log.Level)

	slog.Init(logdir, "serv.log", logConfig.Log.Level)
	statlog.Init(logdir, "stat.log", args.servLoc)
	return nil
}

func (m *Service) Init(confEtcd configEtcd, args *cmdArgs, initfn func(ServBase) error, procs map[string]Processor) error {
	fun := "Service.Init -->"

	servLoc := args.servLoc
	sessKey := args.sessKey

	sb, err := NewServBaseV2(confEtcd, servLoc, sessKey)
	if err != nil {
		slog.Panicf("%s init servbase loc:%s key:%s err:%s", fun, servLoc, sessKey, err)
		return err
	}

	m.initLog(sb, args)
	defer slog.Sync()
	defer statlog.Sync()

	m.initTracer(servLoc)
	m.callInitFunc(sb, initfn)

	err = m.initProcessor(sb, procs)
	if err != nil {
		slog.Panicf("%s processor name empty", fun)
		return err
	}

	m.initBackdoork(sb)
	m.initMetric(sb)

	var pause chan bool
	pause <- true

	return nil
}

func (m *Service) initProcessor(sb *ServBaseV2, procs map[string]Processor) error {
	fun := "Service.initProcessor -->"

	for n, p := range procs {
		if len(n) == 0 {
			slog.Errorf("%r processor name empty", fun)
			return fmt.Errorf("processor name empty")
		}

		if n[0] == '_' {
			slog.Errorf("%s processor name can not prefix '_'", fun)
			return fmt.Errorf("processor name can not prefix '_'")
		}

		if p == nil {
			slog.Errorf("%s processor:%s is nil", fun, n)
			return fmt.Errorf("processor:%s is nil", n)
		} else {
			err := p.Init()
			if err != nil {
				slog.Errorf("%s processor:%s init err:%s", fun, err)
				return fmt.Errorf("processor:%s init err:%s", n, err)
			}
		}
	}

	infos, err := m.loadDriver(sb, procs)
	if err != nil {
		slog.Errorf("%s load driver err:%s", fun, err)
		return err
	}

	err = sb.RegisterService(infos)
	if err != nil {
		slog.Errorf("%s regist service err:%s", fun, err)
		return err
	}

	return nil
}

func (m *Service) callInitFunc(sb *ServBaseV2, initfn func(ServBase) error) error {
	fun := "Service.callInitFunc -->"

	err := initfn(sb)
	if err != nil {
		slog.Panicf("%s serv init err:%s", fun, err)
		return err
	}

	return nil
}

func (m *Service) initTracer(servLoc string) error {
	fun := "Service.initTracer -->"

	err := trace.InitDefaultTracer(servLoc)
	if err != nil {
		slog.Errorf("%s init tracer fail:%v", fun, err)
	}

	return err
}

func (m *Service) initBackdoork(sb *ServBaseV2) error {
	fun := "Service.initBackdoork -->"

	backdoor := &backDoorHttp{}
	err := backdoor.Init()
	if err != nil {
		slog.Panicf("%s init backdoor err:%s", fun, err)
		return err
	}

	binfos, err := m.loadDriver(sb, map[string]Processor{"_PROC_BACKDOOR": backdoor})
	if err == nil {
		err = sb.RegisterBackDoor(binfos)
		if err != nil {
			slog.Errorf("%s regist backdoor err:%s", fun, err)
		}

	} else {
		slog.Warnf("%s load backdoor driver err:%s", fun, err)
	}

	return err
}

func (m *Service) initMetric(sb *ServBaseV2) error {
	fun := "Service.initMetric -->"

	metrics := rocserv.NewMetricsprocessor()
	err := metrics.Init()
	if err != nil {
		slog.Warnf("%s init metrics err:%s", fun, err)
	}

	minfos, err := m.loadDriver(sb, map[string]Processor{"_PROC_METRICS": metrics})
	if err == nil {
		err = sb.RegisterMetrics(minfos)
		if err != nil {
			slog.Warnf("%s regist backdoor err:%s", fun, err)
		}

	} else {
		slog.Warnf("%s load metrics driver err:%s", fun, err)
	}
	return err
}

func (m *Service) getMetricOps(sb *ServBaseV2) *rocserv.MetricsOpts {
	fun := "Service.getMetricOps -->"

	var metricConfig struct {
		metric *rocserv.MetricsOpts
	}
	err := sb.ServConfig(&metricConfig)
	if err != nil {
		slog.Panicf("%s serv config err:%s", fun, err)
		fmt.Sprintf("%s serv config err:%s", fun, err)
		return nil
	}
	return metricConfig.metric
}

func Serve(etcds []string, baseLoc string, initfn func(ServBase) error, procs map[string]Processor) error {
	return service.Serve(configEtcd{etcds, baseLoc}, initfn, procs)
}

func Init(etcds []string, baseLoc string, servLoc, servKey, logDir string, initfn func(ServBase) error, procs map[string]Processor) error {
	args := &cmdArgs{
		logMaxSize:    0,
		logMaxBackups: 0,
		servLoc:       servLoc,
		logDir:        logDir,
		sessKey:       servKey,
	}
	return service.Init(configEtcd{etcds, baseLoc}, args, initfn, procs)
}

func Test(etcds []string, baseLoc string, initfn func(ServBase) error) error {
	args := &cmdArgs{
		logMaxSize:    0,
		logMaxBackups: 0,
		servLoc:       "test/test",
		sessKey:       "test",
		logDir:        "console",
	}
	return service.Init(configEtcd{etcds, baseLoc}, args, initfn, nil)
}
<|endoftext|>


<commit_before>package renter

import (
	"github.com/NebulousLabs/Sia/modules"
	"github.com/NebulousLabs/Sia/modules/renter/contractor"
)

// A hostPool is a collection of active host connections, in the form of
// Editors. The renter uses a hostPool to prevent connecting to the same host
// more than once. This is more efficient, and also makes it easier to
// serialize contract revisions.
type hostPool struct {
	hosts          []contractor.Editor
	blacklist      []modules.NetAddress
	hostContractor hostContractor
	hdb            hostDB
}

// Close closes all of the hostPool's open host connections.
func (p *hostPool) Close() error {
	for _, h := range p.hosts {
		h.Close()
	}
	return nil
}

// add adds a contract's host to the hostPool and returns it as an Editor.
func (p *hostPool) add(contract modules.RenterContract) (contractor.Editor, error) {
	for _, h := range p.hosts {
		if h.Address() == contract.NetAddress {
			return h, nil
		}
	}
	hu, err := p.hostContractor.Editor(contract)
	if err != nil {
		p.blacklist = append(p.blacklist, contract.NetAddress)
		return nil, err
	}
	p.hosts = append(p.hosts, hu)
	return hu, nil
}

// remove disconnects from a host and adds it to the blacklist.
func (p *hostPool) remove(addr modules.NetAddress) {
	for i, h := range p.hosts {
		if h.Address() == addr {
			h.Close()
			p.hosts = append(p.hosts[:i], p.hosts[i+1:]...)
			p.blacklist = append(p.blacklist, addr)
			return
		}
	}
}

// uniqueHosts will return up to 'n' unique hosts that are not in 'exclude'.
// The pool draws from its set of active connections first, and then negotiates
// new contracts if more hosts are required. Note that this latter case
// requires network I/O, so the caller should always assume that uniqueHosts
// will block.
func (p *hostPool) uniqueHosts(n int, exclude []modules.NetAddress) (hosts []contractor.Editor) {
	if n == 0 {
		return
	}

	// convert slice to map for easier lookups
	excludeSet := make(map[modules.NetAddress]struct{})
	for _, ip := range exclude {
		excludeSet[ip] = struct{}{}
	}

	// First reuse existing connections.
	for _, h := range p.hosts {
		if _, ok := excludeSet[h.Address()]; ok {
			continue
		}
		hosts = append(hosts, h)
		if len(hosts) >= n {
			return hosts
		}
	}

	// Extend the exclude set with the pool's blacklist, and the hosts we're
	// already connected to.
	for _, ip := range p.blacklist {
		excludeSet[ip] = struct{}{}
	}
	for _, h := range p.hosts {
		excludeSet[h.Address()] = struct{}{}
	}

	// Next try to reuse existing contracts.
	for _, contract := range p.hostContractor.Contracts() {
		if _, ok := excludeSet[contract.NetAddress]; ok {
			continue
		}
		hu, err := p.add(contract)
		if err != nil {
			continue
		}
		hosts = append(hosts, hu)
		excludeSet[hu.Address()] = struct{}{}
		if len(hosts) >= n {
			break
		}
	}

	return hosts
}

// newHostPool returns an empty hostPool.
func (r *Renter) newHostPool() *hostPool {
	return &hostPool{
		hostContractor: r.hostContractor,
		hdb:            r.hostDB,
	}
}
<commit_msg>build.Critical if removing unknown host from pool<commit_after>package renter

import (
	"github.com/NebulousLabs/Sia/build"
	"github.com/NebulousLabs/Sia/modules"
	"github.com/NebulousLabs/Sia/modules/renter/contractor"
)

// A hostPool is a collection of active host connections, in the form of
// Editors. The renter uses a hostPool to prevent connecting to the same host
// more than once. This is more efficient, and also makes it easier to
// serialize contract revisions.
type hostPool struct {
	hosts          []contractor.Editor
	blacklist      []modules.NetAddress
	hostContractor hostContractor
	hdb            hostDB
}

// Close closes all of the hostPool's open host connections.
func (p *hostPool) Close() error {
	for _, h := range p.hosts {
		h.Close()
	}
	return nil
}

// add adds a contract's host to the hostPool and returns it as an Editor.
func (p *hostPool) add(contract modules.RenterContract) (contractor.Editor, error) {
	for _, h := range p.hosts {
		if h.Address() == contract.NetAddress {
			return h, nil
		}
	}
	hu, err := p.hostContractor.Editor(contract)
	if err != nil {
		p.blacklist = append(p.blacklist, contract.NetAddress)
		return nil, err
	}
	p.hosts = append(p.hosts, hu)
	return hu, nil
}

// remove disconnects from a host and adds it to the blacklist.
func (p *hostPool) remove(addr modules.NetAddress) {
	for i, h := range p.hosts {
		if h.Address() == addr {
			h.Close()
			p.hosts = append(p.hosts[:i], p.hosts[i+1:]...)
			p.blacklist = append(p.blacklist, addr)
			return
		}
	}
	build.Critical("could not remove host from pool: no record of host", addr)
}

// uniqueHosts will return up to 'n' unique hosts that are not in 'exclude'.
// The pool draws from its set of active connections first, and then negotiates
// new contracts if more hosts are required. Note that this latter case
// requires network I/O, so the caller should always assume that uniqueHosts
// will block.
func (p *hostPool) uniqueHosts(n int, exclude []modules.NetAddress) (hosts []contractor.Editor) {
	if n == 0 {
		return
	}

	// convert slice to map for easier lookups
	excludeSet := make(map[modules.NetAddress]struct{})
	for _, ip := range exclude {
		excludeSet[ip] = struct{}{}
	}

	// First reuse existing connections.
	for _, h := range p.hosts {
		if _, ok := excludeSet[h.Address()]; ok {
			continue
		}
		hosts = append(hosts, h)
		if len(hosts) >= n {
			return hosts
		}
	}

	// Extend the exclude set with the pool's blacklist, and the hosts we're
	// already connected to.
	for _, ip := range p.blacklist {
		excludeSet[ip] = struct{}{}
	}
	for _, h := range p.hosts {
		excludeSet[h.Address()] = struct{}{}
	}

	// Next try to reuse existing contracts.
	for _, contract := range p.hostContractor.Contracts() {
		if _, ok := excludeSet[contract.NetAddress]; ok {
			continue
		}
		hu, err := p.add(contract)
		if err != nil {
			continue
		}
		hosts = append(hosts, hu)
		excludeSet[hu.Address()] = struct{}{}
		if len(hosts) >= n {
			break
		}
	}

	return hosts
}

// newHostPool returns an empty hostPool.
func (r *Renter) newHostPool() *hostPool {
	return &hostPool{
		hostContractor: r.hostContractor,
		hdb:            r.hostDB,
	}
}
<|endoftext|>


<commit_before>// EVH is designed to be a single-use file transfer system.  Its purpose is to replace
// aging methods of sharing files such as FTP.  With the advent of services like
// DropBox, Box, Google Drive and the like, this type of service is becoming more
// commonplace EVH has some differentiating features that make it an especially
// good tool for corporations and/or home use.
//
// EVH runs in two modes: server and client.  Server hosts a web server interface for
// uploading and downloading files.  The Client is for uploading only and runs
// in a terminal.  This app is designed to run on all platforms that Go supports.
package main

import (
	"crypto/tls"
	"flag"
	"html/template"
	"log"
	"net/http"
	"os"
)

// Flags
var ConfigFileFlag string
var DstEmailFlag string
var ExpirationFlag string
var FileDescrFlag string
var FilesFieldFlag string
var ProgressFlag bool
var ServerFlag bool
var SrcEmailFlag string
var UrlFlag string
var Evh1ImportFlag bool
var ProxyUrlFlag string

// Global Variables
var UploadUrlPath = "/upload/"
var DownloadUrlPath = "/download/"
var AdminUrlPath = "/admin/"
var Files []string
var HttpProto = "http"
var SiteDown bool
var Templates *template.Template

// Constants
const VERSION = "2.5.11"

func init() {
	flag.StringVar(&ConfigFileFlag, "c", "", "Location of the Configuration file")
	flag.BoolVar(&ServerFlag, "server", false, "Listen for incoming file uploads")

	// Client flags
	flag.StringVar(&UrlFlag, "url", "", "Remote server URL to send files to (client only)")
	flag.StringVar(&FilesFieldFlag, "field", "", "Field name of the form (client only)")
	flag.StringVar(&SrcEmailFlag, "from", "", "Email address of uploader (client only)")
	flag.StringVar(&DstEmailFlag, "to", "", "Comma separated set of email address(es) of file recipient(s) (client only)")
	flag.StringVar(&FileDescrFlag, "description", "", "File desription (use quotes) (client only)")
	flag.BoolVar(&ProgressFlag, "progress", true, "Show progress bar during upload (client only)")
	flag.StringVar(&ExpirationFlag, "expires", "", "Example 1:d for 1 day (client only)")
	flag.BoolVar(&Evh1ImportFlag, "import", false, "Import data from EVH1 instance (client only)")
	flag.StringVar(&ProxyUrlFlag, "proxy", "", "URL/Address for proxy (env=use environment proxy, other=use as defined")
}

func main() {
	flag.Parse()

	// Load in our Config
	Config = NewConfig(ConfigFileFlag)
	Config.ImportFlags()

	if ServerFlag {
		// Final sanity check
		if Config.Server.Assets == "" {
			log.Fatal("ERROR: Cannot continue without specifying assets path")
		}
		if Config.Server.Templates == "" {
			log.Fatal("ERROR: Cannot continue without specifying templates path")
		}
		if Config.Server.ListenAddr == "" {
			log.Fatal("ERROR: Cannot continue without specifying listenaddr value")
		}
		if Config.Server.Mailserver == "" {
			log.Println("WARNING: cannot send emails, mailserver not set")
		}

		// Set so all generated URLs use https if enabled
		if Config.Server.Ssl {
			HttpProto = "https"
		}

		// Setup our assets dir (if it don't already exist)
		err := os.MkdirAll(Config.Server.Assets, 0700)
		if err != nil {
			log.Fatal("Cannot setup assetdir as needed: " + err.Error())
		}

		// Parse our html templates
		go RefreshTemplates()
		go ScrubDownloads()

		// Register our handler functions
		http.HandleFunc(UploadUrlPath, SSLCheck(UploadHandler))
		http.HandleFunc(DownloadUrlPath, SSLCheck(AssetHandler))
		http.HandleFunc(AdminUrlPath, BasicAuth(SSLCheck(AdminHandler)))
		http.HandleFunc("/", Evh1Intercept(SSLCheck(HomeHandler)))

		// Listen
		log.Println("Listening...")

		// Spawn HTTPS listener in another thread
		go func() {
			if Config.Server.Ssl == false || Config.Server.SslPort == "" {
				return
			}
			var addrSsl = Config.Server.ListenAddr + ":" + Config.Server.SslPort
			//listenErrSsl := http.ListenAndServeTLS(addrSsl, Config.Server.CertFile, Config.Server.KeyFile, nil)

			var config = &tls.Config{MinVersion: tls.VersionTLS10}
			var server = &http.Server{Addr: addrSsl, TLSConfig: config}
			listenErrSsl := server.ListenAndServeTLS(Config.Server.CertFile, Config.Server.KeyFile)

			if listenErrSsl != nil {
				log.Fatal("ERROR: ssl listen problem: " + listenErrSsl.Error())
			}
		}()

		// Start non-SSL listener
		var addrNonSsl = Config.Server.ListenAddr + ":" + Config.Server.NonSslPort
		listenErr := http.ListenAndServe(addrNonSsl, nil)
		if listenErr != nil {
			log.Fatal("ERROR: non-ssl listen problem: " + listenErr.Error())
		}
	} else {
		// Run import if requested
		if Evh1ImportFlag {
			SpitSlurp()
			return
		}

		// Final sanity check
		if Config.Client.DestEmail == "" {
			log.Println("WARNING: no -destemail value set, cannot send reciever an email")
		}
		if Config.Client.Email == "" {
			log.Println("WARNING: no -email value set, cannot send email to uploader")
		}
		if Config.Client.Field == "" {
			log.Println("WARNING: no -field value set, using \"file\" instead")
			Config.Client.Field = "file"
		}
		if Config.Client.Url == "" {
			log.Fatal("ERROR: Cannot continue without specifying -url value")
		}

		// All filenames are unflagged arguments, loop through them and uplod the file(s)
		for _, fname := range flag.Args() {
			fi, err := os.Stat(fname)
			if err != nil {
				log.Println("WARNING: Cannot read file, skipping ", fname, ": ", err.Error())
			} else {
				if fi.Mode().IsRegular() {
					Files = append(Files, fname)
				}
			}
		}

		Upload(Files)
	}
}
<commit_msg>Version bump to 2.5.12<commit_after>// EVH is designed to be a single-use file transfer system.  Its purpose is to replace
// aging methods of sharing files such as FTP.  With the advent of services like
// DropBox, Box, Google Drive and the like, this type of service is becoming more
// commonplace EVH has some differentiating features that make it an especially
// good tool for corporations and/or home use.
//
// EVH runs in two modes: server and client.  Server hosts a web server interface for
// uploading and downloading files.  The Client is for uploading only and runs
// in a terminal.  This app is designed to run on all platforms that Go supports.
package main

import (
	"crypto/tls"
	"flag"
	"html/template"
	"log"
	"net/http"
	"os"
)

// Flags
var ConfigFileFlag string
var DstEmailFlag string
var ExpirationFlag string
var FileDescrFlag string
var FilesFieldFlag string
var ProgressFlag bool
var ServerFlag bool
var SrcEmailFlag string
var UrlFlag string
var Evh1ImportFlag bool
var ProxyUrlFlag string

// Global Variables
var UploadUrlPath = "/upload/"
var DownloadUrlPath = "/download/"
var AdminUrlPath = "/admin/"
var Files []string
var HttpProto = "http"
var SiteDown bool
var Templates *template.Template

// Constants
const VERSION = "2.5.12"

func init() {
	flag.StringVar(&ConfigFileFlag, "c", "", "Location of the Configuration file")
	flag.BoolVar(&ServerFlag, "server", false, "Listen for incoming file uploads")

	// Client flags
	flag.StringVar(&UrlFlag, "url", "", "Remote server URL to send files to (client only)")
	flag.StringVar(&FilesFieldFlag, "field", "", "Field name of the form (client only)")
	flag.StringVar(&SrcEmailFlag, "from", "", "Email address of uploader (client only)")
	flag.StringVar(&DstEmailFlag, "to", "", "Comma separated set of email address(es) of file recipient(s) (client only)")
	flag.StringVar(&FileDescrFlag, "description", "", "File desription (use quotes) (client only)")
	flag.BoolVar(&ProgressFlag, "progress", true, "Show progress bar during upload (client only)")
	flag.StringVar(&ExpirationFlag, "expires", "", "Example 1:d for 1 day (client only)")
	flag.BoolVar(&Evh1ImportFlag, "import", false, "Import data from EVH1 instance (client only)")
	flag.StringVar(&ProxyUrlFlag, "proxy", "", "URL/Address for proxy (env=use environment proxy, other=use as defined")
}

func main() {
	flag.Parse()

	// Load in our Config
	Config = NewConfig(ConfigFileFlag)
	Config.ImportFlags()

	if ServerFlag {
		// Final sanity check
		if Config.Server.Assets == "" {
			log.Fatal("ERROR: Cannot continue without specifying assets path")
		}
		if Config.Server.Templates == "" {
			log.Fatal("ERROR: Cannot continue without specifying templates path")
		}
		if Config.Server.ListenAddr == "" {
			log.Fatal("ERROR: Cannot continue without specifying listenaddr value")
		}
		if Config.Server.Mailserver == "" {
			log.Println("WARNING: cannot send emails, mailserver not set")
		}

		// Set so all generated URLs use https if enabled
		if Config.Server.Ssl {
			HttpProto = "https"
		}

		// Setup our assets dir (if it don't already exist)
		err := os.MkdirAll(Config.Server.Assets, 0700)
		if err != nil {
			log.Fatal("Cannot setup assetdir as needed: " + err.Error())
		}

		// Parse our html templates
		go RefreshTemplates()
		go ScrubDownloads()

		// Register our handler functions
		http.HandleFunc(UploadUrlPath, SSLCheck(UploadHandler))
		http.HandleFunc(DownloadUrlPath, SSLCheck(AssetHandler))
		http.HandleFunc(AdminUrlPath, BasicAuth(SSLCheck(AdminHandler)))
		http.HandleFunc("/", Evh1Intercept(SSLCheck(HomeHandler)))

		// Listen
		log.Println("Listening...")

		// Spawn HTTPS listener in another thread
		go func() {
			if Config.Server.Ssl == false || Config.Server.SslPort == "" {
				return
			}
			var addrSsl = Config.Server.ListenAddr + ":" + Config.Server.SslPort
			//listenErrSsl := http.ListenAndServeTLS(addrSsl, Config.Server.CertFile, Config.Server.KeyFile, nil)

			var config = &tls.Config{MinVersion: tls.VersionTLS10}
			var server = &http.Server{Addr: addrSsl, TLSConfig: config}
			listenErrSsl := server.ListenAndServeTLS(Config.Server.CertFile, Config.Server.KeyFile)

			if listenErrSsl != nil {
				log.Fatal("ERROR: ssl listen problem: " + listenErrSsl.Error())
			}
		}()

		// Start non-SSL listener
		var addrNonSsl = Config.Server.ListenAddr + ":" + Config.Server.NonSslPort
		listenErr := http.ListenAndServe(addrNonSsl, nil)
		if listenErr != nil {
			log.Fatal("ERROR: non-ssl listen problem: " + listenErr.Error())
		}
	} else {
		// Run import if requested
		if Evh1ImportFlag {
			SpitSlurp()
			return
		}

		// Final sanity check
		if Config.Client.DestEmail == "" {
			log.Println("WARNING: no -destemail value set, cannot send reciever an email")
		}
		if Config.Client.Email == "" {
			log.Println("WARNING: no -email value set, cannot send email to uploader")
		}
		if Config.Client.Field == "" {
			log.Println("WARNING: no -field value set, using \"file\" instead")
			Config.Client.Field = "file"
		}
		if Config.Client.Url == "" {
			log.Fatal("ERROR: Cannot continue without specifying -url value")
		}

		// All filenames are unflagged arguments, loop through them and uplod the file(s)
		for _, fname := range flag.Args() {
			fi, err := os.Stat(fname)
			if err != nil {
				log.Println("WARNING: Cannot read file, skipping ", fname, ": ", err.Error())
			} else {
				if fi.Mode().IsRegular() {
					Files = append(Files, fname)
				}
			}
		}

		Upload(Files)
	}
}
<|endoftext|>