<commit_before>package ilium

import "fmt"
import "math/rand"

type ParticleTracerPathType int

const (
	PARTICLE_TRACER_EMITTED_W_PATH     ParticleTracerPathType = 1 << iota
	PARTICLE_TRACER_DIRECT_SENSOR_PATH ParticleTracerPathType = 1 << iota
)

type ParticleTracerRRContribution int

const (
	PARTICLE_TRACER_RR_ALPHA  ParticleTracerRRContribution = iota
	PARTICLE_TRACER_RR_ALBEDO ParticleTracerRRContribution = iota
)

type ParticleDebugRecord struct {
	tag string
	s   Spectrum
}

type ParticleRecord struct {
	sensor       Sensor
	x, y         int
	_WeLiDivPdf  Spectrum
	debugRecords []ParticleDebugRecord
}

func (pr *ParticleRecord) Accumulate() {
	pr.sensor.AccumulateLightContribution(pr.x, pr.y, pr._WeLiDivPdf)
	for _, debugRecord := range pr.debugRecords {
		pr.sensor.AccumulateLightDebugInfo(
			debugRecord.tag, pr.x, pr.y, debugRecord.s)
	}
}

type ParticleTracer struct {
	pathTypes                   ParticleTracerPathType
	russianRouletteContribution ParticleTracerRRContribution
	russianRouletteState        *RussianRouletteState
	maxEdgeCount                int
	debugLevel                  int
	debugMaxEdgeCount           int
}

func (pt *ParticleTracer) InitializeParticleTracer(
	pathTypes ParticleTracerPathType,
	russianRouletteContribution ParticleTracerRRContribution,
	russianRouletteState *RussianRouletteState,
	maxEdgeCount, debugLevel, debugMaxEdgeCount int) {
	pt.pathTypes = pathTypes
	pt.russianRouletteContribution = russianRouletteContribution
	pt.russianRouletteState = russianRouletteState
	pt.maxEdgeCount = maxEdgeCount
	pt.debugLevel = debugLevel
	pt.debugMaxEdgeCount = debugMaxEdgeCount
}

func (pt *ParticleTracer) hasSomethingToDo() bool {
	if pt.maxEdgeCount <= 0 {
		return false
	}

	if (pt.pathTypes & PARTICLE_TRACER_EMITTED_W_PATH) != 0 {
		return true
	}

	if (pt.pathTypes & PARTICLE_TRACER_DIRECT_SENSOR_PATH) != 0 {
		return true
	}

	return false
}

func (pt *ParticleTracer) GetSampleConfig(sensors []Sensor) SampleConfig {
	if !pt.hasSomethingToDo() {
		return SampleConfig{}
	}

	// maxVertexCount = maxEdgeCount + 1, and there are two
	// non-interior vertices (or one in the degenerate case).
	maxInteriorVertexCount := maxInt(0, pt.maxEdgeCount-1)
	// Sample wi for each interior vertex to build the next edge
	// of the path.
	numWiSamples := minInt(3, maxInteriorVertexCount)
	sample1DLengths := []int{
		// One to pick the light.
		1,
	}
	sample2DLengths := []int{numWiSamples}

	if (pt.pathTypes & PARTICLE_TRACER_DIRECT_SENSOR_PATH) != 0 {
		// Do direct sensor sampling for the first vertex and
		// each interior vertex; don't do it from the last
		// vertex since that would add an extra edge.
		numDirectSensorSamples := minInt(3, maxInteriorVertexCount+1)
		// Generates samples for direct sampling for all
		// sensors, even though some of them may not be able
		// to use direct sensor sampling (due to having a
		// specular direction).
		directSensorSampleLengths := make([]int, len(sensors))
		for i := 0; i < len(directSensorSampleLengths); i++ {
			directSensorSampleLengths[i] = numDirectSensorSamples
		}
		sample1DLengths = append(
			sample1DLengths, directSensorSampleLengths...)
		sample2DLengths = append(
			sample2DLengths, directSensorSampleLengths...)
	}

	return SampleConfig{
		Sample1DLengths: sample1DLengths,
		Sample2DLengths: sample2DLengths,
	}
}

func (pt *ParticleTracer) makeWWeAlphaDebugRecords(
	edgeCount int, sensor Sensor, w float32, wWeAlpha, f1, f2 *Spectrum,
	f1Name, f2Name string) []ParticleDebugRecord {
	var debugRecords []ParticleDebugRecord
	if pt.debugLevel >= 1 {
		width := widthInt(pt.debugMaxEdgeCount)
		var tagSuffix string
		if edgeCount <= pt.debugMaxEdgeCount {
			tagSuffix = fmt.Sprintf("%0*d", width, edgeCount)
		} else {
			tagSuffix = fmt.Sprintf(
				"%0*d-%0*d", width, pt.debugMaxEdgeCount+1,
				width, pt.maxEdgeCount)
		}

		debugRecord := ParticleDebugRecord{
			tag: "wWA" + tagSuffix,
			s:   *wWeAlpha,
		}
		debugRecords = append(debugRecords, debugRecord)

		if pt.debugLevel >= 2 {
			f1DebugRecord := ParticleDebugRecord{
				tag: f1Name + tagSuffix,
				s:   *f1,
			}

			// Scale f2 by the pixel count so that it
			// becomes visible. (Assume that this scaling
			// factor is normally part of f1.)
			//
			// TODO(akalin): Remove this once we use
			// output formats with better range.
			sensorExtent := sensor.GetExtent()
			scale := sensorExtent.GetPixelCount()
			var scaledF2 Spectrum
			scaledF2.Scale(f2, float32(scale))
			f2DebugRecord := ParticleDebugRecord{
				tag: f2Name + tagSuffix,
				s:   scaledF2,
			}

			debugRecords = append(
				debugRecords, f1DebugRecord, f2DebugRecord)
		}
	}
	return debugRecords
}

func (pt *ParticleTracer) computeEmittedImportance(
	edgeCount int, alpha *Spectrum, wo Vector3, intersection *Intersection,
	records []ParticleRecord) []ParticleRecord {
	for _, sensor := range intersection.Sensors {
		x, y, We := sensor.ComputePixelPositionAndWe(
			intersection.P, intersection.N, wo)

		if !We.IsValid() {
			fmt.Printf("Invalid We %v returned for "+
				"intersection %v and wo %v and sensor %v\n",
				We, intersection, wo, sensor)
			continue
		}

		if We.IsBlack() {
			continue
		}

		// TODO(akalin): Implement multiple importance sampling.
		var invW float32 = 1
		if (pt.pathTypes&PARTICLE_TRACER_DIRECT_SENSOR_PATH) != 0 &&
			!sensor.HasSpecularDirection() {
			invW++
		}
		w := 1 / invW

		var wWe Spectrum
		wWe.Scale(&We, w)

		var wWeAlpha Spectrum
		wWeAlpha.Mul(&wWe, alpha)
		debugRecords := pt.makeWWeAlphaDebugRecords(
			edgeCount, sensor, w, &wWeAlpha, &We, alpha, "We", "Ae")
		particleRecord := ParticleRecord{
			sensor,
			x,
			y,
			wWeAlpha,
			debugRecords,
		}
		records = append(records, particleRecord)
	}
	return records
}

// This implements the sensor equivalent of direct lighting sampling.
func (pt *ParticleTracer) directSampleSensors(
	currentEdgeCount int, rng *rand.Rand, scene *Scene, sensors []Sensor,
	tracerBundle SampleBundle, alpha *Spectrum, p Point3,
	pEpsilon float32, n Normal3, wo Vector3, material Material,
	records []ParticleRecord) []ParticleRecord {
	directSensor1DSamples := tracerBundle.Samples1D[1:]
	directSensor2DSamples := tracerBundle.Samples2D[1:]

	sampleIndex := currentEdgeCount
	for i, sensor := range sensors {
		if sensor.HasSpecularDirection() {
			continue
		}

		u := directSensor1DSamples[i].GetSample(sampleIndex, rng)
		v := directSensor2DSamples[i].GetSample(sampleIndex, rng)
		x, y, WeDivPdf, wi, shadowRay :=
			sensor.SamplePixelPositionAndWeFromPoint(
				u.U, v.U1, v.U2, p, pEpsilon, n)

		if !WeDivPdf.IsValid() {
			fmt.Printf("Invalid WeDivPdf %v returned for "+
				"point %v and sensor %v\n",
				WeDivPdf, p, sensor)
			continue
		}

		if WeDivPdf.IsBlack() {
			continue
		}

		if scene.Aggregate.Intersect(&shadowRay, nil) {
			continue
		}

		f := material.ComputeF(MATERIAL_IMPORTANCE_TRANSPORT, wo, wi, n)

		if f.IsBlack() {
			continue
		}

		sensorEdgeCount := currentEdgeCount + 1

		// TODO(akalin): Implement multiple importance sampling.
		var invW float32 = 1
		if (pt.pathTypes&PARTICLE_TRACER_EMITTED_W_PATH) != 0 &&
			!sensor.HasSpecularPosition() {
			invW++
		}
		w := 1 / invW

		var wWeDivPdf Spectrum
		wWeDivPdf.Scale(&WeDivPdf, w)

		var fAlpha Spectrum
		fAlpha.Mul(&f, alpha)

		var wWeAlphaNext Spectrum
		wWeAlphaNext.Mul(&wWeDivPdf, &fAlpha)
		debugRecords := pt.makeWWeAlphaDebugRecords(
			sensorEdgeCount, sensor, w, &wWeAlphaNext, &WeDivPdf,
			&fAlpha, "Wd", "Ad")
		particleRecord := ParticleRecord{
			sensor,
			x,
			y,
			wWeAlphaNext,
			debugRecords,
		}
		records = append(records, particleRecord)
	}
	return records
}

// A wrapper that implements the Material interface in terms of Light
// functions.
type lightMaterial struct {
	light    Light
	pSurface Point3
}

func (lm *lightMaterial) SampleWi(transportType MaterialTransportType,
	u1, u2 float32, wo Vector3, n Normal3) (
	wi Vector3, fDivPdf Spectrum, pdf float32) {
	panic("called unexpectedly")
}

func (lm *lightMaterial) ComputeF(transportType MaterialTransportType,
	wo, wi Vector3, n Normal3) Spectrum {
	return lm.light.ComputeLeDirectional(lm.pSurface, n, wi)
}

func (lm *lightMaterial) ComputePdf(transportType MaterialTransportType,
	wo, wi Vector3, n Normal3) float32 {
	panic("called unexpectedly")
}

