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

package isvcs

import "github.com/zenoss/glog"

var logstash *IService

func initLogstash() {
	var err error

	command := "exec /opt/logstash-2.3.3/bin/logstash agent -f /usr/local/serviced/resources/logstash/logstash.conf"
	localFilePortBinding := portBinding{
		HostIp:         "0.0.0.0",
		HostIpOverride: "", // logstash should always be open
		HostPort:       5042,
	}
	lumberJackPortBinding := portBinding{
		HostIp:         "0.0.0.0",
		HostIpOverride: "", // lumberjack should always be open
		HostPort:       5043,
	}
	webserverPortBinding := portBinding{
		HostIp:         "127.0.0.1",
		HostIpOverride: "SERVICED_ISVC_LOGSTASH_PORT_9292_HOSTIP",
		HostPort:       9292,
	}

	logstash, err = NewIService(
		IServiceDefinition{
			ID:      LogstashISVC.ID,
			Name:    "logstash",
			Repo:    IMAGE_REPO,
			Tag:     IMAGE_TAG,
			Command: func() string { return command },
			PortBindings: []portBinding{
				localFilePortBinding,
				lumberJackPortBinding,
				webserverPortBinding},
			Volumes:    map[string]string{},
			Notify:     notifyLogstashConfigChange,
			Links:      []string{"serviced-isvcs_elasticsearch-logstash:elasticsearch"},
			StartGroup: 1,
		})
	if err != nil {
		glog.Fatalf("Error initializing logstash_master container: %s", err)
	}
}

func notifyLogstashConfigChange(svc *IService, value interface{}) error {

	if message, ok := value.(string); ok {
		if message == "restart logstash" {
			return svc.Restart()
		}
	}
	return nil
}
<commit_msg>Replace lumberjack references with filebeat<commit_after>// Copyright 2014 The Serviced Authors.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package isvcs

import "github.com/zenoss/glog"

var logstash *IService

func initLogstash() {
	var err error

	command := "exec /opt/logstash-2.3.3/bin/logstash agent -f /usr/local/serviced/resources/logstash/logstash.conf"
	localFilePortBinding := portBinding{
		HostIp:         "0.0.0.0",
		HostIpOverride: "", // logstash should always be open
		HostPort:       5042,
	}
	filebeatPortBinding := portBinding{
		HostIp:         "0.0.0.0",
		HostIpOverride: "", // filebeat should always be open
		HostPort:       5043,
	}
	webserverPortBinding := portBinding{
		HostIp:         "127.0.0.1",
		HostIpOverride: "SERVICED_ISVC_LOGSTASH_PORT_9292_HOSTIP",
		HostPort:       9292,
	}

	logstash, err = NewIService(
		IServiceDefinition{
			ID:      LogstashISVC.ID,
			Name:    "logstash",
			Repo:    IMAGE_REPO,
			Tag:     IMAGE_TAG,
			Command: func() string { return command },
			PortBindings: []portBinding{
				localFilePortBinding,
				filebeatPortBinding,
				webserverPortBinding},
			Volumes:    map[string]string{},
			Notify:     notifyLogstashConfigChange,
			Links:      []string{"serviced-isvcs_elasticsearch-logstash:elasticsearch"},
			StartGroup: 1,
		})
	if err != nil {
		glog.Fatalf("Error initializing logstash_master container: %s", err)
	}
}

