<commit_before>package main

import (
	"encoding/json"
	"log"
	"net/http"
	"os"

	"code.google.com/p/go-uuid/uuid"
	"github.com/codegangsta/negroni"
	"github.com/joho/godotenv"
	"github.com/julienschmidt/httprouter"
	"github.com/unrolled/render"

	"github.com/wantedly/risu/registry"
	"github.com/wantedly/risu/schema"
	"github.com/wantedly/risu/shell"
)

const (
	DefaultSourceBaseDir = "/var/risu/src/github.com/"
)

var (
	ren = render.New()
	reg = registry.NewRegistry(os.Getenv("REGISTRY_BACKEND"), os.Getenv("REGISTRY_ENDPOINT"))
)

func loadEnv() {
	err := godotenv.Load()
	if err != nil {
		log.Print("Error loading .env file")
	}
}

func create(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	defer r.Body.Close()
	var opts schema.BuildCreateOpts
	err := json.NewDecoder(r.Body).Decode(&opts)
	if err != nil {
		log.Fatal(err)
		ren.JSON(w, http.StatusInternalServerError, map[string]string{"status": "internal server error"})
		return
	}

	build, err := reg.Create(opts)
	if err != nil {
		log.Fatal(err)
		ren.JSON(w, http.StatusInternalServerError, map[string]string{"status": "internal server error"})
		return
	}
	ren.JSON(w, http.StatusAccepted, build)

	go func() {
		if err := checkoutGitRepository(build, DefaultSourceBaseDir); err != nil {
			return
		}

		if err := dockerBuild(build); err != nil {
			if err := reg.Set(build, schema.BuildUpdateOpts{Status: "failed to build"}); err != nil {
				printLog(build, err.Error())
			}

			printLog(build, err.Error())
			return
		}
		if err := reg.Set(build, schema.BuildUpdateOpts{Status: "build completed and pushing"}); err != nil {
			printLog(build, err.Error())
		}

		if err := dockerPush(build); err != nil {
			if err := reg.Set(build, schema.BuildUpdateOpts{Status: "failed to push"}); err != nil {
				printLog(build, err.Error())
			}

			printLog(build, err.Error())
			return
		}
		if err := reg.Set(build, schema.BuildUpdateOpts{Status: "build completed and pushed"}); err != nil {
			printLog(build, err.Error())
		}

		if err := refreshCache(build); err != nil {
			printLog(build, err.Error())
			return
		}
	}()
}

func root(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
	ren.JSON(w, http.StatusOK, map[string]string{"status": "ok"})
}

func index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
	builds, err := reg.List()
	if err != nil {
		ren.JSON(w, http.StatusInternalServerError, map[string]string{"status": "internal server error"})
		return
	}
	ren.JSON(w, http.StatusOK, builds)
}

func show(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	id := ps.ByName("id")
	uuid := uuid.Parse(id)
	build, err := reg.Get(uuid)
	if err != nil {
		ren.JSON(w, http.StatusNotFound, map[string]string{"status": "not found"})
		return
	}
	ren.JSON(w, http.StatusOK, build)
}

// Clone run "git clone <repository_URL>" and "git checkout branch"
func checkoutGitRepository(build schema.Build, dir string) error {
	if _, err := os.Stat(dir); err != nil {
		if err := os.MkdirAll(dir, 0755); err != nil {
			log.Fatal(err)
		}
	}

	// htpps://<token>@github.com/<SourceRepo>.git
	cloneURL := "https://" + os.Getenv("GITHUB_ACCESS_TOKEN") + "@github.com/" + build.SourceRepo + ".git"

	clonePath := dir + build.SourceRepo

	// debug
	printLog(build, clonePath)

	shell.Command("git", "clone", cloneURL, clonePath)
	shell.CommandInDir(clonePath, "git", "fetch", "origin", build.SourceBranch)
	shell.CommandInDir(clonePath, "git", "checkout", "remotes/origin/"+build.SourceBranch, "-f")
	shell.CommandInDir(clonePath, "git", "submodule", "update", "--init")
	return nil
}

func refreshCache(build schema.Build) error {
	saveBaseDir, err := extractCache(build)

	if err != nil {
		return err
	}

	if err = putCache(build, saveBaseDir); err != nil {
		return err
	}

	return nil
}

func setUpServer() *negroni.Negroni {
	router := httprouter.New()
	router.GET("/", root)
	router.GET("/builds", index)
	router.GET("/builds/:id", show)
	router.POST("/builds", create)

	n := negroni.Classic()
	n.UseHandler(router)
	return n
}

func main() {
	loadEnv()
	if os.Getenv("GITHUB_ACCESS_TOKEN") == "" {
		log.Fatal("Please provide 'GITHUB_ACCESS_TOKEN' through environment")
	}
	n := setUpServer()
	n.Run(":8080")
}
<commit_msg>Print log if repository checkout is failed<commit_after>package main

import (
	"encoding/json"
	"log"
	"net/http"
	"os"

	"code.google.com/p/go-uuid/uuid"
	"github.com/codegangsta/negroni"
	"github.com/joho/godotenv"
	"github.com/julienschmidt/httprouter"
	"github.com/unrolled/render"

	"github.com/wantedly/risu/registry"
	"github.com/wantedly/risu/schema"
	"github.com/wantedly/risu/shell"
)

const (
	DefaultSourceBaseDir = "/var/risu/src/github.com/"
)

var (
	ren = render.New()
	reg = registry.NewRegistry(os.Getenv("REGISTRY_BACKEND"), os.Getenv("REGISTRY_ENDPOINT"))
)

func loadEnv() {
	err := godotenv.Load()
	if err != nil {
		log.Print("Error loading .env file")
	}
}

func create(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	defer r.Body.Close()
	var opts schema.BuildCreateOpts
	err := json.NewDecoder(r.Body).Decode(&opts)
	if err != nil {
		log.Fatal(err)
		ren.JSON(w, http.StatusInternalServerError, map[string]string{"status": "internal server error"})
		return
	}

	build, err := reg.Create(opts)
	if err != nil {
		log.Fatal(err)
		ren.JSON(w, http.StatusInternalServerError, map[string]string{"status": "internal server error"})
		return
	}
	ren.JSON(w, http.StatusAccepted, build)

	go func() {
		if err := checkoutGitRepository(build, DefaultSourceBaseDir); err != nil {
			return
		}

		if err := dockerBuild(build); err != nil {
			if err := reg.Set(build, schema.BuildUpdateOpts{Status: "failed to build"}); err != nil {
				printLog(build, err.Error())
			}

			printLog(build, err.Error())
			return
		}
		if err := reg.Set(build, schema.BuildUpdateOpts{Status: "build completed and pushing"}); err != nil {
			printLog(build, err.Error())
		}

		if err := dockerPush(build); err != nil {
			if err := reg.Set(build, schema.BuildUpdateOpts{Status: "failed to push"}); err != nil {
				printLog(build, err.Error())
			}

			printLog(build, err.Error())
			return
		}
		if err := reg.Set(build, schema.BuildUpdateOpts{Status: "build completed and pushed"}); err != nil {
			printLog(build, err.Error())
		}

		if err := refreshCache(build); err != nil {
			printLog(build, err.Error())
			return
		}
	}()
}

func root(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
	ren.JSON(w, http.StatusOK, map[string]string{"status": "ok"})
}

func index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
	builds, err := reg.List()
	if err != nil {
		ren.JSON(w, http.StatusInternalServerError, map[string]string{"status": "internal server error"})
		return
	}
	ren.JSON(w, http.StatusOK, builds)
}

func show(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	id := ps.ByName("id")
	uuid := uuid.Parse(id)
	build, err := reg.Get(uuid)
	if err != nil {
		ren.JSON(w, http.StatusNotFound, map[string]string{"status": "not found"})
		return
	}
	ren.JSON(w, http.StatusOK, build)
}

// Clone run "git clone <repository_URL>" and "git checkout branch"
func checkoutGitRepository(build schema.Build, dir string) error {
	if _, err := os.Stat(dir); err != nil {
		if err := os.MkdirAll(dir, 0755); err != nil {
			printLog(build, err.Error())
		}
	}

	// htpps://<token>@github.com/<SourceRepo>.git
	cloneURL := "https://" + os.Getenv("GITHUB_ACCESS_TOKEN") + "@github.com/" + build.SourceRepo + ".git"

	clonePath := dir + build.SourceRepo

	// debug
	printLog(build, clonePath)

	shell.Command("git", "clone", cloneURL, clonePath)
	shell.CommandInDir(clonePath, "git", "fetch", "origin", build.SourceBranch)
	shell.CommandInDir(clonePath, "git", "checkout", "remotes/origin/"+build.SourceBranch, "-f")
	shell.CommandInDir(clonePath, "git", "submodule", "update", "--init")
	return nil
}

func refreshCache(build schema.Build) error {
	saveBaseDir, err := extractCache(build)

	if err != nil {
		return err
	}

	if err = putCache(build, saveBaseDir); err != nil {
		return err
	}

	return nil
}

func setUpServer() *negroni.Negroni {
	router := httprouter.New()
	router.GET("/", root)
	router.GET("/builds", index)
	router.GET("/builds/:id", show)
	router.POST("/builds", create)

	n := negroni.Classic()
	n.UseHandler(router)
	return n
}

func main() {
	loadEnv()
	if os.Getenv("GITHUB_ACCESS_TOKEN") == "" {
		log.Fatal("Please provide 'GITHUB_ACCESS_TOKEN' through environment")
	}
	n := setUpServer()
	n.Run(":8080")
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
)

type rod int

const (
	RodDigging rod = iota
	RodBlink
	RodTeleportOther
	RodLightningBolt
	RodFireball
	RodFog
	RodObstruction
	RodShatter
	RodSwapping
	// below unimplemented
	RodConfusingClouds
	RodFear
	RodFreezingClouds
)

const NumRods = int(RodSwapping) + 1

func (r rod) Letter() rune {
	return '/'
}

func (r rod) Rare() bool {
	switch r {
	case RodDigging, RodTeleportOther, RodShatter, RodSwapping:
		return true
	default:
		return false
	}
}

func (r rod) String() string {
	var text string
	switch r {
	case RodDigging:
		text = "rod of digging"
	case RodBlink:
		text = "rod of blinking"
	case RodTeleportOther:
		text = "rod of teleport other"
	case RodFog:
		text = "rod of fog"
	case RodFear:
		text = "rod of fear"
	case RodFireball:
		text = "rod of fireball"
	case RodLightningBolt:
		text = "rod of lightning bolt"
	case RodObstruction:
		text = "rod of obstruction"
	case RodShatter:
		text = "rod of shatter"
	case RodSwapping:
		text = "rod of swapping"
	case RodFreezingClouds:
		text = "rod of freezing clouds"
	case RodConfusingClouds:
		text = "rod of confusing clouds"
	}
	return text
}

func (r rod) Desc() string {
	var text string
	switch r {
	case RodDigging:
		text = "digs through walls."
	case RodBlink:
		text = "makes you blink away within your line of sight."
	case RodTeleportOther:
		text = "teleports away one of your foes."
	case RodFog:
		text = "creates a dense fog that reduces your (and monster's) line of sight."
	case RodFireball:
		text = "throws a 1-radius fireball at your foes."
	case RodLightningBolt:
		text = "throws a lightning bolt through one or more enemies."
	case RodObstruction:
		text = "creates a temporary wall at targeted location."
	case RodShatter:
		text = "induces an explosion around a wall. The wall can disintegrate."
	case RodSwapping:
		text = "makes you swap positions with a targeted monster."
	case RodFear:
		text = "TODO"
	case RodFreezingClouds:
		text = "TODO"
	case RodConfusingClouds:
		text = "TODO"
	}
	return fmt.Sprintf("The %s %s. Rods sometimes regain charges as you go deeper. This rod can have up to %d charges.", r, text, r.MaxCharge())
}

type rodProps struct {
	Charge int
}

func (r rod) MaxCharge() (charges int) {
	switch r {
	case RodBlink:
		charges = 5
	case RodTeleportOther, RodDigging:
		charges = 3
	default:
		charges = 4
	}
	return charges
}

func (r rod) Rate() int {
	rate := r.MaxCharge() - 2
	if rate < 1 {
		rate = 1
	}
	return rate
}

func (r rod) MPCost() (mp int) {
	switch r {
	case RodBlink:
		mp = 3
	case RodTeleportOther, RodDigging, RodShatter:
		mp = 5
	default:
		mp = 4
	}
	return mp
}

func (r rod) Use(g *game, ev event) error {
	rods := g.Player.Rods
	if rods[r].Charge <= 0 {
		return errors.New("No charges remaining on this rod.")
	}
	if r.MPCost() > g.Player.MP {
		return errors.New("Not enough magic points for using this rod.")
	}
	var err error
	switch r {
	case RodBlink:
		err = g.EvokeRodBlink(ev)
	case RodTeleportOther:
		err = g.EvokeRodTeleportOther(ev)
	case RodLightningBolt:
		err = g.EvokeRodLightningBolt(ev)
	case RodFireball:
		err = g.EvokeRodFireball(ev)
	case RodFog:
		err = g.EvokeRodFog(ev)
	case RodDigging:
		err = g.EvokeRodDigging(ev)
	case RodObstruction:
		err = g.EvokeRodObstruction(ev)
	case RodShatter:
		err = g.EvokeRodShatter(ev)
	case RodSwapping:
		err = g.EvokeRodSwapping(ev)
	}

	if err != nil {
		return err
	}
	rods[r].Charge--
	g.Player.MP -= r.MPCost()
	g.StoryPrintf("You evoked your %s.", r)
	g.FairAction()
	ev.Renew(g, 7)
	return nil
}

