<commit_before>// Copyright 2017 PingCAP, 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,
// See the License for the specific language governing permissions and
// limitations under the License.

package parser

import (
	"testing"
)

func BenchmarkSysbenchSelect(b *testing.B) {
	parser := New()
	sql := "SELECT pad FROM sbtest1 WHERE id=1;"
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		_, err := parser.Parse(sql, "", "")
		if err != nil {
			b.Fatal(err)
		}
	}
	b.ReportAllocs()
}

func BenchmarkParse(b *testing.B) {
	var table = []string{
		"insert into t values (1), (2), (3)",
		"insert into t values (4), (5), (6), (7)",
		"select c from t where c > 2",
	}
	parser := New()
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		for _, v := range table {
			_, err := parser.Parse(v, "", "")
			if err != nil {
				b.Failed()
			}
		}
	}
	b.ReportAllocs()
}
<commit_msg>parser: add complex query bench (#7815)<commit_after>// Copyright 2017 PingCAP, 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,
// See the License for the specific language governing permissions and
// limitations under the License.

package parser

import (
	"testing"
)

func BenchmarkSysbenchSelect(b *testing.B) {
	parser := New()
	sql := "SELECT pad FROM sbtest1 WHERE id=1;"
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		_, err := parser.Parse(sql, "", "")
		if err != nil {
			b.Fatal(err)
		}
	}
	b.ReportAllocs()
}

func BenchmarkParseComplex(b *testing.B) {
	var table = []string{
		`SELECT DISTINCT ca.l9_convergence_code AS atb2, cu.cust_sub_type AS account_type, cst.description AS account_type_desc, ss.prim_resource_val AS msisdn, ca.ban AS ban_key, To_char(mo.memo_date, 'YYYYMMDD') AS memo_date, cu.l9_identification AS thai_id, ss.subscriber_no AS subs_key, ss.dealer_code AS shop_code, cd.description AS shop_name, mot.short_desc, Regexp_substr(mo.attr1value, '[^ ;]+', 1, 3) staff_id, mo.operator_id AS user_id, mo.memo_system_text, co2.soc_name AS first_socname, co3.soc_name AS previous_socname, co.soc_name AS current_socname, Regexp_substr(mo.attr1value, '[^ ; ]+', 1, 1) NAME, co.soc_description AS current_pp_desc, co3.soc_description AS prev_pp_desc, co.soc_cd AS soc_cd, ( SELECT Sum(br.amount) FROM bl1_rc_rates BR, customer CU, subscriber SS WHERE br.service_receiver_id = ss.subscriber_no AND br.receiver_customer = ss.customer_id AND br.effective_date <= br.expiration_date AND (( ss. sub_status <> 'C' AND ss. sub_status <> 'T' AND br.expiration_date IS NULL) OR ( ss. sub_status = 'C' AND br.expiration_date LIKE ss.effective_date)) AND br.pp_ind = 'Y' AND br.cycle_code = cu.bill_cycle) AS pp_rate, cu.bill_cycle AS cycle_code, To_char(Nvl(ss.l9_tmv_act_date, ss.init_act_date),'YYYYMMDD') AS activated_date, To_char(cd.effective_date, 'YYYYMMDD') AS shop_effective_date, cd.expiration_date AS shop_expired_date, ca.l9_company_code AS company_code FROM service_details S, product CO, csm_pay_channel CPC, account CA, subscriber SS, customer CU, customer_sub_type CST, csm_dealer CD, service_details S2, product CO2, service_details S3, product CO3, memo MO , memo_type MOT, logical_date LO, charge_details CHD WHERE ss.subscriber_no = chd.agreement_no AND cpc.pym_channel_no = chd.target_pcn AND chd.chg_split_type = 'DR' AND chd.expiration_date IS NULL AND s.soc = co.soc_cd AND co.soc_type = 'P' AND s.agreement_no = ss.subscriber_no AND ss.prim_resource_tp = 'C' AND cpc.payment_category = 'POST' AND ca.ban = cpc.ban AND ( ca.l9_company_code = 'RF' OR ca.l9_company_code = 'RM' OR ca.l9_company_code = 'TM') AND ss.customer_id = cu.customer_id AND cu.cust_sub_type = cst.cust_sub_type AND cu.customer_type = cst.customer_type AND ss.dealer_code = cd.dealer AND s2.effective_date= ( SELECT Max(sa1.effective_date) FROM service_details SA1, product o1 WHERE sa1.agreement_no = ss.subscriber_no AND co.soc_cd = sa1.soc AND co.soc_type = 'P' ) AND s2.agreement_no = s.agreement_no AND s2.soc = co2.soc_cd AND co2.soc_type = 'P' AND s2.effective_date = ( SELECT Min(sa1.effective_date) FROM service_details SA1, product o1 WHERE sa1.agreement_no = ss.subscriber_no AND co2.soc_cd = sa1.soc AND co.soc_type = 'P' ) AND s3.agreement_no = s.agreement_no AND s3.soc = co3.soc_cd AND co3.soc_type = 'P' AND s3.effective_date = ( SELECT Max(sa1.effective_date) FROM service_details SA1, a product o1 WHERE sa1.agreement_no = ss.subscriber_no AND sa1.effective_date < ( SELECT Max(sa1.effective_date) FROM service_details SA1, product o1 WHERE sa1.agreement_no = ss.subscriber_no AND co3.soc_cd = sa1.soc AND co3.soc_type = 'P' ) AND co3.soc_cd = sa1.soc AND o1.soc_type = 'P' ) AND mo.entity_id = ss.subscriber_no AND mo.entity_type_id = 6 AND mo.memo_type_id = mot.memo_type_id AND Trunc(mo.sys_creation_date) = ( SELECT Trunc(lo.logical_date - 1) FROM lo) trunc(lo.logical_date - 1) AND lo.expiration_date IS NULL AND lo.logical_date_type = 'B' AND lo.expiration_date IS NULL AND ( mot.short_desc = 'BCN' OR mot.short_desc = 'BCNM' )`}
	parser := New()
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		for _, v := range table {
			_, err := parser.Parse(v, "", "")
			if err != nil {
				b.Failed()
			}
		}
	}
	b.ReportAllocs()
}

func BenchmarkParseSimple(b *testing.B) {
	var table = []string{
		"insert into t values (1), (2), (3)",
		"insert into t values (4), (5), (6), (7)",
		"select c from t where c > 2",
	}
	parser := New()
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		for _, v := range table {
			_, err := parser.Parse(v, "", "")
			if err != nil {
				b.Failed()
			}
		}
	}
	b.ReportAllocs()
}
<|endoftext|>


<commit_before>/*
 * qm.go, part of gochem.
 *
 *
 * Copyright 2012 Raul Mera <rmera{at}chemDOThelsinkiDOTfi>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General
 * Public License along with this program.  If not, see
 * <http://www.gnu.org/licenses/>.
 *
 *
 * Gochem is developed at the laboratory for instruction in Swedish, Department of Chemistry,
 * University of Helsinki, Finland.
 *
 *
 */
/***Dedicated to the long life of the Ven. Khenpo Phuntzok Tenzin Rinpoche***/

package chem

import "os"
import "strings"
import "fmt"
import  "github.com/skelterjohn/go.matrix"
import "os/exec"

type MopacRunner struct{
	defmethod string
	command string
	inputname string
	}

func MakeMopacRunner() *MopacRunner{
	run:=new(MopacRunner)
	run.SetDefaults()
	return run
	}

//MopacRunner methods

func (O *MopacRunner)SetnCPU(cpu int){
	//It does nothing! :-D
	}

func (O *MopacRunner)SetName(name string){
	O.inputname=name
	}

func (O *MopacRunner)SetCommand(name string){
	O.command=name
	}

func (O *MopacRunner)SetDefaults(){
	O.defmethod="PM6-DH2X"
	O.command=os.ExpandEnv("${MOPAC_LICENSE}/MOPAC2009.exe")
	}

//BuildInput builds an input for ORCA based int the data in atoms, coords and C.
//returns only error.
func (O *MopacRunner) BuildInput(atoms Ref, coords *matrix.DenseMatrix, Q *QMCalc) error{
	if strings.Contains(Q.Others,"RI"){
		Q.Others=""
		}
	//Only error so far
	if atoms==nil || coords == nil {
		return fmt.Errorf("Missing charges or coordinates")
		}
	ValidMethods:=[]string{"PM3","PM6","PM7","AM1"}
	if IsIn(Q.Method[0:3],ValidMethods)==-1{ //not found
		fmt.Fprintf(os.Stderr,"no method assigned for MOPAC calculation, will used the default %s, \n",O.defmethod)
		Q.Method=O.defmethod
		}
	opt:="" //Empty string means optimize
	if Q.Optimize==false{
		opt="1SCF"
		}
	//If this flag is set we'll look for a suitable MO file.
	//If not found, we'll just use the default ORCA guess
	hfuhf:="RHF"
	if atoms.Unpaired()!=0{
		hfuhf="UHF"
		}
	cosmo:=""
	if Q.Dielectric>0{
		cosmo=fmt.Sprintf("EPS=%2.1f RSOLV=1.3",Q.Dielectric)
		}
	multi:=mopacMultiplicity[atoms.Unpaired()+1]
	charge:=fmt.Sprintf("CHARGE=%d",atoms.Charge())
	MainOptions:=[]string{hfuhf,Q.Method,opt,cosmo,charge,multi,Q.Others,"BONDS AUX\n"}
	mainline:=strings.Join(MainOptions," ")
	//Now lets write the thing
	if O.inputname==""{
		O.inputname="input"
		}
	file,err:=os.Create(fmt.Sprintf("%s.mop",O.inputname))
	if err!=nil{
		return err
		}
	defer file.Close()
	if _,err=fmt.Fprint(file,"* ===============================\n* Input file for Mopac\n* ===============================\n");err!=nil{
		return err //After this check I just assume the file is ok and dont check again.
		}
	fmt.Fprint(file,mainline)
	fmt.Fprint(file,"\n")
	fmt.Fprint(file,"Mopac file generated by gochem :-)\n")
	//now the coordinates
	for i:=0;i<atoms.Len();i++{
		tag:=1
		if isInInt(Q.CConstraints,i)==true{
			tag=0
			}
	//	fmt.Println(atoms.Atom(i).Symbol)
		fmt.Fprintf(file,"%-2s  %8.5f %d %8.5f %d %8.5f %d\n",atoms.Atom(i).Symbol, coords.Get(i,0), tag, coords.Get(i,1), tag, coords.Get(i,2),tag)
		}
	fmt.Fprintf(file,"\n")
	return nil
	}

//Run runs the command given by the string O.command
//it waits or not for the result depending of
func (O *MopacRunner) Run(wait bool) (err error){
	command:=exec.Command("nohup",O.command,fmt.Sprintf("%s.inp",O.inputname))
	if wait==true{
		err=command.Run()
		}else{
		err=command.Start()
		}
	return err
	}

var mopacMultiplicity = map[int] string {
      1: "Singlet",
	  2: "Doublet",
      3: "Triplet",
	  4: "Quartet",
	  5: "Quintet",
	  6: "Sextet",
	  7: "Heptet",
	  8: "Octet",
	  9: "Nonet",
}

<commit_msg>starting the implementation of reading geometries and energies from mopac calculations.<commit_after>/*
 * qm.go, part of gochem.
 *
 *
 * Copyright 2012 Raul Mera <rmera{at}chemDOThelsinkiDOTfi>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General
 * Public License along with this program.  If not, see
 * <http://www.gnu.org/licenses/>.
 *
 *
 * Gochem is developed at the laboratory for instruction in Swedish, Department of Chemistry,
 * University of Helsinki, Finland.
 *
 *
 */
/***Dedicated to the long life of the Ven. Khenpo Phuntzok Tenzin Rinpoche***/

package chem

import "os"
import "strings"
import "fmt"
import  "github.com/skelterjohn/go.matrix"
import "os/exec"

type MopacRunner struct{
	defmethod string
	command string
	inputname string
	}

func MakeMopacRunner() *MopacRunner{
	run:=new(MopacRunner)
	run.SetDefaults()
	return run
	}

//MopacRunner methods

func (O *MopacRunner)SetnCPU(cpu int){
	//It does nothing! :-D
	}

func (O *MopacRunner)SetName(name string){
	O.inputname=name
	}

func (O *MopacRunner)SetCommand(name string){
	O.command=name
	}

func (O *MopacRunner)SetDefaults(){
	O.defmethod="PM6-DH2X"
	O.command=os.ExpandEnv("${MOPAC_LICENSE}/MOPAC2009.exe")
	}

