<commit_before>package oauth2

import (
	"encoding/json"
	"fmt"
	"net/http"
	"strings"
	"time"

	"code.google.com/p/goauth2/oauth"
	"github.com/codegangsta/martini"
	"github.com/codegangsta/martini-contrib/sessions"
)

const (
	keyToken    = "oauth2_token"
	keyNextPage = "next"
)

var (
	// Path to handle OAuth 2.0 logins.
	PathLogin = "/login"
	// Path to handle OAuth 2.0 logouts.
	PathLogout = "/logout"
	// Path to handle callback from OAuth 2.0 backend
	// to exchange credentials.
	PathCallback = "/oauth2callback"
	// Path to handle error cases.
	PathError = "/oauth2error"
)

// Represents OAuth2 backend options.
type Options struct {
	ClientId     string
	ClientSecret string
	RedirectURL  string
	Scopes       []string

	AuthUrl  string
	TokenUrl string
}

// Represents a container that contains
// user's OAuth 2.0 access and refresh tokens.
type Tokens interface {
	AccessToken() string
	RefreshToken() string
	Expiry() time.Time
}

type token struct {
	tk *oauth.Token
}

// Returns the access token.
func (t *token) AccessToken() string {
	return t.tk.AccessToken
}

// Returns the refresh token.
func (t *token) RefreshToken() string {
	return t.tk.RefreshToken
}

// Returns whether the access token is
// expired or not.
func (t *token) Expired() bool {
	return t.tk.Expired()
}

// Returns the expiry time of the user's
// access token.
func (t *token) Expiry() time.Time {
	return t.tk.Expiry
}

// Formats tokens into string.
func (t *token) String() string {
	return fmt.Sprintf("%v", t.tk)
}

// Returns a new Google OAuth 2.0 backend endpoint.
func Google(opts *Options) martini.Handler {
	opts.AuthUrl = "https://accounts.google.com/o/oauth2/auth"
	opts.TokenUrl = "https://accounts.google.com/o/oauth2/token"
	return OAuth2Provider(opts)
}

// Returns a new Github OAuth 2.0 backend endpoint.
func Github(opts *Options) martini.Handler {
	opts.AuthUrl = "https://github.com/login/oauth/authorize"
	opts.TokenUrl = "https://github.com/login/oauth/access_token"
	return OAuth2Provider(opts)
}

// Returns a generic OAuth 2.0 backend endpoint.
func OAuth2Provider(opts *Options) martini.Handler {
	config := &oauth.Config{
		ClientId:     opts.ClientId,
		ClientSecret: opts.ClientSecret,
		RedirectURL:  opts.RedirectURL,
		Scope:        strings.Join(opts.Scopes, " "),
		AuthURL:      opts.AuthUrl,
		TokenURL:     opts.TokenUrl,
	}

	transport := &oauth.Transport{
		Config:    config,
		Transport: http.DefaultTransport,
	}

	return func(s sessions.Session, c martini.Context, w http.ResponseWriter, r *http.Request) {
		if r.Method == "GET" {
			switch r.URL.Path {
			case PathLogin:
				login(transport, s, w, r)
			case PathLogout:
				logout(transport, s, w, r)
			case PathCallback:
				handleOAuth2Callback(transport, s, w, r)
			}
		}
		// Inject tokens.
		c.MapTo(unmarshallToken(s), (*Tokens)(nil))
	}
}

func login(t *oauth.Transport, s sessions.Session, w http.ResponseWriter, r *http.Request) {
	next := r.URL.Query().Get(keyNextPage)
	if s.Get(keyToken) == nil {
		// User is not logged in.
		http.Redirect(w, r, t.Config.AuthCodeURL(next), 302)
		return
	}
	// No need to login, redirect to the next page.
	http.Redirect(w, r, next, 302)
}

func logout(t *oauth.Transport, s sessions.Session, w http.ResponseWriter, r *http.Request) {
	next := r.URL.Query().Get(keyNextPage)
	s.Delete(keyToken)
	http.Redirect(w, r, next, 302)
}

func handleOAuth2Callback(t *oauth.Transport, s sessions.Session, w http.ResponseWriter, r *http.Request) {
	next := r.URL.Query().Get("state")
	code := r.URL.Query().Get("code")
	tk, err := t.Exchange(code)
	if err != nil {
		// Pass the error message, or allow dev to provide its own
		// error handler.
		http.Redirect(w, r, PathError, 302)
		return
	}
	// Store the credentials in the session.
	val, _ := json.Marshal(tk)
	s.Set(keyToken, val)
	http.Redirect(w, r, next, 302)
}

func unmarshallToken(s sessions.Session) (t *token) {
	if s.Get(keyToken) == nil {
		return
	}
	data := s.Get(keyToken).([]byte)
	var tk oauth.Token
	json.Unmarshal(data, &tk)
	return &token{tk: &tk}
}
<commit_msg>[oauth2] Redirect code shouldn't be hard-coded.<commit_after>package oauth2

import (
	"encoding/json"
	"fmt"
	"net/http"
	"strings"
	"time"

	"code.google.com/p/goauth2/oauth"
	"github.com/codegangsta/martini"
	"github.com/codegangsta/martini-contrib/sessions"
)

const (
	codeRedirect = 302
	keyToken     = "oauth2_token"
	keyNextPage  = "next"
)

var (
	// Path to handle OAuth 2.0 logins.
	PathLogin = "/login"
	// Path to handle OAuth 2.0 logouts.
	PathLogout = "/logout"
	// Path to handle callback from OAuth 2.0 backend
	// to exchange credentials.
	PathCallback = "/oauth2callback"
	// Path to handle error cases.
	PathError = "/oauth2error"
)

// Represents OAuth2 backend options.
type Options struct {
	ClientId     string
	ClientSecret string
	RedirectURL  string
	Scopes       []string

	AuthUrl  string
	TokenUrl string
}

// Represents a container that contains
// user's OAuth 2.0 access and refresh tokens.
type Tokens interface {
	AccessToken() string
	RefreshToken() string
	Expiry() time.Time
}

type token struct {
	tk *oauth.Token
}

// Returns the access token.
func (t *token) AccessToken() string {
	return t.tk.AccessToken
}

// Returns the refresh token.
func (t *token) RefreshToken() string {
	return t.tk.RefreshToken
}

// Returns whether the access token is
// expired or not.
func (t *token) Expired() bool {
	return t.tk.Expired()
}

// Returns the expiry time of the user's
// access token.
func (t *token) Expiry() time.Time {
	return t.tk.Expiry
}

// Formats tokens into string.
func (t *token) String() string {
	return fmt.Sprintf("%v", t.tk)
}

// Returns a new Google OAuth 2.0 backend endpoint.
func Google(opts *Options) martini.Handler {
	opts.AuthUrl = "https://accounts.google.com/o/oauth2/auth"
	opts.TokenUrl = "https://accounts.google.com/o/oauth2/token"
	return OAuth2Provider(opts)
}

// Returns a new Github OAuth 2.0 backend endpoint.
func Github(opts *Options) martini.Handler {
	opts.AuthUrl = "https://github.com/login/oauth/authorize"
	opts.TokenUrl = "https://github.com/login/oauth/access_token"
	return OAuth2Provider(opts)
}

// Returns a generic OAuth 2.0 backend endpoint.
func OAuth2Provider(opts *Options) martini.Handler {
	config := &oauth.Config{
		ClientId:     opts.ClientId,
		ClientSecret: opts.ClientSecret,
		RedirectURL:  opts.RedirectURL,
		Scope:        strings.Join(opts.Scopes, " "),
		AuthURL:      opts.AuthUrl,
		TokenURL:     opts.TokenUrl,
	}

	transport := &oauth.Transport{
		Config:    config,
		Transport: http.DefaultTransport,
	}

	return func(s sessions.Session, c martini.Context, w http.ResponseWriter, r *http.Request) {
		if r.Method == "GET" {
			switch r.URL.Path {
			case PathLogin:
				login(transport, s, w, r)
			case PathLogout:
				logout(transport, s, w, r)
			case PathCallback:
				handleOAuth2Callback(transport, s, w, r)
			}
		}
		// Inject tokens.
		c.MapTo(unmarshallToken(s), (*Tokens)(nil))
	}
}

func login(t *oauth.Transport, s sessions.Session, w http.ResponseWriter, r *http.Request) {
	next := r.URL.Query().Get(keyNextPage)
	if s.Get(keyToken) == nil {
		// User is not logged in.
		http.Redirect(w, r, t.Config.AuthCodeURL(next), codeRedirect)
		return
	}
	// No need to login, redirect to the next page.
	http.Redirect(w, r, next, codeRedirect)
}

func logout(t *oauth.Transport, s sessions.Session, w http.ResponseWriter, r *http.Request) {
	next := r.URL.Query().Get(keyNextPage)
	s.Delete(keyToken)
	http.Redirect(w, r, next, codeRedirect)
}

func handleOAuth2Callback(t *oauth.Transport, s sessions.Session, w http.ResponseWriter, r *http.Request) {
	next := r.URL.Query().Get("state")
	code := r.URL.Query().Get("code")
	tk, err := t.Exchange(code)
	if err != nil {
		// Pass the error message, or allow dev to provide its own
		// error handler.
		http.Redirect(w, r, PathError, codeRedirect)
		return
	}
	// Store the credentials in the session.
	val, _ := json.Marshal(tk)
	s.Set(keyToken, val)
	http.Redirect(w, r, next, codeRedirect)
}

func unmarshallToken(s sessions.Session) (t *token) {
	if s.Get(keyToken) == nil {
		return
	}
	data := s.Get(keyToken).([]byte)
	var tk oauth.Token
	json.Unmarshal(data, &tk)
	return &token{tk: &tk}
}
<|endoftext|>


<commit_before>package glplus

import (
	"math"

	"github.com/go-gl/mathgl/mgl32"
)

var (
	sVertShaderObj = `#version 330
  ATTRIBUTE vec3 position;
	ATTRIBUTE float uvs;
	ATTRIBUTE vec3 normal;
	VARYINGOUT float out_uvs;
	VARYINGOUT vec4 out_color;
	uniform vec3 light;
	uniform mat4 mProjViewModel;
	uniform mat4 mViewModel;
	uniform mat4 mView;
	uniform vec4 ambient;
	uniform float shininess;
	uniform vec4 specular;
	uniform vec4 diffuse;

  void main()
  {
		// set the specular term to black
		vec4 spec = vec4(0.0);

		vec3 l_dir = normalize(mView * vec4(light, 0)).xyz;
		vec3 n = normalize(mViewModel * vec4(normal, 0)).xyz;
		float intensity = max(dot(n, l_dir), 0.0);

		// if the vertex is lit compute the specular term
		if (intensity > 0.0) {

				// compute position in camera space
				vec3 pos = vec3(mViewModel * vec4(position, 1)).xyz;
				// compute eye vector and normalize it
				vec3 eye = normalize(-pos);
				// compute the half vector
				vec3 h = normalize(l_dir + eye);

				// compute the specular term into spec
				float intSpec = max(dot(h,n), 0.0);
				spec = specular * pow(intSpec, shininess);
		}
		// add the specular term
		out_color = max(intensity *  diffuse + spec, ambient);

		out_uvs = uvs;
		gl_Position = mProjViewModel * vec4(position, 1.0);
  }`

	sFragShaderObj = `#version 330
	VARYINGIN float out_uvs;
	VARYINGIN vec4 out_color;
  COLOROUT

  void main(void)
  {
		FRAGCOLOR = out_color;
  }`

	sVertShaderObjTex = `#version 330
	ATTRIBUTE vec3 position;
	ATTRIBUTE vec2 uvs;
	ATTRIBUTE vec3 normal;
	VARYINGOUT vec2 out_uvs;
	VARYINGOUT vec4 out_color;
	uniform vec3 light;
	uniform mat4 mProjViewModel;
	uniform mat4 mViewModel;
	uniform mat4 mView;
	uniform vec4 ambient;
	uniform float shininess;
	uniform vec4 specular;
	uniform vec4 diffuse;

	void main()
	{
		// set the specular term to black
		vec4 spec = vec4(0.0);

		vec3 l_dir = normalize(mView * vec4(light, 0)).xyz;
		vec3 n = normalize(mViewModel * vec4(normal, 0)).xyz;
		float intensity = max(dot(n, l_dir), 0.0);

		// if the vertex is lit compute the specular term
		if (intensity > 0.0) {

				// compute position in camera space
				vec3 pos = vec3(mViewModel * vec4(position, 1)).xyz;
				// compute eye vector and normalize it
				vec3 eye = normalize(-pos);
				// compute the half vector
				vec3 h = normalize(l_dir + eye);

				// compute the specular term into spec
				float intSpec = max(dot(h,n), 0.0);
				spec = specular * pow(intSpec, shininess);
		}
		// add the specular term
		out_color = max(intensity *  diffuse + spec, ambient);

		out_uvs = uvs;
		gl_Position = mProjViewModel * vec4(position, 1.0);
	}`

	sFragShaderObjTex = `#version 330
	uniform sampler2D tex1;
	uniform mat3 matuv;
  VARYINGIN vec2 out_uvs;
	VARYINGIN vec4 out_color;
  COLOROUT

  void main(void)
  {
		vec2 new_uvs = vec2(1.0-out_uvs.x, out_uvs.y);
		new_uvs = (matuv * vec3(new_uvs, 1)).xy;
		vec4 texcolor = TEXTURE2D(tex1, new_uvs);
		FRAGCOLOR = out_color * texcolor;
  }`

	sVertShaderObjColorTable = `#version 330
	ATTRIBUTE vec3 position;
	ATTRIBUTE float uvs;
	ATTRIBUTE vec3 normal;
	VARYINGOUT float out_uvs;
	VARYINGOUT vec4 out_color;
	uniform vec3 light;
	uniform mat4 mProjViewModel;
	uniform mat4 mViewModel;
	uniform mat4 mView;
	uniform vec4 ambient;
	uniform float shininess;
	uniform vec4 specular;
	uniform vec4 diffuse;

	void main()
	{
		// set the specular term to black
		vec4 spec = vec4(0.0);

		vec3 l_dir = normalize(mView * vec4(light, 0)).xyz;
		vec3 n = normalize(mViewModel * vec4(normal, 0)).xyz;
		float intensity = max(dot(n, l_dir), 0.0);

		// if the vertex is lit compute the specular term
		if (intensity > 0.0) {

				// compute position in camera space
				vec3 pos = vec3(mViewModel * vec4(position, 1)).xyz;
				// compute eye vector and normalize it
				vec3 eye = normalize(-pos);
				// compute the half vector
				vec3 h = normalize(l_dir + eye);

				// compute the specular term into spec
				float intSpec = max(dot(h,n), 0.0);
				spec = specular * pow(intSpec, shininess);
		}
		// add the specular term
		out_color = max(intensity *  diffuse + spec, ambient);

		out_uvs = uvs;
		gl_Position = mProjViewModel * vec4(position, 1.0);
	}`

	sFragShaderObjColorTable = `#version 330
	uniform sampler2D tex1;
  VARYINGIN float out_uvs;
	VARYINGIN vec4 out_color;
  COLOROUT

  void main(void)
  {
		vec4 texcolor = TEXTURE2D(tex1, vec2(out_uvs, 0));
		FRAGCOLOR = out_color * texcolor;
  }`
)