func notifyLogstashConfigChange(svc *IService, value interface{}) error {

	if message, ok := value.(string); ok {
		if message == "restart logstash" {
			return svc.Restart()
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package core

import (
	"math/rand"
	"time"

	"github.com/af83/edwig/logger"
	"github.com/af83/edwig/model"
)

type ModelGuardian struct {
	model.ClockConsumer
	model.UUIDConsumer

	stop        chan struct{}
	referential *Referential
}

func NewModelGuardian(referential *Referential) *ModelGuardian {
	return &ModelGuardian{referential: referential}
}

func (guardian *ModelGuardian) Start() {
	logger.Log.Debugf("Start models guardian")

	rand.Seed(time.Now().UTC().UnixNano())
	guardian.stop = make(chan struct{})
	go guardian.Run()
}

func (guardian *ModelGuardian) Stop() {
	if guardian.stop != nil {
		close(guardian.stop)
	}
}

func (guardian *ModelGuardian) Run() {
	c := guardian.Clock().After(10 * time.Second)

	for {
		select {
		case <-guardian.stop:
			return
		case <-c:
			logger.Log.Debugf("Model guardian visit")

			guardian.refreshStopAreas()
			guardian.checkReloadModel()
			guardian.simulateActualAttributes()
			guardian.requestSituations()

			c = guardian.Clock().After(10 * time.Second)
		}
	}
}

func (guardian *ModelGuardian) checkReloadModel() {
	if guardian.Clock().Now().After(guardian.referential.NextReloadAt()) {
		guardian.referential.ReloadModel()
	}
}

func (guardian *ModelGuardian) refreshStopAreas() {
	// Open a new transaction
	tx := guardian.referential.NewTransaction()
	defer tx.Close()

	now := guardian.Clock().Now()

	for _, stopArea := range tx.Model().StopAreas().FindAll() {
		if stopArea.ParentId != "" {
			parent, ok := stopArea.Parent()
			if ok && !parent.CollectChildren {
				continue
			}
		}
		if !stopArea.CollectedAlways && !stopArea.CollectedUntil.After(now) {
			continue
		}

		if stopArea.NextCollectAt.Before(now) {
			stopAreaTx := guardian.referential.NewTransaction()

			transactionnalStopArea, _ := stopAreaTx.Model().StopAreas().Find(stopArea.Id())

			randNb := time.Duration(rand.Intn(20)+40) * time.Second

			transactionnalStopArea.NextCollectAt = now.Add(randNb)
			transactionnalStopArea.Save()
			stopAreaTx.Commit()
			stopAreaTx.Close()

			stopAreaUpdateRequest := &StopAreaUpdateRequest{
				id:         StopAreaUpdateRequestId(guardian.NewUUID()),
				stopAreaId: transactionnalStopArea.Id(),
				createdAt:  now,
			}
			guardian.referential.CollectManager().UpdateStopArea(stopAreaUpdateRequest)
		}
	}
}

func (guardian *ModelGuardian) requestSituations() {
	tx := guardian.referential.NewTransaction()
	defer tx.Close()

	now := guardian.Clock().Now()

	for _, line := range tx.Model().Lines().FindAll() {
		if !line.CollectGeneralMessages || now.Before(line.CollectedAt().Add(1*time.Minute)) {
			continue
		}

		lineTx := guardian.referential.NewTransaction()

		transactionnalLine, _ := lineTx.Model().Lines().Find(line.Id())

		transactionnalLine.Updated(now)
		transactionnalLine.Save()
		lineTx.Commit()
		lineTx.Close()

		situationUpdateRequest := &SituationUpdateRequest{
			id:        SituationUpdateRequestId(guardian.NewUUID()),
			lineId:    line.Id(),
			createdAt: now,
		}
		guardian.referential.CollectManager().UpdateSituation(situationUpdateRequest)
	}
}

func (guardian *ModelGuardian) simulateActualAttributes() {
	tx := guardian.referential.NewTransaction()
	defer tx.Close()

	for _, stopVisit := range tx.Model().StopVisits().FindAll() {
		if stopVisit.IsCollected() {
			continue
		}

		// too verbse
		// logger.Log.Debugf("Simulate actual attributes on StopVisit %v", stopVisit.Id())

		stopVisitTx := guardian.referential.NewTransaction()
		defer stopVisitTx.Close()

		transactionnalStopVisit, _ := tx.Model().StopVisits().Find(stopVisit.Id())
		simulator := NewActualAttributesSimulator(&transactionnalStopVisit)
		simulator.SetClock(guardian.Clock())
		if simulator.Simulate() {
			transactionnalStopVisit.Save()
			stopVisitTx.Commit()
		} else {
			stopVisitTx.Rollback()
		}
	}
}

type ActualAttributesSimulator struct {
	model.ClockConsumer

	stopVisit *model.StopVisit
	now       time.Time
}

func NewActualAttributesSimulator(stopVisit *model.StopVisit) *ActualAttributesSimulator {
	return &ActualAttributesSimulator{stopVisit: stopVisit}
}

func (simulator *ActualAttributesSimulator) Now() time.Time {
	if simulator.now.IsZero() {
		simulator.now = simulator.Clock().Now()
	}
	return simulator.now
}

func (simulator *ActualAttributesSimulator) ArrivalTime() time.Time {
	return simulator.stopVisit.Schedules.ArrivalTimeFromKind([]model.StopVisitScheduleType{"expected", "aimed"})
}

func (simulator *ActualAttributesSimulator) AfterArrivalTime() bool {
	return simulator.Clock().Now().After(simulator.ArrivalTime())
}

func (simulator *ActualAttributesSimulator) DepartureTime() time.Time {
	return simulator.stopVisit.Schedules.DepartureTimeFromKind([]model.StopVisitScheduleType{"expected", "aimed"})
}

func (simulator *ActualAttributesSimulator) AfterDepartureTime() bool {
	return simulator.Clock().Now().After(simulator.DepartureTime())
}

func (simulator *ActualAttributesSimulator) Simulate() bool {
	if simulator.stopVisit.IsCollected() {
		return false
	}

	return simulator.simulateArrival() || simulator.simulateDeparture()
}

func (simulator *ActualAttributesSimulator) simulateArrival() bool {
	if simulator.AfterArrivalTime() && simulator.CanArrive() {
		simulator.stopVisit.ArrivalStatus = model.STOP_VISIT_ARRIVAL_CANCELLED
		simulator.stopVisit.Schedules.SetArrivalTime(model.STOP_VISIT_SCHEDULE_ACTUAL, simulator.ArrivalTime())

		logger.Log.Printf("Set StopVisit %s ArrivalStatus at %s", simulator.stopVisit.Id(), model.STOP_VISIT_ARRIVAL_CANCELLED)

		if !simulator.AfterDepartureTime() {
			simulator.stopVisit.VehicleAtStop = true
			logger.Log.Printf("Set StopVisit %s VehicleAtStop at true", simulator.stopVisit.Id())
		}

		return true
	}

	return false
}

func (simulator *ActualAttributesSimulator) CanArrive() bool {
	switch simulator.stopVisit.ArrivalStatus {
	case model.STOP_VISIT_ARRIVAL_ONTIME, model.STOP_VISIT_ARRIVAL_EARLY, model.STOP_VISIT_ARRIVAL_DELAYED:
		return true
	default:
		return false
	}
}

func (simulator *ActualAttributesSimulator) CanDepart() bool {
	switch simulator.stopVisit.DepartureStatus {
	case model.STOP_VISIT_DEPARTURE_ONTIME, model.STOP_VISIT_DEPARTURE_EARLY, model.STOP_VISIT_DEPARTURE_DELAYED:
		return true
	default:
		return false
	}
}

func (simulator *ActualAttributesSimulator) simulateDeparture() bool {
	if simulator.AfterDepartureTime() && simulator.CanDepart() {
		simulator.stopVisit.DepartureStatus = model.STOP_VISIT_DEPARTURE_CANCELLED

		simulator.stopVisit.Schedules.SetDepartureTime(model.STOP_VISIT_SCHEDULE_ACTUAL, simulator.DepartureTime())
		simulator.stopVisit.VehicleAtStop = false

		logger.Log.Printf("Set StopVisit %s DepartureStatus at %s", simulator.stopVisit.Id(), model.STOP_VISIT_DEPARTURE_CANCELLED)

		return true
	}
	return false
}
<commit_msg>Refs #5872<commit_after>package core

import (
	"math/rand"
	"time"

	"github.com/af83/edwig/logger"
	"github.com/af83/edwig/model"
)

type ModelGuardian struct {
	model.ClockConsumer
	model.UUIDConsumer

	stop        chan struct{}
	referential *Referential
}

func NewModelGuardian(referential *Referential) *ModelGuardian {
	return &ModelGuardian{referential: referential}
}

func (guardian *ModelGuardian) Start() {
	logger.Log.Debugf("Start models guardian")

	rand.Seed(time.Now().UTC().UnixNano())
	guardian.stop = make(chan struct{})
	go guardian.Run()
}

func (guardian *ModelGuardian) Stop() {
	if guardian.stop != nil {
		close(guardian.stop)
	}
}

func (guardian *ModelGuardian) Run() {
	c := guardian.Clock().After(10 * time.Second)

	for {
		select {
		case <-guardian.stop:
			logger.Log.Debugf("Model guardian stop")
			return
		case <-c:
			logger.Log.Debugf("Model guardian visit")

			if guardian.checkReloadModel() {
				return
			}

			guardian.refreshStopAreas()
			guardian.simulateActualAttributes()
			guardian.requestSituations()

			c = guardian.Clock().After(10 * time.Second)
		}
	}
}

func (guardian *ModelGuardian) checkReloadModel() bool {
	if guardian.Clock().Now().After(guardian.referential.NextReloadAt()) {
		guardian.referential.ReloadModel()
		return true
	}
	return false
}

func (guardian *ModelGuardian) refreshStopAreas() {
	// Open a new transaction
	tx := guardian.referential.NewTransaction()
	defer tx.Close()

	now := guardian.Clock().Now()

	for _, stopArea := range tx.Model().StopAreas().FindAll() {
		if stopArea.ParentId != "" {
			parent, ok := stopArea.Parent()
			if ok && !parent.CollectChildren {
				continue
			}
		}
		if !stopArea.CollectedAlways && !stopArea.CollectedUntil.After(now) {
			continue
		}

		if stopArea.NextCollectAt.Before(now) {
			stopAreaTx := guardian.referential.NewTransaction()

			transactionnalStopArea, _ := stopAreaTx.Model().StopAreas().Find(stopArea.Id())

			randNb := time.Duration(rand.Intn(20)+40) * time.Second

			transactionnalStopArea.NextCollectAt = now.Add(randNb)
			transactionnalStopArea.Save()
			stopAreaTx.Commit()
			stopAreaTx.Close()

			stopAreaUpdateRequest := &StopAreaUpdateRequest{
				id:         StopAreaUpdateRequestId(guardian.NewUUID()),
				stopAreaId: transactionnalStopArea.Id(),
				createdAt:  now,
			}
			guardian.referential.CollectManager().UpdateStopArea(stopAreaUpdateRequest)
		}
	}
}

func (guardian *ModelGuardian) requestSituations() {
	tx := guardian.referential.NewTransaction()
	defer tx.Close()

	now := guardian.Clock().Now()

	for _, line := range tx.Model().Lines().FindAll() {
		if !line.CollectGeneralMessages || now.Before(line.CollectedAt().Add(1*time.Minute)) {
			continue
		}

		lineTx := guardian.referential.NewTransaction()

		transactionnalLine, _ := lineTx.Model().Lines().Find(line.Id())

		transactionnalLine.Updated(now)
		transactionnalLine.Save()
		lineTx.Commit()
		lineTx.Close()

		situationUpdateRequest := &SituationUpdateRequest{
			id:        SituationUpdateRequestId(guardian.NewUUID()),
			lineId:    line.Id(),
			createdAt: now,
		}
		guardian.referential.CollectManager().UpdateSituation(situationUpdateRequest)
	}
}

func (guardian *ModelGuardian) simulateActualAttributes() {
	tx := guardian.referential.NewTransaction()
	defer tx.Close()

	for _, stopVisit := range tx.Model().StopVisits().FindAll() {
		if stopVisit.IsCollected() {
			continue
		}

		// too verbse
		// logger.Log.Debugf("Simulate actual attributes on StopVisit %v", stopVisit.Id())

		stopVisitTx := guardian.referential.NewTransaction()
		defer stopVisitTx.Close()

		transactionnalStopVisit, _ := tx.Model().StopVisits().Find(stopVisit.Id())
		simulator := NewActualAttributesSimulator(&transactionnalStopVisit)
		simulator.SetClock(guardian.Clock())
		if simulator.Simulate() {
			transactionnalStopVisit.Save()
			stopVisitTx.Commit()
		} else {
			stopVisitTx.Rollback()
		}
	}
}

type ActualAttributesSimulator struct {
	model.ClockConsumer

	stopVisit *model.StopVisit
	now       time.Time
}

func NewActualAttributesSimulator(stopVisit *model.StopVisit) *ActualAttributesSimulator {
	return &ActualAttributesSimulator{stopVisit: stopVisit}
}

func (simulator *ActualAttributesSimulator) Now() time.Time {
	if simulator.now.IsZero() {
		simulator.now = simulator.Clock().Now()
	}
	return simulator.now
}

func (simulator *ActualAttributesSimulator) ArrivalTime() time.Time {
	return simulator.stopVisit.Schedules.ArrivalTimeFromKind([]model.StopVisitScheduleType{"expected", "aimed"})
}

func (simulator *ActualAttributesSimulator) AfterArrivalTime() bool {
	return simulator.Clock().Now().After(simulator.ArrivalTime())
}

func (simulator *ActualAttributesSimulator) DepartureTime() time.Time {
	return simulator.stopVisit.Schedules.DepartureTimeFromKind([]model.StopVisitScheduleType{"expected", "aimed"})
}

func (simulator *ActualAttributesSimulator) AfterDepartureTime() bool {
	return simulator.Clock().Now().After(simulator.DepartureTime())
}

func (simulator *ActualAttributesSimulator) Simulate() bool {
	if simulator.stopVisit.IsCollected() {
		return false
	}

	return simulator.simulateArrival() || simulator.simulateDeparture()
}

func (simulator *ActualAttributesSimulator) simulateArrival() bool {
	if simulator.AfterArrivalTime() && simulator.CanArrive() {
		simulator.stopVisit.ArrivalStatus = model.STOP_VISIT_ARRIVAL_CANCELLED
		simulator.stopVisit.Schedules.SetArrivalTime(model.STOP_VISIT_SCHEDULE_ACTUAL, simulator.ArrivalTime())

		logger.Log.Printf("Set StopVisit %s ArrivalStatus at %s", simulator.stopVisit.Id(), model.STOP_VISIT_ARRIVAL_CANCELLED)

		if !simulator.AfterDepartureTime() {
			simulator.stopVisit.VehicleAtStop = true
			logger.Log.Printf("Set StopVisit %s VehicleAtStop at true", simulator.stopVisit.Id())
		}

		return true
	}

	return false
}

func (simulator *ActualAttributesSimulator) CanArrive() bool {
	switch simulator.stopVisit.ArrivalStatus {
	case model.STOP_VISIT_ARRIVAL_ONTIME, model.STOP_VISIT_ARRIVAL_EARLY, model.STOP_VISIT_ARRIVAL_DELAYED:
		return true
	default:
		return false
	}
}

func (simulator *ActualAttributesSimulator) CanDepart() bool {
	switch simulator.stopVisit.DepartureStatus {
	case model.STOP_VISIT_DEPARTURE_ONTIME, model.STOP_VISIT_DEPARTURE_EARLY, model.STOP_VISIT_DEPARTURE_DELAYED:
		return true
	default:
		return false
	}
}

func (simulator *ActualAttributesSimulator) simulateDeparture() bool {
	if simulator.AfterDepartureTime() && simulator.CanDepart() {
		simulator.stopVisit.DepartureStatus = model.STOP_VISIT_DEPARTURE_CANCELLED

		simulator.stopVisit.Schedules.SetDepartureTime(model.STOP_VISIT_SCHEDULE_ACTUAL, simulator.DepartureTime())
		simulator.stopVisit.VehicleAtStop = false

		logger.Log.Printf("Set StopVisit %s DepartureStatus at %s", simulator.stopVisit.Id(), model.STOP_VISIT_DEPARTURE_CANCELLED)

		return true
	}
	return false
}
<|endoftext|>


<commit_before>package models

import (
	"bytes"
	"crypto/md5"
	"encoding/base64"
	"encoding/gob"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"regexp"
	"strings"

	log "github.com/Sirupsen/logrus"
	"github.com/SpectoLabs/hoverfly/core/handlers/v1"
	"github.com/SpectoLabs/hoverfly/core/handlers/v2"
	"github.com/SpectoLabs/hoverfly/core/interfaces"
	"github.com/SpectoLabs/hoverfly/core/util"
	"github.com/tdewolff/minify"
	"github.com/tdewolff/minify/json"
	"github.com/tdewolff/minify/xml"
)

const (
	contentTypeJSON = "application/json"
	contentTypeXML  = "application/xml"
	otherType       = "otherType"
)

var (
	rxJSON = regexp.MustCompile("[/+]json$")
	rxXML  = regexp.MustCompile("[/+]xml$")
	// mime types which will not be base 64 encoded when exporting as JSON
	supportedMimeTypes = [...]string{"text", "plain", "css", "html", "json", "xml", "js", "javascript"}
	minifiers          *minify.M
)

func init() {
	// GetNewMinifiers - sets minify.M with prepared xml/json minifiers
	minifiers = minify.New()
	minifiers.AddFuncRegexp(regexp.MustCompile("[/+]xml$"), xml.Minify)
	minifiers.AddFuncRegexp(regexp.MustCompile("[/+]json$"), json.Minify)
}

// Payload structure holds request and response structure
type RequestResponsePair struct {
	Response ResponseDetails `json:"response"`
	Request  RequestDetails  `json:"request"`
}

func (this RequestResponsePair) Id() string {
	return this.Request.Hash()
}

func (this RequestResponsePair) IdWithoutHost() string {
	return this.Request.HashWithoutHost()
}

// Encode method encodes all exported Payload fields to bytes
func (this *RequestResponsePair) Encode() ([]byte, error) {
	buf := new(bytes.Buffer)
	enc := gob.NewEncoder(buf)
	err := enc.Encode(this)
	if err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}

func (this *RequestResponsePair) ConvertToV1RequestResponsePairView() *v1.RequestResponsePairView {
	return &v1.RequestResponsePairView{Response: this.Response.ConvertToV1ResponseDetailsView(), Request: this.Request.ConvertToV1RequestDetailsView()}
}

func (this *RequestResponsePair) ConvertToRequestResponsePairView() v2.RequestResponsePairView {
	return v2.RequestResponsePairView{Response: this.Response.ConvertToResponseDetailsView(), Request: this.Request.ConvertToRequestDetailsView()}
}

// NewPayloadFromBytes decodes supplied bytes into Payload structure
func NewRequestResponsePairFromBytes(data []byte) (*RequestResponsePair, error) {
	var pair *RequestResponsePair
	buf := bytes.NewBuffer(data)
	dec := gob.NewDecoder(buf)
	err := dec.Decode(&pair)
	if err != nil {
		return nil, err
	}
	return pair, nil
}

func NewRequestResponsePairFromRequestResponsePairView(pairView interfaces.RequestResponsePair) RequestResponsePair {
	return RequestResponsePair{
		Response: NewResponseDetailsFromResponse(pairView.GetResponse()),
		Request:  NewRequestDetailsFromRequest(pairView.GetRequest()),
	}
}

// RequestDetails stores information about request, it's used for creating unique hash and also as a payload structure
type RequestDetails struct {
	Path        string              `json:"path"`
	Method      string              `json:"method"`
	Destination string              `json:"destination"`
	Scheme      string              `json:"scheme"`
	Query       string              `json:"query"`
	Body        string              `json:"body"`
	Headers     map[string][]string `json:"headers"`
}

func NewRequestDetailsFromHttpRequest(req *http.Request) (RequestDetails, error) {
	if req.Body == nil {
		req.Body = ioutil.NopCloser(bytes.NewBuffer([]byte("")))
	}

	reqBody, err := util.GetRequestBody(req)

	if err != nil {
		log.WithFields(log.Fields{
			"error": err.Error(),
			"mode":  "capture",
		}).Error("Got error while reading request body")
		return RequestDetails{}, err
	}

	requestDetails := RequestDetails{
		Path:        req.URL.Path,
		Method:      req.Method,
		Destination: req.Host,
		Scheme:      req.URL.Scheme,
		Query:       req.URL.RawQuery,
		Body:        string(reqBody),
		Headers:     req.Header,
	}
	return requestDetails, nil
}

func CopyBody(body io.ReadCloser) (resp1, resp2 io.ReadCloser, err error) {
	var buf bytes.Buffer
	if _, err = buf.ReadFrom(body); err != nil {
		return nil, nil, err
	}
	if err = body.Close(); err != nil {
		return nil, nil, err
	}
	return ioutil.NopCloser(&buf), ioutil.NopCloser(bytes.NewReader(buf.Bytes())), nil
}

func NewRequestDetailsFromRequest(data interfaces.Request) RequestDetails {
	return RequestDetails{
		Path:        util.PointerToString(data.GetPath()),
		Method:      util.PointerToString(data.GetMethod()),
		Destination: util.PointerToString(data.GetDestination()),
		Scheme:      util.PointerToString(data.GetScheme()),
		Query:       util.PointerToString(data.GetQuery()),
		Body:        util.PointerToString(data.GetBody()),
		Headers:     data.GetHeaders(),
	}
}

func (this *RequestDetails) ConvertToV1RequestDetailsView() v1.RequestDetailsView {
	s := "recording"
	return v1.RequestDetailsView{
		RequestType: &s,
		Path:        &this.Path,
		Method:      &this.Method,
		Destination: &this.Destination,
		Scheme:      &this.Scheme,
		Query:       &this.Query,
		Body:        &this.Body,
		Headers:     this.Headers,
	}
}

func (this *RequestDetails) ConvertToRequestDetailsView() v2.RequestDetailsView {
	s := "recording"
	return v2.RequestDetailsView{
		RequestType: &s,
		Path:        &this.Path,
		Method:      &this.Method,
		Destination: &this.Destination,
		Scheme:      &this.Scheme,
		Query:       &this.Query,
		Body:        &this.Body,
		Headers:     this.Headers,
	}
}

func (r *RequestDetails) concatenate(withHost bool) string {
	var buffer bytes.Buffer

	if withHost {
		buffer.WriteString(r.Destination)
	}

	values, _ := url.ParseQuery(r.Query)

	buffer.WriteString(r.Path)
	buffer.WriteString(r.Method)
	buffer.WriteString(values.Encode())
	if len(r.Body) > 0 {
		ct := r.getContentType()

		if ct == contentTypeJSON || ct == contentTypeXML {
			buffer.WriteString(r.minifyBody(ct))
		} else {
			log.WithFields(log.Fields{
				"content-type": r.Headers["Content-Type"],
			}).Debug("unknown content type")

			buffer.WriteString(r.Body)
		}
	}

	return buffer.String()
}

func (r *RequestDetails) minifyBody(mediaType string) (minified string) {
	var err error
	minified, err = minifiers.String(mediaType, r.Body)
	if err != nil {
		log.WithFields(log.Fields{
			"error":       err.Error(),
			"destination": r.Destination,
			"path":        r.Path,
			"method":      r.Method,
		}).Errorf("failed to minify request body, media type given: %s. Request matching might fail", mediaType)
		return r.Body
	}
	log.Debugf("body minified, mediatype: %s", mediaType)
	return minified
}

func (r *RequestDetails) Hash() string {
	h := md5.New()
	io.WriteString(h, r.concatenate(true))
	return fmt.Sprintf("%x", h.Sum(nil))
}

func (r *RequestDetails) HashWithoutHost() string {
	h := md5.New()
	io.WriteString(h, r.concatenate(false))
	return fmt.Sprintf("%x", h.Sum(nil))
}

func (r *RequestDetails) getContentType() string {
	for _, v := range r.Headers["Content-Type"] {
		if rxJSON.MatchString(v) {
			return contentTypeJSON
		}
		if rxXML.MatchString(v) {
			return contentTypeXML
		}
	}
	return otherType
}

// ResponseDetails structure hold response body from external service, body is not decoded and is supposed
// to be bytes, however headers should provide all required information for later decoding
// by the client.
type ResponseDetails struct {
	Status  int                 `json:"status"`
	Body    string              `json:"body"`
	Headers map[string][]string `json:"headers"`
}

func NewResponseDetailsFromResponse(data interfaces.Response) ResponseDetails {
	body := data.GetBody()

	if data.GetEncodedBody() == true {
		decoded, _ := base64.StdEncoding.DecodeString(data.GetBody())
		body = string(decoded)
	}

	return ResponseDetails{Status: data.GetStatus(), Body: body, Headers: data.GetHeaders()}
}

// This function will create a JSON appriopriate version of ResponseDetails for the v1 API
// If the response headers indicate that the content is encoded, or it has a non-matching
// supported mimetype, we base64 encode it.
func (r *ResponseDetails) ConvertToV1ResponseDetailsView() v1.ResponseDetailsView {
	needsEncoding := false

	// Check headers for gzip
	contentEncodingValues := r.Headers["Content-Encoding"]
	if len(contentEncodingValues) > 0 {
		needsEncoding = true
	} else {
		mimeType := http.DetectContentType([]byte(r.Body))
		needsEncoding = true
		for _, v := range supportedMimeTypes {
			if strings.Contains(mimeType, v) {
				needsEncoding = false
				break
			}
		}
	}

	// If contains gzip, base64 encode
	body := r.Body
	if needsEncoding {
		body = base64.StdEncoding.EncodeToString([]byte(r.Body))
	}

	return v1.ResponseDetailsView{Status: r.Status, Body: body, Headers: r.Headers, EncodedBody: needsEncoding}
}

// This function will create a JSON appriopriate version of ResponseDetails for the v2 API
// If the response headers indicate that the content is encoded, or it has a non-matching
// supported mimetype, we base64 encode it.
func (r *ResponseDetails) ConvertToResponseDetailsView() v2.ResponseDetailsView {
	needsEncoding := false

	// Check headers for gzip
	contentEncodingValues := r.Headers["Content-Encoding"]
	if len(contentEncodingValues) > 0 {
		needsEncoding = true
	} else {
		mimeType := http.DetectContentType([]byte(r.Body))
		needsEncoding = true
		for _, v := range supportedMimeTypes {
			if strings.Contains(mimeType, v) {
				needsEncoding = false
				break
			}
		}
	}

	// If contains gzip, base64 encode
	body := r.Body
	if needsEncoding {
		body = base64.StdEncoding.EncodeToString([]byte(r.Body))
	}

	return v2.ResponseDetailsView{Status: r.Status, Body: body, Headers: r.Headers, EncodedBody: needsEncoding}
}
<commit_msg>Replacing url.ParseQuery() with utils.SortQueryString() to be consistent with RequestTemplateStore<commit_after>package models

import (
	"bytes"
	"crypto/md5"
	"encoding/base64"
	"encoding/gob"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"regexp"
	"strings"

	log "github.com/Sirupsen/logrus"
	"github.com/SpectoLabs/hoverfly/core/handlers/v1"
	"github.com/SpectoLabs/hoverfly/core/handlers/v2"
	"github.com/SpectoLabs/hoverfly/core/interfaces"
	"github.com/SpectoLabs/hoverfly/core/util"
	"github.com/tdewolff/minify"
	"github.com/tdewolff/minify/json"
	"github.com/tdewolff/minify/xml"
)

const (
	contentTypeJSON = "application/json"
	contentTypeXML  = "application/xml"
	otherType       = "otherType"
)

var (
	rxJSON = regexp.MustCompile("[/+]json$")
	rxXML  = regexp.MustCompile("[/+]xml$")
	// mime types which will not be base 64 encoded when exporting as JSON
	supportedMimeTypes = [...]string{"text", "plain", "css", "html", "json", "xml", "js", "javascript"}
	minifiers          *minify.M
)

func init() {
	// GetNewMinifiers - sets minify.M with prepared xml/json minifiers
	minifiers = minify.New()
	minifiers.AddFuncRegexp(regexp.MustCompile("[/+]xml$"), xml.Minify)
	minifiers.AddFuncRegexp(regexp.MustCompile("[/+]json$"), json.Minify)
}

// Payload structure holds request and response structure
type RequestResponsePair struct {
	Response ResponseDetails `json:"response"`
	Request  RequestDetails  `json:"request"`
}

func (this RequestResponsePair) Id() string {
	return this.Request.Hash()
}

func (this RequestResponsePair) IdWithoutHost() string {
	return this.Request.HashWithoutHost()
}

// Encode method encodes all exported Payload fields to bytes
func (this *RequestResponsePair) Encode() ([]byte, error) {
	buf := new(bytes.Buffer)
	enc := gob.NewEncoder(buf)
	err := enc.Encode(this)
	if err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}

func (this *RequestResponsePair) ConvertToV1RequestResponsePairView() *v1.RequestResponsePairView {
	return &v1.RequestResponsePairView{Response: this.Response.ConvertToV1ResponseDetailsView(), Request: this.Request.ConvertToV1RequestDetailsView()}
}

func (this *RequestResponsePair) ConvertToRequestResponsePairView() v2.RequestResponsePairView {
	return v2.RequestResponsePairView{Response: this.Response.ConvertToResponseDetailsView(), Request: this.Request.ConvertToRequestDetailsView()}
}

// NewPayloadFromBytes decodes supplied bytes into Payload structure
func NewRequestResponsePairFromBytes(data []byte) (*RequestResponsePair, error) {
	var pair *RequestResponsePair
	buf := bytes.NewBuffer(data)
	dec := gob.NewDecoder(buf)
	err := dec.Decode(&pair)
	if err != nil {
		return nil, err
	}
	return pair, nil
}

func NewRequestResponsePairFromRequestResponsePairView(pairView interfaces.RequestResponsePair) RequestResponsePair {
	return RequestResponsePair{
		Response: NewResponseDetailsFromResponse(pairView.GetResponse()),
		Request:  NewRequestDetailsFromRequest(pairView.GetRequest()),
	}
}

// RequestDetails stores information about request, it's used for creating unique hash and also as a payload structure
type RequestDetails struct {
	Path        string              `json:"path"`
	Method      string              `json:"method"`
	Destination string              `json:"destination"`
	Scheme      string              `json:"scheme"`
	Query       string              `json:"query"`
	Body        string              `json:"body"`
	Headers     map[string][]string `json:"headers"`
}

func NewRequestDetailsFromHttpRequest(req *http.Request) (RequestDetails, error) {
	if req.Body == nil {
		req.Body = ioutil.NopCloser(bytes.NewBuffer([]byte("")))
	}

	reqBody, err := util.GetRequestBody(req)

	if err != nil {
		log.WithFields(log.Fields{
			"error": err.Error(),
			"mode":  "capture",
		}).Error("Got error while reading request body")
		return RequestDetails{}, err
	}

	requestDetails := RequestDetails{
		Path:        req.URL.Path,
		Method:      req.Method,
		Destination: req.Host,
		Scheme:      req.URL.Scheme,
		Query:       req.URL.RawQuery,
		Body:        string(reqBody),
		Headers:     req.Header,
	}
	return requestDetails, nil
}

func CopyBody(body io.ReadCloser) (resp1, resp2 io.ReadCloser, err error) {
	var buf bytes.Buffer
	if _, err = buf.ReadFrom(body); err != nil {
		return nil, nil, err
	}
	if err = body.Close(); err != nil {
		return nil, nil, err
	}
	return ioutil.NopCloser(&buf), ioutil.NopCloser(bytes.NewReader(buf.Bytes())), nil
}

func NewRequestDetailsFromRequest(data interfaces.Request) RequestDetails {
	return RequestDetails{
		Path:        util.PointerToString(data.GetPath()),
		Method:      util.PointerToString(data.GetMethod()),
		Destination: util.PointerToString(data.GetDestination()),
		Scheme:      util.PointerToString(data.GetScheme()),
		Query:       util.PointerToString(data.GetQuery()),
		Body:        util.PointerToString(data.GetBody()),
		Headers:     data.GetHeaders(),
	}
}

func (this *RequestDetails) ConvertToV1RequestDetailsView() v1.RequestDetailsView {
	s := "recording"
	return v1.RequestDetailsView{
		RequestType: &s,
		Path:        &this.Path,
		Method:      &this.Method,
		Destination: &this.Destination,
		Scheme:      &this.Scheme,
		Query:       &this.Query,
		Body:        &this.Body,
		Headers:     this.Headers,
	}
}

func (this *RequestDetails) ConvertToRequestDetailsView() v2.RequestDetailsView {
	s := "recording"
	return v2.RequestDetailsView{
		RequestType: &s,
		Path:        &this.Path,
		Method:      &this.Method,
		Destination: &this.Destination,
		Scheme:      &this.Scheme,
		Query:       &this.Query,
		Body:        &this.Body,
		Headers:     this.Headers,
	}
}

func (r *RequestDetails) concatenate(withHost bool) string {
	var buffer bytes.Buffer

	if withHost {
		buffer.WriteString(r.Destination)
	}

	buffer.WriteString(r.Path)
	buffer.WriteString(r.Method)
	buffer.WriteString(util.SortQueryString(r.Query))
	if len(r.Body) > 0 {
		ct := r.getContentType()

		if ct == contentTypeJSON || ct == contentTypeXML {
			buffer.WriteString(r.minifyBody(ct))
		} else {
			log.WithFields(log.Fields{
				"content-type": r.Headers["Content-Type"],
			}).Debug("unknown content type")

			buffer.WriteString(r.Body)
		}
	}

	return buffer.String()
}

func (r *RequestDetails) minifyBody(mediaType string) (minified string) {
	var err error
	minified, err = minifiers.String(mediaType, r.Body)
	if err != nil {
		log.WithFields(log.Fields{
			"error":       err.Error(),
			"destination": r.Destination,
			"path":        r.Path,
			"method":      r.Method,
		}).Errorf("failed to minify request body, media type given: %s. Request matching might fail", mediaType)
		return r.Body
	}
	log.Debugf("body minified, mediatype: %s", mediaType)
	return minified
}

func (r *RequestDetails) Hash() string {
	h := md5.New()
	io.WriteString(h, r.concatenate(true))
	return fmt.Sprintf("%x", h.Sum(nil))
}

func (r *RequestDetails) HashWithoutHost() string {
	h := md5.New()
	io.WriteString(h, r.concatenate(false))
	return fmt.Sprintf("%x", h.Sum(nil))
}

func (r *RequestDetails) getContentType() string {
	for _, v := range r.Headers["Content-Type"] {
		if rxJSON.MatchString(v) {
			return contentTypeJSON
		}
		if rxXML.MatchString(v) {
			return contentTypeXML
		}
	}
	return otherType
}

// ResponseDetails structure hold response body from external service, body is not decoded and is supposed
// to be bytes, however headers should provide all required information for later decoding
// by the client.
type ResponseDetails struct {
	Status  int                 `json:"status"`
	Body    string              `json:"body"`
	Headers map[string][]string `json:"headers"`
}

func NewResponseDetailsFromResponse(data interfaces.Response) ResponseDetails {
	body := data.GetBody()

	if data.GetEncodedBody() == true {
		decoded, _ := base64.StdEncoding.DecodeString(data.GetBody())
		body = string(decoded)
	}

	return ResponseDetails{Status: data.GetStatus(), Body: body, Headers: data.GetHeaders()}
}

// This function will create a JSON appriopriate version of ResponseDetails for the v1 API
// If the response headers indicate that the content is encoded, or it has a non-matching
// supported mimetype, we base64 encode it.
func (r *ResponseDetails) ConvertToV1ResponseDetailsView() v1.ResponseDetailsView {
	needsEncoding := false

	// Check headers for gzip
	contentEncodingValues := r.Headers["Content-Encoding"]
	if len(contentEncodingValues) > 0 {
		needsEncoding = true
	} else {
		mimeType := http.DetectContentType([]byte(r.Body))
		needsEncoding = true
		for _, v := range supportedMimeTypes {
			if strings.Contains(mimeType, v) {
				needsEncoding = false
				break
			}
		}
	}

	// If contains gzip, base64 encode
	body := r.Body
	if needsEncoding {
		body = base64.StdEncoding.EncodeToString([]byte(r.Body))
	}

	return v1.ResponseDetailsView{Status: r.Status, Body: body, Headers: r.Headers, EncodedBody: needsEncoding}
}

// This function will create a JSON appriopriate version of ResponseDetails for the v2 API
// If the response headers indicate that the content is encoded, or it has a non-matching
// supported mimetype, we base64 encode it.
func (r *ResponseDetails) ConvertToResponseDetailsView() v2.ResponseDetailsView {
	needsEncoding := false

	// Check headers for gzip
	contentEncodingValues := r.Headers["Content-Encoding"]
	if len(contentEncodingValues) > 0 {
		needsEncoding = true
	} else {
		mimeType := http.DetectContentType([]byte(r.Body))
		needsEncoding = true
		for _, v := range supportedMimeTypes {
			if strings.Contains(mimeType, v) {
				needsEncoding = false
				break
			}
		}
	}

	// If contains gzip, base64 encode
	body := r.Body
	if needsEncoding {
		body = base64.StdEncoding.EncodeToString([]byte(r.Body))
	}

	return v2.ResponseDetailsView{Status: r.Status, Body: body, Headers: r.Headers, EncodedBody: needsEncoding}
}
<|endoftext|>


<commit_before>package narcissus

import (
	"fmt"
	"reflect"
	"strconv"
	"strings"
)

// Parse parses a structure pointer and feeds its fields with Augeas data
func (n *Narcissus) Parse(val interface{}) error {
	ref, err := structRef(val)
	if err != nil {
		return fmt.Errorf("invalid interface: %v", err)
	}

	path, err := getPath(ref)
	if err != nil {
		return fmt.Errorf("undefined path: %v", err)
	}

	return n.parseStruct(ref, path)
}

func (n *Narcissus) parseStruct(ref reflect.Value, path string) error {
	refType := ref.Type()
	for i := 0; i < refType.NumField(); i++ {
		if refType.Field(i).Name == "augeasPath" {
			// Ignore the special `augeasPath` field
			continue
		}
		value, err := n.getField(ref.Field(i), refType.Field(i), path)
		// TODO: implement omitempty
		if err == ErrNodeNotFound {
			continue
		}
		if err != nil {
			return fmt.Errorf("failed to retrieve field %s: %v", refType.Field(i).Name, err)
		}
		if value == "" {
			// for now
			continue
		}
		err = setField(ref.Field(i), refType.Field(i), value)
		if err != nil {
			return err
		}
	}

	return nil
}

func (n *Narcissus) getField(field reflect.Value, fieldType reflect.StructField, path string) (interface{}, error) {
	fieldPath := fmt.Sprintf("%s/%s", path, fieldType.Tag.Get("path"))
	if field.Kind() == reflect.Slice {
		return n.getSliceField(field, fieldType, path, fieldPath)
	} else if field.Kind() == reflect.Map {
		return n.getMapField(field, fieldType, fieldPath)
	}
	return n.getSimpleField(fieldType.Type, fieldPath, fieldType.Tag)
}

func (n *Narcissus) getSimpleField(fieldType reflect.Type, fieldPath string, tag reflect.StructTag) (interface{}, error) {
	aug := n.Augeas
	var value string
	var err error
	if tag.Get("value-from") == "label" {
		value, err = aug.Label(fieldPath)
	} else {
		value, err = aug.Get(fieldPath)
	}
	if err != nil && strings.Contains(err.Error(), "No matching node") {
		return nil, ErrNodeNotFound
	}

	switch fieldType.Kind() {
	case reflect.String:
		return value, nil
	case reflect.Bool:
		bvalue, err := strconv.ParseBool(value)
		if err != nil {
			return nil, fmt.Errorf("failed to convert %s to bool: %v", value, err)
		}
		return bvalue, nil
	case reflect.Int:
		intValue, err := strconv.ParseInt(value, 10, 32)
		if err != nil {
			return nil, fmt.Errorf("failed to convert %s to int: %v", value, err)
		}
		return int(intValue), nil
	}
	return nil, fmt.Errorf("unsupported type %s", fieldType.Kind())
}

func (n *Narcissus) getSliceField(field reflect.Value, fieldType reflect.StructField, path, fieldPath string) (interface{}, error) {
	aug := n.Augeas

	if fieldType.Tag.Get("type") == "seq" {
		fieldPath = fmt.Sprintf("%s/*[label()=~regexp('[0-9]*')]", path)
	}
	matches, err := aug.Match(fieldPath)
	if err != nil {
		return nil, err
	}
	values := reflect.MakeSlice(field.Type(), len(matches), len(matches))
	for i, m := range matches {
		vType := field.Type().Elem()
		var value reflect.Value
		if vType.Kind() == reflect.Struct {
			vStruct := reflect.New(vType)
			err = n.parseStruct(vStruct.Elem(), m)
			if err != nil {
				return nil, fmt.Errorf("failed to get slice element: %v", err)
			}
			value = vStruct.Elem()
		} else {
			val, err := n.getSimpleField(vType, m, "")
			if err != nil {
				return nil, fmt.Errorf("failed to get slice element: %v", err)
			}
			value = reflect.ValueOf(val)
		}
		values.Index(i).Set(value)
	}
	return values.Interface(), nil
}

func (n *Narcissus) getMapField(field reflect.Value, fieldType reflect.StructField, fieldPath string) (interface{}, error) {
	aug := n.Augeas
	values := reflect.MakeMap(field.Type())
	matches, err := aug.Match(fieldPath)
	if err != nil {
		return nil, err
	}
	for _, m := range matches {
		var label string
		if fieldType.Tag.Get("key") == "label" {
			label, err = aug.Label(m)
		} else {
			label, err = aug.Get(m)
		}
		if err != nil {
			return nil, err
		}
		vType := field.Type().Elem()
		var value reflect.Value
		if vType.Kind() == reflect.Struct {
			vStruct := reflect.New(vType)
			err = n.parseStruct(vStruct.Elem(), m)
			if err != nil {
				return nil, err
			}
			value = vStruct.Elem()
		} else {
			val, err := n.getSimpleField(vType, m, "")
			if err != nil {
				return nil, fmt.Errorf("failed to get slice element: %v", err)
			}
			value = reflect.ValueOf(val)
		}
		values.SetMapIndex(reflect.ValueOf(label), value)
	}
	return values.Interface(), nil
}

func setField(field reflect.Value, fieldType reflect.StructField, value interface{}) error {
	if !field.CanSet() {
		return fmt.Errorf("cannot set field %s", fieldType.Name)
	}

	v := reflect.ValueOf(value)
	if field.Kind() == v.Kind() {
		field.Set(v)
		return nil
	}

	return fmt.Errorf("Wrong value type (%v for %v)", v.Kind(), field.Kind())
}
<commit_msg>Add getStructOrSimpleField() to refactor<commit_after>package narcissus

import (
	"fmt"
	"reflect"
	"strconv"
	"strings"
)

// Parse parses a structure pointer and feeds its fields with Augeas data
func (n *Narcissus) Parse(val interface{}) error {
	ref, err := structRef(val)
	if err != nil {
		return fmt.Errorf("invalid interface: %v", err)
	}

	path, err := getPath(ref)
	if err != nil {
		return fmt.Errorf("undefined path: %v", err)
	}

	return n.parseStruct(ref, path)
}

func (n *Narcissus) parseStruct(ref reflect.Value, path string) error {
	refType := ref.Type()
	for i := 0; i < refType.NumField(); i++ {
		if refType.Field(i).Name == "augeasPath" {
			// Ignore the special `augeasPath` field
			continue
		}
		value, err := n.getField(ref.Field(i), refType.Field(i), path)
		// TODO: implement omitempty
		if err == ErrNodeNotFound {
			continue
		}
		if err != nil {
			return fmt.Errorf("failed to retrieve field %s: %v", refType.Field(i).Name, err)
		}
		if value == "" {
			// for now
			continue
		}
		err = setField(ref.Field(i), refType.Field(i), value)
		if err != nil {
			return err
		}
	}

	return nil
}

func (n *Narcissus) getField(field reflect.Value, fieldType reflect.StructField, path string) (interface{}, error) {
	fieldPath := fmt.Sprintf("%s/%s", path, fieldType.Tag.Get("path"))
	if field.Kind() == reflect.Slice {
		return n.getSliceField(field, fieldType, path, fieldPath)
	} else if field.Kind() == reflect.Map {
		return n.getMapField(field, fieldType, fieldPath)
	}
	return n.getSimpleField(fieldType.Type, fieldPath, fieldType.Tag)
}

func (n *Narcissus) getSimpleField(fieldType reflect.Type, fieldPath string, tag reflect.StructTag) (interface{}, error) {
	aug := n.Augeas
	var value string
	var err error
	if tag.Get("value-from") == "label" {
		value, err = aug.Label(fieldPath)
	} else {
		value, err = aug.Get(fieldPath)
	}
	if err != nil && strings.Contains(err.Error(), "No matching node") {
		return nil, ErrNodeNotFound
	}

	switch fieldType.Kind() {
	case reflect.String:
		return value, nil
	case reflect.Bool:
		bvalue, err := strconv.ParseBool(value)
		if err != nil {
			return nil, fmt.Errorf("failed to convert %s to bool: %v", value, err)
		}
		return bvalue, nil
	case reflect.Int:
		intValue, err := strconv.ParseInt(value, 10, 32)
		if err != nil {
			return nil, fmt.Errorf("failed to convert %s to int: %v", value, err)
		}
		return int(intValue), nil
	}
	return nil, fmt.Errorf("unsupported type %s", fieldType.Kind())
}

func (n *Narcissus) getSliceField(field reflect.Value, fieldType reflect.StructField, path, fieldPath string) (interface{}, error) {
	aug := n.Augeas

	if fieldType.Tag.Get("type") == "seq" {
		fieldPath = fmt.Sprintf("%s/*[label()=~regexp('[0-9]*')]", path)
	}
	matches, err := aug.Match(fieldPath)
	if err != nil {
		return nil, err
	}
	values := reflect.MakeSlice(field.Type(), len(matches), len(matches))
	for i, m := range matches {
		value, err := n.getStructOrSimpleField(field, m)
		if err != nil {
			return nil, fmt.Errorf("Failed to get slice element: %v", err)
		}
		values.Index(i).Set(value)
	}
	return values.Interface(), nil
}

func (n *Narcissus) getMapField(field reflect.Value, fieldType reflect.StructField, fieldPath string) (interface{}, error) {
	aug := n.Augeas
	values := reflect.MakeMap(field.Type())
	matches, err := aug.Match(fieldPath)
	if err != nil {
		return nil, err
	}
	for _, m := range matches {
		var label string
		if fieldType.Tag.Get("key") == "label" {
			label, err = aug.Label(m)
		} else {
			label, err = aug.Get(m)
		}
		if err != nil {
			return nil, err
		}
		value, err := n.getStructOrSimpleField(field, m)
		if err != nil {
			return nil, fmt.Errorf("Failed to get map element: %v", err)
		}
		values.SetMapIndex(reflect.ValueOf(label), value)
	}
	return values.Interface(), nil
}

func (n *Narcissus) getStructOrSimpleField(field reflect.Value, path string) (value reflect.Value, err error) {
	vType := field.Type().Elem()
	if vType.Kind() == reflect.Struct {
		vStruct := reflect.New(vType)
		err = n.parseStruct(vStruct.Elem(), path)
		if err != nil {
			err = fmt.Errorf("failed to get slice element: %v", err)
			return
		}
		return vStruct.Elem(), nil
	}
	val, err := n.getSimpleField(vType, path, "")
	if err != nil {
		err = fmt.Errorf("failed to get slice element: %v", err)
		return
	}
	return reflect.ValueOf(val), nil
}

func setField(field reflect.Value, fieldType reflect.StructField, value interface{}) error {
	if !field.CanSet() {
		return fmt.Errorf("cannot set field %s", fieldType.Name)
	}

	v := reflect.ValueOf(value)
	if field.Kind() == v.Kind() {
		field.Set(v)
		return nil
	}

	return fmt.Errorf("Wrong value type (%v for %v)", v.Kind(), field.Kind())
}
<|endoftext|>


<commit_before>// Copyright 2009 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 bytes

// Simple byte buffer for marshaling data.

import (
	"io";
	"os";
)

// Copy from string to byte array at offset doff.  Assume there's room.
func copyString(dst []byte, doff int, str string) {
	for soff := 0; soff < len(str); soff++ {
		dst[doff] = str[soff];
		doff++;
	}
}

// A Buffer is a variable-sized buffer of bytes
// with Read and Write methods.
// The zero value for Buffer is an empty buffer ready to use.
type Buffer struct {
	buf		[]byte;		// contents are the bytes buf[off : len(buf)]
	off		int;		// read at &buf[off], write at &buf[len(buf)]
	oneByte		[1]byte;	// avoid allocation of slice on each WriteByte
	bootstrap	[64]byte;	// memory to hold first slice; helps small buffers (Printf) avoid allocation.
}

// Bytes returns the contents of the unread portion of the buffer;
// len(b.Bytes()) == b.Len().
func (b *Buffer) Bytes() []byte	{ return b.buf[b.off:] }

// String returns the contents of the unread portion of the buffer
// as a string.  If the Buffer is a nil pointer, it returns "<nil>".
func (b *Buffer) String() string {
	if b == nil {
		// Special case, useful in debugging.
		return "<nil>"
	}
	return string(b.buf[b.off:]);
}

// Len returns the number of bytes of the unread portion of the buffer;
// b.Len() == len(b.Bytes()).
func (b *Buffer) Len() int	{ return len(b.buf) - b.off }

// Truncate discards all but the first n unread bytes from the buffer.
// It is an error to call b.Truncate(n) with n > b.Len().
func (b *Buffer) Truncate(n int) {
	if n == 0 {
		// Reuse buffer space.
		b.off = 0
	}
	b.buf = b.buf[0 : b.off+n];
}

// Reset resets the buffer so it has no content.
// b.Reset() is the same as b.Truncate(0).
func (b *Buffer) Reset()	{ b.Truncate(0) }

// Resize buffer to guarantee enough space for n more bytes.
// After this call, the state of b.buf is inconsistent.
// It must be fixed up as is done in Write and WriteString.
func (b *Buffer) resize(n int) {
	var buf []byte;
	if b.buf == nil && n <= len(b.bootstrap) {
		buf = &b.bootstrap
	} else {
		buf = b.buf;
		if len(b.buf)+n > cap(b.buf) {
			// not enough space anywhere
			buf = make([]byte, 2*cap(b.buf)+n)
		}
		copy(buf, b.buf[b.off:]);
	}
	b.buf = buf;
	b.off = 0;
}

// Write appends the contents of p to the buffer.  The return
// value n is the length of p; err is always nil.
func (b *Buffer) Write(p []byte) (n int, err os.Error) {
	m := b.Len();
	n = len(p);
	if len(b.buf)+n > cap(b.buf) {
		b.resize(n)
	}
	b.buf = b.buf[0 : b.off+m+n];
	copy(b.buf[b.off+m:], p);
	return n, nil;
}

// WriteString appends the contents of s to the buffer.  The return
// value n is the length of s; err is always nil.
func (b *Buffer) WriteString(s string) (n int, err os.Error) {
	m := b.Len();
	n = len(s);
	if len(b.buf)+n > cap(b.buf) {
		b.resize(n)
	}
	b.buf = b.buf[0 : b.off+m+n];
	copyString(b.buf, b.off+m, s);
	return n, nil;
}

// MinRead is the minimum slice size passed to a Read call by
// Buffer.ReadFrom.  As long as the Buffer has at least MinRead bytes beyond
// what is required to hold the contents of r, ReadFrom will not grow the
// underlying buffer.
const MinRead = 512

// ReadFrom reads data from r until EOF and appends it to the buffer.
// The return value n is the number of bytes read.
// Any error except os.EOF encountered during the read
// is also returned.
func (b *Buffer) ReadFrom(r io.Reader) (n int64, err os.Error) {
	for {
		if cap(b.buf)-len(b.buf) < MinRead {
			var newBuf []byte;
			// can we get space without allocation?
			if b.off+cap(b.buf)-len(b.buf) >= MinRead {
				// reuse beginning of buffer
				newBuf = b.buf[0 : len(b.buf)-b.off]
			} else {
				// not enough space at end; put space on end
				newBuf = make([]byte, len(b.buf)-b.off, 2*(cap(b.buf)-b.off)+MinRead)
			}
			copy(newBuf, b.buf[b.off:]);
			b.buf = newBuf;
			b.off = 0;
		}
		m, e := r.Read(b.buf[len(b.buf):cap(b.buf)]);
		b.buf = b.buf[b.off : len(b.buf)+m];
		n += int64(m);
		if e == os.EOF {
			break
		}
		if e != nil {
			return n, e
		}
	}
	return n, nil;	// err is EOF, so return nil explicitly
}

// WriteTo writes data to w until the buffer is drained or an error
// occurs. The return value n is the number of bytes written.
// Any error encountered during the write is also returned.
func (b *Buffer) WriteTo(w io.Writer) (n int64, err os.Error) {
	for b.off < len(b.buf) {
		m, e := w.Write(b.buf[b.off:]);
		n += int64(m);
		b.off += m;
		if e != nil {
			return n, e
		}
	}
	return;
}

// WriteByte appends the byte c to the buffer.
// The returned error is always nil, but is included
// to match bufio.Writer's WriteByte.
func (b *Buffer) WriteByte(c byte) os.Error {
	b.oneByte[0] = c;
	b.Write(&b.oneByte);
	return nil;
}

// Read reads the next len(p) bytes from the buffer or until the buffer
// is drained.  The return value n is the number of bytes read.  If the
// buffer has no data to return, err is os.EOF even if len(p) is zero;
// otherwise it is nil.
func (b *Buffer) Read(p []byte) (n int, err os.Error) {
	if b.off >= len(b.buf) {
		return 0, os.EOF
	}
	m := b.Len();
	n = len(p);

	if n > m {
		// more bytes requested than available
		n = m
	}

	copy(p, b.buf[b.off:b.off+n]);
	b.off += n;
	return n, err;
}

// ReadByte reads and returns the next byte from the buffer.
// If no byte is available, it returns error os.EOF.
func (b *Buffer) ReadByte() (c byte, err os.Error) {
	if b.off >= len(b.buf) {
		return 0, os.EOF
	}
	c = b.buf[b.off];
	b.off++;
	return c, nil;
}

// NewBuffer creates and initializes a new Buffer
// using buf as its initial contents.
func NewBuffer(buf []byte) *Buffer	{ return &Buffer{buf: buf} }

// NewBufferString creates and initializes a new Buffer
// using string s as its initial contents.
func NewBufferString(s string) *Buffer {
	buf := make([]byte, len(s));
	copyString(buf, 0, s);
	return &Buffer{buf: buf};
}
<commit_msg>When the buffer is empty, reset b.off to the beginning of the buffer to avoid growing unnecessarily.<commit_after>// Copyright 2009 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 bytes

// Simple byte buffer for marshaling data.

import (
	"io";
	"os";
)

// Copy from string to byte array at offset doff.  Assume there's room.
func copyString(dst []byte, doff int, str string) {
	for soff := 0; soff < len(str); soff++ {
		dst[doff] = str[soff];
		doff++;
	}
}

// A Buffer is a variable-sized buffer of bytes
// with Read and Write methods.
// The zero value for Buffer is an empty buffer ready to use.
type Buffer struct {
	buf		[]byte;		// contents are the bytes buf[off : len(buf)]
	off		int;		// read at &buf[off], write at &buf[len(buf)]
	oneByte		[1]byte;	// avoid allocation of slice on each WriteByte
	bootstrap	[64]byte;	// memory to hold first slice; helps small buffers (Printf) avoid allocation.
}

// Bytes returns the contents of the unread portion of the buffer;
// len(b.Bytes()) == b.Len().
func (b *Buffer) Bytes() []byte	{ return b.buf[b.off:] }

// String returns the contents of the unread portion of the buffer
// as a string.  If the Buffer is a nil pointer, it returns "<nil>".
func (b *Buffer) String() string {
	if b == nil {
		// Special case, useful in debugging.
		return "<nil>"
	}
	return string(b.buf[b.off:]);
}

// Len returns the number of bytes of the unread portion of the buffer;
// b.Len() == len(b.Bytes()).
func (b *Buffer) Len() int	{ return len(b.buf) - b.off }

// Truncate discards all but the first n unread bytes from the buffer.
// It is an error to call b.Truncate(n) with n > b.Len().
func (b *Buffer) Truncate(n int) {
	if n == 0 {
		// Reuse buffer space.
		b.off = 0
	}
	b.buf = b.buf[0 : b.off+n];
}

// Reset resets the buffer so it has no content.
// b.Reset() is the same as b.Truncate(0).
func (b *Buffer) Reset()	{ b.Truncate(0) }

// Resize buffer to guarantee enough space for n more bytes.
// After this call, the state of b.buf is inconsistent.
// It must be fixed up as is done in Write and WriteString.
func (b *Buffer) resize(n int) {
	var buf []byte;
	if b.buf == nil && n <= len(b.bootstrap) {
		buf = &b.bootstrap
	} else {
		buf = b.buf;
		if len(b.buf)+n > cap(b.buf) {
			// not enough space anywhere
			buf = make([]byte, 2*cap(b.buf)+n)
		}
		copy(buf, b.buf[b.off:]);
	}
	b.buf = buf;
	b.off = 0;
}

// Write appends the contents of p to the buffer.  The return
// value n is the length of p; err is always nil.
func (b *Buffer) Write(p []byte) (n int, err os.Error) {
	m := b.Len();
	// If buffer is empty, reset to recover space.
	if m == 0 && b.off != 0 {
		b.Truncate(0)
	}
	n = len(p);
	if len(b.buf)+n > cap(b.buf) {
		b.resize(n)
	}
	b.buf = b.buf[0 : b.off+m+n];
	copy(b.buf[b.off+m:], p);
	return n, nil;
}

// WriteString appends the contents of s to the buffer.  The return
// value n is the length of s; err is always nil.
func (b *Buffer) WriteString(s string) (n int, err os.Error) {
	m := b.Len();
	// If buffer is empty, reset to recover space.
	if m == 0 && b.off != 0 {
		b.Truncate(0)
	}
	n = len(s);
	if len(b.buf)+n > cap(b.buf) {
		b.resize(n)
	}
	b.buf = b.buf[0 : b.off+m+n];
	copyString(b.buf, b.off+m, s);
	return n, nil;
}

// MinRead is the minimum slice size passed to a Read call by
// Buffer.ReadFrom.  As long as the Buffer has at least MinRead bytes beyond
// what is required to hold the contents of r, ReadFrom will not grow the
// underlying buffer.
const MinRead = 512

// ReadFrom reads data from r until EOF and appends it to the buffer.
// The return value n is the number of bytes read.
// Any error except os.EOF encountered during the read
// is also returned.
func (b *Buffer) ReadFrom(r io.Reader) (n int64, err os.Error) {
	// If buffer is empty, reset to recover space.
	if b.off >= len(b.buf) {
		b.Truncate(0)
	}
	for {
		if cap(b.buf)-len(b.buf) < MinRead {
			var newBuf []byte;
			// can we get space without allocation?
			if b.off+cap(b.buf)-len(b.buf) >= MinRead {
				// reuse beginning of buffer
				newBuf = b.buf[0 : len(b.buf)-b.off]
			} else {
				// not enough space at end; put space on end
				newBuf = make([]byte, len(b.buf)-b.off, 2*(cap(b.buf)-b.off)+MinRead)
			}
			copy(newBuf, b.buf[b.off:]);
			b.buf = newBuf;
			b.off = 0;
		}
		m, e := r.Read(b.buf[len(b.buf):cap(b.buf)]);
		b.buf = b.buf[b.off : len(b.buf)+m];
		n += int64(m);
		if e == os.EOF {
			break
		}
		if e != nil {
			return n, e
		}
	}
	return n, nil;	// err is EOF, so return nil explicitly
}

// WriteTo writes data to w until the buffer is drained or an error
// occurs. The return value n is the number of bytes written.
// Any error encountered during the write is also returned.
func (b *Buffer) WriteTo(w io.Writer) (n int64, err os.Error) {
	for b.off < len(b.buf) {
		m, e := w.Write(b.buf[b.off:]);
		n += int64(m);
		b.off += m;
		if e != nil {
			return n, e
		}
	}
	// Buffer is now empty; reset.
	b.Truncate(0);
	return;
}

// WriteByte appends the byte c to the buffer.
// The returned error is always nil, but is included
// to match bufio.Writer's WriteByte.
func (b *Buffer) WriteByte(c byte) os.Error {
	b.oneByte[0] = c;
	b.Write(&b.oneByte);
	return nil;
}

// Read reads the next len(p) bytes from the buffer or until the buffer
// is drained.  The return value n is the number of bytes read.  If the
// buffer has no data to return, err is os.EOF even if len(p) is zero;
// otherwise it is nil.
func (b *Buffer) Read(p []byte) (n int, err os.Error) {
	if b.off >= len(b.buf) {
		// Buffer is empty, reset to recover space.
		b.Truncate(0);
		return 0, os.EOF;
	}
	m := b.Len();
	n = len(p);

	if n > m {
		// more bytes requested than available
		n = m
	}

	copy(p, b.buf[b.off:b.off+n]);
	b.off += n;
	return n, err;
}

// ReadByte reads and returns the next byte from the buffer.
// If no byte is available, it returns error os.EOF.
func (b *Buffer) ReadByte() (c byte, err os.Error) {
	if b.off >= len(b.buf) {
		// Buffer is empty, reset to recover space.
		b.Truncate(0);
		return 0, os.EOF;
	}
	c = b.buf[b.off];
	b.off++;
	return c, nil;
}

// NewBuffer creates and initializes a new Buffer
// using buf as its initial contents.
func NewBuffer(buf []byte) *Buffer	{ return &Buffer{buf: buf} }

// NewBufferString creates and initializes a new Buffer
// using string s as its initial contents.
func NewBufferString(s string) *Buffer {
	buf := make([]byte, len(s));
	copyString(buf, 0, s);
	return &Buffer{buf: buf};
}
<|endoftext|>


<commit_before>package html // import "github.com/tdewolff/parse/html"

import "github.com/tdewolff/parse"

// Token is a single token unit with an attribute value (if given) and hash of the data.
type Token struct {
	TokenType
	Data    []byte
	AttrVal []byte
	Hash    Hash
}

// TokenBuffer is a buffer that allows for token look-ahead.
type TokenBuffer struct {
	l *Lexer

	buf []Token
	pos int
}

// NewTokenBuffer returns a new TokenBuffer.
func NewTokenBuffer(l *Lexer) *TokenBuffer {
	return &TokenBuffer{
		l:   l,
		buf: make([]Token, 0, 8),
	}
}

func (z *TokenBuffer) read(p []Token) int {
	for i := 0; i < len(p); i++ {
		tt, data := z.l.Next()
		if !z.l.IsEOF() {
			data = parse.Copy(data)
		}

		var attrVal []byte
		var hash Hash
		if tt == AttributeToken {
			attrVal = z.l.AttrVal()
			if !z.l.IsEOF() {
				attrVal = parse.Copy(attrVal)
			}
			hash = ToHash(data)
		} else if tt == StartTagToken || tt == EndTagToken {
			hash = ToHash(data)
		}
		p[i] = Token{tt, data, attrVal, hash}
		if tt == ErrorToken {
			return i + 1
		}
	}
	return len(p)
}

// Peek returns the ith element and possibly does an allocation.
// Peeking past an error will panic.
func (z *TokenBuffer) Peek(end int) *Token {
	end += z.pos
	if end >= len(z.buf) {
		c := cap(z.buf)
		d := len(z.buf) - z.pos
		var buf []Token
		if 2*d > c {
			buf = make([]Token, d, 2*c)
		} else {
			buf = z.buf[:d]
		}
		copy(buf, z.buf[z.pos:])

		n := z.read(buf[d:cap(buf)])
		end -= z.pos
		z.pos, z.buf = 0, buf[:d+n]
	}
	return &z.buf[end]
}

// Shift returns the first element and advances position.
func (z *TokenBuffer) Shift() *Token {
	t := z.Peek(0)
	z.pos++
	return t
}
<commit_msg>Struct copy performance improvement<commit_after>package html // import "github.com/tdewolff/parse/html"

import "github.com/tdewolff/parse"

// Token is a single token unit with an attribute value (if given) and hash of the data.
type Token struct {
	TokenType
	Data    []byte
	AttrVal []byte
	Hash    Hash
}

// TokenBuffer is a buffer that allows for token look-ahead.
type TokenBuffer struct {
	l *Lexer

	buf []Token
	pos int
}

// NewTokenBuffer returns a new TokenBuffer.
func NewTokenBuffer(l *Lexer) *TokenBuffer {
	return &TokenBuffer{
		l:   l,
		buf: make([]Token, 0, 8),
	}
}

func (z *TokenBuffer) read(p []Token) int {
	for i := 0; i < len(p); i++ {
		tt, data := z.l.Next()
		if !z.l.IsEOF() {
			data = parse.Copy(data)
		}

		var attrVal []byte
		var hash Hash
		if tt == AttributeToken {
			attrVal = z.l.AttrVal()
			if !z.l.IsEOF() {
				attrVal = parse.Copy(attrVal)
			}
			hash = ToHash(data)
		} else if tt == StartTagToken || tt == EndTagToken {
			hash = ToHash(data)
		}
		p[i].TokenType = tt
		p[i].Data = data
		p[i].AttrVal = attrVal
		p[i].Hash = hash
		if tt == ErrorToken {
			return i + 1
		}
	}
	return len(p)
}

// Peek returns the ith element and possibly does an allocation.
// Peeking past an error will panic.
func (z *TokenBuffer) Peek(end int) *Token {
	end += z.pos
	if end >= len(z.buf) {
		c := cap(z.buf)
		d := len(z.buf) - z.pos
		var buf []Token
		if 2*d > c {
			buf = make([]Token, d, 2*c)
		} else {
			buf = z.buf[:d]
		}
		copy(buf, z.buf[z.pos:])

		n := z.read(buf[d:cap(buf)])
		end -= z.pos
		z.pos, z.buf = 0, buf[:d+n]
	}
	return &z.buf[end]
}

// Shift returns the first element and advances position.
func (z *TokenBuffer) Shift() *Token {
	t := z.Peek(0)
	z.pos++
	return t
}
<|endoftext|>


<commit_before>// Copyright 2011 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 http provides HTTP client and server implementations.

Get, Head, Post, and PostForm make HTTP requests:

	resp, err := http.Get("http://example.com/")
	...
	resp, err := http.Post("http://example.com/upload", "image/jpeg", &buf)
	...
	resp, err := http.PostForm("http://example.com/form",
 		url.Values{"key": {"Value"}, "id": {"123"}})

The client must close the response body when finished with it:

	resp, err := http.Get("http://example.com/")
	if err != nil {
		// handle error
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	// ...

For control over HTTP client headers, redirect policy, and other
settings, create a Client:

	client := &http.Client{
		CheckRedirect: redirectPolicyFunc,
	}

	resp, err := client.Get("http://example.com")
	// ...

	req, err := http.NewRequest("GET", "http://example.com", nil)
	// ...
	req.Header.Add("If-None-Match", `W/"wyzzy"`)
	resp, err := client.Do(req)
	// ...

For control over proxies, TLS configuration, keep-alives,
compression, and other settings, create a Transport:

	tr := &http.Transport{
		TLSClientConfig:    &tls.Config{RootCAs: pool},
		DisableCompression: true,
	}
	client := &http.Client{Transport: tr}
	resp, err := client.Get("https://example.com")

Clients and Transports are safe for concurrent use by multiple
goroutines and for efficiency should only be created once and re-used.

ListenAndServe starts an HTTP server with a given address and handler.
The handler is usually nil, which means to use DefaultServeMux.
Handle and HandleFunc add handlers to DefaultServeMux:

	http.Handle("/foo", fooHandler)

	http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.RawPath))
	})

	log.Fatal(http.ListenAndServe(":8080", nil))

