<commit_before>package mdata

import (
	"github.com/grafana/metrictank/mdata/errors"
	"github.com/grafana/metrictank/schema"
)

// ReorderBuffer keeps a window of data during which it is ok to send data out of order.
// The reorder buffer itself is not thread safe because it is only used by AggMetric,
// which is thread safe, so there is no locking in the buffer.
//
// newest=0 may mean no points added yet, or newest point is at position 0.
// we use the Ts of points in the buffer to check for valid points. Ts == 0 means no point
// in particular newest.Ts == 0 means the buffer is empty
// the buffer is evenly spaced (points are `interval` apart) and may be sparsely populated
type ReorderBuffer struct {
	newest      uint32         // index of newest buffer entry
	interval    uint32         // metric interval
	buf         []schema.Point // the actual buffer holding the data
	allowUpdate bool           // whether or not to allow overwriting data points with same timestamps
}

func NewReorderBuffer(reorderWindow, interval uint32, allowUpdate bool) *ReorderBuffer {
	return &ReorderBuffer{
		interval:    interval,
		buf:         make([]schema.Point, reorderWindow),
		allowUpdate: allowUpdate,
	}
}

// Add adds the point if it falls within the window.
// it returns points that have been purged out of the buffer, as well as whether the add succeeded.
func (rob *ReorderBuffer) Add(ts uint32, val float64) (schema.Point, []schema.Point, error) {
	ts = AggBoundary(ts, rob.interval)

	newestTs := rob.buf[rob.newest].Ts
	// out of order and too old
	if newestTs != 0 && ts < newestTs && ts <= newestTs-(uint32(cap(rob.buf))*rob.interval) {
		return schema.Point{}, nil, errors.ErrMetricTooOld
	}

	var firstPoint schema.Point
	var res []schema.Point
	oldest := (rob.newest + 1) % uint32(cap(rob.buf))
	index := (ts / rob.interval) % uint32(cap(rob.buf))
	if ts == rob.buf[index].Ts {
		if rob.allowUpdate {
			rob.buf[index].Ts = ts
			rob.buf[index].Val = val
		} else {
			return schema.Point{}, nil, errors.ErrMetricNewValueForTimestamp
		}
	} else if ts > newestTs {
		flushCount := (ts - newestTs) / rob.interval
		if flushCount > uint32(cap(rob.buf)) {
			flushCount = uint32(cap(rob.buf))
		}

		if flushCount > 1 {
			res = make([]schema.Point, 0, flushCount-1)
		}
		for i := uint32(0); i < flushCount; i++ {
			if rob.buf[oldest].Ts != 0 {
				if firstPoint.Ts == 0 {
					firstPoint = rob.buf[oldest]
				} else {
					res = append(res, rob.buf[oldest])
				}
				rob.buf[oldest].Ts = 0
			}
			oldest = (oldest + 1) % uint32(cap(rob.buf))
		}
		rob.buf[index].Ts = ts
		rob.buf[index].Val = val
		rob.newest = index
	} else {
		metricsReordered.Inc()
		rob.buf[index].Ts = ts
		rob.buf[index].Val = val
	}

	return firstPoint, res, nil
}

// Get returns the points in the buffer
func (rob *ReorderBuffer) Get() []schema.Point {
	res := make([]schema.Point, 0, cap(rob.buf))
	oldest := (rob.newest + 1) % uint32(cap(rob.buf))

	for {
		if rob.buf[oldest].Ts != 0 {
			res = append(res, rob.buf[oldest])
		}
		if oldest == rob.newest {
			break
		}
		oldest = (oldest + 1) % uint32(cap(rob.buf))
	}

	return res
}

func (rob *ReorderBuffer) Reset() {
	for i := range rob.buf {
		rob.buf[i].Ts = 0
	}
	rob.newest = 0
}

func (rob *ReorderBuffer) Flush() []schema.Point {
	res := rob.Get()
	rob.Reset()

	return res
}

func (rob *ReorderBuffer) IsEmpty() bool {
	return rob.buf[rob.newest].Ts == 0
}
<commit_msg>Fix underflow when ROB time range > newestTs<commit_after>package mdata

import (
	"github.com/grafana/metrictank/mdata/errors"
	"github.com/grafana/metrictank/schema"
)

// ReorderBuffer keeps a window of data during which it is ok to send data out of order.
// The reorder buffer itself is not thread safe because it is only used by AggMetric,
// which is thread safe, so there is no locking in the buffer.
//
// newest=0 may mean no points added yet, or newest point is at position 0.
// we use the Ts of points in the buffer to check for valid points. Ts == 0 means no point
// in particular newest.Ts == 0 means the buffer is empty
// the buffer is evenly spaced (points are `interval` apart) and may be sparsely populated
type ReorderBuffer struct {
	newest      uint32         // index of newest buffer entry
	interval    uint32         // metric interval
	buf         []schema.Point // the actual buffer holding the data
	allowUpdate bool           // whether or not to allow overwriting data points with same timestamps
}

func NewReorderBuffer(reorderWindow, interval uint32, allowUpdate bool) *ReorderBuffer {
	return &ReorderBuffer{
		interval:    interval,
		buf:         make([]schema.Point, reorderWindow),
		allowUpdate: allowUpdate,
	}
}

// Add adds the point if it falls within the window.
// it returns points that have been purged out of the buffer, as well as whether the add succeeded.
func (rob *ReorderBuffer) Add(ts uint32, val float64) (schema.Point, []schema.Point, error) {
	ts = AggBoundary(ts, rob.interval)

	newestTs := rob.buf[rob.newest].Ts
	// out of order and too old
	if newestTs != 0 && ts < newestTs && newestTs-ts >= (uint32(cap(rob.buf))*rob.interval) {
		return schema.Point{}, nil, errors.ErrMetricTooOld
	}

	var firstPoint schema.Point
	var res []schema.Point
	oldest := (rob.newest + 1) % uint32(cap(rob.buf))
	index := (ts / rob.interval) % uint32(cap(rob.buf))
	if ts == rob.buf[index].Ts {
		if rob.allowUpdate {
			rob.buf[index].Ts = ts
			rob.buf[index].Val = val
		} else {
			return schema.Point{}, nil, errors.ErrMetricNewValueForTimestamp
		}
	} else if ts > newestTs {
		flushCount := (ts - newestTs) / rob.interval
		if flushCount > uint32(cap(rob.buf)) {
			flushCount = uint32(cap(rob.buf))
		}

		if flushCount > 1 {
			res = make([]schema.Point, 0, flushCount-1)
		}
		for i := uint32(0); i < flushCount; i++ {
			if rob.buf[oldest].Ts != 0 {
				if firstPoint.Ts == 0 {
					firstPoint = rob.buf[oldest]
				} else {
					res = append(res, rob.buf[oldest])
				}
				rob.buf[oldest].Ts = 0
			}
			oldest = (oldest + 1) % uint32(cap(rob.buf))
		}
		rob.buf[index].Ts = ts
		rob.buf[index].Val = val
		rob.newest = index
	} else {
		metricsReordered.Inc()
		rob.buf[index].Ts = ts
		rob.buf[index].Val = val
	}

	return firstPoint, res, nil
}

// Get returns the points in the buffer
func (rob *ReorderBuffer) Get() []schema.Point {
	res := make([]schema.Point, 0, cap(rob.buf))
	oldest := (rob.newest + 1) % uint32(cap(rob.buf))

	for {
		if rob.buf[oldest].Ts != 0 {
			res = append(res, rob.buf[oldest])
		}
		if oldest == rob.newest {
			break
		}
		oldest = (oldest + 1) % uint32(cap(rob.buf))
	}

	return res
}

func (rob *ReorderBuffer) Reset() {
	for i := range rob.buf {
		rob.buf[i].Ts = 0
	}
	rob.newest = 0
}

func (rob *ReorderBuffer) Flush() []schema.Point {
	res := rob.Get()
	rob.Reset()

	return res
}

func (rob *ReorderBuffer) IsEmpty() bool {
	return rob.buf[rob.newest].Ts == 0
}
<|endoftext|>


<commit_before>package approvals

import (
	"bytes"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"io"
	"os"
	"reflect"
	"regexp"
	"strings"

	"github.com/approvals/go-approval-tests/reporters"
	"github.com/approvals/go-approval-tests/utils"
)

var (
	defaultReporter            = reporters.NewDiffReporter()
	defaultFrontLoadedReporter = reporters.NewFrontLoadedReporter()
	defaultFolder              = ""
)

// Failable is an interface wrapper around testing.T
type Failable interface {
	Fail()
	Fatal(args ...interface{})
	Fatalf(format string, args ...interface{})
	Name() string
	Log(args ...interface{})
	Logf(format string, args ...interface{})
	Helper()
}

// VerifyWithExtension Example:
//   VerifyWithExtension(t, strings.NewReader("Hello"), ".json")
// Deprecated: Please use Verify with the Options() fluent syntax.
func VerifyWithExtension(t Failable, reader io.Reader, extWithDot string, opts ...verifyOptions) {
	t.Helper()
	Verify(t, reader, alwaysOption(opts).WithExtension(extWithDot))
}

// Verify Example:
//   Verify(t, strings.NewReader("Hello"))
func Verify(t Failable, reader io.Reader, opts ...verifyOptions) {
	t.Helper()

	if len(opts) > 1 {
		panic("Please use fluent syntax for options, see documentation for more information")
	}

	var extWithDot string
	if len(opts) == 0 || opts[0].extWithDot == "" {
		extWithDot = ".txt"
	} else {
		extWithDot = opts[0].extWithDot
	}

	namer := getApprovalName(t)

	if len(opts) > 0 {
		b, err := io.ReadAll(reader)
		if err != nil {
			// TODO: do something
		}

		result := string(b)
		for _, o := range opts {
			for _, sb := range o.scrubbers {
				result = sb(result)
			}
		}

		reader = strings.NewReader(result)
	}

	reporter := getReporter()
	err := namer.compare(namer.getApprovalFile(extWithDot), namer.getReceivedFile(extWithDot), reader)
	if err != nil {
		reporter.Report(namer.getApprovalFile(extWithDot), namer.getReceivedFile(extWithDot))
		t.Log("Failed Approval: received does not match approved.")
		t.Fail()
	} else {
		_ = os.Remove(namer.getReceivedFile(extWithDot))
	}
}

// VerifyString stores the passed string into the received file and confirms
// that it matches the approved local file. On failure, it will launch a reporter.
func VerifyString(t Failable, s string, opts ...verifyOptions) {
	t.Helper()
	reader := strings.NewReader(s)
	Verify(t, reader, opts...)
}

// VerifyXMLStruct Example:
//   VerifyXMLStruct(t, xml)
func VerifyXMLStruct(t Failable, obj interface{}, opts ...verifyOptions) {
	t.Helper()
	xmlContent, err := xml.MarshalIndent(obj, "", "  ")
	if err != nil {
		tip := ""
		if reflect.TypeOf(obj).Name() == "" {
			tip = "when using anonymous types be sure to include\n  XMLName xml.Name `xml:\"Your_Name_Here\"`\n"
		}
		message := fmt.Sprintf("error while pretty printing XML\n%verror:\n  %v\nXML:\n  %v\n", tip, err, obj)
		Verify(t, strings.NewReader(message), alwaysOption(opts).WithExtension(".xml"))
	} else {
		Verify(t, bytes.NewReader(xmlContent), alwaysOption(opts).WithExtension(".xml"))
	}
}