func (pt *ParticleTracer) SampleLightPath(
	rng *rand.Rand, scene *Scene, sensors []Sensor,
	lightBundle, tracerBundle SampleBundle) []ParticleRecord {
	if !pt.hasSomethingToDo() {
		return []ParticleRecord{}
	}

	if len(scene.Lights) == 0 {
		return []ParticleRecord{}
	}

	u := tracerBundle.Samples1D[0][0]
	light, pChooseLight := scene.SampleLight(u.U)

	var edgeCount int
	var ray Ray
	// alpha = Le * T(path) / pdf.
	var alpha Spectrum
	var albedo Spectrum
	var records []ParticleRecord

	if pt.pathTypes == PARTICLE_TRACER_EMITTED_W_PATH {
		// No need to sample the spatial and directional
		// components separately.
		initialRay, LeDivPdf := light.SampleRay(lightBundle)
		if LeDivPdf.IsBlack() {
			return records
		}

		LeDivPdf.ScaleInv(&LeDivPdf, pChooseLight)
		ray = initialRay
		alpha = LeDivPdf
		albedo = LeDivPdf
	} else if (pt.pathTypes & PARTICLE_TRACER_DIRECT_SENSOR_PATH) != 0 {
		pSurface, pSurfaceEpsilon, nSurface, LeSpatialDivPdf :=
			light.SampleSurface(lightBundle)
		if LeSpatialDivPdf.IsBlack() {
			return records
		}

		LeSpatialDivPdf.ScaleInv(&LeSpatialDivPdf, pChooseLight)
		alpha = LeSpatialDivPdf

		records = pt.directSampleSensors(
			edgeCount, rng, scene, sensors, tracerBundle,
			&alpha, pSurface, pSurfaceEpsilon, nSurface,
			Vector3{}, &lightMaterial{light, pSurface}, records)

		wo, LeDirectionalDivPdf := light.SampleDirection(
			lightBundle, pSurface, nSurface)
		if LeDirectionalDivPdf.IsBlack() {
			return records
		}

		ray = Ray{pSurface, wo, pSurfaceEpsilon, infFloat32(+1)}
		alpha.Mul(&alpha, &LeDirectionalDivPdf)
		albedo = alpha
	}

	wiSamples := tracerBundle.Samples2D[0]
	var t *Spectrum
	switch pt.russianRouletteContribution {
	case PARTICLE_TRACER_RR_ALPHA:
		t = &alpha
	case PARTICLE_TRACER_RR_ALBEDO:
		t = &albedo
	}
	for {
		pContinue := pt.russianRouletteState.GetContinueProbability(
			edgeCount, t)
		if pContinue <= 0 {
			break
		}
		if pContinue < 1 {
			if randFloat32(rng) > pContinue {
				break
			}
			alpha.ScaleInv(&alpha, pContinue)
		}
		var intersection Intersection
		if !scene.Aggregate.Intersect(&ray, &intersection) {
			break
		}
		// The new edge is between ray.O and intersection.P.
		edgeCount++

		var wo Vector3
		wo.Flip(&ray.D)

		if (pt.pathTypes & PARTICLE_TRACER_EMITTED_W_PATH) != 0 {
			records = pt.computeEmittedImportance(
				edgeCount, &alpha, wo, &intersection,
				records)
		}

		if edgeCount >= pt.maxEdgeCount {
			break
		}

		p := intersection.P
		pEpsilon := intersection.PEpsilon
		n := intersection.N
		material := intersection.Material

		// Don't direct-sample sensors for the last edge,
		// since the process adds an extra edge.
		if (pt.pathTypes & PARTICLE_TRACER_DIRECT_SENSOR_PATH) != 0 {
			records = pt.directSampleSensors(
				edgeCount, rng, scene, sensors, tracerBundle,
				&alpha, p, pEpsilon, n, wo, material, records)
		}

		sampleIndex := edgeCount - 1
		u := wiSamples.GetSample(sampleIndex, rng)
		wi, fDivPdf, pdf := material.SampleWi(
			MATERIAL_IMPORTANCE_TRANSPORT, u.U1, u.U2, wo, n)
		if fDivPdf.IsBlack() || pdf == 0 {
			break
		}
		if !fDivPdf.IsValid() {
			fmt.Printf("Invalid fDivPdf %v returned for "+
				"intersection %v and wo %v\n",
				fDivPdf, intersection, wo)
			break
		}

		ray = Ray{p, wi, pEpsilon, infFloat32(+1)}
		alpha.Mul(&alpha, &fDivPdf)
		albedo = fDivPdf
	}

	return records
}
<commit_msg>Emit more debug info in ParticleTracer<commit_after>package ilium

import "fmt"
import "math/rand"

type ParticleTracerPathType int

const (
	PARTICLE_TRACER_EMITTED_W_PATH     ParticleTracerPathType = 1 << iota
	PARTICLE_TRACER_DIRECT_SENSOR_PATH ParticleTracerPathType = 1 << iota
)

type ParticleTracerRRContribution int

const (
	PARTICLE_TRACER_RR_ALPHA  ParticleTracerRRContribution = iota
	PARTICLE_TRACER_RR_ALBEDO ParticleTracerRRContribution = iota
)

type ParticleDebugRecord struct {
	tag string
	s   Spectrum
}

type ParticleRecord struct {
	sensor       Sensor
	x, y         int
	_WeLiDivPdf  Spectrum
	debugRecords []ParticleDebugRecord
}

func (pr *ParticleRecord) Accumulate() {
	pr.sensor.AccumulateLightContribution(pr.x, pr.y, pr._WeLiDivPdf)
	for _, debugRecord := range pr.debugRecords {
		pr.sensor.AccumulateLightDebugInfo(
			debugRecord.tag, pr.x, pr.y, debugRecord.s)
	}
}

type ParticleTracer struct {
	pathTypes                   ParticleTracerPathType
	russianRouletteContribution ParticleTracerRRContribution
	russianRouletteState        *RussianRouletteState
	maxEdgeCount                int
	debugLevel                  int
	debugMaxEdgeCount           int
}

func (pt *ParticleTracer) InitializeParticleTracer(
	pathTypes ParticleTracerPathType,
	russianRouletteContribution ParticleTracerRRContribution,
	russianRouletteState *RussianRouletteState,
	maxEdgeCount, debugLevel, debugMaxEdgeCount int) {
	pt.pathTypes = pathTypes
	pt.russianRouletteContribution = russianRouletteContribution
	pt.russianRouletteState = russianRouletteState
	pt.maxEdgeCount = maxEdgeCount
	pt.debugLevel = debugLevel
	pt.debugMaxEdgeCount = debugMaxEdgeCount
}

func (pt *ParticleTracer) hasSomethingToDo() bool {
	if pt.maxEdgeCount <= 0 {
		return false
	}

	if (pt.pathTypes & PARTICLE_TRACER_EMITTED_W_PATH) != 0 {
		return true
	}

	if (pt.pathTypes & PARTICLE_TRACER_DIRECT_SENSOR_PATH) != 0 {
		return true
	}

	return false
}

func (pt *ParticleTracer) GetSampleConfig(sensors []Sensor) SampleConfig {
	if !pt.hasSomethingToDo() {
		return SampleConfig{}
	}

	// maxVertexCount = maxEdgeCount + 1, and there are two
	// non-interior vertices (or one in the degenerate case).
	maxInteriorVertexCount := maxInt(0, pt.maxEdgeCount-1)
	// Sample wi for each interior vertex to build the next edge
	// of the path.
	numWiSamples := minInt(3, maxInteriorVertexCount)
	sample1DLengths := []int{
		// One to pick the light.
		1,
	}
	sample2DLengths := []int{numWiSamples}

	if (pt.pathTypes & PARTICLE_TRACER_DIRECT_SENSOR_PATH) != 0 {
		// Do direct sensor sampling for the first vertex and
		// each interior vertex; don't do it from the last
		// vertex since that would add an extra edge.
		numDirectSensorSamples := minInt(3, maxInteriorVertexCount+1)
		// Generates samples for direct sampling for all
		// sensors, even though some of them may not be able
		// to use direct sensor sampling (due to having a
		// specular direction).
		directSensorSampleLengths := make([]int, len(sensors))
		for i := 0; i < len(directSensorSampleLengths); i++ {
			directSensorSampleLengths[i] = numDirectSensorSamples
		}
		sample1DLengths = append(
			sample1DLengths, directSensorSampleLengths...)
		sample2DLengths = append(
			sample2DLengths, directSensorSampleLengths...)
	}

	return SampleConfig{
		Sample1DLengths: sample1DLengths,
		Sample2DLengths: sample2DLengths,
	}
}

func (pt *ParticleTracer) makeWWeAlphaDebugRecords(
	edgeCount int, sensor Sensor, w float32, wWeAlpha, f1, f2 *Spectrum,
	f1Name, f2Name string) []ParticleDebugRecord {
	var debugRecords []ParticleDebugRecord
	if pt.debugLevel >= 1 {
		width := widthInt(pt.debugMaxEdgeCount)

		var f1F2 Spectrum
		f1F2.Mul(f1, f2)

		f1F2TotalDebugRecord := ParticleDebugRecord{
			tag: f1Name + f2Name,
			s:   f1F2,
		}

		wF1F2TotalDebugRecord := ParticleDebugRecord{
			tag: "w" + f1Name + f2Name,
			s:   *wWeAlpha,
		}

		debugRecords = append(debugRecords,
			f1F2TotalDebugRecord, wF1F2TotalDebugRecord)

		var tagSuffix string
		if edgeCount <= pt.debugMaxEdgeCount {
			tagSuffix = fmt.Sprintf("%0*d", width, edgeCount)
		} else {
			tagSuffix = fmt.Sprintf(
				"%0*d-%0*d", width, pt.debugMaxEdgeCount+1,
				width, pt.maxEdgeCount)
		}

		if pt.debugLevel >= 2 {
			wWeAlphaDebugRecord := ParticleDebugRecord{
				tag: "wWA" + tagSuffix,
				s:   *wWeAlpha,
			}

			f1F2DebugRecord := ParticleDebugRecord{
				tag: f1Name + f2Name + tagSuffix,
				s:   f1F2,
			}

			wF1F2DebugRecord := ParticleDebugRecord{
				tag: "w" + f1Name + f2Name + tagSuffix,
				s:   *wWeAlpha,
			}

			debugRecords = append(debugRecords,
				wWeAlphaDebugRecord, f1F2DebugRecord,
				wF1F2DebugRecord)
		}

		if pt.debugLevel >= 3 {
			f1DebugRecord := ParticleDebugRecord{
				tag: f1Name + tagSuffix,
				s:   *f1,
			}

			// Scale f2 by the pixel count so that it
			// becomes visible. (Assume that this scaling
			// factor is normally part of f1.)
			//
			// TODO(akalin): Remove this once we use
			// output formats with better range.
			sensorExtent := sensor.GetExtent()
			scale := sensorExtent.GetPixelCount()
			var scaledF2 Spectrum
			scaledF2.Scale(f2, float32(scale))
			f2DebugRecord := ParticleDebugRecord{
				tag: f2Name + tagSuffix,
				s:   scaledF2,
			}

			debugRecords = append(
				debugRecords, f1DebugRecord, f2DebugRecord)
		}
	}
	return debugRecords
}

func (pt *ParticleTracer) computeEmittedImportance(
	edgeCount int, alpha *Spectrum, wo Vector3, intersection *Intersection,
	records []ParticleRecord) []ParticleRecord {
	for _, sensor := range intersection.Sensors {
		x, y, We := sensor.ComputePixelPositionAndWe(
			intersection.P, intersection.N, wo)

		if !We.IsValid() {
			fmt.Printf("Invalid We %v returned for "+
				"intersection %v and wo %v and sensor %v\n",
				We, intersection, wo, sensor)
			continue
		}

		if We.IsBlack() {
			continue
		}

		// TODO(akalin): Implement multiple importance sampling.
		var invW float32 = 1
		if (pt.pathTypes&PARTICLE_TRACER_DIRECT_SENSOR_PATH) != 0 &&
			!sensor.HasSpecularDirection() {
			invW++
		}
		w := 1 / invW

		var wWe Spectrum
		wWe.Scale(&We, w)

		var wWeAlpha Spectrum
		wWeAlpha.Mul(&wWe, alpha)
		debugRecords := pt.makeWWeAlphaDebugRecords(
			edgeCount, sensor, w, &wWeAlpha, &We, alpha, "We", "Ae")
		particleRecord := ParticleRecord{
			sensor,
			x,
			y,
			wWeAlpha,
			debugRecords,
		}
		records = append(records, particleRecord)
	}
	return records
}

// This implements the sensor equivalent of direct lighting sampling.
func (pt *ParticleTracer) directSampleSensors(
	currentEdgeCount int, rng *rand.Rand, scene *Scene, sensors []Sensor,
	tracerBundle SampleBundle, alpha *Spectrum, p Point3,
	pEpsilon float32, n Normal3, wo Vector3, material Material,
	records []ParticleRecord) []ParticleRecord {
	directSensor1DSamples := tracerBundle.Samples1D[1:]
	directSensor2DSamples := tracerBundle.Samples2D[1:]

	sampleIndex := currentEdgeCount
	for i, sensor := range sensors {
		if sensor.HasSpecularDirection() {
			continue
		}

		u := directSensor1DSamples[i].GetSample(sampleIndex, rng)
		v := directSensor2DSamples[i].GetSample(sampleIndex, rng)
		x, y, WeDivPdf, wi, shadowRay :=
			sensor.SamplePixelPositionAndWeFromPoint(
				u.U, v.U1, v.U2, p, pEpsilon, n)

		if !WeDivPdf.IsValid() {
			fmt.Printf("Invalid WeDivPdf %v returned for "+
				"point %v and sensor %v\n",
				WeDivPdf, p, sensor)
			continue
		}

		if WeDivPdf.IsBlack() {
			continue
		}

		if scene.Aggregate.Intersect(&shadowRay, nil) {
			continue
		}

		f := material.ComputeF(MATERIAL_IMPORTANCE_TRANSPORT, wo, wi, n)

		if f.IsBlack() {
			continue
		}

		sensorEdgeCount := currentEdgeCount + 1

		// TODO(akalin): Implement multiple importance sampling.
		var invW float32 = 1
		if (pt.pathTypes&PARTICLE_TRACER_EMITTED_W_PATH) != 0 &&
			!sensor.HasSpecularPosition() {
			invW++
		}
		w := 1 / invW

		var wWeDivPdf Spectrum
		wWeDivPdf.Scale(&WeDivPdf, w)

		var fAlpha Spectrum
		fAlpha.Mul(&f, alpha)

		var wWeAlphaNext Spectrum
		wWeAlphaNext.Mul(&wWeDivPdf, &fAlpha)
		debugRecords := pt.makeWWeAlphaDebugRecords(
			sensorEdgeCount, sensor, w, &wWeAlphaNext, &WeDivPdf,
			&fAlpha, "Wd", "Ad")
		particleRecord := ParticleRecord{
			sensor,
			x,
			y,
			wWeAlphaNext,
			debugRecords,
		}
		records = append(records, particleRecord)
	}
	return records
}