func (g *game) EvokeRodBlink(ev event) error {
	if g.Player.HasStatus(StatusLignification) {
		return errors.New("You cannot blink while lignified.")
	}
	g.Blink(ev)
	return nil
}

func (g *game) Blink(ev event) {
	if g.Player.HasStatus(StatusLignification) {
		return
	}
	losPos := []position{}
	for pos, b := range g.Player.LOS {
		if !b {
			continue
		}
		if g.Dungeon.Cell(pos).T != FreeCell {
			continue
		}
		mons, _ := g.MonsterAt(pos)
		if mons.Exists() {
			continue
		}
		losPos = append(losPos, pos)
	}
	if len(losPos) == 0 {
		// should not happen
		g.Print("You could not blink.")
		return
	}
	npos := losPos[RandInt(len(losPos))]
	if npos.Distance(g.Player.Pos) <= 3 {
		// Give close cells less chance to make blinking more useful
		npos = losPos[RandInt(len(losPos))]
	}
	g.Player.Pos = npos
	g.Print("You blink away.")
	g.CollectGround()
	g.ComputeLOS()
	g.MakeMonstersAware()
}

func (g *game) EvokeRodTeleportOther(ev event) error {
	if !g.ui.ChooseTarget(g, &chooser{}) {
		return errors.New(DoNothing)
	}
	mons, _ := g.MonsterAt(g.Player.Target)
	// mons not nil (check done in the targeter)
	mons.TeleportAway(g)
	return nil
}

func (g *game) EvokeRodLightningBolt(ev event) error {
	if !g.ui.ChooseTarget(g, &chooser{flammable: true}) {
		return errors.New(DoNothing)
	}
	ray := g.Ray(g.Player.Target)
	g.Print("A lightning bolt emerges straight from the rod.")
	g.ui.LightningBoltAnimation(g, ray)
	for _, pos := range ray {
		g.Burn(pos, ev)
		mons, _ := g.MonsterAt(pos)
		if mons == nil {
			continue
		}
		mons.HP -= RandInt(21)
		if mons.HP <= 0 {
			g.Printf("%s is killed by the bolt.", mons.Kind.Indefinite(true))
			g.HandleKill(mons, ev)
		}
		g.MakeNoise(12, mons.Pos)
		mons.MakeHuntIfHurt(g)
	}
	return nil
}

func (g *game) EvokeRodFireball(ev event) error {
	if !g.ui.ChooseTarget(g, &chooser{area: true, minDist: true, flammable: true}) {
		return errors.New(DoNothing)
	}
	neighbors := g.Dungeon.FreeNeighbors(g.Player.Target)
	g.Print("A fireball emerges straight from the rod.")
	g.ui.ExplosionAnimation(g, FireExplosion, g.Player.Target)
	for _, pos := range append(neighbors, g.Player.Target) {
		g.Burn(pos, ev)
		mons, _ := g.MonsterAt(pos)
		if mons == nil {
			continue
		}
		mons.HP -= RandInt(21)
		if mons.HP <= 0 {
			g.Printf("%s is killed by the fireball.", mons.Kind.Indefinite(true))
			g.HandleKill(mons, ev)
		}
		g.MakeNoise(12, mons.Pos)
		mons.MakeHuntIfHurt(g)
	}
	return nil
}

type cloud int

const (
	CloudFog cloud = iota
	CloudFire
)

func (g *game) EvokeRodFog(ev event) error {
	g.Fog(g.Player.Pos, 3, ev)
	g.Print("You are surrounded by a dense fog.")
	return nil
}

func (g *game) Fog(at position, radius int, ev event) {
	dij := &normalPath{game: g}
	nm := Dijkstra(dij, []position{at}, radius)
	for pos := range nm {
		_, ok := g.Clouds[pos]
		if !ok {
			g.Clouds[pos] = CloudFog
			g.PushEvent(&cloudEvent{ERank: ev.Rank() + 100 + RandInt(100), EAction: CloudEnd, Pos: pos})
		}
	}
	g.ComputeLOS()
}

func (g *game) EvokeRodDigging(ev event) error {
	if !g.ui.ChooseTarget(g, &wallChooser{}) {
		return errors.New(DoNothing)
	}
	pos := g.Player.Target
	for i := 0; i < 3; i++ {
		g.Dungeon.SetCell(pos, FreeCell)
		g.MakeNoise(17, pos)
		g.Fog(pos, 1, ev)
		pos = pos.To(pos.Dir(g.Player.Pos))
		if !g.Player.LOS[pos] {
			g.UnknownDig[pos] = true
		}
		if !pos.valid() || g.Dungeon.Cell(pos).T != WallCell {
			break
		}
	}
	g.Print("You see the wall disintegrate with a crash.")
	g.ComputeLOS()
	g.MakeMonstersAware()
	return nil
}

func (g *game) EvokeRodShatter(ev event) error {
	if !g.ui.ChooseTarget(g, &wallChooser{minDist: true}) {
		return errors.New(DoNothing)
	}
	neighbors := g.Dungeon.FreeNeighbors(g.Player.Target)
	if RandInt(2) == 0 {
		g.Dungeon.SetCell(g.Player.Target, FreeCell)
		g.ComputeLOS()
		g.MakeMonstersAware()
		g.MakeNoise(19, g.Player.Target)
		g.Print("You see the wall disappear in a noisy explosion.")
		g.ui.ExplosionAnimation(g, WallExplosion, g.Player.Target)
		g.Fog(g.Player.Target, 2, ev)
	} else {
		g.MakeNoise(15, g.Player.Target)
		g.Print("You see an explosion around the wall.")
		g.ui.ExplosionAnimation(g, AroundWallExplosion, g.Player.Target)
	}
	for _, pos := range neighbors {
		mons, _ := g.MonsterAt(pos)
		if !mons.Exists() {
			continue
		}
		mons.HP -= RandInt(30)
		if mons.HP <= 0 {
			g.Printf("%s is killed by the explosion.", mons.Kind.Indefinite(true))
			g.HandleKill(mons, ev)
		}
		g.MakeNoise(12, mons.Pos)
		mons.MakeHuntIfHurt(g)
	}
	return nil
}

func (g *game) EvokeRodObstruction(ev event) error {
	if !g.ui.ChooseTarget(g, &chooser{needsFreeWay: true, free: true}) {
		return errors.New(DoNothing)
	}
	neighbors := g.Dungeon.FreeNeighbors(g.Player.Target)
	for _, pos := range neighbors {
		g.MakeNoise(18, pos)
		break
	}
	g.Dungeon.SetCell(g.Player.Target, WallCell)
	delete(g.Clouds, g.Player.Target)
	if g.TemporalWalls != nil {
		g.TemporalWalls[g.Player.Target] = true
	}
	g.PushEvent(&cloudEvent{ERank: ev.Rank() + 200 + RandInt(50), Pos: g.Player.Target, EAction: ObstructionEnd})
	g.Printf("You see a wall appear from nothing.")
	g.ComputeLOS()
	return nil
}

func (g *game) EvokeRodSwapping(ev event) error {
	if g.Player.HasStatus(StatusLignification) {
		return errors.New("You cannot use this rod while lignified.")
	}
	if !g.ui.ChooseTarget(g, &chooser{}) {
		return errors.New(DoNothing)
	}
	mons, _ := g.MonsterAt(g.Player.Target)
	// mons not nil (check done in the targeter)
	mons.Pos, g.Player.Pos = g.Player.Pos, mons.Pos
	mons.MakeAware(g)
	g.Printf("You swap positions with the %s.", mons.Kind)
	g.CollectGround()
	g.ComputeLOS()
	g.MakeMonstersAware()
	return nil
}

func (g *game) GeneratedRodsCount() int {
	count := 0
	for _, b := range g.GeneratedRods {
		if b {
			count++
		}
	}
	return count
}

func (g *game) GenerateRod() {
	count := 0
	for {
		count++
		if count > 1000 {
			panic("GenerateRod")
		}
		pos := g.FreeCellForStatic()
		r := rod(RandInt(NumRods))
		if r.Rare() && RandInt(3) == 0 {
			r = rod(RandInt(NumRods))
		}
		if g.Player.Rods[r] == nil && !g.GeneratedRods[r] {
			g.GeneratedRods[r] = true
			g.Rods[pos] = r
			return
		}
	}
}
<commit_msg>typos in rod description<commit_after>package main

import (
	"errors"
	"fmt"
)

type rod int

const (
	RodDigging rod = iota
	RodBlink
	RodTeleportOther
	RodLightningBolt
	RodFireball
	RodFog
	RodObstruction
	RodShatter
	RodSwapping
	// below unimplemented
	RodConfusingClouds
	RodFear
	RodFreezingClouds
)

const NumRods = int(RodSwapping) + 1

func (r rod) Letter() rune {
	return '/'
}

func (r rod) Rare() bool {
	switch r {
	case RodDigging, RodTeleportOther, RodShatter, RodSwapping:
		return true
	default:
		return false
	}
}

func (r rod) String() string {
	var text string
	switch r {
	case RodDigging:
		text = "rod of digging"
	case RodBlink:
		text = "rod of blinking"
	case RodTeleportOther:
		text = "rod of teleport other"
	case RodFog:
		text = "rod of fog"
	case RodFear:
		text = "rod of fear"
	case RodFireball:
		text = "rod of fireball"
	case RodLightningBolt:
		text = "rod of lightning bolt"
	case RodObstruction:
		text = "rod of obstruction"
	case RodShatter:
		text = "rod of shatter"
	case RodSwapping:
		text = "rod of swapping"
	case RodFreezingClouds:
		text = "rod of freezing clouds"
	case RodConfusingClouds:
		text = "rod of confusing clouds"
	}
	return text
}

func (r rod) Desc() string {
	var text string
	switch r {
	case RodDigging:
		text = "digs through walls."
	case RodBlink:
		text = "makes you blink away within your line of sight."
	case RodTeleportOther:
		text = "teleports away one of your foes."
	case RodFog:
		text = "creates a dense fog that reduces your (and monster's) line of sight."
	case RodFireball:
		text = "throws a 1-radius fireball at your foes."
	case RodLightningBolt:
		text = "throws a lightning bolt through one or more enemies."
	case RodObstruction:
		text = "creates a temporary wall at targeted location."
	case RodShatter:
		text = "induces an explosion around a wall. The wall can disintegrate."
	case RodSwapping:
		text = "makes you swap positions with a targeted monster."
	case RodFear:
		text = "TODO"
	case RodFreezingClouds:
		text = "TODO"
	case RodConfusingClouds:
		text = "TODO"
	}
	return fmt.Sprintf("The %s %s Rods sometimes regain charges as you go deeper. This rod can have up to %d charges.", r, text, r.MaxCharge())
}

type rodProps struct {
	Charge int
}

func (r rod) MaxCharge() (charges int) {
	switch r {
	case RodBlink:
		charges = 5
	case RodTeleportOther, RodDigging:
		charges = 3
	default:
		charges = 4
	}
	return charges
}

func (r rod) Rate() int {
	rate := r.MaxCharge() - 2
	if rate < 1 {
		rate = 1
	}
	return rate
}

func (r rod) MPCost() (mp int) {
	switch r {
	case RodBlink:
		mp = 3
	case RodTeleportOther, RodDigging, RodShatter:
		mp = 5
	default:
		mp = 4
	}
	return mp
}

func (r rod) Use(g *game, ev event) error {
	rods := g.Player.Rods
	if rods[r].Charge <= 0 {
		return errors.New("No charges remaining on this rod.")
	}
	if r.MPCost() > g.Player.MP {
		return errors.New("Not enough magic points for using this rod.")
	}
	var err error
	switch r {
	case RodBlink:
		err = g.EvokeRodBlink(ev)
	case RodTeleportOther:
		err = g.EvokeRodTeleportOther(ev)
	case RodLightningBolt:
		err = g.EvokeRodLightningBolt(ev)
	case RodFireball:
		err = g.EvokeRodFireball(ev)
	case RodFog:
		err = g.EvokeRodFog(ev)
	case RodDigging:
		err = g.EvokeRodDigging(ev)
	case RodObstruction:
		err = g.EvokeRodObstruction(ev)
	case RodShatter:
		err = g.EvokeRodShatter(ev)
	case RodSwapping:
		err = g.EvokeRodSwapping(ev)
	}

	if err != nil {
		return err
	}
	rods[r].Charge--
	g.Player.MP -= r.MPCost()
	g.StoryPrintf("You evoked your %s.", r)
	g.FairAction()
	ev.Renew(g, 7)
	return nil
}