// VerifyXMLBytes Example:
//   VerifyXMLBytes(t, []byte("<Test/>"))
func VerifyXMLBytes(t Failable, bs []byte, opts ...verifyOptions) {
	t.Helper()
	type node struct {
		Attr     []xml.Attr
		XMLName  xml.Name
		Children []node `xml:",any"`
		Text     string `xml:",chardata"`
	}
	x := node{}

	err := xml.Unmarshal(bs, &x)
	if err != nil {
		message := fmt.Sprintf("error while parsing XML\nerror:\n  %s\nXML:\n  %s\n", err, string(bs))
		Verify(t, strings.NewReader(message), alwaysOption(opts).WithExtension(".xml"))
	} else {
		VerifyXMLStruct(t, x, opts...)
	}
}

// VerifyJSONStruct Example:
//   VerifyJSONStruct(t, json)
func VerifyJSONStruct(t Failable, obj interface{}, opts ...verifyOptions) {
	t.Helper()

	jsonb, err := json.MarshalIndent(obj, "", "  ")
	if err != nil {
		message := fmt.Sprintf("error while pretty printing JSON\nerror:\n  %s\nJSON:\n  %s\n", err, obj)
		Verify(t, strings.NewReader(message), alwaysOption(opts).WithExtension(".json"))
	} else {
		Verify(t, bytes.NewReader(jsonb), alwaysOption(opts).WithExtension(".json"))
	}
}

// VerifyJSONBytes Example:
//   VerifyJSONBytes(t, []byte("{ \"Greeting\": \"Hello\" }"))
func VerifyJSONBytes(t Failable, bs []byte, opts ...verifyOptions) {
	t.Helper()
	var obj map[string]interface{}
	err := json.Unmarshal(bs, &obj)
	if err != nil {
		message := fmt.Sprintf("error while parsing JSON\nerror:\n  %s\nJSON:\n  %s\n", err, string(bs))
		Verify(t, strings.NewReader(message), alwaysOption(opts).WithExtension(".json"))
	} else {
		VerifyJSONStruct(t, obj, opts...)
	}
}

// VerifyMap Example:
//   VerifyMap(t, map[string][string] { "dog": "bark" })
func VerifyMap(t Failable, m interface{}, opts ...verifyOptions) {
	t.Helper()
	outputText := utils.PrintMap(m)
	VerifyString(t, outputText, opts...)
}

// VerifyArray Example:
//   VerifyArray(t, []string{"dog", "cat"})
func VerifyArray(t Failable, array interface{}, opts ...verifyOptions) {
	t.Helper()
	outputText := utils.PrintArray(array)
	VerifyString(t, outputText, opts...)
}

// VerifyAll Example:
//   VerifyAll(t, "uppercase", []string("dog", "cat"}, func(x interface{}) string { return strings.ToUpper(x.(string)) })
func VerifyAll(t Failable, header string, collection interface{}, transform func(interface{}) string, opts ...verifyOptions) {
	t.Helper()
	if len(header) != 0 {
		header = fmt.Sprintf("%s\n\n\n", header)
	}

	outputText := header + strings.Join(utils.MapToString(collection, transform), "\n")
	VerifyString(t, outputText, opts...)
}

type reporterCloser struct {
	reporter reporters.Reporter
}

func (s *reporterCloser) Close() error {
	defaultReporter = s.reporter
	return nil
}

type frontLoadedReporterCloser struct {
	reporter reporters.Reporter
}

func (s *frontLoadedReporterCloser) Close() error {
	defaultFrontLoadedReporter = s.reporter
	return nil
}

// UseReporter configures which reporter to use on failure.
// Add at the test or method level to configure your reporter.
//
// The following examples shows how to use a reporter for all of your test cases
// in a package directory through go's setup feature.
//
//
//	func TestMain(m *testing.M) {
//		r := approvals.UseReporter(reporters.NewBeyondCompareReporter())
//		defer r.Close()
//
//		os.Exit(m.Run())
//	}
//
func UseReporter(reporter reporters.Reporter) io.Closer {
	closer := &reporterCloser{
		reporter: defaultReporter,
	}

	defaultReporter = reporter
	return closer
}

// UseFrontLoadedReporter configures reporters ahead of all other reporters to
// handle situations like CI. These reporters usually prevent reporting in
// scenarios that are headless.
func UseFrontLoadedReporter(reporter reporters.Reporter) io.Closer {
	closer := &frontLoadedReporterCloser{
		reporter: defaultFrontLoadedReporter,
	}

	defaultFrontLoadedReporter = reporter
	return closer
}

func getReporter() reporters.Reporter {
	return reporters.NewFirstWorkingReporter(
		defaultFrontLoadedReporter,
		defaultReporter,
	)
}

// UseFolder configures which folder to use to store approval files.
// By default, the approval files will be stored at the same level as the code.
//
// The following examples shows how to use the idiomatic 'testdata' folder
// for all of your test cases in a package directory.
//
//
//	func TestMain(m *testing.M) {
//		approvals.UseFolder("testdata")
//
//		os.Exit(m.Run())
//	}
//
func UseFolder(f string) {
	defaultFolder = f
}

type scrubber func(s string) string

// verifyOptions can be accessed via the approvals.Options() API enabling configuration of scrubbers
type verifyOptions struct {
	scrubbers  []scrubber
	extWithDot string
}

// Options enables providing individual Verify functions with customisations such as scrubbers
func Options() verifyOptions {
	return verifyOptions{}
}

// WithRegexScrubber allows you to 'scrub' dynamic data such as timestamps within your test input
// and replace it with a static placeholder
func (v verifyOptions) WithRegexScrubber(scrubber *regexp.Regexp, replacer string) verifyOptions {
	v.scrubbers = append(v.scrubbers, func(s string) string {
		return scrubber.ReplaceAllString(s, replacer)
	})
	return v
}

// WithExtension overrides the default file extension (.txt) for approval files.
func (v verifyOptions) WithExtension(extension string) verifyOptions {
	v.extWithDot = extension
	return v
}

func alwaysOption(opts []verifyOptions) verifyOptions {
	var v verifyOptions
	if len(opts) == 0 {
		v = Options()
	} else {
		v = opts[0]
	}

	return v
}
<commit_msg>Handle error if reader is invalid<commit_after>package approvals

import (
	"bytes"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"io"
	"os"
	"reflect"
	"regexp"
	"strings"

	"github.com/approvals/go-approval-tests/reporters"
	"github.com/approvals/go-approval-tests/utils"
)

var (
	defaultReporter            = reporters.NewDiffReporter()
	defaultFrontLoadedReporter = reporters.NewFrontLoadedReporter()
	defaultFolder              = ""
)

// Failable is an interface wrapper around testing.T
type Failable interface {
	Fail()
	Fatal(args ...interface{})
	Fatalf(format string, args ...interface{})
	Name() string
	Log(args ...interface{})
	Logf(format string, args ...interface{})
	Helper()
}

// VerifyWithExtension Example:
//   VerifyWithExtension(t, strings.NewReader("Hello"), ".json")
// Deprecated: Please use Verify with the Options() fluent syntax.
func VerifyWithExtension(t Failable, reader io.Reader, extWithDot string, opts ...verifyOptions) {
	t.Helper()
	Verify(t, reader, alwaysOption(opts).WithExtension(extWithDot))
}

// Verify Example:
//   Verify(t, strings.NewReader("Hello"))
func Verify(t Failable, reader io.Reader, opts ...verifyOptions) {
	t.Helper()

	if len(opts) > 1 {
		panic("Please use fluent syntax for options, see documentation for more information")
	}

	var extWithDot string
	if len(opts) == 0 || opts[0].extWithDot == "" {
		extWithDot = ".txt"
	} else {
		extWithDot = opts[0].extWithDot
	}

	namer := getApprovalName(t)

	if len(opts) > 0 {
		b, err := io.ReadAll(reader)
		if err != nil {
			panic(err)
		}

		result := string(b)
		for _, o := range opts {
			for _, sb := range o.scrubbers {
				result = sb(result)
			}
		}

		reader = strings.NewReader(result)
	}

	reporter := getReporter()
	err := namer.compare(namer.getApprovalFile(extWithDot), namer.getReceivedFile(extWithDot), reader)
	if err != nil {
		reporter.Report(namer.getApprovalFile(extWithDot), namer.getReceivedFile(extWithDot))
		t.Log("Failed Approval: received does not match approved.")
		t.Fail()
	} else {
		_ = os.Remove(namer.getReceivedFile(extWithDot))
	}
}

// VerifyString stores the passed string into the received file and confirms
// that it matches the approved local file. On failure, it will launch a reporter.
func VerifyString(t Failable, s string, opts ...verifyOptions) {
	t.Helper()
	reader := strings.NewReader(s)
	Verify(t, reader, opts...)
}

// VerifyXMLStruct Example:
//   VerifyXMLStruct(t, xml)
func VerifyXMLStruct(t Failable, obj interface{}, opts ...verifyOptions) {
	t.Helper()
	xmlContent, err := xml.MarshalIndent(obj, "", "  ")
	if err != nil {
		tip := ""
		if reflect.TypeOf(obj).Name() == "" {
			tip = "when using anonymous types be sure to include\n  XMLName xml.Name `xml:\"Your_Name_Here\"`\n"
		}
		message := fmt.Sprintf("error while pretty printing XML\n%verror:\n  %v\nXML:\n  %v\n", tip, err, obj)
		Verify(t, strings.NewReader(message), alwaysOption(opts).WithExtension(".xml"))
	} else {
		Verify(t, bytes.NewReader(xmlContent), alwaysOption(opts).WithExtension(".xml"))
	}
}

// VerifyXMLBytes Example:
//   VerifyXMLBytes(t, []byte("<Test/>"))
func VerifyXMLBytes(t Failable, bs []byte, opts ...verifyOptions) {
	t.Helper()
	type node struct {
		Attr     []xml.Attr
		XMLName  xml.Name
		Children []node `xml:",any"`
		Text     string `xml:",chardata"`
	}
	x := node{}

	err := xml.Unmarshal(bs, &x)
	if err != nil {
		message := fmt.Sprintf("error while parsing XML\nerror:\n  %s\nXML:\n  %s\n", err, string(bs))
		Verify(t, strings.NewReader(message), alwaysOption(opts).WithExtension(".xml"))
	} else {
		VerifyXMLStruct(t, x, opts...)
	}
}