//BuildInput builds an input for ORCA based int the data in atoms, coords and C.
//returns only error.
func (O *MopacRunner) BuildInput(atoms Ref, coords *matrix.DenseMatrix, Q *QMCalc) error{
	if strings.Contains(Q.Others,"RI"){
		Q.Others=""
		}
	//Only error so far
	if atoms==nil || coords == nil {
		return fmt.Errorf("Missing charges or coordinates")
		}
	ValidMethods:=[]string{"PM3","PM6","PM7","AM1"}
	if IsIn(Q.Method[0:3],ValidMethods)==-1{ //not found
		fmt.Fprintf(os.Stderr,"no method assigned for MOPAC calculation, will used the default %s, \n",O.defmethod)
		Q.Method=O.defmethod
		}
	opt:="" //Empty string means optimize
	if Q.Optimize==false{
		opt="1SCF"
		}
	//If this flag is set we'll look for a suitable MO file.
	//If not found, we'll just use the default ORCA guess
	hfuhf:="RHF"
	if atoms.Unpaired()!=0{
		hfuhf="UHF"
		}
	cosmo:=""
	if Q.Dielectric>0{
		cosmo=fmt.Sprintf("EPS=%2.1f RSOLV=1.3",Q.Dielectric)
		}
	multi:=mopacMultiplicity[atoms.Unpaired()+1]
	charge:=fmt.Sprintf("CHARGE=%d",atoms.Charge())
	MainOptions:=[]string{hfuhf,Q.Method,opt,cosmo,charge,multi,Q.Others,"BONDS AUX\n"}
	mainline:=strings.Join(MainOptions," ")
	//Now lets write the thing
	if O.inputname==""{
		O.inputname="input"
		}
	file,err:=os.Create(fmt.Sprintf("%s.mop",O.inputname))
	if err!=nil{
		return err
		}
	defer file.Close()
	if _,err=fmt.Fprint(file,"* ===============================\n* Input file for Mopac\n* ===============================\n");err!=nil{
		return err //After this check I just assume the file is ok and dont check again.
		}
	fmt.Fprint(file,mainline)
	fmt.Fprint(file,"\n")
	fmt.Fprint(file,"Mopac file generated by gochem :-)\n")
	//now the coordinates
	for i:=0;i<atoms.Len();i++{
		tag:=1
		if isInInt(Q.CConstraints,i)==true{
			tag=0
			}
	//	fmt.Println(atoms.Atom(i).Symbol)
		fmt.Fprintf(file,"%-2s  %8.5f %d %8.5f %d %8.5f %d\n",atoms.Atom(i).Symbol, coords.Get(i,0), tag, coords.Get(i,1), tag, coords.Get(i,2),tag)
		}
	fmt.Fprintf(file,"\n")
	return nil
	}

//Run runs the command given by the string O.command
//it waits or not for the result depending of
func (O *MopacRunner) Run(wait bool) (err error){
	command:=exec.Command("nohup",O.command,fmt.Sprintf("%s.inp",O.inputname))
	if wait==true{
		err=command.Run()
		}else{
		err=command.Start()
		}
	return err
	}

var mopacMultiplicity = map[int] string {
      1: "Singlet",
	  2: "Doublet",
      3: "Triplet",
	  4: "Quartet",
	  5: "Quintet",
	  6: "Sextet",
	  7: "Heptet",
	  8: "Octet",
	  9: "Nonet",
}

func (O *MopacRunner) GetEnergy() (float64, error){
	file,err:=os.Create(fmt.Sprintf("%s.out",O.inputname))
	if err!=nil{
		return err
		}
	defer file.Close()
	file=
	}
<|endoftext|>


<commit_before>package parser

import (
	"fmt"
	"testing"
)

var items = map[itemType]string{
	itemVersion:  "itemVersion",
	itemOperator: "itemOperator",
	itemSet:      "itemSet",
	itemRange:    "itemRange",
	itemAdvanced: "itemAdvanced",
	itemError:    "itemError",
	itemEOF:      "itemEOF",
}

var constraints = []string{
	"1.0 || >=2.5.0 || 5.0.0 - 7.2.3",
	"~1.2.3",
	"^4.5.2-alpha.1",
	"=2.3.2",
	"<=1.2.3",
	"5.3.5||4.3.5",
	"5.3.5 ||4.3.5",
	"5.3.5|| 4.3.5",
	"5.3.5 4.3.5",
	">=1.2.3",
	">= 1.2.3",
	"M",
}

// Just for debugging, not a real test. REMOVE THIS.
func TestLexer(t *testing.T) {
	for _, c := range constraints {
		_, ch := lex(c)
		for {
			s, ok := <-ch
			if ok != false {
				fmt.Printf("%v: '%v' \n", items[s.typ], s)
			} else {
				break
			}
		}
	}
}

// Poor implementation, just for initial testing.
func BenchmarkLexerComplex(b *testing.B) {
	const VERSION = "1.0.0 || >=2.5.0 || 5.0.0 - 7.2.3 || ~4.3.1 ^2.1.1"

	b.ResetTimer()
	for n := 0; n < b.N; n++ {
		_, ch := lex(VERSION)
		for {
			_, ok := <-ch
			if ok == false {
				//fmt.Printf("%v: '%v' \n", items[s.typ], s)
				//} else {
				break
			}
		}
	}
}

// Poor implementation, just for initial testing.
func BenchmarkLexerSimple(b *testing.B) {
	const VERSION = "1.0.0"

	b.ResetTimer()
	for n := 0; n < b.N; n++ {
		_, ch := lex(VERSION)
		for {
			_, ok := <-ch
			if ok == false {
				//fmt.Printf("%v: '%v' \n", items[s.typ], s)
				//} else {
				break
			}
		}
	}
}
<commit_msg>Added more debugging methods.<commit_after>package parser

import (
	"fmt"
	"testing"
)

var items = map[itemType]string{
	itemVersion:  "itemVersion",
	itemOperator: "itemOperator",
	itemSet:      "itemSet",
	itemRange:    "itemRange",
	itemAdvanced: "itemAdvanced",
	itemError:    "itemError",
	itemEOF:      "itemEOF",
}

var constraints = []string{
	"1.0.0 || >=2.5.0 || 5.0.0 - 7.2.3",
	"~1.2.3",
	"^4.5.2-alpha.1",
	"=2.3.2",
	"<=1.2.3",
	"5.3.5||4.3.5",
	"5.3.5 ||4.3.5",
	"5.3.5|| 4.3.5",
	"5.3.5 4.3.5",
	">=1.2.3",

	">= 1.2.3",
	"1.2.3 >=",
	"5.3.5 |1| 4.3.5",
	"5. 4.4",
	"<1<1",
	"<1||",
	"M",
	"1.0",
	"1.x",
	"1.*.2",
	"*.1.2",
}

// Just for debugging, not a real test. REMOVE THIS.
func TestLexer(t *testing.T) {
	for _, c := range constraints {
		_, ch := lex(c)
		for {
			s, ok := <-ch
			if ok != false {
				fmt.Printf("%v: '%v' \n", items[s.typ], s)
				if s.typ == itemEOF || s.typ == itemError {
					fmt.Println("")
				}
			} else {
				break
			}
		}
	}
}

// Poor implementation, just for initial testing.
func BenchmarkLexerComplex(b *testing.B) {
	const VERSION = "1.0.0 || >=2.5.0 || 5.0.0 - 7.2.3 || ~4.3.1 ^2.1.1"

	b.ResetTimer()
	for n := 0; n < b.N; n++ {
		_, ch := lex(VERSION)
		for {
			_, ok := <-ch
			if ok == false {
				//fmt.Printf("%v: '%v' \n", items[s.typ], s)
				//} else {
				break
			}
		}
	}
}

// Poor implementation, just for initial testing.
func BenchmarkLexerSimple(b *testing.B) {
	const VERSION = "1.0.0"

	b.ResetTimer()
	for n := 0; n < b.N; n++ {
		_, ch := lex(VERSION)
		for {
			_, ok := <-ch
			if ok == false {
				//fmt.Printf("%v: '%v' \n", items[s.typ], s)
				//} else {
				break
			}
		}
	}
}
<|endoftext|>


<commit_before>package parser

import "github.com/xlab/c/cc"

type TargetArchBits int

const (
	Arch32 TargetArchBits = 32
	Arch64 TargetArchBits = 64
)

var predefinedBase = `
#define __STDC_HOSTED__ 1
#define __STDC_VERSION__ 199901L
#define __STDC__ 1
#define __GNUC__ 4
#define __builtin_va_list void *
#define __asm__(x)
#define __asm(x)
#define __inline inline
#define __attribute__(x)
#define __POSIX_C_DEPRECATED(ver)
`

var predefines = map[TargetArchBits]string{
	Arch32: predefinedBase + `#define __i386__ 1`,
	Arch64: predefinedBase + `#define __x86_64__ 1`,
}

var models = map[TargetArchBits]*cc.Model{
	Arch32: model32,
	Arch64: model64,
}

var arches = map[string]TargetArchBits{
	"386":    Arch32,
	"arm":    Arch32,
	"armbe":  Arch32,
	"mips":   Arch32,
	"mipsle": Arch32,
	"sparc":  Arch32,
	//
	"amd64":       Arch64,
	"amd64p32":    Arch64,
	"arm64":       Arch64,
	"arm64be":     Arch64,
	"ppc64":       Arch64,
	"ppc64le":     Arch64,
	"mips64":      Arch64,
	"mips64le":    Arch64,
	"mips64p32":   Arch64,
	"mips64p32le": Arch64,
	"sparc64":     Arch64,
}

var model32 = &cc.Model{
	Items: map[cc.Kind]cc.ModelItem{
		cc.Ptr:               {4, 4, "__TODO_PTR"},
		cc.Void:              {0, 1, "__TODO_VOID"},
		cc.Char:              {1, 1, "int8"},
		cc.SChar:             {1, 1, "int8"},
		cc.UChar:             {1, 1, "byte"},
		cc.Short:             {2, 2, "int16"},
		cc.UShort:            {2, 2, "uint16"},
		cc.Int:               {4, 4, "int32"},
		cc.UInt:              {4, 4, "uint32"},
		cc.Long:              {4, 4, "int32"},
		cc.ULong:             {4, 4, "uint32"},
		cc.LongLong:          {8, 8, "int64"},
		cc.ULongLong:         {8, 8, "uint64"},
		cc.Float:             {4, 4, "float32"},
		cc.Double:            {8, 8, "float64"},
		cc.LongDouble:        {8, 8, "float64"},
		cc.Bool:              {1, 1, "bool"},
		cc.FloatComplex:      {8, 8, "complex64"},
		cc.DoubleComplex:     {16, 16, "complex128"},
		cc.LongDoubleComplex: {16, 16, "complex128"},
	},
}

var model64 = &cc.Model{
	Items: map[cc.Kind]cc.ModelItem{
		cc.Ptr:               {8, 8, "__TODO_PTR"},
		cc.Void:              {0, 1, "__TODO_VOID"},
		cc.Char:              {1, 1, "int8"},
		cc.SChar:             {1, 1, "int8"},
		cc.UChar:             {1, 1, "byte"},
		cc.Short:             {2, 2, "int16"},
		cc.UShort:            {2, 2, "uint16"},
		cc.Int:               {4, 4, "int32"},
		cc.UInt:              {4, 4, "uint32"},
		cc.Long:              {8, 8, "int64"},
		cc.ULong:             {8, 8, "uint64"},
		cc.LongLong:          {8, 8, "int64"},
		cc.ULongLong:         {8, 8, "uint64"},
		cc.Float:             {4, 4, "float32"},
		cc.Double:            {8, 8, "float64"},
		cc.LongDouble:        {8, 8, "float64"},
		cc.Bool:              {1, 1, "bool"},
		cc.FloatComplex:      {8, 8, "complex64"},
		cc.DoubleComplex:     {16, 16, "complex128"},
		cc.LongDoubleComplex: {16, 16, "complex128"},
	},
}
<commit_msg>Respect __signed built-in macro.<commit_after>package parser

import "github.com/xlab/c/cc"

type TargetArchBits int

const (
	Arch32 TargetArchBits = 32
	Arch64 TargetArchBits = 64
)

var predefinedBase = `
#define __STDC_HOSTED__ 1
#define __STDC_VERSION__ 199901L
#define __STDC__ 1
#define __GNUC__ 4
#define __builtin_va_list void *
#define __asm__(x)
#define __asm(x)
#define __inline inline
#define __signed signed
#define __attribute__(x)
#define __POSIX_C_DEPRECATED(ver)
`

var predefines = map[TargetArchBits]string{
	Arch32: predefinedBase + `#define __i386__ 1`,
	Arch64: predefinedBase + `#define __x86_64__ 1`,
}

var models = map[TargetArchBits]*cc.Model{
	Arch32: model32,
	Arch64: model64,
}

var arches = map[string]TargetArchBits{
	"386":    Arch32,
	"arm":    Arch32,
	"armbe":  Arch32,
	"mips":   Arch32,
	"mipsle": Arch32,
	"sparc":  Arch32,
	//
	"amd64":       Arch64,
	"amd64p32":    Arch64,
	"arm64":       Arch64,
	"arm64be":     Arch64,
	"ppc64":       Arch64,
	"ppc64le":     Arch64,
	"mips64":      Arch64,
	"mips64le":    Arch64,
	"mips64p32":   Arch64,
	"mips64p32le": Arch64,
	"sparc64":     Arch64,
}

var model32 = &cc.Model{
	Items: map[cc.Kind]cc.ModelItem{
		cc.Ptr:               {4, 4, "__TODO_PTR"},
		cc.Void:              {0, 1, "__TODO_VOID"},
		cc.Char:              {1, 1, "int8"},
		cc.SChar:             {1, 1, "int8"},
		cc.UChar:             {1, 1, "byte"},
		cc.Short:             {2, 2, "int16"},
		cc.UShort:            {2, 2, "uint16"},
		cc.Int:               {4, 4, "int32"},
		cc.UInt:              {4, 4, "uint32"},
		cc.Long:              {4, 4, "int32"},
		cc.ULong:             {4, 4, "uint32"},
		cc.LongLong:          {8, 8, "int64"},
		cc.ULongLong:         {8, 8, "uint64"},
		cc.Float:             {4, 4, "float32"},
		cc.Double:            {8, 8, "float64"},
		cc.LongDouble:        {8, 8, "float64"},
		cc.Bool:              {1, 1, "bool"},
		cc.FloatComplex:      {8, 8, "complex64"},
		cc.DoubleComplex:     {16, 16, "complex128"},
		cc.LongDoubleComplex: {16, 16, "complex128"},
	},
}