func (g *game) EvokeRodBlink(ev event) error {
	if g.Player.HasStatus(StatusLignification) {
		return errors.New("You cannot blink while lignified.")
	}
	g.Blink(ev)
	return nil
}

func (g *game) Blink(ev event) {
	if g.Player.HasStatus(StatusLignification) {
		return
	}
	losPos := []position{}
	for pos, b := range g.Player.LOS {
		if !b {
			continue
		}
		if g.Dungeon.Cell(pos).T != FreeCell {
			continue
		}
		mons, _ := g.MonsterAt(pos)
		if mons.Exists() {
			continue
		}
		losPos = append(losPos, pos)
	}
	if len(losPos) == 0 {
		// should not happen
		g.Print("You could not blink.")
		return
	}
	npos := losPos[RandInt(len(losPos))]
	if npos.Distance(g.Player.Pos) <= 3 {
		// Give close cells less chance to make blinking more useful
		npos = losPos[RandInt(len(losPos))]
	}
	g.Player.Pos = npos
	g.Print("You blink away.")
	g.CollectGround()
	g.ComputeLOS()
	g.MakeMonstersAware()
}

func (g *game) EvokeRodTeleportOther(ev event) error {
	if !g.ui.ChooseTarget(g, &chooser{}) {
		return errors.New(DoNothing)
	}
	mons, _ := g.MonsterAt(g.Player.Target)
	// mons not nil (check done in the targeter)
	mons.TeleportAway(g)
	return nil
}

func (g *game) EvokeRodLightningBolt(ev event) error {
	if !g.ui.ChooseTarget(g, &chooser{flammable: true}) {
		return errors.New(DoNothing)
	}
	ray := g.Ray(g.Player.Target)
	g.Print("A lightning bolt emerges straight from the rod.")
	g.ui.LightningBoltAnimation(g, ray)
	for _, pos := range ray {
		g.Burn(pos, ev)
		mons, _ := g.MonsterAt(pos)
		if mons == nil {
			continue
		}
		mons.HP -= RandInt(21)
		if mons.HP <= 0 {
			g.Printf("%s is killed by the bolt.", mons.Kind.Indefinite(true))
			g.HandleKill(mons, ev)
		}
		g.MakeNoise(12, mons.Pos)
		mons.MakeHuntIfHurt(g)
	}
	return nil
}

func (g *game) EvokeRodFireball(ev event) error {
	if !g.ui.ChooseTarget(g, &chooser{area: true, minDist: true, flammable: true}) {
		return errors.New(DoNothing)
	}
	neighbors := g.Dungeon.FreeNeighbors(g.Player.Target)
	g.Print("A fireball emerges straight from the rod.")
	g.ui.ExplosionAnimation(g, FireExplosion, g.Player.Target)
	for _, pos := range append(neighbors, g.Player.Target) {
		g.Burn(pos, ev)
		mons, _ := g.MonsterAt(pos)
		if mons == nil {
			continue
		}
		mons.HP -= RandInt(21)
		if mons.HP <= 0 {
			g.Printf("%s is killed by the fireball.", mons.Kind.Indefinite(true))
			g.HandleKill(mons, ev)
		}
		g.MakeNoise(12, mons.Pos)
		mons.MakeHuntIfHurt(g)
	}
	return nil
}

type cloud int

const (
	CloudFog cloud = iota
	CloudFire
)

func (g *game) EvokeRodFog(ev event) error {
	g.Fog(g.Player.Pos, 3, ev)
	g.Print("You are surrounded by a dense fog.")
	return nil
}

func (g *game) Fog(at position, radius int, ev event) {
	dij := &normalPath{game: g}
	nm := Dijkstra(dij, []position{at}, radius)
	for pos := range nm {
		_, ok := g.Clouds[pos]
		if !ok {
			g.Clouds[pos] = CloudFog
			g.PushEvent(&cloudEvent{ERank: ev.Rank() + 100 + RandInt(100), EAction: CloudEnd, Pos: pos})
		}
	}
	g.ComputeLOS()
}

func (g *game) EvokeRodDigging(ev event) error {
	if !g.ui.ChooseTarget(g, &wallChooser{}) {
		return errors.New(DoNothing)
	}
	pos := g.Player.Target
	for i := 0; i < 3; i++ {
		g.Dungeon.SetCell(pos, FreeCell)
		g.MakeNoise(17, pos)
		g.Fog(pos, 1, ev)
		pos = pos.To(pos.Dir(g.Player.Pos))
		if !g.Player.LOS[pos] {
			g.UnknownDig[pos] = true
		}
		if !pos.valid() || g.Dungeon.Cell(pos).T != WallCell {
			break
		}
	}
	g.Print("You see the wall disintegrate with a crash.")
	g.ComputeLOS()
	g.MakeMonstersAware()
	return nil
}

func (g *game) EvokeRodShatter(ev event) error {
	if !g.ui.ChooseTarget(g, &wallChooser{minDist: true}) {
		return errors.New(DoNothing)
	}
	neighbors := g.Dungeon.FreeNeighbors(g.Player.Target)
	if RandInt(2) == 0 {
		g.Dungeon.SetCell(g.Player.Target, FreeCell)
		g.ComputeLOS()
		g.MakeMonstersAware()
		g.MakeNoise(19, g.Player.Target)
		g.Print("You see the wall disappear in a noisy explosion.")
		g.ui.ExplosionAnimation(g, WallExplosion, g.Player.Target)
		g.Fog(g.Player.Target, 2, ev)
	} else {
		g.MakeNoise(15, g.Player.Target)
		g.Print("You see an explosion around the wall.")
		g.ui.ExplosionAnimation(g, AroundWallExplosion, g.Player.Target)
	}
	for _, pos := range neighbors {
		mons, _ := g.MonsterAt(pos)
		if !mons.Exists() {
			continue
		}
		mons.HP -= RandInt(30)
		if mons.HP <= 0 {
			g.Printf("%s is killed by the explosion.", mons.Kind.Indefinite(true))
			g.HandleKill(mons, ev)
		}
		g.MakeNoise(12, mons.Pos)
		mons.MakeHuntIfHurt(g)
	}
	return nil
}

func (g *game) EvokeRodObstruction(ev event) error {
	if !g.ui.ChooseTarget(g, &chooser{needsFreeWay: true, free: true}) {
		return errors.New(DoNothing)
	}
	neighbors := g.Dungeon.FreeNeighbors(g.Player.Target)
	for _, pos := range neighbors {
		g.MakeNoise(18, pos)
		break
	}
	g.Dungeon.SetCell(g.Player.Target, WallCell)
	delete(g.Clouds, g.Player.Target)
	if g.TemporalWalls != nil {
		g.TemporalWalls[g.Player.Target] = true
	}
	g.PushEvent(&cloudEvent{ERank: ev.Rank() + 200 + RandInt(50), Pos: g.Player.Target, EAction: ObstructionEnd})
	g.Printf("You see a wall appear from nothing.")
	g.ComputeLOS()
	return nil
}

func (g *game) EvokeRodSwapping(ev event) error {
	if g.Player.HasStatus(StatusLignification) {
		return errors.New("You cannot use this rod while lignified.")
	}
	if !g.ui.ChooseTarget(g, &chooser{}) {
		return errors.New(DoNothing)
	}
	mons, _ := g.MonsterAt(g.Player.Target)
	// mons not nil (check done in the targeter)
	mons.Pos, g.Player.Pos = g.Player.Pos, mons.Pos
	mons.MakeAware(g)
	g.Printf("You swap positions with the %s.", mons.Kind)
	g.CollectGround()
	g.ComputeLOS()
	g.MakeMonstersAware()
	return nil
}

func (g *game) GeneratedRodsCount() int {
	count := 0
	for _, b := range g.GeneratedRods {
		if b {
			count++
		}
	}
	return count
}

func (g *game) GenerateRod() {
	count := 0
	for {
		count++
		if count > 1000 {
			panic("GenerateRod")
		}
		pos := g.FreeCellForStatic()
		r := rod(RandInt(NumRods))
		if r.Rare() && RandInt(3) == 0 {
			r = rod(RandInt(NumRods))
		}
		if g.Player.Rods[r] == nil && !g.GeneratedRods[r] {
			g.GeneratedRods[r] = true
			g.Rods[pos] = r
			return
		}
	}
}
<|endoftext|>


<commit_before>package gocards

type Room struct {
    Players     []Player
    BlackHand   []BlackCard
    dealer      int
}

func NewRoom() *Room {
    room := Room{}
    room.dealer = 0
    room.Players = []Player{}
    room.BlackHand = []BlackCard{}

    return &room
}

func (room *Room) SetPlayers(players []Player) {
    room.Players = players
    room.dealer = 0
}

func (room *Room) Dealer() Player {
    return room.Players[room.dealer]
}

func (room *Room) NonDealers() chan Player {
     c := make(chan Player)

     go func(count int, players []Player, dealerNumber int) {
        for i := 0; i < count; i++ {
            if i == dealerNumber {
                continue
            }

            c <- players[i]
        }

        close(c)
     }(len(room.Players), room.Players, room.dealer)

     return c
}

func (room *Room) RotateDealer() {
    if room.dealer + 1 == len(room.Players) {
        room.dealer = 0
    } else {
        room.dealer++
    }
}<commit_msg>removing unneeded freezing<commit_after>package gocards

type Room struct {
    Players     []Player
    BlackHand   []BlackCard
    dealer      int
}

func NewRoom() *Room {
    room := Room{}
    room.dealer = 0
    room.Players = []Player{}
    room.BlackHand = []BlackCard{}

    return &room
}

func (room *Room) SetPlayers(players []Player) {
    room.Players = players
    room.dealer = 0
}

func (room *Room) Dealer() Player {
    return room.Players[room.dealer]
}

func (room *Room) NonDealers() chan Player {
     c := make(chan Player)

     go func(players []Player, dealerNumber int) {
        for i := 0; i < len(players); i++ {
            if i == dealerNumber {
                continue
            }

            c <- players[i]
        }

        close(c)
     }(room.Players, room.dealer)

     return c
}

func (room *Room) RotateDealer() {
    if room.dealer + 1 == len(room.Players) {
        room.dealer = 0
    } else {
        room.dealer++
    }
}<|endoftext|>


<commit_before><commit_msg>Removed unwanted files<commit_after><|endoftext|>


<commit_before><commit_msg>Added channel for syncing, TSMW option<commit_after><|endoftext|>


<commit_before>//
// Copyright © 2011-2012 Guy M. Allard
//
// 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 stompngo

import (
	"log"
)

// Exported Connection methods

/*
	A convience method to return connection status.
*/
func (c *Connection) Connected() bool {
	return c.connected
}

/*
	A convienience method to return broker assigned session id.
*/
func (c *Connection) Session() string {
	return c.session
}

/*
	Return connection protocol level.
*/
func (c *Connection) Protocol() string {
	return c.protocol
}

/*
	Set Logger to a client defined logger for this connection.

	Set to "nil" to disable logging.
*/
func (c *Connection) SetLogger(l *log.Logger) {
	c.logger = l
}

/*
	Return Heartbeat Send Ticker Interval in ms.  A return value of zero means
	no heartbeats are being sent.
*/
func (c *Connection) SendTickerInterval() int64 {
	if c.hbd == nil {
		return 0
	}
	return c.hbd.sti / 1000000
}

/*
	Return Heartbeat Receive Ticker Interval in ms.  A return value of zero means
	no heartbeats are being received.
*/
func (c *Connection) ReceiveTickerInterval() int64 {
	if c.hbd == nil {
		return 0
	}
	return c.hbd.rti / 1000000
}

/*
	Return Heartbeat Send Ticker count.
*/
func (c *Connection) SendTickerCount() int64 {
	if c.hbd == nil {
		return 0
	}
	return c.hbd.sc
}

/*
	Return Heartbeat Receive Ticker count.
*/
func (c *Connection) ReceiveTickerCount() int64 {
	if c.hbd == nil {
		return 0
	}
	return c.hbd.rc
}

// Package exported functions

/*
	A convenience method to check if a particular STOMP version is supported
	in the current implementation.
*/
func Supported(v string) bool {
	return supported.Supported(v)
}

// Unexported Connection methods

/*
	Log data if possible.
*/
func (c *Connection) log(v ...interface{}) {
	if c.logger == nil {
		return
	}
	c.logger.Print(c.session, v)
	return
}

/*
	Shutdown logic.
*/
func (c *Connection) shutdown() {
	// Shutdown heartbeats if necessary
	if c.hbd != nil {
		if c.hbd.hbs {
			c.hbd.ssd <- true
		}
		if c.hbd.hbr {
			c.hbd.rsd <- true
		}
	}
	// Stop writer go routine
	c.wsd <- true
	// We are not connected
	c.connected = false
	return
}

/*
	Read error handler.
*/
func (c *Connection) handleReadError(md MessageData) {
	// Notify any general subscriber of error
	c.input <- md
	// Notify all individual subscribers of error
	c.subsLock.Lock()
	for key := range c.subs {
		c.subs[key] <- md
	}
	c.subsLock.Unlock()
	//
	c.shutdown() // We are done here .....
	return
}
<commit_msg>Issue #7,  Fixes hang problem, load and GOMAXPROCS>1.<commit_after>//
// Copyright © 2011-2012 Guy M. Allard
//
// 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 stompngo