// A wrapper that implements the Material interface in terms of Light
// functions.
type lightMaterial struct {
	light    Light
	pSurface Point3
}

func (lm *lightMaterial) SampleWi(transportType MaterialTransportType,
	u1, u2 float32, wo Vector3, n Normal3) (
	wi Vector3, fDivPdf Spectrum, pdf float32) {
	panic("called unexpectedly")
}

func (lm *lightMaterial) ComputeF(transportType MaterialTransportType,
	wo, wi Vector3, n Normal3) Spectrum {
	return lm.light.ComputeLeDirectional(lm.pSurface, n, wi)
}

func (lm *lightMaterial) ComputePdf(transportType MaterialTransportType,
	wo, wi Vector3, n Normal3) float32 {
	panic("called unexpectedly")
}

func (pt *ParticleTracer) SampleLightPath(
	rng *rand.Rand, scene *Scene, sensors []Sensor,
	lightBundle, tracerBundle SampleBundle) []ParticleRecord {
	if !pt.hasSomethingToDo() {
		return []ParticleRecord{}
	}

	if len(scene.Lights) == 0 {
		return []ParticleRecord{}
	}

	u := tracerBundle.Samples1D[0][0]
	light, pChooseLight := scene.SampleLight(u.U)

	var edgeCount int
	var ray Ray
	// alpha = Le * T(path) / pdf.
	var alpha Spectrum
	var albedo Spectrum
	var records []ParticleRecord

	if pt.pathTypes == PARTICLE_TRACER_EMITTED_W_PATH {
		// No need to sample the spatial and directional
		// components separately.
		initialRay, LeDivPdf := light.SampleRay(lightBundle)
		if LeDivPdf.IsBlack() {
			return records
		}

		LeDivPdf.ScaleInv(&LeDivPdf, pChooseLight)
		ray = initialRay
		alpha = LeDivPdf
		albedo = LeDivPdf
	} else if (pt.pathTypes & PARTICLE_TRACER_DIRECT_SENSOR_PATH) != 0 {
		pSurface, pSurfaceEpsilon, nSurface, LeSpatialDivPdf :=
			light.SampleSurface(lightBundle)
		if LeSpatialDivPdf.IsBlack() {
			return records
		}

		LeSpatialDivPdf.ScaleInv(&LeSpatialDivPdf, pChooseLight)
		alpha = LeSpatialDivPdf

		records = pt.directSampleSensors(
			edgeCount, rng, scene, sensors, tracerBundle,
			&alpha, pSurface, pSurfaceEpsilon, nSurface,
			Vector3{}, &lightMaterial{light, pSurface}, records)

		wo, LeDirectionalDivPdf := light.SampleDirection(
			lightBundle, pSurface, nSurface)
		if LeDirectionalDivPdf.IsBlack() {
			return records
		}

		ray = Ray{pSurface, wo, pSurfaceEpsilon, infFloat32(+1)}
		alpha.Mul(&alpha, &LeDirectionalDivPdf)
		albedo = alpha
	}

	wiSamples := tracerBundle.Samples2D[0]
	var t *Spectrum
	switch pt.russianRouletteContribution {
	case PARTICLE_TRACER_RR_ALPHA:
		t = &alpha
	case PARTICLE_TRACER_RR_ALBEDO:
		t = &albedo
	}
	for {
		pContinue := pt.russianRouletteState.GetContinueProbability(
			edgeCount, t)
		if pContinue <= 0 {
			break
		}
		if pContinue < 1 {
			if randFloat32(rng) > pContinue {
				break
			}
			alpha.ScaleInv(&alpha, pContinue)
		}
		var intersection Intersection
		if !scene.Aggregate.Intersect(&ray, &intersection) {
			break
		}
		// The new edge is between ray.O and intersection.P.
		edgeCount++

		var wo Vector3
		wo.Flip(&ray.D)

		if (pt.pathTypes & PARTICLE_TRACER_EMITTED_W_PATH) != 0 {
			records = pt.computeEmittedImportance(
				edgeCount, &alpha, wo, &intersection,
				records)
		}

		if edgeCount >= pt.maxEdgeCount {
			break
		}

		p := intersection.P
		pEpsilon := intersection.PEpsilon
		n := intersection.N
		material := intersection.Material

		// Don't direct-sample sensors for the last edge,
		// since the process adds an extra edge.
		if (pt.pathTypes & PARTICLE_TRACER_DIRECT_SENSOR_PATH) != 0 {
			records = pt.directSampleSensors(
				edgeCount, rng, scene, sensors, tracerBundle,
				&alpha, p, pEpsilon, n, wo, material, records)
		}

		sampleIndex := edgeCount - 1
		u := wiSamples.GetSample(sampleIndex, rng)
		wi, fDivPdf, pdf := material.SampleWi(
			MATERIAL_IMPORTANCE_TRANSPORT, u.U1, u.U2, wo, n)
		if fDivPdf.IsBlack() || pdf == 0 {
			break
		}
		if !fDivPdf.IsValid() {
			fmt.Printf("Invalid fDivPdf %v returned for "+
				"intersection %v and wo %v\n",
				fDivPdf, intersection, wo)
			break
		}

		ray = Ray{p, wi, pEpsilon, infFloat32(+1)}
		alpha.Mul(&alpha, &fDivPdf)
		albedo = fDivPdf
	}

	return records
}
<|endoftext|>


<commit_before>package service

import (
	"fmt"
	"io"
	"strings"
	"text/tabwriter"

	"golang.org/x/net/context"

	"github.com/docker/docker/api/client"
	"github.com/docker/docker/cli"
	"github.com/docker/docker/opts"
	"github.com/docker/docker/pkg/stringid"
	"github.com/docker/engine-api/types"
	"github.com/docker/engine-api/types/swarm"
	"github.com/spf13/cobra"
)

const (
	listItemFmt = "%s\t%s\t%s\t%s\t%s\n"
)

type listOptions struct {
	quiet  bool
	filter opts.FilterOpt
}

func newListCommand(dockerCli *client.DockerCli) *cobra.Command {
	opts := listOptions{filter: opts.NewFilterOpt()}

	cmd := &cobra.Command{
		Use:     "ls",
		Aliases: []string{"list"},
		Short:   "List services",
		Args:    cli.NoArgs,
		RunE: func(cmd *cobra.Command, args []string) error {
			return runList(dockerCli, opts)
		},
	}

	flags := cmd.Flags()
	flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Only display IDs")
	flags.VarP(&opts.filter, "filter", "f", "Filter output based on conditions provided")

	return cmd
}

func runList(dockerCli *client.DockerCli, opts listOptions) error {
	client := dockerCli.Client()

	services, err := client.ServiceList(
		context.Background(),
		types.ServiceListOptions{Filter: opts.filter.Value()})
	if err != nil {
		return err
	}

	out := dockerCli.Out()
	if opts.quiet {
		printQuiet(out, services)
	} else {
		printTable(out, services)
	}
	return nil
}

func printTable(out io.Writer, services []swarm.Service) {
	writer := tabwriter.NewWriter(out, 0, 4, 2, ' ', 0)

	// Ignore flushing errors
	defer writer.Flush()

	fmt.Fprintf(writer, listItemFmt, "ID", "NAME", "REPLICAS", "IMAGE", "COMMAND")
	for _, service := range services {
		scale := ""
		if service.Spec.Mode.Replicated != nil && service.Spec.Mode.Replicated.Replicas != nil {
			scale = fmt.Sprintf("%d", *service.Spec.Mode.Replicated.Replicas)
		} else if service.Spec.Mode.Global != nil {
			scale = "global"
		}
		fmt.Fprintf(
			writer,
			listItemFmt,
			stringid.TruncateID(service.ID),
			service.Spec.Name,
			scale,
			service.Spec.TaskTemplate.ContainerSpec.Image,
			strings.Join(service.Spec.TaskTemplate.ContainerSpec.Args, " "))
	}
}

func printQuiet(out io.Writer, services []swarm.Service) {
	for _, service := range services {
		fmt.Fprintln(out, service.ID)
	}
}
<commit_msg>api/client/service: list running services over replicas<commit_after>package service

import (
	"fmt"
	"io"
	"strings"
	"text/tabwriter"

	"github.com/docker/docker/api/client"
	"github.com/docker/docker/cli"
	"github.com/docker/docker/opts"
	"github.com/docker/docker/pkg/stringid"
	"github.com/docker/engine-api/types"
	"github.com/docker/engine-api/types/filters"
	"github.com/docker/engine-api/types/swarm"
	"github.com/spf13/cobra"
	"golang.org/x/net/context"
)

const (
	listItemFmt = "%s\t%s\t%s\t%s\t%s\n"
)

type listOptions struct {
	quiet  bool
	filter opts.FilterOpt
}

func newListCommand(dockerCli *client.DockerCli) *cobra.Command {
	opts := listOptions{filter: opts.NewFilterOpt()}

	cmd := &cobra.Command{
		Use:     "ls",
		Aliases: []string{"list"},
		Short:   "List services",
		Args:    cli.NoArgs,
		RunE: func(cmd *cobra.Command, args []string) error {
			return runList(dockerCli, opts)
		},
	}

	flags := cmd.Flags()
	flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Only display IDs")
	flags.VarP(&opts.filter, "filter", "f", "Filter output based on conditions provided")

	return cmd
}

func runList(dockerCli *client.DockerCli, opts listOptions) error {
	ctx := context.Background()
	client := dockerCli.Client()

	services, err := client.ServiceList(ctx, types.ServiceListOptions{Filter: opts.filter.Value()})
	if err != nil {
		return err
	}

	out := dockerCli.Out()
	if opts.quiet {
		printQuiet(out, services)
	} else {
		taskFilter := filters.NewArgs()
		for _, service := range services {
			taskFilter.Add("service", service.ID)
		}

		tasks, err := client.TaskList(ctx, types.TaskListOptions{Filter: taskFilter})
		if err != nil {
			return err
		}

		running := map[string]int{}
		for _, task := range tasks {
			if task.Status.State == "running" {
				running[task.ServiceID]++
			}
		}

		printTable(out, services, running)
	}
	return nil
}

func printTable(out io.Writer, services []swarm.Service, running map[string]int) {
	writer := tabwriter.NewWriter(out, 0, 4, 2, ' ', 0)

	// Ignore flushing errors
	defer writer.Flush()

	fmt.Fprintf(writer, listItemFmt, "ID", "NAME", "REPLICAS", "IMAGE", "COMMAND")
	for _, service := range services {
		replicas := ""
		if service.Spec.Mode.Replicated != nil && service.Spec.Mode.Replicated.Replicas != nil {
			replicas = fmt.Sprintf("%d/%d", running[service.ID], *service.Spec.Mode.Replicated.Replicas)
		} else if service.Spec.Mode.Global != nil {
			replicas = "global"
		}
		fmt.Fprintf(
			writer,
			listItemFmt,
			stringid.TruncateID(service.ID),
			service.Spec.Name,
			replicas,
			service.Spec.TaskTemplate.ContainerSpec.Image,
			strings.Join(service.Spec.TaskTemplate.ContainerSpec.Args, " "))
	}
}

func printQuiet(out io.Writer, services []swarm.Service) {
	for _, service := range services {
		fmt.Fprintln(out, service.ID)
	}
}
<|endoftext|>


<commit_before>package waitstate

import (
	"errors"
	"fmt"
	"time"

	"koding/kites/kloud/machinestate"
)

var ErrWaitTimeout = errors.New("timeout while waiting for state")

var MetaState = map[string]struct{ Desired, OnGoing machinestate.State }{
	"build":           {machinestate.Running, machinestate.Building},
	"destroy":         {machinestate.Terminated, machinestate.Terminating},
	"start":           {machinestate.Running, machinestate.Starting},
	"stop":            {machinestate.Stopped, machinestate.Stopping},
	"restart":         {machinestate.Running, machinestate.Rebooting},
	"create-snapshot": {machinestate.Stopped, machinestate.Pending},
	"create-volume":   {machinestate.Stopped, machinestate.Pending},
	"detach-volume":   {machinestate.Stopped, machinestate.Pending},
	"attach-volume":   {machinestate.Stopped, machinestate.Pending},
}

// WaitState is used to track the state of a given process.
type WaitState struct {
	StateFunc       func(int) (machinestate.State, error) // State checker function
	PushFunc        func(string, int, machinestate.State) // Event pusher function
	Action          string                                // Request of action to change states
	Timeout         time.Duration                         // Global timeout to cancel the waiting
	EventerInterval time.Duration                         // Ticker interval to push events
	PollerInterval  time.Duration                         // Ticker interval to poll state changes
	Start, Finish   int                                   // Eventer progress bounds
}