// ObjRender ...
type ObjRender struct {
	Obj *Obj

	progCoord *GPProgram
	vbo       *VBO
	tex       *GPTexture
}

// ObjsRender ...
type ObjsRender struct {
	Objs []*ObjRender
}

// Bounds ...
func (m *ObjsRender) Bounds() (b Bounds) {
	var build BoundBuilder
	build.reset()

	for _, obj := range m.Objs {
		build.include64(obj.Obj.Bounds.X.Lo, obj.Obj.Bounds.Y.Lo, obj.Obj.Bounds.Z.Lo)
		build.include64(obj.Obj.Bounds.X.Hi, obj.Obj.Bounds.Y.Hi, obj.Obj.Bounds.Z.Hi)
	}
	return build.build()
}

// NormalizedMat ...
func (m *ObjsRender) NormalizedMat() (mres mgl32.Mat4) {
	center := m.Bounds().Center()
	length := m.Bounds().Length()
	scale := 1 / length

	mres = mgl32.HomogRotate3DX(math.Pi / 2)
	mres = mres.Mul4(mgl32.Scale3D(scale, scale, scale))
	mres = mres.Mul4(mgl32.Translate3D(-center[0], -center[1], -center[2]))
	return mres
}

// Delete ...
func (m *ObjsRender) Delete() {
	for _, obj := range m.Objs {
		obj.Delete()
	}
}

// Draw ...
func (m *ObjsRender) Draw(material *Material, camera, projection, model mgl32.Mat4, light mgl32.Vec3, uvAngle float64, tex *GPTexture) {
	for _, obj := range m.Objs {
		obj.Draw(material, camera, projection, model, light, uvAngle, tex)
	}
}

// NewObjsVBO ...
func NewObjsVBO(objs []*Obj, hasColorTable bool) (m *ObjsRender) {
	m = &ObjsRender{}
	for _, obj := range objs {
		m.Objs = append(m.Objs, NewObjVBO(obj, hasColorTable))
	}
	return m
}

// NewObjVBO ...
func NewObjVBO(obj *Obj, hasColorTable bool) (m *ObjRender) {
	var err error

	m = &ObjRender{
		Obj: obj,
	}

	var attribs = []string{
		"position",
		"uvs",
		"normal",
	}
	if obj.TexImg != nil {
		if m.progCoord, err = LoadShaderProgram(sVertShaderObjTex, sFragShaderObjTex, attribs); err != nil {
			panic(err)
		}

		if m.tex, err = NewRGBATexture(obj.TexImg, true, false); err != nil {
			panic(err)
		}
	} else if hasColorTable {
		if m.progCoord, err = LoadShaderProgram(sVertShaderObjColorTable, sFragShaderObjColorTable, attribs); err != nil {
			panic(err)
		}
	} else {
		if m.progCoord, err = LoadShaderProgram(sVertShaderObj, sFragShaderObj, attribs); err != nil {
			panic(err)
		}
	}
	opt := DefaultVBOOptions()
	opt.Normals = 3
	if obj.TexImg == nil {
		opt.UV = 1
	}
	m.vbo = NewVBO(m.progCoord, opt, obj.ObjVertices, nil)

	return m
}

// Delete ...
func (m *ObjRender) Delete() {
	m.progCoord.DeleteProgram()
	m.vbo.DeleteVBO()
	if m.tex != nil {
		m.tex.DeleteTexture()
	}
}

// NormalizedMat ...
func (m *ObjRender) NormalizedMat() (mres mgl32.Mat4) {
	return m.Obj.NormalizedMat()
}

// Draw ...
func (m *ObjRender) Draw(material *Material, camera, projection, model mgl32.Mat4, light mgl32.Vec3, uvAngle float64, tex *GPTexture) {
	m.progCoord.UseProgram()

	matuv := mgl32.Translate2D(0.5, 0.5)
	matuv = matuv.Mul3(mgl32.Rotate3DZ(-float32(uvAngle)))
	matuv = matuv.Mul3(mgl32.Translate2D(-0.5, -0.5))

	mViewModel := camera.Mul4(model)
	mProjViewModel := projection.Mul4(mViewModel)
	m.progCoord.ProgramUniformMatrix4fv("mViewModel", mViewModel)
	m.progCoord.ProgramUniformMatrix4fv("mProjViewModel", mProjViewModel)
	m.progCoord.ProgramUniformMatrix4fv("mView", camera)
	m.progCoord.ProgramUniform3fv("light", light)
	m.progCoord.ProgramUniformMatrix3fv("matuv", matuv)

	if m.tex != nil {
		m.tex.BindTexture(0)
		m.progCoord.ProgramUniform1i("tex1", 0)
	} else if tex != nil {
		tex.BindTexture(0)
		m.progCoord.ProgramUniform1i("tex1", 0)
	}

	m.vbo.Bind(m.progCoord)
	m.progCoord.Material(material)

	var err error
	if err = m.progCoord.ValidateProgram(); err != nil {
		panic(err)
	}
	m.vbo.Draw()
	m.vbo.Unbind(m.progCoord)

	if m.tex != nil {
		m.tex.UnbindTexture(0)
	} else if tex != nil {
		m.tex.UnbindTexture(0)
	}

	m.progCoord.UnuseProgram()
}
<commit_msg>simpler<commit_after>package glplus

import (
	"math"

	"github.com/go-gl/mathgl/mgl32"
)

var (
	sVertShaderObj = `#version 330
  ATTRIBUTE vec3 position;
	ATTRIBUTE float uvs;
	ATTRIBUTE vec3 normal;
	VARYINGOUT float out_uvs;
	VARYINGOUT vec4 out_color;
	uniform vec3 light;
	uniform mat4 mProjViewModel;
	uniform mat4 mViewModel;
	uniform mat4 mView;
	uniform vec4 ambient;
	uniform float shininess;
	uniform vec4 specular;
	uniform vec4 diffuse;

  void main()
  {
		// set the specular term to black
		vec4 spec = vec4(0.0);

		vec3 l_dir = normalize(mView * vec4(light, 0)).xyz;
		vec3 n = normalize(mViewModel * vec4(normal, 0)).xyz;
		float intensity = max(dot(n, l_dir), 0.0);

		// if the vertex is lit compute the specular term
		if (intensity > 0.0) {

				// compute position in camera space
				vec3 pos = vec3(mViewModel * vec4(position, 1)).xyz;
				// compute eye vector and normalize it
				vec3 eye = normalize(-pos);
				// compute the half vector
				vec3 h = normalize(l_dir + eye);

				// compute the specular term into spec
				float intSpec = max(dot(h,n), 0.0);
				spec = specular * pow(intSpec, shininess);
		}
		// add the specular term
		out_color = max(intensity *  diffuse + spec, ambient);

		out_uvs = uvs;
		gl_Position = mProjViewModel * vec4(position, 1.0);
  }`

	sFragShaderObj = `#version 330
	VARYINGIN float out_uvs;
	VARYINGIN vec4 out_color;
  COLOROUT

  void main(void)
  {
		FRAGCOLOR = out_color;
  }`

	sVertShaderObjTex = `#version 330
	ATTRIBUTE vec3 position;
	ATTRIBUTE vec2 uvs;
	ATTRIBUTE vec3 normal;
	VARYINGOUT vec2 out_uvs;
	VARYINGOUT vec4 out_color;
	uniform vec3 light;
	uniform mat4 mProjViewModel;
	uniform mat4 mViewModel;
	uniform mat4 mView;
	uniform vec4 ambient;
	uniform float shininess;
	uniform vec4 specular;
	uniform vec4 diffuse;

	void main()
	{
		// set the specular term to black
		vec4 spec = vec4(0.0);

		vec3 l_dir = normalize(mView * vec4(light, 0)).xyz;
		vec3 n = normalize(mViewModel * vec4(normal, 0)).xyz;
		float intensity = max(dot(n, l_dir), 0.0);

		// if the vertex is lit compute the specular term
		if (intensity > 0.0) {

				// compute position in camera space
				vec3 pos = vec3(mViewModel * vec4(position, 1)).xyz;
				// compute eye vector and normalize it
				vec3 eye = normalize(-pos);
				// compute the half vector
				vec3 h = normalize(l_dir + eye);

				// compute the specular term into spec
				float intSpec = max(dot(h,n), 0.0);
				spec = specular * pow(intSpec, shininess);
		}
		// add the specular term
		out_color = max(intensity *  diffuse + spec, ambient);

		out_uvs = uvs;
		gl_Position = mProjViewModel * vec4(position, 1.0);
	}`

	sFragShaderObjTex = `#version 330
	uniform sampler2D tex1;
	uniform mat3 matuv;
  VARYINGIN vec2 out_uvs;
	VARYINGIN vec4 out_color;
  COLOROUT

  void main(void)
  {
		vec2 new_uvs = vec2(1.0-out_uvs.x, out_uvs.y);
		new_uvs = (matuv * vec3(new_uvs, 1)).xy;
		vec4 texcolor = TEXTURE2D(tex1, new_uvs);
		FRAGCOLOR = out_color * texcolor;
  }`

	sFragShaderObjColorTable = `#version 330
	uniform sampler2D tex1;
  VARYINGIN float out_uvs;
	VARYINGIN vec4 out_color;
  COLOROUT

  void main(void)
  {
		vec4 texcolor = TEXTURE2D(tex1, vec2(out_uvs, 0));
		FRAGCOLOR = out_color * texcolor;
  }`
)

// ObjRender ...
type ObjRender struct {
	Obj *Obj

	progCoord *GPProgram
	vbo       *VBO
	tex       *GPTexture
}

// ObjsRender ...
type ObjsRender struct {
	Objs []*ObjRender
}

// Bounds ...
func (m *ObjsRender) Bounds() (b Bounds) {
	var build BoundBuilder
	build.reset()

	for _, obj := range m.Objs {
		build.include64(obj.Obj.Bounds.X.Lo, obj.Obj.Bounds.Y.Lo, obj.Obj.Bounds.Z.Lo)
		build.include64(obj.Obj.Bounds.X.Hi, obj.Obj.Bounds.Y.Hi, obj.Obj.Bounds.Z.Hi)
	}
	return build.build()
}

// NormalizedMat ...
func (m *ObjsRender) NormalizedMat() (mres mgl32.Mat4) {
	center := m.Bounds().Center()
	length := m.Bounds().Length()
	scale := 1 / length

	mres = mgl32.HomogRotate3DX(math.Pi / 2)
	mres = mres.Mul4(mgl32.Scale3D(scale, scale, scale))
	mres = mres.Mul4(mgl32.Translate3D(-center[0], -center[1], -center[2]))
	return mres
}

// Delete ...
func (m *ObjsRender) Delete() {
	for _, obj := range m.Objs {
		obj.Delete()
	}
}

// Draw ...
func (m *ObjsRender) Draw(material *Material, camera, projection, model mgl32.Mat4, light mgl32.Vec3, uvAngle float64, tex *GPTexture) {
	for _, obj := range m.Objs {
		obj.Draw(material, camera, projection, model, light, uvAngle, tex)
	}
}

// NewObjsVBO ...
func NewObjsVBO(objs []*Obj, hasColorTable bool) (m *ObjsRender) {
	m = &ObjsRender{}
	for _, obj := range objs {
		m.Objs = append(m.Objs, NewObjVBO(obj, hasColorTable))
	}
	return m
}

// NewObjVBO ...
func NewObjVBO(obj *Obj, hasColorTable bool) (m *ObjRender) {
	var err error

	m = &ObjRender{
		Obj: obj,
	}

	var attribs = []string{
		"position",
		"uvs",
		"normal",
	}
	if obj.TexImg != nil {
		if m.progCoord, err = LoadShaderProgram(sVertShaderObjTex, sFragShaderObjTex, attribs); err != nil {
			panic(err)
		}

		if m.tex, err = NewRGBATexture(obj.TexImg, true, false); err != nil {
			panic(err)
		}
	} else if hasColorTable {
		if m.progCoord, err = LoadShaderProgram(sVertShaderObj, sFragShaderObjColorTable, attribs); err != nil {
			panic(err)
		}
	} else {
		if m.progCoord, err = LoadShaderProgram(sVertShaderObj, sFragShaderObj, attribs); err != nil {
			panic(err)
		}
	}
	opt := DefaultVBOOptions()
	opt.Normals = 3
	if obj.TexImg == nil {
		opt.UV = 1
	}
	m.vbo = NewVBO(m.progCoord, opt, obj.ObjVertices, nil)

	return m
}

