<commit_before>package cmd

// Version defines the current Pop version.
const Version = "v4.9.0"
<commit_msg>Revert version to development to fix release<commit_after>package cmd

// Version defines the current Pop version.
const Version = "development"
<|endoftext|>


<commit_before>package hugolib

const Version = "0.13-DEV"

var (
	CommitHash string
	BuildDate  string
)

var hugoInfo *HugoInfo

// HugoInfo contains information about the current Hugo environment
type HugoInfo struct {
	Version    string
	Generator  string
	CommitHash string
	BuildDate  string
}

func init() {
	hugoInfo = &HugoInfo{
		Version:    Version,
		CommitHash: CommitHash,
		BuildDate:  BuildDate,
		Generator:  `<meta name="generator" content="Hugo ` + Version + `" />`,
	}
}
<commit_msg>Fix the Hugo.Generator tag so it can be used<commit_after>package hugolib

import (
	"html/template"
)

const Version = "0.13-DEV"

var (
	CommitHash string
	BuildDate  string
)

var hugoInfo *HugoInfo

// HugoInfo contains information about the current Hugo environment
type HugoInfo struct {
	Version    string
	Generator  template.HTML
	CommitHash string
	BuildDate  string
}

func init() {
	hugoInfo = &HugoInfo{
		Version:    Version,
		CommitHash: CommitHash,
		BuildDate:  BuildDate,
		Generator:  `<meta name="generator" content="Hugo ` + Version + `" />`,
	}
}
<|endoftext|>


<commit_before>// +build linux

package memory

import (
	"reflect"
	"strings"
	"testing"
)

func TestGetMemory(t *testing.T) {
	memory, err := Get()
	if err != nil {
		t.Fatalf("error should be nil but got: %v", err)
	}
	if memory.Used <= 0 || memory.Total <= 0 {
		t.Errorf("invalid memory value: %+v", memory)
	}
	t.Logf("memory value: %+v", memory)
}

func TestCollectMemoryStats(t *testing.T) {
	got, err := collectMemoryStats(strings.NewReader(
		`MemTotal:        1929620 kB
MemFree:          113720 kB
Buffers:           81744 kB
Cached:           435712 kB
SwapCached:          504 kB
Active:           817412 kB
Inactive:         754140 kB
Active(anon):     647484 kB
Inactive(anon):   570160 kB
Active(file):     169928 kB
Inactive(file):   183980 kB
Unevictable:         124 kB
Mlocked:             124 kB
HighTotal:       1047928 kB
HighFree:          18692 kB
LowTotal:         881692 kB
LowFree:           95028 kB
SwapTotal:       1959932 kB
SwapFree:        1957500 kB
Dirty:               352 kB
Writeback:             0 kB
AnonPages:       1053804 kB
Mapped:           151408 kB
Shmem:            163548 kB
Slab:             202768 kB
SReclaimable:     177128 kB
SUnreclaim:        25640 kB
KernelStack:        4624 kB
PageTables:        15944 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     2924740 kB
Committed_AS:    7238800 kB
VmallocTotal:     122880 kB
VmallocUsed:       16344 kB
VmallocChunk:     102740 kB
HardwareCorrupted:     0 kB
AnonHugePages:    145408 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:       24568 kB
DirectMap2M:      888832 kB
`))
	if err != nil {
		t.Fatalf("error should be nil but got: %v", err)
	}
	expected := &Stats{
		Total:               uint64(1929620 * 1024),
		Used:                uint64(1298444 * 1024),
		Buffers:             uint64(81744 * 1024),
		Cached:              uint64(435712 * 1024),
		Free:                uint64(113720 * 1024),
		Active:              uint64(817412 * 1024),
		Inactive:            uint64(754140 * 1024),
		SwapTotal:           uint64(1959932 * 1024),
		SwapUsed:            uint64(2432 * 1024),
		SwapCached:          uint64(504 * 1024),
		SwapFree:            uint64(1957500 * 1024),
		MemAvailableEnabled: false,
	}
	if !reflect.DeepEqual(got, expected) {
		t.Errorf("invalid memory value: %+v (expected: %+v)", got, expected)
	}
}

func TestCollectMemoryStats_memAvailable(t *testing.T) {
	got, err := collectMemoryStats(strings.NewReader(
		`MemTotal:        1929620 kB
MemFree:          113720 kB
MemAvailable:     533132 kB
Buffers:           81744 kB
Cached:           435712 kB
SwapCached:          504 kB
Active:           817412 kB
Inactive:         754140 kB
Active(anon):     647484 kB
Inactive(anon):   570160 kB
Active(file):     169928 kB
Inactive(file):   183980 kB
Unevictable:         124 kB
Mlocked:             124 kB
HighTotal:       1047928 kB
HighFree:          18692 kB
LowTotal:         881692 kB
LowFree:           95028 kB
SwapTotal:       1959932 kB
SwapFree:        1957500 kB
Dirty:               352 kB
Writeback:             0 kB
AnonPages:       1053804 kB
Mapped:           151408 kB
Shmem:            163548 kB
Slab:             202768 kB
SReclaimable:     177128 kB
SUnreclaim:        25640 kB
KernelStack:        4624 kB
PageTables:        15944 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     2924740 kB
Committed_AS:    7238800 kB
VmallocTotal:     122880 kB
VmallocUsed:       16344 kB
VmallocChunk:     102740 kB
HardwareCorrupted:     0 kB
AnonHugePages:    145408 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:       24568 kB
DirectMap2M:      888832 kB
`))
	if err != nil {
		t.Fatalf("error should be nil but got: %v", err)
	}
	expected := &Stats{
		Total:               uint64(1929620 * 1024),
		Used:                uint64(1396488 * 1024),
		Buffers:             uint64(81744 * 1024),
		Cached:              uint64(435712 * 1024),
		Free:                uint64(113720 * 1024),
		Available:           uint64(533132 * 1024),
		Active:              uint64(817412 * 1024),
		Inactive:            uint64(754140 * 1024),
		SwapTotal:           uint64(1959932 * 1024),
		SwapUsed:            uint64(2432 * 1024),
		SwapCached:          uint64(504 * 1024),
		SwapFree:            uint64(1957500 * 1024),
		MemAvailableEnabled: true,
	}
	if !reflect.DeepEqual(got, expected) {
		t.Errorf("invalid memory value: %+v (expected: %+v)", got, expected)
	}
}
<commit_msg>introduce table driven test in memory_linux_test.go<commit_after>// +build linux

package memory

import (
	"reflect"
	"strings"
	"testing"
)

func TestGetMemory(t *testing.T) {
	memory, err := Get()
	if err != nil {
		t.Fatalf("error should be nil but got: %v", err)
	}
	if memory.Used <= 0 || memory.Total <= 0 {
		t.Errorf("invalid memory value: %+v", memory)
	}
	t.Logf("memory value: %+v", memory)
}

func TestCollectMemoryStats(t *testing.T) {
	testCases := []struct {
		name   string
		input  string
		expect *Stats
	}{
		{
			name: "Disable MemAvailable",
			input: `MemTotal:        1929620 kB
MemFree:          113720 kB
Buffers:           81744 kB
Cached:           435712 kB
SwapCached:          504 kB
Active:           817412 kB
Inactive:         754140 kB
Active(anon):     647484 kB
Inactive(anon):   570160 kB
Active(file):     169928 kB
Inactive(file):   183980 kB
Unevictable:         124 kB
Mlocked:             124 kB
HighTotal:       1047928 kB
HighFree:          18692 kB
LowTotal:         881692 kB
LowFree:           95028 kB
SwapTotal:       1959932 kB
SwapFree:        1957500 kB
Dirty:               352 kB
Writeback:             0 kB
AnonPages:       1053804 kB
Mapped:           151408 kB
Shmem:            163548 kB
Slab:             202768 kB
SReclaimable:     177128 kB
SUnreclaim:        25640 kB
KernelStack:        4624 kB
PageTables:        15944 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     2924740 kB
Committed_AS:    7238800 kB
VmallocTotal:     122880 kB
VmallocUsed:       16344 kB
VmallocChunk:     102740 kB
HardwareCorrupted:     0 kB
AnonHugePages:    145408 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:       24568 kB
DirectMap2M:      888832 kB
`,
			expect: &Stats{
				Total:               uint64(1929620 * 1024),
				Used:                uint64(1298444 * 1024),
				Buffers:             uint64(81744 * 1024),
				Cached:              uint64(435712 * 1024),
				Free:                uint64(113720 * 1024),
				Active:              uint64(817412 * 1024),
				Inactive:            uint64(754140 * 1024),
				SwapTotal:           uint64(1959932 * 1024),
				SwapUsed:            uint64(2432 * 1024),
				SwapCached:          uint64(504 * 1024),
				SwapFree:            uint64(1957500 * 1024),
				MemAvailableEnabled: false,
			},
		},
		{
			name: "Enable MemAvailable",
			input: `MemTotal:        1929620 kB
MemFree:          113720 kB
MemAvailable:     533132 kB
Buffers:           81744 kB
Cached:           435712 kB
SwapCached:          504 kB
Active:           817412 kB
Inactive:         754140 kB
Active(anon):     647484 kB
Inactive(anon):   570160 kB
Active(file):     169928 kB
Inactive(file):   183980 kB
Unevictable:         124 kB
Mlocked:             124 kB
HighTotal:       1047928 kB
HighFree:          18692 kB
LowTotal:         881692 kB
LowFree:           95028 kB
SwapTotal:       1959932 kB
SwapFree:        1957500 kB
Dirty:               352 kB
Writeback:             0 kB
AnonPages:       1053804 kB
Mapped:           151408 kB
Shmem:            163548 kB
Slab:             202768 kB
SReclaimable:     177128 kB
SUnreclaim:        25640 kB
KernelStack:        4624 kB
PageTables:        15944 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     2924740 kB
Committed_AS:    7238800 kB
VmallocTotal:     122880 kB
VmallocUsed:       16344 kB
VmallocChunk:     102740 kB
HardwareCorrupted:     0 kB
AnonHugePages:    145408 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:       24568 kB
DirectMap2M:      888832 kB
`,
			expect: &Stats{
				Total:               uint64(1929620 * 1024),
				Used:                uint64(1396488 * 1024),
				Buffers:             uint64(81744 * 1024),
				Cached:              uint64(435712 * 1024),
				Free:                uint64(113720 * 1024),
				Available:           uint64(533132 * 1024),
				Active:              uint64(817412 * 1024),
				Inactive:            uint64(754140 * 1024),
				SwapTotal:           uint64(1959932 * 1024),
				SwapUsed:            uint64(2432 * 1024),
				SwapCached:          uint64(504 * 1024),
				SwapFree:            uint64(1957500 * 1024),
				MemAvailableEnabled: true,
			},
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			got, err := collectMemoryStats(strings.NewReader(tc.input))
			if err != nil {
				t.Fatalf("error should be nil but got: %v", err)
			}
			if !reflect.DeepEqual(got, tc.expect) {
				t.Errorf("%s: invalid memory value: %+v (expected: %+v)", tc.name, got, tc.expect)
			}
		})
	}
}
<|endoftext|>


<commit_before>package controllers

import (
	"net/http"

	"github.com/jessemillar/byudzhet/helpers"
	"github.com/labstack/echo"
)

func (cg *ControllerGroup) GetSharing(c echo.Context) error {
	token, err := helpers.ValidateJWT(c)
	if err != nil {
		return c.String(http.StatusBadRequest, err.Error())
	}

	response, err := cg.Accessors.GetSharing(c, token.Email)
	if err != nil {
		return c.String(http.StatusBadRequest, err.Error())
	}

	return c.JSON(http.StatusOK, response)
}

func (cg *ControllerGroup) Share(c echo.Context) error {
	token, err := helpers.ValidateJWT(c)
	if err != nil {
		return c.String(http.StatusBadRequest, err.Error())
	}

	response, err := cg.Accessors.Share(c, token.Email)
	if err != nil {
		return c.String(http.StatusBadRequest, err.Error())
	}

	return c.JSON(http.StatusOK, response)
}
<commit_msg>Posting of sharing data works<commit_after>package controllers

import (
	"net/http"

	"github.com/jessemillar/byudzhet/helpers"
	"github.com/labstack/echo"
)

func (cg *ControllerGroup) Share(c echo.Context) error {
	token, err := helpers.ValidateJWT(c)
	if err != nil {
		return c.String(http.StatusBadRequest, err.Error())
	}

	response, err := cg.Accessors.Share(c, token.Email)
	if err != nil {
		return c.String(http.StatusBadRequest, err.Error())
	}

	return c.JSON(http.StatusOK, response)
}

func (cg *ControllerGroup) GetSharing(c echo.Context) error {
	token, err := helpers.ValidateJWT(c)
	if err != nil {
		return c.String(http.StatusBadRequest, err.Error())
	}

	response, err := cg.Accessors.GetSharing(c, token.Email)
	if err != nil {
		return c.String(http.StatusBadRequest, err.Error())
	}

	return c.JSON(http.StatusOK, response)
}
<|endoftext|>


<commit_before>// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
package main_test

import "testing"
import "os"

import "v.io/core/veyron/lib/testutil"
import "v.io/core/veyron/lib/testutil/v23tests"

func TestMain(m *testing.M) {
	testutil.Init()
	// TODO(cnicolaou): call modules.Dispatch and remove the need for TestHelperProcess
	os.Exit(m.Run())
}

func TestV23Agentd(t *testing.T) {
	v23tests.RunTest(t, V23TestAgentd)
}
<commit_msg>TBR: fix go-generate build.<commit_after>// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
package main_test

import "testing"
import "os"

import "v.io/core/veyron/lib/testutil"
import "v.io/core/veyron/lib/testutil/v23tests"