import (
	"log"
)

// Exported Connection methods

/*
	A convience method to return connection status.
*/
func (c *Connection) Connected() bool {
	return c.connected
}

/*
	A convienience method to return broker assigned session id.
*/
func (c *Connection) Session() string {
	return c.session
}

/*
	Return connection protocol level.
*/
func (c *Connection) Protocol() string {
	return c.protocol
}

/*
	Set Logger to a client defined logger for this connection.

	Set to "nil" to disable logging.
*/
func (c *Connection) SetLogger(l *log.Logger) {
	c.logger = l
}

/*
	Return Heartbeat Send Ticker Interval in ms.  A return value of zero means
	no heartbeats are being sent.
*/
func (c *Connection) SendTickerInterval() int64 {
	if c.hbd == nil {
		return 0
	}
	return c.hbd.sti / 1000000
}

/*
	Return Heartbeat Receive Ticker Interval in ms.  A return value of zero means
	no heartbeats are being received.
*/
func (c *Connection) ReceiveTickerInterval() int64 {
	if c.hbd == nil {
		return 0
	}
	return c.hbd.rti / 1000000
}

/*
	Return Heartbeat Send Ticker count.
*/
func (c *Connection) SendTickerCount() int64 {
	if c.hbd == nil {
		return 0
	}
	return c.hbd.sc
}

/*
	Return Heartbeat Receive Ticker count.
*/
func (c *Connection) ReceiveTickerCount() int64 {
	if c.hbd == nil {
		return 0
	}
	return c.hbd.rc
}

// Package exported functions

/*
	A convenience method to check if a particular STOMP version is supported
	in the current implementation.
*/
func Supported(v string) bool {
	return supported.Supported(v)
}

// Unexported Connection methods

/*
	Log data if possible.
*/
func (c *Connection) log(v ...interface{}) {
	if c.logger == nil {
		return
	}
	c.logger.Print(c.session, v)
	return
}

/*
	Shutdown logic.
*/
func (c *Connection) shutdown() {
	// Shutdown heartbeats if necessary
	if c.hbd != nil {
		if c.hbd.hbs {
			c.hbd.ssd <- true
		}
		if c.hbd.hbr {
			c.hbd.rsd <- true
		}
	}
	// Stop writer go routine
	c.wsd <- true
	// We are not connected
	c.connected = false
	return
}

/*
	Read error handler.
*/
func (c *Connection) handleReadError(md MessageData) {
	// Notify any general subscriber of error
	c.input <- md
	// Notify all individual subscribers of error
	c.subsLock.Lock()
	for key := range c.subs {
		c.subs[key] <- md
	}
	c.subsLock.Unlock()
	// Let further shutdown logic proceed normally.
	return
}
<|endoftext|>


<commit_before>// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2012 Julien Schmidt. All rights reserved.
// http://www.julienschmidt.com
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.

package mysql

import (
	"database/sql/driver"
	"errors"
	"net"
	"strings"
	"time"
)

type mysqlConn struct {
	cfg              *config
	flags            clientFlag
	charset          byte
	cipher           []byte
	netConn          net.Conn
	buf              *buffer
	protocol         uint8
	sequence         uint8
	affectedRows     uint64
	insertId         uint64
	maxPacketAllowed int
	maxWriteSize     int
	parseTime        bool
	strict           bool
}

type config struct {
	user   string
	passwd string
	net    string
	addr   string
	dbname string
	params map[string]string
	loc    *time.Location
}

// Handles parameters set in DSN
func (mc *mysqlConn) handleParams() (err error) {
	for param, val := range mc.cfg.params {
		switch param {
		// Charset
		case "charset":
			charsets := strings.Split(val, ",")
			for i := range charsets {
				// ignore errors here - a charset may not exist
				err = mc.exec("SET NAMES " + charsets[i])
				if err == nil {
					break
				}
			}
			if err != nil {
				return
			}

		// handled elsewhere
		case "timeout", "allowAllFiles", "loc":
			continue

		// time.Time parsing
		case "parseTime":
			mc.parseTime = readBool(val)

		// Strict mode
		case "strict":
			mc.strict = readBool(val)

		// TLS-Encryption
		case "tls":
			err = errors.New("TLS-Encryption not implemented yet")
			return

		// Compression
		case "compress":
			err = errors.New("Compression not implemented yet")

		// System Vars
		default:
			err = mc.exec("SET " + param + "=" + val + "")
			if err != nil {
				return
			}
		}
	}

	return
}

func (mc *mysqlConn) Begin() (driver.Tx, error) {
	err := mc.exec("START TRANSACTION")
	if err == nil {
		return &mysqlTx{mc}, err
	}

	return nil, err
}

func (mc *mysqlConn) Close() (err error) {
	mc.writeCommandPacket(comQuit)
	mc.cfg = nil
	mc.buf = nil
	mc.netConn.Close()
	mc.netConn = nil
	return
}

func (mc *mysqlConn) Prepare(query string) (driver.Stmt, error) {
	// Send command
	err := mc.writeCommandPacketStr(comStmtPrepare, query)
	if err != nil {
		return nil, err
	}

	stmt := &mysqlStmt{
		mc: mc,
	}

	// Read Result
	columnCount, err := stmt.readPrepareResultPacket()
	if err == nil {
		if stmt.paramCount > 0 {
			stmt.params, err = stmt.mc.readColumns(stmt.paramCount)
			if err != nil {
				return nil, err
			}
		}

		if columnCount > 0 {
			err = stmt.mc.readUntilEOF()
		}
	}

	return stmt, err
}

func (mc *mysqlConn) Exec(query string, args []driver.Value) (driver.Result, error) {
	if len(args) == 0 { // no args, fastpath
		mc.affectedRows = 0
		mc.insertId = 0

		err := mc.exec(query)
		if err == nil {
			return &mysqlResult{
				affectedRows: int64(mc.affectedRows),
				insertId:     int64(mc.insertId),
			}, err
		}
		return nil, err
	}

	// with args, must use prepared stmt
	return nil, driver.ErrSkip

}

// Internal function to execute commands
func (mc *mysqlConn) exec(query string) (err error) {
	// Send command
	err = mc.writeCommandPacketStr(comQuery, query)
	if err != nil {
		return
	}

	// Read Result
	var resLen int
	resLen, err = mc.readResultSetHeaderPacket()
	if err == nil && resLen > 0 {
		err = mc.readUntilEOF()
		if err != nil {
			return
		}

		err = mc.readUntilEOF()
	}

	return
}

func (mc *mysqlConn) Query(query string, args []driver.Value) (driver.Rows, error) {
	if len(args) == 0 { // no args, fastpath
		// Send command
		err := mc.writeCommandPacketStr(comQuery, query)
		if err == nil {
			// Read Result
			var resLen int
			resLen, err = mc.readResultSetHeaderPacket()
			if err == nil {
				rows := &mysqlRows{mc, false, nil, false}

				if resLen > 0 {
					// Columns
					rows.columns, err = mc.readColumns(resLen)
				}
				return rows, err
			}
		}

		return nil, err
	}

	// with args, must use prepared stmt
	return nil, driver.ErrSkip
}

// Gets the value of the given MySQL System Variable
// The returned byte slice is only valid until the next read
func (mc *mysqlConn) getSystemVar(name string) (val []byte, err error) {
	// Send command
	err = mc.writeCommandPacketStr(comQuery, "SELECT @@"+name)
	if err == nil {
		// Read Result
		var resLen int
		resLen, err = mc.readResultSetHeaderPacket()
		if err == nil {
			rows := &mysqlRows{mc, false, nil, false}

			if resLen > 0 {
				// Columns
				rows.columns, err = mc.readColumns(resLen)
			}

			dest := make([]driver.Value, resLen)
			err = rows.readRow(dest)
			if err == nil {
				val = dest[0].([]byte)
				err = mc.readUntilEOF()
			}
		}
	}

	return
}
<commit_msg>Added handleParams case to ignore new CLIENT_FOUND_ROWS param.<commit_after>// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2012 Julien Schmidt. All rights reserved.
// http://www.julienschmidt.com
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.

package mysql

import (
	"database/sql/driver"
	"errors"
	"net"
	"strings"
	"time"
)

type mysqlConn struct {
	cfg              *config
	flags            clientFlag
	charset          byte
	cipher           []byte
	netConn          net.Conn
	buf              *buffer
	protocol         uint8
	sequence         uint8
	affectedRows     uint64
	insertId         uint64
	maxPacketAllowed int
	maxWriteSize     int
	parseTime        bool
	strict           bool
}

type config struct {
	user   string
	passwd string
	net    string
	addr   string
	dbname string
	params map[string]string
	loc    *time.Location
}

// Handles parameters set in DSN
func (mc *mysqlConn) handleParams() (err error) {
	for param, val := range mc.cfg.params {
		switch param {
		// Charset
		case "charset":
			charsets := strings.Split(val, ",")
			for i := range charsets {
				// ignore errors here - a charset may not exist
				err = mc.exec("SET NAMES " + charsets[i])
				if err == nil {
					break
				}
			}
			if err != nil {
				return
			}

		// handled elsewhere
		case "timeout", "allowAllFiles", "loc":
			continue

		// time.Time parsing
		case "parseTime":
			mc.parseTime = readBool(val)

		// Strict mode
		case "strict":
			mc.strict = readBool(val)

		// TLS-Encryption
		case "tls":
			err = errors.New("TLS-Encryption not implemented yet")
			return

		// Compression
		case "compress":
			err = errors.New("Compression not implemented yet")

		case "CLIENT_FOUND_ROWS":

		// System Vars
		default:
			err = mc.exec("SET " + param + "=" + val + "")
			if err != nil {
				return
			}
		}
	}

	return
}

func (mc *mysqlConn) Begin() (driver.Tx, error) {
	err := mc.exec("START TRANSACTION")
	if err == nil {
		return &mysqlTx{mc}, err
	}

	return nil, err
}

func (mc *mysqlConn) Close() (err error) {
	mc.writeCommandPacket(comQuit)
	mc.cfg = nil
	mc.buf = nil
	mc.netConn.Close()
	mc.netConn = nil
	return
}

func (mc *mysqlConn) Prepare(query string) (driver.Stmt, error) {
	// Send command
	err := mc.writeCommandPacketStr(comStmtPrepare, query)
	if err != nil {
		return nil, err
	}

	stmt := &mysqlStmt{
		mc: mc,
	}

	// Read Result
	columnCount, err := stmt.readPrepareResultPacket()
	if err == nil {
		if stmt.paramCount > 0 {
			stmt.params, err = stmt.mc.readColumns(stmt.paramCount)
			if err != nil {
				return nil, err
			}
		}

		if columnCount > 0 {
			err = stmt.mc.readUntilEOF()
		}
	}

	return stmt, err
}

func (mc *mysqlConn) Exec(query string, args []driver.Value) (driver.Result, error) {
	if len(args) == 0 { // no args, fastpath
		mc.affectedRows = 0
		mc.insertId = 0

		err := mc.exec(query)
		if err == nil {
			return &mysqlResult{
				affectedRows: int64(mc.affectedRows),
				insertId:     int64(mc.insertId),
			}, err
		}
		return nil, err
	}

	// with args, must use prepared stmt
	return nil, driver.ErrSkip

}

// Internal function to execute commands
func (mc *mysqlConn) exec(query string) (err error) {
	// Send command
	err = mc.writeCommandPacketStr(comQuery, query)
	if err != nil {
		return
	}

	// Read Result
	var resLen int
	resLen, err = mc.readResultSetHeaderPacket()
	if err == nil && resLen > 0 {
		err = mc.readUntilEOF()
		if err != nil {
			return
		}

		err = mc.readUntilEOF()
	}

	return
}

func (mc *mysqlConn) Query(query string, args []driver.Value) (driver.Rows, error) {
	if len(args) == 0 { // no args, fastpath
		// Send command
		err := mc.writeCommandPacketStr(comQuery, query)
		if err == nil {
			// Read Result
			var resLen int
			resLen, err = mc.readResultSetHeaderPacket()
			if err == nil {
				rows := &mysqlRows{mc, false, nil, false}

				if resLen > 0 {
					// Columns
					rows.columns, err = mc.readColumns(resLen)
				}
				return rows, err
			}
		}

		return nil, err
	}

	// with args, must use prepared stmt
	return nil, driver.ErrSkip
}

// Gets the value of the given MySQL System Variable
// The returned byte slice is only valid until the next read
func (mc *mysqlConn) getSystemVar(name string) (val []byte, err error) {
	// Send command
	err = mc.writeCommandPacketStr(comQuery, "SELECT @@"+name)
	if err == nil {
		// Read Result
		var resLen int
		resLen, err = mc.readResultSetHeaderPacket()
		if err == nil {
			rows := &mysqlRows{mc, false, nil, false}

			if resLen > 0 {
				// Columns
				rows.columns, err = mc.readColumns(resLen)
			}

			dest := make([]driver.Value, resLen)
			err = rows.readRow(dest)
			if err == nil {
				val = dest[0].([]byte)
				err = mc.readUntilEOF()
			}
		}
	}

	return
}
<|endoftext|>