var model64 = &cc.Model{
	Items: map[cc.Kind]cc.ModelItem{
		cc.Ptr:               {8, 8, "__TODO_PTR"},
		cc.Void:              {0, 1, "__TODO_VOID"},
		cc.Char:              {1, 1, "int8"},
		cc.SChar:             {1, 1, "int8"},
		cc.UChar:             {1, 1, "byte"},
		cc.Short:             {2, 2, "int16"},
		cc.UShort:            {2, 2, "uint16"},
		cc.Int:               {4, 4, "int32"},
		cc.UInt:              {4, 4, "uint32"},
		cc.Long:              {8, 8, "int64"},
		cc.ULong:             {8, 8, "uint64"},
		cc.LongLong:          {8, 8, "int64"},
		cc.ULongLong:         {8, 8, "uint64"},
		cc.Float:             {4, 4, "float32"},
		cc.Double:            {8, 8, "float64"},
		cc.LongDouble:        {8, 8, "float64"},
		cc.Bool:              {1, 1, "bool"},
		cc.FloatComplex:      {8, 8, "complex64"},
		cc.DoubleComplex:     {16, 16, "complex128"},
		cc.LongDoubleComplex: {16, 16, "complex128"},
	},
}
<|endoftext|>


<commit_before>package term

import (
	"io"
	"os"
	"os/signal"

	windowsconsole "github.com/moby/term/windows"
	"golang.org/x/sys/windows"
)

// State holds the console mode for the terminal.
type State struct {
	mode uint32
}

// Winsize is used for window size.
type Winsize struct {
	Height uint16
	Width  uint16
}

// vtInputSupported is true if winterm.ENABLE_VIRTUAL_TERMINAL_INPUT is supported by the console
var vtInputSupported bool

// StdStreams returns the standard streams (stdin, stdout, stderr).
func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) {
	// Turn on VT handling on all std handles, if possible. This might
	// fail, in which case we will fall back to terminal emulation.
	var (
		emulateStdin, emulateStdout, emulateStderr bool

		mode uint32
	)

	fd := windows.Handle(os.Stdin.Fd())
	if err := windows.GetConsoleMode(fd, &mode); err == nil {
		// Validate that winterm.ENABLE_VIRTUAL_TERMINAL_INPUT is supported, but do not set it.
		if err = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_INPUT); err != nil {
			emulateStdin = true
		} else {
			vtInputSupported = true
		}
		// Unconditionally set the console mode back even on failure because SetConsoleMode
		// remembers invalid bits on input handles.
		_ = windows.SetConsoleMode(fd, mode)
	}

	fd = windows.Handle(os.Stdout.Fd())
	if err := windows.GetConsoleMode(fd, &mode); err == nil {
		// Validate winterm.DISABLE_NEWLINE_AUTO_RETURN is supported, but do not set it.
		if err = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING|windows.DISABLE_NEWLINE_AUTO_RETURN); err != nil {
			emulateStdout = true
		} else {
			_ = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING)
		}
	}

	fd = windows.Handle(os.Stderr.Fd())
	if err := windows.GetConsoleMode(fd, &mode); err == nil {
		// Validate winterm.DISABLE_NEWLINE_AUTO_RETURN is supported, but do not set it.
		if err = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING|windows.DISABLE_NEWLINE_AUTO_RETURN); err != nil {
			emulateStderr = true
		} else {
			_ = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING)
		}
	}

	// Temporarily use STD_INPUT_HANDLE, STD_OUTPUT_HANDLE and
	// STD_ERROR_HANDLE from syscall rather than x/sys/windows as long as
	// go-ansiterm hasn't switch to x/sys/windows.
	// TODO: switch back to x/sys/windows once go-ansiterm has switched
	if emulateStdin {
		h := uint32(windows.STD_INPUT_HANDLE)
		stdIn = windowsconsole.NewAnsiReader(int(h))
	} else {
		stdIn = os.Stdin
	}

	if emulateStdout {
		h := uint32(windows.STD_OUTPUT_HANDLE)
		stdOut = windowsconsole.NewAnsiWriter(int(h))
	} else {
		stdOut = os.Stdout
	}

	if emulateStderr {
		h := uint32(windows.STD_ERROR_HANDLE)
		stdErr = windowsconsole.NewAnsiWriter(int(h))
	} else {
		stdErr = os.Stderr
	}

	return
}

// GetFdInfo returns the file descriptor for an os.File and indicates whether the file represents a terminal.
func GetFdInfo(in interface{}) (uintptr, bool) {
	return windowsconsole.GetHandleInfo(in)
}

// GetWinsize returns the window size based on the specified file descriptor.
func GetWinsize(fd uintptr) (*Winsize, error) {
	var info windows.ConsoleScreenBufferInfo
	if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil {
		return nil, err
	}

	winsize := &Winsize{
		Width:  uint16(info.Window.Right - info.Window.Left + 1),
		Height: uint16(info.Window.Bottom - info.Window.Top + 1),
	}

	return winsize, nil
}

// IsTerminal returns true if the given file descriptor is a terminal.
func IsTerminal(fd uintptr) bool {
	var mode uint32
	err := windows.GetConsoleMode(windows.Handle(fd), &mode)
	return err == nil
}

// RestoreTerminal restores the terminal connected to the given file descriptor
// to a previous state.
func RestoreTerminal(fd uintptr, state *State) error {
	return windows.SetConsoleMode(windows.Handle(fd), state.mode)
}

// SaveState saves the state of the terminal connected to the given file descriptor.
func SaveState(fd uintptr) (*State, error) {
	var mode uint32

	if err := windows.GetConsoleMode(windows.Handle(fd), &mode); err != nil {
		return nil, err
	}

	return &State{mode: mode}, nil
}

// DisableEcho disables echo for the terminal connected to the given file descriptor.
// -- See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx
func DisableEcho(fd uintptr, state *State) error {
	mode := state.mode
	mode &^= windows.ENABLE_ECHO_INPUT
	mode |= windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT
	err := windows.SetConsoleMode(windows.Handle(fd), mode)
	if err != nil {
		return err
	}

	// Register an interrupt handler to catch and restore prior state
	restoreAtInterrupt(fd, state)
	return nil
}

// SetRawTerminal puts the terminal connected to the given file descriptor into
// raw mode and returns the previous state. On UNIX, this puts both the input
// and output into raw mode. On Windows, it only puts the input into raw mode.
func SetRawTerminal(fd uintptr) (*State, error) {
	state, err := MakeRaw(fd)
	if err != nil {
		return nil, err
	}

	// Register an interrupt handler to catch and restore prior state
	restoreAtInterrupt(fd, state)
	return state, err
}

// SetRawTerminalOutput puts the output of terminal connected to the given file
// descriptor into raw mode. On UNIX, this does nothing and returns nil for the
// state. On Windows, it disables LF -> CRLF translation.
func SetRawTerminalOutput(fd uintptr) (*State, error) {
	state, err := SaveState(fd)
	if err != nil {
		return nil, err
	}

	// Ignore failures, since winterm.DISABLE_NEWLINE_AUTO_RETURN might not be supported on this
	// version of Windows.
	_ = windows.SetConsoleMode(windows.Handle(fd), state.mode|windows.DISABLE_NEWLINE_AUTO_RETURN)
	return state, err
}

// MakeRaw puts the terminal (Windows Console) connected to the given file descriptor into raw
// mode and returns the previous state of the terminal so that it can be restored.
func MakeRaw(fd uintptr) (*State, error) {
	state, err := SaveState(fd)
	if err != nil {
		return nil, err
	}

	mode := state.mode

	// See
	// -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx
	// -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx

	// Disable these modes
	mode &^= windows.ENABLE_ECHO_INPUT
	mode &^= windows.ENABLE_LINE_INPUT
	mode &^= windows.ENABLE_MOUSE_INPUT
	mode &^= windows.ENABLE_WINDOW_INPUT
	mode &^= windows.ENABLE_PROCESSED_INPUT

	// Enable these modes
	mode |= windows.ENABLE_EXTENDED_FLAGS
	mode |= windows.ENABLE_INSERT_MODE
	mode |= windows.ENABLE_QUICK_EDIT_MODE
	if vtInputSupported {
		mode |= windows.ENABLE_VIRTUAL_TERMINAL_INPUT
	}

	err = windows.SetConsoleMode(windows.Handle(fd), mode)
	if err != nil {
		return nil, err
	}
	return state, nil
}

func restoreAtInterrupt(fd uintptr, state *State) {
	sigchan := make(chan os.Signal, 1)
	signal.Notify(sigchan, os.Interrupt)

	go func() {
		_ = <-sigchan
		_ = RestoreTerminal(fd, state)
		os.Exit(0)
	}()
}
<commit_msg>Remove outdated comment in func StdStreams<commit_after>package term

import (
	"io"
	"os"
	"os/signal"

	windowsconsole "github.com/moby/term/windows"
	"golang.org/x/sys/windows"
)

// State holds the console mode for the terminal.
type State struct {
	mode uint32
}

// Winsize is used for window size.
type Winsize struct {
	Height uint16
	Width  uint16
}

// vtInputSupported is true if winterm.ENABLE_VIRTUAL_TERMINAL_INPUT is supported by the console
var vtInputSupported bool

// StdStreams returns the standard streams (stdin, stdout, stderr).
func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) {
	// Turn on VT handling on all std handles, if possible. This might
	// fail, in which case we will fall back to terminal emulation.
	var (
		emulateStdin, emulateStdout, emulateStderr bool

		mode uint32
	)

	fd := windows.Handle(os.Stdin.Fd())
	if err := windows.GetConsoleMode(fd, &mode); err == nil {
		// Validate that winterm.ENABLE_VIRTUAL_TERMINAL_INPUT is supported, but do not set it.
		if err = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_INPUT); err != nil {
			emulateStdin = true
		} else {
			vtInputSupported = true
		}
		// Unconditionally set the console mode back even on failure because SetConsoleMode
		// remembers invalid bits on input handles.
		_ = windows.SetConsoleMode(fd, mode)
	}

	fd = windows.Handle(os.Stdout.Fd())
	if err := windows.GetConsoleMode(fd, &mode); err == nil {
		// Validate winterm.DISABLE_NEWLINE_AUTO_RETURN is supported, but do not set it.
		if err = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING|windows.DISABLE_NEWLINE_AUTO_RETURN); err != nil {
			emulateStdout = true
		} else {
			_ = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING)
		}
	}

	fd = windows.Handle(os.Stderr.Fd())
	if err := windows.GetConsoleMode(fd, &mode); err == nil {
		// Validate winterm.DISABLE_NEWLINE_AUTO_RETURN is supported, but do not set it.
		if err = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING|windows.DISABLE_NEWLINE_AUTO_RETURN); err != nil {
			emulateStderr = true
		} else {
			_ = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING)
		}
	}

	if emulateStdin {
		h := uint32(windows.STD_INPUT_HANDLE)
		stdIn = windowsconsole.NewAnsiReader(int(h))
	} else {
		stdIn = os.Stdin
	}

	if emulateStdout {
		h := uint32(windows.STD_OUTPUT_HANDLE)
		stdOut = windowsconsole.NewAnsiWriter(int(h))
	} else {
		stdOut = os.Stdout
	}

	if emulateStderr {
		h := uint32(windows.STD_ERROR_HANDLE)
		stdErr = windowsconsole.NewAnsiWriter(int(h))
	} else {
		stdErr = os.Stderr
	}

	return
}

// GetFdInfo returns the file descriptor for an os.File and indicates whether the file represents a terminal.
func GetFdInfo(in interface{}) (uintptr, bool) {
	return windowsconsole.GetHandleInfo(in)
}

// GetWinsize returns the window size based on the specified file descriptor.
func GetWinsize(fd uintptr) (*Winsize, error) {
	var info windows.ConsoleScreenBufferInfo
	if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil {
		return nil, err
	}

	winsize := &Winsize{
		Width:  uint16(info.Window.Right - info.Window.Left + 1),
		Height: uint16(info.Window.Bottom - info.Window.Top + 1),
	}

	return winsize, nil
}

// IsTerminal returns true if the given file descriptor is a terminal.
func IsTerminal(fd uintptr) bool {
	var mode uint32
	err := windows.GetConsoleMode(windows.Handle(fd), &mode)
	return err == nil
}

// RestoreTerminal restores the terminal connected to the given file descriptor
// to a previous state.
func RestoreTerminal(fd uintptr, state *State) error {
	return windows.SetConsoleMode(windows.Handle(fd), state.mode)
}

// SaveState saves the state of the terminal connected to the given file descriptor.
func SaveState(fd uintptr) (*State, error) {
	var mode uint32

	if err := windows.GetConsoleMode(windows.Handle(fd), &mode); err != nil {
		return nil, err
	}

	return &State{mode: mode}, nil
}

// DisableEcho disables echo for the terminal connected to the given file descriptor.
// -- See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx
func DisableEcho(fd uintptr, state *State) error {
	mode := state.mode
	mode &^= windows.ENABLE_ECHO_INPUT
	mode |= windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT
	err := windows.SetConsoleMode(windows.Handle(fd), mode)
	if err != nil {
		return err
	}

	// Register an interrupt handler to catch and restore prior state
	restoreAtInterrupt(fd, state)
	return nil
}

// SetRawTerminal puts the terminal connected to the given file descriptor into
// raw mode and returns the previous state. On UNIX, this puts both the input
// and output into raw mode. On Windows, it only puts the input into raw mode.
func SetRawTerminal(fd uintptr) (*State, error) {
	state, err := MakeRaw(fd)
	if err != nil {
		return nil, err
	}

	// Register an interrupt handler to catch and restore prior state
	restoreAtInterrupt(fd, state)
	return state, err
}