// Delete ...
func (m *ObjRender) Delete() {
	m.progCoord.DeleteProgram()
	m.vbo.DeleteVBO()
	if m.tex != nil {
		m.tex.DeleteTexture()
	}
}

// NormalizedMat ...
func (m *ObjRender) NormalizedMat() (mres mgl32.Mat4) {
	return m.Obj.NormalizedMat()
}

// Draw ...
func (m *ObjRender) Draw(material *Material, camera, projection, model mgl32.Mat4, light mgl32.Vec3, uvAngle float64, tex *GPTexture) {
	m.progCoord.UseProgram()

	matuv := mgl32.Translate2D(0.5, 0.5)
	matuv = matuv.Mul3(mgl32.Rotate3DZ(-float32(uvAngle)))
	matuv = matuv.Mul3(mgl32.Translate2D(-0.5, -0.5))

	mViewModel := camera.Mul4(model)
	mProjViewModel := projection.Mul4(mViewModel)
	m.progCoord.ProgramUniformMatrix4fv("mViewModel", mViewModel)
	m.progCoord.ProgramUniformMatrix4fv("mProjViewModel", mProjViewModel)
	m.progCoord.ProgramUniformMatrix4fv("mView", camera)
	m.progCoord.ProgramUniform3fv("light", light)
	m.progCoord.ProgramUniformMatrix3fv("matuv", matuv)

	if m.tex != nil {
		m.tex.BindTexture(0)
		m.progCoord.ProgramUniform1i("tex1", 0)
	} else if tex != nil {
		tex.BindTexture(0)
		m.progCoord.ProgramUniform1i("tex1", 0)
	}

	m.vbo.Bind(m.progCoord)
	m.progCoord.Material(material)

	var err error
	if err = m.progCoord.ValidateProgram(); err != nil {
		panic(err)
	}
	m.vbo.Draw()
	m.vbo.Unbind(m.progCoord)

	if m.tex != nil {
		m.tex.UnbindTexture(0)
	} else if tex != nil {
		m.tex.UnbindTexture(0)
	}

	m.progCoord.UnuseProgram()
}
<|endoftext|>


<commit_before>package querier

import (
	"fmt"
	"time"

	"github.com/prometheus/common/model"
	"github.com/prometheus/prometheus/storage/local"
	"github.com/prometheus/prometheus/storage/metric"
	"golang.org/x/net/context"

	"github.com/weaveworks/cortex/chunk"
	"github.com/weaveworks/cortex/util"
)

// A Querier allows querying all samples in a given time range that match a set
// of label matchers.
type Querier interface {
	Query(ctx context.Context, from, to model.Time, matchers ...*metric.LabelMatcher) (model.Matrix, error)
	LabelValuesForLabelName(context.Context, model.LabelName) (model.LabelValues, error)
}

// A ChunkQuerier is a Querier that fetches samples from a ChunkStore.
type ChunkQuerier struct {
	Store chunk.Store
}

// Query implements Querier and transforms a list of chunks into sample
// matrices.
func (q *ChunkQuerier) Query(ctx context.Context, from, to model.Time, matchers ...*metric.LabelMatcher) (model.Matrix, error) {
	// Get chunks for all matching series from ChunkStore.
	chunks, err := q.Store.Get(ctx, from, to, matchers...)
	if err != nil {
		return nil, err
	}

	return chunk.ChunksToMatrix(chunks)
}

// LabelValuesForLabelName returns all of the label values that are associated with a given label name.
func (q *ChunkQuerier) LabelValuesForLabelName(ctx context.Context, ln model.LabelName) (model.LabelValues, error) {
	// TODO: Support querying historical label values at some point?
	return nil, nil
}

type Queryable struct {
	Q local.Querier
}

func (q Queryable) Querier() (local.Querier, error) {
	return q.Q, nil
}

// A MergeQuerier is a promql.Querier that merges the results of multiple
// cortex.Queriers for the same query.
type MergeQuerier struct {
	Queriers []Querier
}

// QueryRange fetches series for a given time range and label matchers from multiple
// promql.Queriers and returns the merged results as a map of series iterators.
func (qm MergeQuerier) QueryRange(ctx context.Context, from, to model.Time, matchers ...*metric.LabelMatcher) ([]local.SeriesIterator, error) {
	fpToIt := map[model.Fingerprint]local.SeriesIterator{}

	// Fetch samples from all queriers and group them by fingerprint (unsorted
	// and with overlap).
	for _, q := range qm.Queriers {
		matrix, err := q.Query(ctx, from, to, matchers...)
		if err != nil {
			return nil, err
		}

		for _, ss := range matrix {
			fp := ss.Metric.Fingerprint()
			if it, ok := fpToIt[fp]; !ok {
				fpToIt[fp] = sampleStreamIterator{
					ss: ss,
				}
			} else {
				ssIt := it.(sampleStreamIterator)
				ssIt.ss.Values = util.MergeSamples(ssIt.ss.Values, ss.Values)
			}
		}
	}

	iterators := make([]local.SeriesIterator, 0, len(fpToIt))
	for _, it := range fpToIt {
		iterators = append(iterators, it)
	}

	return iterators, nil
}

// QueryInstant fetches series for a given instant and label matchers from multiple
// promql.Queriers and returns the merged results as a map of series iterators.
func (qm MergeQuerier) QueryInstant(ctx context.Context, ts model.Time, stalenessDelta time.Duration, matchers ...*metric.LabelMatcher) ([]local.SeriesIterator, error) {
	// For now, just fall back to QueryRange, as QueryInstant is merely allows
	// for instant-specific optimization.
	return qm.QueryRange(ctx, ts.Add(-stalenessDelta), ts, matchers...)
}

// MetricsForLabelMatchers Implements local.Querier.
func (qm MergeQuerier) MetricsForLabelMatchers(ctx context.Context, from, through model.Time, matcherSets ...metric.LabelMatchers) ([]metric.Metric, error) {
	// TODO: Implement.
	return nil, nil
}

// LastSampleForLabelMatchers implements local.Querier.
func (qm MergeQuerier) LastSampleForLabelMatchers(ctx context.Context, cutoff model.Time, matcherSets ...metric.LabelMatchers) (model.Vector, error) {
	// TODO: Implement.
	return nil, nil
}

// LabelValuesForLabelName implements local.Querier.
func (qm MergeQuerier) LabelValuesForLabelName(ctx context.Context, name model.LabelName) (model.LabelValues, error) {
	valueSet := map[model.LabelValue]struct{}{}
	for _, q := range qm.Queriers {
		vals, err := q.LabelValuesForLabelName(ctx, name)
		if err != nil {
			return nil, err
		}
		for _, v := range vals {
			valueSet[v] = struct{}{}
		}
	}

	values := make(model.LabelValues, 0, len(valueSet))
	for v := range valueSet {
		values = append(values, v)
	}
	return values, nil
}

func (qm MergeQuerier) Close() error {
	return nil
}

// TODO(juliusv): Remove all the dummy local.Storage methods below
// once the upstream web API expects a leaner interface.

type DummyStorage struct {
	Queryable
}

// Append implements local.Storage. Needed to satisfy interface
// requirements for usage with the Prometheus web API.
func (DummyStorage) Append(*model.Sample) error {
	panic("MergeQuerier.Append() should never be called")
}

// NeedsThrottling implements local.Storage. Needed to satisfy
// interface requirements for usage with the Prometheus web API.
func (DummyStorage) NeedsThrottling() bool {
	panic("MergeQuerier.NeedsThrottling() should never be called")
}

// DropMetricsForLabelMatchers implements local.Storage. Needed
// to satisfy interface requirements for usage with the Prometheus
// web API.
func (DummyStorage) DropMetricsForLabelMatchers(context.Context, ...*metric.LabelMatcher) (int, error) {
	return 0, fmt.Errorf("dropping metrics is not supported")
}

// Start implements local.Storage. Needed to satisfy interface
// requirements for usage with the Prometheus web API.
func (DummyStorage) Start() error {
	panic("MergeQuerier.Start() should never be called")
}

// Stop implements local.Storage. Needed to satisfy interface
// requirements for usage with the Prometheus web API.
func (DummyStorage) Stop() error {
	panic("MergeQuerier.Stop() should never be called")
}

// WaitForIndexing implements local.Storage. Needed to satisfy
// interface requirements for usage with the Prometheus
// web API.
func (DummyStorage) WaitForIndexing() {
	panic("MergeQuerier.WaitForIndexing() should never be called")
}
<commit_msg>Fix lint<commit_after>package querier

import (
	"fmt"
	"time"

	"github.com/prometheus/common/model"
	"github.com/prometheus/prometheus/storage/local"
	"github.com/prometheus/prometheus/storage/metric"
	"golang.org/x/net/context"

	"github.com/weaveworks/cortex/chunk"
	"github.com/weaveworks/cortex/util"
)

// A Querier allows querying all samples in a given time range that match a set
// of label matchers.
type Querier interface {
	Query(ctx context.Context, from, to model.Time, matchers ...*metric.LabelMatcher) (model.Matrix, error)
	LabelValuesForLabelName(context.Context, model.LabelName) (model.LabelValues, error)
}

// A ChunkQuerier is a Querier that fetches samples from a ChunkStore.
type ChunkQuerier struct {
	Store chunk.Store
}

// Query implements Querier and transforms a list of chunks into sample
// matrices.
func (q *ChunkQuerier) Query(ctx context.Context, from, to model.Time, matchers ...*metric.LabelMatcher) (model.Matrix, error) {
	// Get chunks for all matching series from ChunkStore.
	chunks, err := q.Store.Get(ctx, from, to, matchers...)
	if err != nil {
		return nil, err
	}

	return chunk.ChunksToMatrix(chunks)
}

// LabelValuesForLabelName returns all of the label values that are associated with a given label name.
func (q *ChunkQuerier) LabelValuesForLabelName(ctx context.Context, ln model.LabelName) (model.LabelValues, error) {
	// TODO: Support querying historical label values at some point?
	return nil, nil
}

// Queryable is an adapter between Prometheus' Queryable and Querier.
type Queryable struct {
	Q local.Querier
}

// Querier implements Queryable
func (q Queryable) Querier() (local.Querier, error) {
	return q.Q, nil
}

// A MergeQuerier is a promql.Querier that merges the results of multiple
// cortex.Queriers for the same query.
type MergeQuerier struct {
	Queriers []Querier
}

// QueryRange fetches series for a given time range and label matchers from multiple
// promql.Queriers and returns the merged results as a map of series iterators.
func (qm MergeQuerier) QueryRange(ctx context.Context, from, to model.Time, matchers ...*metric.LabelMatcher) ([]local.SeriesIterator, error) {
	fpToIt := map[model.Fingerprint]local.SeriesIterator{}

	// Fetch samples from all queriers and group them by fingerprint (unsorted
	// and with overlap).
	for _, q := range qm.Queriers {
		matrix, err := q.Query(ctx, from, to, matchers...)
		if err != nil {
			return nil, err
		}

		for _, ss := range matrix {
			fp := ss.Metric.Fingerprint()
			if it, ok := fpToIt[fp]; !ok {
				fpToIt[fp] = sampleStreamIterator{
					ss: ss,
				}
			} else {
				ssIt := it.(sampleStreamIterator)
				ssIt.ss.Values = util.MergeSamples(ssIt.ss.Values, ss.Values)
			}
		}
	}

	iterators := make([]local.SeriesIterator, 0, len(fpToIt))
	for _, it := range fpToIt {
		iterators = append(iterators, it)
	}

	return iterators, nil
}

// QueryInstant fetches series for a given instant and label matchers from multiple
// promql.Queriers and returns the merged results as a map of series iterators.
func (qm MergeQuerier) QueryInstant(ctx context.Context, ts model.Time, stalenessDelta time.Duration, matchers ...*metric.LabelMatcher) ([]local.SeriesIterator, error) {
	// For now, just fall back to QueryRange, as QueryInstant is merely allows
	// for instant-specific optimization.
	return qm.QueryRange(ctx, ts.Add(-stalenessDelta), ts, matchers...)
}

// MetricsForLabelMatchers Implements local.Querier.
func (qm MergeQuerier) MetricsForLabelMatchers(ctx context.Context, from, through model.Time, matcherSets ...metric.LabelMatchers) ([]metric.Metric, error) {
	// TODO: Implement.
	return nil, nil
}

// LastSampleForLabelMatchers implements local.Querier.
func (qm MergeQuerier) LastSampleForLabelMatchers(ctx context.Context, cutoff model.Time, matcherSets ...metric.LabelMatchers) (model.Vector, error) {
	// TODO: Implement.
	return nil, nil
}

// LabelValuesForLabelName implements local.Querier.
func (qm MergeQuerier) LabelValuesForLabelName(ctx context.Context, name model.LabelName) (model.LabelValues, error) {
	valueSet := map[model.LabelValue]struct{}{}
	for _, q := range qm.Queriers {
		vals, err := q.LabelValuesForLabelName(ctx, name)
		if err != nil {
			return nil, err
		}
		for _, v := range vals {
			valueSet[v] = struct{}{}
		}
	}

	values := make(model.LabelValues, 0, len(valueSet))
	for v := range valueSet {
		values = append(values, v)
	}
	return values, nil
}