// VerifyJSONStruct Example:
//   VerifyJSONStruct(t, json)
func VerifyJSONStruct(t Failable, obj interface{}, opts ...verifyOptions) {
	t.Helper()

	jsonb, err := json.MarshalIndent(obj, "", "  ")
	if err != nil {
		message := fmt.Sprintf("error while pretty printing JSON\nerror:\n  %s\nJSON:\n  %s\n", err, obj)
		Verify(t, strings.NewReader(message), alwaysOption(opts).WithExtension(".json"))
	} else {
		Verify(t, bytes.NewReader(jsonb), alwaysOption(opts).WithExtension(".json"))
	}
}

// VerifyJSONBytes Example:
//   VerifyJSONBytes(t, []byte("{ \"Greeting\": \"Hello\" }"))
func VerifyJSONBytes(t Failable, bs []byte, opts ...verifyOptions) {
	t.Helper()
	var obj map[string]interface{}
	err := json.Unmarshal(bs, &obj)
	if err != nil {
		message := fmt.Sprintf("error while parsing JSON\nerror:\n  %s\nJSON:\n  %s\n", err, string(bs))
		Verify(t, strings.NewReader(message), alwaysOption(opts).WithExtension(".json"))
	} else {
		VerifyJSONStruct(t, obj, opts...)
	}
}

// VerifyMap Example:
//   VerifyMap(t, map[string][string] { "dog": "bark" })
func VerifyMap(t Failable, m interface{}, opts ...verifyOptions) {
	t.Helper()
	outputText := utils.PrintMap(m)
	VerifyString(t, outputText, opts...)
}

// VerifyArray Example:
//   VerifyArray(t, []string{"dog", "cat"})
func VerifyArray(t Failable, array interface{}, opts ...verifyOptions) {
	t.Helper()
	outputText := utils.PrintArray(array)
	VerifyString(t, outputText, opts...)
}

// VerifyAll Example:
//   VerifyAll(t, "uppercase", []string("dog", "cat"}, func(x interface{}) string { return strings.ToUpper(x.(string)) })
func VerifyAll(t Failable, header string, collection interface{}, transform func(interface{}) string, opts ...verifyOptions) {
	t.Helper()
	if len(header) != 0 {
		header = fmt.Sprintf("%s\n\n\n", header)
	}

	outputText := header + strings.Join(utils.MapToString(collection, transform), "\n")
	VerifyString(t, outputText, opts...)
}

type reporterCloser struct {
	reporter reporters.Reporter
}

func (s *reporterCloser) Close() error {
	defaultReporter = s.reporter
	return nil
}

type frontLoadedReporterCloser struct {
	reporter reporters.Reporter
}

func (s *frontLoadedReporterCloser) Close() error {
	defaultFrontLoadedReporter = s.reporter
	return nil
}

// UseReporter configures which reporter to use on failure.
// Add at the test or method level to configure your reporter.
//
// The following examples shows how to use a reporter for all of your test cases
// in a package directory through go's setup feature.
//
//
//	func TestMain(m *testing.M) {
//		r := approvals.UseReporter(reporters.NewBeyondCompareReporter())
//		defer r.Close()
//
//		os.Exit(m.Run())
//	}
//
func UseReporter(reporter reporters.Reporter) io.Closer {
	closer := &reporterCloser{
		reporter: defaultReporter,
	}

	defaultReporter = reporter
	return closer
}

// UseFrontLoadedReporter configures reporters ahead of all other reporters to
// handle situations like CI. These reporters usually prevent reporting in
// scenarios that are headless.
func UseFrontLoadedReporter(reporter reporters.Reporter) io.Closer {
	closer := &frontLoadedReporterCloser{
		reporter: defaultFrontLoadedReporter,
	}

	defaultFrontLoadedReporter = reporter
	return closer
}

func getReporter() reporters.Reporter {
	return reporters.NewFirstWorkingReporter(
		defaultFrontLoadedReporter,
		defaultReporter,
	)
}

// UseFolder configures which folder to use to store approval files.
// By default, the approval files will be stored at the same level as the code.
//
// The following examples shows how to use the idiomatic 'testdata' folder
// for all of your test cases in a package directory.
//
//
//	func TestMain(m *testing.M) {
//		approvals.UseFolder("testdata")
//
//		os.Exit(m.Run())
//	}
//
func UseFolder(f string) {
	defaultFolder = f
}

type scrubber func(s string) string

// verifyOptions can be accessed via the approvals.Options() API enabling configuration of scrubbers
type verifyOptions struct {
	scrubbers  []scrubber
	extWithDot string
}

// Options enables providing individual Verify functions with customisations such as scrubbers
func Options() verifyOptions {
	return verifyOptions{}
}

// WithRegexScrubber allows you to 'scrub' dynamic data such as timestamps within your test input
// and replace it with a static placeholder
func (v verifyOptions) WithRegexScrubber(scrubber *regexp.Regexp, replacer string) verifyOptions {
	v.scrubbers = append(v.scrubbers, func(s string) string {
		return scrubber.ReplaceAllString(s, replacer)
	})
	return v
}

// WithExtension overrides the default file extension (.txt) for approval files.
func (v verifyOptions) WithExtension(extension string) verifyOptions {
	v.extWithDot = extension
	return v
}

func alwaysOption(opts []verifyOptions) verifyOptions {
	var v verifyOptions
	if len(opts) == 0 {
		v = Options()
	} else {
		v = opts[0]
	}

	return v
}
<|endoftext|>


<commit_before>package cc_messages

import "encoding/json"

type DesireAppRequestFromCC struct {
	ProcessGuid     string      `json:"process_guid"`
	DropletUri      string      `json:"droplet_uri"`
	DockerImageUrl  string      `json:"docker_image"`
	Stack           string      `json:"stack"`
	StartCommand    string      `json:"start_command"`
	StagingMetadata string      `json:"staging_metadata"`
	Environment     Environment `json:"environment"`
	MemoryMB        int         `json:"memory_mb"`
	DiskMB          int         `json:"disk_mb"`
	FileDescriptors uint64      `json:"file_descriptors"`
	NumInstances    int         `json:"num_instances"`
	Routes          []string    `json:"routes"`
	LogGuid         string      `json:"log_guid"`
}

func (d DesireAppRequestFromCC) ToJSON() []byte {
	encoded, _ := json.Marshal(d)
	return encoded
}

type CCDesiredStateServerResponse struct {
	Apps        []DesireAppRequestFromCC `json:"apps"`
	CCBulkToken *json.RawMessage         `json:"token"`
}

type CCBulkToken struct {
	Id int `json:"id"`
}
<commit_msg>StagingMetadata => ExectutionMetadata in DesireAppRequestFromCC<commit_after>package cc_messages

import "encoding/json"

type DesireAppRequestFromCC struct {
	ProcessGuid       string      `json:"process_guid"`
	DropletUri        string      `json:"droplet_uri"`
	DockerImageUrl    string      `json:"docker_image"`
	Stack             string      `json:"stack"`
	StartCommand      string      `json:"start_command"`
	ExecutionMetadata string      `json:"execution_metadata"`
	Environment       Environment `json:"environment"`
	MemoryMB          int         `json:"memory_mb"`
	DiskMB            int         `json:"disk_mb"`
	FileDescriptors   uint64      `json:"file_descriptors"`
	NumInstances      int         `json:"num_instances"`
	Routes            []string    `json:"routes"`
	LogGuid           string      `json:"log_guid"`
}

func (d DesireAppRequestFromCC) ToJSON() []byte {
	encoded, _ := json.Marshal(d)
	return encoded
}

type CCDesiredStateServerResponse struct {
	Apps        []DesireAppRequestFromCC `json:"apps"`
	CCBulkToken *json.RawMessage         `json:"token"`
}

type CCBulkToken struct {
	Id int `json:"id"`
}
<|endoftext|>


<commit_before>package cc_messages

import (
	"encoding/json"

	"github.com/cloudfoundry-incubator/bbs/models"
)

type HealthCheckType string

const UnspecifiedHealthCheckType HealthCheckType = "" // backwards-compatibility
const PortHealthCheckType HealthCheckType = "port"
const NoneHealthCheckType HealthCheckType = "none"

const CC_HTTP_ROUTES = "http_routes"

const CC_TCP_ROUTES = "tcp_routes"

const (
	TaskStatePending   = "PENDING"
	TaskStateRunning   = "RUNNING"
	TaskStateCanceling = "CANCELING"
	TaskStateSucceeded = "SUCCEEDED"
)

type DesireAppRequestFromCC struct {
	ProcessGuid                 string                        `json:"process_guid"`
	DropletUri                  string                        `json:"droplet_uri"`
	DockerImageUrl              string                        `json:"docker_image"`
	DockerLoginServer           string                        `json:"docker_login_server,omitempty"`
	DockerUser                  string                        `json:"docker_user,omitempty"`
	DockerPassword              string                        `json:"docker_password,omitempty"`
	DockerEmail                 string                        `json:"docker_email,omitempty"`
	Stack                       string                        `json:"stack"`
	StartCommand                string                        `json:"start_command"`
	ExecutionMetadata           string                        `json:"execution_metadata"`
	Environment                 []*models.EnvironmentVariable `json:"environment"`
	MemoryMB                    int                           `json:"memory_mb"`
	DiskMB                      int                           `json:"disk_mb"`
	FileDescriptors             uint64                        `json:"file_descriptors"`
	NumInstances                int                           `json:"num_instances"`
	RoutingInfo                 CCRouteInfo                   `json:"routing_info"`
	AllowSSH                    bool                          `json:"allow_ssh"`
	LogGuid                     string                        `json:"log_guid"`
	HealthCheckType             HealthCheckType               `json:"health_check_type"`
	HealthCheckTimeoutInSeconds uint                          `json:"health_check_timeout_in_seconds"`
	EgressRules                 []*models.SecurityGroupRule   `json:"egress_rules,omitempty"`
	ETag                        string                        `json:"etag"`
	Ports                       []uint32                      `json:"ports,omitempty"`
	LogSource                   string                        `json:"log_source,omitempty"`
	Network                     *models.Network               `json:"network,omitempty"`
	VolumeMounts                []*models.VolumeMount         `json:"volume_mounts"`
}

type CCRouteInfo map[string]*json.RawMessage

type CCHTTPRoutes []CCHTTPRoute

func (r CCHTTPRoutes) CCRouteInfo() (CCRouteInfo, error) {
	routesJson, err := json.Marshal(r)
	if err != nil {
		return nil, err
	}

	routesPayload := json.RawMessage(routesJson)
	routingInfo := make(map[string]*json.RawMessage)
	routingInfo[CC_HTTP_ROUTES] = &routesPayload
	return routingInfo, nil
}

type CCHTTPRoute struct {
	Hostname        string `json:"hostname"`
	RouteServiceUrl string `json:"route_service_url,omitempty"`
	Port            uint32 `json:"port,omitempty"`
}

type CCTCPRoutes []CCTCPRoute

type CCTCPRoute struct {
	RouterGroupGuid string `json:"router_group_guid"`
	ExternalPort    uint32 `json:"external_port,omitempty"`
	ContainerPort   uint32 `json:"container_port,omitempty"`
}