// SetRawTerminalOutput puts the output of terminal connected to the given file
// descriptor into raw mode. On UNIX, this does nothing and returns nil for the
// state. On Windows, it disables LF -> CRLF translation.
func SetRawTerminalOutput(fd uintptr) (*State, error) {
	state, err := SaveState(fd)
	if err != nil {
		return nil, err
	}

	// Ignore failures, since winterm.DISABLE_NEWLINE_AUTO_RETURN might not be supported on this
	// version of Windows.
	_ = windows.SetConsoleMode(windows.Handle(fd), state.mode|windows.DISABLE_NEWLINE_AUTO_RETURN)
	return state, err
}

// MakeRaw puts the terminal (Windows Console) connected to the given file descriptor into raw
// mode and returns the previous state of the terminal so that it can be restored.
func MakeRaw(fd uintptr) (*State, error) {
	state, err := SaveState(fd)
	if err != nil {
		return nil, err
	}

	mode := state.mode

	// See
	// -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx
	// -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx

	// Disable these modes
	mode &^= windows.ENABLE_ECHO_INPUT
	mode &^= windows.ENABLE_LINE_INPUT
	mode &^= windows.ENABLE_MOUSE_INPUT
	mode &^= windows.ENABLE_WINDOW_INPUT
	mode &^= windows.ENABLE_PROCESSED_INPUT

	// Enable these modes
	mode |= windows.ENABLE_EXTENDED_FLAGS
	mode |= windows.ENABLE_INSERT_MODE
	mode |= windows.ENABLE_QUICK_EDIT_MODE
	if vtInputSupported {
		mode |= windows.ENABLE_VIRTUAL_TERMINAL_INPUT
	}

	err = windows.SetConsoleMode(windows.Handle(fd), mode)
	if err != nil {
		return nil, err
	}
	return state, nil
}

func restoreAtInterrupt(fd uintptr, state *State) {
	sigchan := make(chan os.Signal, 1)
	signal.Notify(sigchan, os.Interrupt)

	go func() {
		_ = <-sigchan
		_ = RestoreTerminal(fd, state)
		os.Exit(0)
	}()
}
<|endoftext|>


<commit_before>package termite

import (
	"github.com/hanwen/go-fuse/fuse"
	"github.com/hanwen/go-fuse/unionfs"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
)

type WorkerFuseFs struct {
	rwDir  string
	tmpDir string
	mount  string
	*fuse.MountState
	fsConnector *fuse.FileSystemConnector
	unionFs     *unionfs.UnionFs
}

func (me *WorkerFuseFs) Stop() {
	err := me.MountState.Unmount()
	if err != nil {
		// TODO - Should be fatal?
		log.Println("Unmount fail:", err)
	} else {
		// If the unmount fails, the RemoveAll will stat all
		// of the FUSE file system.
		os.RemoveAll(me.tmpDir)
	}
}

func (me *Mirror) ReturnFuse(wfs *WorkerFuseFs) {
	me.fuseFileSystemsMutex.Lock()
	defer me.fuseFileSystemsMutex.Unlock()

	if me.shuttingDown {
		wfs.Stop()
	} else {
		me.fuseFileSystems = append(me.fuseFileSystems, wfs)
	}
	me.workingFileSystems[wfs] = "", false
	me.cond.Signal()
}

func newWorkerFuseFs(tmpDir string, rpcFs fuse.FileSystem, writableRoot string) (*WorkerFuseFs, os.Error) {
	tmpDir, err := ioutil.TempDir(tmpDir, "termite-task")
	if err != nil {
		return nil, err
	}
	w := WorkerFuseFs{
		tmpDir: tmpDir,
	}

	type dirInit struct {
		dst *string
		val string
	}

	for _, v := range []dirInit{
		dirInit{&w.rwDir, "rw"},
		dirInit{&w.mount, "mnt"},
	} {
		*v.dst = filepath.Join(w.tmpDir, v.val)
		err = os.Mkdir(*v.dst, 0700)
		if err != nil {
			return nil, err
		}
	}

	tmpBacking := filepath.Join(w.tmpDir, "tmp-backingstore")
	if err := os.Mkdir(tmpBacking, 0700); err != nil {
		return nil, err
	}

	rwFs := fuse.NewLoopbackFileSystem(w.rwDir)

	ttl := 30.0
	opts := unionfs.UnionFsOptions{
		BranchCacheTTLSecs:   ttl,
		DeletionCacheTTLSecs: ttl,
		DeletionDirName:      _DELETIONS,
	}
	mOpts := fuse.FileSystemOptions{
		EntryTimeout:    ttl,
		AttrTimeout:     ttl,
		NegativeTimeout: ttl,
	}

	tmpFs := fuse.NewLoopbackFileSystem(tmpBacking)

	w.unionFs = unionfs.NewUnionFs([]fuse.FileSystem{rwFs, rpcFs}, opts)
	swFs := []fuse.SwitchedFileSystem{
		{"dev", &DevNullFs{}, true},
		{"", rpcFs, false},
		{"tmp", tmpFs, true},
		{"var/tmp", tmpFs, true},

		// TODO - configurable.
		{writableRoot, w.unionFs, false},
	}

	w.fsConnector = fuse.NewFileSystemConnector(fuse.NewSwitchFileSystem(swFs), &mOpts)
	w.MountState = fuse.NewMountState(w.fsConnector)

	fuseOpts := fuse.MountOptions{
		AllowOther: true,
		// Compilers are not that highly parallel.  A lower
		// number also helps stacktrace be less overwhelming.
		MaxBackground: 4,
	}
	err = w.MountState.Mount(w.mount, &fuseOpts)
	if err != nil {
		return nil, err
	}

	go w.MountState.Loop(true)

	return &w, nil
}

func (me *WorkerFuseFs) update(attrs []FileAttr) {
	paths := []string{}
	for _, attr := range attrs {
		path := strings.TrimLeft(attr.Path, "/")

		// TODO - should have bulk interface?
		me.fsConnector.FileNotify(path, 0, 0)
		paths = append(paths, path)
	}
	me.unionFs.DropBranchCache(paths)
	me.unionFs.DropDeletionCache()
}
<commit_msg>Only set allowOther if we are root.<commit_after>package termite

import (
	"github.com/hanwen/go-fuse/fuse"
	"github.com/hanwen/go-fuse/unionfs"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
)

type WorkerFuseFs struct {
	rwDir  string
	tmpDir string
	mount  string
	*fuse.MountState
	fsConnector *fuse.FileSystemConnector
	unionFs     *unionfs.UnionFs
}

func (me *WorkerFuseFs) Stop() {
	err := me.MountState.Unmount()
	if err != nil {
		// TODO - Should be fatal?
		log.Println("Unmount fail:", err)
	} else {
		// If the unmount fails, the RemoveAll will stat all
		// of the FUSE file system.
		os.RemoveAll(me.tmpDir)
	}
}

func (me *Mirror) ReturnFuse(wfs *WorkerFuseFs) {
	me.fuseFileSystemsMutex.Lock()
	defer me.fuseFileSystemsMutex.Unlock()

	if me.shuttingDown {
		wfs.Stop()
	} else {
		me.fuseFileSystems = append(me.fuseFileSystems, wfs)
	}
	me.workingFileSystems[wfs] = "", false
	me.cond.Signal()
}

func newWorkerFuseFs(tmpDir string, rpcFs fuse.FileSystem, writableRoot string) (*WorkerFuseFs, os.Error) {
	tmpDir, err := ioutil.TempDir(tmpDir, "termite-task")
	if err != nil {
		return nil, err
	}
	w := WorkerFuseFs{
		tmpDir: tmpDir,
	}

	type dirInit struct {
		dst *string
		val string
	}

	for _, v := range []dirInit{
		dirInit{&w.rwDir, "rw"},
		dirInit{&w.mount, "mnt"},
	} {
		*v.dst = filepath.Join(w.tmpDir, v.val)
		err = os.Mkdir(*v.dst, 0700)
		if err != nil {
			return nil, err
		}
	}

	tmpBacking := filepath.Join(w.tmpDir, "tmp-backingstore")
	if err := os.Mkdir(tmpBacking, 0700); err != nil {
		return nil, err
	}

	rwFs := fuse.NewLoopbackFileSystem(w.rwDir)

	ttl := 30.0
	opts := unionfs.UnionFsOptions{
		BranchCacheTTLSecs:   ttl,
		DeletionCacheTTLSecs: ttl,
		DeletionDirName:      _DELETIONS,
	}
	mOpts := fuse.FileSystemOptions{
		EntryTimeout:    ttl,
		AttrTimeout:     ttl,
		NegativeTimeout: ttl,
	}

	tmpFs := fuse.NewLoopbackFileSystem(tmpBacking)

	w.unionFs = unionfs.NewUnionFs([]fuse.FileSystem{rwFs, rpcFs}, opts)
	swFs := []fuse.SwitchedFileSystem{
		{"dev", &DevNullFs{}, true},
		{"", rpcFs, false},
		{"tmp", tmpFs, true},
		{"var/tmp", tmpFs, true},

		// TODO - configurable.
		{writableRoot, w.unionFs, false},
	}

	w.fsConnector = fuse.NewFileSystemConnector(fuse.NewSwitchFileSystem(swFs), &mOpts)
	w.MountState = fuse.NewMountState(w.fsConnector)

	fuseOpts := fuse.MountOptions{
		// Compilers are not that highly parallel.  A lower
		// number also helps stacktrace be less overwhelming.
		MaxBackground: 4,
	}
	if os.Geteuid() == 0 {
		fuseOpts.AllowOther = true
	}

	err = w.MountState.Mount(w.mount, &fuseOpts)
	if err != nil {
		return nil, err
	}

	go w.MountState.Loop(true)

	return &w, nil
}

func (me *WorkerFuseFs) update(attrs []FileAttr) {
	paths := []string{}
	for _, attr := range attrs {
		path := strings.TrimLeft(attr.Path, "/")

		// TODO - should have bulk interface?
		me.fsConnector.FileNotify(path, 0, 0)
		paths = append(paths, path)
	}
	me.unionFs.DropBranchCache(paths)
	me.unionFs.DropDeletionCache()
}
<|endoftext|>


<commit_before>// Package umbrella provides utility functions to maintain your Shade
// repository, such as cleaning up orphaned files and chunks.
package umbrella

import (
	"flag"
	"fmt"
	"time"

	"github.com/asjoyner/shade"
	"github.com/asjoyner/shade/drive"
	"github.com/asjoyner/shade/drive/encrypt"
	"github.com/golang/glog"
)

var (
	maxFilesDelete  = flag.Int("maxFilesDelete", 100, "A safety limit: the maxmium number of files to delete per run.")
	maxChunksDelete = flag.Int("maxChunksDelete", 100, "A safety limit: the maxmium number of files to delete per run.")
)

// FoundFile groups files with their associated sums
type FoundFile struct {
	file *shade.File
	sum  []byte
}

// FetchFiles uses the provided client to fetch all of the known files and
// sorts them into those which are inUse and those which are obsolete.
func FetchFiles(client drive.Client) (inUse, obsolete []FoundFile, err error) {
	filesByPath := make(map[string]FoundFile)
	obsolete = make([]FoundFile, 0)
	// ListFiles to retrieve all file objects
	files, err := client.ListFiles()
	if err != nil {
		return nil, nil, fmt.Errorf("%q ListFiles(): %s", client.GetConfig().Provider, err)
	}
	glog.Infof("Found %d file(s) via %s", len(files), client.GetConfig().Provider)
	for _, sha256sum := range files {
		// fetch the file
		f, err := client.GetFile(sha256sum)
		if err != nil {
			glog.Warningf("Failed to fetch file %x: %s  (skipping)", sha256sum, err)
			continue
		}
		file := &shade.File{}
		if err := file.FromJSON(f); err != nil {
			glog.Warningf("Could not unmarshal file %x: %v", sha256sum, err)
			continue
		}
		existing, ok := filesByPath[file.Filename]
		if !ok {
			glog.V(2).Infof("found new file: %x", sha256sum)
			filesByPath[file.Filename] = FoundFile{file, sha256sum}
			continue
		}

		if existing.file.ModifiedTime.After(file.ModifiedTime) {
			glog.V(2).Infof("obsolete file: %x (%d < %d)", sha256sum, file.ModifiedTime.Unix(), existing.file.ModifiedTime.Unix())
			obsolete = append(obsolete, FoundFile{file, sha256sum})
			continue
		}
		filesByPath[file.Filename] = FoundFile{file, sha256sum}
		glog.V(2).Infof("obsolete file: %x (%d < %d)", existing.sum, file.ModifiedTime.Unix(), existing.file.ModifiedTime.Unix())
		obsolete = append(obsolete, FoundFile{existing.file, existing.sum})
	}
	inUse = make([]FoundFile, 0, len(filesByPath))
	for _, ff := range filesByPath {
		inUse = append(inUse, ff)
	}
	return
}