// Wait calls the StateFunc with the specified interval and waits until it
// reached the desired state. It returns nil if the state has been reached
// successfull.
func (w *WaitState) Wait() error {
	if w.Finish == 0 {
		w.Finish = 100
	}

	if w.EventerInterval == 0 {
		w.EventerInterval = 3 * time.Second
	}

	if w.PollerInterval == 0 {
		w.PollerInterval = 30 * time.Second
	}

	if w.Timeout == 0 {
		w.Timeout = 7 * time.Minute
	}

	timeout := time.After(w.Timeout)

	eventTicker := time.NewTicker(w.EventerInterval)
	pollTicker := time.NewTicker(w.PollerInterval)
	defer eventTicker.Stop()
	defer pollTicker.Stop()

	var err error
	metaState := MetaState[w.Action]
	currentState := metaState.OnGoing

	for {
		select {
		// Poll less, push more.
		case <-eventTicker.C:
			if w.Start < w.Finish {
				w.Start += 2
			}

			if w.PushFunc != nil {
				w.PushFunc(fmt.Sprintf("%s called. Desired state: %s. Current state: %s", w.Action, metaState.Desired, currentState),
					w.Start, currentState)
			}

			if currentState == metaState.Desired {
				return nil
			}
		// Poll less, push more.
		case <-pollTicker.C:
			currentState, err = w.StateFunc(w.Start)
			if err != nil {
				return err
			}
		case <-time.After(time.Second * 40):
			// cancel the current ongoing process if it takes too long
			fmt.Println("Canceling current event asking")
			continue
		case <-timeout:
			return ErrWaitTimeout
		}
	}

}
<commit_msg>kloud/waitstate: lazy finish for terminating<commit_after>package waitstate

import (
	"errors"
	"fmt"
	"time"

	"koding/kites/kloud/machinestate"
)

var ErrWaitTimeout = errors.New("timeout while waiting for state")

var MetaState = map[string]struct{ Desired, OnGoing machinestate.State }{
	"build": {machinestate.Running, machinestate.Building},

	// we don't need to wait until it's terminated. So once we see
	// "terminating" we are actually done because there is no going back
	// anymore.
	"destroy": {machinestate.Terminating, machinestate.Terminating},

	"start":           {machinestate.Running, machinestate.Starting},
	"stop":            {machinestate.Stopped, machinestate.Stopping},
	"restart":         {machinestate.Running, machinestate.Rebooting},
	"create-snapshot": {machinestate.Stopped, machinestate.Pending},
	"create-volume":   {machinestate.Stopped, machinestate.Pending},
	"detach-volume":   {machinestate.Stopped, machinestate.Pending},
	"attach-volume":   {machinestate.Stopped, machinestate.Pending},
}

// WaitState is used to track the state of a given process.
type WaitState struct {
	StateFunc       func(int) (machinestate.State, error) // State checker function
	PushFunc        func(string, int, machinestate.State) // Event pusher function
	Action          string                                // Request of action to change states
	Timeout         time.Duration                         // Global timeout to cancel the waiting
	EventerInterval time.Duration                         // Ticker interval to push events
	PollerInterval  time.Duration                         // Ticker interval to poll state changes
	Start, Finish   int                                   // Eventer progress bounds
}

// Wait calls the StateFunc with the specified interval and waits until it
// reached the desired state. It returns nil if the state has been reached
// successfull.
func (w *WaitState) Wait() error {
	if w.Finish == 0 {
		w.Finish = 100
	}

	if w.EventerInterval == 0 {
		w.EventerInterval = 3 * time.Second
	}

	if w.PollerInterval == 0 {
		w.PollerInterval = 20 * time.Second
	}

	if w.Timeout == 0 {
		w.Timeout = 7 * time.Minute
	}

	timeout := time.After(w.Timeout)

	eventTicker := time.NewTicker(w.EventerInterval)
	pollTicker := time.NewTicker(w.PollerInterval)
	defer eventTicker.Stop()
	defer pollTicker.Stop()

	var err error
	metaState := MetaState[w.Action]
	pollState := machinestate.Unknown

	for {
		select {
		// Poll less, push more.
		case <-eventTicker.C:
			if w.Start < w.Finish {
				w.Start += 2
			}

			if w.PushFunc != nil {
				w.PushFunc(fmt.Sprintf("%s called. Desired state: %s. Current state: %s",
					w.Action, metaState.Desired, metaState.OnGoing), w.Start, metaState.OnGoing)
			}

			if pollState == metaState.Desired {
				return nil
			}
		// Poll less, push more.
		case <-pollTicker.C:
			pollState, err = w.StateFunc(w.Start)
			if err != nil {
				return err
			}
		case <-time.After(time.Second * 40):
			// cancel the current ongoing process if it takes too long
			fmt.Println("Canceling current event asking")
			continue
		case <-timeout:
			return ErrWaitTimeout
		}
	}

}
<|endoftext|>


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

package vindexes

import (
	"reflect"
	"testing"

	"strings"

	"github.com/youtube/vitess/go/sqltypes"
	"github.com/youtube/vitess/go/testfiles"
)

var numericStaticMap Vindex

func init() {
	m := make(map[string]string)
	m["json_path"] = testfiles.Locate("vtgate/numeric_static_map_test.json")
	numericStaticMap, _ = CreateVindex("numeric_static_map", "numericStaticMap", m)
}

func TestNumericStaticMapCost(t *testing.T) {
	if numericStaticMap.Cost() != 1 {
		t.Errorf("Cost(): %d, want 1", numericStaticMap.Cost())
	}
}

func TestNumericStaticMapString(t *testing.T) {
	if strings.Compare("numericStaticMap", numericStaticMap.String()) != 0 {
		t.Errorf("String(): %s, want num", numericStaticMap.String())
	}
}

func TestNumericStaticMapMap(t *testing.T) {
	sqlVal, _ := sqltypes.BuildIntegral("8")
	got, err := numericStaticMap.(Unique).Map(nil, []interface{}{
		1,
		int32(2),
		int64(3),
		uint(4),
		uint32(5),
		uint64(6),
		[]byte("7"),
		sqlVal,
	})
	if err != nil {
		t.Error(err)
	}

	// in the third slice, we expect 2 instead of 3 as numeric_static_map_test.json
	// has 3 mapped to 2
	want := [][]byte{
		[]byte("\x00\x00\x00\x00\x00\x00\x00\x01"),
		[]byte("\x00\x00\x00\x00\x00\x00\x00\x02"),
		[]byte("\x00\x00\x00\x00\x00\x00\x00\x02"),
		[]byte("\x00\x00\x00\x00\x00\x00\x00\x04"),
		[]byte("\x00\x00\x00\x00\x00\x00\x00\x05"),
		[]byte("\x00\x00\x00\x00\x00\x00\x00\x06"),
		[]byte("\x00\x00\x00\x00\x00\x00\x00\x07"),
		[]byte("\x00\x00\x00\x00\x00\x00\x00\x08"),
	}
	if !reflect.DeepEqual(got, want) {
		t.Errorf("Map(): %+v, want %+v", got, want)
	}
}

func TestNumericStaticMapMapBadData(t *testing.T) {
	_, err := numericStaticMap.(Unique).Map(nil, []interface{}{1.1})
	want := `NumericStaticMap.Map: getNumber: unexpected type for 1.1: float64`
	if err == nil || err.Error() != want {
		t.Errorf("NumericStaticMap.Map: %v, want %v", err, want)
	}
}

func TestNumericStaticMapVerify(t *testing.T) {
	success, err := numericStaticMap.Verify(nil, []interface{}{1}, [][]byte{[]byte("\x00\x00\x00\x00\x00\x00\x00\x01")})
	if err != nil {
		t.Error(err)
	}
	if !success {
		t.Errorf("Verify(): %+v, want true", success)
	}
}

func TestNumericStaticMapVerifyNeg(t *testing.T) {
	_, err := numericStaticMap.Verify(nil, []interface{}{1, 2}, [][]byte{[]byte("\x16k@\xb4J\xbaK\xd6")})
	want := "NumericStaticMap.Verify: length of ids 2 doesn't match length of ksids 1"
	if err.Error() != want {
		t.Error(err.Error())
	}

	_, err = numericStaticMap.Verify(nil, []interface{}{1.1}, [][]byte{[]byte("\x00\x00\x00\x00\x00\x00\x00\x01")})
	want = `NumericStaticMap.Verify: getNumber: unexpected type for 1.1: float64`
	if err == nil || err.Error() != want {
		t.Errorf("numericStaticMap.Map: %v, want %v", err, want)
	}

	success, err := numericStaticMap.Verify(nil, []interface{}{1}, [][]byte{[]byte("\x00\x00\x00\x00\x00\x00\x00\x02")})
	if err != nil {
		t.Errorf(err.Error())
	}
	if success {
		t.Errorf("Numeric.Verify(): %+v, want false", success)
	}

}
<commit_msg>vtgate/vindexes: Do not run testfiles.Locate() from init() (2nd time).<commit_after>// Copyright 2014, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package vindexes

import (
	"reflect"
	"testing"

	"strings"

	"github.com/youtube/vitess/go/sqltypes"
	"github.com/youtube/vitess/go/testfiles"
)

// createVindex creates the "numeric_static_map" vindex object which is used by
// each test.
//
// IMPORTANT: This code is called per test and must not be called from init()
// because our internal implementation of testfiles.Locate() does not support to
// be called from init().
func createVindex() (Vindex, error) {
	m := make(map[string]string)
	m["json_path"] = testfiles.Locate("vtgate/numeric_static_map_test.json")
	return CreateVindex("numeric_static_map", "numericStaticMap", m)
}

func TestNumericStaticMapCost(t *testing.T) {
	numericStaticMap, err := createVindex()
	if err != nil {
		t.Fatalf("failed to create vindex: %v", err)
	}
	if numericStaticMap.Cost() != 1 {
		t.Errorf("Cost(): %d, want 1", numericStaticMap.Cost())
	}
}

func TestNumericStaticMapString(t *testing.T) {
	numericStaticMap, err := createVindex()
	if err != nil {
		t.Fatalf("failed to create vindex: %v", err)
	}
	if strings.Compare("numericStaticMap", numericStaticMap.String()) != 0 {
		t.Errorf("String(): %s, want num", numericStaticMap.String())
	}
}

func TestNumericStaticMapMap(t *testing.T) {
	numericStaticMap, err := createVindex()
	if err != nil {
		t.Fatalf("failed to create vindex: %v", err)
	}
	sqlVal, _ := sqltypes.BuildIntegral("8")
	got, err := numericStaticMap.(Unique).Map(nil, []interface{}{
		1,
		int32(2),
		int64(3),
		uint(4),
		uint32(5),
		uint64(6),
		[]byte("7"),
		sqlVal,
	})
	if err != nil {
		t.Error(err)
	}

	// in the third slice, we expect 2 instead of 3 as numeric_static_map_test.json
	// has 3 mapped to 2
	want := [][]byte{
		[]byte("\x00\x00\x00\x00\x00\x00\x00\x01"),
		[]byte("\x00\x00\x00\x00\x00\x00\x00\x02"),
		[]byte("\x00\x00\x00\x00\x00\x00\x00\x02"),
		[]byte("\x00\x00\x00\x00\x00\x00\x00\x04"),
		[]byte("\x00\x00\x00\x00\x00\x00\x00\x05"),
		[]byte("\x00\x00\x00\x00\x00\x00\x00\x06"),
		[]byte("\x00\x00\x00\x00\x00\x00\x00\x07"),
		[]byte("\x00\x00\x00\x00\x00\x00\x00\x08"),
	}
	if !reflect.DeepEqual(got, want) {
		t.Errorf("Map(): %+v, want %+v", got, want)
	}
}

func TestNumericStaticMapMapBadData(t *testing.T) {
	numericStaticMap, err := createVindex()
	if err != nil {
		t.Fatalf("failed to create vindex: %v", err)
	}
	_, err = numericStaticMap.(Unique).Map(nil, []interface{}{1.1})
	want := `NumericStaticMap.Map: getNumber: unexpected type for 1.1: float64`
	if err == nil || err.Error() != want {
		t.Errorf("NumericStaticMap.Map: %v, want %v", err, want)
	}
}

func TestNumericStaticMapVerify(t *testing.T) {
	numericStaticMap, err := createVindex()
	if err != nil {
		t.Fatalf("failed to create vindex: %v", err)
	}
	success, err := numericStaticMap.Verify(nil, []interface{}{1}, [][]byte{[]byte("\x00\x00\x00\x00\x00\x00\x00\x01")})
	if err != nil {
		t.Error(err)
	}
	if !success {
		t.Errorf("Verify(): %+v, want true", success)
	}
}