func (r CCTCPRoutes) CCRouteInfo() (CCRouteInfo, error) {
	routesJson, err := json.Marshal(r)
	if err != nil {
		return nil, err
	}

	routesPayload := json.RawMessage(routesJson)
	routingInfo := make(map[string]*json.RawMessage)
	routingInfo[CC_TCP_ROUTES] = &routesPayload
	return routingInfo, nil
}

type CCDesiredStateServerResponse struct {
	Apps        []DesireAppRequestFromCC `json:"apps"`
	CCBulkToken *json.RawMessage         `json:"token"`
}

type CCDesiredAppFingerprint struct {
	ProcessGuid string `json:"process_guid"`
	ETag        string `json:"etag"`
}

type CCTaskState struct {
	TaskGuid              string `json:"task_guid"`
	State                 string `json:"state"`
	CompletionCallbackUrl string `json:"completion_callback"`
}

type CCDesiredStateFingerprintResponse struct {
	Fingerprints []CCDesiredAppFingerprint `json:"fingerprints"`
	CCBulkToken  *json.RawMessage          `json:"token"`
}

type CCTaskStatesResponse struct {
	TaskStates  []CCTaskState    `json:"task_states"`
	CCBulkToken *json.RawMessage `json:"token"`
}

type CCBulkToken struct {
	Id int `json:"id"`
}

type TaskErrorID string

type TaskRequestFromCC struct {
	TaskGuid              string                        `json:"task_guid"`
	LogGuid               string                        `json:"log_guid"`
	MemoryMb              int                           `json:"memory_mb"`
	DiskMb                int                           `json:"disk_mb"`
	Lifecycle             string                        `json:"lifecycle"`
	EnvironmentVariables  []*models.EnvironmentVariable `json:"environment"`
	EgressRules           []*models.SecurityGroupRule   `json:"egress_rules,omitempty"`
	DropletUri            string                        `json:"droplet_uri"`
	DockerPath            string                        `json:"docker_path"`
	RootFs                string                        `json:"rootfs"`
	CompletionCallbackUrl string                        `json:"completion_callback"`
	Command               string                        `json:"command"`
	LogSource             string                        `json:"log_source,omit_empty"`
}

type TaskFailResponseForCC struct {
	TaskGuid      string `json:"task_guid"`
	Failed        bool   `json:"failed"`
	FailureReason string `json:"failure_reason"`
}

type TaskError struct {
	Id      TaskErrorID `json:"id"`
	Message string      `json:"message"`
}
<commit_msg>Add VolumeMounts to cc task message<commit_after>package cc_messages

import (
	"encoding/json"

	"github.com/cloudfoundry-incubator/bbs/models"
)

type HealthCheckType string

const UnspecifiedHealthCheckType HealthCheckType = "" // backwards-compatibility
const PortHealthCheckType HealthCheckType = "port"
const NoneHealthCheckType HealthCheckType = "none"

const CC_HTTP_ROUTES = "http_routes"

const CC_TCP_ROUTES = "tcp_routes"

const (
	TaskStatePending   = "PENDING"
	TaskStateRunning   = "RUNNING"
	TaskStateCanceling = "CANCELING"
	TaskStateSucceeded = "SUCCEEDED"
)

type DesireAppRequestFromCC struct {
	ProcessGuid                 string                        `json:"process_guid"`
	DropletUri                  string                        `json:"droplet_uri"`
	DockerImageUrl              string                        `json:"docker_image"`
	DockerLoginServer           string                        `json:"docker_login_server,omitempty"`
	DockerUser                  string                        `json:"docker_user,omitempty"`
	DockerPassword              string                        `json:"docker_password,omitempty"`
	DockerEmail                 string                        `json:"docker_email,omitempty"`
	Stack                       string                        `json:"stack"`
	StartCommand                string                        `json:"start_command"`
	ExecutionMetadata           string                        `json:"execution_metadata"`
	Environment                 []*models.EnvironmentVariable `json:"environment"`
	MemoryMB                    int                           `json:"memory_mb"`
	DiskMB                      int                           `json:"disk_mb"`
	FileDescriptors             uint64                        `json:"file_descriptors"`
	NumInstances                int                           `json:"num_instances"`
	RoutingInfo                 CCRouteInfo                   `json:"routing_info"`
	AllowSSH                    bool                          `json:"allow_ssh"`
	LogGuid                     string                        `json:"log_guid"`
	HealthCheckType             HealthCheckType               `json:"health_check_type"`
	HealthCheckTimeoutInSeconds uint                          `json:"health_check_timeout_in_seconds"`
	EgressRules                 []*models.SecurityGroupRule   `json:"egress_rules,omitempty"`
	ETag                        string                        `json:"etag"`
	Ports                       []uint32                      `json:"ports,omitempty"`
	LogSource                   string                        `json:"log_source,omitempty"`
	Network                     *models.Network               `json:"network,omitempty"`
	VolumeMounts                []*models.VolumeMount         `json:"volume_mounts"`
}

type CCRouteInfo map[string]*json.RawMessage

type CCHTTPRoutes []CCHTTPRoute

func (r CCHTTPRoutes) CCRouteInfo() (CCRouteInfo, error) {
	routesJson, err := json.Marshal(r)
	if err != nil {
		return nil, err
	}

	routesPayload := json.RawMessage(routesJson)
	routingInfo := make(map[string]*json.RawMessage)
	routingInfo[CC_HTTP_ROUTES] = &routesPayload
	return routingInfo, nil
}

type CCHTTPRoute struct {
	Hostname        string `json:"hostname"`
	RouteServiceUrl string `json:"route_service_url,omitempty"`
	Port            uint32 `json:"port,omitempty"`
}

type CCTCPRoutes []CCTCPRoute

type CCTCPRoute struct {
	RouterGroupGuid string `json:"router_group_guid"`
	ExternalPort    uint32 `json:"external_port,omitempty"`
	ContainerPort   uint32 `json:"container_port,omitempty"`
}

func (r CCTCPRoutes) CCRouteInfo() (CCRouteInfo, error) {
	routesJson, err := json.Marshal(r)
	if err != nil {
		return nil, err
	}

	routesPayload := json.RawMessage(routesJson)
	routingInfo := make(map[string]*json.RawMessage)
	routingInfo[CC_TCP_ROUTES] = &routesPayload
	return routingInfo, nil
}

type CCDesiredStateServerResponse struct {
	Apps        []DesireAppRequestFromCC `json:"apps"`
	CCBulkToken *json.RawMessage         `json:"token"`
}

type CCDesiredAppFingerprint struct {
	ProcessGuid string `json:"process_guid"`
	ETag        string `json:"etag"`
}

type CCTaskState struct {
	TaskGuid              string `json:"task_guid"`
	State                 string `json:"state"`
	CompletionCallbackUrl string `json:"completion_callback"`
}

type CCDesiredStateFingerprintResponse struct {
	Fingerprints []CCDesiredAppFingerprint `json:"fingerprints"`
	CCBulkToken  *json.RawMessage          `json:"token"`
}

type CCTaskStatesResponse struct {
	TaskStates  []CCTaskState    `json:"task_states"`
	CCBulkToken *json.RawMessage `json:"token"`
}

type CCBulkToken struct {
	Id int `json:"id"`
}

type TaskErrorID string

type TaskRequestFromCC struct {
	TaskGuid              string                        `json:"task_guid"`
	LogGuid               string                        `json:"log_guid"`
	MemoryMb              int                           `json:"memory_mb"`
	DiskMb                int                           `json:"disk_mb"`
	Lifecycle             string                        `json:"lifecycle"`
	EnvironmentVariables  []*models.EnvironmentVariable `json:"environment"`
	EgressRules           []*models.SecurityGroupRule   `json:"egress_rules,omitempty"`
	DropletUri            string                        `json:"droplet_uri"`
	DockerPath            string                        `json:"docker_path"`
	RootFs                string                        `json:"rootfs"`
	CompletionCallbackUrl string                        `json:"completion_callback"`
	Command               string                        `json:"command"`
	LogSource             string                        `json:"log_source,omit_empty"`
	VolumeMounts          []*models.VolumeMount         `json:"volume_mounts"`
}

type TaskFailResponseForCC struct {
	TaskGuid      string `json:"task_guid"`
	Failed        bool   `json:"failed"`
	FailureReason string `json:"failure_reason"`
}

type TaskError struct {
	Id      TaskErrorID `json:"id"`
	Message string      `json:"message"`
}
<|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 runtime

import (
	"runtime/internal/atomic"
	"unsafe"
)

// Per-thread (in Go, per-P) cache for small objects.
// This includes a small object cache and local allocation stats.
// No locking needed because it is per-thread (per-P).
//
// mcaches are allocated from non-GC'd memory, so any heap pointers
// must be specially handled.
//
//go:notinheap
type mcache struct {
	// The following members are accessed on every malloc,
	// so they are grouped here for better caching.
	nextSample uintptr // trigger heap sample after allocating this many bytes
	scanAlloc  uintptr // bytes of scannable heap allocated

	// Allocator cache for tiny objects w/o pointers.
	// See "Tiny allocator" comment in malloc.go.

	// tiny points to the beginning of the current tiny block, or
	// nil if there is no current tiny block.
	//
	// tiny is a heap pointer. Since mcache is in non-GC'd memory,
	// we handle it by clearing it in releaseAll during mark
	// termination.
	//
	// tinyAllocs is the number of tiny allocations performed
	// by the P that owns this mcache.
	tiny       uintptr
	tinyoffset uintptr
	tinyAllocs uintptr

	// The rest is not accessed on every malloc.

	alloc [numSpanClasses]*mspan // spans to allocate from, indexed by spanClass

	stackcache [_NumStackOrders]stackfreelist

	// flushGen indicates the sweepgen during which this mcache
	// was last flushed. If flushGen != mheap_.sweepgen, the spans
	// in this mcache are stale and need to the flushed so they
	// can be swept. This is done in acquirep.
	flushGen uint32
}

// A gclink is a node in a linked list of blocks, like mlink,
// but it is opaque to the garbage collector.
// The GC does not trace the pointers during collection,
// and the compiler does not emit write barriers for assignments
// of gclinkptr values. Code should store references to gclinks
// as gclinkptr, not as *gclink.
type gclink struct {
	next gclinkptr
}

// A gclinkptr is a pointer to a gclink, but it is opaque
// to the garbage collector.
type gclinkptr uintptr

// ptr returns the *gclink form of p.
// The result should be used for accessing fields, not stored
// in other data structures.
func (p gclinkptr) ptr() *gclink {
	return (*gclink)(unsafe.Pointer(p))
}

type stackfreelist struct {
	list gclinkptr // linked list of free stacks
	size uintptr   // total size of stacks in list
}

// dummy mspan that contains no free objects.
var emptymspan mspan

func allocmcache() *mcache {
	var c *mcache
	systemstack(func() {
		lock(&mheap_.lock)
		c = (*mcache)(mheap_.cachealloc.alloc())
		c.flushGen = mheap_.sweepgen
		unlock(&mheap_.lock)
	})
	for i := range c.alloc {
		c.alloc[i] = &emptymspan
	}
	c.nextSample = nextSample()
	return c
}