// Cleanup attempts to remove obsolete files and unused chunks from persistent
// storage clients.
func Cleanup(client drive.Client) error {
	inUse, obsolete, err := FetchFiles(client)
	if err != nil {
		return err
	}
	niu := len(inUse)
	no := len(obsolete)
	if niu < no {
		err := fmt.Errorf("more files are obsolete (%d) than remain (%d); aborting", no, niu)
		glog.Warning(err.Error())
		return err
	}
	if no > *maxFilesDelete {
		err := fmt.Errorf("num obsolete files (%d) over safety threshold (%d)", no, maxFilesDelete)
		glog.Warning(err.Error())
		return err
	}
	for _, ff := range obsolete {
		glog.Infof("Releasing obsolete file: %x", ff.sum)
		client.ReleaseFile(ff.sum)
	}

	// Build the map of all the chunksInUse
	chunksInUse := make(map[string]struct{})
	for _, ff := range inUse {
		for _, chunk := range ff.file.Chunks {
			chunksInUse[string(chunk.Sha256)] = struct{}{}
		}
		esums, err := encrypt.GetAllEncryptedSums(ff.file)
		if err != nil {
			summary := fmt.Sprintf("could not get encrypted sums for %s: %d", ff.file.Filename, len(esums))
			glog.Warningf("%s: %s", summary, err)
			return fmt.Errorf("%s: %s", summary, err)
		}
		glog.V(3).Infof("encrypted sums for %s: %d", ff.file.Filename, len(esums))
		for _, s := range esums {
			glog.V(7).Infof("valid encrypted sum: %x", s)
			chunksInUse[string(s)] = struct{}{}
		}
	}

	if err := cleanupUnusedFiles(client, chunksInUse); err != nil {
		return err
	}
	return nil
}

func cleanupUnusedFiles(client drive.Client, chunksInUse map[string]struct{}) error {
	var unusedChunks [][]byte
	lister := client.NewChunkLister()
	for lister.Next() {
		csum := lister.Sha256()
		if _, ok := chunksInUse[string(csum)]; !ok {
			unusedChunks = append(unusedChunks, csum)
			continue
		}
		glog.V(2).Infof("chunk is in use: %x", csum)
	}
	if err := lister.Err(); err != nil {
		return err
	}
	uc := len(unusedChunks)
	if uc >= *maxChunksDelete {
		err := fmt.Errorf("num unused chunks (%d) over safety threshold (%d)", uc, maxFilesDelete)
		glog.Warning(err.Error())
		return err
	}
	for _, csum := range unusedChunks {
		glog.V(2).Infof("removing unreferenced chunk: %x", csum)
		client.ReleaseChunk(csum)
	}
	return nil
}

// CleanupLoop calls Cleanup once per hour
func CleanupLoop(client drive.Client) {
	for {
		Cleanup(client)
		time.Sleep(1 * time.Hour)
	}
}
<commit_msg>Add -deleteMostFiles flag to bypass a safety check<commit_after>// Package umbrella provides utility functions to maintain your Shade
// repository, such as cleaning up orphaned files and chunks.
package umbrella

import (
	"flag"
	"fmt"
	"time"

	"github.com/asjoyner/shade"
	"github.com/asjoyner/shade/drive"
	"github.com/asjoyner/shade/drive/encrypt"
	"github.com/golang/glog"
)

var (
	maxFilesDelete  = flag.Int("maxFilesDelete", 100, "A safety limit: the maxmium number of files to delete per run.")
	maxChunksDelete = flag.Int("maxChunksDelete", 100, "A safety limit: the maxmium number of chunks to delete per run.")
	deleteMostFiles = flag.Bool("deleteMostFiles", false, "A safety limit: more files must remain than are deleted.")
)

// FoundFile groups files with their associated sums
type FoundFile struct {
	file *shade.File
	sum  []byte
}

// FetchFiles uses the provided client to fetch all of the known files and
// sorts them into those which are inUse and those which are obsolete.
func FetchFiles(client drive.Client) (inUse, obsolete []FoundFile, err error) {
	filesByPath := make(map[string]FoundFile)
	obsolete = make([]FoundFile, 0)
	// ListFiles to retrieve all file objects
	files, err := client.ListFiles()
	if err != nil {
		return nil, nil, fmt.Errorf("%q ListFiles(): %s", client.GetConfig().Provider, err)
	}
	glog.Infof("Found %d file(s) via %s", len(files), client.GetConfig().Provider)
	for _, sha256sum := range files {
		// fetch the file
		f, err := client.GetFile(sha256sum)
		if err != nil {
			glog.Warningf("Failed to fetch file %x: %s  (skipping)", sha256sum, err)
			continue
		}
		file := &shade.File{}
		if err := file.FromJSON(f); err != nil {
			glog.Warningf("Could not unmarshal file %x: %v", sha256sum, err)
			continue
		}
		existing, ok := filesByPath[file.Filename]
		if !ok {
			glog.V(4).Infof("found new file: %x", sha256sum)
			filesByPath[file.Filename] = FoundFile{file, sha256sum}
			continue
		}

		if existing.file.ModifiedTime.After(file.ModifiedTime) {
			glog.V(2).Infof("obsolete file: %x (%d < %d)", sha256sum, file.ModifiedTime.Unix(), existing.file.ModifiedTime.Unix())
			obsolete = append(obsolete, FoundFile{file, sha256sum})
			continue
		}
		filesByPath[file.Filename] = FoundFile{file, sha256sum}
		glog.V(2).Infof("obsolete file: %x (%d < %d)", existing.sum, file.ModifiedTime.Unix(), existing.file.ModifiedTime.Unix())
		obsolete = append(obsolete, FoundFile{existing.file, existing.sum})
	}
	inUse = make([]FoundFile, 0, len(filesByPath))
	for _, ff := range filesByPath {
		inUse = append(inUse, ff)
	}
	return
}

// Cleanup attempts to remove obsolete files and unused chunks from persistent
// storage clients.
func Cleanup(client drive.Client) error {
	inUse, obsolete, err := FetchFiles(client)
	if err != nil {
		return err
	}
	niu := len(inUse)
	no := len(obsolete)
	if niu < no && !*deleteMostFiles {
		err := fmt.Errorf("more files are obsolete (%d) than remain (%d); aborting (bypass with --deleteMostFiles)", no, niu)
		glog.Warning(err.Error())
		return err
	}
	if no > *maxFilesDelete {
		err := fmt.Errorf("num obsolete files (%d) over safety threshold (%d)", no, maxFilesDelete)
		glog.Warning(err.Error())
		return err
	}
	for _, ff := range obsolete {
		glog.Infof("Releasing obsolete file: %x", ff.sum)
		client.ReleaseFile(ff.sum)
	}

	// Build the map of all the chunksInUse
	chunksInUse := make(map[string]struct{})
	for _, ff := range inUse {
		for _, chunk := range ff.file.Chunks {
			chunksInUse[string(chunk.Sha256)] = struct{}{}
		}
		esums, err := encrypt.GetAllEncryptedSums(ff.file)
		if err != nil {
			summary := fmt.Sprintf("could not get encrypted sums for %s: %d", ff.file.Filename, len(esums))
			glog.Warningf("%s: %s", summary, err)
			return fmt.Errorf("%s: %s", summary, err)
		}
		glog.V(4).Infof("encrypted sums for %s: %d", ff.file.Filename, len(esums))
		for _, s := range esums {
			glog.V(7).Infof("valid encrypted sum: %x", s)
			chunksInUse[string(s)] = struct{}{}
		}
	}

	if err := cleanupUnusedFiles(client, chunksInUse); err != nil {
		return err
	}
	return nil
}

func cleanupUnusedFiles(client drive.Client, chunksInUse map[string]struct{}) error {
	var unusedChunks [][]byte
	lister := client.NewChunkLister()
	for lister.Next() {
		csum := lister.Sha256()
		if _, ok := chunksInUse[string(csum)]; !ok {
			unusedChunks = append(unusedChunks, csum)
			continue
		}
		glog.V(3).Infof("chunk is in use: %x", csum)
	}
	if err := lister.Err(); err != nil {
		return err
	}
	uc := len(unusedChunks)
	if uc >= *maxChunksDelete {
		err := fmt.Errorf("num unused chunks (%d) over safety threshold (%d)", uc, *maxChunksDelete)
		glog.Warning(err.Error())
		return err
	}
	for _, csum := range unusedChunks {
		glog.V(2).Infof("removing unreferenced chunk: %x", csum)
		client.ReleaseChunk(csum)
	}
	return nil
}

// CleanupLoop calls Cleanup once per hour
func CleanupLoop(client drive.Client) {
	for {
		Cleanup(client)
		time.Sleep(1 * time.Hour)
	}
}
<|endoftext|>


<commit_before>package command

// A CommandCallback takes the name of the player invoking the command, any
// text supplied after the trigger for the command, and an interface via which
// game-wide 'actions' can be taken.
type CommandCallback func(string, string, ICommandHandler)

type Command struct {
	Trigger     string          // The initial text eg. "give".
	Description string          // A description of what the command does.
	Usage       string          // A usage string for the command.
	Callback    CommandCallback // This function will be called if a Message begins with the CommandPrefix and the Trigger.
}

func NewCommand(trigger, desc, usage string, callback CommandCallback) *Command {
	return &Command{Trigger: trigger, Description: desc, Usage: usage, Callback: callback}
}
<commit_msg>Add parameter names to CommandCallback<commit_after>package command

// A CommandCallback takes the name of the player invoking the command, any
// text supplied after the trigger for the command, and an interface via which
// game-wide 'actions' can be taken.
type CommandCallback func(playerName string, args string, handler ICommandHandler)

type Command struct {
	Trigger     string          // The initial text eg. "give".
	Description string          // A description of what the command does.
	Usage       string          // A usage string for the command.
	Callback    CommandCallback // This function will be called if a Message begins with the CommandPrefix and the Trigger.
}

func NewCommand(trigger, desc, usage string, callback CommandCallback) *Command {
	return &Command{Trigger: trigger, Description: desc, Usage: usage, Callback: callback}
}
<|endoftext|>


<commit_before>package uploader

import (
	"bytes"
	"fmt"
	"io/ioutil"

	"github.com/go-microservices/resizer/log"
	"github.com/go-microservices/resizer/option"
	"github.com/go-microservices/resizer/storage"
	"golang.org/x/net/context"
	"golang.org/x/oauth2/google"
	gcs "google.golang.org/api/storage/v1"
)

const scope = gcs.DevstorageFullControlScope

type Uploader struct {
	service   *gcs.Service
	projectID string
	bucket    string
}

// New はアップローダーを作成する。
func New(o option.Options) (*Uploader, error) {
	jsonFile, err := ioutil.ReadFile(o.JSON)
	if err != nil {
		log.Fatalf("Could not open json: %v", err)
	}
	config, err := google.JWTConfigFromJSON(jsonFile, scope)
	if err != nil {
		log.Fatalf("Could not parse json: %v", err)
	}
	client := config.Client(context.Background())
	service, err := gcs.New(client)
	if err != nil {
		log.Fatalf("Unable to create storage service: %v", err)
	}
	return &Uploader{service, o.ProjectID, o.Bucket}, nil
}

func (self *Uploader) Upload(buf *bytes.Buffer, f storage.Image) (string, error) {
	t := log.Start()
	defer log.End(t)

	object := &gcs.Object{Name: f.Filename}
	if res, err := self.service.Objects.Insert(self.bucket, object).Media(buf).Do(); err == nil {
		fmt.Printf("Created object %v at location %v\n\n", res.Name, res.SelfLink)
	} else {
		log.Fatalf("Objects.Insert failed: %v", err)
	}

	url := self.CreateURL(f.Filename)
	log.Printf("ok: url=%s", url)

	return url, nil
}

func (self *Uploader) CreateURL(path string) string {
	return fmt.Sprintf("https://%s.storage.googleapis.com/%s", self.bucket, path)
}
<commit_msg>Set max-age to 180 days<commit_after>package uploader

import (
	"bytes"
	"fmt"
	"io/ioutil"

	"github.com/go-microservices/resizer/log"
	"github.com/go-microservices/resizer/option"
	"github.com/go-microservices/resizer/storage"
	"golang.org/x/net/context"
	"golang.org/x/oauth2/google"
	gcs "google.golang.org/api/storage/v1"
)

const (
	scope     = gcs.DevstorageFullControlScope
	sixMonths = 60 * 60 * 24 * 30 * 6
)

type Uploader struct {
	service   *gcs.Service
	projectID string
	bucket    string
}

// New はアップローダーを作成する。
func New(o option.Options) (*Uploader, error) {
	jsonFile, err := ioutil.ReadFile(o.JSON)
	if err != nil {
		log.Fatalf("Could not open json: %v", err)
	}
	config, err := google.JWTConfigFromJSON(jsonFile, scope)
	if err != nil {
		log.Fatalf("Could not parse json: %v", err)
	}
	client := config.Client(context.Background())
	service, err := gcs.New(client)
	if err != nil {
		log.Fatalf("Unable to create storage service: %v", err)
	}
	return &Uploader{service, o.ProjectID, o.Bucket}, nil
}

func (self *Uploader) Upload(buf *bytes.Buffer, f storage.Image) (string, error) {
	t := log.Start()
	defer log.End(t)

	object := &gcs.Object{Name: f.Filename, CacheControl: fmt.Sprintf("max-age=%d", sixMonths)}
	if res, err := self.service.Objects.Insert(self.bucket, object).Media(buf).Do(); err == nil {
		fmt.Printf("Created object %v at location %v\n\n", res.Name, res.SelfLink)
	} else {
		log.Fatalf("Objects.Insert failed: %v", err)
	}

	url := self.CreateURL(f.Filename)
	log.Printf("ok: url=%s", url)

	return url, nil
}

func (self *Uploader) CreateURL(path string) string {
	return fmt.Sprintf("https://%s.storage.googleapis.com/%s", self.bucket, path)
}
<|endoftext|>


<commit_before>// Copyright 2011 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.

// Package urlfetch provides an http.RoundTripper implementation
// for fetching URLs via App Engine's urlfetch service.
package urlfetch // import "google.golang.org/appengine/urlfetch"

import (
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"

	"github.com/golang/protobuf/proto"
	"golang.org/x/net/context"

	"google.golang.org/appengine/internal"
	pb "google.golang.org/appengine/internal/urlfetch"
)