func TestMain(m *testing.M) {
	testutil.Init()
	cleanup := v23tests.UseSharedBinDir()
	r := m.Run()
	cleanup()
	// TODO(cnicolaou): call modules.Dispatch and remove the need for TestHelperProcess
	os.Exit(r)
}

func TestV23Agentd(t *testing.T) {
	v23tests.RunTest(t, V23TestAgentd)
}
<|endoftext|>


<commit_before>package geo

import "math"

// Rect defines rectangular coordinates.
type Rect struct {
	X, Y, W, H float64
}

// Top returns the top boundary.
func (r Rect) Top() (top float64) {
	return r.Y
}

// SetTop sets the top boundary.
func (r *Rect) SetTop(top float64) {
	r.Y = top
}

// Bottom returns the bottom boundary.
func (r Rect) Bottom() float64 {
	return r.Y + r.H
}

// SetBottom sets the bottom boundary.
func (r *Rect) SetBottom(bottom float64) {
	r.Y = bottom - r.H
}

// Left returns the left boundary.
func (r Rect) Left() float64 {
	return r.X
}

// SetLeft sets the left boundary.
func (r *Rect) SetLeft(left float64) {
	r.X = left
}

// Right returns the right boundary.
func (r Rect) Right() float64 {
	return r.X + r.W
}

// SetRight sets the right boundary.
func (r *Rect) SetRight(right float64) {
	r.X = right - r.W
}

// Width returns the width.
func (r Rect) Width() float64 {
	return r.W
}

// SetWidth sets the width.
func (r *Rect) SetWidth(w float64) {
	r.W = w
}

// Height returns the height.
func (r Rect) Height() float64 {
	return r.H
}

// SetHeight sets the height.
func (r *Rect) SetHeight(h float64) {
	r.H = h
}

// Size returns the width and height.
func (r Rect) Size() (w, h float64) {
	return r.W, r.H
}

// SetSize sets the width and height.
func (r *Rect) SetSize(w, h float64) {
	r.SetWidth(w)
	r.SetHeight(h)
}

// TopLeft returns the coordinates of the top left corner.
func (r Rect) TopLeft() (x, y float64) {
	return r.Left(), r.Top()
}

// SetTopLeft sets the coordinates of the top left corner.
func (r *Rect) SetTopLeft(x, y float64) {
	r.SetLeft(x)
	r.SetRight(y)
}

// BottomLeft returns the coordinates of the bottom left corner.
func (r Rect) BottomLeft() (x, y float64) {
	return r.Left(), r.Bottom()
}

// SetBottomLeft set the coordinates of the bottom left corner.
func (r *Rect) SetBottomLeft(x, y float64) {
	r.SetLeft(x)
	r.SetBottom(y)
}

// TopRight returns the coordinates of the top right corner.
func (r Rect) TopRight() (x, y float64) {
	return r.Right(), r.Top()
}

// SetTopRight sets the coordinates of the top right corner.
func (r *Rect) SetTopRight(x, y float64) {
	r.SetRight(x)
	r.SetTop(y)
}

// BottomRight returns the coordinates of the bottom right corner.
func (r Rect) BottomRight() (x, y float64) {
	return r.Right(), r.Bottom()
}

// SetBottomRight sets the coordinates of the bottom right corner.
func (r *Rect) SetBottomRight(x, y float64) {
	r.SetRight(x)
	r.SetBottom(y)
}

// MidTop returns the coordinates at the top of the rectangle above the center.
func (r Rect) MidTop() (x, y float64) {
	return r.CenterX(), r.Top()
}

// SetMidTop sets the coordinates at the top of the rectangle above the center.
func (r *Rect) SetMidTop(x, y float64) {
	r.SetCenterX(x)
	r.SetTop(y)
}

// MidBottom returns the coordinates at the bottom of the rectangle below the center.
func (r Rect) MidBottom() (x, y float64) {
	return r.CenterX(), r.Bottom()
}

// SetMidBottom sets the coordinates at the bottom of the rectangle below the center.
func (r *Rect) SetMidBottom(x, y float64) {
	r.SetCenterX(x)
	r.SetBottom(y)
}

// MidLeft returns the coordinates at the left of the rectangle in line with the center.
func (r Rect) MidLeft() (x, y float64) {
	return r.Left(), r.CenterY()
}

// SetMidLeft sets the coordinates at the left of the rectangle in line with the center.
func (r *Rect) SetMidLeft(x, y float64) {
	r.SetLeft(x)
	r.SetCenterY(y)
}

// MidRight returns the coordinates at the right of the rectangle in line with the center.
func (r Rect) MidRight() (x, y float64) {
	return r.Right(), r.CenterY()
}

// SetMidRight sets the coordinates at the right of the rectangle in line with the center.
func (r *Rect) SetMidRight(x, y float64) {
	r.SetRight(x)
	r.SetCenterY(y)
}

// Center returns the center coordinates.
func (r Rect) Center() (x, y float64) {
	return r.CenterX(), r.CenterY()
}

// SetCenter sets the center coordinates.
func (r *Rect) SetCenter(x, y float64) {
	r.SetCenterX(x)
	r.SetCenterY(y)
}

// CenterX returns the center x coordinates
func (r Rect) CenterX() float64 {
	return r.X + r.W/2
}

// SetCenterX sets the center x coordinates.
func (r *Rect) SetCenterX(x float64) {
	r.X = x - r.W/2
}

// CenterY returns the center y coordinates.
func (r Rect) CenterY() float64 {
	return r.Y + r.H/2
}

// SetCenterY set the center y coordinates.
func (r *Rect) SetCenterY(y float64) {
	r.Y = y - r.H/2
}

// Area returns the area of the rectangle.
func (r Rect) Area() float64 {
	return r.W * r.H
}

// Move moves the Rect by the given offset, in place.
func (r *Rect) Move(dx, dy float64) {
	r.X += dx
	r.Y += dy
}

// Moved returns a new Rect moved by the given offset relative to this one.
func (r Rect) Moved(dx, dy float64) Rect {
	return Rect{X: r.X + dx, Y: r.Y + dy, W: r.W, H: r.H}
}

// Inflate keeps the same center but changes the size by the given amount, in place.
func (r *Rect) Inflate(dw, dh float64) {
	r.X -= dw / 2
	r.Y -= dh / 2
	r.W += dw
	r.H += dh
}

// Inflated returns a new Rect with the same center whose size is chaged by the given amount.
func (r Rect) Inflated(dw, dh float64) Rect {
	return Rect{X: r.X - dw/2, Y: r.Y - dh/2, W: r.W + dw, H: r.H + dh}
}

// Clamp moves this Rect so that it is within bounds. If it is too large than it is
// centered within bounds.
func (r *Rect) Clamp(bounds Rect) {
	if r.W > bounds.W {
		r.SetCenterX(bounds.CenterX())
	} else {
		r.X = clamp(r.X, bounds.X, bounds.Right()-r.W)
	}
	if r.H > bounds.H {
		r.SetCenterY(bounds.CenterY())
	} else {
		r.Y = clamp(r.Y, bounds.Y, bounds.Bottom()-r.H)
	}
}

// Clamped returns a new Rect that is moved to be within bounds. If it is too large than it
// is centered within bounds.
func (r Rect) Clamped(bounds Rect) Rect {
	var newX, newY float64
	if r.W > bounds.W {
		newX = bounds.CenterX() - r.W/2
	} else {
		newX = clamp(r.X, bounds.X, bounds.Right()-r.W)
	}
	if r.H > bounds.H {
		newY = bounds.CenterY() - r.H/2
	} else {
		newY = clamp(r.Y, bounds.Y, bounds.Bottom()-r.H)
	}
	return Rect{X: newX, Y: newY, W: r.W, H: r.H}
}

// Intersect returns a new Rect that marks the area where the two overlap. If there is
// no intersection the returned Rect will have 0 size.
func (r Rect) Intersect(other Rect) Rect {
	newX := math.Max(r.X, other.X)
	newY := math.Max(r.Y, other.Y)
	return Rect{
		X: newX,
		Y: newY,
		W: math.Min(r.Right(), other.Right()) - newX,
		H: math.Min(r.Bottom(), other.Bottom()) - newY,
	}
}

// Union modifies this Rect to contain both itself and other.
func (r *Rect) Union(other Rect) {
	newX := math.Min(r.X, other.X)
	newY := math.Min(r.Y, other.Y)
	r.W = math.Max(r.Right(), other.Right()) - newX
	r.H = math.Max(r.Bottom(), other.Bottom()) - newY
	r.X = newX
	r.Y = newY
}

// Unioned retruns a new Rect that contain both Rects.
func (r Rect) Unioned(other Rect) Rect {
	newX := math.Min(r.X, other.X)
	newY := math.Min(r.Y, other.Y)
	r.W = math.Max(r.Right(), other.Right()) - newX
	r.H = math.Max(r.Bottom(), other.Bottom()) - newY
	r.X = newX
	r.Y = newY
	return r
}

// Fit modifies this Rect so that it is moved and resized to fit within bounds while maintaining
// its original aspect ratio.
func (r *Rect) Fit(bounds Rect) {
	newW := bounds.H * (r.W / r.H)
	if newW <= bounds.W {
		r.X = clamp(r.X, bounds.X, bounds.Right()-newW)
		r.Y = bounds.Y
		r.W = newW
		r.H = bounds.H
		return
	}
	newH := bounds.W * (r.H / r.W)
	r.X = bounds.X
	r.Y = clamp(r.Y, bounds.Y, bounds.Bottom()-newH)
	r.W = bounds.W
	r.H = newH
}

// Fitted returns a new Rect that is moved and resized to fit within bounds while maintaining
// its original aspect ratio.
func (r Rect) Fitted(bounds Rect) Rect {
	newW := bounds.H * (r.W / r.H)
	if newW <= bounds.W {
		return Rect{X: clamp(r.X, bounds.X, bounds.Right()-newW), Y: bounds.Y, W: newW, H: bounds.H}
	}
	newH := bounds.W * (r.H / r.W)
	return Rect{X: bounds.X, Y: clamp(r.Y, bounds.Y, bounds.Bottom()-newH), W: bounds.W, H: newH}
}

// Normalize fips the Rect in place if its size is negative.
func (r *Rect) Normalize() {
	if r.W < 0 {
		r.X += r.W
		r.W = -r.W
	}
	if r.H < 0 {
		r.Y += r.H
		r.H = -r.H
	}
}

// Normalized returns a fipped but equivalent Rect if its size is negative.
func (r Rect) Normalized() Rect {
	r.Normalize()
	return r
}

// Contains returns true if other is completely inside this one.
func (r Rect) Contains(other Rect) bool {
	return other.X >= r.X && other.Y >= r.Y && other.Right() <= r.Right() && other.Bottom() <= r.Bottom()
}

// CollidePoint returns true if the point is within the Rect. A point along the right or
// bottom edge is not considered inside.
func (r Rect) CollidePoint(x, y float64) bool {
	return x >= r.X && x < r.Right() && y >= r.Y && y < r.Bottom()
}

// CollideRect returns true if the Rects overlap.
func (r Rect) CollideRect(other Rect) bool {
	return r.X < other.Right() && r.Right() > other.X && r.Y < other.Bottom() && r.Bottom() > other.Y
}

// CollideList returns the index of the first Rect this one collides with, or -1 if it
// collides with none.
func (r Rect) CollideList(others []Rect) int {
	for i, other := range others {
		if r.CollideRect(other) {
			return i
		}
	}
	return -1
}

// CollideListAll returns a list of indices of the Rects that collide with this one, or an
// empty list if none.
func (r Rect) CollideListAll(others []Rect) []int {
	list := make([]int, 0, len(others))
	for i, other := range others {
		if r.CollideRect(other) {
			list = append(list, i)
		}
	}
	return list
}

func clamp(i, min, max float64) float64 {
	return math.Max(math.Min(i, max), min)
}

// RectUnion returns a Rect that contains all the given Rects. An empty list returns a
// Rect with size 0.
func RectUnion(rects []Rect) Rect {
	if len(rects) == 0 {
		return Rect{}
	}

	newX, newY := rects[0].X, rects[0].Y
	for _, r := range rects {
		newX = math.Min(newX, r.X)
		newY = math.Min(newY, r.Y)
	}

	farRight, farBottom := rects[0].Right(), rects[0].Bottom()
	for _, r := range rects {
		farRight = math.Max(farRight, r.Right())
		farBottom = math.Max(farBottom, r.Bottom())
	}

	return Rect{X: newX, Y: newY, W: farRight - newX, H: farBottom - newY}
}
<commit_msg>Fix SetTopLeft.<commit_after>package geo

import "math"

// Rect defines rectangular coordinates.
type Rect struct {
	X, Y, W, H float64
}

// Top returns the top boundary.
func (r Rect) Top() (top float64) {
	return r.Y
}

// SetTop sets the top boundary.
func (r *Rect) SetTop(top float64) {
	r.Y = top
}

// Bottom returns the bottom boundary.
func (r Rect) Bottom() float64 {
	return r.Y + r.H
}

// SetBottom sets the bottom boundary.
func (r *Rect) SetBottom(bottom float64) {
	r.Y = bottom - r.H
}

// Left returns the left boundary.
func (r Rect) Left() float64 {
	return r.X
}

// SetLeft sets the left boundary.
func (r *Rect) SetLeft(left float64) {
	r.X = left
}

// Right returns the right boundary.
func (r Rect) Right() float64 {
	return r.X + r.W
}

// SetRight sets the right boundary.
func (r *Rect) SetRight(right float64) {
	r.X = right - r.W
}

// Width returns the width.
func (r Rect) Width() float64 {
	return r.W
}