More control over the server's behavior is available by creating a
custom Server:

	s := &http.Server{
		Addr:           ":8080",
		Handler:        myHandler,
		ReadTimeout:    10 * time.Second,
		WriteTimeout:   10 * time.Second,
		MaxHeaderBytes: 1 << 20,
	}
	log.Fatal(s.ListenAndServe())
*/
package http
<commit_msg>net/http: remove an errant space<commit_after>// Copyright 2011 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 http provides HTTP client and server implementations.

Get, Head, Post, and PostForm make HTTP requests:

	resp, err := http.Get("http://example.com/")
	...
	resp, err := http.Post("http://example.com/upload", "image/jpeg", &buf)
	...
	resp, err := http.PostForm("http://example.com/form",
		url.Values{"key": {"Value"}, "id": {"123"}})

The client must close the response body when finished with it:

	resp, err := http.Get("http://example.com/")
	if err != nil {
		// handle error
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	// ...

For control over HTTP client headers, redirect policy, and other
settings, create a Client:

	client := &http.Client{
		CheckRedirect: redirectPolicyFunc,
	}

	resp, err := client.Get("http://example.com")
	// ...

	req, err := http.NewRequest("GET", "http://example.com", nil)
	// ...
	req.Header.Add("If-None-Match", `W/"wyzzy"`)
	resp, err := client.Do(req)
	// ...

For control over proxies, TLS configuration, keep-alives,
compression, and other settings, create a Transport:

	tr := &http.Transport{
		TLSClientConfig:    &tls.Config{RootCAs: pool},
		DisableCompression: true,
	}
	client := &http.Client{Transport: tr}
	resp, err := client.Get("https://example.com")

Clients and Transports are safe for concurrent use by multiple
goroutines and for efficiency should only be created once and re-used.

ListenAndServe starts an HTTP server with a given address and handler.
The handler is usually nil, which means to use DefaultServeMux.
Handle and HandleFunc add handlers to DefaultServeMux:

	http.Handle("/foo", fooHandler)

	http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.RawPath))
	})

	log.Fatal(http.ListenAndServe(":8080", nil))