// Close is a noop
func (qm MergeQuerier) Close() error {
	return nil
}

// DummyStorage creates a local.Storage compatible struct from a
// Querable, such that it can be used with web.NewAPI.
// TODO(juliusv): Remove all the dummy local.Storage methods below
// once the upstream web API expects a leaner interface.
type DummyStorage struct {
	Queryable
}

// Append implements local.Storage. Needed to satisfy interface
// requirements for usage with the Prometheus web API.
func (DummyStorage) Append(*model.Sample) error {
	panic("MergeQuerier.Append() should never be called")
}

// NeedsThrottling implements local.Storage. Needed to satisfy
// interface requirements for usage with the Prometheus web API.
func (DummyStorage) NeedsThrottling() bool {
	panic("MergeQuerier.NeedsThrottling() should never be called")
}

// DropMetricsForLabelMatchers implements local.Storage. Needed
// to satisfy interface requirements for usage with the Prometheus
// web API.
func (DummyStorage) DropMetricsForLabelMatchers(context.Context, ...*metric.LabelMatcher) (int, error) {
	return 0, fmt.Errorf("dropping metrics is not supported")
}

// Start implements local.Storage. Needed to satisfy interface
// requirements for usage with the Prometheus web API.
func (DummyStorage) Start() error {
	panic("MergeQuerier.Start() should never be called")
}

// Stop implements local.Storage. Needed to satisfy interface
// requirements for usage with the Prometheus web API.
func (DummyStorage) Stop() error {
	panic("MergeQuerier.Stop() should never be called")
}

// WaitForIndexing implements local.Storage. Needed to satisfy
// interface requirements for usage with the Prometheus
// web API.
func (DummyStorage) WaitForIndexing() {
	panic("MergeQuerier.WaitForIndexing() should never be called")
}
<|endoftext|>


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

package main

import (
	"bytes"
	"encoding/hex"
	"fmt"
	"github.com/jacobsa/comeback/blob"
	"github.com/jacobsa/comeback/disk"
	"github.com/jacobsa/comeback/fs"
	"github.com/jacobsa/comeback/repr"
	"io"
	"log"
	"os"
	"path"
	"syscall"
)

const (
	gTarget = "/tmp/restore_target"
)

var blobStore blob.Store

type score struct {
	hash []byte
}

func (s *score) Sha1Hash() []byte {
	return s.hash
}

func fromHexHash(h string) (blob.Score, error) {
	b, err := hex.DecodeString(h)
	if err != nil {
		return nil, fmt.Errorf("Invalid hex string: %s", h)
	}

	return &score{b}, nil
}

// Restore the file whose contents are described by the referenced blobs to the
// supplied target, whose parent must already exist.
func restoreFile(target string, scores []blob.Score) error {
	// Open the file.
	f, err := os.Create(target)
	defer f.Close()

	if err != nil {
		return fmt.Errorf("Create: %v", err)
	}

	// Process each blob.
	for _, score := range scores {
		// Load the blob.
		blob, err := blobStore.Load(score)
		if err != nil {
			return fmt.Errorf("Loading blob: %v", err)
		}

		// Write out its contents.
		_, err = io.Copy(f, bytes.NewReader(blob))
		if err != nil {
			return fmt.Errorf("Copy: %v", err)
		}
	}

	return nil
}

// Like os.Chmod, but don't follow symlinks.
func setPermissions(path string, permissions os.FileMode) error {
	mode := syscallPermissions(permissions)

	// Open the file without following symlinks.
	fd, err := syscall.Open(path, syscall.O_RDONLY|syscall.O_SYMLINK, 0)
	if err != nil {
		return err
	}

	defer syscall.Close(fd)

	// Call fchmod.
	err = syscall.Fchmod(fd, mode)
	if err != nil {
		return err
	}

	return nil
}

// Restore the directory whose contents are described by the referenced blob to
// the supplied target, which must already exist.
func restoreDir(target string, score blob.Score) error {
	// Load the appropriate blob.
	blob, err := blobStore.Load(score)
	if err != nil {
		return fmt.Errorf("Loading blob: %v", err)
	}

	// Parse its contents.
	entries, err := repr.Unmarshal(blob)
	if err != nil {
		return fmt.Errorf("Parsing blob: %v", err)
	}

	// Deal with each entry.
	for _, entry := range entries {
		entryPath := path.Join(target, entry.Name)

		// Switch on type.
		switch entry.Type {
		case fs.TypeFile:
			if err := restoreFile(entryPath, entry.Scores); err != nil {
				return err
			}

			if err := setPermissions(entryPath, entry.Permissions); err != nil {
				return err
			}

		case fs.TypeDirectory:
			if len(entry.Scores) != 1 {
				return fmt.Errorf("Wrong number of scores: %v", entry)
			}

			if err = os.Mkdir(entryPath, 0700); err != nil {
				return err
			}

			if err = restoreDir(entryPath, entry.Scores[0]); err != nil {
				return err
			}

		case fs.TypeSymlink:
			err = os.Symlink(entry.Target, entryPath)
			if err != nil {
				return err
			}

		case fs.TypeNamedPipe:
			err = makeNamedPipe(entryPath, entry.Permissions)
			if err != nil {
				return err
			}

		case fs.TypeBlockDevice:
			err = makeBlockDevice(entryPath, entry.Permissions, entry.Device)
			if err != nil {
				return err
			}

		case fs.TypeCharDevice:
			err = makeCharDevice(entryPath, entry.Permissions, entry.Device)
			if err != nil {
				return err
			}

		default:
			return fmt.Errorf("Don't know how to deal with entry: %v", entry)
		}
	}

	return nil
}

func syscallPermissions(permissions os.FileMode) (o uint32) {
	// Include r/w/x permission bits.
	o = uint32(permissions & os.ModePerm)

	// Also include setuid/setgid/sticky bits.
	if permissions&os.ModeSetuid != 0 {
		o |= syscall.S_ISUID
	}

	if permissions&os.ModeSetgid != 0 {
		o |= syscall.S_ISGID
	}

	if permissions&os.ModeSticky != 0 {
		o |= syscall.S_ISVTX
	}

	return
}

// Create a named pipe at the supplied path.
func makeNamedPipe(path string, permissions os.FileMode) error {
	return syscall.Mkfifo(path, syscallPermissions(permissions))
}

// Create a block device at the supplied path.
func makeBlockDevice(path string, permissions os.FileMode, dev int32) error {
	mode := syscallPermissions(permissions) | syscall.S_IFBLK
	if err := syscall.Mknod(path, mode, int(dev)); err != nil {
		return fmt.Errorf("syscall.Mknod: %v", err)
	}

	return nil
}

// Create a character device at the supplied path.
func makeCharDevice(path string, permissions os.FileMode, dev int32) error {
	mode := syscallPermissions(permissions) | syscall.S_IFCHR
	if err := syscall.Mknod(path, mode, int(dev)); err != nil {
		return fmt.Errorf("syscall.Mknod: %v", err)
	}

	return nil
}

func main() {
	var err error

	// Create the blob store.
	blobStore, err = disk.NewBlobStore("/tmp/blobs")
	if err != nil {
		log.Fatalf("Creating store: %v", err)
	}

	// Parse the score.
	score, err := fromHexHash("697e002f699399f859514f621953c64e14a0e110")
	if err != nil {
		log.Fatalf("Parsing score: %v", err)
	}

	// Make sure the target doesn't exist.
	err = os.RemoveAll(gTarget)
	if err != nil {
		log.Fatalf("RemoveAll: %v", err)
	}

	// Create the target.
	err = os.Mkdir("/tmp/restore_target", 0755)
	if err != nil {
		log.Fatalf("Mkdir: %v", err)
	}

	// Attempt a restore.
	err = restoreDir(gTarget, score)
	if err != nil {
		log.Fatalf("Restoring: %v", err)
	}
}
<commit_msg>Updated score.<commit_after>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"bytes"
	"encoding/hex"
	"fmt"
	"github.com/jacobsa/comeback/blob"
	"github.com/jacobsa/comeback/disk"
	"github.com/jacobsa/comeback/fs"
	"github.com/jacobsa/comeback/repr"
	"io"
	"log"
	"os"
	"path"
	"syscall"
)

const (
	gTarget = "/tmp/restore_target"
)

var blobStore blob.Store

type score struct {
	hash []byte
}

func (s *score) Sha1Hash() []byte {
	return s.hash
}

func fromHexHash(h string) (blob.Score, error) {
	b, err := hex.DecodeString(h)
	if err != nil {
		return nil, fmt.Errorf("Invalid hex string: %s", h)
	}

	return &score{b}, nil
}

// Restore the file whose contents are described by the referenced blobs to the
// supplied target, whose parent must already exist.
func restoreFile(target string, scores []blob.Score) error {
	// Open the file.
	f, err := os.Create(target)
	defer f.Close()

	if err != nil {
		return fmt.Errorf("Create: %v", err)
	}

	// Process each blob.
	for _, score := range scores {
		// Load the blob.
		blob, err := blobStore.Load(score)
		if err != nil {
			return fmt.Errorf("Loading blob: %v", err)
		}

		// Write out its contents.
		_, err = io.Copy(f, bytes.NewReader(blob))
		if err != nil {
			return fmt.Errorf("Copy: %v", err)
		}
	}

	return nil
}

// Like os.Chmod, but don't follow symlinks.
func setPermissions(path string, permissions os.FileMode) error {
	mode := syscallPermissions(permissions)

	// Open the file without following symlinks.
	fd, err := syscall.Open(path, syscall.O_RDONLY|syscall.O_SYMLINK, 0)
	if err != nil {
		return err
	}

	defer syscall.Close(fd)

	// Call fchmod.
	err = syscall.Fchmod(fd, mode)
	if err != nil {
		return err
	}

	return nil
}

// Restore the directory whose contents are described by the referenced blob to
// the supplied target, which must already exist.
func restoreDir(target string, score blob.Score) error {
	// Load the appropriate blob.
	blob, err := blobStore.Load(score)
	if err != nil {
		return fmt.Errorf("Loading blob: %v", err)
	}

	// Parse its contents.
	entries, err := repr.Unmarshal(blob)
	if err != nil {
		return fmt.Errorf("Parsing blob: %v", err)
	}

	// Deal with each entry.
	for _, entry := range entries {
		entryPath := path.Join(target, entry.Name)

		// Switch on type.
		switch entry.Type {
		case fs.TypeFile:
			if err := restoreFile(entryPath, entry.Scores); err != nil {
				return err
			}

			if err := setPermissions(entryPath, entry.Permissions); err != nil {
				return err
			}

		case fs.TypeDirectory:
			if len(entry.Scores) != 1 {
				return fmt.Errorf("Wrong number of scores: %v", entry)
			}

			if err = os.Mkdir(entryPath, 0700); err != nil {
				return err
			}

			if err = restoreDir(entryPath, entry.Scores[0]); err != nil {
				return err
			}

		case fs.TypeSymlink:
			err = os.Symlink(entry.Target, entryPath)
			if err != nil {
				return err
			}

		case fs.TypeNamedPipe:
			err = makeNamedPipe(entryPath, entry.Permissions)
			if err != nil {
				return err
			}

		case fs.TypeBlockDevice:
			err = makeBlockDevice(entryPath, entry.Permissions, entry.Device)
			if err != nil {
				return err
			}

		case fs.TypeCharDevice:
			err = makeCharDevice(entryPath, entry.Permissions, entry.Device)
			if err != nil {
				return err
			}

		default:
			return fmt.Errorf("Don't know how to deal with entry: %v", entry)
		}
	}

	return nil
}

func syscallPermissions(permissions os.FileMode) (o uint32) {
	// Include r/w/x permission bits.
	o = uint32(permissions & os.ModePerm)

	// Also include setuid/setgid/sticky bits.
	if permissions&os.ModeSetuid != 0 {
		o |= syscall.S_ISUID
	}

	if permissions&os.ModeSetgid != 0 {
		o |= syscall.S_ISGID
	}

	if permissions&os.ModeSticky != 0 {
		o |= syscall.S_ISVTX
	}

	return
}

// Create a named pipe at the supplied path.
func makeNamedPipe(path string, permissions os.FileMode) error {
	return syscall.Mkfifo(path, syscallPermissions(permissions))
}

// Create a block device at the supplied path.
func makeBlockDevice(path string, permissions os.FileMode, dev int32) error {
	mode := syscallPermissions(permissions) | syscall.S_IFBLK
	if err := syscall.Mknod(path, mode, int(dev)); err != nil {
		return fmt.Errorf("syscall.Mknod: %v", err)
	}

	return nil
}

// Create a character device at the supplied path.
func makeCharDevice(path string, permissions os.FileMode, dev int32) error {
	mode := syscallPermissions(permissions) | syscall.S_IFCHR
	if err := syscall.Mknod(path, mode, int(dev)); err != nil {
		return fmt.Errorf("syscall.Mknod: %v", err)
	}

	return nil
}

func main() {
	var err error

	// Create the blob store.
	blobStore, err = disk.NewBlobStore("/tmp/blobs")
	if err != nil {
		log.Fatalf("Creating store: %v", err)
	}

	// Parse the score.
	score, err := fromHexHash("228a6254c7585525744192b51f099833fca8c654")
	if err != nil {
		log.Fatalf("Parsing score: %v", err)
	}

	// Make sure the target doesn't exist.
	err = os.RemoveAll(gTarget)
	if err != nil {
		log.Fatalf("RemoveAll: %v", err)
	}

	// Create the target.
	err = os.Mkdir("/tmp/restore_target", 0755)
	if err != nil {
		log.Fatalf("Mkdir: %v", err)
	}

	// Attempt a restore.
	err = restoreDir(gTarget, score)
	if err != nil {
		log.Fatalf("Restoring: %v", err)
	}
}
<|endoftext|>