// SetWidth sets the width.
func (r *Rect) SetWidth(w float64) {
	r.W = w
}

// Height returns the height.
func (r Rect) Height() float64 {
	return r.H
}

// SetHeight sets the height.
func (r *Rect) SetHeight(h float64) {
	r.H = h
}

// Size returns the width and height.
func (r Rect) Size() (w, h float64) {
	return r.W, r.H
}

// SetSize sets the width and height.
func (r *Rect) SetSize(w, h float64) {
	r.SetWidth(w)
	r.SetHeight(h)
}

// TopLeft returns the coordinates of the top left corner.
func (r Rect) TopLeft() (x, y float64) {
	return r.Left(), r.Top()
}

// SetTopLeft sets the coordinates of the top left corner.
func (r *Rect) SetTopLeft(x, y float64) {
	r.SetLeft(x)
	r.SetTop(y)
}

// BottomLeft returns the coordinates of the bottom left corner.
func (r Rect) BottomLeft() (x, y float64) {
	return r.Left(), r.Bottom()
}

// SetBottomLeft set the coordinates of the bottom left corner.
func (r *Rect) SetBottomLeft(x, y float64) {
	r.SetLeft(x)
	r.SetBottom(y)
}

// TopRight returns the coordinates of the top right corner.
func (r Rect) TopRight() (x, y float64) {
	return r.Right(), r.Top()
}

// SetTopRight sets the coordinates of the top right corner.
func (r *Rect) SetTopRight(x, y float64) {
	r.SetRight(x)
	r.SetTop(y)
}

// BottomRight returns the coordinates of the bottom right corner.
func (r Rect) BottomRight() (x, y float64) {
	return r.Right(), r.Bottom()
}

// SetBottomRight sets the coordinates of the bottom right corner.
func (r *Rect) SetBottomRight(x, y float64) {
	r.SetRight(x)
	r.SetBottom(y)
}

// MidTop returns the coordinates at the top of the rectangle above the center.
func (r Rect) MidTop() (x, y float64) {
	return r.CenterX(), r.Top()
}

// SetMidTop sets the coordinates at the top of the rectangle above the center.
func (r *Rect) SetMidTop(x, y float64) {
	r.SetCenterX(x)
	r.SetTop(y)
}

// MidBottom returns the coordinates at the bottom of the rectangle below the center.
func (r Rect) MidBottom() (x, y float64) {
	return r.CenterX(), r.Bottom()
}

// SetMidBottom sets the coordinates at the bottom of the rectangle below the center.
func (r *Rect) SetMidBottom(x, y float64) {
	r.SetCenterX(x)
	r.SetBottom(y)
}

// MidLeft returns the coordinates at the left of the rectangle in line with the center.
func (r Rect) MidLeft() (x, y float64) {
	return r.Left(), r.CenterY()
}

// SetMidLeft sets the coordinates at the left of the rectangle in line with the center.
func (r *Rect) SetMidLeft(x, y float64) {
	r.SetLeft(x)
	r.SetCenterY(y)
}

// MidRight returns the coordinates at the right of the rectangle in line with the center.
func (r Rect) MidRight() (x, y float64) {
	return r.Right(), r.CenterY()
}

// SetMidRight sets the coordinates at the right of the rectangle in line with the center.
func (r *Rect) SetMidRight(x, y float64) {
	r.SetRight(x)
	r.SetCenterY(y)
}

// Center returns the center coordinates.
func (r Rect) Center() (x, y float64) {
	return r.CenterX(), r.CenterY()
}

// SetCenter sets the center coordinates.
func (r *Rect) SetCenter(x, y float64) {
	r.SetCenterX(x)
	r.SetCenterY(y)
}

// CenterX returns the center x coordinates
func (r Rect) CenterX() float64 {
	return r.X + r.W/2
}

// SetCenterX sets the center x coordinates.
func (r *Rect) SetCenterX(x float64) {
	r.X = x - r.W/2
}

// CenterY returns the center y coordinates.
func (r Rect) CenterY() float64 {
	return r.Y + r.H/2
}

// SetCenterY set the center y coordinates.
func (r *Rect) SetCenterY(y float64) {
	r.Y = y - r.H/2
}

// Area returns the area of the rectangle.
func (r Rect) Area() float64 {
	return r.W * r.H
}

// Move moves the Rect by the given offset, in place.
func (r *Rect) Move(dx, dy float64) {
	r.X += dx
	r.Y += dy
}

// Moved returns a new Rect moved by the given offset relative to this one.
func (r Rect) Moved(dx, dy float64) Rect {
	return Rect{X: r.X + dx, Y: r.Y + dy, W: r.W, H: r.H}
}

// Inflate keeps the same center but changes the size by the given amount, in place.
func (r *Rect) Inflate(dw, dh float64) {
	r.X -= dw / 2
	r.Y -= dh / 2
	r.W += dw
	r.H += dh
}

// Inflated returns a new Rect with the same center whose size is chaged by the given amount.
func (r Rect) Inflated(dw, dh float64) Rect {
	return Rect{X: r.X - dw/2, Y: r.Y - dh/2, W: r.W + dw, H: r.H + dh}
}

// Clamp moves this Rect so that it is within bounds. If it is too large than it is
// centered within bounds.
func (r *Rect) Clamp(bounds Rect) {
	if r.W > bounds.W {
		r.SetCenterX(bounds.CenterX())
	} else {
		r.X = clamp(r.X, bounds.X, bounds.Right()-r.W)
	}
	if r.H > bounds.H {
		r.SetCenterY(bounds.CenterY())
	} else {
		r.Y = clamp(r.Y, bounds.Y, bounds.Bottom()-r.H)
	}
}

// Clamped returns a new Rect that is moved to be within bounds. If it is too large than it
// is centered within bounds.
func (r Rect) Clamped(bounds Rect) Rect {
	var newX, newY float64
	if r.W > bounds.W {
		newX = bounds.CenterX() - r.W/2
	} else {
		newX = clamp(r.X, bounds.X, bounds.Right()-r.W)
	}
	if r.H > bounds.H {
		newY = bounds.CenterY() - r.H/2
	} else {
		newY = clamp(r.Y, bounds.Y, bounds.Bottom()-r.H)
	}
	return Rect{X: newX, Y: newY, W: r.W, H: r.H}
}

// Intersect returns a new Rect that marks the area where the two overlap. If there is
// no intersection the returned Rect will have 0 size.
func (r Rect) Intersect(other Rect) Rect {
	newX := math.Max(r.X, other.X)
	newY := math.Max(r.Y, other.Y)
	return Rect{
		X: newX,
		Y: newY,
		W: math.Min(r.Right(), other.Right()) - newX,
		H: math.Min(r.Bottom(), other.Bottom()) - newY,
	}
}

// Union modifies this Rect to contain both itself and other.
func (r *Rect) Union(other Rect) {
	newX := math.Min(r.X, other.X)
	newY := math.Min(r.Y, other.Y)
	r.W = math.Max(r.Right(), other.Right()) - newX
	r.H = math.Max(r.Bottom(), other.Bottom()) - newY
	r.X = newX
	r.Y = newY
}

// Unioned retruns a new Rect that contain both Rects.
func (r Rect) Unioned(other Rect) Rect {
	newX := math.Min(r.X, other.X)
	newY := math.Min(r.Y, other.Y)
	r.W = math.Max(r.Right(), other.Right()) - newX
	r.H = math.Max(r.Bottom(), other.Bottom()) - newY
	r.X = newX
	r.Y = newY
	return r
}

// Fit modifies this Rect so that it is moved and resized to fit within bounds while maintaining
// its original aspect ratio.
func (r *Rect) Fit(bounds Rect) {
	newW := bounds.H * (r.W / r.H)
	if newW <= bounds.W {
		r.X = clamp(r.X, bounds.X, bounds.Right()-newW)
		r.Y = bounds.Y
		r.W = newW
		r.H = bounds.H
		return
	}
	newH := bounds.W * (r.H / r.W)
	r.X = bounds.X
	r.Y = clamp(r.Y, bounds.Y, bounds.Bottom()-newH)
	r.W = bounds.W
	r.H = newH
}

// Fitted returns a new Rect that is moved and resized to fit within bounds while maintaining
// its original aspect ratio.
func (r Rect) Fitted(bounds Rect) Rect {
	newW := bounds.H * (r.W / r.H)
	if newW <= bounds.W {
		return Rect{X: clamp(r.X, bounds.X, bounds.Right()-newW), Y: bounds.Y, W: newW, H: bounds.H}
	}
	newH := bounds.W * (r.H / r.W)
	return Rect{X: bounds.X, Y: clamp(r.Y, bounds.Y, bounds.Bottom()-newH), W: bounds.W, H: newH}
}

// Normalize fips the Rect in place if its size is negative.
func (r *Rect) Normalize() {
	if r.W < 0 {
		r.X += r.W
		r.W = -r.W
	}
	if r.H < 0 {
		r.Y += r.H
		r.H = -r.H
	}
}

// Normalized returns a fipped but equivalent Rect if its size is negative.
func (r Rect) Normalized() Rect {
	r.Normalize()
	return r
}

// Contains returns true if other is completely inside this one.
func (r Rect) Contains(other Rect) bool {
	return other.X >= r.X && other.Y >= r.Y && other.Right() <= r.Right() && other.Bottom() <= r.Bottom()
}

// CollidePoint returns true if the point is within the Rect. A point along the right or
// bottom edge is not considered inside.
func (r Rect) CollidePoint(x, y float64) bool {
	return x >= r.X && x < r.Right() && y >= r.Y && y < r.Bottom()
}

// CollideRect returns true if the Rects overlap.
func (r Rect) CollideRect(other Rect) bool {
	return r.X < other.Right() && r.Right() > other.X && r.Y < other.Bottom() && r.Bottom() > other.Y
}

// CollideList returns the index of the first Rect this one collides with, or -1 if it
// collides with none.
func (r Rect) CollideList(others []Rect) int {
	for i, other := range others {
		if r.CollideRect(other) {
			return i
		}
	}
	return -1
}

// CollideListAll returns a list of indices of the Rects that collide with this one, or an
// empty list if none.
func (r Rect) CollideListAll(others []Rect) []int {
	list := make([]int, 0, len(others))
	for i, other := range others {
		if r.CollideRect(other) {
			list = append(list, i)
		}
	}
	return list
}

func clamp(i, min, max float64) float64 {
	return math.Max(math.Min(i, max), min)
}

// RectUnion returns a Rect that contains all the given Rects. An empty list returns a
// Rect with size 0.
func RectUnion(rects []Rect) Rect {
	if len(rects) == 0 {
		return Rect{}
	}

	newX, newY := rects[0].X, rects[0].Y
	for _, r := range rects {
		newX = math.Min(newX, r.X)
		newY = math.Min(newY, r.Y)
	}

	farRight, farBottom := rects[0].Right(), rects[0].Bottom()
	for _, r := range rects {
		farRight = math.Max(farRight, r.Right())
		farBottom = math.Max(farBottom, r.Bottom())
	}

	return Rect{X: newX, Y: newY, W: farRight - newX, H: farBottom - newY}
}
<|endoftext|>


<commit_before>package espsdk

import (
	"encoding/json"
	"fmt"
	"time"

	log "github.com/Sirupsen/logrus"
)

// A Batch is a container for Contributions of the same type and
// any Releases that may be associated with them.
type Batch struct {
	AssignmentID                     string     `json:"assignment_id,omitempty"`
	BatchTags                        []string   `json:"batch_tags,omitempty"`
	BriefID                          string     `json:"brief_id,omitempty"`
	ContributionsAwaitingReviewCount int        `json:"contributions_awaiting_review_count,omitempty"`
	ContributionsCount               int        `json:"contributions_count,omitempty"`
	CreatedAt                        *time.Time `json:"created_at,omitempty"`
	CreatedBy                        string     `json:"created_by,omitempty"`
	CreatorIstockUsername            string     `json:"creator_istock_username,omitempty"`
	EventID                          string     `json:"event_id,omitempty"`
	ID                               int        `json:"id,omitempty"`
	IsGetty                          bool       `json:"is_getty,omitempty"`
	IsIstock                         bool       `json:"is_istock,omitempty"`
	IstockExclusive                  bool       `json:"istock_exclusive,omitempty"`
	LastContributionSubmittedAt      *time.Time `json:"last_contribution_submitted_at,omitempty"`
	LastSubmittedAt                  *time.Time `json:"last_submitted_at,omitempty"`
	Note                             string     `json:"note,omitempty"`
	ProfileID                        int        `json:"profile_id,omitempty"`
	ReviewedContributionsCount       int        `json:"reviewed_contributions_count,omitempty"`
	RevisableContributionsCount      int        `json:"revisable_contributions_count,omitempty"`
	SaveExtractedMetadata            bool       `json:"save_extracted_metadata,omitempty"`
	Status                           string     `json:"status,omitempty"`
	SubmissionName                   string     `json:"submission_name,omitempty"`
	SubmissionType                   string     `json:"submission_type,omitempty"`
	SubmittedContributionsCount      int        `json:"submitted_contributions_count,omitempty"`
	UpdatedAt                        *time.Time `json:"updated_at,omitempty"`
	UserID                           string     `json:"user_id,omitempty"`
}

// NameIsValid provides validation for a proposed SubmissionName.
func (b Batch) NameIsValid() bool { return len(b.SubmissionName) > 0 }

// TypeIsValid reports whether a proposed type is valid for ESP.
func (b *Batch) TypeIsValid() bool { return batchTypeIsValid[b.SubmissionType] }

// ValidTypes are the BatchTypes supported by ESP.
func (b Batch) ValidTypes() []string {
	keys := make([]string, len(batchTypeIsValid))
	i := 0
	for k := range batchTypeIsValid {
		keys[i] = k
		i++
	}
	return keys
}