<commit_before>// Copyright 2016 Arne Roomann-Kurrik
//
// 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 renderers

import (
	"fmt"
	"github.com/go-gl/gl/v3.3-core/gl"
	"github.com/go-gl/mathgl/mgl32"
	"github.com/kurrik/opengl-benchmarks/common"
	"unsafe"
)

const TEXT_FRAGMENT = `#version 150
precision mediump float;
in vec2 v_TexturePosition;
uniform sampler2D u_Texture;
out vec4 v_FragData;
void main() {
  v_FragData = texture(u_Texture, v_TexturePosition);
}` + "\x00"

const TEXT_VERTEX = `#version 150

#define MAX_TILES 1024

layout (std140) uniform TextureData {
  vec4 Tiles[MAX_TILES];
};

const vec2 WorldPoints[] = vec2[6](
  vec2(-0.5, -0.5),
  vec2( 0.5,  0.5),
  vec2(-0.5,  0.5),
  vec2(-0.5, -0.5),
  vec2( 0.5, -0.5),
  vec2( 0.5,  0.5)
);

const vec2 TexturePoints[] = vec2[6](
  vec2(0.0, 0.0),
  vec2(1.0, 1.0),
  vec2(0.0, 1.0),
  vec2(0.0, 0.0),
  vec2(1.0, 0.0),
  vec2(1.0, 1.0)
);

in float f_Tile;
in vec2 v_WorldPosition;
uniform mat4 m_ModelView;
uniform mat4 m_Projection;
out vec2 v_TexturePosition;
void main() {
  vec4 Tile = Tiles[int(f_Tile)];
  v_TexturePosition = TexturePoints[gl_VertexID] * Tile.xy + Tile.zw;
  vec2 WorldPosition = WorldPoints[gl_VertexID] + v_WorldPosition;
  gl_Position = m_Projection * m_ModelView * vec4(WorldPosition, 0.0, 1.0);
}` + "\x00"

type textDataPoint struct {
	worldPos mgl32.Vec2
	tile     float32
}

type textData struct {
	Points []textDataPoint
}

type Text struct {
	shader        *common.Program
	stride        uintptr
	locColor      int32
	locModelView  int32
	locProjection int32
	data          *textData
	ubo           *common.UniformBuffer
	vbo           *common.ArrayBuffer
}

func NewTextRenderer() (r *Text, err error) {
	r = &Text{
		shader: common.NewProgram(),
	}
	if err = r.shader.Load(TEXT_VERTEX, TEXT_FRAGMENT); err != nil {
		return
	}
	r.shader.Bind()
	var point textDataPoint
	r.stride = unsafe.Sizeof(point)
	r.vbo = common.NewArrayBuffer()
	r.vbo.VertexAttrib(r.shader.ID(), "v_WorldPosition", 2, gl.FLOAT, r.stride, unsafe.Offsetof(point.worldPos), 1)
	r.vbo.VertexAttrib(r.shader.ID(), "f_Tile", 1, gl.FLOAT, r.stride, unsafe.Offsetof(point.tile), 1)

	r.ubo = common.NewUniformBuffer()
	r.ubo.BlockBinding(r.shader.ID(), "TextureData", 1)

	r.locColor = gl.GetUniformLocation(r.shader.ID(), gl.Str("v_Color\x00"))
	r.locModelView = gl.GetUniformLocation(r.shader.ID(), gl.Str("m_ModelView\x00"))
	r.locProjection = gl.GetUniformLocation(r.shader.ID(), gl.Str("m_Projection\x00"))
	return
}

func (r *Text) Bind() {
	r.shader.Bind()
	r.vbo.Bind()
	r.ubo.Bind()

}

func (r *Text) Unbind() {
	r.shader.Unbind()
}

func (r *Text) Delete() {
	r.shader.Delete()
	r.vbo.Delete()
	r.ubo.Delete()
}

func (r *Text) Render(camera *common.Camera) (err error) {
	// Temporary:
	r.data = &textData{
		Points: []textDataPoint{
			textDataPoint{
				worldPos: mgl32.Vec2{0, 0},
				tile:     0,
			},
			textDataPoint{
				worldPos: mgl32.Vec2{1, 1},
				tile:     0,
			},
		},
	}
	var (
		modelView   = mgl32.Ident4()
		vboBytes    = len(r.data.Points) * int(r.stride)
		textureData = []float32{1, 1, 0, 0}
		uboBytes    = int(unsafe.Sizeof(textureData))
	)
	gl.Uniform4f(r.locColor, 0, 255.0/255.0, 0, 255.0/255.0)
	gl.UniformMatrix4fv(r.locModelView, 1, false, &modelView[0])
	gl.UniformMatrix4fv(r.locProjection, 1, false, &camera.Projection[0])
	r.vbo.Upload(r.data.Points, vboBytes)
	r.ubo.Upload(textureData, uboBytes)
	ptsPerInstance := 6
	instanceCount := 2
	gl.DrawArraysInstanced(gl.TRIANGLES, 0, int32(ptsPerInstance), int32(instanceCount))
	if e := gl.GetError(); e != 0 {
		err = fmt.Errorf("ERROR: OpenGL error %X", e)
	}
	return
}
<commit_msg>Pass correct number of bytes<commit_after>// Copyright 2016 Arne Roomann-Kurrik
//
// 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 renderers

import (
	"fmt"
	"github.com/go-gl/gl/v3.3-core/gl"
	"github.com/go-gl/mathgl/mgl32"
	"github.com/kurrik/opengl-benchmarks/common"
	"unsafe"
)

const TEXT_FRAGMENT = `#version 150
precision mediump float;
in vec2 v_TexturePosition;
uniform sampler2D u_Texture;
out vec4 v_FragData;
void main() {
  v_FragData = texture(u_Texture, v_TexturePosition);
}` + "\x00"

const TEXT_VERTEX = `#version 150

#define MAX_TILES 1024

layout (std140) uniform TextureData {
  vec4 Tiles[MAX_TILES];
};

const vec2 WorldPoints[] = vec2[6](
  vec2(-0.5, -0.5),
  vec2( 0.5,  0.5),
  vec2(-0.5,  0.5),
  vec2(-0.5, -0.5),
  vec2( 0.5, -0.5),
  vec2( 0.5,  0.5)
);

const vec2 TexturePoints[] = vec2[6](
  vec2(0.0, 0.0),
  vec2(1.0, 1.0),
  vec2(0.0, 1.0),
  vec2(0.0, 0.0),
  vec2(1.0, 0.0),
  vec2(1.0, 1.0)
);

in float f_Tile;
in vec2 v_WorldPosition;
uniform mat4 m_ModelView;
uniform mat4 m_Projection;
out vec2 v_TexturePosition;
void main() {
  vec4 Tile = Tiles[int(f_Tile)];
  v_TexturePosition = TexturePoints[gl_VertexID] * Tile.xy + Tile.zw;
  vec2 WorldPosition = WorldPoints[gl_VertexID] + v_WorldPosition;
  gl_Position = m_Projection * m_ModelView * vec4(WorldPosition, 0.0, 1.0);
}` + "\x00"

type textDataPoint struct {
	worldPos mgl32.Vec2
	tile     float32
}

type textData struct {
	Points []textDataPoint
}

type Text struct {
	shader        *common.Program
	stride        uintptr
	locColor      int32
	locModelView  int32
	locProjection int32
	data          *textData
	ubo           *common.UniformBuffer
	vbo           *common.ArrayBuffer
}

func NewTextRenderer() (r *Text, err error) {
	r = &Text{
		shader: common.NewProgram(),
	}
	if err = r.shader.Load(TEXT_VERTEX, TEXT_FRAGMENT); err != nil {
		return
	}
	r.shader.Bind()
	var point textDataPoint
	r.stride = unsafe.Sizeof(point)
	r.vbo = common.NewArrayBuffer()
	r.vbo.VertexAttrib(r.shader.ID(), "v_WorldPosition", 2, gl.FLOAT, r.stride, unsafe.Offsetof(point.worldPos), 1)
	r.vbo.VertexAttrib(r.shader.ID(), "f_Tile", 1, gl.FLOAT, r.stride, unsafe.Offsetof(point.tile), 1)

	r.ubo = common.NewUniformBuffer()
	r.ubo.BlockBinding(r.shader.ID(), "TextureData", 1)

	r.locColor = gl.GetUniformLocation(r.shader.ID(), gl.Str("v_Color\x00"))
	r.locModelView = gl.GetUniformLocation(r.shader.ID(), gl.Str("m_ModelView\x00"))
	r.locProjection = gl.GetUniformLocation(r.shader.ID(), gl.Str("m_Projection\x00"))
	return
}

func (r *Text) Bind() {
	r.shader.Bind()
	r.vbo.Bind()
	r.ubo.Bind()

}

func (r *Text) Unbind() {
	r.shader.Unbind()
}

func (r *Text) Delete() {
	r.shader.Delete()
	r.vbo.Delete()
	r.ubo.Delete()
}

func (r *Text) Render(camera *common.Camera) (err error) {
	// Temporary:
	r.data = &textData{
		Points: []textDataPoint{
			textDataPoint{
				worldPos: mgl32.Vec2{0, 0},
				tile:     0,
			},
			textDataPoint{
				worldPos: mgl32.Vec2{1, 1},
				tile:     0,
			},
		},
	}
	var (
		modelView   = mgl32.Ident4()
		vboBytes    = len(r.data.Points) * int(r.stride)
		textureData = []float32{1, 1, 0, 0}
		point       float32
		uboBytes    = len(textureData) * int(unsafe.Sizeof(point))
	)
	gl.Uniform4f(r.locColor, 0, 255.0/255.0, 0, 255.0/255.0)
	gl.UniformMatrix4fv(r.locModelView, 1, false, &modelView[0])
	gl.UniformMatrix4fv(r.locProjection, 1, false, &camera.Projection[0])
	r.vbo.Upload(r.data.Points, vboBytes)
	r.ubo.Upload(textureData, uboBytes)
	ptsPerInstance := 6
	instanceCount := 2
	gl.DrawArraysInstanced(gl.TRIANGLES, 0, int32(ptsPerInstance), int32(instanceCount))
	if e := gl.GetError(); e != 0 {
		err = fmt.Errorf("ERROR: OpenGL error %X", e)
	}
	return
}
<|endoftext|>


<commit_before><commit_msg>Combine client deferred func<commit_after><|endoftext|>


<commit_before>package main

import (
	"os"
	"unicode/utf8"

	log "github.com/Sirupsen/logrus"
	"github.com/caarlos0/env"
	"github.com/fgrehm/go-dockerpty"
	"github.com/fsouza/go-dockerclient"
)

const labelPrefix string = "io.conplicity"

type environment struct {
	Image              string `env:"DUPLICITY_DOCKER_IMAGE" envDefault:"camptocamp/duplicity:latest"`
	DuplicityTargetURL string `env:"DUPLICITY_TARGET_URL"`
	AWSAccessKeyID     string `env:"AWS_ACCESS_KEY_ID"`
	AWSSecretAccessKey string `env:"AWS_SECRET_ACCESS_KEY"`
	SwiftUsername      string `env:"SWIFT_USERNAME"`
	SwiftPassword      string `env:"SWIFT_PASSWORD"`
	SwiftAuthURL       string `env:"SWIFT_AUTHURL"`
	SwiftTenantName    string `env:"SWIFT_TENANTNAME"`
	SwiftRegionName    string `env:"SWIFT_REGIONNAME"`
}

type conplicity struct {
	*docker.Client
	*environment
	Hostname string
}

func main() {
	log.Infof("Starting backup...")

	var err error

	c := &conplicity{}

	c.getEnv()

	c.Hostname, err = os.Hostname()
	checkErr(err, "Failed to get hostname: %v", 1)

	endpoint := "unix:///var/run/docker.sock"

	c.Client, err = docker.NewClient(endpoint)
	checkErr(err, "Failed to create Docker client: %v", 1)

	vols, err := c.ListVolumes(docker.ListVolumesOptions{})
	checkErr(err, "Failed to list Docker volumes: %v", 1)

	err = c.pullImage()
	checkErr(err, "Failed to pull image: %v", 1)

	for _, vol := range vols {
		voll, _ := c.InspectVolume(vol.Name)
		checkErr(err, "Failed to inspect volume "+vol.Name+": %v", -1)
		err = c.backupVolume(voll)
		checkErr(err, "Failed to process volume "+vol.Name+": %v", -1)
	}

	log.Infof("End backup...")
}

func (c *conplicity) getEnv() (err error) {
	c.environment = &environment{}
	env.Parse(c.environment)

	return
}