<commit_before>package raftgorums

import (
	"fmt"
	"log"
	"net"
	"time"

	"golang.org/x/net/context"
	"google.golang.org/grpc"

	gorums "github.com/relab/raft/raftgorums/gorumspb"
	pb "github.com/relab/raft/raftgorums/raftpb"
)

// Node ties an instance of Raft to the network.
type Node struct {
	r *Raft

	server   *grpc.Server
	listener net.Listener

	addr  string
	peers []string

	conf *gorums.Configuration
}

// NewNode returns a Node with an instance of Raft given the configuration.
func NewNode(cfg *Config) *Node {
	peers := make([]string, len(cfg.Nodes))
	// We don't want to mutate cfg.Nodes.
	copy(peers, cfg.Nodes)

	id := cfg.ID
	addr := cfg.Nodes[id-1]
	// Exclude self.
	peers = append(peers[:id-1], peers[id:]...)

	n := &Node{
		r:      NewRaft(cfg),
		server: grpc.NewServer(),
		addr:   addr,
		peers:  peers,
	}

	gorums.RegisterRaftServer(n.server, n)

	return n
}

// Run start listening for incoming messages, and delivers outgoing messages.
func (n *Node) Run() (ferr error) {
	lis, err := net.Listen("tcp", n.addr)

	if err != nil {
		return err
	}

	go func() {
		ferr = n.server.Serve(lis)
	}()

	opts := []gorums.ManagerOption{
		gorums.WithGrpcDialOptions(
			grpc.WithBlock(),
			grpc.WithInsecure(),
			grpc.WithTimeout(TCPConnect*time.Millisecond)),
		// TODO WithLogger?
	}

	mgr, err := gorums.NewManager(n.peers, opts...)

	if err != nil {
		return err
	}

	n.conf, err = mgr.NewConfiguration(mgr.NodeIDs(), NewQuorumSpec(len(n.peers)+1))

	if err != nil {
		return err
	}

	go n.r.Run()

	for {
		rvreqout := n.r.RequestVoteRequestChan()
		aereqout := n.r.AppendEntriesRequestChan()

		select {
		case req := <-rvreqout:
			ctx, cancel := context.WithTimeout(context.Background(), TCPHeartbeat*time.Millisecond)
			res, err := n.conf.RequestVote(ctx, req)
			cancel()

			if err != nil {
				// TODO Better error message.
				log.Println(fmt.Sprintf("RequestVote failed = %v", err))

			}

			if res.RequestVoteResponse == nil {
				continue
			}

			n.r.HandleRequestVoteResponse(res.RequestVoteResponse)
		case req := <-aereqout:
			ctx, cancel := context.WithTimeout(context.Background(), TCPHeartbeat*time.Millisecond)
			res, err := n.conf.AppendEntries(ctx, req)

			if err != nil {
				// TODO Better error message.
				log.Println(fmt.Sprintf("AppendEntries failed = %v", err))

				if res.AppendEntriesResponse == nil {
					continue
				}
			}

			// Cancel on abort.
			if !res.AppendEntriesResponse.Success {
				cancel()
			}

			n.r.HandleAppendEntriesResponse(res.AppendEntriesResponse)
		}
	}
}

// RequestVote implements gorums.RaftServer.
func (n *Node) RequestVote(ctx context.Context, req *pb.RequestVoteRequest) (*pb.RequestVoteResponse, error) {
	return n.r.HandleRequestVoteRequest(req), nil
}

// AppendEntries implements gorums.RaftServer.
func (n *Node) AppendEntries(ctx context.Context, req *pb.AppendEntriesRequest) (*pb.AppendEntriesResponse, error) {
	return n.r.HandleAppendEntriesRequest(req), nil
}

// ClientCommand implements gorums.RaftServer.
func (n *Node) ClientCommand(ctx context.Context, req *pb.ClientCommandRequest) (*pb.ClientCommandResponse, error) {
	return n.r.HandleClientCommandRequest(req)
}
<commit_msg>raftgorums/node.go: Remove unused field<commit_after>package raftgorums

import (
	"fmt"
	"log"
	"net"
	"time"

	"golang.org/x/net/context"
	"google.golang.org/grpc"

	gorums "github.com/relab/raft/raftgorums/gorumspb"
	pb "github.com/relab/raft/raftgorums/raftpb"
)

// Node ties an instance of Raft to the network.
type Node struct {
	r *Raft

	server *grpc.Server

	addr  string
	peers []string

	conf *gorums.Configuration
}

// NewNode returns a Node with an instance of Raft given the configuration.
func NewNode(cfg *Config) *Node {
	peers := make([]string, len(cfg.Nodes))
	// We don't want to mutate cfg.Nodes.
	copy(peers, cfg.Nodes)

	id := cfg.ID
	addr := cfg.Nodes[id-1]
	// Exclude self.
	peers = append(peers[:id-1], peers[id:]...)

	n := &Node{
		r:      NewRaft(cfg),
		server: grpc.NewServer(),
		addr:   addr,
		peers:  peers,
	}

	gorums.RegisterRaftServer(n.server, n)

	return n
}

// Run start listening for incoming messages, and delivers outgoing messages.
func (n *Node) Run() (ferr error) {
	lis, err := net.Listen("tcp", n.addr)

	if err != nil {
		return err
	}

	go func() {
		ferr = n.server.Serve(lis)
	}()

	opts := []gorums.ManagerOption{
		gorums.WithGrpcDialOptions(
			grpc.WithBlock(),
			grpc.WithInsecure(),
			grpc.WithTimeout(TCPConnect*time.Millisecond)),
		// TODO WithLogger?
	}

	mgr, err := gorums.NewManager(n.peers, opts...)

	if err != nil {
		return err
	}

	n.conf, err = mgr.NewConfiguration(mgr.NodeIDs(), NewQuorumSpec(len(n.peers)+1))

	if err != nil {
		return err
	}

	go n.r.Run()

	for {
		rvreqout := n.r.RequestVoteRequestChan()
		aereqout := n.r.AppendEntriesRequestChan()

		select {
		case req := <-rvreqout:
			ctx, cancel := context.WithTimeout(context.Background(), TCPHeartbeat*time.Millisecond)
			res, err := n.conf.RequestVote(ctx, req)
			cancel()

			if err != nil {
				// TODO Better error message.
				log.Println(fmt.Sprintf("RequestVote failed = %v", err))

			}

			if res.RequestVoteResponse == nil {
				continue
			}

			n.r.HandleRequestVoteResponse(res.RequestVoteResponse)
		case req := <-aereqout:
			ctx, cancel := context.WithTimeout(context.Background(), TCPHeartbeat*time.Millisecond)
			res, err := n.conf.AppendEntries(ctx, req)

			if err != nil {
				// TODO Better error message.
				log.Println(fmt.Sprintf("AppendEntries failed = %v", err))

				if res.AppendEntriesResponse == nil {
					continue
				}
			}

			// Cancel on abort.
			if !res.AppendEntriesResponse.Success {
				cancel()
			}

			n.r.HandleAppendEntriesResponse(res.AppendEntriesResponse)
		}
	}
}

// RequestVote implements gorums.RaftServer.
func (n *Node) RequestVote(ctx context.Context, req *pb.RequestVoteRequest) (*pb.RequestVoteResponse, error) {
	return n.r.HandleRequestVoteRequest(req), nil
}

// AppendEntries implements gorums.RaftServer.
func (n *Node) AppendEntries(ctx context.Context, req *pb.AppendEntriesRequest) (*pb.AppendEntriesResponse, error) {
	return n.r.HandleAppendEntriesRequest(req), nil
}

// ClientCommand implements gorums.RaftServer.
func (n *Node) ClientCommand(ctx context.Context, req *pb.ClientCommandRequest) (*pb.ClientCommandResponse, error) {
	return n.r.HandleClientCommandRequest(req)
}
<|endoftext|>


<commit_before>package common

import (
	"github.com/henrylee2cn/mahonia"
	"math"
	"net/http"
	"net/url"
	"regexp"
	"strconv"
	"strings"
)

// 清除标签
func CleanHtml(str string, depth int) string {
	if depth > 0 {
		//将HTML标签全转换成小写
		re, _ := regexp.Compile("\\<[\\S\\s]+?\\>")
		str = re.ReplaceAllStringFunc(str, strings.ToLower)
	}
	if depth > 1 {
		//去除STYLE
		re, _ := regexp.Compile("\\<style[\\S\\s]+?\\</style\\>")
		str = re.ReplaceAllString(str, "")
	}
	if depth > 2 {
		//去除SCRIPT
		re, _ := regexp.Compile("\\<script[\\S\\s]+?\\</script\\>")
		str = re.ReplaceAllString(str, "")
	}
	if depth > 3 {
		//去除所有尖括号内的HTML代码，并换成换行符
		re, _ := regexp.Compile("\\<[\\S\\s]+?\\>")
		str = re.ReplaceAllString(str, "\n")
	}
	if depth > 4 {
		//去除连续的换行符
		re, _ := regexp.Compile("\\s{2,}")
		str = re.ReplaceAllString(str, "\n")
	}
	return str
}

// 去除常见转义字符
func Deprive(s string) string {
	s = strings.Replace(s, "\n", "", -1)
	s = strings.Replace(s, "\r", "", -1)
	s = strings.Replace(s, "\t", "", -1)
	s = strings.Replace(s, ` `, "", -1)
	return s
}

// 去除常见转义字符
func Deprive2(s string) string {
	s = strings.Replace(s, "\n", "", -1)
	s = strings.Replace(s, "\r", "", -1)
	s = strings.Replace(s, "\t", "", -1)
	s = strings.Replace(s, `\n`, "", -1)
	s = strings.Replace(s, `\r`, "", -1)
	s = strings.Replace(s, `\t`, "", -1)
	s = strings.Replace(s, ` `, "", -1)
	return s
}

// 舍去尾数
func Floor(f float64, n int) float64 {
	pow10_n := math.Pow10(n)
	return math.Trunc((f)*pow10_n) / pow10_n
}

// cookies字符串转[]*http.Cookie，（如"mt=ci%3D-1_0; thw=cn; sec=5572dc7c40ce07d4e8c67e4879a; v=0;"）
func SplitCookies(cookieStr string) (cookies []*http.Cookie) {
	slice := strings.Split(cookieStr, ";")
	for _, v := range slice {
		oneCookie := &http.Cookie{}
		s := strings.Split(v, "=")
		if len(s) == 2 {
			oneCookie.Name = strings.Trim(s[0], " ")
			oneCookie.Value = strings.Trim(s[1], " ")
			cookies = append(cookies, oneCookie)
		}
	}
	return
}

func DecodeString(src, charset string) string {
	return mahonia.NewDecoder(charset).ConvertString(src)
}

func EncodeString(src, charset string) string {
	return mahonia.NewEncoder(charset).ConvertString(src)
}

func ConvertToString(src string, srcCode string, tagCode string) string {
	srcCoder := mahonia.NewDecoder(srcCode)
	srcResult := srcCoder.ConvertString(src)
	tagCoder := mahonia.NewDecoder(tagCode)
	_, cdata, _ := tagCoder.Translate([]byte(srcResult), true)
	result := string(cdata)
	return result
}

func GBKToUTF8(src string) string {
	return DecodeString(EncodeString(src, "ISO-8859-1"), "GBK")
}

//将"咖啡色|绿色"转为"咖啡色|绿色"
func UnicodeToUTF8(str string) string {
	str = strings.TrimLeft(str, "&#")
	str = strings.TrimRight(str, ";")
	strSlice := strings.Split(str, ";&#")

	for k, s := range strSlice {
		if i, err := strconv.Atoi(s); err == nil {
			strSlice[k] = string(i)
		}
	}
	return strings.Join(strSlice, "")
}

//将`{"area":[["quanguo","\u5168\u56fd\u8054\u9500"]]｝`转为`{"area":[["quanguo","全国联销"]]｝`
func Unicode16ToUTF8(str string) string {
	i := 0
	if strings.Index(str, `\u`) > 0 {
		i = 1
	}
	strSlice := strings.Split(str, `\u`)
	last := len(strSlice) - 1
	if len(strSlice[last]) > 4 {
		strSlice = append(strSlice, string(strSlice[last][4:]))
		strSlice[last] = string(strSlice[last][:4])
	}
	for ; i <= last; i++ {
		if x, err := strconv.ParseInt(strSlice[i], 16, 32); err == nil {
			strSlice[i] = string(x)
		}
	}
	return strings.Join(strSlice, "")
}

//@SchemeAndHost https://www.baidu.com
//@path /search?w=x
func MakeUrl(path string, schemeAndHost ...string) (string, bool) {
	if string(path[0]) != "/" && strings.ToLower(string(path[0])) != "h" {
		path = "/" + path
	}
	u := path
	idx := strings.Index(path, "://")
	if idx < 0 {
		if len(schemeAndHost) > 0 {
			u = schemeAndHost[0] + u
		} else {
			return u, false
		}
	}
	_, err := url.Parse(u)
	if err != nil {
		return u, false
	}
	return u, true
}
<commit_msg>添加获取文章页正文的通用方法<commit_after>package common

import (
	"github.com/PuerkitoBio/goquery"
	"github.com/henrylee2cn/mahonia"
	"math"
	"net/http"
	"net/url"
	"regexp"
	"strconv"
	"strings"
)