More control over the server's behavior is available by creating a
custom Server:

	s := &http.Server{
		Addr:           ":8080",
		Handler:        myHandler,
		ReadTimeout:    10 * time.Second,
		WriteTimeout:   10 * time.Second,
		MaxHeaderBytes: 1 << 20,
	}
	log.Fatal(s.ListenAndServe())
*/
package http
<|endoftext|>


<commit_before>// Copyright 2009 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 net

import (
	"io"
	"io/ioutil"
	"os"
	"runtime"
	"testing"
	"time"
)

func TestShutdown(t *testing.T) {
	if runtime.GOOS == "plan9" {
		t.Logf("skipping test on %q", runtime.GOOS)
		return
	}
	ln, err := Listen("tcp", "127.0.0.1:0")
	if err != nil {
		if ln, err = Listen("tcp6", "[::1]:0"); err != nil {
			t.Fatalf("ListenTCP on :0: %v", err)
		}
	}

	go func() {
		c, err := ln.Accept()
		if err != nil {
			t.Fatalf("Accept: %v", err)
		}
		var buf [10]byte
		n, err := c.Read(buf[:])
		if n != 0 || err != io.EOF {
			t.Fatalf("server Read = %d, %v; want 0, io.EOF", n, err)
		}
		c.Write([]byte("response"))
		c.Close()
	}()

	c, err := Dial("tcp", ln.Addr().String())
	if err != nil {
		t.Fatalf("Dial: %v", err)
	}
	defer c.Close()

	err = c.(*TCPConn).CloseWrite()
	if err != nil {
		t.Fatalf("CloseWrite: %v", err)
	}
	var buf [10]byte
	n, err := c.Read(buf[:])
	if err != nil {
		t.Fatalf("client Read: %d, %v", n, err)
	}
	got := string(buf[:n])
	if got != "response" {
		t.Errorf("read = %q, want \"response\"", got)
	}
}