func (c *conplicity) backupVolume(vol *docker.Volume) (err error) {
	if utf8.RuneCountInString(vol.Name) == 64 {
		log.Infof("Ignoring unnamed volume " + vol.Name)
		return
	}

	if getVolumeLabel(vol, ".ignore") == "true" {
		log.Infof("Ignoring blacklisted volume " + vol.Name)
		return
	}

	// TODO: detect if it's a Database volume (PostgreSQL, MySQL, OpenLDAP...) and launch DUPLICITY_PRECOMMAND instead of backuping the volume
	log.Infof("ID: " + vol.Name)
	log.Infof("Driver: " + vol.Driver)
	log.Infof("Mountpoint: " + vol.Mountpoint)
	log.Infof("Creating duplicity container...")
	container, err := c.CreateContainer(
		docker.CreateContainerOptions{
			Config: &docker.Config{
				Cmd: []string{
					"--full-if-older-than", "15D",
					"--s3-use-new-style",
					"--no-encryption",
					"--allow-source-mismatch",
					"/var/backups",
					c.DuplicityTargetURL + "/" + c.Hostname + "/" + vol.Name,
				},
				Env: []string{
					"AWS_ACCESS_KEY_ID=" + c.AWSAccessKeyID,
					"AWS_SECRET_ACCESS_KEY=" + c.AWSSecretAccessKey,
					"SWIFT_USERNAME=" + c.SwiftUsername,
					"SWIFT_PASSWORD=" + c.SwiftPassword,
					"SWIFT_AUTHURL=" + c.SwiftAuthURL,
					"SWIFT_TENANTNAME=" + c.SwiftTenantName,
					"SWIFT_REGIONNAME=" + c.SwiftRegionName,
					"SWIFT_AUTHVERSION=2",
				},
				Image:        c.Image,
				OpenStdin:    true,
				StdinOnce:    true,
				AttachStdin:  true,
				AttachStdout: true,
				AttachStderr: true,
				Tty:          true,
			},
		},
	)

	checkErr(err, "Failed to create container for volume "+vol.Name+": %v", 1)

	defer func() {
		c.RemoveContainer(docker.RemoveContainerOptions{
			ID:    container.ID,
			Force: true,
		})
	}()

	binds := []string{
		vol.Mountpoint + ":/var/backups:ro",
	}

	err = dockerpty.Start(c.Client, container, &docker.HostConfig{
		Binds: binds,
	})
	checkErr(err, "Failed to start container for volume "+vol.Name+": %v", -1)
	return
}

func (c *conplicity) pullImage() (err error) {
	if _, err = c.InspectImage(c.Image); err != nil {
		// TODO: output pull to logs
		log.Infof("Pulling image %v", c.Image)
		err = c.PullImage(docker.PullImageOptions{
			Repository: c.Image,
		}, docker.AuthConfiguration{})
	}

	return err
}

func getVolumeLabel(vol *docker.Volume, key string) (value string) {
  value = vol.Labels[labelPrefix + key]
  return
}

func checkErr(err error, msg string, exit int) {
	if err != nil {
		log.Errorf(msg, err)

		if exit != -1 {
			os.Exit(exit)
		}
	}
}
<commit_msg>Add .full_if_old_than label<commit_after>package main

import (
	"os"
	"unicode/utf8"

	log "github.com/Sirupsen/logrus"
	"github.com/caarlos0/env"
	"github.com/fgrehm/go-dockerpty"
	"github.com/fsouza/go-dockerclient"
)

const labelPrefix string = "io.conplicity"

type environment struct {
	Image              string `env:"DUPLICITY_DOCKER_IMAGE" envDefault:"camptocamp/duplicity:latest"`
	DuplicityTargetURL string `env:"DUPLICITY_TARGET_URL"`
	AWSAccessKeyID     string `env:"AWS_ACCESS_KEY_ID"`
	AWSSecretAccessKey string `env:"AWS_SECRET_ACCESS_KEY"`
	SwiftUsername      string `env:"SWIFT_USERNAME"`
	SwiftPassword      string `env:"SWIFT_PASSWORD"`
	SwiftAuthURL       string `env:"SWIFT_AUTHURL"`
	SwiftTenantName    string `env:"SWIFT_TENANTNAME"`
	SwiftRegionName    string `env:"SWIFT_REGIONNAME"`
}

type conplicity struct {
	*docker.Client
	*environment
	Hostname string
}

func main() {
	log.Infof("Starting backup...")

	var err error

	c := &conplicity{}

	c.getEnv()

	c.Hostname, err = os.Hostname()
	checkErr(err, "Failed to get hostname: %v", 1)

	endpoint := "unix:///var/run/docker.sock"

	c.Client, err = docker.NewClient(endpoint)
	checkErr(err, "Failed to create Docker client: %v", 1)

	vols, err := c.ListVolumes(docker.ListVolumesOptions{})
	checkErr(err, "Failed to list Docker volumes: %v", 1)

	err = c.pullImage()
	checkErr(err, "Failed to pull image: %v", 1)

	for _, vol := range vols {
		voll, _ := c.InspectVolume(vol.Name)
		checkErr(err, "Failed to inspect volume "+vol.Name+": %v", -1)
		err = c.backupVolume(voll)
		checkErr(err, "Failed to process volume "+vol.Name+": %v", -1)
	}

	log.Infof("End backup...")
}

func (c *conplicity) getEnv() (err error) {
	c.environment = &environment{}
	env.Parse(c.environment)

	return
}

func (c *conplicity) backupVolume(vol *docker.Volume) (err error) {
	if utf8.RuneCountInString(vol.Name) == 64 {
		log.Infof("Ignoring unnamed volume " + vol.Name)
		return
	}

	if getVolumeLabel(vol, ".ignore") == "true" {
		log.Infof("Ignoring blacklisted volume " + vol.Name)
		return
	}

	// TODO: detect if it's a Database volume (PostgreSQL, MySQL, OpenLDAP...) and launch DUPLICITY_PRECOMMAND instead of backuping the volume
	log.Infof("ID: " + vol.Name)
	log.Infof("Driver: " + vol.Driver)
	log.Infof("Mountpoint: " + vol.Mountpoint)
	log.Infof("Creating duplicity container...")

	fullIfOlderThan := getVolumeLabel(vol, ".full_if_old_than")
	if fullIfOlderThan == "" {
		fullIfOlderThan = "15D"
	}

	container, err := c.CreateContainer(
		docker.CreateContainerOptions{
			Config: &docker.Config{
				Cmd: []string{
					"--full-if-older-than", fullIfOlderThan,
					"--s3-use-new-style",
					"--no-encryption",
					"--allow-source-mismatch",
					"/var/backups",
					c.DuplicityTargetURL + "/" + c.Hostname + "/" + vol.Name,
				},
				Env: []string{
					"AWS_ACCESS_KEY_ID=" + c.AWSAccessKeyID,
					"AWS_SECRET_ACCESS_KEY=" + c.AWSSecretAccessKey,
					"SWIFT_USERNAME=" + c.SwiftUsername,
					"SWIFT_PASSWORD=" + c.SwiftPassword,
					"SWIFT_AUTHURL=" + c.SwiftAuthURL,
					"SWIFT_TENANTNAME=" + c.SwiftTenantName,
					"SWIFT_REGIONNAME=" + c.SwiftRegionName,
					"SWIFT_AUTHVERSION=2",
				},
				Image:        c.Image,
				OpenStdin:    true,
				StdinOnce:    true,
				AttachStdin:  true,
				AttachStdout: true,
				AttachStderr: true,
				Tty:          true,
			},
		},
	)

	checkErr(err, "Failed to create container for volume "+vol.Name+": %v", 1)

	defer func() {
		c.RemoveContainer(docker.RemoveContainerOptions{
			ID:    container.ID,
			Force: true,
		})
	}()

	binds := []string{
		vol.Mountpoint + ":/var/backups:ro",
	}

	err = dockerpty.Start(c.Client, container, &docker.HostConfig{
		Binds: binds,
	})
	checkErr(err, "Failed to start container for volume "+vol.Name+": %v", -1)
	return
}

func (c *conplicity) pullImage() (err error) {
	if _, err = c.InspectImage(c.Image); err != nil {
		// TODO: output pull to logs
		log.Infof("Pulling image %v", c.Image)
		err = c.PullImage(docker.PullImageOptions{
			Repository: c.Image,
		}, docker.AuthConfiguration{})
	}

	return err
}

func getVolumeLabel(vol *docker.Volume, key string) (value string) {
	value = vol.Labels[labelPrefix+key]
	return
}