// Path returns the path for the Batch. If the Batch has no ID, Path returns
// the root for all Batches (the Batch Index).
func (b Batch) Path() string {
	if b.ID == 0 {
		return Batches
	}
	return fmt.Sprintf("%s/%d", Batches, b.ID)
}

// A BatchUpdate contains a Batch. This matches the
// structure of the JSON payload the API expects during a PUT.
type BatchUpdate struct {
	Batch Batch `json:"submission_batch"`
}

// Path returns the path of the batch being updated.
func (bu BatchUpdate) Path() string { return bu.Batch.Path() }

// Marshal serializes a BatchUpdate into a byte slice.
func (bu BatchUpdate) Marshal() ([]byte, error) { return indentedJSON(bu) }

var batchTypeIsValid = map[string]bool{
	"getty_creative_video":  true,
	"getty_editorial_video": true,
	"getty_creative_still":  true,
	"getty_editorial_still": true,
	"istock_creative_video": true,
}

// A BatchListContainer matches the structure of the JSON payload returned
// by the GET (all) Batches API endpoint.
type BatchList struct {
	Items []Batch `json:"items"`
	Meta  struct {
		TotalItems int `json:"total_items"`
	} `json:"meta"`
}

// Unmarshal attempts to deserialize the provided JSON payload
// into the complete metadata returned by a request to the Index (GET all)
// API endpoint.
func (blc BatchList) Unmarshal(payload []byte) BatchList {
	var dest BatchList
	err := json.Unmarshal(payload, &dest)
	check(err)
	return dest
}

func check(err error) {
	if err != nil {
		log.Fatal(err)
	}
}
<commit_msg>enable easy retrieval of newest Batch<commit_after>package espsdk

import (
	"encoding/json"
	"fmt"
	"time"

	log "github.com/Sirupsen/logrus"
)

// A Batch is a container for Contributions of the same type and
// any Releases that may be associated with them.
type Batch struct {
	AssignmentID                     string     `json:"assignment_id,omitempty"`
	BatchTags                        []string   `json:"batch_tags,omitempty"`
	BriefID                          string     `json:"brief_id,omitempty"`
	ContributionsAwaitingReviewCount int        `json:"contributions_awaiting_review_count,omitempty"`
	ContributionsCount               int        `json:"contributions_count,omitempty"`
	CreatedAt                        *time.Time `json:"created_at,omitempty"`
	CreatedBy                        string     `json:"created_by,omitempty"`
	CreatorIstockUsername            string     `json:"creator_istock_username,omitempty"`
	EventID                          string     `json:"event_id,omitempty"`
	ID                               int        `json:"id,omitempty"`
	IsGetty                          bool       `json:"is_getty,omitempty"`
	IsIstock                         bool       `json:"is_istock,omitempty"`
	IstockExclusive                  bool       `json:"istock_exclusive,omitempty"`
	LastContributionSubmittedAt      *time.Time `json:"last_contribution_submitted_at,omitempty"`
	LastSubmittedAt                  *time.Time `json:"last_submitted_at,omitempty"`
	Note                             string     `json:"note,omitempty"`
	ProfileID                        int        `json:"profile_id,omitempty"`
	ReviewedContributionsCount       int        `json:"reviewed_contributions_count,omitempty"`
	RevisableContributionsCount      int        `json:"revisable_contributions_count,omitempty"`
	SaveExtractedMetadata            bool       `json:"save_extracted_metadata,omitempty"`
	Status                           string     `json:"status,omitempty"`
	SubmissionName                   string     `json:"submission_name,omitempty"`
	SubmissionType                   string     `json:"submission_type,omitempty"`
	SubmittedContributionsCount      int        `json:"submitted_contributions_count,omitempty"`
	UpdatedAt                        *time.Time `json:"updated_at,omitempty"`
	UserID                           string     `json:"user_id,omitempty"`
}

// NameIsValid provides validation for a proposed SubmissionName.
func (b Batch) NameIsValid() bool { return len(b.SubmissionName) > 0 }

// TypeIsValid reports whether a proposed type is valid for ESP.
func (b *Batch) TypeIsValid() bool { return batchTypeIsValid[b.SubmissionType] }

// ValidTypes are the BatchTypes supported by ESP.
func (b Batch) ValidTypes() []string {
	keys := make([]string, len(batchTypeIsValid))
	i := 0
	for k := range batchTypeIsValid {
		keys[i] = k
		i++
	}
	return keys
}

// Path returns the path for the Batch. If the Batch has no ID, Path returns
// the root for all Batches (the Batch Index).
func (b Batch) Path() string {
	if b.ID == 0 {
		return Batches
	}
	return fmt.Sprintf("%s/%d", Batches, b.ID)
}

// A BatchUpdate contains a Batch. This matches the
// structure of the JSON payload the API expects during a PUT.
type BatchUpdate struct {
	Batch Batch `json:"submission_batch"`
}

// Path returns the path of the batch being updated.
func (bu BatchUpdate) Path() string { return bu.Batch.Path() }

// Marshal serializes a BatchUpdate into a byte slice.
func (bu BatchUpdate) Marshal() ([]byte, error) { return indentedJSON(bu) }

var batchTypeIsValid = map[string]bool{
	"getty_creative_video":  true,
	"getty_editorial_video": true,
	"getty_creative_still":  true,
	"getty_editorial_still": true,
	"istock_creative_video": true,
}

// A BatchListContainer matches the structure of the JSON payload returned
// by the GET (all) Batches API endpoint.
type BatchList struct {
	Items []Batch `json:"items,omitempty"`
	Meta  struct {
		TotalItems int `json:"total_items,omitempty"`
	} `json:"meta,omitempty"`
}

// Unmarshal attempts to deserialize the provided JSON payload
// into the complete metadata returned by a request to the Index (GET all)
// API endpoint.
func (bl BatchList) Unmarshal(payload []byte) BatchList {
	var dest BatchList
	err := json.Unmarshal(payload, &dest)
	check(err)
	return dest
}

func (bl BatchList) Last() Batch {
	return bl.Items[len(bl.Items)-1]
}