func TestNumericStaticMapVerifyNeg(t *testing.T) {
	numericStaticMap, err := createVindex()
	if err != nil {
		t.Fatalf("failed to create vindex: %v", err)
	}
	_, err = numericStaticMap.Verify(nil, []interface{}{1, 2}, [][]byte{[]byte("\x16k@\xb4J\xbaK\xd6")})
	want := "NumericStaticMap.Verify: length of ids 2 doesn't match length of ksids 1"
	if err.Error() != want {
		t.Error(err.Error())
	}

	_, err = numericStaticMap.Verify(nil, []interface{}{1.1}, [][]byte{[]byte("\x00\x00\x00\x00\x00\x00\x00\x01")})
	want = `NumericStaticMap.Verify: getNumber: unexpected type for 1.1: float64`
	if err == nil || err.Error() != want {
		t.Errorf("numericStaticMap.Map: %v, want %v", err, want)
	}

	success, err := numericStaticMap.Verify(nil, []interface{}{1}, [][]byte{[]byte("\x00\x00\x00\x00\x00\x00\x00\x02")})
	if err != nil {
		t.Errorf(err.Error())
	}
	if success {
		t.Errorf("Numeric.Verify(): %+v, want false", success)
	}

}
<|endoftext|>


<commit_before>package integration_test

import (
	"os/exec"
	"testing"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gbytes"
	. "github.com/onsi/gomega/gexec"
)

func TestIntegration(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "CLI Integration")
}

var _ = Describe("exit codes", func() {
	It("exits non-zero when an unknown command is invoked", func() {
		result := Cf("some-command-that-should-never-actually-be-a-real-thing-i-can-use")

		Eventually(result).Should(Say("not a registered command"))
		Eventually(result).Should(Exit(1))
	})

	It("exits non-zero when known command is invoked with invalid option", func() {
		result := Cf("push", "--crazy")
		Eventually(result).Should(Exit(1))
	})
})

func Cf(args ...string) *Session {
	path, err := Build("github.com/cloudfoundry/cli/main")
	Expect(err).NotTo(HaveOccurred())

	session, err := Start(exec.Command(path, args...), GinkgoWriter, GinkgoWriter)
	Expect(err).NotTo(HaveOccurred())

	return session
}
<commit_msg>Cleans up our gexec.Build() artifacts.<commit_after>package integration_test

import (
	"os/exec"
	"testing"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gbytes"
	. "github.com/onsi/gomega/gexec"
)

func TestIntegration(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "CLI Integration")
}

var _ = Describe("exit codes", func() {
	It("exits non-zero when an unknown command is invoked", func() {
		result := Cf("some-command-that-should-never-actually-be-a-real-thing-i-can-use")

		Eventually(result).Should(Say("not a registered command"))
		Eventually(result).Should(Exit(1))
	})

	It("exits non-zero when known command is invoked with invalid option", func() {
		result := Cf("push", "--crazy")
		Eventually(result).Should(Exit(1))
	})
})

func Cf(args ...string) *Session {
	path, err := Build("github.com/cloudfoundry/cli/main")
	Expect(err).NotTo(HaveOccurred())

	session, err := Start(exec.Command(path, args...), GinkgoWriter, GinkgoWriter)
	Expect(err).NotTo(HaveOccurred())

	return session
}

// gexec.Build leaves a compiled binary behind in /tmp.
var _ = AfterSuite(func() {
	CleanupBuildArtifacts()
})
<|endoftext|>


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

package core

import (
	"fmt"
	"os"
	"strings"
)

// A Mapping represents a contiguous subset of the inferior's address space.
type Mapping struct {
	min  Address
	max  Address
	perm Perm

	f   *os.File // file backing this region
	off int64    // offset of start of this mapping in f

	// For regions originally backed by a file but now in the core file,
	// (probably because it is copy-on-write) this is the original data source.
	// This info is just for printing; the data in this source is stale.
	origF   *os.File
	origOff int64

	// Contents of f at offset off. Length=max-min.
	contents []byte
}

// Min returns the lowest virtual address of the mapping.
func (m *Mapping) Min() Address {
	return m.min
}

// Max returns the virtual address of the byte just beyond the mapping.
func (m *Mapping) Max() Address {
	return m.max
}

// Size returns int64(Max-Min)
func (m *Mapping) Size() int64 {
	return m.max.Sub(m.min)
}

// Perm returns the permissions on the mapping.
func (m *Mapping) Perm() Perm {
	return m.perm
}

// Source returns the backing file and offset for the mapping, or "", 0 if none.
func (m *Mapping) Source() (string, int64) {
	if m.f == nil {
		return "", 0
	}
	return m.f.Name(), m.off
}

// CopyOnWrite reports whether the mapping is a copy-on-write region, i.e.
// it started as a mapped file and is now writeable.
// TODO: is this distinguishable from a write-back region?
func (m *Mapping) CopyOnWrite() bool {
	return m.origF != nil
}

// For CopyOnWrite mappings, OrigSource returns the file/offset of the
// original copy of the data, or "", 0 if none.
func (m *Mapping) OrigSource() (string, int64) {
	if m.origF == nil {
		return "", 0
	}
	return m.origF.Name(), m.origOff
}

// A Perm represents the permissions allowed for a Mapping.
type Perm uint8

const (
	Read Perm = 1 << iota
	Write
	Exec
)

func (p Perm) String() string {
	var a [3]string
	b := a[:0]
	if p&Read != 0 {
		b = append(b, "Read")
	}
	if p&Write != 0 {
		b = append(b, "Write")
	}
	if p&Exec != 0 {
		b = append(b, "Exec")
	}
	if len(b) == 0 {
		b = append(b, "None")
	}
	return strings.Join(b, "|")
}

// We assume that OS pages are at least 4K in size. So every mapping
// starts and ends at a multiple of 4K.
// We divide the other 64-12 = 52 bits into levels in a page table.
type pageTable0 [1 << 10]*Mapping
type pageTable1 [1 << 10]*pageTable0
type pageTable2 [1 << 10]*pageTable1
type pageTable3 [1 << 10]*pageTable2
type pageTable4 [1 << 12]*pageTable3

const pageSize Address = 1 << 12

// findMapping is simple enough that it inlines.
func (p *Process) findMapping(a Address) *Mapping {
	t3 := p.pageTable[a>>52]
	if t3 == nil {
		return nil
	}
	t2 := t3[a>>42%(1<<10)]
	if t2 == nil {
		return nil
	}
	t1 := t2[a>>32%(1<<10)]
	if t1 == nil {
		return nil
	}
	t0 := t1[a>>22%(1<<10)]
	if t0 == nil {
		return nil
	}
	return t0[a>>12%(1<<10)]
}

func (p *Process) addMapping(m *Mapping) error {
	if m.min%(pageSize) != 0 {
		return fmt.Errorf("mapping start %x isn't a multiple of 4096", m.min)
	}
	if m.max%(pageSize) != 0 {
		return fmt.Errorf("mapping end %x isn't a multiple of 4096", m.max)
	}
	for a := m.min; a < m.max; a += 1 << 12 {
		i3 := a >> 52
		t3 := p.pageTable[i3]
		if t3 == nil {
			t3 = new(pageTable3)
			p.pageTable[i3] = t3
		}
		i2 := a >> 42 % (1 << 10)
		t2 := t3[i2]
		if t2 == nil {
			t2 = new(pageTable2)
			t3[i2] = t2
		}
		i1 := a >> 32 % (1 << 10)
		t1 := t2[i1]
		if t1 == nil {
			t1 = new(pageTable1)
			t2[i1] = t1
		}
		i0 := a >> 22 % (1 << 10)
		t0 := t1[i0]
		if t0 == nil {
			t0 = new(pageTable0)
			t1[i0] = t0
		}
		t0[a>>12%(1<<10)] = m
	}
	return nil
}

// splicedMemory represents a memory space formed from multiple regions.
// Much of the logic was copied from delve/pkg/proc/core.go.
type splicedMemory struct {
	mappings []*Mapping
}

func (s *splicedMemory) Add(min, max Address, perm Perm, f *os.File, off int64) {
	if max-min <= 0 {
		return
	}

	// Align max.
	if max%pageSize != 0 {
		max = (max + pageSize) & ^(pageSize - 1)
	}
	// Align min.
	if gap := min % pageSize; gap != 0 {
		off -= int64(gap)
		min -= gap
	}

	newMappings := make([]*Mapping, 0, len(s.mappings)+1)
	add := func(m *Mapping) {
		if m.Size() <= 0 {
			return
		}
		newMappings = append(newMappings, m)
	}

	inserted := false
	for _, entry := range s.mappings {
		switch {
		case entry.max < min: // entry is completely before the new region.
			add(entry)
		case max < entry.min: // entry is completely after the new region.
			if !inserted {
				add(&Mapping{min: min, max: max, perm: perm, f: f, off: off})
				inserted = true
			}
			add(entry)
		case min <= entry.min && entry.max <= max:
			// entry is completely overwritten by the new region. Drop.
		case entry.min <= min && entry.max <= max:
			// new region overwrites the end of the entry.
			entry.max = min
			add(entry)
		case min <= entry.min && max <= entry.max:
			// new region overwrites the begining of the entry.
			if !inserted {
				add(&Mapping{min: min, max: max, perm: perm, f: f, off: off})
				inserted = true
			}
			entry.off += int64(max - entry.min)
			entry.min = max
			add(entry)
		case entry.min < min && max < entry.max:
			// new region punches a hole in the entry.
			entry2 := *entry

			entry.max = min
			entry2.off += int64(max - entry.min)
			entry2.min = max
			add(entry)
			add(&Mapping{min: min, max: max, perm: perm, f: f, off: off})
			add(&entry2)
			inserted = true
		default:
			panic(fmt.Sprintf("Unhandled case: existing entry is (min:0x%x max:0x%x), new entry is (min:0x%x max:0x%x)", entry.min, entry.max, min, max))
		}
	}
	if !inserted {
		add(&Mapping{min: min, max: max, perm: perm, f: f, off: off})
	}
	s.mappings = newMappings
}
<commit_msg>internal: fix typo<commit_after>// Copyright 2017 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package core

import (
	"fmt"
	"os"
	"strings"
)

// A Mapping represents a contiguous subset of the inferior's address space.
type Mapping struct {
	min  Address
	max  Address
	perm Perm

	f   *os.File // file backing this region
	off int64    // offset of start of this mapping in f

	// For regions originally backed by a file but now in the core file,
	// (probably because it is copy-on-write) this is the original data source.
	// This info is just for printing; the data in this source is stale.
	origF   *os.File
	origOff int64

	// Contents of f at offset off. Length=max-min.
	contents []byte
}

// Min returns the lowest virtual address of the mapping.
func (m *Mapping) Min() Address {
	return m.min
}

// Max returns the virtual address of the byte just beyond the mapping.
func (m *Mapping) Max() Address {
	return m.max
}

// Size returns int64(Max-Min)
func (m *Mapping) Size() int64 {
	return m.max.Sub(m.min)
}

// Perm returns the permissions on the mapping.
func (m *Mapping) Perm() Perm {
	return m.perm
}

// Source returns the backing file and offset for the mapping, or "", 0 if none.
func (m *Mapping) Source() (string, int64) {
	if m.f == nil {
		return "", 0
	}
	return m.f.Name(), m.off
}

// CopyOnWrite reports whether the mapping is a copy-on-write region, i.e.
// it started as a mapped file and is now writeable.
// TODO: is this distinguishable from a write-back region?
func (m *Mapping) CopyOnWrite() bool {
	return m.origF != nil
}

// For CopyOnWrite mappings, OrigSource returns the file/offset of the
// original copy of the data, or "", 0 if none.
func (m *Mapping) OrigSource() (string, int64) {
	if m.origF == nil {
		return "", 0
	}
	return m.origF.Name(), m.origOff
}

// A Perm represents the permissions allowed for a Mapping.
type Perm uint8

const (
	Read Perm = 1 << iota
	Write
	Exec
)

func (p Perm) String() string {
	var a [3]string
	b := a[:0]
	if p&Read != 0 {
		b = append(b, "Read")
	}
	if p&Write != 0 {
		b = append(b, "Write")
	}
	if p&Exec != 0 {
		b = append(b, "Exec")
	}
	if len(b) == 0 {
		b = append(b, "None")
	}
	return strings.Join(b, "|")
}

// We assume that OS pages are at least 4K in size. So every mapping
// starts and ends at a multiple of 4K.
// We divide the other 64-12 = 52 bits into levels in a page table.
type pageTable0 [1 << 10]*Mapping
type pageTable1 [1 << 10]*pageTable0
type pageTable2 [1 << 10]*pageTable1
type pageTable3 [1 << 10]*pageTable2
type pageTable4 [1 << 12]*pageTable3