func TestShutdownUnix(t *testing.T) {
	if runtime.GOOS == "plan9" {
		t.Logf("skipping test on %q", runtime.GOOS)
		return
	}
	f, err := ioutil.TempFile("", "go_net_unixtest")
	if err != nil {
		t.Fatalf("TempFile: %s", err)
	}
	f.Close()
	tmpname := f.Name()
	os.Remove(tmpname)
	ln, err := Listen("unix", tmpname)
	if err != nil {
		t.Fatalf("ListenUnix on %s: %s", tmpname, err)
	}
	defer os.Remove(tmpname)

	go func() {
		c, err := ln.Accept()
		if err != nil {
			t.Fatalf("Accept: %v", err)
		}
		var buf [10]byte
		n, err := c.Read(buf[:])
		if n != 0 || err != io.EOF {
			t.Fatalf("server Read = %d, %v; want 0, io.EOF", n, err)
		}
		c.Write([]byte("response"))
		c.Close()
	}()

	c, err := Dial("unix", tmpname)
	if err != nil {
		t.Fatalf("Dial: %v", err)
	}
	defer c.Close()

	err = c.(*UnixConn).CloseWrite()
	if err != nil {
		t.Fatalf("CloseWrite: %v", err)
	}
	var buf [10]byte
	n, err := c.Read(buf[:])
	if err != nil {
		t.Fatalf("client Read: %d, %v", n, err)
	}
	got := string(buf[:n])
	if got != "response" {
		t.Errorf("read = %q, want \"response\"", got)
	}
}