func check(err error) {
	if err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package datastore

// basicBatch implements the transaction interface for datastores who do
// not have any sort of underlying transactional support
type basicBatch struct {
	puts    map[Key][]byte
	deletes map[Key]struct{}

	target Datastore
}

func NewBasicBatch(ds Datastore) Batch {
	return &basicBatch{
		puts:    make(map[Key][]byte),
		deletes: make(map[Key]struct{}),
		target:  ds,
	}
}

func (bt *basicBatch) Put(key Key, val []byte) error {
	bt.puts[key] = val
	return nil
}

func (bt *basicBatch) Delete(key Key) error {
	bt.deletes[key] = struct{}{}
	return nil
}

func (bt *basicBatch) Commit() error {
	for k, val := range bt.puts {
		if err := bt.target.Put(k, val); err != nil {
			return err
		}
	}

	for k, _ := range bt.deletes {
		if err := bt.target.Delete(k); err != nil {
			return err
		}
	}

	return nil
}
<commit_msg>make BasicBatch handle concurrent puts/deletes<commit_after>package datastore

type verb int

type op struct {
	delete bool
	value  []byte
}

// basicBatch implements the transaction interface for datastores who do
// not have any sort of underlying transactional support
type basicBatch struct {
	ops map[Key]op

	target Datastore
}

func NewBasicBatch(ds Datastore) Batch {
	return &basicBatch{
		ops:    make(map[Key]op),
		target: ds,
	}
}

func (bt *basicBatch) Put(key Key, val []byte) error {
	bt.ops[key] = op{value: val}
	return nil
}

func (bt *basicBatch) Delete(key Key) error {
	bt.ops[key] = op{delete: true}
	return nil
}

func (bt *basicBatch) Commit() error {
	var err error
	for k, op := range bt.ops {
		if op.delete {
			err = bt.target.Delete(k)
			// We could try to do something smarter but I really
			// don't care. Delete should be idempotent anyways.
			if err == ErrNotFound {
				err = nil
			}
		} else {
			err = bt.target.Put(k, op.value)
		}
		if err != nil {
			break
		}
	}

	return err
}
<|endoftext|>


<commit_before>package pgx

import (
	"context"

	"github.com/jackc/pgconn"
	"github.com/jackc/pgtype"
	errors "golang.org/x/xerrors"
)

type batchItem struct {
	query             string
	arguments         []interface{}
	parameterOIDs     []pgtype.OID
	resultFormatCodes []int16
}

// Batch queries are a way of bundling multiple queries together to avoid
// unnecessary network round trips.
type Batch struct {
	conn  *Conn
	items []*batchItem
	ctx   context.Context
	err   error

	mrr *pgconn.MultiResultReader
}

// BeginBatch returns a *Batch query for c.
func (c *Conn) BeginBatch() *Batch {
	return &Batch{conn: c}
}

// Conn returns the underlying connection that b will or was performed on.
func (b *Batch) Conn() *Conn {
	return b.conn
}

// Queue queues a query to batch b. query can be an SQL query or the name of a prepared statement. parameterOIDs and
// resultFormatCodes should be nil if query is a prepared statement. Otherwise, parameterOIDs are required if there are
// parameters and resultFormatCodes are required if there is a result.
func (b *Batch) Queue(query string, arguments []interface{}, parameterOIDs []pgtype.OID, resultFormatCodes []int16) {
	b.items = append(b.items, &batchItem{
		query:             query,
		arguments:         arguments,
		parameterOIDs:     parameterOIDs,
		resultFormatCodes: resultFormatCodes,
	})
}

// Send sends all queued queries to the server at once. All queries are run in an implicit transaction unless explicit
// transaction control statements are executed.
func (b *Batch) Send(ctx context.Context) error {
	if b.err != nil {
		return b.err
	}

	b.ctx = ctx

	batch := &pgconn.Batch{}

	for _, bi := range b.items {
		var parameterOIDs []pgtype.OID
		ps := b.conn.preparedStatements[bi.query]

		if ps != nil {
			parameterOIDs = ps.ParameterOIDs
		} else {
			parameterOIDs = bi.parameterOIDs
		}

		args, err := convertDriverValuers(bi.arguments)
		if err != nil {
			return err
		}

		paramFormats := make([]int16, len(args))
		paramValues := make([][]byte, len(args))
		for i := range args {
			paramFormats[i] = chooseParameterFormatCode(b.conn.ConnInfo, parameterOIDs[i], args[i])
			paramValues[i], err = newencodePreparedStatementArgument(b.conn.ConnInfo, parameterOIDs[i], args[i])
			if err != nil {
				return err
			}

		}

		if ps != nil {
			resultFormats := bi.resultFormatCodes
			if resultFormats == nil {
				resultFormats = make([]int16, len(ps.FieldDescriptions))
				for i := range resultFormats {
					if dt, ok := b.conn.ConnInfo.DataTypeForOID(ps.FieldDescriptions[i].DataType); ok {
						if _, ok := dt.Value.(pgtype.BinaryDecoder); ok {
							resultFormats[i] = BinaryFormatCode
						} else {
							resultFormats[i] = TextFormatCode
						}
					}
				}
			}

			batch.ExecPrepared(ps.Name, paramValues, paramFormats, resultFormats)
		} else {
			oids := make([]uint32, len(parameterOIDs))
			for i := 0; i < len(parameterOIDs); i++ {
				oids[i] = uint32(parameterOIDs[i])
			}
			batch.ExecParams(bi.query, paramValues, oids, paramFormats, bi.resultFormatCodes)
		}
	}

	b.mrr = b.conn.pgConn.ExecBatch(ctx, batch)

	return nil
}

// ExecResults reads the results from the next query in the batch as if the
// query has been sent with Exec.
func (b *Batch) ExecResults() (pgconn.CommandTag, error) {
	if !b.mrr.NextResult() {
		err := b.mrr.Close()
		if err == nil {
			err = errors.New("no result")
		}
		return nil, err
	}

	return b.mrr.ResultReader().Close()
}

// QueryResults reads the results from the next query in the batch as if the
// query has been sent with Query.
func (b *Batch) QueryResults() (Rows, error) {
	rows := b.conn.getRows("batch query", nil)

	if !b.mrr.NextResult() {
		rows.err = b.mrr.Close()
		if rows.err == nil {
			rows.err = errors.New("no result")
		}
		rows.closed = true
		return rows, rows.err
	}

	rows.resultReader = b.mrr.ResultReader()
	return rows, nil
}

// QueryRowResults reads the results from the next query in the batch as if the
// query has been sent with QueryRow.
func (b *Batch) QueryRowResults() Row {
	rows, _ := b.QueryResults()
	return (*connRow)(rows.(*connRows))

}

// Close closes the batch operation. Any error that occured during a batch
// operation may have made it impossible to resyncronize the connection with the
// server. In this case the underlying connection will have been closed.
func (b *Batch) Close() (err error) {
	return b.mrr.Close()
}

func (b *Batch) die(err error) {
	if b.err != nil {
		return
	}

	b.err = err
	b.conn.die(err)
}
<commit_msg>Remove unused Batch.ctx<commit_after>package pgx

import (
	"context"

	"github.com/jackc/pgconn"
	"github.com/jackc/pgtype"
	errors "golang.org/x/xerrors"
)

type batchItem struct {
	query             string
	arguments         []interface{}
	parameterOIDs     []pgtype.OID
	resultFormatCodes []int16
}

// Batch queries are a way of bundling multiple queries together to avoid
// unnecessary network round trips.
type Batch struct {
	conn  *Conn
	items []*batchItem
	err   error

	mrr *pgconn.MultiResultReader
}

// BeginBatch returns a *Batch query for c.
func (c *Conn) BeginBatch() *Batch {
	return &Batch{conn: c}
}

// Conn returns the underlying connection that b will or was performed on.
func (b *Batch) Conn() *Conn {
	return b.conn
}

// Queue queues a query to batch b. query can be an SQL query or the name of a prepared statement. parameterOIDs and
// resultFormatCodes should be nil if query is a prepared statement. Otherwise, parameterOIDs are required if there are
// parameters and resultFormatCodes are required if there is a result.
func (b *Batch) Queue(query string, arguments []interface{}, parameterOIDs []pgtype.OID, resultFormatCodes []int16) {
	b.items = append(b.items, &batchItem{
		query:             query,
		arguments:         arguments,
		parameterOIDs:     parameterOIDs,
		resultFormatCodes: resultFormatCodes,
	})
}

// Send sends all queued queries to the server at once. All queries are run in an implicit transaction unless explicit
// transaction control statements are executed.
func (b *Batch) Send(ctx context.Context) error {
	if b.err != nil {
		return b.err
	}

	batch := &pgconn.Batch{}

	for _, bi := range b.items {
		var parameterOIDs []pgtype.OID
		ps := b.conn.preparedStatements[bi.query]

		if ps != nil {
			parameterOIDs = ps.ParameterOIDs
		} else {
			parameterOIDs = bi.parameterOIDs
		}

		args, err := convertDriverValuers(bi.arguments)
		if err != nil {
			return err
		}

		paramFormats := make([]int16, len(args))
		paramValues := make([][]byte, len(args))
		for i := range args {
			paramFormats[i] = chooseParameterFormatCode(b.conn.ConnInfo, parameterOIDs[i], args[i])
			paramValues[i], err = newencodePreparedStatementArgument(b.conn.ConnInfo, parameterOIDs[i], args[i])
			if err != nil {
				return err
			}

		}

		if ps != nil {
			resultFormats := bi.resultFormatCodes
			if resultFormats == nil {
				resultFormats = make([]int16, len(ps.FieldDescriptions))
				for i := range resultFormats {
					if dt, ok := b.conn.ConnInfo.DataTypeForOID(ps.FieldDescriptions[i].DataType); ok {
						if _, ok := dt.Value.(pgtype.BinaryDecoder); ok {
							resultFormats[i] = BinaryFormatCode
						} else {
							resultFormats[i] = TextFormatCode
						}
					}
				}
			}

			batch.ExecPrepared(ps.Name, paramValues, paramFormats, resultFormats)
		} else {
			oids := make([]uint32, len(parameterOIDs))
			for i := 0; i < len(parameterOIDs); i++ {
				oids[i] = uint32(parameterOIDs[i])
			}
			batch.ExecParams(bi.query, paramValues, oids, paramFormats, bi.resultFormatCodes)
		}
	}

	b.mrr = b.conn.pgConn.ExecBatch(ctx, batch)

	return nil
}

// ExecResults reads the results from the next query in the batch as if the
// query has been sent with Exec.
func (b *Batch) ExecResults() (pgconn.CommandTag, error) {
	if !b.mrr.NextResult() {
		err := b.mrr.Close()
		if err == nil {
			err = errors.New("no result")
		}
		return nil, err
	}

	return b.mrr.ResultReader().Close()
}

// QueryResults reads the results from the next query in the batch as if the
// query has been sent with Query.
func (b *Batch) QueryResults() (Rows, error) {
	rows := b.conn.getRows("batch query", nil)

	if !b.mrr.NextResult() {
		rows.err = b.mrr.Close()
		if rows.err == nil {
			rows.err = errors.New("no result")
		}
		rows.closed = true
		return rows, rows.err
	}

	rows.resultReader = b.mrr.ResultReader()
	return rows, nil
}

// QueryRowResults reads the results from the next query in the batch as if the
// query has been sent with QueryRow.
func (b *Batch) QueryRowResults() Row {
	rows, _ := b.QueryResults()
	return (*connRow)(rows.(*connRows))

}

// Close closes the batch operation. Any error that occured during a batch
// operation may have made it impossible to resyncronize the connection with the
// server. In this case the underlying connection will have been closed.
func (b *Batch) Close() (err error) {
	return b.mrr.Close()
}

func (b *Batch) die(err error) {
	if b.err != nil {
		return
	}

	b.err = err
	b.conn.die(err)
}
<|endoftext|>


<commit_before>package chacha20

import (
	"bytes"
	"encoding/hex"
	"testing"
	"fmt"
)

// stolen from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-00#section-7
var testVectors = [][]string{
	[]string{
		"0000000000000000000000000000000000000000000000000000000000000000",
		"0000000000000000",
		"76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669",
	},
	[]string{
		"0000000000000000000000000000000000000000000000000000000000000001",
		"0000000000000000",
		"4540f05a9f1fb296d7736e7b208e3c96eb4fe1834688d2604f450952ed432d41bbe2a0b6ea7566d2a5d1e7e20d42af2c53d792b1c43fea817e9ad275",
	},
	[]string{
		"0000000000000000000000000000000000000000000000000000000000000000",
		"0000000000000001",
		"de9cba7bf3d69ef5e786dc63973f653a0b49e015adbff7134fcb7df137821031e85a050278a7084527214f73efc7fa5b5277062eb7a0433e445f41e3",
	},
	[]string{
		"0000000000000000000000000000000000000000000000000000000000000000",
		"0100000000000000",
		"ef3fdfd6c61578fbf5cf35bd3dd33b8009631634d21e42ac33960bd138e50d32111e4caf237ee53ca8ad6426194a88545ddc497a0b466e7d6bbdb004",
	},
	[]string{
		"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
		"0001020304050607",
		"f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f15916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c507b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb",
	},
}

func TestChaCha20(t *testing.T) {
	for i, vector := range testVectors {
		t.Logf("Running test vector %d", i)

		key, err := hex.DecodeString(vector[0])
		if err != nil {
			t.Error(err)
		}

		nonce, err := hex.DecodeString(vector[1])
		if err != nil {
			t.Error(err)
		}

		c, err := NewCipher(key, nonce)
		if err != nil {
			t.Error(err)
		}

		expected, err := hex.DecodeString(vector[2])
		if err != nil {
			t.Error(err)
		}

		src := make([]byte, len(expected))
		dst := make([]byte, len(expected))
		c.XORKeyStream(dst, src)

		if !bytes.Equal(expected, dst) {
			t.Errorf("Bad keystream: expected %x, was %x", expected, dst)

			for i, v := range expected {
				if dst[i] != v {
					t.Logf("Mismatch at offset %d: %x vs %x", i, v, dst[i])
					break
				}
			}
		}
	}
}

func ExampleCipher() {
	key, err := hex.DecodeString("60143a3d7c7137c3622d490e7dbb85859138d198d9c648960e186412a6250722")
	if err != nil {
		panic(err)
	}

	// A nonce should only be used once. Generate it randomly.
	nonce, err := hex.DecodeString("308c92676fa95973")
	if err != nil {
		panic(err)
	}

	c, err := NewCipher(key, nonce)
	if err != nil {
		panic(err)
	}

	src := []byte("hello I am a secret message")
	dst := make([]byte, len(src))

	c.XORKeyStream(dst, src)

	fmt.Printf("%x\n", dst)
	// Output:
	// a05452ebd981422dcdab2c9cde0d20a03f769e87d3e976ee6d6a11
}

const benchSize = 1024 * 1024

func BenchmarkChaCha20(b *testing.B) {
	b.SetBytes(benchSize)
	key := make([]byte, KeySize)
	nonce := make([]byte, NonceSize)
	input := make([]byte, benchSize)
	output := make([]byte, benchSize)
	c, _ := NewCipher(key, nonce)
	for i := 0; i < b.N; i++ {
		c.XORKeyStream(output, input)
	}
}
<commit_msg>Formatting changes.<commit_after>package chacha20

import (
	"bytes"
	"encoding/hex"
	"fmt"
	"testing"
)

// stolen from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-00#section-7
var testVectors = [][]string{
	[]string{
		"0000000000000000000000000000000000000000000000000000000000000000",
		"0000000000000000",
		"76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669",
	},
	[]string{
		"0000000000000000000000000000000000000000000000000000000000000001",
		"0000000000000000",
		"4540f05a9f1fb296d7736e7b208e3c96eb4fe1834688d2604f450952ed432d41bbe2a0b6ea7566d2a5d1e7e20d42af2c53d792b1c43fea817e9ad275",
	},
	[]string{
		"0000000000000000000000000000000000000000000000000000000000000000",
		"0000000000000001",
		"de9cba7bf3d69ef5e786dc63973f653a0b49e015adbff7134fcb7df137821031e85a050278a7084527214f73efc7fa5b5277062eb7a0433e445f41e3",
	},
	[]string{
		"0000000000000000000000000000000000000000000000000000000000000000",
		"0100000000000000",
		"ef3fdfd6c61578fbf5cf35bd3dd33b8009631634d21e42ac33960bd138e50d32111e4caf237ee53ca8ad6426194a88545ddc497a0b466e7d6bbdb004",
	},
	[]string{
		"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
		"0001020304050607",
		"f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f15916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c507b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb",
	},
}

func TestChaCha20(t *testing.T) {
	for i, vector := range testVectors {
		t.Logf("Running test vector %d", i)

		key, err := hex.DecodeString(vector[0])
		if err != nil {
			t.Error(err)
		}

		nonce, err := hex.DecodeString(vector[1])
		if err != nil {
			t.Error(err)
		}

		c, err := NewCipher(key, nonce)
		if err != nil {
			t.Error(err)
		}

		expected, err := hex.DecodeString(vector[2])
		if err != nil {
			t.Error(err)
		}

		src := make([]byte, len(expected))
		dst := make([]byte, len(expected))
		c.XORKeyStream(dst, src)

		if !bytes.Equal(expected, dst) {
			t.Errorf("Bad keystream: expected %x, was %x", expected, dst)

			for i, v := range expected {
				if dst[i] != v {
					t.Logf("Mismatch at offset %d: %x vs %x", i, v, dst[i])
					break
				}
			}
		}
	}
}

func ExampleCipher() {
	key, err := hex.DecodeString("60143a3d7c7137c3622d490e7dbb85859138d198d9c648960e186412a6250722")
	if err != nil {
		panic(err)
	}

	// A nonce should only be used once. Generate it randomly.
	nonce, err := hex.DecodeString("308c92676fa95973")
	if err != nil {
		panic(err)
	}

	c, err := NewCipher(key, nonce)
	if err != nil {
		panic(err)
	}

	src := []byte("hello I am a secret message")
	dst := make([]byte, len(src))

	c.XORKeyStream(dst, src)

	fmt.Printf("%x\n", dst)
	// Output:
	// a05452ebd981422dcdab2c9cde0d20a03f769e87d3e976ee6d6a11
}

const benchSize = 1024 * 1024

func BenchmarkChaCha20(b *testing.B) {
	b.SetBytes(benchSize)
	key := make([]byte, KeySize)
	nonce := make([]byte, NonceSize)
	input := make([]byte, benchSize)
	output := make([]byte, benchSize)
	c, _ := NewCipher(key, nonce)
	for i := 0; i < b.N; i++ {
		c.XORKeyStream(output, input)
	}
}
<|endoftext|>


<commit_before>package sqsadaptor

import "time"

// AggData type
type AggData struct {
	TotalReqs      int         `json:"total-reqs"`
	TotalTimedOut  int         `json:"total-timed-out"`
	AveTimeToFirst int         `json:"ave-time-to-first"`
	TotBytesRead   int         `json:"tot-bytes-read"`
	Statuses       map[int]int `json:"statuses"`
	AveTimeForReq  int64       `json:"ave-time-for-req"`
	AveReqPerSec   int         `json:"ave-req-per-sec"`
	Slowest        int64       `json:"slowest"`
	Fastest        int64       `json:"fastest"`
}

// RegionsAggData type
type RegionsAggData struct {
	Regions map[string]AggData
}

// Aggregate listens for results and sends totals
func Aggregate(outChan chan RegionsAggData, queueURL string, totalExpectedRequests int) {
	defer close(outChan)
	data := RegionsAggData{make(map[string]AggData)}

	adaptor := NewSQSAdaptor(queueURL)
	timeoutStart := time.Now()
	for {
		result := adaptor.Receive()
		if result != nil {

			outChan <- data
			timeoutStart = time.Now()
		} else {
			waited := time.Since(timeoutStart)
			if waited.Seconds() > 10 {
				break
			}
		}
	}
}
<commit_msg>Change totalExpectedRequests to uint<commit_after>package sqsadaptor

import "time"

// AggData type
type AggData struct {
	TotalReqs      int         `json:"total-reqs"`
	TotalTimedOut  int         `json:"total-timed-out"`
	AveTimeToFirst int         `json:"ave-time-to-first"`
	TotBytesRead   int         `json:"tot-bytes-read"`
	Statuses       map[int]int `json:"statuses"`
	AveTimeForReq  int64       `json:"ave-time-for-req"`
	AveReqPerSec   int         `json:"ave-req-per-sec"`
	Slowest        int64       `json:"slowest"`
	Fastest        int64       `json:"fastest"`
}

// RegionsAggData type
type RegionsAggData struct {
	Regions map[string]AggData
}

// Aggregate listens for results and sends totals
func Aggregate(outChan chan RegionsAggData, queueURL string, totalExpectedRequests uint) {
	defer close(outChan)
	data := RegionsAggData{make(map[string]AggData)}

	adaptor := NewSQSAdaptor(queueURL)
	timeoutStart := time.Now()
	for {
		result := adaptor.Receive()
		if result != nil {

			outChan <- data
			timeoutStart = time.Now()
		} else {
			waited := time.Since(timeoutStart)
			if waited.Seconds() > 10 {
				break
			}
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 Jeremy Wall (jeremy@marzhillstudios.com)
// Use of this source code is governed by the Artistic License 2.0.
// That License is included in the LICENSE file.
package main

import (
	"fmt"
	"log"
	"os"
	"strings"

	"github.com/blevesearch/bleve"
	"github.com/blevesearch/bleve/analysis"
	"github.com/blevesearch/bleve/analysis/char/html"
	"github.com/blevesearch/bleve/analysis/lang/en"
	"github.com/blevesearch/bleve/mapping"
	"github.com/blevesearch/bleve/registry"
	"github.com/blevesearch/bleve/search/highlight/highlighter/ansi"
)

const htmlMimeType = "text/html"

// handle text/html types
func init() {
	registry.RegisterAnalyzer(htmlMimeType, func(config map[string]interface{}, cache *registry.Cache) (*analysis.Analyzer, error) {
		a, err := en.AnalyzerConstructor(config, cache)
		if err != nil {
			if cf, err := cache.CharFilterNamed(html.Name); err == nil {
				a.CharFilters = []analysis.CharFilter{cf}
			} else {
				return nil, err
			}
		}

		return a, err
	})
}

func buildHtmlDocumentMapping() *mapping.DocumentMapping {
	dm := bleve.NewDocumentMapping()
	dm.DefaultAnalyzer = htmlMimeType
	return dm
}

type Index interface {
	Put(data *IFile) error
	Query(terms []string) (*bleve.SearchResult, error)
	Close() error
}

type bleveIndex struct {
	index bleve.Index
}

func (i *bleveIndex) Put(data *IFile) error {
	if err := i.index.Index((*data).Path(), data); err != nil {
		return fmt.Errorf("Error writing to index: %q", err)
	}
	return nil
}

func (i *bleveIndex) Query(terms []string) (*bleve.SearchResult, error) {
	searchQuery := strings.Join(terms, " ")
	query := bleve.NewQueryStringQuery(searchQuery)
	// TODO(jwall): limit, skip, and explain should be configurable.
	request := bleve.NewSearchRequestOptions(query, *limit, *from, false)
	if *useHighlight {
		request.Highlight = bleve.NewHighlightWithStyle(ansi.Name)
	} else {
		request.Highlight = bleve.NewHighlight()
	}

	result, err := i.index.Search(request)
	if err != nil {
		log.Printf("Search Error: %q", err)
		return nil, err
	}
	return result, nil
}

func (i *bleveIndex) Close() error {
	return i.index.Close()
}
func NewIndex(indexLocation string) (Index, error) {
	// TODO(jwall): An abstract indexing interface?
	var index bleve.Index
	if _, err := os.Stat(indexLocation); os.IsNotExist(err) {
		mapping := bleve.NewIndexMapping()
		mapping.DefaultAnalyzer = "en"
		mapping.AddDocumentMapping(htmlMimeType, buildHtmlDocumentMapping())
		// TODO(jwall): Create document mappings for our custom types.
		log.Printf("Creating new index %q", indexLocation)
		if index, err = bleve.New(indexLocation, mapping); err != nil {
			return nil, fmt.Errorf("Error creating index %q\n", err)
		}
	} else {
		readOnly := false
		if *isQuery {
			readOnly = true
		}
		opts := map[string]interface{}{
			"read_only": readOnly,
		}
		Debugf("Opening index %q (readonly: %t)\n", indexLocation, readOnly)
		if index, err = bleve.OpenUsing(indexLocation, opts); err != nil {
			return nil, fmt.Errorf("Error opening index %q\n", err)
		}
	}
	return &bleveIndex{index}, nil
}
<commit_msg>Use scorch by default<commit_after>// Copyright 2015 Jeremy Wall (jeremy@marzhillstudios.com)
// Use of this source code is governed by the Artistic License 2.0.
// That License is included in the LICENSE file.
package main

import (
	"fmt"
	"log"
	"os"
	"strings"

	"github.com/blevesearch/bleve"
	"github.com/blevesearch/bleve/analysis"
	"github.com/blevesearch/bleve/analysis/char/html"
	"github.com/blevesearch/bleve/analysis/lang/en"
	"github.com/blevesearch/bleve/mapping"
	"github.com/blevesearch/bleve/registry"
	"github.com/blevesearch/bleve/search/highlight/highlighter/ansi"
)

const htmlMimeType = "text/html"

// handle text/html types
func init() {
	registry.RegisterAnalyzer(htmlMimeType, func(config map[string]interface{}, cache *registry.Cache) (*analysis.Analyzer, error) {
		a, err := en.AnalyzerConstructor(config, cache)
		if err != nil {
			if cf, err := cache.CharFilterNamed(html.Name); err == nil {
				a.CharFilters = []analysis.CharFilter{cf}
			} else {
				return nil, err
			}
		}

		return a, err
	})
}

func buildHtmlDocumentMapping() *mapping.DocumentMapping {
	dm := bleve.NewDocumentMapping()
	dm.DefaultAnalyzer = htmlMimeType
	return dm
}

type Index interface {
	Put(data *IFile) error
	Query(terms []string) (*bleve.SearchResult, error)
	Close() error
}

type bleveIndex struct {
	index bleve.Index
}

func (i *bleveIndex) Put(data *IFile) error {
	if err := i.index.Index((*data).Path(), data); err != nil {
		return fmt.Errorf("Error writing to index: %q", err)
	}
	return nil
}

func (i *bleveIndex) Query(terms []string) (*bleve.SearchResult, error) {
	searchQuery := strings.Join(terms, " ")
	query := bleve.NewQueryStringQuery(searchQuery)
	// TODO(jwall): limit, skip, and explain should be configurable.
	request := bleve.NewSearchRequestOptions(query, *limit, *from, false)
	if *useHighlight {
		request.Highlight = bleve.NewHighlightWithStyle(ansi.Name)
	} else {
		request.Highlight = bleve.NewHighlight()
	}

	result, err := i.index.Search(request)
	if err != nil {
		log.Printf("Search Error: %q", err)
		return nil, err
	}
	return result, nil
}

func (i *bleveIndex) Close() error {
	return i.index.Close()
}
func NewIndex(indexLocation string) (Index, error) {
	// TODO(jwall): An abstract indexing interface?
	var index bleve.Index
	if _, err := os.Stat(indexLocation); os.IsNotExist(err) {
		mapping := bleve.NewIndexMapping()
		mapping.DefaultAnalyzer = "en"
		mapping.AddDocumentMapping(htmlMimeType, buildHtmlDocumentMapping())
		// TODO(jwall): Create document mappings for our custom types.
		log.Printf("Creating new index %q", indexLocation)
		if index, err = bleve.NewUsing(indexLocation, mapping, "scorch", "scorch", nil); err != nil {
			return nil, fmt.Errorf("Error creating index %q\n", err)
		}
	} else {
		readOnly := false
		if *isQuery {
			readOnly = true
		}
		opts := map[string]interface{}{
			"read_only": readOnly,
		}
		Debugf("Opening index %q (readonly: %t)\n", indexLocation, readOnly)
		if index, err = bleve.OpenUsing(indexLocation, opts); err != nil {
			return nil, fmt.Errorf("Error opening index %q\n", err)
		}
	}
	return &bleveIndex{index}, nil
}
<|endoftext|>


<commit_before>package controllers_test

import (
	"fmt"
	"github.com/jinzhu/gorm"
	. "gopkg.in/check.v1"
	"net/http"
	"net/http/httptest"
	"polyflix"
	. "polyflix/controllers"
	"testing"
)

var (
	url    = "localhost:3000"
	dbConn string
)

// Hook up gocheck into the "go test" runner.
func Test(t *testing.T) { TestingT(t) }

type MovieControllerSuite struct {
	server *httptest.Server
	db     gorm.DB
}

var _ = Suite(&MovieControllerSuite{})

func (s *MovieControllerSuite) SetUpSuite(c *C) {
	env := "test"
	dbConn := main.GetDbConn(env)
	s.db = main.DbInit(dbConn)
	s.server = httptest.NewServer(main.Handlers(s.db))
}

func (s *MovieControllerSuite) TestMovie(c *C) {
	movie := Movie{Title: "Fight Club", Themoviedbid: 500}
	c.Assert(movie.Title, FitsTypeOf, string("Fight Club"))
	c.Assert(movie.Themoviedbid, FitsTypeOf, int(500))
	c.Assert(movie, FitsTypeOf, Movie{})
}

func (s *MovieControllerSuite) TestSinglePayload(c *C) {
	movie := Movie{Title: "Fight Club", Themoviedbid: 500}
	payload := SinglePayload{Movie: movie}
	c.Assert(payload.Movie.Title, FitsTypeOf, string("Fight Club"))
	c.Assert(payload.Movie.Themoviedbid, FitsTypeOf, int(500))
	c.Assert(payload.Movie, FitsTypeOf, Movie{})
	c.Assert(payload, FitsTypeOf, SinglePayload{})
}

func (s *MovieControllerSuite) TestArrayPayload(c *C) {
	movie := Movie{Title: "Fight Club", Themoviedbid: 500}
	movies := []Movie{movie}
	payload := ArrayPayload{Movies: movies}
	c.Assert(payload.Movies[0].Title, FitsTypeOf, string("Fight Club"))
	c.Assert(payload.Movies[0].Themoviedbid, FitsTypeOf, int(500))
	c.Assert(payload.Movies[0], FitsTypeOf, Movie{})
	c.Assert(payload, FitsTypeOf, ArrayPayload{})
}

func (s *MovieControllerSuite) TestIndexHandler(c *C) {
	controller := MoviesController{DB: s.db}
	recorder := httptest.NewRecorder()
	url := fmt.Sprintf("%s/movies", s.server.URL)
	req, err := http.NewRequest("GET", url, nil)
	c.Assert(err, IsNil)

	controller.IndexHandler(recorder, req)

	c.Assert(recorder.Code, Equals, 200)
}

func (s *MovieControllerSuite) TestShowHandler(c *C) {
	controller := MoviesController{DB: s.db}
	recorder := httptest.NewRecorder()
	url := fmt.Sprintf("%s/movies/1", s.server.URL)
	req, err := http.NewRequest("GET", url, nil)
	c.Assert(err, IsNil)

	controller.ShowHandler(recorder, req)

	c.Assert(recorder.Code, Equals, 200)
}

func (s *MovieControllerSuite) TestDestroyHandler(c *C) {
	controller := MoviesController{DB: s.db}
	recorder := httptest.NewRecorder()
	url := fmt.Sprintf("%s/movies/1", s.server.URL)
	req, err := http.NewRequest("DELETE", url, nil)
	c.Assert(err, IsNil)

	controller.ShowHandler(recorder, req)

	c.Assert(recorder.Code, Equals, 200)
}
<commit_msg>Go add db setup and server teardown to test suite<commit_after>package controllers_test

import (
	"fmt"
	"github.com/jinzhu/gorm"
	. "gopkg.in/check.v1"
	"net/http"
	"net/http/httptest"
	"polyflix"
	. "polyflix/controllers"
	"testing"
	"time"
)

var (
	url    = "localhost:3000"
	dbConn string
	now    = time.Now()
	movie1 = Movie{Title: "Fury", Themoviedbid: 228150, CreatedAt: now, UpdatedAt: now}
	movie2 = Movie{Title: "Interstellar", Themoviedbid: 157336, CreatedAt: now, UpdatedAt: now}
)

// Hook up gocheck into the "go test" runner.
func Test(t *testing.T) { TestingT(t) }

type MovieControllerSuite struct {
	server *httptest.Server
	db     gorm.DB
}

var _ = Suite(&MovieControllerSuite{})

func (s *MovieControllerSuite) SetUpSuite(c *C) {
	env := "test"
	dbConn := main.GetDbConn(env)
	s.db = main.DbInit(dbConn)
	s.server = httptest.NewServer(main.Handlers(s.db))
	s.db.Where(Movie{Themoviedbid: 228150}).FirstOrCreate(&movie1)
	s.db.Where(Movie{Themoviedbid: 157336}).FirstOrCreate(&movie2)
}

func (s *MovieControllerSuite) TearDownSuite(c *C) {
	s.server.Close()
}

func (s *MovieControllerSuite) TestMovie(c *C) {
	movie := Movie{Title: "Fight Club", Themoviedbid: 500}
	c.Assert(movie.Title, FitsTypeOf, string("Fight Club"))
	c.Assert(movie.Themoviedbid, FitsTypeOf, int(500))
	c.Assert(movie, FitsTypeOf, Movie{})
}

func (s *MovieControllerSuite) TestSinglePayload(c *C) {
	movie := Movie{Title: "Fight Club", Themoviedbid: 500}
	payload := SinglePayload{Movie: movie}
	c.Assert(payload.Movie.Title, FitsTypeOf, string("Fight Club"))
	c.Assert(payload.Movie.Themoviedbid, FitsTypeOf, int(500))
	c.Assert(payload.Movie, FitsTypeOf, Movie{})
	c.Assert(payload, FitsTypeOf, SinglePayload{})
}

func (s *MovieControllerSuite) TestArrayPayload(c *C) {
	movie := Movie{Title: "Fight Club", Themoviedbid: 500}
	movies := []Movie{movie}
	payload := ArrayPayload{Movies: movies}
	c.Assert(payload.Movies[0].Title, FitsTypeOf, string("Fight Club"))
	c.Assert(payload.Movies[0].Themoviedbid, FitsTypeOf, int(500))
	c.Assert(payload.Movies[0], FitsTypeOf, Movie{})
	c.Assert(payload, FitsTypeOf, ArrayPayload{})
}

func (s *MovieControllerSuite) TestIndexHandler(c *C) {
	controller := MoviesController{DB: s.db}
	recorder := httptest.NewRecorder()
	url := fmt.Sprintf("%s/movies", s.server.URL)
	req, err := http.NewRequest("GET", url, nil)
	c.Assert(err, IsNil)

	controller.IndexHandler(recorder, req)

	c.Assert(recorder.Code, Equals, http.StatusOK)
}

func (s *MovieControllerSuite) TestShowHandler(c *C) {
	controller := MoviesController{DB: s.db}
	recorder := httptest.NewRecorder()
	url := fmt.Sprintf("%s/movies/1", s.server.URL)
	req, err := http.NewRequest("GET", url, nil)
	c.Assert(err, IsNil)

	controller.ShowHandler(recorder, req)

	c.Assert(recorder.Code, Equals, http.StatusOK)
}

func (s *MovieControllerSuite) TestDestroyHandler(c *C) {
	controller := MoviesController{DB: s.db}
	recorder := httptest.NewRecorder()
	url := fmt.Sprintf("%s/movies/1", s.server.URL)
	req, err := http.NewRequest("DELETE", url, nil)
	c.Assert(err, IsNil)

	controller.ShowHandler(recorder, req)

	c.Assert(recorder.Code, Equals, http.StatusOK)
}
<|endoftext|>


<commit_before>package models

import "fmt"

func (mr *MessageReply) GetCacheId() int64 {
	return mr.MessageId
}

func (mr *MessageReply) CachePrefix(id int64) string {
	return fmt.Sprintf("%s:%d", "channelmessagecontainer", id)
}

func (mr *MessageReply) GetForCache(id int64) (string, error) {
	return CacheForChannelMessage(id)
}
<commit_msg>cache: delete message reply cacher implementation<commit_after><|endoftext|>


<commit_before>package main

import (
	"log"
	"socialapi/config"
	"socialapi/workers/presence"

	"github.com/koding/runner"
)

var (
	name = "Presence"
)

func main() {
	r := runner.New(name)
	if err := r.Init(); err != nil {
		log.Fatal(err.Error())
	}

	appConfig := config.MustRead(r.Conf.Path)
	r.SetContext(presence.New(r.Log, appConfig))
	r.Register(presence.Ping{}).On(presence.EventName).Handle((*presence.Controller).Ping)
	r.Listen()
	r.Wait()
}
<commit_msg>go/presence: init mongo connection<commit_after>package main

import (
	"koding/db/mongodb/modelhelper"
	"log"
	"socialapi/config"
	"socialapi/workers/presence"

	"github.com/koding/runner"
)

var (
	name = "Presence"
)

func main() {
	r := runner.New(name)
	if err := r.Init(); err != nil {
		log.Fatal(err.Error())
	}

	appConfig := config.MustRead(r.Conf.Path)
	modelhelper.Initialize(appConfig.Mongo)
	defer modelhelper.Close()

	r.SetContext(presence.New(r.Log, appConfig))
	r.Register(presence.Ping{}).On(presence.EventName).Handle((*presence.Controller).Ping)
	r.Listen()
	r.Wait()
}
<|endoftext|>


<commit_before>package weed_server

import (
	"errors"
	"io"
	"mime"
	"mime/multipart"
	"net/http"
	"strconv"
	"strings"
	"time"

	"github.com/chrislusf/weed-fs/go/glog"
	"github.com/chrislusf/weed-fs/go/images"
	"github.com/chrislusf/weed-fs/go/operation"
	"github.com/chrislusf/weed-fs/go/stats"
	"github.com/chrislusf/weed-fs/go/storage"
	"github.com/chrislusf/weed-fs/go/topology"
)

var fileNameEscaper = strings.NewReplacer("\\", "\\\\", "\"", "\\\"")

func (vs *VolumeServer) storeHandler(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "GET":
		stats.ReadRequest()
		vs.GetOrHeadHandler(w, r)
	case "HEAD":
		stats.ReadRequest()
		vs.GetOrHeadHandler(w, r)
	case "DELETE":
		stats.DeleteRequest()
		vs.guard.Secure(vs.DeleteHandler)(w, r)
	case "PUT":
		stats.WriteRequest()
		vs.guard.Secure(vs.PostHandler)(w, r)
	case "POST":
		stats.WriteRequest()
		vs.guard.Secure(vs.PostHandler)(w, r)
	}
}

func (vs *VolumeServer) GetOrHeadHandler(w http.ResponseWriter, r *http.Request) {
	n := new(storage.Needle)
	vid, fid, filename, ext, _ := parseURLPath(r.URL.Path)
	volumeId, err := storage.NewVolumeId(vid)
	if err != nil {
		glog.V(2).Infoln("parsing error:", err, r.URL.Path)
		w.WriteHeader(http.StatusBadRequest)
		return
	}
	err = n.ParsePath(fid)
	if err != nil {
		glog.V(2).Infoln("parsing fid error:", err, r.URL.Path)
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	glog.V(4).Infoln("volume", volumeId, "reading", n)
	if !vs.store.HasVolume(volumeId) {
		lookupResult, err := operation.Lookup(vs.GetMasterNode(), volumeId.String())
		glog.V(2).Infoln("volume", volumeId, "found on", lookupResult, "error", err)
		if err == nil && len(lookupResult.Locations) > 0 {
			http.Redirect(w, r, "http://"+lookupResult.Locations[0].Url+r.URL.Path, http.StatusMovedPermanently)
		} else {
			glog.V(2).Infoln("lookup error:", err, r.URL.Path)
			w.WriteHeader(http.StatusNotFound)
		}
		return
	}
	cookie := n.Cookie
	count, e := vs.store.Read(volumeId, n)
	glog.V(4).Infoln("read bytes", count, "error", e)
	if e != nil || count <= 0 {
		glog.V(0).Infoln("read error:", e, r.URL.Path)
		w.WriteHeader(http.StatusNotFound)
		return
	}
	if n.Cookie != cookie {
		glog.V(0).Infoln("request", r.URL.Path, "with unmaching cookie seen:", cookie, "expected:", n.Cookie, "from", r.RemoteAddr, "agent", r.UserAgent())
		w.WriteHeader(http.StatusNotFound)
		return
	}
	if n.LastModified != 0 {
		w.Header().Set("Last-Modified", time.Unix(int64(n.LastModified), 0).UTC().Format(http.TimeFormat))
		if r.Header.Get("If-Modified-Since") != "" {
			if t, parseError := time.Parse(http.TimeFormat, r.Header.Get("If-Modified-Since")); parseError == nil {
				if t.Unix() >= int64(n.LastModified) {
					w.WriteHeader(http.StatusNotModified)
					return
				}
			}
		}
	}
	etag := n.Etag()
	if inm := r.Header.Get("If-None-Match"); inm == etag {
		w.WriteHeader(http.StatusNotModified)
		return
	}
	w.Header().Set("Etag", etag)
	if n.NameSize > 0 && filename == "" {
		filename = string(n.Name)
		dotIndex := strings.LastIndex(filename, ".")
		if dotIndex > 0 {
			ext = filename[dotIndex:]
		}
	}
	mtype := ""
	if ext != "" {
		mtype = mime.TypeByExtension(ext)
	}
	if n.MimeSize > 0 {
		mt := string(n.Mime)
		if mt != "application/octet-stream" {
			mtype = mt
		}
	}
	if mtype != "" {
		w.Header().Set("Content-Type", mtype)
	}
	if filename != "" {
		w.Header().Set("Content-Disposition", "filename=\""+fileNameEscaper.Replace(filename)+"\"")
	}
	if ext != ".gz" {
		if n.IsGzipped() {
			if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
				w.Header().Set("Content-Encoding", "gzip")
			} else {
				if n.Data, err = storage.UnGzipData(n.Data); err != nil {
					glog.V(0).Infoln("lookup error:", err, r.URL.Path)
				}
			}
		}
	}
	if ext == ".png" || ext == ".jpg" || ext == ".gif" {
		width, height := 0, 0
		if r.FormValue("width") != "" {
			width, _ = strconv.Atoi(r.FormValue("width"))
		}
		if r.FormValue("height") != "" {
			height, _ = strconv.Atoi(r.FormValue("height"))
		}
		n.Data, _, _ = images.Resized(ext, n.Data, width, height)
	}

	w.Header().Set("Accept-Ranges", "bytes")
	if r.Method == "HEAD" {
		w.Header().Set("Content-Length", strconv.Itoa(len(n.Data)))
		return
	}
	rangeReq := r.Header.Get("Range")
	if rangeReq == "" {
		w.Header().Set("Content-Length", strconv.Itoa(len(n.Data)))
		if _, e = w.Write(n.Data); e != nil {
			glog.V(0).Infoln("response write error:", e)
		}
		return
	}

	//the rest is dealing with partial content request
	//mostly copy from src/pkg/net/http/fs.go
	size := int64(len(n.Data))
	ranges, err := parseRange(rangeReq, size)
	if err != nil {
		http.Error(w, err.Error(), http.StatusRequestedRangeNotSatisfiable)
		return
	}
	if sumRangesSize(ranges) > size {
		// The total number of bytes in all the ranges
		// is larger than the size of the file by
		// itself, so this is probably an attack, or a
		// dumb client.  Ignore the range request.
		ranges = nil
		return
	}
	if len(ranges) == 0 {
		return
	}
	if len(ranges) == 1 {
		// RFC 2616, Section 14.16:
		// "When an HTTP message includes the content of a single
		// range (for example, a response to a request for a
		// single range, or to a request for a set of ranges
		// that overlap without any holes), this content is
		// transmitted with a Content-Range header, and a
		// Content-Length header showing the number of bytes
		// actually transferred.
		// ...
		// A response to a request for a single range MUST NOT
		// be sent using the multipart/byteranges media type."
		ra := ranges[0]
		w.Header().Set("Content-Length", strconv.FormatInt(ra.length, 10))
		w.Header().Set("Content-Range", ra.contentRange(size))
		w.WriteHeader(http.StatusPartialContent)
		if _, e = w.Write(n.Data[ra.start : ra.start+ra.length]); e != nil {
			glog.V(0).Infoln("response write error:", e)
		}
		return
	}
	// process mulitple ranges
	for _, ra := range ranges {
		if ra.start > size {
			http.Error(w, "Out of Range", http.StatusRequestedRangeNotSatisfiable)
			return
		}
	}
	sendSize := rangesMIMESize(ranges, mtype, size)
	pr, pw := io.Pipe()
	mw := multipart.NewWriter(pw)
	w.Header().Set("Content-Type", "multipart/byteranges; boundary="+mw.Boundary())
	sendContent := pr
	defer pr.Close() // cause writing goroutine to fail and exit if CopyN doesn't finish.
	go func() {
		for _, ra := range ranges {
			part, err := mw.CreatePart(ra.mimeHeader(mtype, size))
			if err != nil {
				pw.CloseWithError(err)
				return
			}
			if _, err = part.Write(n.Data[ra.start : ra.start+ra.length]); err != nil {
				pw.CloseWithError(err)
				return
			}
		}
		mw.Close()
		pw.Close()
	}()
	if w.Header().Get("Content-Encoding") == "" {
		w.Header().Set("Content-Length", strconv.FormatInt(sendSize, 10))
	}
	w.WriteHeader(http.StatusPartialContent)
	io.CopyN(w, sendContent, sendSize)

}

func (vs *VolumeServer) PostHandler(w http.ResponseWriter, r *http.Request) {
	if e := r.ParseForm(); e != nil {
		glog.V(0).Infoln("form parse error:", e)
		writeJsonError(w, r, http.StatusBadRequest, e)
		return
	}
	vid, _, _, _, _ := parseURLPath(r.URL.Path)
	volumeId, ve := storage.NewVolumeId(vid)
	if ve != nil {
		glog.V(0).Infoln("NewVolumeId error:", ve)
		writeJsonError(w, r, http.StatusBadRequest, ve)
		return
	}
	needle, ne := storage.NewNeedle(r, vs.FixJpgOrientation)
	if ne != nil {
		writeJsonError(w, r, http.StatusBadRequest, ne)
		return
	}

	ret := operation.UploadResult{}
	size, errorStatus := topology.ReplicatedWrite(vs.GetMasterNode(),
		vs.store, volumeId, needle, r)
	httpStatus := http.StatusCreated
	if errorStatus != "" {
		httpStatus = http.StatusInternalServerError
		ret.Error = errorStatus
	}
	if needle.HasName() {
		ret.Name = string(needle.Name)
	}
	ret.Size = size
	writeJsonQuiet(w, r, httpStatus, ret)
}

func (vs *VolumeServer) DeleteHandler(w http.ResponseWriter, r *http.Request) {
	n := new(storage.Needle)
	vid, fid, _, _, _ := parseURLPath(r.URL.Path)
	volumeId, _ := storage.NewVolumeId(vid)
	n.ParsePath(fid)

	glog.V(2).Infoln("deleting", n)

	cookie := n.Cookie
	count, ok := vs.store.Read(volumeId, n)

	if ok != nil {
		m := make(map[string]uint32)
		m["size"] = 0
		writeJsonQuiet(w, r, http.StatusNotFound, m)
		return
	}

	if n.Cookie != cookie {
		glog.V(0).Infoln("delete", r.URL.Path, "with unmaching cookie from ", r.RemoteAddr, "agent", r.UserAgent())
		return
	}

	n.Size = 0
	ret := topology.ReplicatedDelete(vs.GetMasterNode(), vs.store, volumeId, n, r)

	if ret != 0 {
		m := make(map[string]uint32)
		m["size"] = uint32(count)
		writeJsonQuiet(w, r, http.StatusAccepted, m)
	} else {
		writeJsonError(w, r, http.StatusInternalServerError, errors.New("Deletion Failed."))
	}

}

//Experts only: takes multiple fid parameters. This function does not propagate deletes to replicas.
func (vs *VolumeServer) batchDeleteHandler(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	var ret []operation.DeleteResult
	for _, fid := range r.Form["fid"] {
		vid, id_cookie, err := operation.ParseFileId(fid)
		if err != nil {
			ret = append(ret, operation.DeleteResult{Fid: fid, Error: err.Error()})
			continue
		}
		n := new(storage.Needle)
		volumeId, _ := storage.NewVolumeId(vid)
		n.ParsePath(id_cookie)
		glog.V(4).Infoln("batch deleting", n)
		cookie := n.Cookie
		if _, err := vs.store.Read(volumeId, n); err != nil {
			ret = append(ret, operation.DeleteResult{Fid: fid, Error: err.Error()})
			continue
		}
		if n.Cookie != cookie {
			ret = append(ret, operation.DeleteResult{Fid: fid, Error: "File Random Cookie does not match."})
			glog.V(0).Infoln("deleting", fid, "with unmaching cookie from ", r.RemoteAddr, "agent", r.UserAgent())
			return
		}
		if size, err := vs.store.Delete(volumeId, n); err != nil {
			ret = append(ret, operation.DeleteResult{Fid: fid, Error: err.Error()})
		} else {
			ret = append(ret, operation.DeleteResult{Fid: fid, Size: int(size)})
		}
	}

	writeJsonQuiet(w, r, http.StatusAccepted, ret)
}
<commit_msg>Redirect to publicUrl<commit_after>package weed_server

import (
	"errors"
	"io"
	"mime"
	"mime/multipart"
	"net/http"
	"strconv"
	"strings"
	"time"

	"github.com/chrislusf/weed-fs/go/glog"
	"github.com/chrislusf/weed-fs/go/images"
	"github.com/chrislusf/weed-fs/go/operation"
	"github.com/chrislusf/weed-fs/go/stats"
	"github.com/chrislusf/weed-fs/go/storage"
	"github.com/chrislusf/weed-fs/go/topology"
)

var fileNameEscaper = strings.NewReplacer("\\", "\\\\", "\"", "\\\"")

func (vs *VolumeServer) storeHandler(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "GET":
		stats.ReadRequest()
		vs.GetOrHeadHandler(w, r)
	case "HEAD":
		stats.ReadRequest()
		vs.GetOrHeadHandler(w, r)
	case "DELETE":
		stats.DeleteRequest()
		vs.guard.Secure(vs.DeleteHandler)(w, r)
	case "PUT":
		stats.WriteRequest()
		vs.guard.Secure(vs.PostHandler)(w, r)
	case "POST":
		stats.WriteRequest()
		vs.guard.Secure(vs.PostHandler)(w, r)
	}
}

func (vs *VolumeServer) GetOrHeadHandler(w http.ResponseWriter, r *http.Request) {
	n := new(storage.Needle)
	vid, fid, filename, ext, _ := parseURLPath(r.URL.Path)
	volumeId, err := storage.NewVolumeId(vid)
	if err != nil {
		glog.V(2).Infoln("parsing error:", err, r.URL.Path)
		w.WriteHeader(http.StatusBadRequest)
		return
	}
	err = n.ParsePath(fid)
	if err != nil {
		glog.V(2).Infoln("parsing fid error:", err, r.URL.Path)
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	glog.V(4).Infoln("volume", volumeId, "reading", n)
	if !vs.store.HasVolume(volumeId) {
		lookupResult, err := operation.Lookup(vs.GetMasterNode(), volumeId.String())
		glog.V(2).Infoln("volume", volumeId, "found on", lookupResult, "error", err)
		if err == nil && len(lookupResult.Locations) > 0 {
			http.Redirect(w, r, "http://"+lookupResult.Locations[0].PublicUrl+r.URL.Path, http.StatusMovedPermanently)
		} else {
			glog.V(2).Infoln("lookup error:", err, r.URL.Path)
			w.WriteHeader(http.StatusNotFound)
		}
		return
	}
	cookie := n.Cookie
	count, e := vs.store.Read(volumeId, n)
	glog.V(4).Infoln("read bytes", count, "error", e)
	if e != nil || count <= 0 {
		glog.V(0).Infoln("read error:", e, r.URL.Path)
		w.WriteHeader(http.StatusNotFound)
		return
	}
	if n.Cookie != cookie {
		glog.V(0).Infoln("request", r.URL.Path, "with unmaching cookie seen:", cookie, "expected:", n.Cookie, "from", r.RemoteAddr, "agent", r.UserAgent())
		w.WriteHeader(http.StatusNotFound)
		return
	}
	if n.LastModified != 0 {
		w.Header().Set("Last-Modified", time.Unix(int64(n.LastModified), 0).UTC().Format(http.TimeFormat))
		if r.Header.Get("If-Modified-Since") != "" {
			if t, parseError := time.Parse(http.TimeFormat, r.Header.Get("If-Modified-Since")); parseError == nil {
				if t.Unix() >= int64(n.LastModified) {
					w.WriteHeader(http.StatusNotModified)
					return
				}
			}
		}
	}
	etag := n.Etag()
	if inm := r.Header.Get("If-None-Match"); inm == etag {
		w.WriteHeader(http.StatusNotModified)
		return
	}
	w.Header().Set("Etag", etag)
	if n.NameSize > 0 && filename == "" {
		filename = string(n.Name)
		dotIndex := strings.LastIndex(filename, ".")
		if dotIndex > 0 {
			ext = filename[dotIndex:]
		}
	}
	mtype := ""
	if ext != "" {
		mtype = mime.TypeByExtension(ext)
	}
	if n.MimeSize > 0 {
		mt := string(n.Mime)
		if mt != "application/octet-stream" {
			mtype = mt
		}
	}
	if mtype != "" {
		w.Header().Set("Content-Type", mtype)
	}
	if filename != "" {
		w.Header().Set("Content-Disposition", "filename=\""+fileNameEscaper.Replace(filename)+"\"")
	}
	if ext != ".gz" {
		if n.IsGzipped() {
			if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
				w.Header().Set("Content-Encoding", "gzip")
			} else {
				if n.Data, err = storage.UnGzipData(n.Data); err != nil {
					glog.V(0).Infoln("lookup error:", err, r.URL.Path)
				}
			}
		}
	}
	if ext == ".png" || ext == ".jpg" || ext == ".gif" {
		width, height := 0, 0
		if r.FormValue("width") != "" {
			width, _ = strconv.Atoi(r.FormValue("width"))
		}
		if r.FormValue("height") != "" {
			height, _ = strconv.Atoi(r.FormValue("height"))
		}
		n.Data, _, _ = images.Resized(ext, n.Data, width, height)
	}

	w.Header().Set("Accept-Ranges", "bytes")
	if r.Method == "HEAD" {
		w.Header().Set("Content-Length", strconv.Itoa(len(n.Data)))
		return
	}
	rangeReq := r.Header.Get("Range")
	if rangeReq == "" {
		w.Header().Set("Content-Length", strconv.Itoa(len(n.Data)))
		if _, e = w.Write(n.Data); e != nil {
			glog.V(0).Infoln("response write error:", e)
		}
		return
	}

	//the rest is dealing with partial content request
	//mostly copy from src/pkg/net/http/fs.go
	size := int64(len(n.Data))
	ranges, err := parseRange(rangeReq, size)
	if err != nil {
		http.Error(w, err.Error(), http.StatusRequestedRangeNotSatisfiable)
		return
	}
	if sumRangesSize(ranges) > size {
		// The total number of bytes in all the ranges
		// is larger than the size of the file by
		// itself, so this is probably an attack, or a
		// dumb client.  Ignore the range request.
		ranges = nil
		return
	}
	if len(ranges) == 0 {
		return
	}
	if len(ranges) == 1 {
		// RFC 2616, Section 14.16:
		// "When an HTTP message includes the content of a single
		// range (for example, a response to a request for a
		// single range, or to a request for a set of ranges
		// that overlap without any holes), this content is
		// transmitted with a Content-Range header, and a
		// Content-Length header showing the number of bytes
		// actually transferred.
		// ...
		// A response to a request for a single range MUST NOT
		// be sent using the multipart/byteranges media type."
		ra := ranges[0]
		w.Header().Set("Content-Length", strconv.FormatInt(ra.length, 10))
		w.Header().Set("Content-Range", ra.contentRange(size))
		w.WriteHeader(http.StatusPartialContent)
		if _, e = w.Write(n.Data[ra.start : ra.start+ra.length]); e != nil {
			glog.V(0).Infoln("response write error:", e)
		}
		return
	}
	// process mulitple ranges
	for _, ra := range ranges {
		if ra.start > size {
			http.Error(w, "Out of Range", http.StatusRequestedRangeNotSatisfiable)
			return
		}
	}
	sendSize := rangesMIMESize(ranges, mtype, size)
	pr, pw := io.Pipe()
	mw := multipart.NewWriter(pw)
	w.Header().Set("Content-Type", "multipart/byteranges; boundary="+mw.Boundary())
	sendContent := pr
	defer pr.Close() // cause writing goroutine to fail and exit if CopyN doesn't finish.
	go func() {
		for _, ra := range ranges {
			part, err := mw.CreatePart(ra.mimeHeader(mtype, size))
			if err != nil {
				pw.CloseWithError(err)
				return
			}
			if _, err = part.Write(n.Data[ra.start : ra.start+ra.length]); err != nil {
				pw.CloseWithError(err)
				return
			}
		}
		mw.Close()
		pw.Close()
	}()
	if w.Header().Get("Content-Encoding") == "" {
		w.Header().Set("Content-Length", strconv.FormatInt(sendSize, 10))
	}
	w.WriteHeader(http.StatusPartialContent)
	io.CopyN(w, sendContent, sendSize)

}

func (vs *VolumeServer) PostHandler(w http.ResponseWriter, r *http.Request) {
	if e := r.ParseForm(); e != nil {
		glog.V(0).Infoln("form parse error:", e)
		writeJsonError(w, r, http.StatusBadRequest, e)
		return
	}
	vid, _, _, _, _ := parseURLPath(r.URL.Path)
	volumeId, ve := storage.NewVolumeId(vid)
	if ve != nil {
		glog.V(0).Infoln("NewVolumeId error:", ve)
		writeJsonError(w, r, http.StatusBadRequest, ve)
		return
	}
	needle, ne := storage.NewNeedle(r, vs.FixJpgOrientation)
	if ne != nil {
		writeJsonError(w, r, http.StatusBadRequest, ne)
		return
	}

	ret := operation.UploadResult{}
	size, errorStatus := topology.ReplicatedWrite(vs.GetMasterNode(),
		vs.store, volumeId, needle, r)
	httpStatus := http.StatusCreated
	if errorStatus != "" {
		httpStatus = http.StatusInternalServerError
		ret.Error = errorStatus
	}
	if needle.HasName() {
		ret.Name = string(needle.Name)
	}
	ret.Size = size
	writeJsonQuiet(w, r, httpStatus, ret)
}

func (vs *VolumeServer) DeleteHandler(w http.ResponseWriter, r *http.Request) {
	n := new(storage.Needle)
	vid, fid, _, _, _ := parseURLPath(r.URL.Path)
	volumeId, _ := storage.NewVolumeId(vid)
	n.ParsePath(fid)

	glog.V(2).Infoln("deleting", n)

	cookie := n.Cookie
	count, ok := vs.store.Read(volumeId, n)

	if ok != nil {
		m := make(map[string]uint32)
		m["size"] = 0
		writeJsonQuiet(w, r, http.StatusNotFound, m)
		return
	}

	if n.Cookie != cookie {
		glog.V(0).Infoln("delete", r.URL.Path, "with unmaching cookie from ", r.RemoteAddr, "agent", r.UserAgent())
		return
	}

	n.Size = 0
	ret := topology.ReplicatedDelete(vs.GetMasterNode(), vs.store, volumeId, n, r)

	if ret != 0 {
		m := make(map[string]uint32)
		m["size"] = uint32(count)
		writeJsonQuiet(w, r, http.StatusAccepted, m)
	} else {
		writeJsonError(w, r, http.StatusInternalServerError, errors.New("Deletion Failed."))
	}

}

//Experts only: takes multiple fid parameters. This function does not propagate deletes to replicas.
func (vs *VolumeServer) batchDeleteHandler(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	var ret []operation.DeleteResult
	for _, fid := range r.Form["fid"] {
		vid, id_cookie, err := operation.ParseFileId(fid)
		if err != nil {
			ret = append(ret, operation.DeleteResult{Fid: fid, Error: err.Error()})
			continue
		}
		n := new(storage.Needle)
		volumeId, _ := storage.NewVolumeId(vid)
		n.ParsePath(id_cookie)
		glog.V(4).Infoln("batch deleting", n)
		cookie := n.Cookie
		if _, err := vs.store.Read(volumeId, n); err != nil {
			ret = append(ret, operation.DeleteResult{Fid: fid, Error: err.Error()})
			continue
		}
		if n.Cookie != cookie {
			ret = append(ret, operation.DeleteResult{Fid: fid, Error: "File Random Cookie does not match."})
			glog.V(0).Infoln("deleting", fid, "with unmaching cookie from ", r.RemoteAddr, "agent", r.UserAgent())
			return
		}
		if size, err := vs.store.Delete(volumeId, n); err != nil {
			ret = append(ret, operation.DeleteResult{Fid: fid, Error: err.Error()})
		} else {
			ret = append(ret, operation.DeleteResult{Fid: fid, Size: int(size)})
		}
	}

	writeJsonQuiet(w, r, http.StatusAccepted, ret)
}
<|endoftext|>