const pageSize Address = 1 << 12

// findMapping is simple enough that it inlines.
func (p *Process) findMapping(a Address) *Mapping {
	t3 := p.pageTable[a>>52]
	if t3 == nil {
		return nil
	}
	t2 := t3[a>>42%(1<<10)]
	if t2 == nil {
		return nil
	}
	t1 := t2[a>>32%(1<<10)]
	if t1 == nil {
		return nil
	}
	t0 := t1[a>>22%(1<<10)]
	if t0 == nil {
		return nil
	}
	return t0[a>>12%(1<<10)]
}

func (p *Process) addMapping(m *Mapping) error {
	if m.min%(pageSize) != 0 {
		return fmt.Errorf("mapping start %x isn't a multiple of 4096", m.min)
	}
	if m.max%(pageSize) != 0 {
		return fmt.Errorf("mapping end %x isn't a multiple of 4096", m.max)
	}
	for a := m.min; a < m.max; a += 1 << 12 {
		i3 := a >> 52
		t3 := p.pageTable[i3]
		if t3 == nil {
			t3 = new(pageTable3)
			p.pageTable[i3] = t3
		}
		i2 := a >> 42 % (1 << 10)
		t2 := t3[i2]
		if t2 == nil {
			t2 = new(pageTable2)
			t3[i2] = t2
		}
		i1 := a >> 32 % (1 << 10)
		t1 := t2[i1]
		if t1 == nil {
			t1 = new(pageTable1)
			t2[i1] = t1
		}
		i0 := a >> 22 % (1 << 10)
		t0 := t1[i0]
		if t0 == nil {
			t0 = new(pageTable0)
			t1[i0] = t0
		}
		t0[a>>12%(1<<10)] = m
	}
	return nil
}

// splicedMemory represents a memory space formed from multiple regions.
// Much of the logic was copied from delve/pkg/proc/core.go.
type splicedMemory struct {
	mappings []*Mapping
}

func (s *splicedMemory) Add(min, max Address, perm Perm, f *os.File, off int64) {
	if max-min <= 0 {
		return
	}

	// Align max.
	if max%pageSize != 0 {
		max = (max + pageSize) & ^(pageSize - 1)
	}
	// Align min.
	if gap := min % pageSize; gap != 0 {
		off -= int64(gap)
		min -= gap
	}

	newMappings := make([]*Mapping, 0, len(s.mappings)+1)
	add := func(m *Mapping) {
		if m.Size() <= 0 {
			return
		}
		newMappings = append(newMappings, m)
	}

	inserted := false
	for _, entry := range s.mappings {
		switch {
		case entry.max < min: // entry is completely before the new region.
			add(entry)
		case max < entry.min: // entry is completely after the new region.
			if !inserted {
				add(&Mapping{min: min, max: max, perm: perm, f: f, off: off})
				inserted = true
			}
			add(entry)
		case min <= entry.min && entry.max <= max:
			// entry is completely overwritten by the new region. Drop.
		case entry.min <= min && entry.max <= max:
			// new region overwrites the end of the entry.
			entry.max = min
			add(entry)
		case min <= entry.min && max <= entry.max:
			// new region overwrites the beginning of the entry.
			if !inserted {
				add(&Mapping{min: min, max: max, perm: perm, f: f, off: off})
				inserted = true
			}
			entry.off += int64(max - entry.min)
			entry.min = max
			add(entry)
		case entry.min < min && max < entry.max:
			// new region punches a hole in the entry.
			entry2 := *entry

			entry.max = min
			entry2.off += int64(max - entry.min)
			entry2.min = max
			add(entry)
			add(&Mapping{min: min, max: max, perm: perm, f: f, off: off})
			add(&entry2)
			inserted = true
		default:
			panic(fmt.Sprintf("Unhandled case: existing entry is (min:0x%x max:0x%x), new entry is (min:0x%x max:0x%x)", entry.min, entry.max, min, max))
		}
	}
	if !inserted {
		add(&Mapping{min: min, max: max, perm: perm, f: f, off: off})
	}
	s.mappings = newMappings
}
<|endoftext|>


<commit_before>package etw

import (
	"bytes"
	"crypto/sha1"
	"encoding/binary"
	"strings"
	"unicode/utf16"

	"golang.org/x/sys/windows"
)

// Provider represents an ETW event provider. It is identified by a provider
// name and ID (GUID), which should always have a 1:1 mapping to each other
// (e.g. don't use multiple provider names with the same ID, or vice versa).
type Provider struct {
	ID         *windows.GUID
	handle     providerHandle
	metadata   []byte
	callback   EnableCallback
	index      uint
	enabled    bool
	level      Level
	keywordAny uint64
	keywordAll uint64
}

type providerHandle windows.Handle

// ProviderState informs the provider EnableCallback what action is being
// performed.
type ProviderState uint32

const (
	// ProviderStateDisable indicates the provider is being disabled.
	ProviderStateDisable ProviderState = iota
	// ProviderStateEnable indicates the provider is being enabled.
	ProviderStateEnable
	// ProviderStateCaptureState indicates the provider is having its current
	// state snap-shotted.
	ProviderStateCaptureState
)

// EnableCallback is the form of the callback function that receives provider
// enable/disable notifications from ETW.
type EnableCallback func(*windows.GUID, ProviderState, Level, uint64, uint64, uintptr)

func providerCallback(sourceID *windows.GUID, state ProviderState, level Level, matchAnyKeyword uint64, matchAllKeyword uint64, filterData uintptr, i uintptr) {
	provider := providers.getProvider(uint(i))

	switch state {
	case ProviderStateDisable:
		provider.enabled = false
	case ProviderStateEnable:
		provider.enabled = true
		provider.level = level
		provider.keywordAny = matchAnyKeyword
		provider.keywordAll = matchAllKeyword
	}

	if provider.callback != nil {
		provider.callback(sourceID, state, level, matchAnyKeyword, matchAllKeyword, filterData)
	}
}

// providerCallbackAdapter acts as the first-level callback from the C/ETW side
// for provider notifications. Because Go has trouble with callback arguments of
// different size, it has only pointer-sized arguments, which are then cast to
// the appropriate types when calling providerCallback.
func providerCallbackAdapter(sourceID *windows.GUID, state uintptr, level uintptr, matchAnyKeyword uintptr, matchAllKeyword uintptr, filterData uintptr, i uintptr) uintptr {
	providerCallback(sourceID, ProviderState(state), Level(level), uint64(matchAnyKeyword), uint64(matchAllKeyword), filterData, i)
	return 0
}

// providerIDFromName generates a provider ID based on the provider name. It
// uses the same algorithm as used by .NET's EventSource class, which is based
// on RFC 4122. More information on the algorithm can be found here:
// https://blogs.msdn.microsoft.com/dcook/2015/09/08/etw-provider-names-and-guids/
// The algorithm is roughly:
// Hash = Sha1(namespace + arg.ToUpper().ToUtf16be())
// Guid = Hash[0..15], with Hash[7] tweaked according to RFC 4122
func providerIDFromName(name string) *windows.GUID {
	buffer := sha1.New()

	namespace := []byte{0x48, 0x2C, 0x2D, 0xB2, 0xC3, 0x90, 0x47, 0xC8, 0x87, 0xF8, 0x1A, 0x15, 0xBF, 0xC1, 0x30, 0xFB}
	buffer.Write(namespace)

	binary.Write(buffer, binary.BigEndian, utf16.Encode([]rune(strings.ToUpper(name))))

	sum := buffer.Sum(nil)
	sum[7] = (sum[7] & 0xf) | 0x50

	return &windows.GUID{
		Data1: binary.LittleEndian.Uint32(sum[0:4]),
		Data2: binary.LittleEndian.Uint16(sum[4:6]),
		Data3: binary.LittleEndian.Uint16(sum[6:8]),
		Data4: [8]byte{sum[8], sum[9], sum[10], sum[11], sum[12], sum[13], sum[14], sum[15]},
	}
}

// NewProvider creates and registers a new ETW provider. The provider ID is
// generated based on the provider name.
func NewProvider(name string, callback EnableCallback) (provider *Provider, err error) {
	return NewProviderWithID(name, providerIDFromName(name), callback)
}

// NewProviderWithID creates and registers a new ETW provider, allowing the
// provider ID to be manually specified. This is most useful when there is an
// existing provider ID that must be used to conform to existing diagnostic
// infrastructure.
func NewProviderWithID(name string, id *windows.GUID, callback EnableCallback) (provider *Provider, err error) {
	providerCallbackOnce.Do(func() {
		globalProviderCallback = windows.NewCallback(providerCallbackAdapter)
	})

	provider = providers.newProvider()
	defer func() {
		if err != nil {
			providers.removeProvider(provider)
		}
	}()
	provider.ID = id
	provider.callback = callback

	if err := eventRegister(provider.ID, globalProviderCallback, uintptr(provider.index), &provider.handle); err != nil {
		return nil, err
	}

	metadata := &bytes.Buffer{}
	binary.Write(metadata, binary.LittleEndian, uint16(0)) // Write empty size for buffer (to update later)
	metadata.WriteString(name)
	metadata.WriteByte(0)                                                   // Null terminator for name
	binary.LittleEndian.PutUint16(metadata.Bytes(), uint16(metadata.Len())) // Update the size at the beginning of the buffer
	provider.metadata = metadata.Bytes()

	return provider, nil
}

// Close unregisters the provider.
func (provider *Provider) Close() error {
	providers.removeProvider(provider)
	return eventUnregister(provider.handle)
}

// IsEnabled calls IsEnabledForLevelAndKeywords with LevelAlways and all
// keywords set.
func (provider *Provider) IsEnabled() bool {
	return provider.IsEnabledForLevelAndKeywords(LevelAlways, ^uint64(0))
}

// IsEnabledForLevel calls IsEnabledForLevelAndKeywords with the specified level
// and all keywords set.
func (provider *Provider) IsEnabledForLevel(level Level) bool {
	return provider.IsEnabledForLevelAndKeywords(level, ^uint64(0))
}

// IsEnabledForLevelAndKeywords allows event producer code to check if there are
// any event sessions that are interested in an event, based on the event level
// and keywords. Although this check happens automatically in the ETW
// infrastructure, it can be useful to check if an event will actually be
// consumed before doing expensive work to build the event data.
func (provider *Provider) IsEnabledForLevelAndKeywords(level Level, keywords uint64) bool {
	if !provider.enabled {
		return false
	}

	// ETW automatically sets the level to 255 if it is specified as 0, so we
	// don't need to worry about the level=0 (all events) case.
	if level > provider.level {
		return false
	}

	if keywords != 0 && (keywords&provider.keywordAny == 0 || keywords&provider.keywordAll != provider.keywordAll) {
		return false
	}

	return true
}

// WriteEvent writes a single ETW event from the provider. The event is
// constructed based on the EventOpt and FieldOpt values that are passed as
// opts.
func (provider *Provider) WriteEvent(name string, eventOpts []EventOpt, fieldOpts []FieldOpt) error {
	tags := uint32(0)
	descriptor := NewEventDescriptor()
	em := &EventMetadata{}
	ed := &EventData{}

	// We need to evaluate the EventOpts first since they might change tags, and
	// we write out the tags before evaluating FieldOpts.
	for _, opt := range eventOpts {
		opt(descriptor, &tags)
	}

	if !provider.IsEnabledForLevelAndKeywords(descriptor.Level, descriptor.Keyword) {
		return nil
	}

	em.WriteEventHeader(name, tags)

	for _, opt := range fieldOpts {
		opt(em, ed)
	}

	return provider.WriteEventRaw(descriptor, [][]byte{em.Bytes()}, [][]byte{ed.Bytes()})
}

// WriteEventRaw writes a single ETW event from the provider. This function is
// less abstracted than WriteEvent, and presents a fairly direct interface to
// the event writing functionality. It expects a series of event metadata and
// event data blobs to be passed in, which must conform to the TraceLogging
// schema. The functions on EventMetadata and EventData can help with creating
// these blobs. The blobs of each type are effectively concatenated together by
// the ETW infrastructure.
func (provider *Provider) WriteEventRaw(descriptor *EventDescriptor, metadataBlobs [][]byte, dataBlobs [][]byte) error {
	dataDescriptorCount := uint32(1 + len(metadataBlobs) + len(dataBlobs))
	dataDescriptors := make([]eventDataDescriptor, 0, dataDescriptorCount)

	dataDescriptors = append(dataDescriptors, newEventDataDescriptor(eventDataDescriptorTypeProviderMetadata, provider.metadata))
	for _, blob := range metadataBlobs {
		dataDescriptors = append(dataDescriptors, newEventDataDescriptor(eventDataDescriptorTypeEventMetadata, blob))
	}
	for _, blob := range dataBlobs {
		dataDescriptors = append(dataDescriptors, newEventDataDescriptor(eventDataDescriptorTypeUserData, blob))
	}

	return eventWriteTransfer(provider.handle, descriptor, nil, nil, dataDescriptorCount, &dataDescriptors[0])
}
<commit_msg>Support ETW events with no data fields<commit_after>package etw