func TestTCPListenClose(t *testing.T) {
	ln, err := Listen("tcp", "127.0.0.1:0")
	if err != nil {
		t.Fatalf("Listen failed: %v", err)
	}

	done := make(chan bool, 1)
	go func() {
		time.Sleep(100 * time.Millisecond)
		ln.Close()
	}()
	go func() {
		c, err := ln.Accept()
		if err == nil {
			c.Close()
			t.Error("Accept succeeded")
		} else {
			t.Logf("Accept timeout error: %s (any error is fine)", err)
		}
		done <- true
	}()
	select {
	case <-done:
	case <-time.After(2 * time.Second):
		t.Fatal("timeout waiting for TCP close")
	}
}

func TestUDPListenClose(t *testing.T) {
	ln, err := ListenPacket("udp", "127.0.0.1:0")
	if err != nil {
		t.Fatalf("Listen failed: %v", err)
	}

	buf := make([]byte, 1000)
	done := make(chan bool, 1)
	go func() {
		time.Sleep(100 * time.Millisecond)
		ln.Close()
	}()
	go func() {
		_, _, err = ln.ReadFrom(buf)
		if err == nil {
			t.Error("ReadFrom succeeded")
		} else {
			t.Logf("ReadFrom timeout error: %s (any error is fine)", err)
		}
		done <- true
	}()
	select {
	case <-done:
	case <-time.After(2 * time.Second):
		t.Fatal("timeout waiting for UDP close")
	}
}
<commit_msg>net: skip UnixShutdown test on windows<commit_after>// Copyright 2009 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 net

import (
	"io"
	"io/ioutil"
	"os"
	"runtime"
	"testing"
	"time"
)

func TestShutdown(t *testing.T) {
	if runtime.GOOS == "plan9" {
		t.Logf("skipping test on %q", runtime.GOOS)
		return
	}
	ln, err := Listen("tcp", "127.0.0.1:0")
	if err != nil {
		if ln, err = Listen("tcp6", "[::1]:0"); err != nil {
			t.Fatalf("ListenTCP on :0: %v", err)
		}
	}

	go func() {
		c, err := ln.Accept()
		if err != nil {
			t.Fatalf("Accept: %v", err)
		}
		var buf [10]byte
		n, err := c.Read(buf[:])
		if n != 0 || err != io.EOF {
			t.Fatalf("server Read = %d, %v; want 0, io.EOF", n, err)
		}
		c.Write([]byte("response"))
		c.Close()
	}()

	c, err := Dial("tcp", ln.Addr().String())
	if err != nil {
		t.Fatalf("Dial: %v", err)
	}
	defer c.Close()

	err = c.(*TCPConn).CloseWrite()
	if err != nil {
		t.Fatalf("CloseWrite: %v", err)
	}
	var buf [10]byte
	n, err := c.Read(buf[:])
	if err != nil {
		t.Fatalf("client Read: %d, %v", n, err)
	}
	got := string(buf[:n])
	if got != "response" {
		t.Errorf("read = %q, want \"response\"", got)
	}
}

func TestShutdownUnix(t *testing.T) {
	switch runtime.GOOS {
	case "windows", "plan9":
		t.Logf("skipping test on %q", runtime.GOOS)
		return
	}
	f, err := ioutil.TempFile("", "go_net_unixtest")
	if err != nil {
		t.Fatalf("TempFile: %s", err)
	}
	f.Close()
	tmpname := f.Name()
	os.Remove(tmpname)
	ln, err := Listen("unix", tmpname)
	if err != nil {
		t.Fatalf("ListenUnix on %s: %s", tmpname, err)
	}
	defer os.Remove(tmpname)

	go func() {
		c, err := ln.Accept()
		if err != nil {
			t.Fatalf("Accept: %v", err)
		}
		var buf [10]byte
		n, err := c.Read(buf[:])
		if n != 0 || err != io.EOF {
			t.Fatalf("server Read = %d, %v; want 0, io.EOF", n, err)
		}
		c.Write([]byte("response"))
		c.Close()
	}()

	c, err := Dial("unix", tmpname)
	if err != nil {
		t.Fatalf("Dial: %v", err)
	}
	defer c.Close()

	err = c.(*UnixConn).CloseWrite()
	if err != nil {
		t.Fatalf("CloseWrite: %v", err)
	}
	var buf [10]byte
	n, err := c.Read(buf[:])
	if err != nil {
		t.Fatalf("client Read: %d, %v", n, err)
	}
	got := string(buf[:n])
	if got != "response" {
		t.Errorf("read = %q, want \"response\"", got)
	}
}

func TestTCPListenClose(t *testing.T) {
	ln, err := Listen("tcp", "127.0.0.1:0")
	if err != nil {
		t.Fatalf("Listen failed: %v", err)
	}

	done := make(chan bool, 1)
	go func() {
		time.Sleep(100 * time.Millisecond)
		ln.Close()
	}()
	go func() {
		c, err := ln.Accept()
		if err == nil {
			c.Close()
			t.Error("Accept succeeded")
		} else {
			t.Logf("Accept timeout error: %s (any error is fine)", err)
		}
		done <- true
	}()
	select {
	case <-done:
	case <-time.After(2 * time.Second):
		t.Fatal("timeout waiting for TCP close")
	}
}

func TestUDPListenClose(t *testing.T) {
	ln, err := ListenPacket("udp", "127.0.0.1:0")
	if err != nil {
		t.Fatalf("Listen failed: %v", err)
	}

	buf := make([]byte, 1000)
	done := make(chan bool, 1)
	go func() {
		time.Sleep(100 * time.Millisecond)
		ln.Close()
	}()
	go func() {
		_, _, err = ln.ReadFrom(buf)
		if err == nil {
			t.Error("ReadFrom succeeded")
		} else {
			t.Logf("ReadFrom timeout error: %s (any error is fine)", err)
		}
		done <- true
	}()
	select {
	case <-done:
	case <-time.After(2 * time.Second):
		t.Fatal("timeout waiting for UDP close")
	}
}
<|endoftext|>


<commit_before>package epgc

import (
	"database/sql"
	"log"
	"time"
)

// Phone - struct for phone
type Phone struct {
	ID        int64     `sql:"id" json:"id"`
	CompanyID int64     `sql:"company_id, pk, null" json:"company-id"`
	PeopleID  int64     `sql:"people_id, pk, null" json:"people-id"`
	Phone     int64     `sql:"phone, null" json:"phone"`
	Fax       bool      `sql:"fax, null" json:"fax"`
	CreatedAt time.Time `sql:"created_at" json:"created_at"`
	UpdatedAt time.Time `sql:"updated_at" json:"updated_at"`
}

func scanPhone(row *sql.Row) (Phone, error) {
	var (
		sID        sql.NullInt64
		sCompanyID sql.NullInt64
		sPeopleID  sql.NullInt64
		sPhone     sql.NullInt64
		sFax       sql.NullBool
		phone      Phone
	)
	err := row.Scan(&sID, &sCompanyID, &sPeopleID, &sPhone, &sFax)
	if err != nil {
		log.Println("scanPhone row.Scan ", err)
		return phone, err
	}
	phone.ID = n2i(sID)
	phone.CompanyID = n2i(sCompanyID)
	phone.PeopleID = n2i(sPeopleID)
	phone.Phone = n2i(sPhone)
	phone.Fax = n2b(sFax)
	return phone, nil
}