// freemcache releases resources associated with this
// mcache and puts the object onto a free list.
//
// In some cases there is no way to simply release
// resources, such as statistics, so donate them to
// a different mcache (the recipient).
func freemcache(c *mcache) {
	systemstack(func() {
		c.releaseAll()
		stackcache_clear(c)

		// NOTE(rsc,rlh): If gcworkbuffree comes back, we need to coordinate
		// with the stealing of gcworkbufs during garbage collection to avoid
		// a race where the workbuf is double-freed.
		// gcworkbuffree(c.gcworkbuf)

		lock(&mheap_.lock)
		mheap_.cachealloc.free(unsafe.Pointer(c))
		unlock(&mheap_.lock)
	})
}

// getMCache is a convenience function which tries to obtain an mcache.
//
// Returns nil if we're not bootstrapping or we don't have a P. The caller's
// P must not change, so we must be in a non-preemptible state.
func getMCache(mp *m) *mcache {
	// Grab the mcache, since that's where stats live.
	pp := mp.p.ptr()
	var c *mcache
	if pp == nil {
		// We will be called without a P while bootstrapping,
		// in which case we use mcache0, which is set in mallocinit.
		// mcache0 is cleared when bootstrapping is complete,
		// by procresize.
		c = mcache0
	} else {
		c = pp.mcache
	}
	return c
}

// refill acquires a new span of span class spc for c. This span will
// have at least one free object. The current span in c must be full.
//
// Must run in a non-preemptible context since otherwise the owner of
// c could change.
func (c *mcache) refill(spc spanClass) {
	// Return the current cached span to the central lists.
	s := c.alloc[spc]

	if uintptr(s.allocCount) != s.nelems {
		throw("refill of span with free space remaining")
	}
	if s != &emptymspan {
		// Mark this span as no longer cached.
		if s.sweepgen != mheap_.sweepgen+3 {
			throw("bad sweepgen in refill")
		}
		mheap_.central[spc].mcentral.uncacheSpan(s)

		// Count up how many slots were used and record it.
		stats := memstats.heapStats.acquire()
		slotsUsed := int64(s.allocCount) - int64(s.allocCountBeforeCache)
		atomic.Xadd64(&stats.smallAllocCount[spc.sizeclass()], slotsUsed)

		// Flush tinyAllocs.
		if spc == tinySpanClass {
			atomic.Xadd64(&stats.tinyAllocCount, int64(c.tinyAllocs))
			c.tinyAllocs = 0
		}
		memstats.heapStats.release()

		// Count the allocs in inconsistent, internal stats.
		bytesAllocated := slotsUsed * int64(s.elemsize)
		gcController.totalAlloc.Add(bytesAllocated)

		// Update heapLive and flush scanAlloc.
		gcController.update(bytesAllocated, int64(c.scanAlloc))
		c.scanAlloc = 0

		// Clear the second allocCount just to be safe.
		s.allocCountBeforeCache = 0
	}

	// Get a new cached span from the central lists.
	s = mheap_.central[spc].mcentral.cacheSpan()
	if s == nil {
		throw("out of memory")
	}

	if uintptr(s.allocCount) == s.nelems {
		throw("span has no free space")
	}

	// Indicate that this span is cached and prevent asynchronous
	// sweeping in the next sweep phase.
	s.sweepgen = mheap_.sweepgen + 3

	// Store the current alloc count for accounting later.
	s.allocCountBeforeCache = s.allocCount

	c.alloc[spc] = s
}

// allocLarge allocates a span for a large object.
func (c *mcache) allocLarge(size uintptr, noscan bool) *mspan {
	if size+_PageSize < size {
		throw("out of memory")
	}
	npages := size >> _PageShift
	if size&_PageMask != 0 {
		npages++
	}

	// Deduct credit for this span allocation and sweep if
	// necessary. mHeap_Alloc will also sweep npages, so this only
	// pays the debt down to npage pages.
	deductSweepCredit(npages*_PageSize, npages)

	spc := makeSpanClass(0, noscan)
	s := mheap_.alloc(npages, spc)
	if s == nil {
		throw("out of memory")
	}

	// Count the alloc in consistent, external stats.
	stats := memstats.heapStats.acquire()
	atomic.Xadd64(&stats.largeAlloc, int64(npages*pageSize))
	atomic.Xadd64(&stats.largeAllocCount, 1)
	memstats.heapStats.release()

	// Count the alloc in inconsistent, internal stats.
	gcController.totalAlloc.Add(int64(npages * pageSize))

	// Update heapLive.
	gcController.update(int64(s.npages*pageSize), 0)

	// Put the large span in the mcentral swept list so that it's
	// visible to the background sweeper.
	mheap_.central[spc].mcentral.fullSwept(mheap_.sweepgen).push(s)
	s.limit = s.base() + size
	heapBitsForAddr(s.base()).initSpan(s)
	return s
}

func (c *mcache) releaseAll() {
	// Take this opportunity to flush scanAlloc.
	scanAlloc := int64(c.scanAlloc)
	c.scanAlloc = 0

	for i := range c.alloc {
		s := c.alloc[i]
		if s != &emptymspan {
			slotsUsed := int64(s.allocCount) - int64(s.allocCountBeforeCache)
			s.allocCountBeforeCache = 0

			// Adjust smallAllocCount for whatever was allocated.
			stats := memstats.heapStats.acquire()
			atomic.Xadd64(&stats.smallAllocCount[spanClass(i).sizeclass()], slotsUsed)
			memstats.heapStats.release()

			// Adjust the actual allocs in inconsistent, internal stats.
			// We assumed earlier that the full span gets allocated.
			gcController.totalAlloc.Add(slotsUsed * int64(s.elemsize))

			// Release the span to the mcentral.
			mheap_.central[i].mcentral.uncacheSpan(s)
			c.alloc[i] = &emptymspan
		}
	}
	// Clear tinyalloc pool.
	c.tiny = 0
	c.tinyoffset = 0

	// Flush tinyAllocs.
	stats := memstats.heapStats.acquire()
	atomic.Xadd64(&stats.tinyAllocCount, int64(c.tinyAllocs))
	c.tinyAllocs = 0
	memstats.heapStats.release()

	// Updated heapScan.
	gcController.update(0, scanAlloc)
}

// prepareForSweep flushes c if the system has entered a new sweep phase
// since c was populated. This must happen between the sweep phase
// starting and the first allocation from c.
func (c *mcache) prepareForSweep() {
	// Alternatively, instead of making sure we do this on every P
	// between starting the world and allocating on that P, we
	// could leave allocate-black on, allow allocation to continue
	// as usual, use a ragged barrier at the beginning of sweep to
	// ensure all cached spans are swept, and then disable
	// allocate-black. However, with this approach it's difficult
	// to avoid spilling mark bits into the *next* GC cycle.
	sg := mheap_.sweepgen
	if c.flushGen == sg {
		return
	} else if c.flushGen != sg-2 {
		println("bad flushGen", c.flushGen, "in prepareForSweep; sweepgen", sg)
		throw("bad flushGen")
	}
	c.releaseAll()
	stackcache_clear(c)
	atomic.Store(&c.flushGen, mheap_.sweepgen) // Synchronizes with gcStart
}
<commit_msg>runtime: overestimate the amount of allocated memory in heapLive<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 runtime

import (
	"runtime/internal/atomic"
	"unsafe"
)

// Per-thread (in Go, per-P) cache for small objects.
// This includes a small object cache and local allocation stats.
// No locking needed because it is per-thread (per-P).
//
// mcaches are allocated from non-GC'd memory, so any heap pointers
// must be specially handled.
//
//go:notinheap
type mcache struct {
	// The following members are accessed on every malloc,
	// so they are grouped here for better caching.
	nextSample uintptr // trigger heap sample after allocating this many bytes
	scanAlloc  uintptr // bytes of scannable heap allocated

	// Allocator cache for tiny objects w/o pointers.
	// See "Tiny allocator" comment in malloc.go.

	// tiny points to the beginning of the current tiny block, or
	// nil if there is no current tiny block.
	//
	// tiny is a heap pointer. Since mcache is in non-GC'd memory,
	// we handle it by clearing it in releaseAll during mark
	// termination.
	//
	// tinyAllocs is the number of tiny allocations performed
	// by the P that owns this mcache.
	tiny       uintptr
	tinyoffset uintptr
	tinyAllocs uintptr

	// The rest is not accessed on every malloc.

	alloc [numSpanClasses]*mspan // spans to allocate from, indexed by spanClass

	stackcache [_NumStackOrders]stackfreelist

	// flushGen indicates the sweepgen during which this mcache
	// was last flushed. If flushGen != mheap_.sweepgen, the spans
	// in this mcache are stale and need to the flushed so they
	// can be swept. This is done in acquirep.
	flushGen uint32
}

// A gclink is a node in a linked list of blocks, like mlink,
// but it is opaque to the garbage collector.
// The GC does not trace the pointers during collection,
// and the compiler does not emit write barriers for assignments
// of gclinkptr values. Code should store references to gclinks
// as gclinkptr, not as *gclink.
type gclink struct {
	next gclinkptr
}

// A gclinkptr is a pointer to a gclink, but it is opaque
// to the garbage collector.
type gclinkptr uintptr

// ptr returns the *gclink form of p.
// The result should be used for accessing fields, not stored
// in other data structures.
func (p gclinkptr) ptr() *gclink {
	return (*gclink)(unsafe.Pointer(p))
}

type stackfreelist struct {
	list gclinkptr // linked list of free stacks
	size uintptr   // total size of stacks in list
}

// dummy mspan that contains no free objects.
var emptymspan mspan

func allocmcache() *mcache {
	var c *mcache
	systemstack(func() {
		lock(&mheap_.lock)
		c = (*mcache)(mheap_.cachealloc.alloc())
		c.flushGen = mheap_.sweepgen
		unlock(&mheap_.lock)
	})
	for i := range c.alloc {
		c.alloc[i] = &emptymspan
	}
	c.nextSample = nextSample()
	return c
}

// freemcache releases resources associated with this
// mcache and puts the object onto a free list.
//
// In some cases there is no way to simply release
// resources, such as statistics, so donate them to
// a different mcache (the recipient).
func freemcache(c *mcache) {
	systemstack(func() {
		c.releaseAll()
		stackcache_clear(c)

		// NOTE(rsc,rlh): If gcworkbuffree comes back, we need to coordinate
		// with the stealing of gcworkbufs during garbage collection to avoid
		// a race where the workbuf is double-freed.
		// gcworkbuffree(c.gcworkbuf)

		lock(&mheap_.lock)
		mheap_.cachealloc.free(unsafe.Pointer(c))
		unlock(&mheap_.lock)
	})
}

// getMCache is a convenience function which tries to obtain an mcache.
//
// Returns nil if we're not bootstrapping or we don't have a P. The caller's
// P must not change, so we must be in a non-preemptible state.
func getMCache(mp *m) *mcache {
	// Grab the mcache, since that's where stats live.
	pp := mp.p.ptr()
	var c *mcache
	if pp == nil {
		// We will be called without a P while bootstrapping,
		// in which case we use mcache0, which is set in mallocinit.
		// mcache0 is cleared when bootstrapping is complete,
		// by procresize.
		c = mcache0
	} else {
		c = pp.mcache
	}
	return c
}