import (
	"bytes"
	"crypto/sha1"
	"encoding/binary"
	"strings"
	"unicode/utf16"

	"golang.org/x/sys/windows"
)

// Provider represents an ETW event provider. It is identified by a provider
// name and ID (GUID), which should always have a 1:1 mapping to each other
// (e.g. don't use multiple provider names with the same ID, or vice versa).
type Provider struct {
	ID         *windows.GUID
	handle     providerHandle
	metadata   []byte
	callback   EnableCallback
	index      uint
	enabled    bool
	level      Level
	keywordAny uint64
	keywordAll uint64
}

type providerHandle windows.Handle

// ProviderState informs the provider EnableCallback what action is being
// performed.
type ProviderState uint32

const (
	// ProviderStateDisable indicates the provider is being disabled.
	ProviderStateDisable ProviderState = iota
	// ProviderStateEnable indicates the provider is being enabled.
	ProviderStateEnable
	// ProviderStateCaptureState indicates the provider is having its current
	// state snap-shotted.
	ProviderStateCaptureState
)

// EnableCallback is the form of the callback function that receives provider
// enable/disable notifications from ETW.
type EnableCallback func(*windows.GUID, ProviderState, Level, uint64, uint64, uintptr)

func providerCallback(sourceID *windows.GUID, state ProviderState, level Level, matchAnyKeyword uint64, matchAllKeyword uint64, filterData uintptr, i uintptr) {
	provider := providers.getProvider(uint(i))

	switch state {
	case ProviderStateDisable:
		provider.enabled = false
	case ProviderStateEnable:
		provider.enabled = true
		provider.level = level
		provider.keywordAny = matchAnyKeyword
		provider.keywordAll = matchAllKeyword
	}

	if provider.callback != nil {
		provider.callback(sourceID, state, level, matchAnyKeyword, matchAllKeyword, filterData)
	}
}

// providerCallbackAdapter acts as the first-level callback from the C/ETW side
// for provider notifications. Because Go has trouble with callback arguments of
// different size, it has only pointer-sized arguments, which are then cast to
// the appropriate types when calling providerCallback.
func providerCallbackAdapter(sourceID *windows.GUID, state uintptr, level uintptr, matchAnyKeyword uintptr, matchAllKeyword uintptr, filterData uintptr, i uintptr) uintptr {
	providerCallback(sourceID, ProviderState(state), Level(level), uint64(matchAnyKeyword), uint64(matchAllKeyword), filterData, i)
	return 0
}

// providerIDFromName generates a provider ID based on the provider name. It
// uses the same algorithm as used by .NET's EventSource class, which is based
// on RFC 4122. More information on the algorithm can be found here:
// https://blogs.msdn.microsoft.com/dcook/2015/09/08/etw-provider-names-and-guids/
// The algorithm is roughly:
// Hash = Sha1(namespace + arg.ToUpper().ToUtf16be())
// Guid = Hash[0..15], with Hash[7] tweaked according to RFC 4122
func providerIDFromName(name string) *windows.GUID {
	buffer := sha1.New()

	namespace := []byte{0x48, 0x2C, 0x2D, 0xB2, 0xC3, 0x90, 0x47, 0xC8, 0x87, 0xF8, 0x1A, 0x15, 0xBF, 0xC1, 0x30, 0xFB}
	buffer.Write(namespace)

	binary.Write(buffer, binary.BigEndian, utf16.Encode([]rune(strings.ToUpper(name))))

	sum := buffer.Sum(nil)
	sum[7] = (sum[7] & 0xf) | 0x50

	return &windows.GUID{
		Data1: binary.LittleEndian.Uint32(sum[0:4]),
		Data2: binary.LittleEndian.Uint16(sum[4:6]),
		Data3: binary.LittleEndian.Uint16(sum[6:8]),
		Data4: [8]byte{sum[8], sum[9], sum[10], sum[11], sum[12], sum[13], sum[14], sum[15]},
	}
}

// NewProvider creates and registers a new ETW provider. The provider ID is
// generated based on the provider name.
func NewProvider(name string, callback EnableCallback) (provider *Provider, err error) {
	return NewProviderWithID(name, providerIDFromName(name), callback)
}

// NewProviderWithID creates and registers a new ETW provider, allowing the
// provider ID to be manually specified. This is most useful when there is an
// existing provider ID that must be used to conform to existing diagnostic
// infrastructure.
func NewProviderWithID(name string, id *windows.GUID, callback EnableCallback) (provider *Provider, err error) {
	providerCallbackOnce.Do(func() {
		globalProviderCallback = windows.NewCallback(providerCallbackAdapter)
	})

	provider = providers.newProvider()
	defer func() {
		if err != nil {
			providers.removeProvider(provider)
		}
	}()
	provider.ID = id
	provider.callback = callback

	if err := eventRegister(provider.ID, globalProviderCallback, uintptr(provider.index), &provider.handle); err != nil {
		return nil, err
	}

	metadata := &bytes.Buffer{}
	binary.Write(metadata, binary.LittleEndian, uint16(0)) // Write empty size for buffer (to update later)
	metadata.WriteString(name)
	metadata.WriteByte(0)                                                   // Null terminator for name
	binary.LittleEndian.PutUint16(metadata.Bytes(), uint16(metadata.Len())) // Update the size at the beginning of the buffer
	provider.metadata = metadata.Bytes()

	return provider, nil
}

// Close unregisters the provider.
func (provider *Provider) Close() error {
	providers.removeProvider(provider)
	return eventUnregister(provider.handle)
}

// IsEnabled calls IsEnabledForLevelAndKeywords with LevelAlways and all
// keywords set.
func (provider *Provider) IsEnabled() bool {
	return provider.IsEnabledForLevelAndKeywords(LevelAlways, ^uint64(0))
}

// IsEnabledForLevel calls IsEnabledForLevelAndKeywords with the specified level
// and all keywords set.
func (provider *Provider) IsEnabledForLevel(level Level) bool {
	return provider.IsEnabledForLevelAndKeywords(level, ^uint64(0))
}

// IsEnabledForLevelAndKeywords allows event producer code to check if there are
// any event sessions that are interested in an event, based on the event level
// and keywords. Although this check happens automatically in the ETW
// infrastructure, it can be useful to check if an event will actually be
// consumed before doing expensive work to build the event data.
func (provider *Provider) IsEnabledForLevelAndKeywords(level Level, keywords uint64) bool {
	if !provider.enabled {
		return false
	}

	// ETW automatically sets the level to 255 if it is specified as 0, so we
	// don't need to worry about the level=0 (all events) case.
	if level > provider.level {
		return false
	}

	if keywords != 0 && (keywords&provider.keywordAny == 0 || keywords&provider.keywordAll != provider.keywordAll) {
		return false
	}

	return true
}

// WriteEvent writes a single ETW event from the provider. The event is
// constructed based on the EventOpt and FieldOpt values that are passed as
// opts.
func (provider *Provider) WriteEvent(name string, eventOpts []EventOpt, fieldOpts []FieldOpt) error {
	tags := uint32(0)
	descriptor := NewEventDescriptor()
	em := &EventMetadata{}
	ed := &EventData{}

	// We need to evaluate the EventOpts first since they might change tags, and
	// we write out the tags before evaluating FieldOpts.
	for _, opt := range eventOpts {
		opt(descriptor, &tags)
	}

	if !provider.IsEnabledForLevelAndKeywords(descriptor.Level, descriptor.Keyword) {
		return nil
	}

	em.WriteEventHeader(name, tags)

	for _, opt := range fieldOpts {
		opt(em, ed)
	}

	// Don't pass a data blob if there is no event data. There will always be
	// event metadata (e.g. for the name) so we don't need to do this check for
	// the metadata.
	dataBlobs := [][]byte{}
	if len(ed.Bytes()) > 0 {
		dataBlobs = [][]byte{ed.Bytes()}
	}

	return provider.WriteEventRaw(descriptor, [][]byte{em.Bytes()}, dataBlobs)
}

// WriteEventRaw writes a single ETW event from the provider. This function is
// less abstracted than WriteEvent, and presents a fairly direct interface to
// the event writing functionality. It expects a series of event metadata and
// event data blobs to be passed in, which must conform to the TraceLogging
// schema. The functions on EventMetadata and EventData can help with creating
// these blobs. The blobs of each type are effectively concatenated together by
// the ETW infrastructure.
func (provider *Provider) WriteEventRaw(descriptor *EventDescriptor, metadataBlobs [][]byte, dataBlobs [][]byte) error {
	dataDescriptorCount := uint32(1 + len(metadataBlobs) + len(dataBlobs))
	dataDescriptors := make([]eventDataDescriptor, 0, dataDescriptorCount)

	dataDescriptors = append(dataDescriptors, newEventDataDescriptor(eventDataDescriptorTypeProviderMetadata, provider.metadata))
	for _, blob := range metadataBlobs {
		dataDescriptors = append(dataDescriptors, newEventDataDescriptor(eventDataDescriptorTypeEventMetadata, blob))
	}
	for _, blob := range dataBlobs {
		dataDescriptors = append(dataDescriptors, newEventDataDescriptor(eventDataDescriptorTypeUserData, blob))
	}

	return eventWriteTransfer(provider.handle, descriptor, nil, nil, dataDescriptorCount, &dataDescriptors[0])
}
<|endoftext|>


<commit_before>package mbs

import (
	"testing"

	"github.com/dvrkps/valida/internal/testutil"
)

func TestOK(t *testing.T) {
	var tests = []testutil.TestCase{
		{Name: "valid short", Input: "01130234", Want: true},
		{Name: "valid long", Input: "011302340123", Want: true},
		{Name: "too short", Input: "123"},
		{Name: "invalid", Input: "12345678"},
		{Name: "not a number", Input: "1a23b567"},
		{Name: "zeros short", Input: "00000000"},
		{Name: "zeros long", Input: "000000000000"},
		{Name: "empty", Input: ""},
	}

	testutil.Run(t, OK, tests)
}
<commit_msg>internal/mbs: clean testcases<commit_after>package mbs

import (
	"testing"

	"github.com/dvrkps/valida/internal/testutil"
)

func TestOK(t *testing.T) {
	var tests = []testutil.TestCase{
		{Name: "valid short", Input: "01130234", Want: true},
		{Name: "valid long", Input: "011302340123", Want: true},
		{Name: "too short", Input: "123"},
		{Name: "invalid", Input: "12345678"},
		{Name: "not a number", Input: "1a23b567"},
		{Name: "empty"},
	}

	testutil.Run(t, OK, tests)
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"os"
	"strconv"
	"syscall"
	"time"
)

type DebugInfo struct {
	Timestamp          time.Time
	Hostname           string
	Addresses          []string
	InternetConnection bool
	Applications       []DebugApplication
}

type DebugApplication struct {
	Name       string
	DeployFile string
	LogFile    string
	PidFile    int64
	IsRunning  bool
}

func main() {
	port := parseFlags()
	http.HandleFunc("/", debugResponse)

	log.Printf("Debug server running on http://127.0.0.1:%d", port)
	http.ListenAndServe(fmt.Sprintf("127.0.0.1:%d", port), nil)
}

func debugResponse(w http.ResponseWriter, req *http.Request) {
	d := fetchDebugInfo()

	jsonReponse, err := json.Marshal(d)
	failOnError(err, "Cannot marshal JSON")

	w.Header().Set("Content-Type", "application/json")
	w.Write(jsonReponse)
}

func fetchDebugInfo() DebugInfo {
	d := DebugInfo{Timestamp: time.Now()}

	// fetch ip address(es)
	d.Hostname, d.Addresses = ipAddresses()
	// test for internet connection
	d.InternetConnection = checkConnection()
	// log active apps
	d.Applications = checkApps()

	return d
}

func ipAddresses() (hostname string, addrs []string) {
	hostname, err := os.Hostname()
	failOnError(err, "Could not determine hostname")

	addrs, err = net.LookupHost(hostname)
	failOnError(err, "Could not determine IP")
	return
}

func checkConnection() bool {
	// match the request to a known output
	success := "<TITLE>Success</TITLE>" +
		"Success"

	res, err := http.Get("http://www.apple.com/library/test/success.html")

	if err != nil {
		return false
	}

	body, err := ioutil.ReadAll(res.Body)
	defer res.Body.Close()

	if err != nil {
		return false
	}

	return string(body) == success
}