func checkErr(err error, msg string, exit int) {
	if err != nil {
		log.Errorf(msg, err)

		if exit != -1 {
			os.Exit(exit)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"debug/pe"
	"encoding/binary"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"reflect"
	"strings"
	"unsafe"
)

type ImageResourceDirectory struct {
	Characteristics      uint32
	TimeDateStamp        uint32
	MajorVersion         uint16
	MinorVersion         uint16
	NumberOfNamedEntries uint16
	NumberOfIdEntries    uint16
}

type ImageResourceDirectoryEntry struct {
	NameOrId     uint32
	OffsetToData uint32
}

type ImageResourceDataEntry struct {
	OffsetToData uint32
	Size1        uint32
	CodePage     uint32
	Reserved     uint32
}

type Symbol struct {
	Name           [8]byte
	Value          uint32
	SectionNumber  uint16
	Type           uint16
	StorageClass   uint8
	AuxiliaryCount uint8
}

type StringsHeader struct {
	Length uint32
}

const (
	MASK_SUBDIRECTORY = 1 << 31
	TYPE_MANIFEST     = 24
)

var (
	STRING_RSRC = [8]byte{'.', 'r', 's', 'r', 'c', 0, 0, 0}
)

type Writer struct {
	W      io.Writer
	Offset uint32 //FIXME: uint64?
	Err    error
}

func (w *Writer) WriteLE(v interface{}) {
	if w.Err != nil {
		return
	}
	w.Err = binary.Write(w.W, binary.LittleEndian, v)
	if w.Err != nil {
		return
	}
	w.Offset += uint32(reflect.TypeOf(v).Size())
}

func main() {
	err := run()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}

func run() error {
	//TODO: allow options:
	// -o FILENAME - output file name
	// + advanced specification of multiple resources, as a tree (json?)
	if len(os.Args) <= 1 {
		return fmt.Errorf("USAGE: %s FILE.exe.manifest\n"+
			"Generates FILE.res",
			os.Args[0])
	}

	//TODO: try to simplify by adding fake section at beginning, containing strings table in data, and characteristics saying "drop me when linking"

	var fix2 uint32
	fix2 = 0x02ca // symbols (strings) table at the end

	fname := os.Args[1]
	suffix := ".exe.manifest"
	if !strings.HasSuffix(fname, suffix) {
		return fmt.Errorf("Filename '%s' does not end in suffix '%s'", fname, suffix)
	}
	fname = fname[:len(fname)-len(suffix)]

	manifest, err := ioutil.ReadFile(fname + suffix)
	if err != nil {
		return err
	}

	out, err := os.Create(fname + ".res")
	if err != nil {
		return err
	}
	defer out.Close()
	w := Writer{W: out}

	// precalculate some important offsets in resulting file, that we must know earlier
	rawdataoff := uint32(unsafe.Sizeof(pe.FileHeader{}) + unsafe.Sizeof(pe.SectionHeader32{}))
	rawdatalen := uint32(3*unsafe.Sizeof(ImageResourceDirectory{})+
		3*unsafe.Sizeof(ImageResourceDirectoryEntry{})+
		1*unsafe.Sizeof(ImageResourceDataEntry{})) +
		uint32(len(manifest))
	diroff := rawdataoff
	symoff := rawdataoff + rawdatalen

	coffhdr := pe.FileHeader{
		Machine:              0x014c, //FIXME: find out how to differentiate this value, or maybe not necessary for Go
		NumberOfSections:     1,      // .rsrc
		TimeDateStamp:        0,      // was also 0 in sample data from MinGW's windres.exe
		PointerToSymbolTable: uint32(symoff),
		NumberOfSymbols:      1,
		SizeOfOptionalHeader: 0,
		Characteristics:      0x0104, //FIXME: copied from windres.exe output, find out what should be here and why
	}
	w.WriteLE(coffhdr)
	if w.Err != nil {
		return fmt.Errorf("Error writing COFF header: %s", w.Err)
	}

	secthdr := pe.SectionHeader32{
		Name:             STRING_RSRC,
		SizeOfRawData:    rawdatalen,
		PointerToRawData: rawdataoff,
	}
	w.WriteLE(secthdr)
	if w.Err != nil {
		return fmt.Errorf("Error writing .rsrc section header: %s", w.Err)
	}

	// now, build "directory hierarchy" of .rsrc section: first type, then id/name, then language

	w.WriteLE(ImageResourceDirectory{
		NumberOfIdEntries: 1,
	})
	w.WriteLE(ImageResourceDirectoryEntry{
		NameOrId:     TYPE_MANIFEST,
		OffsetToData: MASK_SUBDIRECTORY | (w.Offset + uint32(unsafe.Sizeof(ImageResourceDirectoryEntry{})) - diroff),
	})
	w.WriteLE(ImageResourceDirectory{
		NumberOfIdEntries: 1,
	})
	w.WriteLE(ImageResourceDirectoryEntry{
		NameOrId:     1, // ID
		OffsetToData: MASK_SUBDIRECTORY | (w.Offset + uint32(unsafe.Sizeof(ImageResourceDirectoryEntry{})) - diroff),
	})
	w.WriteLE(ImageResourceDirectory{
		NumberOfIdEntries: 1,
	})
	w.WriteLE(ImageResourceDirectoryEntry{
		NameOrId:     0x0409, //FIXME: language; what value should be here?
		OffsetToData: w.Offset + uint32(unsafe.Sizeof(ImageResourceDirectoryEntry{})) - diroff,
	})

	w.WriteLE(ImageResourceDataEntry{
		OffsetToData: w.Offset + uint32(unsafe.Sizeof(ImageResourceDataEntry{})) - diroff,
		Size1:        uint32(len(manifest)),
		CodePage:     0, //FIXME: what value here? for now just tried 0
	})

	if w.Err != nil {
		return fmt.Errorf("Error writing .rsrc Directory Hierarchy: %s", w.Err)
	}

	if fix2 > 0 {
		manifest = append(manifest, []byte{
			'.', 'r',
			's', 'r', 'c', 0,
			0, 0, 0, 0,
			0, 0, 1, 0,
			0, 0, 3, 0,
			4, 0, 0, 0,
		}...)
	}

	_, err = w.W.Write(manifest)
	if err != nil {
		return fmt.Errorf("Error writing manifest contents: %s", err)
	}

	w.WriteLE(Symbol{
		Name:           STRING_RSRC,
		Value:          0,
		SectionNumber:  1,
		Type:           0, // FIXME: wtf?
		StorageClass:   3, // FIXME: is it ok? and uint8? and what does the value mean?
		AuxiliaryCount: 0, // FIXME: wtf?
	})

	w.WriteLE(StringsHeader{
		Length: uint32(unsafe.Sizeof(StringsHeader{})), // empty strings table -- but we must still show size of the table's header...
	})

	return nil
}
<commit_msg>don't forget to check errors from final WriteLE<commit_after>package main

import (
	"debug/pe"
	"encoding/binary"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"reflect"
	"strings"
	"unsafe"
)

type ImageResourceDirectory struct {
	Characteristics      uint32
	TimeDateStamp        uint32
	MajorVersion         uint16
	MinorVersion         uint16
	NumberOfNamedEntries uint16
	NumberOfIdEntries    uint16
}

type ImageResourceDirectoryEntry struct {
	NameOrId     uint32
	OffsetToData uint32
}

type ImageResourceDataEntry struct {
	OffsetToData uint32
	Size1        uint32
	CodePage     uint32
	Reserved     uint32
}

type Symbol struct {
	Name           [8]byte
	Value          uint32
	SectionNumber  uint16
	Type           uint16
	StorageClass   uint8
	AuxiliaryCount uint8
}

type StringsHeader struct {
	Length uint32
}

const (
	MASK_SUBDIRECTORY = 1 << 31
	TYPE_MANIFEST     = 24
)

var (
	STRING_RSRC = [8]byte{'.', 'r', 's', 'r', 'c', 0, 0, 0}
)

type Writer struct {
	W      io.Writer
	Offset uint32 //FIXME: uint64?
	Err    error
}

func (w *Writer) WriteLE(v interface{}) {
	if w.Err != nil {
		return
	}
	w.Err = binary.Write(w.W, binary.LittleEndian, v)
	if w.Err != nil {
		return
	}
	w.Offset += uint32(reflect.TypeOf(v).Size())
}

func main() {
	err := run()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}

func run() error {
	//TODO: allow options:
	// -o FILENAME - output file name
	// + advanced specification of multiple resources, as a tree (json?)
	if len(os.Args) <= 1 {
		return fmt.Errorf("USAGE: %s FILE.exe.manifest\n"+
			"Generates FILE.res",
			os.Args[0])
	}

	//TODO: try to simplify by adding fake section at beginning, containing strings table in data, and characteristics saying "drop me when linking"

	var fix2 uint32
	fix2 = 0x02ca // symbols (strings) table at the end

	fname := os.Args[1]
	suffix := ".exe.manifest"
	if !strings.HasSuffix(fname, suffix) {
		return fmt.Errorf("Filename '%s' does not end in suffix '%s'", fname, suffix)
	}
	fname = fname[:len(fname)-len(suffix)]

	manifest, err := ioutil.ReadFile(fname + suffix)
	if err != nil {
		return err
	}

	out, err := os.Create(fname + ".res")
	if err != nil {
		return err
	}
	defer out.Close()
	w := Writer{W: out}

	// precalculate some important offsets in resulting file, that we must know earlier
	rawdataoff := uint32(unsafe.Sizeof(pe.FileHeader{}) + unsafe.Sizeof(pe.SectionHeader32{}))
	rawdatalen := uint32(3*unsafe.Sizeof(ImageResourceDirectory{})+
		3*unsafe.Sizeof(ImageResourceDirectoryEntry{})+
		1*unsafe.Sizeof(ImageResourceDataEntry{})) +
		uint32(len(manifest))
	diroff := rawdataoff
	symoff := rawdataoff + rawdatalen

	coffhdr := pe.FileHeader{
		Machine:              0x014c, //FIXME: find out how to differentiate this value, or maybe not necessary for Go
		NumberOfSections:     1,      // .rsrc
		TimeDateStamp:        0,      // was also 0 in sample data from MinGW's windres.exe
		PointerToSymbolTable: uint32(symoff),
		NumberOfSymbols:      1,
		SizeOfOptionalHeader: 0,
		Characteristics:      0x0104, //FIXME: copied from windres.exe output, find out what should be here and why
	}
	w.WriteLE(coffhdr)
	if w.Err != nil {
		return fmt.Errorf("Error writing COFF header: %s", w.Err)
	}

	secthdr := pe.SectionHeader32{
		Name:             STRING_RSRC,
		SizeOfRawData:    rawdatalen,
		PointerToRawData: rawdataoff,
	}
	w.WriteLE(secthdr)
	if w.Err != nil {
		return fmt.Errorf("Error writing .rsrc section header: %s", w.Err)
	}

	// now, build "directory hierarchy" of .rsrc section: first type, then id/name, then language

	w.WriteLE(ImageResourceDirectory{
		NumberOfIdEntries: 1,
	})
	w.WriteLE(ImageResourceDirectoryEntry{
		NameOrId:     TYPE_MANIFEST,
		OffsetToData: MASK_SUBDIRECTORY | (w.Offset + uint32(unsafe.Sizeof(ImageResourceDirectoryEntry{})) - diroff),
	})
	w.WriteLE(ImageResourceDirectory{
		NumberOfIdEntries: 1,
	})
	w.WriteLE(ImageResourceDirectoryEntry{
		NameOrId:     1, // ID
		OffsetToData: MASK_SUBDIRECTORY | (w.Offset + uint32(unsafe.Sizeof(ImageResourceDirectoryEntry{})) - diroff),
	})
	w.WriteLE(ImageResourceDirectory{
		NumberOfIdEntries: 1,
	})
	w.WriteLE(ImageResourceDirectoryEntry{
		NameOrId:     0x0409, //FIXME: language; what value should be here?
		OffsetToData: w.Offset + uint32(unsafe.Sizeof(ImageResourceDirectoryEntry{})) - diroff,
	})

	w.WriteLE(ImageResourceDataEntry{
		OffsetToData: w.Offset + uint32(unsafe.Sizeof(ImageResourceDataEntry{})) - diroff,
		Size1:        uint32(len(manifest)),
		CodePage:     0, //FIXME: what value here? for now just tried 0
	})

	if w.Err != nil {
		return fmt.Errorf("Error writing .rsrc Directory Hierarchy: %s", w.Err)
	}

	if fix2 > 0 {
		manifest = append(manifest, []byte{
			'.', 'r',
			's', 'r', 'c', 0,
			0, 0, 0, 0,
			0, 0, 1, 0,
			0, 0, 3, 0,
			4, 0, 0, 0,
		}...)
	}

	_, err = w.W.Write(manifest)
	if err != nil {
		return fmt.Errorf("Error writing manifest contents: %s", err)
	}

	w.WriteLE(Symbol{
		Name:           STRING_RSRC,
		Value:          0,
		SectionNumber:  1,
		Type:           0, // FIXME: wtf?
		StorageClass:   3, // FIXME: is it ok? and uint8? and what does the value mean?
		AuxiliaryCount: 0, // FIXME: wtf?
	})

	w.WriteLE(StringsHeader{
		Length: uint32(unsafe.Sizeof(StringsHeader{})), // empty strings table -- but we must still show size of the table's header...
	})

	if w.Err != nil {
		return fmt.Errorf("Error writing .rsrc Symbol Table & Strings: %s", w.Err)
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"math/rand"
	"os"
	"path/filepath"
	"sync"
	"time"

	"github.com/dgraph-io/badger/y"
	"github.com/pkg/profile"
)

var (
	dir           = flag.String("dir", "datafiles", "File to read from")
	numReads      = flag.Int64("num", 2000000, "Number of reads")
	mode          = flag.Int("mode", 1, "0 = serial, 1 = parallel, 2 = parallel via channel")
	numGoroutines = flag.Int("jobs", 8, "Number of Goroutines")
	profilemode   = flag.String("profile.mode", "", "Enable profiling mode, one of [cpu, mem, mutex, block]")
)

var readSize int64 = 4 << 10

func getIndices(r *rand.Rand, flist []*os.File, maxFileSize int64) (*os.File, int64) {
	fidx := r.Intn(len(flist))
	iidx := r.Int63n(maxFileSize - readSize)
	return flist[fidx], iidx
}

func Serial(fList []*os.File, maxFileSize int64) {
	startT := time.Now()
	var i int64 = 0
	b := make([]byte, int(readSize))

	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	for ; i < *numReads; i++ {
		fd, offset := getIndices(r, fList, maxFileSize)
		_, err := fd.ReadAt(b, offset)
		if err != nil {
			log.Fatalf("Error reading file: %v", err)
		}
		if i%10000 == 0 {
			log.Printf("Finished %v reads in serial", i)
		}
	}
	fmt.Println("Serial: Number of random reads per second: ",
		float64(*numReads)/time.Since(startT).Seconds())
	fmt.Println("Serial: Time Taken: ", time.Since(startT))
}

func Conc2(fList []*os.File, maxFileSize int64) {
	startT := time.Now()
	var wg sync.WaitGroup
	countPerGo := *numReads / int64(*numGoroutines)
	fmt.Printf("Concurrent mode: Reads per goroutine: %d\n", countPerGo)

	for k := 0; k < *numGoroutines; k++ {
		wg.Add(1)
		go func() {
			b := make([]byte, int(readSize))
			r := rand.New(rand.NewSource(time.Now().UnixNano()))
			var i int64
			for ; i < countPerGo; i++ {
				fd, offset := getIndices(r, fList, maxFileSize)
				_, err := fd.ReadAt(b, offset)
				if err != nil {
					log.Fatalf("Error reading file: %v", err)
				}
			}
			wg.Done()
		}()
	}
	wg.Wait()
	fmt.Println("Concurrent 2: Number of random reads per second: ",
		float64(*numReads)/time.Since(startT).Seconds())
	fmt.Println("Concurrent 2: Time Taken: ", time.Since(startT))
}

type req struct {
	fd     *os.File
	offset int64
}

func Conc3(fList []*os.File, maxFileSize int64) {
	ch := make(chan req, 10000)
	go func() {
		var i int64
		rd := rand.New(rand.NewSource(time.Now().UnixNano()))
		for i = 0; i < *numReads; i++ {
			var r req
			r.fd, r.offset = getIndices(rd, fList, maxFileSize)
			ch <- r
		}
		close(ch)
	}()

	startT := time.Now()
	var wg sync.WaitGroup
	for k := 0; k < *numGoroutines; k++ {
		wg.Add(1)
		go func() {
			b := make([]byte, int(readSize))
			for req := range ch {
				_, err := req.fd.ReadAt(b, req.offset)
				if err != nil {
					log.Fatalf("Error reading file: %v", err)
				}
			}
			wg.Done()
		}()
	}
	wg.Wait()
	fmt.Println("Concurrent 3: Number of random reads per second: ",
		float64(*numReads)/time.Since(startT).Seconds())
	fmt.Println("Concurrent 3: Time Taken: ", time.Since(startT))
}

func main() {
	flag.Parse()

	var flist []*os.File
	var maxFileSize int64
	getFile := func(path string, info os.FileInfo, err error) error {
		if err != nil {
			log.Print(err)
			return nil
		}

		if !info.IsDir() {
			f, err := os.Open(path)
			y.AssertTruef(err == nil, "Error opening file: %v", path)
			flist = append(flist, f)
			log.Println("Opened file:", path, "Size:", info.Size()/(1<<20), "MB")
			maxFileSize = info.Size()
		}
		return nil
	}

	err := filepath.Walk(*dir, getFile)
	if err != nil {
		log.Fatalf("%v", err)
	}
	if len(flist) == 0 {
		log.Fatalf("Must have files already created")
	}

	switch *profilemode {
	case "cpu":
		defer profile.Start(profile.CPUProfile).Stop()
	case "mem":
		defer profile.Start(profile.MemProfile).Stop()
	case "mutex":
		defer profile.Start(profile.MutexProfile).Stop()
	case "block":
		defer profile.Start(profile.BlockProfile).Stop()
	}

	switch *mode {
	case 0:
		Serial(flist, maxFileSize)
	case 1:
		Conc2(flist, maxFileSize)
	case 2:
		Conc3(flist, maxFileSize)
	}
}
<commit_msg>Add trace as well<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"math/rand"
	"os"
	"path/filepath"
	"sync"
	"time"

	"github.com/dgraph-io/badger/y"
	"github.com/pkg/profile"
)

var (
	dir           = flag.String("dir", "datafiles", "File to read from")
	numReads      = flag.Int64("num", 2000000, "Number of reads")
	mode          = flag.Int("mode", 1, "0 = serial, 1 = parallel, 2 = parallel via channel")
	numGoroutines = flag.Int("jobs", 8, "Number of Goroutines")
	profilemode   = flag.String("profile.mode", "", "Enable profiling mode, one of [cpu, mem, mutex, block]")
)

var readSize int64 = 4 << 10

func getIndices(r *rand.Rand, flist []*os.File, maxFileSize int64) (*os.File, int64) {
	fidx := r.Intn(len(flist))
	iidx := r.Int63n(maxFileSize - readSize)
	return flist[fidx], iidx
}

func Serial(fList []*os.File, maxFileSize int64) {
	startT := time.Now()
	var i int64 = 0
	b := make([]byte, int(readSize))

	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	for ; i < *numReads; i++ {
		fd, offset := getIndices(r, fList, maxFileSize)
		_, err := fd.ReadAt(b, offset)
		if err != nil {
			log.Fatalf("Error reading file: %v", err)
		}
		if i%10000 == 0 {
			log.Printf("Finished %v reads in serial", i)
		}
	}
	fmt.Println("Serial: Number of random reads per second: ",
		float64(*numReads)/time.Since(startT).Seconds())
	fmt.Println("Serial: Time Taken: ", time.Since(startT))
}

func Conc2(fList []*os.File, maxFileSize int64) {
	startT := time.Now()
	var wg sync.WaitGroup
	countPerGo := *numReads / int64(*numGoroutines)
	fmt.Printf("Concurrent mode: Reads per goroutine: %d\n", countPerGo)

	for k := 0; k < *numGoroutines; k++ {
		wg.Add(1)
		go func() {
			b := make([]byte, int(readSize))
			r := rand.New(rand.NewSource(time.Now().UnixNano()))
			var i int64
			for ; i < countPerGo; i++ {
				fd, offset := getIndices(r, fList, maxFileSize)
				_, err := fd.ReadAt(b, offset)
				if err != nil {
					log.Fatalf("Error reading file: %v", err)
				}
			}
			wg.Done()
		}()
	}
	wg.Wait()
	fmt.Println("Concurrent 2: Number of random reads per second: ",
		float64(*numReads)/time.Since(startT).Seconds())
	fmt.Println("Concurrent 2: Time Taken: ", time.Since(startT))
}

type req struct {
	fd     *os.File
	offset int64
}

func Conc3(fList []*os.File, maxFileSize int64) {
	ch := make(chan req, 10000)
	go func() {
		var i int64
		rd := rand.New(rand.NewSource(time.Now().UnixNano()))
		for i = 0; i < *numReads; i++ {
			var r req
			r.fd, r.offset = getIndices(rd, fList, maxFileSize)
			ch <- r
		}
		close(ch)
	}()

	startT := time.Now()
	var wg sync.WaitGroup
	for k := 0; k < *numGoroutines; k++ {
		wg.Add(1)
		go func() {
			b := make([]byte, int(readSize))
			for req := range ch {
				_, err := req.fd.ReadAt(b, req.offset)
				if err != nil {
					log.Fatalf("Error reading file: %v", err)
				}
			}
			wg.Done()
		}()
	}
	wg.Wait()
	fmt.Println("Concurrent 3: Number of random reads per second: ",
		float64(*numReads)/time.Since(startT).Seconds())
	fmt.Println("Concurrent 3: Time Taken: ", time.Since(startT))
}

func main() {
	flag.Parse()

	var flist []*os.File
	var maxFileSize int64
	getFile := func(path string, info os.FileInfo, err error) error {
		if err != nil {
			log.Print(err)
			return nil
		}

		if !info.IsDir() {
			f, err := os.Open(path)
			y.AssertTruef(err == nil, "Error opening file: %v", path)
			flist = append(flist, f)
			log.Println("Opened file:", path, "Size:", info.Size()/(1<<20), "MB")
			maxFileSize = info.Size()
		}
		return nil
	}

	err := filepath.Walk(*dir, getFile)
	if err != nil {
		log.Fatalf("%v", err)
	}
	if len(flist) == 0 {
		log.Fatalf("Must have files already created")
	}

	switch *profilemode {
	case "cpu":
		defer profile.Start(profile.CPUProfile).Stop()
	case "mem":
		defer profile.Start(profile.MemProfile).Stop()
	case "mutex":
		defer profile.Start(profile.MutexProfile).Stop()
	case "block":
		defer profile.Start(profile.BlockProfile).Stop()
	case "trace":
		defer profile.Start(profile.TraceProfile).Stop()
	}

	switch *mode {
	case 0:
		Serial(flist, maxFileSize)
	case 1:
		Conc2(flist, maxFileSize)
	case 2:
		Conc3(flist, maxFileSize)
	}
}
<|endoftext|>


<commit_before><commit_msg>note update/sync<commit_after><|endoftext|>


<commit_before>package audioExport

import (
	"bytes"
	"encoding/binary"
	"os"
)

/**
 * The WaveFile struct is used to create uncompressed .wav files.
 */
type WaveFile struct {
	file        *os.File
	description WaveDescription
}

/**
 * This struct describes the format of the audio data.  See the .wav format
 * specification for a complete definition of these members.
 */
type WaveDescription struct {
	NumChannels   int16
	SampleRate    uint32
	BitsPerSample int16
}

/**
 * Creates the file and writes the necessary headers.  The corresponding
 * "Close" method should always be called when you're done with the file.
 * @param {string} fileName The name of the file to be created.
 * @return {error} Non-nil if an error occured.
 */
func (w *WaveFile) Open(fileName string, description WaveDescription) error {
	var err error

	w.file, err = os.Create(fileName)
	if err != nil {
		return err
	}

	w.description = description

	buffer := new(bytes.Buffer)
	err = w.writeHeader(buffer)
	if err != nil {
		return err
	}

	_, err = w.file.Write(buffer.Bytes())
	return err
}

/**
 * Writes the binary waveform to the file.  This can be called several times,
 * so long as the file doesn't reach its 4GB limit.
 * @param {[]byte} bytes The waveform data to be written to the file.  For
 *                       multichannel audio, the data should already be muxed.
 * @return {error} Non-nil if an error occured.
 */
func (w *WaveFile) WriteBytes(bytes []byte) error {
	// TODO: Write bytes to file
	return nil
}

/**
 * Muxes and writes the channels to the file.  This can be called several
 * times, so long as the file doesn't reach its 4GB limit.
 * @param {[]byte} channels The audio data in each channel.  If the file
 *                          description calls for more channels than what is
 *                          passed, the other channels will be filled with
 *                          zeroes.
 * @return {error} Non-nil if an error occured.
 */
func (w *WaveFile) WriteChannels(channels ...[]byte) error {
	// TODO: Mux and write the bytes to the file
	return nil
}

/**
 * Closes the file.  This should always be called when you're done writing
 * data.
 * @return {error} Non-nil if an error occured.
 */
func (w *WaveFile) Close() error {
	// TODO: Adjust block sizes
	return w.file.Close()
}

/***** Private Methods *****/

/**
 * Writes the header chunks to the file.
 * @return {error} Non-nil if an error occured.
 */
func (w *WaveFile) writeHeader(buffer *bytes.Buffer) error {
	var err error

	err = w.writeRIFFChunk(buffer)
	if err != nil {
		return err
	}

	return nil
}

/**
 * Writes the container (RIFF) chunk to the file.
 * @return {error} Non-nil if an error occured.
 */
func (w *WaveFile) writeRIFFChunk(buffer *bytes.Buffer) error {
	var err error

	// ChunkID (RIFF)
	_, err = buffer.WriteString("RIFF")
	if err != nil {
		return err
	}

	// ChunkSize (Unknown at this time)
	err = binary.Write(buffer, binary.LittleEndian, uint32(0))
	if err != nil {
		return err
	}

	// Format (WAVE)
	_, err = buffer.WriteString("WAVE")
	if err != nil {
		return err
	}

	return nil
}

func (w *WaveFile) writeFmtChunk(buffer *bytes.Buffer) error {
	return nil
}
<commit_msg>Added fmt chunk<commit_after>package audioExport

import (
	"bytes"
	"encoding/binary"
	"os"
)

/**
 * The WaveFile struct is used to create uncompressed .wav files.
 */
type WaveFile struct {
	file        *os.File
	description WaveDescription
}

/**
 * This struct describes the format of the audio data.  See the .wav format
 * specification for a complete definition of these members.
 */
type WaveDescription struct {
	NumChannels   int16
	SampleRate    uint32
	BitsPerSample int16
}

/**
 * Creates the file and writes the necessary headers.  The corresponding
 * "Close" method should always be called when you're done with the file.
 * @param {string} fileName The name of the file to be created.
 * @return {error} Non-nil if an error occured.
 */
func (w *WaveFile) Open(fileName string, description WaveDescription) error {
	var err error

	w.file, err = os.Create(fileName)
	if err != nil {
		return err
	}

	w.description = description

	buffer := new(bytes.Buffer)
	err = w.writeHeader(buffer)
	if err != nil {
		return err
	}

	_, err = w.file.Write(buffer.Bytes())
	return err
}

/**
 * Writes the binary waveform to the file.  This can be called several times,
 * so long as the file doesn't reach its 4GB limit.
 * @param {[]byte} bytes The waveform data to be written to the file.  For
 *                       multichannel audio, the data should already be muxed.
 * @return {error} Non-nil if an error occured.
 */
func (w *WaveFile) WriteBytes(bytes []byte) error {
	// TODO: Write bytes to file
	return nil
}

/**
 * Muxes and writes the channels to the file.  This can be called several
 * times, so long as the file doesn't reach its 4GB limit.
 * @param {[]byte} channels The audio data in each channel.  If the file
 *                          description calls for more channels than what is
 *                          passed, the other channels will be filled with
 *                          zeroes.
 * @return {error} Non-nil if an error occured.
 */
func (w *WaveFile) WriteChannels(channels ...[]byte) error {
	// TODO: Mux and write the bytes to the file
	return nil
}

/**
 * Closes the file.  This should always be called when you're done writing
 * data.
 * @return {error} Non-nil if an error occured.
 */
func (w *WaveFile) Close() error {
	// TODO: Adjust block sizes
	return w.file.Close()
}

/***** Private Methods *****/

/**
 * Writes the header chunks to the buffer.
 * @return {error} Non-nil if an error occured.
 */
func (w *WaveFile) writeHeader(buffer *bytes.Buffer) error {
	var err error

	err = w.writeRIFFChunk(buffer)
	if err != nil {
		return err
	}

	err = w.writeFmtChunk(buffer)
	if err != nil {
		return err
	}

	return nil
}

/**
 * Writes the container (RIFF) chunk to the buffer.
 * @return {error} Non-nil if an error occured.
 */
func (w *WaveFile) writeRIFFChunk(buffer *bytes.Buffer) error {
	var err error

	// Chunk ID (RIFF)
	_, err = buffer.WriteString("RIFF")
	if err != nil {
		return err
	}

	// Chunk size (Unknown at this time)
	err = binary.Write(buffer, binary.LittleEndian, uint32(0))
	if err != nil {
		return err
	}

	// Format (WAVE)
	_, err = buffer.WriteString("WAVE")
	if err != nil {
		return err
	}

	return nil
}

/**
 * Writes the mandatory fmt chunk to the buffer.
 */
func (w *WaveFile) writeFmtChunk(buffer *bytes.Buffer) error {
	var err error

	// Chunk ID (fmt )
	_, err = buffer.WriteString("fmt ")
	if err != nil {
		return err
	}

	// Chunk size (always 16)
	err = binary.Write(buffer, binary.LittleEndian, uint32(16))
	if err != nil {
		return err
	}

	// Audio format (1 = uncompressed PCM)
	err = binary.Write(buffer, binary.LittleEndian, uint16(1))
	if err != nil {
		return err
	}

	// Number of channels
	err = binary.Write(buffer, binary.LittleEndian, w.description.NumChannels)
	if err != nil {
		return err
	}

	// Sample rate
	err = binary.Write(buffer, binary.LittleEndian, w.description.SampleRate)
	if err != nil {
		return err
	}

	blockAlign := w.description.NumChannels * w.description.BitsPerSample / 8
	byteRate := w.description.SampleRate * uint32(blockAlign)

	// Byte rate
	err = binary.Write(buffer, binary.LittleEndian, byteRate)
	if err != nil {
		return err
	}

	// Block align
	err = binary.Write(buffer, binary.LittleEndian, blockAlign)
	if err != nil {
		return err
	}

	// Bits per sample
	err = binary.Write(buffer, binary.LittleEndian, w.description.BitsPerSample)
	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>