// refill acquires a new span of span class spc for c. This span will
// have at least one free object. The current span in c must be full.
//
// Must run in a non-preemptible context since otherwise the owner of
// c could change.
func (c *mcache) refill(spc spanClass) {
	// Return the current cached span to the central lists.
	s := c.alloc[spc]

	if uintptr(s.allocCount) != s.nelems {
		throw("refill of span with free space remaining")
	}
	if s != &emptymspan {
		// Mark this span as no longer cached.
		if s.sweepgen != mheap_.sweepgen+3 {
			throw("bad sweepgen in refill")
		}
		mheap_.central[spc].mcentral.uncacheSpan(s)

		// Count up how many slots were used and record it.
		stats := memstats.heapStats.acquire()
		slotsUsed := int64(s.allocCount) - int64(s.allocCountBeforeCache)
		atomic.Xadd64(&stats.smallAllocCount[spc.sizeclass()], slotsUsed)

		// Flush tinyAllocs.
		if spc == tinySpanClass {
			atomic.Xadd64(&stats.tinyAllocCount, int64(c.tinyAllocs))
			c.tinyAllocs = 0
		}
		memstats.heapStats.release()

		// Count the allocs in inconsistent, internal stats.
		bytesAllocated := slotsUsed * int64(s.elemsize)
		gcController.totalAlloc.Add(bytesAllocated)

		// Clear the second allocCount just to be safe.
		s.allocCountBeforeCache = 0
	}

	// Get a new cached span from the central lists.
	s = mheap_.central[spc].mcentral.cacheSpan()
	if s == nil {
		throw("out of memory")
	}

	if uintptr(s.allocCount) == s.nelems {
		throw("span has no free space")
	}

	// Indicate that this span is cached and prevent asynchronous
	// sweeping in the next sweep phase.
	s.sweepgen = mheap_.sweepgen + 3

	// Store the current alloc count for accounting later.
	s.allocCountBeforeCache = s.allocCount

	// Update heapLive and flush scanAlloc.
	//
	// We have not yet allocated anything new into the span, but we
	// assume that all of its slots will get used, so this makes
	// heapLive an overestimate.
	//
	// When the span gets uncached, we'll fix up this overestimate
	// if necessary (see releaseAll).
	//
	// We pick an overestimate here because an underestimate leads
	// the pacer to believe that it's in better shape than it is,
	// which appears to lead to more memory used. See #53738 for
	// more details.
	usedBytes := uintptr(s.allocCount) * s.elemsize
	gcController.update(int64(s.npages*pageSize)-int64(usedBytes), int64(c.scanAlloc))
	c.scanAlloc = 0

	c.alloc[spc] = s
}

// allocLarge allocates a span for a large object.
func (c *mcache) allocLarge(size uintptr, noscan bool) *mspan {
	if size+_PageSize < size {
		throw("out of memory")
	}
	npages := size >> _PageShift
	if size&_PageMask != 0 {
		npages++
	}

	// Deduct credit for this span allocation and sweep if
	// necessary. mHeap_Alloc will also sweep npages, so this only
	// pays the debt down to npage pages.
	deductSweepCredit(npages*_PageSize, npages)

	spc := makeSpanClass(0, noscan)
	s := mheap_.alloc(npages, spc)
	if s == nil {
		throw("out of memory")
	}

	// Count the alloc in consistent, external stats.
	stats := memstats.heapStats.acquire()
	atomic.Xadd64(&stats.largeAlloc, int64(npages*pageSize))
	atomic.Xadd64(&stats.largeAllocCount, 1)
	memstats.heapStats.release()

	// Count the alloc in inconsistent, internal stats.
	gcController.totalAlloc.Add(int64(npages * pageSize))

	// Update heapLive.
	gcController.update(int64(s.npages*pageSize), 0)

	// Put the large span in the mcentral swept list so that it's
	// visible to the background sweeper.
	mheap_.central[spc].mcentral.fullSwept(mheap_.sweepgen).push(s)
	s.limit = s.base() + size
	heapBitsForAddr(s.base()).initSpan(s)
	return s
}

func (c *mcache) releaseAll() {
	// Take this opportunity to flush scanAlloc.
	scanAlloc := int64(c.scanAlloc)
	c.scanAlloc = 0

	sg := mheap_.sweepgen
	dHeapLive := int64(0)
	for i := range c.alloc {
		s := c.alloc[i]
		if s != &emptymspan {
			slotsUsed := int64(s.allocCount) - int64(s.allocCountBeforeCache)
			s.allocCountBeforeCache = 0

			// Adjust smallAllocCount for whatever was allocated.
			stats := memstats.heapStats.acquire()
			atomic.Xadd64(&stats.smallAllocCount[spanClass(i).sizeclass()], slotsUsed)
			memstats.heapStats.release()

			// Adjust the actual allocs in inconsistent, internal stats.
			// We assumed earlier that the full span gets allocated.
			gcController.totalAlloc.Add(slotsUsed * int64(s.elemsize))

			if s.sweepgen != sg+1 {
				// refill conservatively counted unallocated slots in gcController.heapLive.
				// Undo this.
				//
				// If this span was cached before sweep, then gcController.heapLive was totally
				// recomputed since caching this span, so we don't do this for stale spans.
				dHeapLive -= int64(uintptr(s.nelems)-uintptr(s.allocCount)) * int64(s.elemsize)
			}

			// Release the span to the mcentral.
			mheap_.central[i].mcentral.uncacheSpan(s)
			c.alloc[i] = &emptymspan
		}
	}
	// Clear tinyalloc pool.
	c.tiny = 0
	c.tinyoffset = 0

	// Flush tinyAllocs.
	stats := memstats.heapStats.acquire()
	atomic.Xadd64(&stats.tinyAllocCount, int64(c.tinyAllocs))
	c.tinyAllocs = 0
	memstats.heapStats.release()

	// Update heapLive and heapScan.
	gcController.update(dHeapLive, scanAlloc)
}

// prepareForSweep flushes c if the system has entered a new sweep phase
// since c was populated. This must happen between the sweep phase
// starting and the first allocation from c.
func (c *mcache) prepareForSweep() {
	// Alternatively, instead of making sure we do this on every P
	// between starting the world and allocating on that P, we
	// could leave allocate-black on, allow allocation to continue
	// as usual, use a ragged barrier at the beginning of sweep to
	// ensure all cached spans are swept, and then disable
	// allocate-black. However, with this approach it's difficult
	// to avoid spilling mark bits into the *next* GC cycle.
	sg := mheap_.sweepgen
	if c.flushGen == sg {
		return
	} else if c.flushGen != sg-2 {
		println("bad flushGen", c.flushGen, "in prepareForSweep; sweepgen", sg)
		throw("bad flushGen")
	}
	c.releaseAll()
	stackcache_clear(c)
	atomic.Store(&c.flushGen, mheap_.sweepgen) // Synchronizes with gcStart
}
<|endoftext|>


<commit_before>package primitives

type Camera struct {
	lowerLeft, horizontal, vertical, origin Vector
}

func NewCamera() Camera {
	c := Camera{}

	c.lowerLeft = Vector{-2.0, -1.0, -1.0}
	c.horizontal = Vector{4.0, 0.0, 0.0}
	c.vertical = Vector{0.0, 2.0, 0.0}
	c.origin = Vector{0.0, 0.0, 0.0}

	return c
}

func (c Camera) RayAt(u float64, v float64) Ray {
	position := c.position(u, v)
	direction := c.direction(position)

	return Ray{c.origin, direction}
}

func (c Camera) position(u float64, v float64) Vector {
	horizontal := c.horizontal.MultiplyScalar(u)
	vertical := c.vertical.MultiplyScalar(v)

	return horizontal.Add(vertical)
}

func (c Camera) direction(position Vector) Vector {
	return c.lowerLeft.Add(position)
}
<commit_msg>Remove un-needed method<commit_after>package primitives

type Camera struct {
	lowerLeft, horizontal, vertical, origin Vector
}

func NewCamera() Camera {
	c := Camera{}

	c.lowerLeft = Vector{-2.0, -1.0, -1.0}
	c.horizontal = Vector{4.0, 0.0, 0.0}
	c.vertical = Vector{0.0, 2.0, 0.0}
	c.origin = Vector{0.0, 0.0, 0.0}

	return c
}

func (c Camera) RayAt(u float64, v float64) Ray {
	position := c.position(u, v)
	direction := c.lowerLeft.Add(position)

	return Ray{c.origin, direction}
}

func (c Camera) position(u float64, v float64) Vector {
	horizontal := c.horizontal.MultiplyScalar(u)
	vertical := c.vertical.MultiplyScalar(v)

	return horizontal.Add(vertical)
}
<|endoftext|>


<commit_before>package cli

import (
	"fmt"
	"path"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/bitrise-tools/bitrise-machine/config"
	"github.com/bitrise-tools/bitrise-machine/utils"
	"github.com/bitrise-io/go-utils/pathutil"
	"github.com/codegangsta/cli"
)

func doSetupSSH(configModel config.MachineConfigModel) (config.SSHConfigModel, error) {
	log.Infoln("==> doSetupSSH")
	sshConfigModel := config.SSHConfigModel{}

	// Read `vagrant ssh-config` log/output
	outputs, err := utils.RunAndReturnCombinedOutput(MachineWorkdir, configModel.Envs.ToCmdEnvs(), "vagrant", "ssh-config")
	if err != nil {
		log.Errorf("'vagrant ssh-config' failed with output: %s", outputs)
		return sshConfigModel, err
	}

	// Convert `vagrant ssh-config` to our SSHConfigModel
	sshConfigModel, err = config.CreateSSHConfigFromVagrantSSHConfigLog(outputs)
	if err != nil {
		log.Errorf("'vagrant ssh-config' returned an invalid output (failed to scan SSH Config): %s", outputs)
		return sshConfigModel, err
	}

	// Generate SSH Keypair
	privBytes, pubBytes, err := utils.GenerateSSHKeypair()
	if err != nil {
		return sshConfigModel, err
	}

	// Write the SSH Keypair to file
	privKeyFilePth, _, err := config.WriteSSHKeypairToFiles(MachineWorkdir, privBytes, pubBytes)
	if err != nil {
		return sshConfigModel, err
	}

	// Replace the ~/.ssh/authorized_keys inside the VM to only allow
	//  the new keypair
	replaceAuthKeysCmd := fmt.Sprintf(`printf "%s" > ~/.ssh/authorized_keys`, pubBytes)
	if err := utils.RunCommandThroughSSH(sshConfigModel, replaceAuthKeysCmd); err != nil {
		return sshConfigModel, err
	}

	// Save private key as the new identity
	sshConfigModel.IdentityPath = privKeyFilePth
	if err := sshConfigModel.WriteIntoFileInDir(MachineWorkdir); err != nil {
		return sshConfigModel, err
	}

	return sshConfigModel, nil
}