// Transport is an implementation of http.RoundTripper for
// App Engine. Users should generally create an http.Client using
// this transport and use the Client rather than using this transport
// directly.
type Transport struct {
	Context context.Context

	// Controls whether the application checks the validity of SSL certificates
	// over HTTPS connections. A value of false (the default) instructs the
	// application to send a request to the server only if the certificate is
	// valid and signed by a trusted certificate authority (CA), and also
	// includes a hostname that matches the certificate. A value of true
	// instructs the application to perform no certificate validation.
	AllowInvalidServerCertificate bool
}

// Verify statically that *Transport implements http.RoundTripper.
var _ http.RoundTripper = (*Transport)(nil)

// Client returns an *http.Client using a default urlfetch Transport. This
// client will have the default deadline of 5 seconds, and will check the
// validity of SSL certificates.
//
// Any deadline of the provided context will be used for requests through this client;
// if the client does not have a deadline then a 5 second default is used.
func Client(ctx context.Context) *http.Client {
	return &http.Client{
		Transport: &Transport{
			Context: ctx,
		},
	}
}

type bodyReader struct {
	content   []byte
	truncated bool
	closed    bool
}

// ErrTruncatedBody is the error returned after the final Read() from a
// response's Body if the body has been truncated by App Engine's proxy.
var ErrTruncatedBody = errors.New("urlfetch: truncated body")

func statusCodeToText(code int) string {
	if t := http.StatusText(code); t != "" {
		return t
	}
	return strconv.Itoa(code)
}

func (br *bodyReader) Read(p []byte) (n int, err error) {
	if br.closed {
		if br.truncated {
			return 0, ErrTruncatedBody
		}
		return 0, io.EOF
	}
	n = copy(p, br.content)
	if n > 0 {
		br.content = br.content[n:]
		return
	}
	if br.truncated {
		br.closed = true
		return 0, ErrTruncatedBody
	}
	return 0, io.EOF
}

func (br *bodyReader) Close() error {
	br.closed = true
	br.content = nil
	return nil
}

// A map of the URL Fetch-accepted methods that take a request body.
var methodAcceptsRequestBody = map[string]bool{
	"POST":  true,
	"PUT":   true,
	"PATCH": true,
}

// urlString returns a valid string given a URL. This function is necessary because
// the String method of URL doesn't correctly handle URLs with non-empty Opaque values.
// See http://code.google.com/p/go/issues/detail?id=4860.
func urlString(u *url.URL) string {
	if u.Opaque == "" || strings.HasPrefix(u.Opaque, "//") {
		return u.String()
	}
	aux := *u
	aux.Opaque = "//" + aux.Host + aux.Opaque
	return aux.String()
}

// RoundTrip issues a single HTTP request and returns its response. Per the
// http.RoundTripper interface, RoundTrip only returns an error if there
// was an unsupported request or the URL Fetch proxy fails.
// Note that HTTP response codes such as 5xx, 403, 404, etc are not
// errors as far as the transport is concerned and will be returned
// with err set to nil.
func (t *Transport) RoundTrip(req *http.Request) (res *http.Response, err error) {
	methNum, ok := pb.URLFetchRequest_RequestMethod_value[req.Method]
	if !ok {
		return nil, fmt.Errorf("urlfetch: unsupported HTTP method %q", req.Method)
	}

	method := pb.URLFetchRequest_RequestMethod(methNum)

	freq := &pb.URLFetchRequest{
		Method:                        &method,
		Url:                           proto.String(urlString(req.URL)),
		FollowRedirects:               proto.Bool(false), // http.Client's responsibility
		MustValidateServerCertificate: proto.Bool(!t.AllowInvalidServerCertificate),
	}
	if deadline, ok := t.Context.Deadline(); ok {
		freq.Deadline = proto.Float64(deadline.Sub(time.Now()).Seconds())
	}

	for k, vals := range req.Header {
		for _, val := range vals {
			freq.Header = append(freq.Header, &pb.URLFetchRequest_Header{
				Key:   proto.String(k),
				Value: proto.String(val),
			})
		}
	}
	if methodAcceptsRequestBody[req.Method] && req.Body != nil {
		// Avoid a []byte copy if req.Body has a Bytes method.
		switch b := req.Body.(type) {
		case interface {
			Bytes() []byte
		}:
			freq.Payload = b.Bytes()
		default:
			freq.Payload, err = ioutil.ReadAll(req.Body)
			if err != nil {
				return nil, err
			}
		}
	}

	fres := &pb.URLFetchResponse{}
	if err := internal.Call(t.Context, "urlfetch", "Fetch", freq, fres); err != nil {
		return nil, err
	}

	res = &http.Response{}
	res.StatusCode = int(*fres.StatusCode)
	res.Status = fmt.Sprintf("%d %s", res.StatusCode, statusCodeToText(res.StatusCode))
	res.Header = make(http.Header)
	res.Request = req

	// Faked:
	res.ProtoMajor = 1
	res.ProtoMinor = 1
	res.Proto = "HTTP/1.1"
	res.Close = true

	for _, h := range fres.Header {
		hkey := http.CanonicalHeaderKey(*h.Key)
		hval := *h.Value
		if hkey == "Content-Length" {
			// Will get filled in below for all but HEAD requests.
			if req.Method == "HEAD" {
				res.ContentLength, _ = strconv.ParseInt(hval, 10, 64)
			}
			continue
		}
		res.Header.Add(hkey, hval)
	}

	if req.Method != "HEAD" {
		res.ContentLength = int64(len(fres.Content))
	}

	truncated := fres.GetContentWasTruncated()
	res.Body = &bodyReader{content: fres.Content, truncated: truncated}
	return
}