// 清除标签
func CleanHtml(str string, depth int) string {
	if depth > 0 {
		//将HTML标签全转换成小写
		re, _ := regexp.Compile("\\<[\\S\\s]+?\\>")
		str = re.ReplaceAllStringFunc(str, strings.ToLower)
	}
	if depth > 1 {
		//去除STYLE
		re, _ := regexp.Compile("\\<style[\\S\\s]+?\\</style\\>")
		str = re.ReplaceAllString(str, "")
	}
	if depth > 2 {
		//去除SCRIPT
		re, _ := regexp.Compile("\\<script[\\S\\s]+?\\</script\\>")
		str = re.ReplaceAllString(str, "")
	}
	if depth > 3 {
		//去除所有尖括号内的HTML代码，并换成换行符
		re, _ := regexp.Compile("\\<[\\S\\s]+?\\>")
		str = re.ReplaceAllString(str, "\n")
	}
	if depth > 4 {
		//去除连续的换行符
		re, _ := regexp.Compile("\\s{2,}")
		str = re.ReplaceAllString(str, "\n")
	}
	return str
}

// 提取文章页的正文
// 思路：认为文本节点最长的标签的父标签为文章正文
func ExtractArticle(html string) string {
	//将HTML标签全转换成小写
	re := regexp.MustCompile("<[\\S\\s]+?>")
	html = re.ReplaceAllStringFunc(html, strings.ToLower)
	//去除head
	re = regexp.MustCompile("<head[\\S\\s]+?</head>")
	html = re.ReplaceAllString(html, "")
	//去除STYLE
	re = regexp.MustCompile("<style[\\S\\s]+?</style>")
	html = re.ReplaceAllString(html, "")
	//去除SCRIPT
	re = regexp.MustCompile("<script[\\S\\s]+?</script>")
	html = re.ReplaceAllString(html, "")
	//去除注释
	re = regexp.MustCompile("<![\\S\\s]+?>")
	html = re.ReplaceAllString(html, "")
	// fmt.Println(html)

	// 获取每个子标签
	re = regexp.MustCompile("<[A-Za-z]+[^<]*>([^<>]+)</[A-Za-z]+>")
	ss := re.FindAllStringSubmatch(html, -1)
	// fmt.Printf("所有子标签：\n%#v\n", ss)

	var maxLen int
	var idx int
	for k, v := range ss {
		l := len([]rune(v[1]))
		if l > maxLen {
			maxLen = l
			idx = k
		}
	}
	// fmt.Println("最长段落：", ss[idx][0])

	html = strings.Replace(html, ss[idx][0], `<pholcus id="pholcus">`+ss[idx][1]+`</pholcus>`, -1)
	r := strings.NewReader(html)
	dom, err := goquery.NewDocumentFromReader(r)
	if err != nil {
		return ""
	}
	return dom.Find("pholcus#pholcus").Parent().Text()
}

// 去除常见转义字符
func Deprive(s string) string {
	s = strings.Replace(s, "\n", "", -1)
	s = strings.Replace(s, "\r", "", -1)
	s = strings.Replace(s, "\t", "", -1)
	s = strings.Replace(s, ` `, "", -1)
	return s
}

// 去除常见转义字符
func Deprive2(s string) string {
	s = strings.Replace(s, "\n", "", -1)
	s = strings.Replace(s, "\r", "", -1)
	s = strings.Replace(s, "\t", "", -1)
	s = strings.Replace(s, `\n`, "", -1)
	s = strings.Replace(s, `\r`, "", -1)
	s = strings.Replace(s, `\t`, "", -1)
	s = strings.Replace(s, ` `, "", -1)
	return s
}

// 舍去尾数
func Floor(f float64, n int) float64 {
	pow10_n := math.Pow10(n)
	return math.Trunc((f)*pow10_n) / pow10_n
}

// cookies字符串转[]*http.Cookie，（如"mt=ci%3D-1_0; thw=cn; sec=5572dc7c40ce07d4e8c67e4879a; v=0;"）
func SplitCookies(cookieStr string) (cookies []*http.Cookie) {
	slice := strings.Split(cookieStr, ";")
	for _, v := range slice {
		oneCookie := &http.Cookie{}
		s := strings.Split(v, "=")
		if len(s) == 2 {
			oneCookie.Name = strings.Trim(s[0], " ")
			oneCookie.Value = strings.Trim(s[1], " ")
			cookies = append(cookies, oneCookie)
		}
	}
	return
}

func DecodeString(src, charset string) string {
	return mahonia.NewDecoder(charset).ConvertString(src)
}

func EncodeString(src, charset string) string {
	return mahonia.NewEncoder(charset).ConvertString(src)
}

func ConvertToString(src string, srcCode string, tagCode string) string {
	srcCoder := mahonia.NewDecoder(srcCode)
	srcResult := srcCoder.ConvertString(src)
	tagCoder := mahonia.NewDecoder(tagCode)
	_, cdata, _ := tagCoder.Translate([]byte(srcResult), true)
	result := string(cdata)
	return result
}

func GBKToUTF8(src string) string {
	return DecodeString(EncodeString(src, "ISO-8859-1"), "GBK")
}

//将"咖啡色|绿色"转为"咖啡色|绿色"
func UnicodeToUTF8(str string) string {
	str = strings.TrimLeft(str, "&#")
	str = strings.TrimRight(str, ";")
	strSlice := strings.Split(str, ";&#")

	for k, s := range strSlice {
		if i, err := strconv.Atoi(s); err == nil {
			strSlice[k] = string(i)
		}
	}
	return strings.Join(strSlice, "")
}

//将`{"area":[["quanguo","\u5168\u56fd\u8054\u9500"]]｝`转为`{"area":[["quanguo","全国联销"]]｝`
func Unicode16ToUTF8(str string) string {
	i := 0
	if strings.Index(str, `\u`) > 0 {
		i = 1
	}
	strSlice := strings.Split(str, `\u`)
	last := len(strSlice) - 1
	if len(strSlice[last]) > 4 {
		strSlice = append(strSlice, string(strSlice[last][4:]))
		strSlice[last] = string(strSlice[last][:4])
	}
	for ; i <= last; i++ {
		if x, err := strconv.ParseInt(strSlice[i], 16, 32); err == nil {
			strSlice[i] = string(x)
		}
	}
	return strings.Join(strSlice, "")
}

//@SchemeAndHost https://www.baidu.com
//@path /search?w=x
func MakeUrl(path string, schemeAndHost ...string) (string, bool) {
	if string(path[0]) != "/" && strings.ToLower(string(path[0])) != "h" {
		path = "/" + path
	}
	u := path
	idx := strings.Index(path, "://")
	if idx < 0 {
		if len(schemeAndHost) > 0 {
			u = schemeAndHost[0] + u
		} else {
			return u, false
		}
	}
	_, err := url.Parse(u)
	if err != nil {
		return u, false
	}
	return u, true
}
<|endoftext|>


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

// Package rand implements a cryptographically secure pseudorandom number
// generator.
package rand