func scanPhones(rows *sql.Rows, opt string) ([]Phone, error) {
	var phones []Phone
	for rows.Next() {
		var (
			sID        sql.NullInt64
			sCompanyID sql.NullInt64
			sPeopleID  sql.NullInt64
			sPhone     sql.NullInt64
			sFax       sql.NullBool
			phone      Phone
		)
		switch opt {
		case "list":
			err := rows.Scan(&sID, &sCompanyID, &sPeopleID, &sPhone, &sFax)
			if err != nil {
				log.Println("scanPhones rows.Scan list ", err)
				return phones, err
			}
			phone.CompanyID = n2i(sCompanyID)
			phone.PeopleID = n2i(sPeopleID)
			phone.Fax = n2b(sFax)
		case "short":
			err := rows.Scan(&sID, &sPhone)
			if err != nil {
				log.Println("scanPhones rows.Scan short ", err)
				return phones, err
			}
		}
		phone.ID = n2i(sID)
		phone.Phone = n2i(sPhone)
		phones = append(phones, phone)
	}
	err := rows.Err()
	if err != nil {
		log.Println("scanPhones rows.Err ", err)
	}
	return phones, err
}

// GetPhone - get one phone by id
func (e *Edb) GetPhone(id int64) (Phone, error) {
	if id == 0 {
		return Phone{}, nil
	}
	stmt, err := e.db.Prepare("SELECT id, company_id, people_id, phone, fax FROM phones WHERE id = $1")
	if err != nil {
		log.Println("GetPhone e.db.Prepare", err)
		return Phone{}, err
	}
	row := stmt.QueryRow(id)
	phone, err := scanPhone(row)
	return phone, nil
}

// GetPhoneList - get all phones for list
func (e *Edb) GetPhoneList() ([]Phone, error) {
	rows, err := e.db.Query("SELECT id, company_id, people_id, phone, fax FROM phones ORDER BY phone ASC")
	if err != nil {
		log.Println("GetPhoneList e.db.Query ", err)
		return []Phone{}, err
	}
	phones, err := scanPhones(rows, "list")
	return phones, err
}

// GetCompanyPhones - get all phones by company id
func (e *Edb) GetCompanyPhones(id int64, fax bool) ([]Phone, error) {
	if id == 0 {
		return []Phone{}, nil
	}
	rows, err := e.db.Query("SELECT id, phone FROM phones ORDER BY phone ASC WHERE company_id = $1 AND fax = $2", id, fax)
	if err != nil {
		log.Println("GetCompanyPhones e.db.Query ", err)
		return []Phone{}, err
	}
	phones, err := scanPhones(rows, "short")
	return phones, err
}

// GetPeoplePhones - get all phones by people id
func (e *Edb) GetPeoplePhones(id int64, fax bool) ([]Phone, error) {
	if id == 0 {
		return []Phone{}, nil
	}
	rows, err := e.db.Query("SELECT id, phone FROM phones ORDER BY phone ASC WHERE people_id = $1 AND fax = $2", id, fax)
	if err != nil {
		log.Println("GetPeoplePhones e.db.Query ", err)
		return []Phone{}, err
	}
	phones, err := scanPhones(rows, "short")
	return phones, err
}

// GetCompanyPhonesAll - get all faxes or phones by company id and isfax
func (e *Edb) GetCompanyPhonesAll(id int64, fax bool) ([]Phone, error) {
	if id == 0 {
		return []Phone{}, nil
	}
	rows, err := e.db.Query("SELECT id, phone FROM phones ORDER BY phone ASC WHERE company_id = $1 and fax = $2", id, fax)
	if err != nil {
		log.Println("GetCompanyPhonesAll e.db.Query ", err)
		return []Phone{}, nil
	}
	phones, err := scanPhones(rows, "short")
	return phones, err
}

// GetPeoplePhonesAll - get all phones and faxes by people id
func (e *Edb) GetPeoplePhonesAll(id int64, fax bool) ([]Phone, error) {
	if id == 0 {
		return []Phone{}, nil
	}
	rows, err := e.db.Query("SELECT id, phone FROM phones ORDER BY phone ASC WHERE people_id = $1 and fax = $2", id, fax)
	if err != nil {
		log.Println("GetPeoplePhonesAll e.db.Query ", err)
		return []Phone{}, nil
	}
	phones, err := scanPhones(rows, "short")
	return phones, err
}

// CreatePhone - create new phone
func (e *Edb) CreatePhone(phone Phone) (int64, error) {
	stmt, err := e.db.Prepare(`INSERT INTO phones(company_id, people_id, phone, fax, created_at) VALUES($1, $2, $3, $4, now()) RETURNING id`)
	if err != nil {
		log.Println("CreatePhone e.db.Prepare ", err)
		return 0, err
	}
	err = stmt.QueryRow(i2n(phone.CompanyID), i2n(phone.PeopleID), i2n(phone.Phone), phone.Fax).Scan(&phone.ID)
	if err != nil {
		log.Println("CreatePhone db.QueryRow ", err)
		return 0, err
	}
	return phone.ID, nil
}

// CreateCompanyPhones - create new phones to company
func (e *Edb) CreateCompanyPhones(company Company, fax bool) error {
	err := e.CleanCompanyPhones(company, fax)
	if err != nil {
		log.Println("CreateCompanyPhones CleanCompanyPhones ", err)
		return err
	}
	for _, value := range company.Phones {
		var id int64
		phone := Phone{}
		err = e.db.QueryRow("SELECT id FROM phones WHERE company_id = $1 and phone = $2 and fax = $3 RETURNING id", company.ID, value.Phone, fax).Scan(&id)
		if phone.ID == 0 {
			value.CompanyID = company.ID
			value.Fax = fax
			_, err = e.CreatePhone(value)
			if err != nil {
				log.Println("CreateCompanyPhones CreatePhone ", err)
				return err
			}
		}
	}
	return nil
}

// CreatePeoplePhones - create new phones to people
func (e *Edb) CreatePeoplePhones(people People, fax bool) error {
	err := e.CleanPeoplePhones(people, fax)
	if err != nil {
		log.Println("CreatePeoplePhones CleanPeoplePhones ", err)
		return err
	}
	var allPhones []Phone
	if fax {
		allPhones = people.Faxes
	} else {
		allPhones = people.Phones
	}
	for _, value := range allPhones {
		phone := Phone{}
		err = e.db.QueryRow("SELECT id FROM phones WHERE people_id = $1 and phone = $2 and fax = $3 RETURNING id", people.ID, value.Phone, fax).Scan(&phone.ID)
		if phone.ID == 0 {
			value.PeopleID = people.ID
			value.Fax = fax
			_, err = e.CreatePhone(value)
			if err != nil {
				log.Println("CreatePeoplePhones CreatePhone ", err)
				return err
			}
		}
	}
	return nil
}

// CleanCompanyPhones - delete all unnecessary phones by company id
func (e *Edb) CleanCompanyPhones(company Company, fax bool) error {
	phones := []int64{}
	for _, value := range company.Phones {
		phones = append(phones, value.Phone)
	}
	if len(phones) == 0 {
		_, err := e.db.Exec("DELETE FROM phones WHERE company_id = $1 and fax = $2", company.ID, fax)
		if err != nil {
			log.Println("CleanCompanyPhones e.db.Exec ", err)
			return err
		}
	} else {
		rows, err := e.db.Query("SELECT id, phone FROM phones WHERE company_id = $1 and fax = $2", company.ID, fax)
		if err != nil {
			log.Println("CleanCompanyPhones e.db.Query ", err)
			return err
		}
		companyPhones, err := scanPhones(rows, "short")
		if err != nil {
			log.Println("CleanCompanyPhones scanPhones ", err)
			return err
		}
		for _, value := range companyPhones {
			if int64InSlice(value.Phone, phones) == false {
				_, err = e.db.Exec("DELETE FROM phones WHERE company_id = $1 and phone = $2 and fax = $3", company.ID, value.Phone, fax)
				if err != nil {
					log.Println("CleanCompanyPhones e.db.Exec ", err)
					return err
				}
			}
		}
	}
	return nil
}

// CleanPeoplePhones - delete all unnecessary phones by people id
func (e *Edb) CleanPeoplePhones(people People, fax bool) error {
	phones := []int64{}
	for _, value := range people.Phones {
		phones = append(phones, value.Phone)
	}
	if len(phones) == 0 {
		_, err := e.db.Exec("DELETE FROM phones WHERE people_id = $1 and fax = $2", people.ID, fax)
		if err != nil {
			log.Println("CleanPeoplePhones e.db.Exec ", err)
			return err
		}
	} else {
		rows, err := e.db.Query("SELECT id, phone FROM phones WHERE people_id = $1 and fax = $2", people.ID, fax)
		if err != nil {
			log.Println("CleanPeoplePhones e.db.Query ", err)
			return err
		}
		peoplePhones, err := scanPhones(rows, "short")
		if err != nil {
			log.Println("CleanPeoplePhones scanPhones ", err)
			return err
		}
		for _, value := range peoplePhones {
			if int64InSlice(value.Phone, phones) == false {
				_, err = e.db.Exec("DELETE FROM phones WHERE people_id = $1 and phone = $2 and fax = $3", people.ID, value.Phone, fax)
				if err != nil {
					log.Println("CleanPeoplePhones e.db.Exec ", err)
					return err
				}
			}
		}
	}
	return nil
}

// DeleteAllCompanyPhones - delete all phones and faxes by company id
func (e *Edb) DeleteAllCompanyPhones(id int64) error {
	if id == 0 {
		return nil
	}
	_, err := e.db.Exec("DELETE FROM phones WHERE company_id = ?", id)
	if err != nil {
		log.Println("DeleteAllCompanyPhones e.db.Exec ", err)
	}
	return err
}

// DeleteAllPeoplePhones - delete all phones and faxes by people id
func (e *Edb) DeleteAllPeoplePhones(id int64) error {
	if id == 0 {
		return nil
	}
	_, err := e.db.Exec("DELETE FROM phones WHERE people_id = ?", id)
	if err != nil {
		log.Println("DeleteAllPeoplePhones e.db.Exec ", err)
	}
	return err
}

func (e *Edb) phoneCreateTable() error {
	str := `CREATE TABLE IF NOT EXISTS phones (id bigserial primary key, people_id bigint, company_id bigint, phone bigint, fax bool NOT NULL DEFAULT false, created_at TIMESTAMP without time zone, updated_at TIMESTAMP without time zone)`
	_, err := e.db.Exec(str)
	if err != nil {
		log.Println("phoneCreateTable e.db.Exec ", err)
	}
	return err
}
<commit_msg>fix sql, delete fax<commit_after>package epgc

import (
	"database/sql"
	"log"
	"time"
)

// Phone - struct for phone
type Phone struct {
	ID        int64     `sql:"id" json:"id"`
	CompanyID int64     `sql:"company_id, pk, null" json:"company-id"`
	PeopleID  int64     `sql:"people_id, pk, null" json:"people-id"`
	Phone     int64     `sql:"phone, null" json:"phone"`
	Fax       bool      `sql:"fax, null" json:"fax"`
	CreatedAt time.Time `sql:"created_at" json:"created_at"`
	UpdatedAt time.Time `sql:"updated_at" json:"updated_at"`
}

func scanPhone(row *sql.Row) (Phone, error) {
	var (
		sID        sql.NullInt64
		sCompanyID sql.NullInt64
		sPeopleID  sql.NullInt64
		sPhone     sql.NullInt64
		sFax       sql.NullBool
		phone      Phone
	)
	err := row.Scan(&sID, &sCompanyID, &sPeopleID, &sPhone, &sFax)
	if err != nil {
		log.Println("scanPhone row.Scan ", err)
		return phone, err
	}
	phone.ID = n2i(sID)
	phone.CompanyID = n2i(sCompanyID)
	phone.PeopleID = n2i(sPeopleID)
	phone.Phone = n2i(sPhone)
	phone.Fax = n2b(sFax)
	return phone, nil
}

func scanPhones(rows *sql.Rows, opt string) ([]Phone, error) {
	var phones []Phone
	for rows.Next() {
		var (
			sID        sql.NullInt64
			sCompanyID sql.NullInt64
			sPeopleID  sql.NullInt64
			sPhone     sql.NullInt64
			sFax       sql.NullBool
			phone      Phone
		)
		switch opt {
		case "list":
			err := rows.Scan(&sID, &sCompanyID, &sPeopleID, &sPhone, &sFax)
			if err != nil {
				log.Println("scanPhones rows.Scan list ", err)
				return phones, err
			}
			phone.CompanyID = n2i(sCompanyID)
			phone.PeopleID = n2i(sPeopleID)
			phone.Fax = n2b(sFax)
		case "short":
			err := rows.Scan(&sID, &sPhone)
			if err != nil {
				log.Println("scanPhones rows.Scan short ", err)
				return phones, err
			}
		}
		phone.ID = n2i(sID)
		phone.Phone = n2i(sPhone)
		phones = append(phones, phone)
	}
	err := rows.Err()
	if err != nil {
		log.Println("scanPhones rows.Err ", err)
	}
	return phones, err
}

// GetPhone - get one phone by id
func (e *Edb) GetPhone(id int64) (Phone, error) {
	if id == 0 {
		return Phone{}, nil
	}
	stmt, err := e.db.Prepare(`SELECT id, company_id, people_id, phone, fax FROM phones WHERE id = $1`)
	if err != nil {
		log.Println("GetPhone e.db.Prepare", err)
		return Phone{}, err
	}
	row := stmt.QueryRow(id)
	phone, err := scanPhone(row)
	return phone, nil
}

// GetPhoneList - get all phones for list
func (e *Edb) GetPhoneList() ([]Phone, error) {
	rows, err := e.db.Query(`SELECT id, company_id, people_id, phone, fax FROM phones ORDER BY phone ASC`)
	if err != nil {
		log.Println("GetPhoneList e.db.Query ", err)
		return []Phone{}, err
	}
	phones, err := scanPhones(rows, "list")
	return phones, err
}

// GetCompanyPhones - get all phones by company id
func (e *Edb) GetCompanyPhones(id int64, fax bool) ([]Phone, error) {
	if id == 0 {
		return []Phone{}, nil
	}
	rows, err := e.db.Query(`SELECT id, phone FROM phones WHERE company_id = $1 AND fax = $2 ORDER BY phone ASC`, id, fax)
	if err != nil {
		log.Println("GetCompanyPhones e.db.Query ", err)
		return []Phone{}, err
	}
	phones, err := scanPhones(rows, "short")
	return phones, err
}