// doTimesync generates an appropriately formatted
//  time string, then calls `sudo date` through SSH
// This is required for Virtual Machines which are
//  simply rolled back to a snapshot state which might
//  mess up the VM's time (restores it to the snapshot time)
func doTimesync(sshConfigModel config.SSHConfigModel) error {
	log.Infoln("==> doTimesync")

	const layout = "2006-01-02 15:04:05 MST"
	timeNow := time.Now()
	timeAsString := timeNow.UTC().Format(layout)
	// THIS ONLY WORKS ON OSX VM!!
	timeSyncCmd := fmt.Sprintf("%s %s",
		`sudo date -uf "%Y-%m-%d %H:%M:%S UTC"`,
		`"`+timeAsString+`"`)
	log.Infoln("timeSyncCmd: ", timeSyncCmd)

	if err := utils.RunCommandThroughSSH(sshConfigModel, timeSyncCmd); err != nil {
		return err
	}

	return nil
}

func setup(c *cli.Context) {
	log.Infoln("Setup")

	configModel, err := config.ReadMachineConfigFileFromDir(MachineWorkdir)
	if err != nil {
		log.Fatalln("Failed to read Config file: ", err)
	}

	isOK, err := pathutil.IsPathExists(path.Join(MachineWorkdir, "Vagrantfile"))
	if err != nil {
		log.Fatalln("Failed to check 'Vagrantfile' in the WorkDir: ", err)
	}
	if !isOK {
		log.Fatalln("Vagrantfile not found in the WorkDir!")
	}

	log.Infof("configModel: %#v", configModel)

	isSkipSetups := false
	if config.IsSSHKeypairFileExistInDirectory(MachineWorkdir) && !c.Bool(ForceFlagKey) {
		log.Info("Host is already prepared and no --force flag was specified, skipping setup.")
		isSkipSetups = true
	}

	if !isSkipSetups {
		// doCleanup
		if configModel.IsCleanupBeforeSetup {
			if err := doCleanup(configModel, ""); err != nil {
				log.Fatalf("Failed to Cleanup: %s", err)
			}
		}

		// ssh
		_, err := doSetupSSH(configModel)
		if err != nil {
			log.Fatalf("Failed to Setup SSH: %s", err)
		}
	}

	// time sync
	sshConfigModel, err := config.ReadSSHConfigFileFromDir(MachineWorkdir)
	if err != nil {
		log.Fatalf("Failed to read SSH Config file! Error: %s", err)
	}
	if configModel.IsDoTimesyncAtSetup {
		if err := doTimesync(sshConfigModel); err != nil {
			log.Fatalf("Failed to do Time Sync: %s", err)
		}
	}

	log.Infoln("=> Setup DONE - OK")
}
<commit_msg>added more Debug info to setup:doSetupSSH<commit_after>package cli

import (
	"fmt"
	"path"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/bitrise-io/go-utils/pathutil"
	"github.com/bitrise-tools/bitrise-machine/config"
	"github.com/bitrise-tools/bitrise-machine/utils"
	"github.com/codegangsta/cli"
)

func doSetupSSH(configModel config.MachineConfigModel) (config.SSHConfigModel, error) {
	log.Infoln("==> doSetupSSH")
	sshConfigModel := config.SSHConfigModel{}

	// Read `vagrant ssh-config` log/output
	outputs, err := utils.RunAndReturnCombinedOutput(MachineWorkdir, configModel.Envs.ToCmdEnvs(), "vagrant", "ssh-config")
	if err != nil {
		log.Errorf("'vagrant ssh-config' failed with output: %s", outputs)
		return sshConfigModel, err
	}
	log.Debugln("===> (raw) vagrant ssh-config retrieved")

	// Convert `vagrant ssh-config` to our SSHConfigModel
	sshConfigModel, err = config.CreateSSHConfigFromVagrantSSHConfigLog(outputs)
	if err != nil {
		log.Errorf("'vagrant ssh-config' returned an invalid output (failed to scan SSH Config): %s", outputs)
		return sshConfigModel, err
	}
	log.Debugln("===> vagrant ssh-config parsed")

	// Generate SSH Keypair
	privBytes, pubBytes, err := utils.GenerateSSHKeypair()
	if err != nil {
		return sshConfigModel, err
	}
	log.Debugln("===> SSH Keypair generated")

	// Write the SSH Keypair to file
	privKeyFilePth, _, err := config.WriteSSHKeypairToFiles(MachineWorkdir, privBytes, pubBytes)
	if err != nil {
		return sshConfigModel, err
	}
	log.Debugln("===> SSH Keypair written to file")

	// Replace the ~/.ssh/authorized_keys inside the VM to only allow
	//  the new keypair
	replaceAuthKeysCmd := fmt.Sprintf(`printf "%s" > ~/.ssh/authorized_keys`, pubBytes)
	log.Debugf("===> Running command through SSH: %s", replaceAuthKeysCmd)
	if err := utils.RunCommandThroughSSH(sshConfigModel, replaceAuthKeysCmd); err != nil {
		return sshConfigModel, err
	}
	log.Debugln("===> SSH Keypair is now authorized to access the VM")

	// Save private key as the new identity
	sshConfigModel.IdentityPath = privKeyFilePth
	if err := sshConfigModel.WriteIntoFileInDir(MachineWorkdir); err != nil {
		return sshConfigModel, err
	}
	log.Debugln("===> New identity (private SSH key) saved into config in workdir")

	log.Debugln("==> doSetupSSH [done]")
	return sshConfigModel, nil
}

// doTimesync generates an appropriately formatted
//  time string, then calls `sudo date` through SSH
// This is required for Virtual Machines which are
//  simply rolled back to a snapshot state which might
//  mess up the VM's time (restores it to the snapshot time)
func doTimesync(sshConfigModel config.SSHConfigModel) error {
	log.Infoln("==> doTimesync")

	const layout = "2006-01-02 15:04:05 MST"
	timeNow := time.Now()
	timeAsString := timeNow.UTC().Format(layout)
	// THIS ONLY WORKS ON OSX VM!!
	timeSyncCmd := fmt.Sprintf("%s %s",
		`sudo date -uf "%Y-%m-%d %H:%M:%S UTC"`,
		`"`+timeAsString+`"`)
	log.Infoln("timeSyncCmd: ", timeSyncCmd)

	if err := utils.RunCommandThroughSSH(sshConfigModel, timeSyncCmd); err != nil {
		return err
	}

	return nil
}

func setup(c *cli.Context) {
	log.Infoln("Setup")

	configModel, err := config.ReadMachineConfigFileFromDir(MachineWorkdir)
	if err != nil {
		log.Fatalln("Failed to read Config file: ", err)
	}

	isOK, err := pathutil.IsPathExists(path.Join(MachineWorkdir, "Vagrantfile"))
	if err != nil {
		log.Fatalln("Failed to check 'Vagrantfile' in the WorkDir: ", err)
	}
	if !isOK {
		log.Fatalln("Vagrantfile not found in the WorkDir!")
	}

	log.Infof("configModel: %#v", configModel)

	isSkipSetups := false
	if config.IsSSHKeypairFileExistInDirectory(MachineWorkdir) && !c.Bool(ForceFlagKey) {
		log.Info("Host is already prepared and no --force flag was specified, skipping setup.")
		isSkipSetups = true
	}

	if !isSkipSetups {
		// doCleanup
		if configModel.IsCleanupBeforeSetup {
			if err := doCleanup(configModel, ""); err != nil {
				log.Fatalf("Failed to Cleanup: %s", err)
			}
		}

		// ssh
		_, err := doSetupSSH(configModel)
		if err != nil {
			log.Fatalf("Failed to Setup SSH: %s", err)
		}
	}

	// time sync
	sshConfigModel, err := config.ReadSSHConfigFileFromDir(MachineWorkdir)
	if err != nil {
		log.Fatalf("Failed to read SSH Config file! Error: %s", err)
	}
	if configModel.IsDoTimesyncAtSetup {
		if err := doTimesync(sshConfigModel); err != nil {
			log.Fatalf("Failed to do Time Sync: %s", err)
		}
	}

	log.Infoln("=> Setup DONE - OK")
}
<|endoftext|>


<commit_before>/*
 * src/go/dnsresolvh.go
 * ============================================================================
 * DNS Resolver Daemon (dnsresolvd). Version 0.1
 * ============================================================================
 * A daemon that performs DNS lookups for the given hostname
 * passed in an HTTP request, with the focus on its implementation
 * using various programming languages. (net/http-boosted impl.)
 * ============================================================================
 * Copyright (C) 2017-2020 Radislav (Radicchio) Golubtsov
 *
 * (See the LICENSE file at the top of the source tree.)
 */

package main

import (
    "fmt"
    "log/syslog"
)

// Helper constants.
const (
    _EXIT_FAILURE     int    =    1 //    Failing exit status.
    _EXIT_SUCCESS     int    =    0 // Successful exit status.
    _EMPTY_STRING     string =   ""
    _COMMA_SPACE_SEP  string = ", "
    _NEW_LINE         string = "\n"
    _AMPER            string =  "&"
    _ONE_SPACE_STRING string =  " "
    _PRINT_BANNER_OPT string = "-V"
    _COLON            string =  ":"
)

// Common error messages.
const (
    _ERR_PREFIX                    string = "error"
    _ERR_PORT_MUST_BE_POSITIVE_INT string = ": <port_number> must be "   +
                                            "a positive integer value, " +
                                            "in the range 1024-49151."
    _ERR_CANNOT_START_SERVER       string = ": FATAL: Cannot start server "
    _ERR_SRV_UNKNOWN_REASON        string = "for an unknown reason. Exiting..."
    _ERR_SRV_PORT_IS_IN_USE        string = "due to the port requested " +
                                            "is in use. Exiting..."
    _ERR_ADDR_ALREADY_IN_USE       string = "address already in use"
)

// Print this error message when there are no any args passed.
const (
    _ERR_MUST_BE_ONE_TWO_ARGS_1 string = ": There must be one or two args " +
                                         "passed: "
    _ERR_MUST_BE_ONE_TWO_ARGS_2 string = " args found"
)

// Print this usage info just after any inappropriate input.
const (
    _MSG_USAGE_TEMPLATE_1 string = "Usage: "
    _MSG_USAGE_TEMPLATE_2 string = " <port_number> [-V]"
)

// Constant: The minimum port number allowed.
const _MIN_PORT uint = 1024

// Constant: The maximum port number allowed.
const _MAX_PORT uint = 49151

// Common notification messages.
const _MSG_SERVER_STARTED_1 string = "Server started on port "
const _MSG_SERVER_STARTED_2 string = "=== Hit Ctrl+C to terminate it."

// HTTP request params.
const (
    _PRM_FMT_HTML string = "html"
    _PRM_FMT_JSON string = "json"
)