func checkApps() (apps []DebugApplication) {
	appNames := []string{
		"buttons", "cease", "example", "magic",
		"server", "updater", "debug",
	}

	for _, appName := range appNames {
		apps = append(apps, checkApp(appName))
	}

	return
}

func checkApp(appName string) (app DebugApplication) {
	app.Name = appName
	app.DeployFile = fetchDeployFile(appName)
	app.LogFile = fetchLogFile(appName)
	app.PidFile = fetchPidFile(appName)
	app.IsRunning = checkProcess(app.PidFile)
	return
}

func fetchDeployFile(appName string) (output string) {
	pathTemplate := "/opt/radiodan/apps/%s/current/.deploy"
	path := fmt.Sprintf(pathTemplate, appName)
	file, err := ioutil.ReadFile(path)

	if err != nil {
		log.Println("[!] Could not open file", path)
		return
	}

	output = string(file)

	return
}

func fetchLogFile(appName string) (output string) {
	return
}

func fetchPidFile(appName string) (output int64) {
	pathTemplate := "/var/run/radiodan/radiodan-%s.pid"
	path := fmt.Sprintf(pathTemplate, appName)
	file, err := ioutil.ReadFile(path)

	if err != nil {
		log.Println("[!] Could not open file", path)
		return
	}

	output, err = strconv.ParseInt(string(file), 10, 0)
	failOnError(err, "FAIL")

	log.Println(fmt.Sprintf("%s:%s:%d", path, string(file), output))

	return
}

func checkProcess(pid int64) (running bool) {
	running = false

	// this isn't the pid we're looking for
	if pid == 0 {
		return
	}

	// see if that process exists
	process, err := os.FindProcess(int(pid))
	if err != nil {
		return
	}

	// see if the process responds to sig 0
	err = process.Signal(syscall.Signal(0))
	running = (err == nil)

	return
}

func parseFlags() (port int) {
	flag.IntVar(&port, "port", 8080, "Port for server")
	flag.Parse()
	return
}

func failOnError(err error, msg string) {
	if err != nil {
		log.Fatalf("%s: %s", msg, err)
		panic(fmt.Sprintf("%s: %s", msg, err))
	}
}
<commit_msg>Strip newline from pid file<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"os"
	"strconv"
	"strings"
	"syscall"
	"time"
)

type DebugInfo struct {
	Timestamp          time.Time
	Hostname           string
	Addresses          []string
	InternetConnection bool
	Applications       []DebugApplication
}

type DebugApplication struct {
	Name       string
	DeployFile string
	LogFile    string
	PidFile    int64
	IsRunning  bool
}

func main() {
	port := parseFlags()
	http.HandleFunc("/", debugResponse)

	log.Printf("Debug server running on http://127.0.0.1:%d", port)
	http.ListenAndServe(fmt.Sprintf("127.0.0.1:%d", port), nil)
}

func debugResponse(w http.ResponseWriter, req *http.Request) {
	d := fetchDebugInfo()

	jsonReponse, err := json.Marshal(d)
	failOnError(err, "Cannot marshal JSON")

	w.Header().Set("Content-Type", "application/json")
	w.Write(jsonReponse)
}

func fetchDebugInfo() DebugInfo {
	d := DebugInfo{Timestamp: time.Now()}

	// fetch ip address(es)
	d.Hostname, d.Addresses = ipAddresses()
	// test for internet connection
	d.InternetConnection = checkConnection()
	// log active apps
	d.Applications = checkApps()

	return d
}

func ipAddresses() (hostname string, addrs []string) {
	hostname, err := os.Hostname()
	failOnError(err, "Could not determine hostname")

	addrs, err = net.LookupHost(hostname)
	failOnError(err, "Could not determine IP")
	return
}

func checkConnection() bool {
	// match the request to a known output
	success := "<TITLE>Success</TITLE>" +
		"Success"

	res, err := http.Get("http://www.apple.com/library/test/success.html")

	if err != nil {
		return false
	}

	body, err := ioutil.ReadAll(res.Body)
	defer res.Body.Close()

	if err != nil {
		return false
	}

	return string(body) == success
}

func checkApps() (apps []DebugApplication) {
	appNames := []string{
		"buttons", "cease", "example", "magic",
		"server", "updater", "debug",
	}

	for _, appName := range appNames {
		apps = append(apps, checkApp(appName))
	}

	return
}

func checkApp(appName string) (app DebugApplication) {
	app.Name = appName
	app.DeployFile = fetchDeployFile(appName)
	app.LogFile = fetchLogFile(appName)
	app.PidFile = fetchPidFile(appName)
	app.IsRunning = checkProcess(app.PidFile)
	return
}

func fetchDeployFile(appName string) (output string) {
	pathTemplate := "/opt/radiodan/apps/%s/current/.deploy"
	path := fmt.Sprintf(pathTemplate, appName)
	file, err := ioutil.ReadFile(path)

	if err != nil {
		log.Println("[!] Could not open file", path)
		return
	}

	output = string(file)

	return
}

func fetchLogFile(appName string) (output string) {
	return
}

func fetchPidFile(appName string) (output int64) {
	pathTemplate := "/var/run/radiodan/radiodan-%s.pid"
	path := fmt.Sprintf(pathTemplate, appName)
	file, err := ioutil.ReadFile(path)

	if err != nil {
		log.Println("[!] Could not open file", path)
		return
	}

	pidString := strings.Trim(string(file), "\n")
	output, err = strconv.ParseInt(pidString, 10, 0)

	failOnError(err, "Could not parse pid as integer")

	return
}

func checkProcess(pid int64) (running bool) {
	running = false

	// this isn't the pid we're looking for
	if pid == 0 {
		return
	}

	// see if that process exists
	process, err := os.FindProcess(int(pid))
	if err != nil {
		return
	}

	// see if the process responds to sig 0
	err = process.Signal(syscall.Signal(0))
	running = (err == nil)

	return
}

func parseFlags() (port int) {
	flag.IntVar(&port, "port", 8080, "Port for server")
	flag.Parse()
	return
}

func failOnError(err error, msg string) {
	if err != nil {
		log.Fatalf("%s: %s", msg, err)
		panic(fmt.Sprintf("%s: %s", msg, err))
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2018 Laurent Moussault. All rights reserved.
// Licensed under a simplified BSD license (see LICENSE file).

package gl

import (
	"errors"

	"github.com/cozely/cozely/internal"
)

////////////////////////////////////////////////////////////////////////////////

/*
#cgo linux LDFLAGS: -ldl
#include "glad.h"

void errorCallback(
    GLenum source,
    GLenum type,
    GLuint id,
    GLenum severity,
    GLsizei length,
    const GLchar *message,
    const void *userParam);

static inline int InitOpenGL(int debug){
	if(!gladLoadGL()) {
		return -1;
	}

	if(debug) {
		glEnable(GL_DEBUG_OUTPUT);
		glDebugMessageCallback(errorCallback, NULL);
	}

	return 0;
}
*/
import "C"

////////////////////////////////////////////////////////////////////////////////

func init() {
	internal.GLSetup = setup
}

func setup() error {
	var d C.int
	if internal.Config.Debug {
		d = 1
	}
	if C.InitOpenGL(d) != 0 {
		return errors.New("gl setup: impossible to initialize OpenGL")
	}

	clearPipelineCurrentState()

	return nil
}

////////////////////////////////////////////////////////////////////////////////

func prerender() error {
	DefaultFramebuffer.Bind(DrawFramebuffer)
	ClearColorBuffer(struct{ R, G, B, A float32 }{0, 0, 0, 0}) //TODO: ...
	return nil
}

////////////////////////////////////////////////////////////////////////////////

func init() {
	internal.GLCleanup = cleanup
}

func cleanup() error {
	return nil
}

////////////////////////////////////////////////////////////////////////////////
<commit_msg>Fix framebuffer not clearing<commit_after>// Copyright (c) 2013-2018 Laurent Moussault. All rights reserved.
// Licensed under a simplified BSD license (see LICENSE file).

package gl

import (
	"errors"

	"github.com/cozely/cozely/internal"
)

////////////////////////////////////////////////////////////////////////////////

/*
#cgo linux LDFLAGS: -ldl
#include "glad.h"

void errorCallback(
    GLenum source,
    GLenum type,
    GLuint id,
    GLenum severity,
    GLsizei length,
    const GLchar *message,
    const void *userParam);

static inline int InitOpenGL(int debug){
	if(!gladLoadGL()) {
		return -1;
	}

	if(debug) {
		glEnable(GL_DEBUG_OUTPUT);
		glDebugMessageCallback(errorCallback, NULL);
	}

	return 0;
}
*/
import "C"

////////////////////////////////////////////////////////////////////////////////

func init() {
	internal.GLSetup = setup
}

func setup() error {
	var d C.int
	if internal.Config.Debug {
		d = 1
	}
	if C.InitOpenGL(d) != 0 {
		return errors.New("gl setup: impossible to initialize OpenGL")
	}

	clearPipelineCurrentState()

	return nil
}

////////////////////////////////////////////////////////////////////////////////

func init() {
	internal.GLPrerender = prerender
}

func prerender() error {
	DefaultFramebuffer.Bind(DrawFramebuffer)
	ClearColorBuffer(struct{ R, G, B, A float32 }{0, 0, 0, 0}) //TODO: ...
	return nil
}

////////////////////////////////////////////////////////////////////////////////

func init() {
	internal.GLCleanup = cleanup
}

func cleanup() error {
	return nil
}

////////////////////////////////////////////////////////////////////////////////
<|endoftext|>


<commit_before>// depdup: A Streaming Deduplication package
//
// This package implements streaming deduplication, allowing you to remove duplicated data in streams.
// It implements variable block sizes and automatic content block adaptation.
// It has a fully streaming mode and an indexed mode, that has significantly reduced memory requirements.
//
// Read for an introduction to deduplication: https://blog.klauspost.com/fast-stream-deduplication-in-go
//
// Package home: https://github.com/klauspost/dedup
//
// Godoc: https://godoc.org/github.com/klauspost/dedup
//
package dedup

import (
	hasher "crypto/sha1"
	"fmt"
	"math/big"
)

// Returns an approximate Birthday probability calculation
// based on the number of blocks given and the hash size.
//
// It uses the simplified calculation:  p = k(k-1) / (2N)
//
// From http://preshing.com/20110504/hash-collision-probabilities/
func BirthdayProblem(blocks int) string {
	k := big.NewInt(int64(blocks))
	km1 := big.NewInt(int64(blocks - 1))
	ksq := k.Mul(k, km1)
	n := big.NewInt(0)
	n = n.Exp(big.NewInt(2), big.NewInt(int64(hasher.Size)*8), nil)
	twoN := n.Add(n, n)
	var t, t2 big.Rat
	var res *big.Rat
	//
	res = t.SetFrac(ksq, twoN)
	f64, _ := res.Float64()
	inv := t2.Inv(res).FloatString(0)
	invs := fmt.Sprintf(" ~ 1/%s ~ %v", inv, f64)

	return "Collision probability is" + invs
}
<commit_msg>Remove the need to import the hash function in dedup.go<commit_after>// depdup: A Streaming Deduplication package
//
// This package implements streaming deduplication, allowing you to remove duplicated data in streams.
// It implements variable block sizes and automatic content block adaptation.
// It has a fully streaming mode and an indexed mode, that has significantly reduced memory requirements.
//
// Read for an introduction to deduplication: https://blog.klauspost.com/fast-stream-deduplication-in-go
//
// Package home: https://github.com/klauspost/dedup
//
// Godoc: https://godoc.org/github.com/klauspost/dedup
//
package dedup

import (
	"fmt"
	"math/big"
)

// Returns an approximate Birthday probability calculation
// based on the number of blocks given and the hash size.
//
// It uses the simplified calculation:  p = k(k-1) / (2N)
//
// From http://preshing.com/20110504/hash-collision-probabilities/
func BirthdayProblem(blocks int) string {
	k := big.NewInt(int64(blocks))
	km1 := big.NewInt(int64(blocks - 1))
	ksq := k.Mul(k, km1)
	n := big.NewInt(0)
	n = n.Exp(big.NewInt(2), big.NewInt(int64(HashSize)*8), nil)
	twoN := n.Add(n, n)
	var t, t2 big.Rat
	var res *big.Rat
	//
	res = t.SetFrac(ksq, twoN)
	f64, _ := res.Float64()
	inv := t2.Inv(res).FloatString(0)
	invs := fmt.Sprintf(" ~ 1/%s ~ %v", inv, f64)

	return "Collision probability is" + invs
}
<|endoftext|>