// GetPeoplePhones - get all phones by people id
func (e *Edb) GetPeoplePhones(id int64, fax bool) ([]Phone, error) {
	if id == 0 {
		return []Phone{}, nil
	}
	rows, err := e.db.Query(`SELECT id, phone FROM phones ORDER BY phone ASC WHERE people_id = $1 AND fax = $2`, id, fax)
	if err != nil {
		log.Println("GetPeoplePhones e.db.Query ", err)
		return []Phone{}, err
	}
	phones, err := scanPhones(rows, "short")
	return phones, err
}

// GetCompanyPhonesAll - get all faxes or phones by company id and isfax
func (e *Edb) GetCompanyPhonesAll(id int64, fax bool) ([]Phone, error) {
	if id == 0 {
		return []Phone{}, nil
	}
	rows, err := e.db.Query(`SELECT id, phone FROM phones WHERE company_id = $1 and fax = $2 ORDER BY phone ASC`, id, fax)
	if err != nil {
		log.Println("GetCompanyPhonesAll e.db.Query ", err)
		return []Phone{}, nil
	}
	phones, err := scanPhones(rows, "short")
	return phones, err
}

// GetPeoplePhonesAll - get all phones and faxes by people id
func (e *Edb) GetPeoplePhonesAll(id int64, fax bool) ([]Phone, error) {
	if id == 0 {
		return []Phone{}, nil
	}
	rows, err := e.db.Query(`SELECT id, phone FROM phones WHERE people_id = $1 and fax = $2 ORDER BY phone ASC`, id, fax)
	if err != nil {
		log.Println("GetPeoplePhonesAll e.db.Query ", err)
		return []Phone{}, nil
	}
	phones, err := scanPhones(rows, "short")
	return phones, err
}

// CreatePhone - create new phone
func (e *Edb) CreatePhone(phone Phone) (int64, error) {
	stmt, err := e.db.Prepare(`INSERT INTO phones(company_id, people_id, phone, fax, created_at) VALUES($1, $2, $3, $4, now()) RETURNING id`)
	if err != nil {
		log.Println("CreatePhone e.db.Prepare ", err)
		return 0, err
	}
	err = stmt.QueryRow(i2n(phone.CompanyID), i2n(phone.PeopleID), i2n(phone.Phone), phone.Fax).Scan(&phone.ID)
	if err != nil {
		log.Println("CreatePhone db.QueryRow ", err)
		return 0, err
	}
	return phone.ID, nil
}

// CreateCompanyPhones - create new phones to company
func (e *Edb) CreateCompanyPhones(company Company, fax bool) error {
	err := e.CleanCompanyPhones(company, fax)
	if err != nil {
		log.Println("CreateCompanyPhones CleanCompanyPhones ", err)
		return err
	}
	for _, value := range company.Phones {
		var id int64
		phone := Phone{}
		err = e.db.QueryRow(`SELECT id FROM phones WHERE company_id = $1 and phone = $2 and fax = $3 RETURNING id`, company.ID, value.Phone, fax).Scan(&id)
		if phone.ID == 0 {
			value.CompanyID = company.ID
			value.Fax = fax
			_, err = e.CreatePhone(value)
			if err != nil {
				log.Println("CreateCompanyPhones CreatePhone ", err)
				return err
			}
		}
	}
	return nil
}

// CreatePeoplePhones - create new phones to people
func (e *Edb) CreatePeoplePhones(people People, fax bool) error {
	err := e.CleanPeoplePhones(people, fax)
	if err != nil {
		log.Println("CreatePeoplePhones CleanPeoplePhones ", err)
		return err
	}
	var allPhones []Phone
	if fax {
		allPhones = people.Faxes
	} else {
		allPhones = people.Phones
	}
	for _, value := range allPhones {
		phone := Phone{}
		err = e.db.QueryRow(`SELECT id FROM phones WHERE people_id = $1 and phone = $2 and fax = $3 RETURNING id`, people.ID, value.Phone, fax).Scan(&phone.ID)
		if phone.ID == 0 {
			value.PeopleID = people.ID
			value.Fax = fax
			_, err = e.CreatePhone(value)
			if err != nil {
				log.Println("CreatePeoplePhones CreatePhone ", err)
				return err
			}
		}
	}
	return nil
}

// CleanCompanyPhones - delete all unnecessary phones by company id
func (e *Edb) CleanCompanyPhones(company Company, fax bool) error {
	var (
		phones    []int64
		allPhones []Phone
	)
	if fax {
		allPhones = company.Faxes
	} else {
		allPhones = company.Phones
	}
	for _, value := range allPhones {
		phones = append(phones, value.Phone)
	}
	if len(phones) == 0 {
		_, err := e.db.Exec(`DELETE FROM phones WHERE company_id = $1 and fax = $2`, company.ID, fax)
		if err != nil {
			log.Println("CleanCompanyPhones e.db.Exec ", err)
			return err
		}
	} else {
		rows, err := e.db.Query(`SELECT id, phone FROM phones WHERE company_id = $1 and fax = $2`, company.ID, fax)
		if err != nil {
			log.Println("CleanCompanyPhones e.db.Query ", err)
			return err
		}
		companyPhones, err := scanPhones(rows, "short")
		if err != nil {
			log.Println("CleanCompanyPhones scanPhones ", err)
			return err
		}
		for _, value := range companyPhones {
			if int64InSlice(value.Phone, phones) == false {
				_, err = e.db.Exec(`DELETE FROM phones WHERE company_id = $1 and phone = $2 and fax = $3`, company.ID, value.Phone, fax)
				if err != nil {
					log.Println("CleanCompanyPhones e.db.Exec ", err)
					return err
				}
			}
		}
	}
	return nil
}

// CleanPeoplePhones - delete all unnecessary phones by people id
func (e *Edb) CleanPeoplePhones(people People, fax bool) error {
	var (
		phones    []int64
		allPhones []Phone
	)
	if fax {
		allPhones = people.Faxes
	} else {
		allPhones = people.Phones
	}
	for _, value := range allPhones {
		phones = append(phones, value.Phone)
	}
	if len(phones) == 0 {
		_, err := e.db.Exec(`DELETE FROM phones WHERE people_id = $1 and fax = $2`, people.ID, fax)
		if err != nil {
			log.Println("CleanPeoplePhones e.db.Exec ", err)
			return err
		}
	} else {
		rows, err := e.db.Query(`SELECT id, phone FROM phones WHERE people_id = $1 and fax = $2`, people.ID, fax)
		if err != nil {
			log.Println("CleanPeoplePhones e.db.Query ", err)
			return err
		}
		peoplePhones, err := scanPhones(rows, "short")
		if err != nil {
			log.Println("CleanPeoplePhones scanPhones ", err)
			return err
		}
		for _, value := range peoplePhones {
			if int64InSlice(value.Phone, phones) == false {
				_, err = e.db.Exec(`DELETE FROM phones WHERE people_id = $1 and phone = $2 and fax = $3`, people.ID, value.Phone, fax)
				if err != nil {
					log.Println("CleanPeoplePhones e.db.Exec ", err)
					return err
				}
			}
		}
	}
	return nil
}

// DeleteAllCompanyPhones - delete all phones and faxes by company id
func (e *Edb) DeleteAllCompanyPhones(id int64) error {
	if id == 0 {
		return nil
	}
	_, err := e.db.Exec(`DELETE FROM phones WHERE company_id = $1`, id)
	if err != nil {
		log.Println("DeleteAllCompanyPhones e.db.Exec ", id, err)
	}
	return err
}

// DeleteAllPeoplePhones - delete all phones and faxes by people id
func (e *Edb) DeleteAllPeoplePhones(id int64) error {
	if id == 0 {
		return nil
	}
	_, err := e.db.Exec(`DELETE FROM phones WHERE people_id = $1`, id)
	if err != nil {
		log.Println("DeleteAllPeoplePhones e.db.Exec ", id, err)
	}
	return err
}

func (e *Edb) phoneCreateTable() error {
	str := `CREATE TABLE IF NOT EXISTS phones (id bigserial primary key, people_id bigint, company_id bigint, phone bigint, fax bool NOT NULL DEFAULT false, created_at TIMESTAMP without time zone, updated_at TIMESTAMP without time zone)`
	_, err := e.db.Exec(str)
	if err != nil {
		log.Println("phoneCreateTable e.db.Exec ", err)
	}
	return err
}
<|endoftext|>


<commit_before>package picol

import (
	"errors"
	"fmt"
	"strings"
)

var (
	PICOL_RETURN   = errors.New("RETURN")
	PICOL_BREAK    = errors.New("BREAK")
	PICOL_CONTINUE = errors.New("CONTINUE")
)

type Var string
type CmdFunc func(i *Interp, argv []string, privdata interface{}) (string, error)
type Cmd struct {
	fn       CmdFunc
	privdata interface{}
}
type CallFrame struct {
	vars   map[string]Var
	parent *CallFrame
}
type Interp struct {
	level     int
	callframe *CallFrame
	commands  map[string]Cmd
}

func InitInterp() *Interp {
	return &Interp{
		level:     0,
		callframe: &CallFrame{vars: make(map[string]Var)},
		commands:  make(map[string]Cmd),
	}
}

func (i *Interp) Var(name string) (Var, bool) {
	v, ok := i.callframe.vars[name]
	return v, ok
}
func (i *Interp) SetVar(name, val string) {
	i.callframe.vars[name] = Var(val)
}

func (i *Interp) UnsetVar(name string) {
	delete(i.callframe.vars, name)
}

func (i *Interp) Command(name string) *Cmd {
	v, ok := i.commands[name]
	if !ok {
		return nil
	}
	return &v
}

func (i *Interp) RegisterCommand(name string, fn CmdFunc, privdata interface{}) error {
	c := i.Command(name)
	if c != nil {
		return fmt.Errorf("Command '%s' already defined", name)
	}

	i.commands[name] = Cmd{fn, privdata}
	return nil
}

/* EVAL! */
func (i *Interp) Eval(t string) (string, error) {
	p := InitParser(t)
	var result string
	var err error

	argv := []string{}

	for {
		prevtype := p.Type
		// XXX
		t = p.GetToken()
		if p.Type == PT_EOF {
			break
		}

		switch p.Type {
		case PT_VAR:
			v, ok := i.Var(t)
			if !ok {
				return "", fmt.Errorf("No such variable '%s'", t)
			}
			t = string(v)
		case PT_CMD:
			result, err = i.Eval(t)
			if err != nil {
				return result, err
			} else {
				t = result
			}
		case PT_ESC:
			// XXX: escape handling missing!
		case PT_SEP:
			prevtype = p.Type
			continue
		}

		// We have a complete command + args. Call it!
		if p.Type == PT_EOL {
			prevtype = p.Type
			if len(argv) != 0 {
				c := i.Command(argv[0])
				if c == nil {
					return "", fmt.Errorf("No such command '%s'", argv[0])
				}
				result, err = c.fn(i, argv, c.privdata)
				if err != nil {
					return result, err
				}
			}
			// Prepare for the next command
			argv = []string{}
			continue
		}

		// We have a new token, append to the previous or as new arg?
		if prevtype == PT_SEP || prevtype == PT_EOL {
			argv = append(argv, t)
		} else { // Interpolation
			argv[len(argv)-1] = strings.Join([]string{argv[len(argv)-1], t}, "")
		}
		prevtype = p.Type
	}
	return result, nil
}
<commit_msg>fix search variables<commit_after>package picol

import (
	"errors"
	"fmt"
	"strings"
)

var (
	PICOL_RETURN   = errors.New("RETURN")
	PICOL_BREAK    = errors.New("BREAK")
	PICOL_CONTINUE = errors.New("CONTINUE")
)

type Var string
type CmdFunc func(i *Interp, argv []string, privdata interface{}) (string, error)
type Cmd struct {
	fn       CmdFunc
	privdata interface{}
}
type CallFrame struct {
	vars   map[string]Var
	parent *CallFrame
}
type Interp struct {
	level     int
	callframe *CallFrame
	commands  map[string]Cmd
}

func InitInterp() *Interp {
	return &Interp{
		level:     0,
		callframe: &CallFrame{vars: make(map[string]Var)},
		commands:  make(map[string]Cmd),
	}
}

func (i *Interp) Var(name string) (Var, bool) {
	for frame := i.callframe; frame != nil; frame = frame.parent {
		v, ok := frame.vars[name]
		if ok {
			return v, ok
		}
	}
	return "", false
}
func (i *Interp) SetVar(name, val string) {
	i.callframe.vars[name] = Var(val)
}

func (i *Interp) UnsetVar(name string) {
	delete(i.callframe.vars, name)
}

func (i *Interp) Command(name string) *Cmd {
	v, ok := i.commands[name]
	if !ok {
		return nil
	}
	return &v
}

func (i *Interp) RegisterCommand(name string, fn CmdFunc, privdata interface{}) error {
	c := i.Command(name)
	if c != nil {
		return fmt.Errorf("Command '%s' already defined", name)
	}

	i.commands[name] = Cmd{fn, privdata}
	return nil
}

/* EVAL! */
func (i *Interp) Eval(t string) (string, error) {
	p := InitParser(t)
	var result string
	var err error

	argv := []string{}

	for {
		prevtype := p.Type
		// XXX
		t = p.GetToken()
		if p.Type == PT_EOF {
			break
		}

		switch p.Type {
		case PT_VAR:
			v, ok := i.Var(t)
			if !ok {
				return "", fmt.Errorf("No such variable '%s'", t)
			}
			t = string(v)
		case PT_CMD:
			result, err = i.Eval(t)
			if err != nil {
				return result, err
			} else {
				t = result
			}
		case PT_ESC:
			// XXX: escape handling missing!
		case PT_SEP:
			prevtype = p.Type
			continue
		}

		// We have a complete command + args. Call it!
		if p.Type == PT_EOL {
			prevtype = p.Type
			if len(argv) != 0 {
				c := i.Command(argv[0])
				if c == nil {
					return "", fmt.Errorf("No such command '%s'", argv[0])
				}
				result, err = c.fn(i, argv, c.privdata)
				if err != nil {
					return result, err
				}
			}
			// Prepare for the next command
			argv = []string{}
			continue
		}

		// We have a new token, append to the previous or as new arg?
		if prevtype == PT_SEP || prevtype == PT_EOL {
			argv = append(argv, t)
		} else { // Interpolation
			argv[len(argv)-1] = strings.Join([]string{argv[len(argv)-1], t}, "")
		}
		prevtype = p.Type
	}
	return result, nil
}
<|endoftext|>