func init() {
	internal.RegisterErrorCodeMap("urlfetch", pb.URLFetchServiceError_ErrorCode_name)
	internal.RegisterTimeoutErrorCode("urlfetch", int32(pb.URLFetchServiceError_DEADLINE_EXCEEDED))
}
<commit_msg>Fix documented default deadline in urlfetch client (#249)<commit_after>// Copyright 2011 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.

// Package urlfetch provides an http.RoundTripper implementation
// for fetching URLs via App Engine's urlfetch service.
package urlfetch // import "google.golang.org/appengine/urlfetch"

import (
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"

	"github.com/golang/protobuf/proto"
	"golang.org/x/net/context"

	"google.golang.org/appengine/internal"
	pb "google.golang.org/appengine/internal/urlfetch"
)

// Transport is an implementation of http.RoundTripper for
// App Engine. Users should generally create an http.Client using
// this transport and use the Client rather than using this transport
// directly.
type Transport struct {
	Context context.Context

	// Controls whether the application checks the validity of SSL certificates
	// over HTTPS connections. A value of false (the default) instructs the
	// application to send a request to the server only if the certificate is
	// valid and signed by a trusted certificate authority (CA), and also
	// includes a hostname that matches the certificate. A value of true
	// instructs the application to perform no certificate validation.
	AllowInvalidServerCertificate bool
}

// Verify statically that *Transport implements http.RoundTripper.
var _ http.RoundTripper = (*Transport)(nil)

// Client returns an *http.Client using a default urlfetch Transport. This
// client will check the validity of SSL certificates.
//
// Any deadline of the provided context will be used for requests through this client.
// If the client does not have a deadline, then an App Engine default of 60 second is used.
func Client(ctx context.Context) *http.Client {
	return &http.Client{
		Transport: &Transport{
			Context: ctx,
		},
	}
}

type bodyReader struct {
	content   []byte
	truncated bool
	closed    bool
}

// ErrTruncatedBody is the error returned after the final Read() from a
// response's Body if the body has been truncated by App Engine's proxy.
var ErrTruncatedBody = errors.New("urlfetch: truncated body")

func statusCodeToText(code int) string {
	if t := http.StatusText(code); t != "" {
		return t
	}
	return strconv.Itoa(code)
}

func (br *bodyReader) Read(p []byte) (n int, err error) {
	if br.closed {
		if br.truncated {
			return 0, ErrTruncatedBody
		}
		return 0, io.EOF
	}
	n = copy(p, br.content)
	if n > 0 {
		br.content = br.content[n:]
		return
	}
	if br.truncated {
		br.closed = true
		return 0, ErrTruncatedBody
	}
	return 0, io.EOF
}

func (br *bodyReader) Close() error {
	br.closed = true
	br.content = nil
	return nil
}

// A map of the URL Fetch-accepted methods that take a request body.
var methodAcceptsRequestBody = map[string]bool{
	"POST":  true,
	"PUT":   true,
	"PATCH": true,
}

// urlString returns a valid string given a URL. This function is necessary because
// the String method of URL doesn't correctly handle URLs with non-empty Opaque values.
// See http://code.google.com/p/go/issues/detail?id=4860.
func urlString(u *url.URL) string {
	if u.Opaque == "" || strings.HasPrefix(u.Opaque, "//") {
		return u.String()
	}
	aux := *u
	aux.Opaque = "//" + aux.Host + aux.Opaque
	return aux.String()
}

// RoundTrip issues a single HTTP request and returns its response. Per the
// http.RoundTripper interface, RoundTrip only returns an error if there
// was an unsupported request or the URL Fetch proxy fails.
// Note that HTTP response codes such as 5xx, 403, 404, etc are not
// errors as far as the transport is concerned and will be returned
// with err set to nil.
func (t *Transport) RoundTrip(req *http.Request) (res *http.Response, err error) {
	methNum, ok := pb.URLFetchRequest_RequestMethod_value[req.Method]
	if !ok {
		return nil, fmt.Errorf("urlfetch: unsupported HTTP method %q", req.Method)
	}

	method := pb.URLFetchRequest_RequestMethod(methNum)

	freq := &pb.URLFetchRequest{
		Method:                        &method,
		Url:                           proto.String(urlString(req.URL)),
		FollowRedirects:               proto.Bool(false), // http.Client's responsibility
		MustValidateServerCertificate: proto.Bool(!t.AllowInvalidServerCertificate),
	}
	if deadline, ok := t.Context.Deadline(); ok {
		freq.Deadline = proto.Float64(deadline.Sub(time.Now()).Seconds())
	}

	for k, vals := range req.Header {
		for _, val := range vals {
			freq.Header = append(freq.Header, &pb.URLFetchRequest_Header{
				Key:   proto.String(k),
				Value: proto.String(val),
			})
		}
	}
	if methodAcceptsRequestBody[req.Method] && req.Body != nil {
		// Avoid a []byte copy if req.Body has a Bytes method.
		switch b := req.Body.(type) {
		case interface {
			Bytes() []byte
		}:
			freq.Payload = b.Bytes()
		default:
			freq.Payload, err = ioutil.ReadAll(req.Body)
			if err != nil {
				return nil, err
			}
		}
	}

	fres := &pb.URLFetchResponse{}
	if err := internal.Call(t.Context, "urlfetch", "Fetch", freq, fres); err != nil {
		return nil, err
	}

	res = &http.Response{}
	res.StatusCode = int(*fres.StatusCode)
	res.Status = fmt.Sprintf("%d %s", res.StatusCode, statusCodeToText(res.StatusCode))
	res.Header = make(http.Header)
	res.Request = req

	// Faked:
	res.ProtoMajor = 1
	res.ProtoMinor = 1
	res.Proto = "HTTP/1.1"
	res.Close = true

	for _, h := range fres.Header {
		hkey := http.CanonicalHeaderKey(*h.Key)
		hval := *h.Value
		if hkey == "Content-Length" {
			// Will get filled in below for all but HEAD requests.
			if req.Method == "HEAD" {
				res.ContentLength, _ = strconv.ParseInt(hval, 10, 64)
			}
			continue
		}
		res.Header.Add(hkey, hval)
	}

	if req.Method != "HEAD" {
		res.ContentLength = int64(len(fres.Content))
	}

	truncated := fres.GetContentWasTruncated()
	res.Body = &bodyReader{content: fres.Content, truncated: truncated}
	return
}

func init() {
	internal.RegisterErrorCodeMap("urlfetch", pb.URLFetchServiceError_ErrorCode_name)
	internal.RegisterTimeoutErrorCode("urlfetch", int32(pb.URLFetchServiceError_DEADLINE_EXCEEDED))
}
<|endoftext|>


<commit_before>package fire

import (
	"errors"
	"reflect"

	"github.com/asaskevich/govalidator"
	"gopkg.in/mgo.v2/bson"
)

// Model is the main interface implemented by every fire model embedding Base.
type Model interface {
	ID() bson.ObjectId
	Meta() *Meta

	MustGet(string) interface{}
	MustSet(string, interface{})

	initialize(Model)
}

// The ValidatableModel interface can be additionally implemented to provide
// a custom validation method that is used by the Validate function.
type ValidatableModel interface {
	Model

	// The Validate method that should return normal errors about invalid fields.
	Validate() error
}

// Validate uses the govalidator package to validate the model based on
// the "valid" struct tags. If the passed model also implements the
// ValidatableModel interface, Validate method will be invoked after the struct
// validation.
func Validate(m Model) error {
	// validate id
	if !m.ID().Valid() {
		return errors.New("Invalid ID")
	}

	// invoke custom validation method when available
	if validatableModel, ok := m.(ValidatableModel); ok {
		err := validatableModel.Validate()
		if err != nil {
			return err
		}
	}

	// validate model
	_, err := govalidator.ValidateStruct(m)
	if err != nil {
		return err
	}

	return nil
}

// Init initializes the internals of a model and should be called before using
// a newly created Model.
func Init(model Model) Model {
	model.initialize(model)
	return model
}

// InitSlice initializes all models in a slice of the form *[]*Post and returns
// a new slice that contains all initialized models.
func InitSlice(ptr interface{}) []Model {
	// get slice
	slice := reflect.ValueOf(ptr).Elem()

	// make model slice
	models := make([]Model, slice.Len())

	// iterate over entries
	for i := 0; i < slice.Len(); i++ {
		m := Init(slice.Index(i).Interface().(Model))
		models[i] = m
	}

	return models
}

// C is a short-hand function to extract the collection of a model.
func C(m Model) string {
	return Init(m).Meta().Collection
}

// F is a short-hand function to extract the BSON field name of a model
// attribute.
func F(m Model, field string) string {
	return Init(m).Meta().MustFindField(field).BSONName
}

// A is a short-hand function to extract the JSON attribute name of model
// attribute.
func A(m Model, field string) string {
	return Init(m).Meta().MustFindField(field).JSONName
}

// Base is the base for every fire model.
type Base struct {
	DocID bson.ObjectId `json:"-" bson:"_id,omitempty"`

	model interface{}
	meta  *Meta
}

// ID returns the models id.
func (b *Base) ID() bson.ObjectId {
	return b.DocID
}

// MustGet returns the value of the given field.
//
// Note: MustGet will return the value of the first field that has a matching
// Name, JSONName, or BSONName and will panic if no field can be found.
func (b *Base) MustGet(name string) interface{} {
	field := b.meta.MustFindField(name)

	// read value from model struct
	structField := reflect.ValueOf(b.model).Elem().Field(field.index)
	return structField.Interface()
}

// MustSet will set the given field to the the passed valued.
//
// Note: MustSet will set the value of the first field that has a matching Name,
// JSONName, or BSONName and will panic if no field can been found. The method
// will also panic if the type of the field and the passed value do not match.
func (b *Base) MustSet(name string, value interface{}) {
	field := b.meta.MustFindField(name)

	// set the value on model struct
	reflect.ValueOf(b.model).Elem().Field(field.index).Set(reflect.ValueOf(value))
}

// Meta returns the models Meta structure.
func (b *Base) Meta() *Meta {
	return b.meta
}

func (b *Base) initialize(model Model) {
	b.model = model

	// set id if missing
	if !b.DocID.Valid() {
		b.DocID = bson.NewObjectId()
	}

	// assign meta
	b.meta = NewMeta(model)
}
<commit_msg>fix typo<commit_after>package fire

import (
	"errors"
	"reflect"

	"github.com/asaskevich/govalidator"
	"gopkg.in/mgo.v2/bson"
)

// Model is the main interface implemented by every fire model embedding Base.
type Model interface {
	ID() bson.ObjectId
	Meta() *Meta

	MustGet(string) interface{}
	MustSet(string, interface{})

	initialize(Model)
}

// The ValidatableModel interface can be additionally implemented to provide
// a custom validation method that is used by the Validate function.
type ValidatableModel interface {
	Model

	// The Validate method that should return normal errors about invalid fields.
	Validate() error
}

// Validate uses the govalidator package to validate the model based on
// the "valid" struct tags. If the passed model also implements the
// ValidatableModel interface, Validate method will be invoked after the struct
// validation.
func Validate(m Model) error {
	// validate id
	if !m.ID().Valid() {
		return errors.New("Invalid ID")
	}

	// invoke custom validation method when available
	if validatableModel, ok := m.(ValidatableModel); ok {
		err := validatableModel.Validate()
		if err != nil {
			return err
		}
	}

	// validate model
	_, err := govalidator.ValidateStruct(m)
	if err != nil {
		return err
	}

	return nil
}

// Init initializes the internals of a model and should be called before using
// a newly created Model.
func Init(model Model) Model {
	model.initialize(model)
	return model
}

// InitSlice initializes all models in a slice of the form *[]*Post and returns
// a new slice that contains all initialized models.
func InitSlice(ptr interface{}) []Model {
	// get slice
	slice := reflect.ValueOf(ptr).Elem()

	// make model slice
	models := make([]Model, slice.Len())

	// iterate over entries
	for i := 0; i < slice.Len(); i++ {
		m := Init(slice.Index(i).Interface().(Model))
		models[i] = m
	}

	return models
}

// C is a short-hand function to extract the collection of a model.
func C(m Model) string {
	return Init(m).Meta().Collection
}

// F is a short-hand function to extract the BSON field name of a model
// attribute.
func F(m Model, field string) string {
	return Init(m).Meta().MustFindField(field).BSONName
}

// A is a short-hand function to extract the JSON attribute name of a model
// attribute.
func A(m Model, field string) string {
	return Init(m).Meta().MustFindField(field).JSONName
}

// Base is the base for every fire model.
type Base struct {
	DocID bson.ObjectId `json:"-" bson:"_id,omitempty"`

	model interface{}
	meta  *Meta
}

// ID returns the models id.
func (b *Base) ID() bson.ObjectId {
	return b.DocID
}

// MustGet returns the value of the given field.
//
// Note: MustGet will return the value of the first field that has a matching
// Name, JSONName, or BSONName and will panic if no field can be found.
func (b *Base) MustGet(name string) interface{} {
	field := b.meta.MustFindField(name)

	// read value from model struct
	structField := reflect.ValueOf(b.model).Elem().Field(field.index)
	return structField.Interface()
}

// MustSet will set the given field to the the passed valued.
//
// Note: MustSet will set the value of the first field that has a matching Name,
// JSONName, or BSONName and will panic if no field can been found. The method
// will also panic if the type of the field and the passed value do not match.
func (b *Base) MustSet(name string, value interface{}) {
	field := b.meta.MustFindField(name)

	// set the value on model struct
	reflect.ValueOf(b.model).Elem().Field(field.index).Set(reflect.ValueOf(value))
}

// Meta returns the models Meta structure.
func (b *Base) Meta() *Meta {
	return b.meta
}

func (b *Base) initialize(model Model) {
	b.model = model

	// set id if missing
	if !b.DocID.Valid() {
		b.DocID = bson.NewObjectId()
	}

	// assign meta
	b.meta = NewMeta(model)
}
<|endoftext|>


<commit_before>package main

import "encoding/json"

type Image struct {
	path    string
	Caption string `json:"caption" db:"caption"`
	Credits string `json:"credits" db:"credits"`
	UnitId  int    `json:"unit_id" db:"unit_id"`
	ID      int    `json:"id" db:"id"`
}

type RotateImage struct {
	Basepath string `json:"basepath" db:"basepath"`
	Num      int    `json:"num" db:"num"`
	Caption  string `json:"caption" db:"caption"`
	Credits  string `json:"credits" db:"credits"`
	ID       int    `json:"id" db:"id"`
}

type Row struct {
	LeftMarkdown  string `json:"left_markdown" db:"left_markdown"`
	LeftHtml      string `json:"left_html" db:"left_html"`
	RightMarkdown string `json:"right_markdown" db:"right_markdown"`
	RightHtml     string `json:"right_html" db:"right_html"`
	ID            int    `json:"id" db:"row_id"`
}

type Page struct {
	Title  string `json:"title" db:"title"`
	Rows   []Row  `json:"rows" db:"rows"`
	UnitID int    `json:"unit_id" db:"unit_id"`
	ID     int    `json:"id" db:"id"`
}

type Unit struct {
	Title       string `json:"title" db:"title"`
	UnitImageID int    `json:"rotate_image_id" db:"rotate_image_id"`
	PageIds     []int  `json:"pageids" db:"pageids"`
	Published   bool   `json:"published" db:"published"`
	UserId      int    `json:"userid" db:"userid"`
	ID          int    `json:"id" db:"id"`
}

func (r *Image) UnmarshalJSON(data []byte) error {
	type Alias Image
	aux := &struct {
		MyID int `json:"image_id"`
		*Alias
	}{
		Alias: (*Alias)(r),
	}
	if err := json.Unmarshal(data, &aux); err != nil {
		return err
	}
	if r.ID == 0 {
		r.ID = aux.MyID
	}
	return nil
}

func (r *RotateImage) UnmarshalJSON(data []byte) error {
	type Alias RotateImage
	aux := &struct {
		MyID int `json:"rotate_image_id"`
		*Alias
	}{
		Alias: (*Alias)(r),
	}
	if err := json.Unmarshal(data, &aux); err != nil {
		return err
	}
	if r.ID == 0 {
		r.ID = aux.MyID
	}
	return nil
}

func (r *Row) UnmarshalJSON(data []byte) error {
	type Alias Row
	aux := &struct {
		MyID int `json:"row_id"`
		*Alias
	}{
		Alias: (*Alias)(r),
	}
	if err := json.Unmarshal(data, &aux); err != nil {
		return err
	}
	if r.ID == 0 {
		r.ID = aux.MyID
	}
	return nil
}

func (r *Page) UnmarshalJSON(data []byte) error {
	type Alias Page
	aux := &struct {
		MyID int `json:"page_id"`
		*Alias
	}{
		Alias: (*Alias)(r),
	}
	if err := json.Unmarshal(data, &aux); err != nil {
		return err
	}
	if r.ID == 0 {
		r.ID = aux.MyID
	}
	return nil
}

func (r *Unit) UnmarshalJSON(data []byte) error {
	type Alias Unit
	aux := &struct {
		MyID int `json:"unit_id"`
		*Alias
	}{
		Alias: (*Alias)(r),
	}
	if err := json.Unmarshal(data, &aux); err != nil {
		return err
	}
	if r.ID == 0 {
		r.ID = aux.MyID
	}
	return nil
}
<commit_msg>change model to work with frontend<commit_after>package main

import "encoding/json"

type Image struct {
	path    string
	Caption string `json:"caption" db:"caption"`
	Credits string `json:"credits" db:"credits"`
	UnitId  int    `json:"unit_id" db:"unit_id"`
	ID      int    `json:"id" db:"id"`
}

type RotateImage struct {
	Basepath string `json:"basepath" db:"basepath"`
	Num      int    `json:"num" db:"num"`
	Caption  string `json:"caption" db:"caption"`
	Credits  string `json:"credits" db:"credits"`
	ID       int    `json:"id" db:"id"`
}

type Row struct {
	LeftMarkdown  string `json:"left_markdown" db:"left_markdown"`
	LeftHtml      string `json:"left_html" db:"left_html"`
	RightMarkdown string `json:"right_markdown" db:"right_markdown"`
	RightHtml     string `json:"right_html" db:"right_html"`
	ID            int    `json:"id" db:"row_id"`
}

type Page struct {
	Title  string `json:"title" db:"title"`
	Rows   []Row  `json:"rows" db:"rows"`
	UnitID int    `json:"unit_id" db:"unit_id"`
	ID     int    `json:"id" db:"id"`
}

type Unit struct {
	Title       string `json:"title" db:"title"`
	UnitImageID int    `json:"rotateImageId" db:"rotate_image_id"`
	PageIds     []int  `json:"pageIds" db:"pageids"`
	Published   bool   `json:"published" db:"published"`
	UserId      int    `json:"userId" db:"userid"`
	ID          int    `json:"id" db:"id"`
}

func (r *Image) UnmarshalJSON(data []byte) error {
	type Alias Image
	aux := &struct {
		MyID int `json:"image_id"`
		*Alias
	}{
		Alias: (*Alias)(r),
	}
	if err := json.Unmarshal(data, &aux); err != nil {
		return err
	}
	if r.ID == 0 {
		r.ID = aux.MyID
	}
	return nil
}

func (r *RotateImage) UnmarshalJSON(data []byte) error {
	type Alias RotateImage
	aux := &struct {
		MyID int `json:"rotate_image_id"`
		*Alias
	}{
		Alias: (*Alias)(r),
	}
	if err := json.Unmarshal(data, &aux); err != nil {
		return err
	}
	if r.ID == 0 {
		r.ID = aux.MyID
	}
	return nil
}

func (r *Row) UnmarshalJSON(data []byte) error {
	type Alias Row
	aux := &struct {
		MyID int `json:"row_id"`
		*Alias
	}{
		Alias: (*Alias)(r),
	}
	if err := json.Unmarshal(data, &aux); err != nil {
		return err
	}
	if r.ID == 0 {
		r.ID = aux.MyID
	}
	return nil
}

func (r *Page) UnmarshalJSON(data []byte) error {
	type Alias Page
	aux := &struct {
		MyID int `json:"page_id"`
		*Alias
	}{
		Alias: (*Alias)(r),
	}
	if err := json.Unmarshal(data, &aux); err != nil {
		return err
	}
	if r.ID == 0 {
		r.ID = aux.MyID
	}
	return nil
}

func (r *Unit) UnmarshalJSON(data []byte) error {
	type Alias Unit
	aux := &struct {
		MyID int `json:"unit_id"`
		*Alias
	}{
		Alias: (*Alias)(r),
	}
	if err := json.Unmarshal(data, &aux); err != nil {
		return err
	}
	if r.ID == 0 {
		r.ID = aux.MyID
	}
	return nil
}
<|endoftext|>


<commit_before>/*

   Copyright 2016 Wenhui Shen <www.webx.top>

   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 pprof

import (
	"net/http/pprof"

	"github.com/webx-top/echo"
)

var typeNames = []string{`heap`, `goroutine`, `block`, `threadcreate`, `allocs`, `mutex`}

// Wrap adds several routes from package `net/http/pprof` to *gin.Engine object
func Wrap(router *echo.Echo) {

	router.Get("/debug/pprof/", pprof.Index)
	for _, name := range typeNames {
		router.Get("/debug/pprof/"+name, pprof.Handler(name))
	}
	router.Get("/debug/pprof/cmdline", pprof.Cmdline)
	router.Get("/debug/pprof/profile", pprof.Profile)
	router.Get("/debug/pprof/symbol", pprof.Symbol)
	router.Get("/debug/pprof/trace", pprof.Trace)
}

// Wrapper make sure we are backward compatible
var Wrapper = Wrap
<commit_msg>update<commit_after>/*

   Copyright 2016 Wenhui Shen <www.webx.top>

   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 pprof

import (
	"net/http/pprof"

	"github.com/webx-top/echo"
)

var typeNames = []string{`heap`, `goroutine`, `block`, `threadcreate`, `allocs`, `mutex`}

// Wrap adds several routes from package `net/http/pprof` to *gin.Engine object
func Wrap(router *echo.Echo) {
	RegisterRoute(router.Group("/debug"))
}

// Wrapper make sure we are backward compatible
var Wrapper = Wrap

func RegisterRoute(router echo.RouteRegister) {
	router.Get("/pprof/", pprof.Index)
	for _, name := range typeNames {
		router.Get("/pprof/"+name, pprof.Handler(name))
	}
	router.Get("/pprof/cmdline", pprof.Cmdline)
	router.Get("/pprof/profile", pprof.Profile)
	router.Get("/pprof/symbol", pprof.Symbol)
	router.Get("/pprof/trace", pprof.Trace)
}
<|endoftext|>


<commit_before>package handlers

import (
	"fmt"
	"os"
	"io"
	"path"
	"strings"
	"bytes"
	"net/url"

	"github.com/coreos/go-etcd/etcd"
	"github.com/headzoo/etcdsh/etcdsh"
	"github.com/headzoo/etcdsh/config"
	"github.com/bobappleyard/readline"
	"github.com/headzoo/etcdsh/parser"
	"github.com/flynn/go-shlex"
)

// Controller stores handlers and calls them.
type Controller struct {
	wdir                  string
	wdirKeys              []string
	handlers              HandlerMap
	config                *config.Config
	client                *etcd.Client
	stdout, stderr, stdin *os.File
	prompter              *parser.Prompt
}

// Create a new Controller.
func NewController(conf *config.Config, client *etcd.Client, stdout, stderr, stdin *os.File) *Controller {
	c := &Controller{
		config: conf,
		client: client,
		stdout: stdout,
		stdin: stdin,
		stderr: stderr,
		wdir: "/",
		handlers: make(HandlerMap),
		prompter: parser.NewPrompt(),
	}

	c.prompter.AddFormatter('w', func() string {
			return c.wdir
		})
	c.prompter.AddFormatter('W', func() string {
			return path.Base(c.wdir)
		})
	c.prompter.AddFormatter('v', func() string {
			return etcdsh.Version
		})
	c.prompter.AddFormatter('m', func() string {
			u, err := url.Parse(conf.Machine)
			if err == nil {
				return u.Host
			} else {
				return conf.Machine
			}
		})

	return c
}

// Starts the controller.
func (c *Controller) Start() int {
	c.welcome()
	c.ChangeWorkingDir("/")

	readline.Completer = c.filenameCompleter
	buffer := bytes.NewBufferString("")
	prompt := ""

	for {
		if buffer.Len() == 0 {
			prompt = c.ps1()
		} else {
			prompt = c.ps2()
		}

		line, err := readline.String(prompt)
		if err == io.EOF {
			break
		}
		if err != nil {
			panic(err)
		}

		line = strings.TrimSpace(line)
		if strings.ToLower(line) == "q" || strings.ToLower(line) == "exit" {
			return 0
		}
		if strings.HasSuffix(line, "\\") {
			buffer.WriteString(strings.TrimSuffix(line, "\\") + "\n")
		} else {
			if buffer.Len() > 0 {
				buffer.WriteString(line)
				line = buffer.String()
				buffer.Reset()
			}

			parts, err := shlex.Split(line)
			if err != nil {
				panic(err)
			}
			readline.AddHistory(line)

			in := NewInput(parts[0])
			if len(parts) > 1 {
				in.Args = parts[1:]
			}
			c.handleInput(in)
		}
	}

	return 0
}

// Client returns the etcd client
func (c *Controller) Client() *etcd.Client {
	return c.client
}

// Config returns the app configuration.
func (c *Controller) Config() *config.Config {
	return c.config
}

// Add appends a handler to the map.
func (c *Controller) Add(h Handler) {
	c.handlers[h.Command()] = h
}

// Handlers returns the complete list of added handlers.
func (c *Controller) Handlers() HandlerMap {
	return c.handlers
}

// WorkingDir returns the working directory. The value of a is appended to the value.
func (c *Controller) WorkingDir(a string) string {
	a = strings.Replace(a, "\n", "", -1)
	wdir := c.wdir + "/" + a
	return path.Clean(wdir)
}

// ChangeWorkingDir changes the current working directory.
func (c *Controller) ChangeWorkingDir(wdir string) string {
	if strings.HasPrefix(wdir, "/") {
		c.wdir = wdir
	} else {
		c.wdir = c.WorkingDir("/"+wdir)
	}

	resp, err := c.client.Get(c.wdir, true, true)
	if err != nil {
		panic(err)
	}

	count := c.getNodeCount(resp.Node, 0)
	c.wdirKeys = make([]string, count)
	c.addNodeToWDir(resp.Node, 0)

	return c.wdir
}

// addNodeToWDir adds the keys from all child nodes to the working dir keys.
func (c *Controller) addNodeToWDir(node *etcd.Node, index int) int {
	for _, n := range node.Nodes {
		c.wdirKeys[index] = n.Key
		index++
		index = c.addNodeToWDir(n, index)
	}

	return index
}

// getNodeCount recursively counts the child nodes in node.
func (c *Controller) getNodeCount(node *etcd.Node, count int) int {
	for _, n := range node.Nodes {
		count++
		count = c.getNodeCount(n, count)
	}

	return count
}

// ps1 returns the first type of prompt.
func (c *Controller) ps1() string {
	prompt, _ := c.prompter.Parse(c.config.PS1)
	return prompt
}

// ps2 returns the second type of prompt.
func (c *Controller) ps2() string {
	prompt, _ := c.prompter.Parse(c.config.PS2)
	return prompt
}

// hasHandler returns whether a command handler has been added with the given id.
func (c *Controller) hasHandler(id string) bool {
	_, ok := c.handlers[id]
	return ok
}

// Handles the user input.
func (c *Controller) handleInput(i *Input) {
	handler, ok := c.handlers[i.Cmd]
	if !ok {
		fmt.Fprintln(c.stderr, fmt.Sprintf("The command %s does not exist.", i.Cmd))
	} else if !handler.Validate(i) {
		fmt.Fprintln(c.stderr, fmt.Sprintf("Invalid use of command, use: %s", handler.Syntax()))
	} else {
		output, err := handler.Handle(i)
		if err == nil {
			fmt.Fprint(c.stdout, output)
		} else {
			fmt.Fprintln(c.stderr, err)
		}
	}
}

// filenameCompleter is a callback function for the readline.Completer variable.
func (c *Controller) filenameCompleter(query, ctx string) []string {
	var keys []string
	for _, key := range c.wdirKeys {
		base := strings.TrimPrefix(key, "/")
		if strings.HasPrefix(base, query) {
			keys = append(keys, base)
		}
	}

	return keys
}

// Welcome displays a welcome message.
func (c *Controller) welcome() {
	fmt.Fprintln(c.stdout, "Interactive etcd shell started.")
	if c.hasHandler("help") {
		fmt.Fprintln(c.stdout, "Type 'help' for a list of commands.")
	}
	fmt.Fprintln(c.stdout, "Type 'exit' or 'q' to quit.")
	fmt.Fprintln(c.stdout, "")
}
<commit_msg>Formatting<commit_after>package handlers

import (
	"fmt"
	"os"
	"io"
	"path"
	"strings"
	"bytes"
	"net/url"

	"github.com/coreos/go-etcd/etcd"
	"github.com/headzoo/etcdsh/etcdsh"
	"github.com/headzoo/etcdsh/config"
	"github.com/bobappleyard/readline"
	"github.com/headzoo/etcdsh/parser"
	"github.com/flynn/go-shlex"
)

// Controller stores handlers and calls them.
type Controller struct {
	wdir                  string
	wdirKeys              []string
	handlers              HandlerMap
	config                *config.Config
	client                *etcd.Client
	stdout, stderr, stdin *os.File
	prompter              *parser.Prompt
}

// Create a new Controller.
func NewController(conf *config.Config, client *etcd.Client, stdout, stderr, stdin *os.File) *Controller {
	c := &Controller{
		config: conf,
		client: client,
		stdout: stdout,
		stdin: stdin,
		stderr: stderr,
		wdir: "/",
		handlers: make(HandlerMap),
		prompter: parser.NewPrompt(),
	}

	c.prompter.AddFormatter('w', func() string {
			return c.wdir
		})
	c.prompter.AddFormatter('W', func() string {
			return path.Base(c.wdir)
		})
	c.prompter.AddFormatter('v', func() string {
			return etcdsh.Version
		})
	c.prompter.AddFormatter('m', func() string {
			u, err := url.Parse(conf.Machine)
			if err == nil {
				return u.Host
			} else {
				return conf.Machine
			}
		})

	return c
}

// Starts the controller.
func (c *Controller) Start() int {
	c.welcome()
	c.ChangeWorkingDir("/")

	readline.Completer = c.filenameCompleter
	buffer := bytes.NewBufferString("")
	prompt := ""

	for {
		if buffer.Len() == 0 {
			prompt = c.ps1()
		} else {
			prompt = c.ps2()
		}

		line, err := readline.String(prompt)
		if err == io.EOF {
			break
		}
		if err != nil {
			panic(err)
		}

		line = strings.TrimSpace(line)
		if strings.ToLower(line) == "q" || strings.ToLower(line) == "exit" {
			return 0
		}
		if strings.HasSuffix(line, "\\") {
			buffer.WriteString(strings.TrimSuffix(line, "\\") + "\n")
		} else {
			if buffer.Len() > 0 {
				buffer.WriteString(line)
				line = buffer.String()
				buffer.Reset()
			}

			parts, err := shlex.Split(line)
			if err != nil {
				panic(err)
			}
			readline.AddHistory(line)

			in := NewInput(parts[0])
			if len(parts) > 1 {
				in.Args = parts[1:]
			}
			c.handleInput(in)
		}
	}

	return 0
}

// Client returns the etcd client
func (c *Controller) Client() *etcd.Client {
	return c.client
}

// Config returns the app configuration.
func (c *Controller) Config() *config.Config {
	return c.config
}

// Add appends a handler to the map.
func (c *Controller) Add(h Handler) {
	c.handlers[h.Command()] = h
}

// Handlers returns the complete list of added handlers.
func (c *Controller) Handlers() HandlerMap {
	return c.handlers
}

// WorkingDir returns the working directory. The value of a is appended to the value.
func (c *Controller) WorkingDir(a string) string {
	a = strings.Replace(a, "\n", "", -1)
	wdir := c.wdir + "/" + a
	return path.Clean(wdir)
}

// ChangeWorkingDir changes the current working directory.
func (c *Controller) ChangeWorkingDir(wdir string) string {
	if strings.HasPrefix(wdir, "/") {
		c.wdir = wdir
	} else {
		c.wdir = c.WorkingDir("/"+wdir)
	}

	resp, err := c.client.Get(c.wdir, true, true)
	if err != nil {
		panic(err)
	}

	count := c.getNodeCount(resp.Node, 0)
	c.wdirKeys = make([]string, count)
	c.addNodeToWorkingDirKeys(resp.Node, 0)

	return c.wdir
}

// addNodeToWDir adds the keys from all child nodes to the working dir keys.
func (c *Controller) addNodeToWorkingDirKeys(node *etcd.Node, index int) int {
	for _, n := range node.Nodes {
		c.wdirKeys[index] = n.Key
		index++
		index = c.addNodeToWorkingDirKeys(n, index)
	}

	return index
}

// getNodeCount recursively counts the child nodes in node.
func (c *Controller) getNodeCount(node *etcd.Node, count int) int {
	for _, n := range node.Nodes {
		count++
		count = c.getNodeCount(n, count)
	}

	return count
}

// ps1 returns the first type of prompt.
func (c *Controller) ps1() string {
	prompt, _ := c.prompter.Parse(c.config.PS1)
	return prompt
}

// ps2 returns the second type of prompt.
func (c *Controller) ps2() string {
	prompt, _ := c.prompter.Parse(c.config.PS2)
	return prompt
}

// hasHandler returns whether a command handler has been added with the given id.
func (c *Controller) hasHandler(id string) bool {
	_, ok := c.handlers[id]
	return ok
}

// Handles the user input.
func (c *Controller) handleInput(i *Input) {
	handler, ok := c.handlers[i.Cmd]
	if !ok {
		fmt.Fprintln(c.stderr, fmt.Sprintf("The command %s does not exist.", i.Cmd))
	} else if !handler.Validate(i) {
		fmt.Fprintln(c.stderr, fmt.Sprintf("Invalid use of command, use: %s", handler.Syntax()))
	} else {
		output, err := handler.Handle(i)
		if err == nil {
			fmt.Fprint(c.stdout, output)
		} else {
			fmt.Fprintln(c.stderr, err)
		}
	}
}

// filenameCompleter is a callback function for the readline.Completer variable.
func (c *Controller) filenameCompleter(query, ctx string) []string {
	var keys []string
	for _, key := range c.wdirKeys {
		base := strings.TrimPrefix(key, "/")
		if strings.HasPrefix(base, query) {
			keys = append(keys, base)
		}
	}

	return keys
}

// Welcome displays a welcome message.
func (c *Controller) welcome() {
	fmt.Fprintln(c.stdout, "Interactive etcd shell started.")
	if c.hasHandler("help") {
		fmt.Fprintln(c.stdout, "Type 'help' for a list of commands.")
	}
	fmt.Fprintln(c.stdout, "Type 'exit' or 'q' to quit.")
	fmt.Fprintln(c.stdout, "")
}
<|endoftext|>