import (
	"io"

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

// reader implements an io.Reader that returns pseudorandom bytes.
type reader struct{}

// Read implements io.Reader.Read.
func (reader) Read(p []byte) (int, error) {
	return unix.Getrandom(p, 0)
}

// Reader is the default reader.
var Reader io.Reader = reader{}

// Read reads from the default reader.
func Read(b []byte) (int, error) {
	return io.ReadFull(Reader, b)
}
<commit_msg>Support for older Linux kernels without getrandom<commit_after>// Copyright 2018 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package rand implements a cryptographically secure pseudorandom number
// generator.
package rand

import (
	"crypto/rand"
	"io"
	"sync"

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

// reader implements an io.Reader that returns pseudorandom bytes.
type reader struct {
	once         sync.Once
	useGetrandom bool
}

// Read implements io.Reader.Read.
func (r *reader) Read(p []byte) (int, error) {
	r.once.Do(func() {
		_, err := unix.Getrandom(p, 0)
		if err != unix.ENOSYS {
			r.useGetrandom = true
		}
	})

	if r.useGetrandom {
		return unix.Getrandom(p, 0)
	}
	return rand.Read(p)
}

// Reader is the default reader.
var Reader io.Reader = &reader{}

// Read reads from the default reader.
func Read(b []byte) (int, error) {
	return io.ReadFull(Reader, b)
}

// Init can be called to make sure /dev/urandom is pre-opened on kernels that
// do not support getrandom(2).
func Init() error {
	p := make([]byte, 1)
	_, err := Read(p)
	return err
}
<|endoftext|>


<commit_before>package actors

import (
	"fmt"
	"os"
	"path/filepath"

	"github.com/cloudfoundry/cli/cf/api/application_bits"
	"github.com/cloudfoundry/cli/cf/api/resources"
	"github.com/cloudfoundry/cli/cf/app_files"
	"github.com/cloudfoundry/cli/cf/errors"
	"github.com/cloudfoundry/cli/cf/models"
	"github.com/cloudfoundry/gofileutils/fileutils"
)

//go:generate counterfeiter -o fakes/fake_push_actor.go . PushActor
type PushActor interface {
	UploadApp(appGuid string, zipFile *os.File, presentFiles []resources.AppFileResource) error
	PopulateFileMode(appDir string, presentFiles []resources.AppFileResource) ([]resources.AppFileResource, error)
	GatherFiles(appDir string, uploadDir string) ([]resources.AppFileResource, bool, error)
}

type PushActorImpl struct {
	appBitsRepo application_bits.ApplicationBitsRepository
	appfiles    app_files.AppFiles
	zipper      app_files.Zipper
}

func NewPushActor(appBitsRepo application_bits.ApplicationBitsRepository, zipper app_files.Zipper, appfiles app_files.AppFiles) PushActor {
	return PushActorImpl{
		appBitsRepo: appBitsRepo,
		appfiles:    appfiles,
		zipper:      zipper,
	}
}

func (actor PushActorImpl) PopulateFileMode(appDir string, presentFiles []resources.AppFileResource) ([]resources.AppFileResource, error) {
	for i, _ := range presentFiles {
		fileInfo, err := os.Lstat(filepath.Join(appDir, presentFiles[i].Path))
		if err != nil {
			return presentFiles, err
		}
		presentFiles[i].Mode = fmt.Sprintf("%#o", fileInfo.Mode())
	}

	return presentFiles, nil
}

func (actor PushActorImpl) GatherFiles(appDir string, uploadDir string) (presentFiles []resources.AppFileResource, hasFileToUpload bool, apiErr error) {
	if actor.zipper.IsZipFile(appDir) {
		fileutils.TempDir("unzipped-app", func(tmpDir string, err error) {
			err = actor.zipper.Unzip(appDir, tmpDir)
			if err != nil {
				presentFiles = nil
				apiErr = err
				return
			}
			presentFiles, hasFileToUpload, apiErr = actor.copyUploadableFiles(tmpDir, uploadDir)
		})
	} else {
		presentFiles, hasFileToUpload, apiErr = actor.copyUploadableFiles(appDir, uploadDir)
	}
	return presentFiles, hasFileToUpload, apiErr
}

func (actor PushActorImpl) UploadApp(appGuid string, zipFile *os.File, presentFiles []resources.AppFileResource) error {
	return actor.appBitsRepo.UploadBits(appGuid, zipFile, presentFiles)
}

func (actor PushActorImpl) copyUploadableFiles(appDir string, uploadDir string) (presentFiles []resources.AppFileResource, hasFileToUpload bool, err error) {
	// Find which files need to be uploaded
	allAppFiles, err := actor.appfiles.AppFilesInDir(appDir)
	if err != nil {
		return
	}

	appFilesToUpload, presentFiles, apiErr := actor.getFilesToUpload(allAppFiles)
	if apiErr != nil {
		err = errors.New(apiErr.Error())
		return
	}
	hasFileToUpload = len(appFilesToUpload) > 0

	// Copy files into a temporary directory and return it
	err = actor.appfiles.CopyFiles(appFilesToUpload, appDir, uploadDir)
	if err != nil {
		return
	}

	// copy cfignore if present
	fileutils.CopyPathToPath(filepath.Join(appDir, ".cfignore"), filepath.Join(uploadDir, ".cfignore")) //error handling?

	return
}

func (actor PushActorImpl) getFilesToUpload(allAppFiles []models.AppFileFields) (appFilesToUpload []models.AppFileFields, presentFiles []resources.AppFileResource, apiErr error) {
	appFilesRequest := []resources.AppFileResource{}
	for _, file := range allAppFiles {
		appFilesRequest = append(appFilesRequest, resources.AppFileResource{
			Path: file.Path,
			Sha1: file.Sha1,
			Size: file.Size,
		})
	}

	presentFiles, apiErr = actor.appBitsRepo.GetApplicationFiles(appFilesRequest)
	if apiErr != nil {
		return nil, nil, apiErr
	}

	appFilesToUpload = make([]models.AppFileFields, len(allAppFiles))
	copy(appFilesToUpload, allAppFiles)
	for _, file := range presentFiles {
		appFile := models.AppFileFields{
			Path: file.Path,
			Sha1: file.Sha1,
			Size: file.Size,
		}
		appFilesToUpload = actor.deleteAppFile(appFilesToUpload, appFile)
	}

	return
}

func (actor PushActorImpl) deleteAppFile(appFiles []models.AppFileFields, targetFile models.AppFileFields) []models.AppFileFields {
	for i, file := range appFiles {
		if file.Path == targetFile.Path {
			appFiles[i] = appFiles[len(appFiles)-1]
			return appFiles[:len(appFiles)-1]
		}
	}
	return appFiles
}
<commit_msg>Do not shadow named return value<commit_after>package actors

import (
	"fmt"
	"os"
	"path/filepath"

	"github.com/cloudfoundry/cli/cf/api/application_bits"
	"github.com/cloudfoundry/cli/cf/api/resources"
	"github.com/cloudfoundry/cli/cf/app_files"
	"github.com/cloudfoundry/cli/cf/errors"
	"github.com/cloudfoundry/cli/cf/models"
	"github.com/cloudfoundry/gofileutils/fileutils"
)

//go:generate counterfeiter -o fakes/fake_push_actor.go . PushActor
type PushActor interface {
	UploadApp(appGuid string, zipFile *os.File, presentFiles []resources.AppFileResource) error
	PopulateFileMode(appDir string, presentFiles []resources.AppFileResource) ([]resources.AppFileResource, error)
	GatherFiles(appDir string, uploadDir string) ([]resources.AppFileResource, bool, error)
}

type PushActorImpl struct {
	appBitsRepo application_bits.ApplicationBitsRepository
	appfiles    app_files.AppFiles
	zipper      app_files.Zipper
}

func NewPushActor(appBitsRepo application_bits.ApplicationBitsRepository, zipper app_files.Zipper, appfiles app_files.AppFiles) PushActor {
	return PushActorImpl{
		appBitsRepo: appBitsRepo,
		appfiles:    appfiles,
		zipper:      zipper,
	}
}

func (actor PushActorImpl) PopulateFileMode(appDir string, presentFiles []resources.AppFileResource) ([]resources.AppFileResource, error) {
	for i, _ := range presentFiles {
		fileInfo, err := os.Lstat(filepath.Join(appDir, presentFiles[i].Path))
		if err != nil {
			return presentFiles, err
		}
		presentFiles[i].Mode = fmt.Sprintf("%#o", fileInfo.Mode())
	}

	return presentFiles, nil
}

func (actor PushActorImpl) GatherFiles(appDir string, uploadDir string) (presentFiles []resources.AppFileResource, hasFileToUpload bool, apiErr error) {
	if actor.zipper.IsZipFile(appDir) {
		fileutils.TempDir("unzipped-app", func(tmpDir string, err error) {
			err = actor.zipper.Unzip(appDir, tmpDir)
			if err != nil {
				presentFiles = nil
				apiErr = err
				return
			}
			presentFiles, hasFileToUpload, apiErr = actor.copyUploadableFiles(tmpDir, uploadDir)
		})
	} else {
		presentFiles, hasFileToUpload, apiErr = actor.copyUploadableFiles(appDir, uploadDir)
	}
	return presentFiles, hasFileToUpload, apiErr
}

func (actor PushActorImpl) UploadApp(appGuid string, zipFile *os.File, presentFiles []resources.AppFileResource) error {
	return actor.appBitsRepo.UploadBits(appGuid, zipFile, presentFiles)
}

func (actor PushActorImpl) copyUploadableFiles(appDir string, uploadDir string) (presentFiles []resources.AppFileResource, hasFileToUpload bool, err error) {
	// Find which files need to be uploaded
	var allAppFiles []models.AppFileFields
	allAppFiles, err = actor.appfiles.AppFilesInDir(appDir)
	if err != nil {
		return
	}

	appFilesToUpload, presentFiles, apiErr := actor.getFilesToUpload(allAppFiles)
	if apiErr != nil {
		err = errors.New(apiErr.Error())
		return
	}
	hasFileToUpload = len(appFilesToUpload) > 0

	// Copy files into a temporary directory and return it
	err = actor.appfiles.CopyFiles(appFilesToUpload, appDir, uploadDir)
	if err != nil {
		return
	}

	// copy cfignore if present
	fileutils.CopyPathToPath(filepath.Join(appDir, ".cfignore"), filepath.Join(uploadDir, ".cfignore")) //error handling?

	return
}

func (actor PushActorImpl) getFilesToUpload(allAppFiles []models.AppFileFields) (appFilesToUpload []models.AppFileFields, presentFiles []resources.AppFileResource, apiErr error) {
	appFilesRequest := []resources.AppFileResource{}
	for _, file := range allAppFiles {
		appFilesRequest = append(appFilesRequest, resources.AppFileResource{
			Path: file.Path,
			Sha1: file.Sha1,
			Size: file.Size,
		})
	}

	presentFiles, apiErr = actor.appBitsRepo.GetApplicationFiles(appFilesRequest)
	if apiErr != nil {
		return nil, nil, apiErr
	}

	appFilesToUpload = make([]models.AppFileFields, len(allAppFiles))
	copy(appFilesToUpload, allAppFiles)
	for _, file := range presentFiles {
		appFile := models.AppFileFields{
			Path: file.Path,
			Sha1: file.Sha1,
			Size: file.Size,
		}
		appFilesToUpload = actor.deleteAppFile(appFilesToUpload, appFile)
	}

	return
}

func (actor PushActorImpl) deleteAppFile(appFiles []models.AppFileFields, targetFile models.AppFileFields) []models.AppFileFields {
	for i, file := range appFiles {
		if file.Path == targetFile.Path {
			appFiles[i] = appFiles[len(appFiles)-1]
			return appFiles[:len(appFiles)-1]
		}
	}
	return appFiles
}
<|endoftext|>


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

package unicode

import (
	"bytes"

	"github.com/blevesearch/segment"

	"github.com/blevesearch/bleve/analysis"
	"github.com/blevesearch/bleve/registry"
)

const Name = "unicode"

type UnicodeTokenizer struct {
}

func NewUnicodeTokenizer() *UnicodeTokenizer {
	return &UnicodeTokenizer{}
}

func (rt *UnicodeTokenizer) Tokenize(input []byte) analysis.TokenStream {

	rv := make(analysis.TokenStream, 0)

	segmenter := segment.NewWordSegmenter(bytes.NewReader(input))
	start := 0
	pos := 1
	for segmenter.Segment() {
		segmentBytes := segmenter.Bytes()
		end := start + len(segmentBytes)
		if segmenter.Type() != segment.None {
			token := analysis.Token{
				Term:     segmentBytes,
				Start:    start,
				End:      end,
				Position: pos,
				Type:     convertType(segmenter.Type()),
			}
			rv = append(rv, &token)
			pos++
		}
		start = end

	}
	return rv
}

func UnicodeTokenizerConstructor(config map[string]interface{}, cache *registry.Cache) (analysis.Tokenizer, error) {
	return NewUnicodeTokenizer(), nil
}

func init() {
	registry.RegisterTokenizer(Name, UnicodeTokenizerConstructor)
}

func convertType(segmentWordType int) analysis.TokenType {
	switch segmentWordType {
	case segment.Ideo:
		return analysis.Ideographic
	case segment.Kana:
		return analysis.Ideographic
	case segment.Number:
		return analysis.Numeric
	}
	return analysis.AlphaNumeric
}
<commit_msg>change unicode tokenizer to use direct segmenter api<commit_after>//  Copyright (c) 2014 Couchbase, Inc.
//  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
//  except in compliance with the License. You may obtain a copy of the License at
//    http://www.apache.org/licenses/LICENSE-2.0
//  Unless required by applicable law or agreed to in writing, software distributed under the
//  License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
//  either express or implied. See the License for the specific language governing permissions
//  and limitations under the License.

package unicode

import (
	"github.com/blevesearch/segment"

	"github.com/blevesearch/bleve/analysis"
	"github.com/blevesearch/bleve/registry"
)

const Name = "unicode"

type UnicodeTokenizer struct {
}

func NewUnicodeTokenizer() *UnicodeTokenizer {
	return &UnicodeTokenizer{}
}

func (rt *UnicodeTokenizer) Tokenize(input []byte) analysis.TokenStream {

	rv := make(analysis.TokenStream, 0)

	segmenter := segment.NewWordSegmenterDirect(input)
	start := 0
	pos := 1
	for segmenter.Segment() {
		segmentBytes := segmenter.Bytes()
		end := start + len(segmentBytes)
		if segmenter.Type() != segment.None {
			token := analysis.Token{
				Term:     segmentBytes,
				Start:    start,
				End:      end,
				Position: pos,
				Type:     convertType(segmenter.Type()),
			}
			rv = append(rv, &token)
			pos++
		}
		start = end

	}
	return rv
}

func UnicodeTokenizerConstructor(config map[string]interface{}, cache *registry.Cache) (analysis.Tokenizer, error) {
	return NewUnicodeTokenizer(), nil
}

func init() {
	registry.RegisterTokenizer(Name, UnicodeTokenizerConstructor)
}

func convertType(segmentWordType int) analysis.TokenType {
	switch segmentWordType {
	case segment.Ideo:
		return analysis.Ideographic
	case segment.Kana:
		return analysis.Ideographic
	case segment.Number:
		return analysis.Numeric
	}
	return analysis.AlphaNumeric
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"os/exec"
)

//RunCommand executes a command against the host shell
func RunCommand(command string) (string, error) {
	cmd := exec.Command(command)
	var out bytes.Buffer
	cmd.Stdout = &out
	var errOut bytes.Buffer
	cmd.Stderr = &errOut
	err := cmd.Run()
	if err != nil {
		return errOut.String(), err
	}
	return out.String(), nil
}
<commit_msg>modified os command of sctl-minion to work :)<commit_after>package main

import (
	"bytes"
	"os/exec"
	"strings"
)

//RunCommand executes a command against the host shell
func RunCommand(command string) (string, error) {
	parts := strings.Fields(command)
	command = parts[0]
	args := parts[1:len(parts)]
	cmd := exec.Command(command, args...)
	var out bytes.Buffer
	cmd.Stdout = &out
	var errOut bytes.Buffer
	cmd.Stderr = &errOut
	err := cmd.Run()
	if err != nil {
		return errOut.String(), err
	}
	return out.String(), nil
}
<|endoftext|>


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

package cassandra

import (
	"sort"
	"testing"

	"github.com/square/metrics/api"
	"github.com/square/metrics/testing_support/assert"
)

var cassandraClean = true

func newCassandraAPI(t *testing.T) (*CassandraMetricMetadataAPI, api.MetricMetadataAPIContext) {
	if !cassandraClean {
		t.Fatalf("Attempted to create new database without cleaning up the old one.")
	}
	cassandraClean = false
	cassandra, err := NewCassandraMetricMetadataAPI(CassandraMetricMetadataConfig{
		Hosts:    []string{"localhost"},
		Keyspace: "metrics_indexer_test",
	})
	if err != nil {
		t.Fatalf("Cannot instantiate Cassandra API: %s", err.Error())
	}
	return cassandra.(*CassandraMetricMetadataAPI), api.MetricMetadataAPIContext{}
}

func cleanAPI(t *testing.T, c *CassandraMetricMetadataAPI) {
	cleanDatabase(t, &c.db)
	cassandraClean = true
}

func Test_MetricName_GetTagSet_API(t *testing.T) {
	a := assert.New(t)
	cassandra, context := newCassandraAPI(t)
	defer cleanAPI(t, cassandra)

	if _, err := cassandra.GetAllTags("sample", context); err == nil {
		t.Errorf("Cassandra API should error on fetching nonexistent metric")
	}

	metricNamesTests := []struct {
		addTest      bool
		metricName   string
		tagString    string
		expectedTags map[string][]string // { metricName: [ tags ] }
	}{
		{true, "sample", "foo=bar1", map[string][]string{
			"sample": []string{"foo=bar1"},
		}},
		{true, "sample", "foo=bar2", map[string][]string{
			"sample": []string{"foo=bar1", "foo=bar2"},
		}},
		{true, "sample2", "foo=bar2", map[string][]string{
			"sample":  []string{"foo=bar1", "foo=bar2"},
			"sample2": []string{"foo=bar2"},
		}},
		{false, "sample2", "foo=bar2", map[string][]string{
			"sample": []string{"foo=bar1", "foo=bar2"},
		}},
		{false, "sample", "foo=bar1", map[string][]string{
			"sample": []string{"foo=bar2"},
		}},
	}

	for _, c := range metricNamesTests {
		if c.addTest {
			a.CheckError(cassandra.AddMetric(api.TaggedMetric{
				api.MetricKey(c.metricName),
				api.ParseTagSet(c.tagString),
			}, context))
		} else {
			a.CheckError(cassandra.RemoveMetric(api.TaggedMetric{

				api.MetricKey(c.metricName),
				api.ParseTagSet(c.tagString),
			}, context))
		}

		for k, v := range c.expectedTags {
			if tags, err := cassandra.GetAllTags(api.MetricKey(k), context); err != nil {
				t.Errorf("Error fetching tags")
			} else {
				stringTags := make([]string, len(tags))
				for i, tag := range tags {
					stringTags[i] = tag.Serialize()
				}

				a.EqInt(len(stringTags), len(v))
				sort.Sort(sort.StringSlice(stringTags))
				sort.Sort(sort.StringSlice(v))
				a.Eq(stringTags, v)
			}
		}
	}
}

func Test_GetAllMetrics_API(t *testing.T) {
	a := assert.New(t)
	cassandra, context := newCassandraAPI(t)
	defer cleanAPI(t, cassandra)
	a.CheckError(cassandra.AddMetric(api.TaggedMetric{
		"metric.a",
		api.ParseTagSet("foo=a"),
	}, context))
	a.CheckError(cassandra.AddMetric(api.TaggedMetric{
		"metric.a",
		api.ParseTagSet("foo=b"),
	}, context))
	a.CheckError(cassandra.AddMetrics([]api.TaggedMetric{
		{
			"metric.c",
			api.TagSet{
				"bar": "cat",
			},
		},
		{
			"metric.d",
			api.TagSet{
				"bar": "dog",
			},
		},
		{
			"metric.e",
			api.TagSet{
				"bar": "cat",
			},
		},
	}, context))
	keys, err := cassandra.GetAllMetrics(context)
	a.CheckError(err)
	sort.Sort(api.MetricKeys(keys))
	a.Eq(keys, []api.MetricKey{"metric.a", "metric.c", "metric.d", "metric.e"})
	a.CheckError(cassandra.AddMetric(api.TaggedMetric{
		"metric.b",
		api.ParseTagSet("foo=c"),
	}, context))
	a.CheckError(cassandra.AddMetric(api.TaggedMetric{
		"metric.b",
		api.ParseTagSet("foo=c"),
	}, context))
	keys, err = cassandra.GetAllMetrics(context)
	a.CheckError(err)
	sort.Sort(api.MetricKeys(keys))
	a.Eq(keys, []api.MetricKey{"metric.a", "metric.b", "metric.c", "metric.d", "metric.e"})
}

func Test_TagIndex_API(t *testing.T) {
	a := assert.New(t)
	cassandra, context := newCassandraAPI(t)
	defer cleanAPI(t, cassandra)

	if rows, err := cassandra.GetMetricsForTag("environment", "production", context); err != nil {
		a.CheckError(err)
	} else {
		a.EqInt(len(rows), 0)
	}
	a.CheckError(cassandra.AddMetric(api.TaggedMetric{
		"a.b.c",
		api.TagSet{
			"environment": "production",
		},
	}, context))
	a.CheckError(cassandra.AddMetric(api.TaggedMetric{
		"d.e.f",
		api.TagSet{
			"environment": "production",
		},
	}, context))

	if rows, err := cassandra.GetMetricsForTag("environment", "production", context); err != nil {
		a.CheckError(err)
	} else {
		a.EqInt(len(rows), 2)
	}

	a.CheckError(cassandra.RemoveMetric(api.TaggedMetric{
		"a.b.c",
		api.TagSet{
			"environment": "production",
		},
	}, context))
	if rows, err := cassandra.GetMetricsForTag("environment", "production", context); err != nil {
		a.CheckError(err)
	} else {
		a.EqInt(len(rows), 1)
		a.EqString(string(rows[0]), "d.e.f")
	}
}
<commit_msg>truncate test cassandra API<commit_after>// Copyright 2015 Square Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cassandra

import (
	"fmt"
	"sort"
	"testing"

	"github.com/square/metrics/api"
	"github.com/square/metrics/testing_support/assert"
)

var cassandraClean = true

func newCassandraAPI(t *testing.T) (*CassandraMetricMetadataAPI, api.MetricMetadataAPIContext) {
	if !cassandraClean {
		t.Fatalf("Attempted to create new database without cleaning up the old one.")
	}
	cassandraClean = false
	cassandraInterface, err := NewCassandraMetricMetadataAPI(CassandraMetricMetadataConfig{
		Hosts:    []string{"localhost"},
		Keyspace: "metrics_indexer_test",
	})
	if err != nil {
		t.Fatalf("Cannot instantiate Cassandra API: %s", err.Error())
	}
	cassandra := cassandraInterface.(*CassandraMetricMetadataAPI)

	tables := []string{"metric_names", "tag_index", "metric_name_set"}
	for _, table := range tables {
		// Truncate the tables
		if err := cassandra.db.session.Query(fmt.Sprintf("TRUNCATE %s", table)).Exec(); err != nil {
			t.Fatalf("Cannot truncate %s: %s", table, err.Error())
		}
	}
	return cassandra, api.MetricMetadataAPIContext{}
}

func cleanAPI(t *testing.T, c *CassandraMetricMetadataAPI) {
	cleanDatabase(t, &c.db)
	cassandraClean = true
}

func Test_MetricName_GetTagSet_API(t *testing.T) {
	a := assert.New(t)
	cassandra, context := newCassandraAPI(t)
	defer cleanAPI(t, cassandra)

	if _, err := cassandra.GetAllTags("sample", context); err == nil {
		t.Errorf("Cassandra API should error on fetching nonexistent metric")
	}

	metricNamesTests := []struct {
		addTest      bool
		metricName   string
		tagString    string
		expectedTags map[string][]string // { metricName: [ tags ] }
	}{
		{true, "sample", "foo=bar1", map[string][]string{
			"sample": []string{"foo=bar1"},
		}},
		{true, "sample", "foo=bar2", map[string][]string{
			"sample": []string{"foo=bar1", "foo=bar2"},
		}},
		{true, "sample2", "foo=bar2", map[string][]string{
			"sample":  []string{"foo=bar1", "foo=bar2"},
			"sample2": []string{"foo=bar2"},
		}},
		{false, "sample2", "foo=bar2", map[string][]string{
			"sample": []string{"foo=bar1", "foo=bar2"},
		}},
		{false, "sample", "foo=bar1", map[string][]string{
			"sample": []string{"foo=bar2"},
		}},
	}

	for _, c := range metricNamesTests {
		if c.addTest {
			a.CheckError(cassandra.AddMetric(api.TaggedMetric{
				api.MetricKey(c.metricName),
				api.ParseTagSet(c.tagString),
			}, context))
		} else {
			a.CheckError(cassandra.RemoveMetric(api.TaggedMetric{

				api.MetricKey(c.metricName),
				api.ParseTagSet(c.tagString),
			}, context))
		}

		for k, v := range c.expectedTags {
			if tags, err := cassandra.GetAllTags(api.MetricKey(k), context); err != nil {
				t.Errorf("Error fetching tags")
			} else {
				stringTags := make([]string, len(tags))
				for i, tag := range tags {
					stringTags[i] = tag.Serialize()
				}

				a.EqInt(len(stringTags), len(v))
				sort.Sort(sort.StringSlice(stringTags))
				sort.Sort(sort.StringSlice(v))
				a.Eq(stringTags, v)
			}
		}
	}
}

func Test_GetAllMetrics_API(t *testing.T) {
	a := assert.New(t)
	cassandra, context := newCassandraAPI(t)
	defer cleanAPI(t, cassandra)
	a.CheckError(cassandra.AddMetric(api.TaggedMetric{
		"metric.a",
		api.ParseTagSet("foo=a"),
	}, context))
	a.CheckError(cassandra.AddMetric(api.TaggedMetric{
		"metric.a",
		api.ParseTagSet("foo=b"),
	}, context))
	a.CheckError(cassandra.AddMetrics([]api.TaggedMetric{
		{
			"metric.c",
			api.TagSet{
				"bar": "cat",
			},
		},
		{
			"metric.d",
			api.TagSet{
				"bar": "dog",
			},
		},
		{
			"metric.e",
			api.TagSet{
				"bar": "cat",
			},
		},
	}, context))
	keys, err := cassandra.GetAllMetrics(context)
	a.CheckError(err)
	sort.Sort(api.MetricKeys(keys))
	a.Eq(keys, []api.MetricKey{"metric.a", "metric.c", "metric.d", "metric.e"})
	a.CheckError(cassandra.AddMetric(api.TaggedMetric{
		"metric.b",
		api.ParseTagSet("foo=c"),
	}, context))
	a.CheckError(cassandra.AddMetric(api.TaggedMetric{
		"metric.b",
		api.ParseTagSet("foo=c"),
	}, context))
	keys, err = cassandra.GetAllMetrics(context)
	a.CheckError(err)
	sort.Sort(api.MetricKeys(keys))
	a.Eq(keys, []api.MetricKey{"metric.a", "metric.b", "metric.c", "metric.d", "metric.e"})
}

func Test_TagIndex_API(t *testing.T) {
	a := assert.New(t)
	cassandra, context := newCassandraAPI(t)
	defer cleanAPI(t, cassandra)

	if rows, err := cassandra.GetMetricsForTag("environment", "production", context); err != nil {
		a.CheckError(err)
	} else {
		a.EqInt(len(rows), 0)
	}
	a.CheckError(cassandra.AddMetric(api.TaggedMetric{
		"a.b.c",
		api.TagSet{
			"environment": "production",
		},
	}, context))
	a.CheckError(cassandra.AddMetric(api.TaggedMetric{
		"d.e.f",
		api.TagSet{
			"environment": "production",
		},
	}, context))

	if rows, err := cassandra.GetMetricsForTag("environment", "production", context); err != nil {
		a.CheckError(err)
	} else {
		a.EqInt(len(rows), 2)
	}

	a.CheckError(cassandra.RemoveMetric(api.TaggedMetric{
		"a.b.c",
		api.TagSet{
			"environment": "production",
		},
	}, context))
	if rows, err := cassandra.GetMetricsForTag("environment", "production", context); err != nil {
		a.CheckError(err)
	} else {
		a.EqInt(len(rows), 1)
		a.EqString(string(rows[0]), "d.e.f")
	}
}
<|endoftext|>


<commit_before>package raven

import (
	"fmt"
	"net/http"
	"net/http/httptest"
	"net/url"
	"path"
	"testing"
)

func TestCaptureMessage(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(
		func(w http.ResponseWriter, req *http.Request) {
			fmt.Fprint(w, "hello")
		}))
	defer server.Close()

	publicKey := "abcd"
	secretKey := "efgh"
	project := "1"
	sentryPath := "/sentry/path"

	// Build the client
	u, _ := url.Parse(server.URL)
	u.User = url.UserPassword(publicKey, secretKey)
	u.Path = path.Join(sentryPath, project)
	client, err := NewClient(u.String())
	if err != nil {
		t.Fatalf("failed to make client: %s", err)
	}

	// Test the client is set up correctly
	if client.PublicKey != publicKey {
		t.Logf("bad public key: got %s, want %s", client.PublicKey, publicKey)
		t.Fail()
	}
	if client.SecretKey != secretKey {
		t.Logf("bad public key: got %s, want %s", client.PublicKey, publicKey)
		t.Fail()
	}
	if client.Project != project {
		t.Logf("bad project: got %s, want %s", client.Project, project)
		t.Fail()
	}
	if client.URL.Path != sentryPath {
		t.Logf("bad path: got %s, want %s", client.URL.Path, sentryPath)
		t.Fail()
	}

	_, err = client.CaptureMessage("test message")
	if err != nil {
		t.Logf("CaptureMessage failed: %s", err)
		t.Fail()
	}
}
<commit_msg>Added some simple tests for Capture()<commit_after>package raven