// HTTP response headers.
const (
    _HDR_CONTENT_TYPE_N      string = "Content-Type"
    _HDR_CONTENT_TYPE_V_HTML string = "text/html; charset=UTF-8"
    _HDR_CONTENT_TYPE_V_JSON string = "application/json"
    _HDR_CACHE_CONTROL_N     string = "Cache-Control"
    _HDR_CACHE_CONTROL_V     string = "no-cache, no-store, must-revalidate"
    _HDR_EXPIRES_N           string = "Expires"
    _HDR_EXPIRES_V           string = "Thu, 01 Dec 1994 16:00:00 GMT"
    _HDR_PRAGMA_N            string = "Pragma"
    _HDR_PRAGMA_V            string = "no-cache"
)

// Response data names.
const (
    _DAT_HOSTNAME_N string = "hostname"
    _DAT_ADDRESS_N  string = "address"
    _DAT_VERSION_N  string = "version"
    _DAT_VERSION_V  string = "IPv"
)

// Daemon name, version, and copyright banners.
const (
    _DMN_NAME        string = "DNS Resolver Daemon (dnsresolvd)"
    _DMN_DESCRIPTION string = "Performs DNS lookups for the given " +
                              "hostname passed in an HTTP request"
    _DMN_VERSION_S__ string = "Version"
    _DMN_VERSION     string = "0.1"
    _DMN_COPYRIGHT__ string = "Copyright (C) 2017-2020"
    _DMN_AUTHOR      string = "Radislav Golubtsov <ragolubtsov@my.com>"
)

// Constant: The default hostname to look up for.
const _DEF_HOSTNAME string = "openbsd.org"

// Helper function. Makes final buffer cleanups, closes streams, etc.
func _cleanups_fixate(log *syslog.Writer) {
    // Closing the system logger.
    log.Close()
}

// Helper function. Draws a horizontal separator banner.
func _separator_draw(banner_text string) {
    i := len(banner_text)

    for { fmt.Printf("%c", '='); i--; if (i == 0) { break } }; fmt.Println()
}

// vim:set nu et ts=4 sw=4:
<commit_msg>net/http/go: Add remaining constants.<commit_after>/*
 * src/go/dnsresolvh.go
 * ============================================================================
 * DNS Resolver Daemon (dnsresolvd). Version 0.1
 * ============================================================================
 * A daemon that performs DNS lookups for the given hostname
 * passed in an HTTP request, with the focus on its implementation
 * using various programming languages. (net/http-boosted impl.)
 * ============================================================================
 * Copyright (C) 2017-2020 Radislav (Radicchio) Golubtsov
 *
 * (See the LICENSE file at the top of the source tree.)
 */

package main

import (
    "fmt"
    "log/syslog"
)

// Helper constants.
const (
    _EXIT_FAILURE     int    =    1 //    Failing exit status.
    _EXIT_SUCCESS     int    =    0 // Successful exit status.
    _EMPTY_STRING     string =   ""
    _COLON_SPACE_SEP  string = ": "
    _COMMA_SPACE_SEP  string = ", "
    _NEW_LINE         string = "\n"
    _AMPER            string =  "&"
    _ONE_SPACE_STRING string =  " "
    _PRINT_BANNER_OPT string = "-V"
    _COLON            string =  ":"
)

// Common error messages.
const (
    _ERR_PREFIX                    string = "error"
    _ERR_PORT_MUST_BE_POSITIVE_INT string = ": <port_number> must be "   +
                                            "a positive integer value, " +
                                            "in the range 1024-49151."
    _ERR_CANNOT_START_SERVER       string = ": FATAL: Cannot start server "
    _ERR_SRV_UNKNOWN_REASON        string = "for an unknown reason. Exiting..."
    _ERR_SRV_PORT_IS_IN_USE        string = "due to the port requested " +
                                            "is in use. Exiting..."
    _ERR_COULD_NOT_LOOKUP          string = "could not lookup hostname"
    _ERR_ADDR_ALREADY_IN_USE       string = "address already in use"
)

// Print this error message when there are no any args passed.
const (
    _ERR_MUST_BE_ONE_TWO_ARGS_1 string = ": There must be one or two args " +
                                         "passed: "
    _ERR_MUST_BE_ONE_TWO_ARGS_2 string = " args found"
)

// Print this usage info just after any inappropriate input.
const (
    _MSG_USAGE_TEMPLATE_1 string = "Usage: "
    _MSG_USAGE_TEMPLATE_2 string = " <port_number> [-V]"
)

// Constant: The minimum port number allowed.
const _MIN_PORT uint = 1024

// Constant: The maximum port number allowed.
const _MAX_PORT uint = 49151

// Common notification messages.
const _MSG_SERVER_STARTED_1 string = "Server started on port "
const _MSG_SERVER_STARTED_2 string = "=== Hit Ctrl+C to terminate it."

// HTTP request params.
const (
    _PRM_FMT_HTML string = "html"
    _PRM_FMT_JSON string = "json"
)

// HTTP response headers.
const (
    _HDR_CONTENT_TYPE_N      string = "Content-Type"
    _HDR_CONTENT_TYPE_V_HTML string = "text/html; charset=UTF-8"
    _HDR_CONTENT_TYPE_V_JSON string = "application/json"
    _HDR_CACHE_CONTROL_N     string = "Cache-Control"
    _HDR_CACHE_CONTROL_V     string = "no-cache, no-store, must-revalidate"
    _HDR_EXPIRES_N           string = "Expires"
    _HDR_EXPIRES_V           string = "Thu, 01 Dec 1994 16:00:00 GMT"
    _HDR_PRAGMA_N            string = "Pragma"
    _HDR_PRAGMA_V            string = "no-cache"
)

// Response data names.
const (
    _DAT_HOSTNAME_N string = "hostname"
    _DAT_ADDRESS_N  string = "address"
    _DAT_VERSION_N  string = "version"
    _DAT_VERSION_V  string = "IPv"
)

// Daemon name, version, and copyright banners.
const (
    _DMN_NAME        string = "DNS Resolver Daemon (dnsresolvd)"
    _DMN_DESCRIPTION string = "Performs DNS lookups for the given " +
                              "hostname passed in an HTTP request"
    _DMN_VERSION_S__ string = "Version"
    _DMN_VERSION     string = "0.1"
    _DMN_COPYRIGHT__ string = "Copyright (C) 2017-2020"
    _DMN_AUTHOR      string = "Radislav Golubtsov <ragolubtsov@my.com>"
)

// Constant: The default hostname to look up for.
const _DEF_HOSTNAME string = "openbsd.org"

// Helper function. Makes final buffer cleanups, closes streams, etc.
func _cleanups_fixate(log *syslog.Writer) {
    // Closing the system logger.
    log.Close()
}

// Helper function. Draws a horizontal separator banner.
func _separator_draw(banner_text string) {
    i := len(banner_text)

    for { fmt.Printf("%c", '='); i--; if (i == 0) { break } }; fmt.Println()
}

// vim:set nu et ts=4 sw=4:
<|endoftext|>


<commit_before>package gossip

import (
	"encoding/gob"
	"errors"
	. "gossip/message"
	. "gossip/node"
	. "gossip/node_list"
	. "gossip/registry"
	"gossip/util"
	"net/http"
	"net/rpc"
)

var registry *Registry
var seq uint64

// Start up the RPC Server
func server(registry *Registry, port int) error {
	rpc.Register(registry)
	rpc.HandleHTTP()
  return http.ListenAndServe(util.Address("", port), nil)
}

// Fetch the initial registry from the address
func connect(registry *Registry, address string) error {
	client, err := rpc.DialHTTP("tcp", address)
	if err != nil {
		return err
	}

	var reply *NodeList
	err = client.Call("Registry.Query", "", &reply)
	if err != nil {
		return err
	}

	MergeRegistries(registry, reply)
	return nil
}

func client(registry *Registry, seeds []string, port int) error {
	// Get the registries from each of the seeds
  failed := 0
	for _, seed := range seeds {
    if seed != "" {
      if connect(registry, seed) != nil {
        failed++
      }
    }
	}

  // If we couldn't connect to any seeds
  if failed >= len(seeds) {
    return errors.New("Unable to connect to any seed nodes")
  }

	// Announce yourself on the network
	var reply int
	seq++
	message := &Message{
		Origin:        registry.Self,
		Seq:           seq,
		ServiceMethod: "Registry.AddNode",
		Args:          registry.Self,
	}
	gob.Register(registry.Self)
	return registry.Announce(message, &reply)
}

func Start(name string, hostname string, seeds []string, port int) (chan []byte, error) {
	address := util.Address(hostname, port)
	registry = NewRegistry(name)
	registry.Self = &Node{Name: name, Address: address}

  go server(registry, port)
  err := client(registry, seeds, port)
  if err != nil {
    return nil, err
  }

	return registry.Data, nil
}

func Broadcast(data []byte) {
	var reply int
	seq++
	message := &Message{
		Origin:        registry.Self,
		Seq:           seq,
		ServiceMethod: "Registry.Data",
		Args:          data,
	}
	gob.Register(registry.Self)
	registry.Announce(message, &reply)
}
<commit_msg>Fmting<commit_after>package gossip

import (
	"encoding/gob"
	"errors"
	. "gossip/message"
	. "gossip/node"
	. "gossip/node_list"
	. "gossip/registry"
	"gossip/util"
	"net/http"
	"net/rpc"
)

var registry *Registry
var seq uint64

// Start up the RPC Server
func server(registry *Registry, port int) error {
	rpc.Register(registry)
	rpc.HandleHTTP()
	return http.ListenAndServe(util.Address("", port), nil)
}

// Fetch the initial registry from the address
func connect(registry *Registry, address string) error {
	client, err := rpc.DialHTTP("tcp", address)
	if err != nil {
		return err
	}

	var reply *NodeList
	err = client.Call("Registry.Query", "", &reply)
	if err != nil {
		return err
	}

	MergeRegistries(registry, reply)
	return nil
}

func client(registry *Registry, seeds []string, port int) error {
	// Get the registries from each of the seeds
	failed := 0
	for _, seed := range seeds {
		if seed != "" {
			if connect(registry, seed) != nil {
				failed++
			}
		}
	}

	// If we couldn't connect to any seeds
	if failed >= len(seeds) {
		return errors.New("Unable to connect to any seed nodes")
	}

	// Announce yourself on the network
	var reply int
	seq++
	message := &Message{
		Origin:        registry.Self,
		Seq:           seq,
		ServiceMethod: "Registry.AddNode",
		Args:          registry.Self,
	}
	gob.Register(registry.Self)
	return registry.Announce(message, &reply)
}

func Start(name string, hostname string, seeds []string, port int) (chan []byte, error) {
	address := util.Address(hostname, port)
	registry = NewRegistry(name)
	registry.Self = &Node{Name: name, Address: address}

	go server(registry, port)
	err := client(registry, seeds, port)
	if err != nil {
		return nil, err
	}

	return registry.Data, nil
}

func Broadcast(data []byte) {
	var reply int
	seq++
	message := &Message{
		Origin:        registry.Self,
		Seq:           seq,
		ServiceMethod: "Registry.Data",
		Args:          data,
	}
	gob.Register(registry.Self)
	registry.Announce(message, &reply)
}
<|endoftext|>