import (
	"fmt"
	"net/http"
	"net/http/httptest"
	"net/url"
	"path"
	"testing"
)

func BuildSentryDSN(baseUrl, publicKey, secretKey, project, sentryPath string) string {
	u, _ := url.Parse(baseUrl)
	u.User = url.UserPassword(publicKey, secretKey)
	u.Path = path.Join(sentryPath, project)
	return u.String()
}

func TestCaptureMessage(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(
		func(w http.ResponseWriter, req *http.Request) {
			fmt.Fprint(w, "hello")
		}))
	defer server.Close()

	publicKey := "abcd"
	secretKey := "efgh"
	project := "1"
	sentryPath := "/sentry/path"

	// Build the client
	client, err := NewClient(BuildSentryDSN(server.URL, publicKey, secretKey, project, sentryPath))
	if err != nil {
		t.Fatalf("failed to make client: %s", err)
	}

	// Test the client is set up correctly
	if client.PublicKey != publicKey {
		t.Logf("bad public key: got %s, want %s", client.PublicKey, publicKey)
		t.Fail()
	}
	if client.SecretKey != secretKey {
		t.Logf("bad public key: got %s, want %s", client.PublicKey, publicKey)
		t.Fail()
	}
	if client.Project != project {
		t.Logf("bad project: got %s, want %s", client.Project, project)
		t.Fail()
	}
	if client.URL.Path != sentryPath {
		t.Logf("bad path: got %s, want %s", client.URL.Path, sentryPath)
		t.Fail()
	}

	_, err = client.CaptureMessage("test message")
	if err != nil {
		t.Logf("CaptureMessage failed: %s", err)
		t.Fail()
	}
}

func TestCapture(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(
		func(w http.ResponseWriter, req *http.Request) {
			fmt.Fprint(w, "hello")
		}))
	defer server.Close()

	publicKey := "abcd"
	secretKey := "efgh"
	project := "1"
	sentryPath := "/sentry/path"

	// Build the client
	client, err := NewClient(BuildSentryDSN(server.URL, publicKey, secretKey, project, sentryPath))
	if err != nil {
		t.Fatalf("failed to make client: %s", err)
	}

	// Send the message
	testEvent := func(ev *Event) {
		err := client.Capture(ev)
		if err != nil {
			t.Fatal(err)
		}
		// All fields must be set
		if ev.EventId == "" {
			t.Error("EventId must not be empty.")
		}
		if ev.Project == "" {
			t.Error("Project must not be empty.")
		}
		if ev.Timestamp == "" {
			t.Error("Timestamp must not be empty.")
		}
		if ev.Level == "" {
			t.Error("Level must not be empty.")
		}
		if ev.Logger == "" {
			t.Error("Logger must not be empty.")
		}
		if fmt.Sprintf("test.%s.%s", ev.Logger, ev.Level) != ev.Message {
			t.Errorf("Expected message to match error and logger %s == test.%s.%s", ev.Message, ev.Logger, ev.Level)
		}
	}

	testEvent(&Event{Message: "test.root.error"})
	testEvent(&Event{Message: "test.root.warn", Level: "warn"})
	testEvent(&Event{Message: "test.auth.error", Logger: "auth"})
	testEvent(&Event{Message: "test.root.error", Timestamp: "2013-10-17T11:25:59"})
	testEvent(&Event{Message: "test.root.error", EventId: "1234-34567-8912-124123"})
	testEvent(&Event{Message: "test.auth.info", Level: "info", Logger: "auth"})
}
<|endoftext|>