<commit_before>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/user"
	"path"
	"strings"
	"sync"

	"code.google.com/p/go.crypto/ssh"
	"code.google.com/p/gopass"

	"github.com/sudharsh/henchman/lib"
)

func currentUsername() *user.User {
	u, err := user.Current()
	if err != nil {
		panic("Couldn't get current username: " + err.Error())
	}
	return u
}

func defaultKeyFile() string {
	u := currentUsername()
	return path.Join(u.HomeDir, ".ssh", "id_rsa")
}

func parseExtraArgs(args string) henchman.TaskVars {
	extraArgs := make(henchman.TaskVars)
	if args == "" {
		return extraArgs
	}
	for _, a := range strings.Split(args, " ") {
		kv := strings.Split(a, "=")
		extraArgs[kv[0]] = kv[1]
	}
	return extraArgs
}

func validateModulesPath() (string, error) {
	_modulesDir := os.Getenv("HENCHMAN_MODULES_PATH")
	if _modulesDir == "" {
		cwd, _ := os.Getwd()
		_modulesDir = path.Join(cwd, "modules")
	}
	modulesDir := flag.String("modules", _modulesDir, "Path to the modules")
	_, err := os.Stat(*modulesDir)
	return *modulesDir, err
}

func main() {
	username := flag.String("user", currentUsername().Username, "User to run as")
	usePassword := flag.Bool("password", false, "Use password authentication")
	keyfile := flag.String("private-keyfile", defaultKeyFile(), "Path to the keyfile")
	extraArgs := flag.String("args", "", "Extra arguments for the plan")

	modulesDir, err := validateModulesPath()
	if err != nil {
		log.Fatalf("Couldn't stat modules path '%s'\n", modulesDir)
	}

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: %s [args] <plan>\n\n", os.Args[0])
		flag.PrintDefaults()
	}
	flag.Parse()

	planFile := flag.Arg(0)
	if planFile == "" {
		flag.Usage()
		os.Exit(1)
	}

	if *username == "" {
		fmt.Fprintf(os.Stderr, "Missing username")
		os.Exit(1)
	}
	var sshAuth ssh.AuthMethod
	if *usePassword {
		var password string
		if password, err = gopass.GetPass("Password:"); err != nil {
			log.Fatalf("Couldn't get password: " + err.Error())
			os.Exit(1)
		}
		sshAuth, err = henchman.PasswordAuth(password)
	} else {
		sshAuth, err = henchman.ClientKeyAuth(*keyfile)
	}
	if err != nil {
		log.Fatalf("SSH Auth prep failed: " + err.Error())
	}
	config := &ssh.ClientConfig{
		User: *username,
		Auth: []ssh.AuthMethod{sshAuth},
	}

	planBuf, err := ioutil.ReadFile(planFile)
	if err != nil {
		log.Fatalf("Error reading plan - %s\n", planFile)
		os.Exit(1)
	}

	var plan *henchman.Plan
	parsedArgs := parseExtraArgs(*extraArgs)
	plan, err = henchman.NewPlan(planBuf, &parsedArgs)
	if err != nil {
		log.Fatalf("Couldn't read the plan: %s", err)
		os.Exit(1)
	}

	wg := new(sync.WaitGroup)
	machines := henchman.Machines(plan.Hosts, config)
	for _, _machine := range machines {
		machine := _machine
		wg.Add(1)
		go func() {
			defer wg.Done()
			for _, task := range plan.Tasks {
				status := task.Run(machine, plan.Vars)
				plan.SaveStatus(&task, status)
			}
		}()
	}
	wg.Wait()
	plan.PrintReport()
}
<commit_msg>Don't continue the plan on a machine if a task returns 'failure'<commit_after>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/user"
	"path"
	"strings"
	"sync"

	"code.google.com/p/go.crypto/ssh"
	"code.google.com/p/gopass"

	"github.com/sudharsh/henchman/lib"
)

func currentUsername() *user.User {
	u, err := user.Current()
	if err != nil {
		panic("Couldn't get current username: " + err.Error())
	}
	return u
}

func defaultKeyFile() string {
	u := currentUsername()
	return path.Join(u.HomeDir, ".ssh", "id_rsa")
}

func parseExtraArgs(args string) henchman.TaskVars {
	extraArgs := make(henchman.TaskVars)
	if args == "" {
		return extraArgs
	}
	for _, a := range strings.Split(args, " ") {
		kv := strings.Split(a, "=")
		extraArgs[kv[0]] = kv[1]
	}
	return extraArgs
}

func validateModulesPath() (string, error) {
	_modulesDir := os.Getenv("HENCHMAN_MODULES_PATH")
	if _modulesDir == "" {
		cwd, _ := os.Getwd()
		_modulesDir = path.Join(cwd, "modules")
	}
	modulesDir := flag.String("modules", _modulesDir, "Path to the modules")
	_, err := os.Stat(*modulesDir)
	return *modulesDir, err
}

func main() {
	username := flag.String("user", currentUsername().Username, "User to run as")
	usePassword := flag.Bool("password", false, "Use password authentication")
	keyfile := flag.String("private-keyfile", defaultKeyFile(), "Path to the keyfile")
	extraArgs := flag.String("args", "", "Extra arguments for the plan")

	modulesDir, err := validateModulesPath()
	if err != nil {
		log.Fatalf("Couldn't stat modules path '%s'\n", modulesDir)
	}

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: %s [args] <plan>\n\n", os.Args[0])
		flag.PrintDefaults()
	}
	flag.Parse()

	planFile := flag.Arg(0)
	if planFile == "" {
		flag.Usage()
		os.Exit(1)
	}

	if *username == "" {
		fmt.Fprintf(os.Stderr, "Missing username")
		os.Exit(1)
	}
	var sshAuth ssh.AuthMethod
	if *usePassword {
		var password string
		if password, err = gopass.GetPass("Password:"); err != nil {
			log.Fatalf("Couldn't get password: " + err.Error())
			os.Exit(1)
		}
		sshAuth, err = henchman.PasswordAuth(password)
	} else {
		sshAuth, err = henchman.ClientKeyAuth(*keyfile)
	}
	if err != nil {
		log.Fatalf("SSH Auth prep failed: " + err.Error())
	}
	config := &ssh.ClientConfig{
		User: *username,
		Auth: []ssh.AuthMethod{sshAuth},
	}

	planBuf, err := ioutil.ReadFile(planFile)
	if err != nil {
		log.Fatalf("Error reading plan - %s\n", planFile)
		os.Exit(1)
	}

	var plan *henchman.Plan
	parsedArgs := parseExtraArgs(*extraArgs)
	plan, err = henchman.NewPlan(planBuf, &parsedArgs)
	if err != nil {
		log.Fatalf("Couldn't read the plan: %s", err)
		os.Exit(1)
	}

	wg := new(sync.WaitGroup)
	machines := henchman.Machines(plan.Hosts, config)
	for _, _machine := range machines {
		machine := _machine
		wg.Add(1)
		go func() {
			defer wg.Done()
			for _, task := range plan.Tasks {
				status := task.Run(machine, plan.Vars)
				plan.SaveStatus(&task, status)
				if status == "failure" {
					log.Printf("Task was unsuccessful: %s\n", task.Id)
					break
				}
			}
		}()
	}
	wg.Wait()
	plan.PrintReport()
}
<|endoftext|>


<commit_before>package main

import (
	"net/http"
	"shuttle_tracking_2/demo"
	"shuttle_tracking_2/tracking"

	log "github.com/Sirupsen/logrus"
	"github.com/gorilla/mux"
)

var (
	// Config holds the global app settings.
	Config = tracking.InitConfig()
	// App holds the application itself.
	App       = tracking.InitApp(Config)
	Demo      = demo.Init()                    // initialize the demo
	DemoUsers = demo.UserCollectionInit(&Demo) // init users
)

// IndexHandler serves the index page.
func IndexHandler(w http.ResponseWriter, r *http.Request) {
	http.ServeFile(w, r, "index.html")
}

// AdminHandler serves the admin page.
func AdminHandler(w http.ResponseWriter, r *http.Request) {
	http.ServeFile(w, r, "admin.html")
}

func main() {
	// close Mongo session when server terminates
	defer App.Session.Close()

	// Start auto updater
	go App.UpdateShuttles(Config.DataFeed, Config.UpdateInterval)

	// Routing
	r := mux.NewRouter()
	r.HandleFunc("/", IndexHandler).Methods("GET")
	r.HandleFunc("/admin", AdminHandler).Methods("GET")
	r.HandleFunc("/admin/{*}", AdminHandler).Methods("GET")
	r.HandleFunc("/vehicles", App.VehiclesHandler).Methods("GET")
	r.HandleFunc("/vehicles/create", App.VehiclesCreateHandler).Methods("POST")
	r.HandleFunc("/vehciles/edit", App.VehiclesEditHandler).Methods("POST")
	r.HandleFunc("/vehicles/{id:[0-9]+}", App.VehiclesDeleteHandler).Methods("DELETE")
	r.HandleFunc("/updates", App.UpdatesHandler).Methods("GET")
	r.HandleFunc("/updates/message", App.UpdateMessageHandler).Methods("GET")
	r.HandleFunc("/routes", App.RoutesHandler).Methods("GET")
	r.HandleFunc("/routes/create", App.RoutesCreateHandler).Methods("POST")
	r.HandleFunc("/stops", App.StopsHandler).Methods("GET")
	r.HandleFunc("/stops/create", App.StopsCreateHandler).Methods("POST")
	r.HandleFunc("/schedule", Demo.ArrivalHandler).Methods("GET")
	r.HandleFunc("/schedule/arrival", Demo.ArrivalTimeHandler).Methods("GET")
	r.HandleFunc("/schedule/arrival/by", DemoUsers.SubscriberHandler).Methods("GET")
	// Static files
	r.PathPrefix("/bower_components/").Handler(http.StripPrefix("/bower_components/", http.FileServer(http.Dir("bower_components/"))))
	r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir("static/"))))
	// Serve requests
	http.Handle("/", r)
	if err := http.ListenAndServe(":8080", r); err != nil {
		log.Fatalf("Unable to ListenAndServe: %v", err)
	}
}
<commit_msg>Fixed mispelled var, to clarify just vehicle delete works<commit_after>package main

import (
	"net/http"
	"shuttle_tracking_2/demo"
	"shuttle_tracking_2/tracking"

	log "github.com/Sirupsen/logrus"
	"github.com/gorilla/mux"
)

var (
	// Config holds the global app settings.
	Config = tracking.InitConfig()
	// App holds the application itself.
	App       = tracking.InitApp(Config)
	Demo      = demo.Init()                    // initialize the demo
	DemoUsers = demo.UserCollectionInit(&Demo) // init users
)

// IndexHandler serves the index page.
func IndexHandler(w http.ResponseWriter, r *http.Request) {
	http.ServeFile(w, r, "index.html")
}

// AdminHandler serves the admin page.
func AdminHandler(w http.ResponseWriter, r *http.Request) {
	http.ServeFile(w, r, "admin.html")
}

func main() {
	// close Mongo session when server terminates
	defer App.Session.Close()

	// Start auto updater
	go App.UpdateShuttles(Config.DataFeed, Config.UpdateInterval)

	// Routing
	r := mux.NewRouter()
	r.HandleFunc("/", IndexHandler).Methods("GET")
	r.HandleFunc("/admin", AdminHandler).Methods("GET")
	r.HandleFunc("/admin/{*}", AdminHandler).Methods("GET")
	r.HandleFunc("/vehicles", App.VehiclesHandler).Methods("GET")
	r.HandleFunc("/vehicles/create", App.VehiclesCreateHandler).Methods("POST")
	r.HandleFunc("/vehicles/edit", App.VehiclesEditHandler).Methods("POST")
	r.HandleFunc("/vehicles/{id:[0-9]+}", App.VehiclesDeleteHandler).Methods("DELETE")
	r.HandleFunc("/updates", App.UpdatesHandler).Methods("GET")
	r.HandleFunc("/updates/message", App.UpdateMessageHandler).Methods("GET")
	r.HandleFunc("/routes", App.RoutesHandler).Methods("GET")
	r.HandleFunc("/routes/create", App.RoutesCreateHandler).Methods("POST")
	r.HandleFunc("/stops", App.StopsHandler).Methods("GET")
	r.HandleFunc("/stops/create", App.StopsCreateHandler).Methods("POST")
	r.HandleFunc("/schedule", Demo.ArrivalHandler).Methods("GET")
	r.HandleFunc("/schedule/arrival", Demo.ArrivalTimeHandler).Methods("GET")
	r.HandleFunc("/schedule/arrival/by", DemoUsers.SubscriberHandler).Methods("GET")
	// Static files
	r.PathPrefix("/bower_components/").Handler(http.StripPrefix("/bower_components/", http.FileServer(http.Dir("bower_components/"))))
	r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir("static/"))))
	// Serve requests
	http.Handle("/", r)
	if err := http.ListenAndServe(":8080", r); err != nil {
		log.Fatalf("Unable to ListenAndServe: %v", err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"os/signal"
	"strings"
	"syscall"
	"time"

	"github.com/twitchscience/aws_utils/environment"
	"github.com/twitchscience/aws_utils/listener"

	"github.com/twitchscience/rs_ingester/keyring"
	"github.com/twitchscience/scoop_protocol/scoop_protocol"

	"github.com/cactus/go-statsd-client/statsd"
	"github.com/crowdmob/goamz/aws"
	"github.com/crowdmob/goamz/sqs"
)

var (
	poolSize               int
	loggingDir             string
	statsPrefix            string
	scoopHost              string
	scoopScheme            string
	keyRing                = keyring.New()
	alreadyCheckedOutError = errors.New("TableName is checked out")
	env                    = environment.GetCloudEnv()
)

type Stats interface {
	Timing(stat string, delta int64, rate float32) error
	Close() error
}

type IngestHandler struct {
	Auth    scoop_protocol.ScoopSigner
	Statter Stats
}

func (i *IngestHandler) Handle(msg *sqs.Message) error {
	start := time.Now()

	log.Printf("got %s;%s\n", msg.Body, msg.MessageId)

	req, err := i.Auth.GetRowCopyRequest(strings.NewReader(msg.Body))
	if err != nil {
		return err
	}

	if !keyRing.Checkout(req.TableName) {
		return alreadyCheckedOutError
	}
	defer keyRing.Return(req.TableName)

	log.Printf("Sending RowCopy to scoop for %s\n", msg.MessageId)

	resp, err := http.Post(copyURL(), "application/json", strings.NewReader(msg.Body))
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)

	if err != nil {
		return err
	}

	if resp.StatusCode != http.StatusOK {
		log.Printf("Post failed with status code: %s body: %q", resp.Status, string(body))
		return errors.New(fmt.Sprintf("Post failed with status code: %s body: %q", resp.Status, string(body)))
	}

	log.Printf("Got res for %s as %v\n", msg.MessageId, err)

	i.Statter.Timing(req.TableName, int64(time.Now().Sub(start)), 1)
	return nil
}

func StartWorkers(addr *listener.SQSAddr, stats Stats) ([]*listener.SQSListener, error) {
	listeners := make([]*listener.SQSListener, poolSize)
	for i := 0; i < poolSize; i++ {
		listeners[i] = listener.BuildSQSListener(addr, &IngestHandler{
			Auth:    scoop_protocol.GetScoopSigner(),
			Statter: stats,
		}, 30*time.Second)
		go listeners[i].Listen()
	}
	return listeners, nil
}

func CloseListeners(listeners []*listener.SQSListener) {
	for _, l := range listeners {
		l.Close()
	}
}

func InitLogger(logDir string) (*os.File, error) {
	file, err := os.Create(
		fmt.Sprintf("%v/%v.%v.log", logDir, "Ingester", time.Now().Format("2006-01-02.15:04:00")))
	if err != nil {
		return nil, err
	}
	log.SetOutput(file)
	return file, nil
}

// copyURL builds and returns the scoop row copy URL from flags
func copyURL() string {
	u := url.URL{
		Scheme: scoopScheme,
		Host:   scoopHost,
		Path:   "/rows/copy",
	}
	return u.String()
}

func init() {
	flag.IntVar(&poolSize, "n_workers", 5, "how many connections to redshift should we form?")
	flag.StringVar(&loggingDir, "logging", "", "where are we logging")
	flag.StringVar(&statsPrefix, "statsPrefix", "ingester", "the prefix to statsd")
	flag.StringVar(&scoopHost, "scoopHost", "localhost:8080", "Scoop server host or host:port")
	flag.StringVar(&scoopScheme, "scoopScheme", "http", "Scoop server URL scheme (e.g. https)")
}

func main() {
	flag.Parse()

	_, err := InitLogger(loggingDir)
	if err != nil {
		log.Fatalln("Failed to start logger")
	}

	auth, err := aws.GetAuth("", "", "", time.Time{})
	if err != nil {
		log.Fatalln("Failed to recieve auth")
	}

	// Set up statsd monitoring
	// - If the env is not set up we wil use a noop connection
	statsdHostport := os.Getenv("STATSD_HOSTPORT")
	var stats Stats
	if statsdHostport == "" {
		// Error is meaningless here.
		stats, _ = statsd.NewNoop(statsdHostport, statsPrefix)
	} else {
		if stats, err = statsd.New(statsdHostport, statsPrefix); err != nil {
			log.Fatalf("Statsd configuration error: %v", err)
		}
		log.Printf("Connected to statsd at %s\n", statsdHostport)
	}

	listeners, err := StartWorkers(
		&listener.SQSAddr{
			Region:    aws.USWest2,
			QueueName: "spade-compactor-" + env,
			Auth:      auth,
		},
		stats,
	)

	if err != nil {
		log.Fatal(err)
	}

	wait := make(chan bool)

	sigc := make(chan os.Signal, 1)
	signal.Notify(sigc,
		syscall.SIGINT)
	go func() {
		<-sigc
		// Cause flush
		CloseListeners(listeners)
		stats.Close()
		wait <- true
	}()

	<-wait
}
<commit_msg>removed logging<commit_after>package main

import (
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"os/signal"
	"strings"
	"syscall"
	"time"

	"github.com/twitchscience/aws_utils/environment"
	"github.com/twitchscience/aws_utils/listener"

	"github.com/twitchscience/rs_ingester/keyring"
	"github.com/twitchscience/scoop_protocol/scoop_protocol"

	"github.com/cactus/go-statsd-client/statsd"
	"github.com/crowdmob/goamz/aws"
	"github.com/crowdmob/goamz/sqs"
)

var (
	poolSize               int
	loggingDir             string
	statsPrefix            string
	scoopHost              string
	scoopScheme            string
	keyRing                = keyring.New()
	alreadyCheckedOutError = errors.New("")
	env                    = environment.GetCloudEnv()
)

type Stats interface {
	Timing(stat string, delta int64, rate float32) error
	Close() error
}

type IngestHandler struct {
	Auth    scoop_protocol.ScoopSigner
	Statter Stats
}

func (i *IngestHandler) Handle(msg *sqs.Message) error {
	start := time.Now()

	req, err := i.Auth.GetRowCopyRequest(strings.NewReader(msg.Body))
	if err != nil {
		return err
	}

	if !keyRing.Checkout(req.TableName) {
		return alreadyCheckedOutError
	}
	defer keyRing.Return(req.TableName)

	resp, err := http.Post(copyURL(), "application/json", strings.NewReader(msg.Body))
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)

	if err != nil {
		return err
	}

	if resp.StatusCode != http.StatusOK {
		return errors.New(fmt.Sprintf("Post failed with status code: %s body: %q", resp.Status, string(body)))
	}

	i.Statter.Timing(req.TableName, int64(time.Now().Sub(start)), 1)
	return nil
}

func StartWorkers(addr *listener.SQSAddr, stats Stats) ([]*listener.SQSListener, error) {
	listeners := make([]*listener.SQSListener, poolSize)
	for i := 0; i < poolSize; i++ {
		listeners[i] = listener.BuildSQSListener(addr, &IngestHandler{
			Auth:    scoop_protocol.GetScoopSigner(),
			Statter: stats,
		}, 30*time.Second)
		go listeners[i].Listen()
	}
	return listeners, nil
}

func CloseListeners(listeners []*listener.SQSListener) {
	for _, l := range listeners {
		l.Close()
	}
}

func InitLogger(logDir string) (*os.File, error) {
	file, err := os.Create(
		fmt.Sprintf("%v/%v.%v.log", logDir, "Ingester", time.Now().Format("2006-01-02.15:04:00")))
	if err != nil {
		return nil, err
	}
	log.SetOutput(file)
	return file, nil
}

// copyURL builds and returns the scoop row copy URL from flags
func copyURL() string {
	u := url.URL{
		Scheme: scoopScheme,
		Host:   scoopHost,
		Path:   "/rows/copy",
	}
	return u.String()
}

func init() {
	flag.IntVar(&poolSize, "n_workers", 5, "how many connections to redshift should we form?")
	flag.StringVar(&loggingDir, "logging", "", "where are we logging")
	flag.StringVar(&statsPrefix, "statsPrefix", "ingester", "the prefix to statsd")
	flag.StringVar(&scoopHost, "scoopHost", "localhost:8080", "Scoop server host or host:port")
	flag.StringVar(&scoopScheme, "scoopScheme", "http", "Scoop server URL scheme (e.g. https)")
}

func main() {
	flag.Parse()

	_, err := InitLogger(loggingDir)
	if err != nil {
		log.Fatalln("Failed to start logger")
	}

	auth, err := aws.GetAuth("", "", "", time.Time{})
	if err != nil {
		log.Fatalln("Failed to recieve auth")
	}

	// Set up statsd monitoring
	// - If the env is not set up we wil use a noop connection
	statsdHostport := os.Getenv("STATSD_HOSTPORT")
	var stats Stats
	if statsdHostport == "" {
		// Error is meaningless here.
		stats, _ = statsd.NewNoop(statsdHostport, statsPrefix)
	} else {
		if stats, err = statsd.New(statsdHostport, statsPrefix); err != nil {
			log.Fatalf("Statsd configuration error: %v", err)
		}
		log.Printf("Connected to statsd at %s\n", statsdHostport)
	}

	listeners, err := StartWorkers(
		&listener.SQSAddr{
			Region:    aws.USWest2,
			QueueName: "spade-compactor-" + env,
			Auth:      auth,
		},
		stats,
	)

	if err != nil {
		log.Fatal(err)
	}

	wait := make(chan bool)

	sigc := make(chan os.Signal, 1)
	signal.Notify(sigc,
		syscall.SIGINT)
	go func() {
		<-sigc
		// Cause flush
		CloseListeners(listeners)
		stats.Close()
		wait <- true
	}()

	<-wait
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"net"
	"net/http"
	"regexp"
	"strings"

	"swapgur/config"
	"swapgur/backend"
	"swapgur/frontend"
)

var categories = []string{
	"random",
	"art",
	"aww",
	"funny",
	"gifs",
	"nature",
	"nsfw",
	"sports",
}

func main() {
	http.HandleFunc("/", RootHandler)
	log.Println("Starting ListenAndServer")
	http.ListenAndServe(config.ListenAddr, nil)
}

func categoryValid(category string) bool {
	for i := range categories {
		if categories[i] == category {
			return true
		}
	}
	return false
}

func RootHandler(w http.ResponseWriter, r *http.Request) {
	status, receiving := bidnessLogic(r)
	w.WriteHeader(status)

	pd := frontend.NewPageData(receiving, categories...)
	if err := frontend.Output(w, pd); err != nil {
		log.Println(err)
	}
}

var welcome = `The rules are easy - give an image, receive an image from a
random person in return. You must use the raw image link (ends in jpg, jpeg,
png, or gif). An example link would be http://i.imgur.com/vHWOYAU.gif`

var imgurDirectRegex = regexp.MustCompile(`^https?://i\.imgur\.com/[a-zA-Z0-9]+\.(jpg|jpeg|png|gif)$`)

func bidnessLogic(r *http.Request) (int, string) {
	pathData := getPathData(r)
	if pathData.category == "" {
		pathData.category = categories[0]
	}

	if !categoryValid(pathData.category) {
		log.Printf("Invalid category '%s' hit", pathData.category)
		return 404, frontend.PageError("Invalid category")

	}

	offering := strings.TrimSpace(r.PostFormValue("offering"))

	if !pathData.mooch {
		if offering == "" {
			return 200, frontend.PageParagraph(welcome)
		} else if !imgurDirectRegex.MatchString(offering) {
			return 400, frontend.PageError("Invalid URL")
		}
	}

	ip, err := determineIP(r)
	if err != nil {
		log.Printf("%s: determing ip")
		return 500, frontend.PageError("Internal Server Error :(")
	} else if !backend.IPCanSwap(ip, offering) {
		return 400, frontend.PageError("You have tried to swap that image too many times! Try a different one.")
	}

	var receiving string
	if pathData.mooch {
		receiving = backend.Get(pathData.category)
	} else {
		receiving = backend.Swap(pathData.category, offering)
	}

	if receiving == "" {
		return 500, frontend.PageError("Internal Server Error :(")
	}

	log.Printf(
		"category: `%s`, offered: '%s', received: '%s'",
		pathData.category,
		offering,
		receiving,
	)

	return 200, frontend.PageImage(receiving)
}

func determineIP(r *http.Request) (string, error) {
	if fips, ok := r.Header["X-Forwarded-IP"]; ok && len(fips) > 0 {
		return fips[0], nil
	}

	ip, _, err := net.SplitHostPort(r.RemoteAddr)
	return ip, err
}

type pathData struct {
	category string
	mooch    bool
}

func getPathData(r *http.Request) *pathData {
	path := r.URL.Path
	pathSplit := strings.Split(path, "/")
	pathData := pathData{}
	if len(pathSplit) > 1 {
		pathData.category = pathSplit[1]
	}

	if r.FormValue("mooch") != "" {
		pathData.mooch = true
	}

	return &pathData
}
<commit_msg>added defaults to the categories<commit_after>package main

import (
	"log"
	"net"
	"net/http"
	"regexp"
	"strings"

	"swapgur/config"
	"swapgur/backend"
	"swapgur/frontend"
)

var categories = []string{
	"random",
	"art",
	"aww",
	"funny",
	"gifs",
	"nature",
	"nsfw",
	"sports",
}

var categoryDefaults = []string{
	"http://i.imgur.com/vHWOYAU.gif", //random
	"http://i.imgur.com/D8CoAEd.jpg", //art
	"http://i.imgur.com/h2EiFHA.jpg", //aww
	"http://i.imgur.com/QnTc8BW.gif", //funny
	"http://i.imgur.com/QnTc8BW.gif", //gifs
	"http://i.imgur.com/Yavzdox.jpg", //nature
	"http://i.imgur.com/N8lL8H6.jpg", //nsfw
	"http://i.imgur.com/gUgkpTx.jpg", //sports
}

func main() {

	for i := range categoryDefaults {
		backend.Swap(categories[i], categoryDefaults[i])
	}

	http.HandleFunc("/", RootHandler)
	log.Println("Starting ListenAndServer")
	http.ListenAndServe(config.ListenAddr, nil)
}

func categoryValid(category string) bool {
	for i := range categories {
		if categories[i] == category {
			return true
		}
	}
	return false
}

func RootHandler(w http.ResponseWriter, r *http.Request) {
	status, receiving := bidnessLogic(r)
	w.WriteHeader(status)

	pd := frontend.NewPageData(receiving, categories...)
	if err := frontend.Output(w, pd); err != nil {
		log.Println(err)
	}
}

var welcome = `The rules are easy - give an image, receive an image from a
random person in return. You must use the raw image link (ends in jpg, jpeg,
png, or gif). An example link would be http://i.imgur.com/vHWOYAU.gif`

var imgurDirectRegex = regexp.MustCompile(`^https?://i\.imgur\.com/[a-zA-Z0-9]+\.(jpg|jpeg|png|gif)$`)

func bidnessLogic(r *http.Request) (int, string) {
	pathData := getPathData(r)
	if pathData.category == "" {
		pathData.category = categories[0]
	}

	if !categoryValid(pathData.category) {
		log.Printf("Invalid category '%s' hit", pathData.category)
		return 404, frontend.PageError("Invalid category")

	}

	offering := strings.TrimSpace(r.PostFormValue("offering"))

	if !pathData.mooch {
		if offering == "" {
			return 200, frontend.PageParagraph(welcome)
		} else if !imgurDirectRegex.MatchString(offering) {
			return 400, frontend.PageError("Invalid URL")
		}
	}

	ip, err := determineIP(r)
	if err != nil {
		log.Printf("%s: determing ip")
		return 500, frontend.PageError("Internal Server Error :(")
	} else if !backend.IPCanSwap(ip, offering) {
		return 400, frontend.PageError("You have tried to swap that image too many times! Try a different one.")
	}

	var receiving string
	if pathData.mooch {
		receiving = backend.Get(pathData.category)
	} else {
		receiving = backend.Swap(pathData.category, offering)
	}

	if receiving == "" {
		return 500, frontend.PageError("Internal Server Error :(")
	}

	log.Printf(
		"category: `%s`, offered: '%s', received: '%s'",
		pathData.category,
		offering,
		receiving,
	)

	return 200, frontend.PageImage(receiving)
}

func determineIP(r *http.Request) (string, error) {
	if fips, ok := r.Header["X-Forwarded-IP"]; ok && len(fips) > 0 {
		return fips[0], nil
	}

	ip, _, err := net.SplitHostPort(r.RemoteAddr)
	return ip, err
}

type pathData struct {
	category string
	mooch    bool
}

func getPathData(r *http.Request) *pathData {
	path := r.URL.Path
	pathSplit := strings.Split(path, "/")
	pathData := pathData{}
	if len(pathSplit) > 1 {
		pathData.category = pathSplit[1]
	}

	if r.FormValue("mooch") != "" {
		pathData.mooch = true
	}

	return &pathData
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"flag"
	"fmt"
	"log"
	"net"
	"strconv"
	"strings"
	"time"

	"github.com/aerospike/aerospike-client-go"
)

type Config struct {
	Hosts     []string
	Namespace string
	Sets      []string
	Timeout   time.Duration
}

type ProcConfig struct {
	Client    *aerospike.Client
	Namespace string
	Set       string
	Done      <-chan error
}

const defaultPort = 3000

type ErrBroadcaster struct {
	listeners []chan error
	input     chan error
}

func (this *ErrBroadcaster) AddListener(ch chan error) { this.listeners = append(this.listeners, ch) }
func (this *ErrBroadcaster) Input() chan<- error       { return this.input }

func (this *ErrBroadcaster) Listen() {
	for err := range this.input {
		for i := range this.listeners {
			go func(listener chan error) {
				listener <- err
			}(this.listeners[i])
		}
	}
}

func main() {
	c := getConfig()
	client, err := connectToAerospike(c.Hosts)
	if err != nil {
		log.Fatal(err.Error())
	}
	client.DefaultScanPolicy = aerospike.NewScanPolicy()
	client.DefaultScanPolicy.Timeout = c.Timeout

	client.DefaultWritePolicy = aerospike.NewWritePolicy()
	client.DefaultWritePolicy.Timeout = c.Timeout

	nodes := client.GetNodes()
	if len(nodes) == 0 {
		log.Fatal("no aerospike nodes found")
	}

	log.Printf("received '%d' nodes, will be using first one to get lists of sets\n", len(nodes))
	conn, err := nodes[0].GetConnection(5 * time.Second)
	if err != nil {
		log.Fatal(err.Error())
	}

	infoMap, err := aerospike.RequestInfo(conn, "sets")
	if err != nil {
		log.Fatal(err.Error())
	}

	sets := extractSets(infoMap["sets"])

}

func getKeys(config *ProcConfig) (keyChan <-chan aerospike.Key) {
	errChan = make(chan error)
	keyChan = make(chan aerospike.Key)

	rs, err := client.ScanAll(nil, namespace, setName)
	if err != nil {
		errChan <- err
		return
	}

	var errOccurred error

	go func() {
		err <- errChan

	}()

	go func() {
		defer close(keyChan)
		for record := range rs.Results() {
			if record.Err != nil {
				errChan <- record.Err
				return
			}

			keyChan <- *record.Record.Key
		}
		return
	}()

	return
}

func deleteKeys(client *aerospike.Client, ns, set string, bufferSize int, keyChan <-chan aerospike.Key, errChan <-chan error) {

	buffer := make([]aerospike.Key, bufferSize, bufferSize)
	i := 0
	for {
		if i >= bufferSize {
			go func(buf []aerospike.Key, errChan chan error) {
				log.Printf("Trying to delete %d records...", len(buffer))
				deleted := 0
				for i := range buf {
					ok, err := client.Delete(policy, key)
					if err != nil {
						errChan <- err
						return
					}
					if ok {
						deleted++
					}
				}
				log.Printf("Delete %d of %d records...", deleted, len(buffer))

			}(buffer)

			buffer = make([]aerospike.Key, bufferSize, bufferSize)
		}
		select {
		case key <- keyChan:
			buffer = append(buffer, keyChan)
		case err <- errChan:
		}

		i++

	}

	for key := range keyChan {

	}

	// when keyChan is closed, that means we have something in errChan

}

func extractSets(infoStr string) []string {
	opts := strings.Split(infoStr, ":")
	sets := []string{}
	for _, opt := range opts {
		if opt[:9] == "set_name=" {
			sets = append(sets, opt[9:])
		}
	}

	return sets
}

func connectToAerospike(hostStrings []string) (*aerospike.Client, error) {
	if len(hostStrings) == 0 {
		return nil, errors.New("no aerospike host provided")
	}

	hosts := make([]*aerospike.Host, len(hostStrings))
	for i, connStr := range hostStrings {
		hostStr, portStr, err := net.SplitHostPort(connStr)
		if err != nil {
			if isErrNoPort(err) {
				hosts[i] = aerospike.NewHost(connStr, defaultPort)
				continue
			}
			return nil, fmt.Errorf("could not split host string '%s' by host and port: %s", connStr, err.Error())
		}

		port, err := strconv.Atoi(portStr)
		if err != nil {
			return nil, fmt.Errorf("could determine port number from string '%s': %s", connStr, err.Error())
		}
		hosts[i] = aerospike.NewHost(hostStr, port)
	}

	return aerospike.NewClientWithPolicyAndHost(nil, hosts...)
}

func isErrNoPort(err error) bool {
	if addrErr, ok := err.(*net.AddrError); ok {
		return addrErr.Err == "missing port in address"
	}

	return false
}

func getConfig() (c Config) {
	var hostsStr string
	var setsStr string

	flag.StringVar(&hostsStr, "h", "localhost:3000", "Comma-separated list of aerospike hosts")
	flag.StringVar(&c.Namespace, "n", "", "Data namespace")
	flag.StringVar(&setsStr, "s", "", "Comma-separated list of set names to erase")

	flag.Parse()

	c.Hosts = strings.Split(hostsStr, ",")
	c.Sets = strings.Split(setsStr, ",")

	return
}
<commit_msg>Added configs for timeout and buffersize. Looks working, need field tests though<commit_after>package main

import (
	"errors"
	"flag"
	"fmt"
	"log"
	"net"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/aerospike/aerospike-client-go"
)

type Config struct {
	Hosts      []string
	Namespace  string
	Sets       []string
	BufferSize int
	Timeout    time.Duration
}

type ProcConfig struct {
	Client    *aerospike.Client
	Namespace string
	Set       string
	Done      chan<- error
}

type Processor func()

const defaultPort = 3000

type ErrBroadcaster struct {
	listeners []chan<- error
	input     chan error
}

func NewErrBroadcaster() *ErrBroadcaster {
	return &ErrBroadcaster{
		listeners: []chan<- error{},
		input:     make(chan error),
	}
}

func (this *ErrBroadcaster) AddListener(ch chan<- error) { this.listeners = append(this.listeners, ch) }
func (this *ErrBroadcaster) Input() chan<- error         { return this.input }

func (this *ErrBroadcaster) Listen() {
	for err := range this.input {
		for i := range this.listeners {
			go func(listener chan<- error) {
				listener <- err
			}(this.listeners[i])
		}
	}
}

func main() {
	c := getConfig()
	client, err := connectToAerospike(c.Hosts)
	if err != nil {
		log.Fatal(err.Error())
	}
	client.DefaultScanPolicy = aerospike.NewScanPolicy()
	client.DefaultScanPolicy.Timeout = c.Timeout

	client.DefaultWritePolicy = aerospike.NewWritePolicy(0, 0)
	client.DefaultWritePolicy.Timeout = c.Timeout

	nodes := client.GetNodes()
	if len(nodes) == 0 {
		log.Fatal("no aerospike nodes found")
	}

	log.Printf("received '%d' nodes, will be using first one to get lists of sets", len(nodes))
	conn, err := nodes[0].GetConnection(5 * time.Second)
	if err != nil {
		log.Fatal(err.Error())
	}

	infoMap, err := aerospike.RequestInfo(conn, "sets")
	if err != nil {
		log.Fatal(err.Error())
	}

	sets := extractSets(infoMap["sets"])

	var wg sync.WaitGroup

	for _, set := range sets {
		log.Printf("Starting removing data from set %s", set)
		wg.Add(1)
		func(set string) {
			defer wg.Done()
			broadcaster := NewErrBroadcaster()

			pc := &ProcConfig{
				Client:    client,
				Namespace: c.Namespace,
				Set:       set,
				Done:      broadcaster.Input(),
			}

			kg, keyChan, kgErrChan := getKeysGetter(pc)
			kr, finishChan, krErrChan := getKeysRemover(pc, c.BufferSize, keyChan)
			output := make(chan error)

			broadcaster.AddListener(kgErrChan)
			broadcaster.AddListener(krErrChan)
			broadcaster.AddListener(output)
			go broadcaster.Listen()

			go kg()
			go kr()

			select {
			case <-output:
			case <-finishChan:
				log.Printf("Cleaning set %s completed\n\n", set)
			}
		}(set)
	}

	wg.Wait()
}

func getKeysGetter(config *ProcConfig) (Processor, <-chan aerospike.Key, chan<- error) {
	keyChan := make(chan aerospike.Key)
	errChan := make(chan error)

	var errBroadcast error
	go func() {
		errBroadcast = <-errChan
	}()

	var p Processor = func() {
		defer close(keyChan)

		rs, err := config.Client.ScanAll(nil, config.Namespace, config.Set)
		if err != nil {
			config.Done <- err
			return
		}
		for record := range rs.Results() {
			if errBroadcast != nil {
				log.Printf("Getting keys aborted. Reason: %s", errBroadcast.Error())
				return
			}
			if record.Err != nil {
				config.Done <- record.Err
				return
			}

			keyChan <- *record.Record.Key
		}
	}

	return p, keyChan, errChan
}

func getKeysRemover(config *ProcConfig, bufferSize int, keyChan <-chan aerospike.Key) (Processor, <-chan string, chan<- error) {
	errChan := make(chan error)
	doneChan := make(chan string)

	var errBroadcast error
	go func() {
		errBroadcast = <-errChan
	}()

	var wg sync.WaitGroup

	var p Processor = func() {
		buffer := make([]aerospike.Key, 0, bufferSize)

		for key := range keyChan {
			if len(buffer) == bufferSize {
				wg.Add(1)
				go removeKeys(config.Client, buffer, config.Done, &wg)

				buffer = make([]aerospike.Key, 0, bufferSize)
			}

			if errBroadcast != nil {
				log.Printf("removing keys aborted. Reason: %s", errBroadcast.Error())
				return
			}

			buffer = append(buffer, key)
		}

		if len(buffer) > 0 {
			wg.Add(1)
			go removeKeys(config.Client, buffer, config.Done, &wg)
		}

		wg.Wait()

		doneChan <- config.Set
	}

	return p, doneChan, errChan
}

func removeKeys(client *aerospike.Client, keys []aerospike.Key, errChan chan<- error, wg *sync.WaitGroup) {
	defer wg.Done()

	log.Printf("Removing %d keys...", len(keys))
	removed := 0
	for i := range keys {
		if ok, err := client.Delete(nil, &keys[i]); err != nil {
			errChan <- err
			return
		} else if ok {
			removed++
		}
	}
	log.Printf("Removed %d of %d keys...", removed, len(keys))
}

func extractSets(infoStr string) []string {
	opts := strings.Split(infoStr, ":")
	sets := []string{}
	for _, opt := range opts {
		if opt[:9] == "set_name=" {
			sets = append(sets, opt[9:])
		}
	}

	return sets
}

func connectToAerospike(hostStrings []string) (*aerospike.Client, error) {
	if len(hostStrings) == 0 {
		return nil, errors.New("no aerospike host provided")
	}

	hosts := make([]*aerospike.Host, len(hostStrings))
	for i, connStr := range hostStrings {
		hostStr, portStr, err := net.SplitHostPort(connStr)
		if err != nil {
			if isErrNoPort(err) {
				hosts[i] = aerospike.NewHost(connStr, defaultPort)
				continue
			}
			return nil, fmt.Errorf("could not split host string '%s' by host and port: %s", connStr, err.Error())
		}

		port, err := strconv.Atoi(portStr)
		if err != nil {
			return nil, fmt.Errorf("could determine port number from string '%s': %s", connStr, err.Error())
		}
		hosts[i] = aerospike.NewHost(hostStr, port)
	}

	return aerospike.NewClientWithPolicyAndHost(nil, hosts...)
}

func isErrNoPort(err error) bool {
	if addrErr, ok := err.(*net.AddrError); ok {
		return addrErr.Err == "missing port in address"
	}

	return false
}

func getConfig() (c Config) {
	var hostsStr string
	var setsStr string

	flag.StringVar(&hostsStr, "h", "localhost:3000", "Comma-separated list of aerospike hosts")
	flag.StringVar(&c.Namespace, "n", "", "Data namespace")
	flag.StringVar(&setsStr, "s", "", "Comma-separated list of set names to erase")
	flag.IntVar(&c.BufferSize, "buffer", 25000, "Size of the buffer to pre-load keys before deleting")
	flag.DurationVar(&c.Timeout, "timeout", 5*time.Second, "Connection timeout")

	flag.Parse()

	c.Hosts = strings.Split(hostsStr, ",")
	c.Sets = strings.Split(setsStr, ",")

	return
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"io"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"time"

	"github.com/go-fsnotify/fsnotify"
	_ "github.com/mjibson/mog/codec/mpa"
	_ "github.com/mjibson/mog/codec/nsf"
	_ "github.com/mjibson/mog/protocol/file"
	_ "github.com/mjibson/mog/protocol/gmusic"
	"github.com/mjibson/mog/server"
)

var (
	flagWatch = flag.Bool("w", false, "watch current directory and exit on changes; for use with an autorestarter")
)

func main() {
	flag.Parse()
	if *flagWatch {
		watch(".", "*.go", quit)
		jsx := run("jsx", "server/static/src", "server/static/scripts")
		watch("server/static/src", "*.js", jsx)
		jsx()
	}
	log.Fatal(server.ListenAndServe(":6601"))
}

func quit() {
	os.Exit(0)
}

func run(name string, arg ...string) func() {
	return func() {
		log.Println("running", name)
		c := exec.Command(name, arg...)
		stdout, err := c.StdoutPipe()
		if err != nil {
			log.Fatal(err)
		}
		stderr, err := c.StderrPipe()
		if err != nil {
			log.Fatal(err)
		}
		if err := c.Start(); err != nil {
			log.Fatal(err)
		}
		go func() { io.Copy(os.Stdout, stdout) }()
		go func() { io.Copy(os.Stderr, stderr) }()
		if err := c.Wait(); err != nil {
			log.Printf("run error: %v: %v", name, err)
		}
		log.Println("run complete:", name)
	}
}

func watch(root, pattern string, f func()) {
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		log.Fatal(err)
	}
	filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
		if matched, err := filepath.Match(pattern, info.Name()); err != nil {
			log.Fatal(err)
		} else if !matched {
			return nil
		}
		err = watcher.Add(path)
		if err != nil {
			log.Fatal(err)
		}
		return nil
	})
	log.Println("watching", pattern, "in", root)
	wait := time.Now()
	go func() {
		for {
			select {
			case event := <-watcher.Events:
				if wait.After(time.Now()) {
					continue
				}
				if event.Op&fsnotify.Write == fsnotify.Write {
					f()
					wait = time.Now().Add(time.Second * 2)
				}
			case err := <-watcher.Errors:
				log.Println("error:", err)
			}
		}
	}()
}
<commit_msg>Use gopkg.in<commit_after>package main

import (
	"flag"
	"io"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"time"

	_ "github.com/mjibson/mog/codec/mpa"
	_ "github.com/mjibson/mog/codec/nsf"
	_ "github.com/mjibson/mog/protocol/file"
	_ "github.com/mjibson/mog/protocol/gmusic"
	"github.com/mjibson/mog/server"
	"gopkg.in/fsnotify.v1"
)

var (
	flagWatch = flag.Bool("w", false, "watch current directory and exit on changes; for use with an autorestarter")
)

func main() {
	flag.Parse()
	if *flagWatch {
		watch(".", "*.go", quit)
		jsx := run("jsx", "server/static/src", "server/static/scripts")
		watch("server/static/src", "*.js", jsx)
		jsx()
	}
	log.Fatal(server.ListenAndServe(":6601"))
}

func quit() {
	os.Exit(0)
}

func run(name string, arg ...string) func() {
	return func() {
		log.Println("running", name)
		c := exec.Command(name, arg...)
		stdout, err := c.StdoutPipe()
		if err != nil {
			log.Fatal(err)
		}
		stderr, err := c.StderrPipe()
		if err != nil {
			log.Fatal(err)
		}
		if err := c.Start(); err != nil {
			log.Fatal(err)
		}
		go func() { io.Copy(os.Stdout, stdout) }()
		go func() { io.Copy(os.Stderr, stderr) }()
		if err := c.Wait(); err != nil {
			log.Printf("run error: %v: %v", name, err)
		}
		log.Println("run complete:", name)
	}
}

func watch(root, pattern string, f func()) {
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		log.Fatal(err)
	}
	filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
		if matched, err := filepath.Match(pattern, info.Name()); err != nil {
			log.Fatal(err)
		} else if !matched {
			return nil
		}
		err = watcher.Add(path)
		if err != nil {
			log.Fatal(err)
		}
		return nil
	})
	log.Println("watching", pattern, "in", root)
	wait := time.Now()
	go func() {
		for {
			select {
			case event := <-watcher.Events:
				if wait.After(time.Now()) {
					continue
				}
				if event.Op&fsnotify.Write == fsnotify.Write {
					f()
					wait = time.Now().Add(time.Second * 2)
				}
			case err := <-watcher.Errors:
				log.Println("error:", err)
			}
		}
	}()
}
<|endoftext|>


<commit_before>// Copyright 2015 Florian Orben. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.

// prettybenchmark: format go benchmarks into tables
//
// Usage: Pipe your benchmark results into "pb"
//    go test -bench=. [-benchmem] | pb
package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"os"
	"regexp"
	"sort"
	"strconv"
	"strings"
	"time"

	"github.com/apcera/termtables"
)

var (
	byWhitespace = regexp.MustCompile(`\s+`)
	byRuns       = regexp.MustCompile(`-\d+$`)
	byIterations = regexp.MustCompile(`(?i:)(Benchmark_?)`)
)

type (
	Foo       struct{}
	benchmark struct {
		info    *benchmarkInfo
		results *results
	}
	benchmarkInfo struct {
		hasFnIterations bool
		benchmemUsed    bool
		suggestedTiming string
	}
	results map[string][]*result
	result  struct {
		Name         string
		FnIterations int
		Runs         int
		Speed        float64
		Bps          int
		Aps          int
	}
)

type sortByFnIterations []*result

func (b sortByFnIterations) Len() int           { return len(b) }
func (b sortByFnIterations) Swap(i, j int)      { b[i], b[j] = b[j], b[i] }
func (b sortByFnIterations) Less(i, j int) bool { return b[i].FnIterations < b[j].FnIterations }

var (
	lines [][]byte
	table *termtables.Table
	bench *benchmark
)

func main() {

	reader := bufio.NewReader(os.Stdin)
	quit := make(chan bool)
	go loading(quit)

	for {
		text, err := reader.ReadBytes('\n')
		if err != nil {
			if err != io.EOF {
				panic(err)
			}
			break
		}
		lines = append(lines, text)
	}
	close(quit)

	bench = newBenchmark(lines)

	table = termtables.CreateTable()
	addTableHeader(table)
	addTableBody(table)

	fmt.Print("\r \n")
	fmt.Println(table.Render())
	fmt.Println(footer())
}

func newBenchmark(l [][]byte) *benchmark {
	results := newResults(l)
	return &benchmark{
		info:    newBenchmarkInfo(results),
		results: results,
	}
}

func newResults(l [][]byte) *results {
	benchMap := make(results)

	for _, l := range l[1 : len(l)-1] {
		bl := newResult(l)
		if bl != nil {
			if _, ok := benchMap[bl.Name]; !ok {
				benchMap[bl.Name] = make([]*result, 0)
			}
			benchMap[bl.Name] = append(benchMap[bl.Name], bl)
		}
	}

	for _, r := range benchMap {
		sort.Sort(sortByFnIterations(r))
	}

	return &benchMap
}

func newResult(b []byte) *result {
	var (
		name   string
		fnIter int
		bps    int
		aps    int
		err    error
		iter   int
		speed  float64
	)

	s := string(b)
	parts := byWhitespace.Split(s, -1)
	nameRuns := byRuns.ReplaceAllString(parts[0], "")
	nameIterations := byIterations.ReplaceAllString(nameRuns, "")
	lastIndex := strings.LastIndex(nameIterations, "_")

	if lastIndex > -1 {
		name = nameIterations[:lastIndex]
		fnIter, _ = strconv.Atoi(nameIterations[lastIndex+1:])
	} else {
		name = nameIterations
		fnIter = -1
	}

	//just print the line if it doesn't have the correct format
	if len(parts) < 4 {
		fmt.Println(s)
		return nil
	}

	iter, err = strconv.Atoi(parts[1])
	if err != nil {
		iter = -1
	}
	speed, err = strconv.ParseFloat(parts[2], 64)
	if err != nil {
		speed = -1
	}

	if len(parts) > 5 {
		bps, err = strconv.Atoi(parts[4])
		if err != nil {
			bps = -1
		}
		aps, err = strconv.Atoi(parts[6])
		if err != nil {
			aps = -1
		}
	} else {

		//without benchmem
		bps = -1
		aps = -1
	}

	return &result{
		Name:         name,
		FnIterations: fnIter,
		Runs:         iter,
		Speed:        speed,
		Bps:          bps,
		Aps:          aps,
	}
}

func newBenchmarkInfo(r *results) *benchmarkInfo {
	var (
		slowest         float64
		hasFnIterations bool
		benchmemUsed    bool
		suggestedTiming string
	)
	suggestedTiming = "ns"

	for _, bl := range *r {
		for _, l := range bl {

			if l.FnIterations > -1 {
				hasFnIterations = true
			}

			if l.Aps > -1 && l.Bps > -1 {
				benchmemUsed = true
			}

			if slowest < l.Speed {
				slowest = l.Speed
			}
		}
	}

	switch {
	case slowest <= 1e3:
		suggestedTiming = "ns"
	case slowest > 1e3 && slowest <= 1e6:
		suggestedTiming = "µs"
		updateSpeedVals(r, float64(1e3))
	case slowest > 1e6 && slowest <= 1e9:
		suggestedTiming = "ms"
		updateSpeedVals(r, float64(1e6))
	case slowest > 1e9:
		suggestedTiming = "s"
		updateSpeedVals(r, float64(1e9))
	}

	return &benchmarkInfo{hasFnIterations, benchmemUsed, suggestedTiming}
}

func updateSpeedVals(r *results, f float64) {
	for _, bl := range *r {
		for _, l := range bl {
			l.Speed = l.Speed / f
		}
	}
}

func footer() string {

	lastLine := bytes.Replace(
		bytes.TrimSpace(lines[len(lines)-1]),
		[]byte{9},
		[]byte{32, 32, 32, 32, 32},
		-1,
	)
	footer := make([]byte, 0, len(lastLine)*2+1)

	footer = append(
		footer,
		lastLine...,
	)

	footer = append(footer, byte(10))
	footer = append(footer, byte(43))
	for i := 0; i < len(lastLine)-2; i++ {
		footer = append(footer, byte(45))
	}
	footer = append(footer, byte(43))

	return bold(string(footer))
}

func addTableHeader(t *termtables.Table) {
	if bench.info.benchmemUsed {
		if bench.info.hasFnIterations {
			t.AddHeaders(bold("Name"), bold("Iterations"), bold("Runs"), bold(bench.info.suggestedTiming+"/op"), bold("B/op"), bold("allocations/op"), "")
		} else {
			t.AddHeaders(bold("Name"), bold("Runs"), bold(bench.info.suggestedTiming+"/op"), bold("B/op"), bold("allocations/op"), "")
		}
	} else {
		if bench.info.hasFnIterations {
			t.AddHeaders(bold("Name"), bold("Iterations"), bold("Runs"), bold(bench.info.suggestedTiming+"/op"), "")
		} else {
			t.AddHeaders(bold("Name"), bold("Runs"), bold(bench.info.suggestedTiming+"/op"), "")
		}
	}
}

func addTableBody(t *termtables.Table) {
	i := len(*bench.results)
	sorted := make([]string, 0, i)
	for name := range *bench.results {
		sorted = append(sorted, name)
	}
	sort.Sort(sort.StringSlice(sorted))

	for _, benchName := range sorted {
		results := (*bench.results)[benchName]

		for j, b := range results {
			var name string
			if j == 0 {
				name = bold(b.Name)
			}

			if bench.info.benchmemUsed {
				if bench.info.hasFnIterations {
					fnIterations := strconv.Itoa(b.FnIterations)

					if fnIterations == "-1" {
						fnIterations = ""
					}

					t.AddRow(name, fnIterations, b.Runs, b.Speed, b.Bps, b.Aps, "⬅")
				} else {
					t.AddRow(name, b.Runs, b.Speed, b.Bps, b.Aps, "⬅")
				}
			} else {
				if bench.info.hasFnIterations {
					fnIterations := strconv.Itoa(b.FnIterations)

					if fnIterations == "-1" {
						fnIterations = ""
					}

					t.AddRow(name, fnIterations, b.Runs, b.Speed, "⬅")
				} else {
					t.AddRow(name, b.Runs, b.Speed, "⬅")
				}
			}
		}

		i--
		if i > 0 {
			t.AddSeparator()
		}
	}

	t.SetAlign(termtables.AlignLeft, 1)
	t.SetAlign(termtables.AlignRight, 2)
	t.SetAlign(termtables.AlignRight, 3)
	t.SetAlign(termtables.AlignRight, 4)
	t.SetAlign(termtables.AlignRight, 5)
	t.SetAlign(termtables.AlignRight, 6)
}

func loading(q chan bool) {
	states := []string{"|", "/", "-", "\\", "|", "/", "–", "\\"}
	current := 0

	for {
		select {
		case <-time.Tick(150 * time.Millisecond):
			fmt.Printf("\r%s", states[current])
			if current == len(states)-1 {
				current = 0
			} else {
				current++
			}
		case <-q:
			break
		}
	}
}

func bold(s string) string {
	return fmt.Sprintf("\033[1m%s\033[0m", s)
}
<commit_msg>fix a typo<commit_after>// Copyright 2015 Florian Orben. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.

// prettybenchmarks: format go benchmarks into tables
//
// Usage: Pipe your benchmark results into "pb"
//    go test -bench=. [-benchmem] | pb
package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"os"
	"regexp"
	"sort"
	"strconv"
	"strings"
	"time"

	"github.com/apcera/termtables"
)

var (
	byWhitespace = regexp.MustCompile(`\s+`)
	byRuns       = regexp.MustCompile(`-\d+$`)
	byIterations = regexp.MustCompile(`(?i:)(Benchmark_?)`)
)

type (
	Foo       struct{}
	benchmark struct {
		info    *benchmarkInfo
		results *results
	}
	benchmarkInfo struct {
		hasFnIterations bool
		benchmemUsed    bool
		suggestedTiming string
	}
	results map[string][]*result
	result  struct {
		Name         string
		FnIterations int
		Runs         int
		Speed        float64
		Bps          int
		Aps          int
	}
)

type sortByFnIterations []*result

func (b sortByFnIterations) Len() int           { return len(b) }
func (b sortByFnIterations) Swap(i, j int)      { b[i], b[j] = b[j], b[i] }
func (b sortByFnIterations) Less(i, j int) bool { return b[i].FnIterations < b[j].FnIterations }

var (
	lines [][]byte
	table *termtables.Table
	bench *benchmark
)

func main() {

	reader := bufio.NewReader(os.Stdin)
	quit := make(chan bool)
	go loading(quit)

	for {
		text, err := reader.ReadBytes('\n')
		if err != nil {
			if err != io.EOF {
				panic(err)
			}
			break
		}
		lines = append(lines, text)
	}
	close(quit)

	bench = newBenchmark(lines)

	table = termtables.CreateTable()
	addTableHeader(table)
	addTableBody(table)

	fmt.Print("\r \n")
	fmt.Println(table.Render())
	fmt.Println(footer())
}

func newBenchmark(l [][]byte) *benchmark {
	results := newResults(l)
	return &benchmark{
		info:    newBenchmarkInfo(results),
		results: results,
	}
}

func newResults(l [][]byte) *results {
	benchMap := make(results)

	for _, l := range l[1 : len(l)-1] {
		bl := newResult(l)
		if bl != nil {
			if _, ok := benchMap[bl.Name]; !ok {
				benchMap[bl.Name] = make([]*result, 0)
			}
			benchMap[bl.Name] = append(benchMap[bl.Name], bl)
		}
	}

	for _, r := range benchMap {
		sort.Sort(sortByFnIterations(r))
	}

	return &benchMap
}

func newResult(b []byte) *result {
	var (
		name   string
		fnIter int
		bps    int
		aps    int
		err    error
		iter   int
		speed  float64
	)

	s := string(b)
	parts := byWhitespace.Split(s, -1)
	nameRuns := byRuns.ReplaceAllString(parts[0], "")
	nameIterations := byIterations.ReplaceAllString(nameRuns, "")
	lastIndex := strings.LastIndex(nameIterations, "_")

	if lastIndex > -1 {
		name = nameIterations[:lastIndex]
		fnIter, _ = strconv.Atoi(nameIterations[lastIndex+1:])
	} else {
		name = nameIterations
		fnIter = -1
	}

	//just print the line if it doesn't have the correct format
	if len(parts) < 4 {
		fmt.Println(s)
		return nil
	}

	iter, err = strconv.Atoi(parts[1])
	if err != nil {
		iter = -1
	}
	speed, err = strconv.ParseFloat(parts[2], 64)
	if err != nil {
		speed = -1
	}

	if len(parts) > 5 {
		bps, err = strconv.Atoi(parts[4])
		if err != nil {
			bps = -1
		}
		aps, err = strconv.Atoi(parts[6])
		if err != nil {
			aps = -1
		}
	} else {

		//without benchmem
		bps = -1
		aps = -1
	}

	return &result{
		Name:         name,
		FnIterations: fnIter,
		Runs:         iter,
		Speed:        speed,
		Bps:          bps,
		Aps:          aps,
	}
}

func newBenchmarkInfo(r *results) *benchmarkInfo {
	var (
		slowest         float64
		hasFnIterations bool
		benchmemUsed    bool
		suggestedTiming string
	)
	suggestedTiming = "ns"

	for _, bl := range *r {
		for _, l := range bl {

			if l.FnIterations > -1 {
				hasFnIterations = true
			}

			if l.Aps > -1 && l.Bps > -1 {
				benchmemUsed = true
			}

			if slowest < l.Speed {
				slowest = l.Speed
			}
		}
	}

	switch {
	case slowest <= 1e3:
		suggestedTiming = "ns"
	case slowest > 1e3 && slowest <= 1e6:
		suggestedTiming = "µs"
		updateSpeedVals(r, float64(1e3))
	case slowest > 1e6 && slowest <= 1e9:
		suggestedTiming = "ms"
		updateSpeedVals(r, float64(1e6))
	case slowest > 1e9:
		suggestedTiming = "s"
		updateSpeedVals(r, float64(1e9))
	}

	return &benchmarkInfo{hasFnIterations, benchmemUsed, suggestedTiming}
}

func updateSpeedVals(r *results, f float64) {
	for _, bl := range *r {
		for _, l := range bl {
			l.Speed = l.Speed / f
		}
	}
}

func footer() string {

	lastLine := bytes.Replace(
		bytes.TrimSpace(lines[len(lines)-1]),
		[]byte{9},
		[]byte{32, 32, 32, 32, 32},
		-1,
	)
	footer := make([]byte, 0, len(lastLine)*2+1)

	footer = append(
		footer,
		lastLine...,
	)

	footer = append(footer, byte(10))
	footer = append(footer, byte(43))
	for i := 0; i < len(lastLine)-2; i++ {
		footer = append(footer, byte(45))
	}
	footer = append(footer, byte(43))

	return bold(string(footer))
}

func addTableHeader(t *termtables.Table) {
	if bench.info.benchmemUsed {
		if bench.info.hasFnIterations {
			t.AddHeaders(bold("Name"), bold("Iterations"), bold("Runs"), bold(bench.info.suggestedTiming+"/op"), bold("B/op"), bold("allocations/op"), "")
		} else {
			t.AddHeaders(bold("Name"), bold("Runs"), bold(bench.info.suggestedTiming+"/op"), bold("B/op"), bold("allocations/op"), "")
		}
	} else {
		if bench.info.hasFnIterations {
			t.AddHeaders(bold("Name"), bold("Iterations"), bold("Runs"), bold(bench.info.suggestedTiming+"/op"), "")
		} else {
			t.AddHeaders(bold("Name"), bold("Runs"), bold(bench.info.suggestedTiming+"/op"), "")
		}
	}
}

func addTableBody(t *termtables.Table) {
	i := len(*bench.results)
	sorted := make([]string, 0, i)
	for name := range *bench.results {
		sorted = append(sorted, name)
	}
	sort.Sort(sort.StringSlice(sorted))

	for _, benchName := range sorted {
		results := (*bench.results)[benchName]

		for j, b := range results {
			var name string
			if j == 0 {
				name = bold(b.Name)
			}

			if bench.info.benchmemUsed {
				if bench.info.hasFnIterations {
					fnIterations := strconv.Itoa(b.FnIterations)

					if fnIterations == "-1" {
						fnIterations = ""
					}

					t.AddRow(name, fnIterations, b.Runs, b.Speed, b.Bps, b.Aps, "⬅")
				} else {
					t.AddRow(name, b.Runs, b.Speed, b.Bps, b.Aps, "⬅")
				}
			} else {
				if bench.info.hasFnIterations {
					fnIterations := strconv.Itoa(b.FnIterations)

					if fnIterations == "-1" {
						fnIterations = ""
					}

					t.AddRow(name, fnIterations, b.Runs, b.Speed, "⬅")
				} else {
					t.AddRow(name, b.Runs, b.Speed, "⬅")
				}
			}
		}

		i--
		if i > 0 {
			t.AddSeparator()
		}
	}

	t.SetAlign(termtables.AlignLeft, 1)
	t.SetAlign(termtables.AlignRight, 2)
	t.SetAlign(termtables.AlignRight, 3)
	t.SetAlign(termtables.AlignRight, 4)
	t.SetAlign(termtables.AlignRight, 5)
	t.SetAlign(termtables.AlignRight, 6)
}

func loading(q chan bool) {
	states := []string{"|", "/", "-", "\\", "|", "/", "–", "\\"}
	current := 0

	for {
		select {
		case <-time.Tick(150 * time.Millisecond):
			fmt.Printf("\r%s", states[current])
			if current == len(states)-1 {
				current = 0
			} else {
				current++
			}
		case <-q:
			break
		}
	}
}

func bold(s string) string {
	return fmt.Sprintf("\033[1m%s\033[0m", s)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	ws "github.com/henderjon/omnilogger/writesplitter"
	"io"
	"log"
	"net/http"
	"os"
	"time"
)

var (
	port           string                      // the port on which to listen
	pswd           string                      // a simple means of authentication
	forceStdout    bool                        // skip disk io and allow output redirection
	reqBuffer      int                         // the size of the incoming request buffer (channel)
	splitLineCount int                         // how many lines per log file
	splitByteCount int                         // how many bytes per log file
	splitPrefix    string                      // the prefix for the log file(s) name
	help           bool                        // I forgot my options
	helpLogger     = log.New(os.Stderr, "", 0) // log to stderr without the timestamps
	totalBytes     uint64                      // 9223372036854775806
	closeInterval  = 10 * time.Minute          // how often to close our file and open a new one
)

func init() {
	flag.StringVar(&port, "port", "8080", "The port used for the server.")
	flag.StringVar(&pswd, "auth", "", "If not empty, this is matched against the Authorization header (e.g. Authorization: Bearer my-password).")
	flag.BoolVar(&forceStdout, "c", false, "Send output to stdout and not disk also disregards -l, -b, and -prefix.")
	flag.IntVar(&reqBuffer, "buf", 0, "The size of the incoming request buffer. A zero (0) will disable buffering.")
	flag.IntVar(&splitLineCount, "l", 5000, "The number of lines at which to split the log files. A zero (0) will disable splitting by lines.")
	flag.IntVar(&splitByteCount, "b", 0, "The number of bytes at which to split the log files. A zero (0) will disable splitting by bytes.")
	flag.StringVar(&splitPrefix, "prefix", "", "A custom prefix to use for log files.")
	flag.BoolVar(&help, "h", false, "Show this message.")
	flag.Parse()

	if help {
		helpLogger.Println("\nOmnilogger is an HTTP server that coalesces log data (line by line) from multiple sources to a common destination. This defaults to consecutively named log files of ~5000 lines. After 10 min of inactivity, the current log file is closed and a new one is opened upon the next write.\n")
		flag.PrintDefaults()
		helpLogger.Println("\n")
		os.Exit(0)
	}

	if err := ws.TestFileIO(); err != nil {
		log.Fatal(err)
	}
}

func main() {
	data := make(chan []byte, reqBuffer)
	wc := newWriteCloser(nil)
	shutdown := make(chan struct{}, 0)

	go watchShutdown(shutdown) // catch system signals and shutdown gracefully
	go watchStatus()           // periodically echo the total number of bytes collects and the duration of the program
	go coalesce(data, wc)      // send all our request data to a single WriteCloser

	// adapters are closures and therefore executed in reverse order
	http.Handle("/", Adapt(parseRequest(data), parseCustomHeader, checkAuth(), ensurePost(), checkShutdown(shutdown)))
	http.ListenAndServe(":"+port, nil)

}

// coalesce runs in it's own goroutine and ranges over a channel and writing the
// data to an io.Writer. All our goroutines send data on this channel and this
// func coalesces them in to one stream.
func coalesce(data chan []byte, wc io.WriteCloser) {
	for {
		select {
		case b := <-data:
			n, _ := wc.Write(append(b, '\n'))
			totalBytes += uint64(n)
		case <-time.After(closeInterval): // after 10 minutes of inactivity close the file
			wc = newWriteCloser(wc)
		}
	}
}

// newWriteCloser is a factory for various io.WriteClosers.
func newWriteCloser(wc io.WriteCloser) io.WriteCloser {
	if forceStdout {
		return os.Stdout // don't ever worry about recycling stdout
	}

	// recycle the old io.WriteCloser with a new WriteSplitter, an explicit Close is better than waiting for GC
	if wc != nil {
		if e := wc.Close(); e != ws.ErrNotAFile {
			log.Fatal(e)
		}
	}

	if splitByteCount > 0 {
		wc = ws.ByteSplitter(splitByteCount, splitPrefix)
	} else {
		wc = ws.LineSplitter(splitLineCount, splitPrefix)
	}
	return wc
}
<commit_msg>clean up -h output<commit_after>package main

import (
	"flag"
	ws "github.com/henderjon/omnilogger/writesplitter"
	"io"
	"log"
	"net/http"
	"os"
	"time"
)

var (
	port           string                      // the port on which to listen
	pswd           string                      // a simple means of authentication
	forceStdout    bool                        // skip disk io and allow output redirection
	reqBuffer      int                         // the size of the incoming request buffer (channel)
	splitLineCount int                         // how many lines per log file
	splitByteCount int                         // how many bytes per log file
	splitPrefix    string                      // the prefix for the log file(s) name
	help           bool                        // I forgot my options
	helpLogger     = log.New(os.Stderr, "", 0) // log to stderr without the timestamps
	totalBytes     uint64                      // 9223372036854775806
	closeInterval  = 10 * time.Minute          // how often to close our file and open a new one
)

func init() {
	flag.StringVar(&port, "port", "8080", "The port used for the server.")
	flag.StringVar(&pswd, "auth", "", "If not empty, this is matched against the Authorization header (e.g. Authorization: Bearer my-password).")
	flag.BoolVar(&forceStdout, "c", false, "Write to stdout; disregard -l, -b, and -prefix.")
	flag.IntVar(&reqBuffer, "buf", 0, "The size of the incoming request buffer. A zero (0) will disable buffering.")
	flag.IntVar(&splitLineCount, "l", 5000, "The number of lines at which to split the log files. A zero (0) will disable splitting by lines.")
	flag.IntVar(&splitByteCount, "b", 0, "The number of bytes at which to split the log files. A zero (0) will disable splitting by bytes.")
	flag.StringVar(&splitPrefix, "prefix", "", "A custom prefix to use for log files.")
	flag.BoolVar(&help, "h", false, "Show this message.")
	flag.Parse()

	if help {
		helpLogger.Println("\nOmnilogger is an HTTP server that coalesces log data (line by line) from multiple sources to a common destination. This defaults to consecutively named log files of ~5000 lines. After 10 min of inactivity, the current log file is closed and a new one is opened upon the next write.\n")
		flag.PrintDefaults()
		helpLogger.Println("\n")
		os.Exit(0)
	}

	if err := ws.TestFileIO(); err != nil {
		log.Fatal(err)
	}
}

func main() {
	data := make(chan []byte, reqBuffer)
	wc := newWriteCloser(nil)
	shutdown := make(chan struct{}, 0)

	go watchShutdown(shutdown) // catch system signals and shutdown gracefully
	go watchStatus()           // periodically echo the total number of bytes collects and the duration of the program
	go coalesce(data, wc)      // send all our request data to a single WriteCloser

	// adapters are closures and therefore executed in reverse order
	http.Handle("/", Adapt(parseRequest(data), parseCustomHeader, checkAuth(), ensurePost(), checkShutdown(shutdown)))
	http.ListenAndServe(":"+port, nil)

}

// coalesce runs in it's own goroutine and ranges over a channel and writing the
// data to an io.Writer. All our goroutines send data on this channel and this
// func coalesces them in to one stream.
func coalesce(data chan []byte, wc io.WriteCloser) {
	for {
		select {
		case b := <-data:
			n, _ := wc.Write(append(b, '\n'))
			totalBytes += uint64(n)
		case <-time.After(closeInterval): // after 10 minutes of inactivity close the file
			wc = newWriteCloser(wc)
		}
	}
}

// newWriteCloser is a factory for various io.WriteClosers.
func newWriteCloser(wc io.WriteCloser) io.WriteCloser {
	if forceStdout {
		return os.Stdout // don't ever worry about recycling stdout
	}

	// recycle the old io.WriteCloser with a new WriteSplitter, an explicit Close is better than waiting for GC
	if wc != nil {
		if e := wc.Close(); e != ws.ErrNotAFile {
			log.Fatal(e)
		}
	}

	if splitByteCount > 0 {
		wc = ws.ByteSplitter(splitByteCount, splitPrefix)
	} else {
		wc = ws.LineSplitter(splitLineCount, splitPrefix)
	}
	return wc
}
<|endoftext|>


<commit_before>// Copyright (c) 2013, Mykola Dvornik <mykola.dvornik@gmail.com>
// All rights reserved.

// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of the Mykola Dvornik nor the
//       names of its contributors may be used to endorse or promote products
//       derived from this software without specific prior written permission.

// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package main

import (
	"bufio"
	"flag"
	"fmt"
	"github.com/ajstarks/svgo"
	"io"
	"log"
	"math"
	"os"
	"path"
	"strconv"
)

const BUFLEN = 1024 * 1024 * 1024 * 10
const HEADERLEN = 2059
const MAX_P_TO_WIDTH = 6.0
const MAX_P_TO_COLOUR = 254.0
const MAX_P_LEVELS = 1024.0

const (
	BLK_STROKE       uint8 = 241
	BLK_PEN_XY       uint8 = 97
	BLK_PEN_PRESSURE uint8 = 100
	BLK_PEN_TILT     uint8 = 101
	BLK_UNKNOWN_1    uint8 = 197
	BLK_UNKNOWN_2    uint8 = 194
	BLK_UNKNOWN_3    uint8 = 199
	ID_LAYER         uint8 = 128
	ID_STROKE_BEGIN  uint8 = 1
	ID_STROKE_END    uint8 = 0
)

var layersCount int = 0
var f0, f1 *os.File

type Stroke struct {
	X, Y, P, TiltX, TiltY []int
	SegmentsCount         uint64
}

func (s *Stroke) AddCoords(x, y int16) {
	s.X = append(s.X, int(x))
	s.Y = append(s.Y, int(y))
	s.SegmentsCount++
}

func (s *Stroke) AddPressure(p int16) {
	s.P = append(s.P, int(p))
}

func (s *Stroke) AddTilt(tx, ty byte) {
	s.TiltX = append(s.TiltX, int(tx))
	s.TiltY = append(s.TiltY, int(ty))
}

type Layer struct {
	Name         string
	Strokes      []Stroke
	StrokesCount uint64
}

func (l *Layer) AddStroke() {
	l.Strokes = append(l.Strokes, Stroke{})
	l.StrokesCount++
}

type Canvas struct {
	Layers      []Layer
	LayersCount uint64
}

func (c *Canvas) AddLayer() {
	c.Layers = append(c.Layers, Layer{})
	c.LayersCount++
}

func ReadLayers(r *bufio.Reader) (Canvas, error) {
	e := error(nil)
	var p, x, y int16
	var id byte
	head := make([]byte, 2)
	data := make([]byte, 4)

	/*WPI is rather inconsistent format*/
	/*It might not contain any 'layer' IDs*/
	/*It has no 'end-of-the-layer' marker*/
	/*In mixes up Big Endiness with Little Endiness*/

	c := Canvas{}
	c.AddLayer()
	l := &c.Layers[c.LayersCount-1]
	l.Name = "l" + strconv.FormatUint(c.LayersCount, 10)
	for {
		_, e = r.Read(head)
		if e == io.EOF {
			break
		}
		switch head[0] {

		case BLK_STROKE:
			id, e = r.ReadByte()
			switch id {
			case ID_LAYER:
				c.AddLayer()
				l = &c.Layers[c.LayersCount-1]
			case ID_STROKE_BEGIN:
				l.AddStroke()
			case ID_STROKE_END:
				/*Do sanity check*/
			}

		case BLK_PEN_XY:
			_, e = r.Read(data)

			x = (int16(data[0]) << 8) | int16(data[1])
			y = (int16(data[2]) << 8) | int16(data[3])

			x = (x+5)/8 + 1414
			y = (2*y + 5) / 8

			l.Strokes[l.StrokesCount-1].AddCoords(x, y)

		case BLK_PEN_PRESSURE:
			_, e = r.Read(data)
			p = (int16(data[2]) << 8) | int16(data[3])
			l.Strokes[l.StrokesCount-1].AddPressure(p)

		case BLK_PEN_TILT:
			_, e = r.Read(data)
			l.Strokes[l.StrokesCount-1].AddTilt(data[0], data[1])

		case BLK_UNKNOWN_1, BLK_UNKNOWN_2, BLK_UNKNOWN_3:
			tmp := make([]byte, head[1]-2)
			_, e = r.Read(tmp)
		}
	}
	layersCount++
	return c, e
}

func PressureToColourFunc(p float64) float64 {
	return (1.0 - math.Sqrt(p)) * MAX_P_TO_COLOUR
}

func PressureToWidthFunc(p float64) float64 {
	return p * MAX_P_TO_WIDTH
}

func AddLayersToSVG(s *svg.SVG, c Canvas) error {
	for _, l := range c.Layers {
		s.Gid(l.Name)
		for i, stroke := range l.Strokes {
			strokeID := "s" + strconv.Itoa(i)
			s.Gid(strokeID)
			for i := uint64(0); i < stroke.SegmentsCount-1; i++ {
				p := 0.5 * float64(stroke.P[i]+stroke.P[i+1]) / MAX_P_LEVELS
				width := PressureToWidthFunc(p)
				colour := PressureToColourFunc(p)
				icolour := int(colour)
				swidth := fmt.Sprintf("%.2f", width)
				scolour := s.RGB(icolour, icolour, icolour)[5:]
				s.Line(stroke.X[i], stroke.Y[i], stroke.X[i+1], stroke.Y[i+1], "stroke-linejoin:round;stroke-linecap:round;fill:none;stroke:"+scolour+";stroke-width:"+swidth)
			}
			s.Gend()
		}
		s.Gend()
	}
	return nil
}

func main() {
	var e error

	flag.Parse()

	wpiName := flag.Arg(0)
	if len(wpiName) == 0 {
		os.Exit(1)
	}

	f0, e = os.Open(wpiName)
	defer func() {
		if e != nil {
			log.Print(e)
		}
		f0.Close()
	}()
	f0.Seek(HEADERLEN, 0)

	svgName := wpiName[0:len(wpiName)-len(path.Ext(wpiName))] + ".svg"
	f1, e = os.OpenFile(svgName, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0750)
	defer func() {
		if e != nil {
			log.Print(e)
		}
		f1.Close()
	}()

	wpiReader := bufio.NewReaderSize(f0, BUFLEN)

	canvas := svg.New(f1)
	canvas.Start(2828, 4000) // WTF? NO DPI, NO PHYSICAL DIMENSONS?

	c, _ := ReadLayers(wpiReader)
	AddLayersToSVG(canvas, c)

	canvas.End()
	f1.Sync()
}
<commit_msg>reduce buffer size from 10G to 10M :D<commit_after>// Copyright (c) 2013, Mykola Dvornik <mykola.dvornik@gmail.com>
// All rights reserved.

// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of the Mykola Dvornik nor the
//       names of its contributors may be used to endorse or promote products
//       derived from this software without specific prior written permission.

// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package main

import (
	"bufio"
	"flag"
	"fmt"
	"github.com/ajstarks/svgo"
	"io"
	"log"
	"math"
	"os"
	"path"
	"strconv"
)

const BUFLEN = 1024 * 1024 * 10
const HEADERLEN = 2059
const MAX_P_TO_WIDTH = 6.0
const MAX_P_TO_COLOUR = 254.0
const MAX_P_LEVELS = 1024.0

const (
	BLK_STROKE       uint8 = 241
	BLK_PEN_XY       uint8 = 97
	BLK_PEN_PRESSURE uint8 = 100
	BLK_PEN_TILT     uint8 = 101
	BLK_UNKNOWN_1    uint8 = 197
	BLK_UNKNOWN_2    uint8 = 194
	BLK_UNKNOWN_3    uint8 = 199
	ID_LAYER         uint8 = 128
	ID_STROKE_BEGIN  uint8 = 1
	ID_STROKE_END    uint8 = 0
)

var layersCount int = 0
var f0, f1 *os.File

type Stroke struct {
	X, Y, P, TiltX, TiltY []int
	SegmentsCount         uint64
}

func (s *Stroke) AddCoords(x, y int16) {
	s.X = append(s.X, int(x))
	s.Y = append(s.Y, int(y))
	s.SegmentsCount++
}

func (s *Stroke) AddPressure(p int16) {
	s.P = append(s.P, int(p))
}

func (s *Stroke) AddTilt(tx, ty byte) {
	s.TiltX = append(s.TiltX, int(tx))
	s.TiltY = append(s.TiltY, int(ty))
}

type Layer struct {
	Name         string
	Strokes      []Stroke
	StrokesCount uint64
}

func (l *Layer) AddStroke() {
	l.Strokes = append(l.Strokes, Stroke{})
	l.StrokesCount++
}

type Canvas struct {
	Layers      []Layer
	LayersCount uint64
}

func (c *Canvas) AddLayer() {
	c.Layers = append(c.Layers, Layer{})
	c.LayersCount++
}

func ReadLayers(r *bufio.Reader) (Canvas, error) {
	e := error(nil)
	var p, x, y int16
	var id byte
	head := make([]byte, 2)
	data := make([]byte, 4)

	/*WPI is rather inconsistent format*/
	/*It might not contain any 'layer' IDs*/
	/*It has no 'end-of-the-layer' marker*/
	/*In mixes up Big Endiness with Little Endiness*/

	c := Canvas{}
	c.AddLayer()
	l := &c.Layers[c.LayersCount-1]
	l.Name = "l" + strconv.FormatUint(c.LayersCount, 10)
	for {
		_, e = r.Read(head)
		if e == io.EOF {
			break
		}
		switch head[0] {

		case BLK_STROKE:
			id, e = r.ReadByte()
			switch id {
			case ID_LAYER:
				c.AddLayer()
				l = &c.Layers[c.LayersCount-1]
			case ID_STROKE_BEGIN:
				l.AddStroke()
			case ID_STROKE_END:
				/*Do sanity check*/
			}

		case BLK_PEN_XY:
			_, e = r.Read(data)

			x = (int16(data[0]) << 8) | int16(data[1])
			y = (int16(data[2]) << 8) | int16(data[3])

			x = (x+5)/8 + 1414
			y = (2*y + 5) / 8

			l.Strokes[l.StrokesCount-1].AddCoords(x, y)

		case BLK_PEN_PRESSURE:
			_, e = r.Read(data)
			p = (int16(data[2]) << 8) | int16(data[3])
			l.Strokes[l.StrokesCount-1].AddPressure(p)

		case BLK_PEN_TILT:
			_, e = r.Read(data)
			l.Strokes[l.StrokesCount-1].AddTilt(data[0], data[1])

		case BLK_UNKNOWN_1, BLK_UNKNOWN_2, BLK_UNKNOWN_3:
			tmp := make([]byte, head[1]-2)
			_, e = r.Read(tmp)
		}
	}
	layersCount++
	return c, e
}

func PressureToColourFunc(p float64) float64 {
	return (1.0 - math.Sqrt(p)) * MAX_P_TO_COLOUR
}

func PressureToWidthFunc(p float64) float64 {
	return p * MAX_P_TO_WIDTH
}

func AddLayersToSVG(s *svg.SVG, c Canvas) error {
	for _, l := range c.Layers {
		s.Gid(l.Name)
		for i, stroke := range l.Strokes {
			strokeID := "s" + strconv.Itoa(i)
			s.Gid(strokeID)
			for i := uint64(0); i < stroke.SegmentsCount-1; i++ {
				p := 0.5 * float64(stroke.P[i]+stroke.P[i+1]) / MAX_P_LEVELS
				width := PressureToWidthFunc(p)
				colour := PressureToColourFunc(p)
				icolour := int(colour)
				swidth := fmt.Sprintf("%.2f", width)
				scolour := s.RGB(icolour, icolour, icolour)[5:]
				s.Line(stroke.X[i], stroke.Y[i], stroke.X[i+1], stroke.Y[i+1], "stroke-linejoin:round;stroke-linecap:round;fill:none;stroke:"+scolour+";stroke-width:"+swidth)
			}
			s.Gend()
		}
		s.Gend()
	}
	return nil
}

func main() {
	var e error

	flag.Parse()

	wpiName := flag.Arg(0)
	if len(wpiName) == 0 {
		os.Exit(1)
	}

	f0, e = os.Open(wpiName)
	defer func() {
		if e != nil {
			log.Print(e)
		}
		f0.Close()
	}()
	f0.Seek(HEADERLEN, 0)

	svgName := wpiName[0:len(wpiName)-len(path.Ext(wpiName))] + ".svg"
	f1, e = os.OpenFile(svgName, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0750)
	defer func() {
		if e != nil {
			log.Print(e)
		}
		f1.Close()
	}()

	wpiReader := bufio.NewReaderSize(f0, BUFLEN)

	canvas := svg.New(f1)
	canvas.Start(2828, 4000) // WTF? NO DPI, NO PHYSICAL DIMENSONS?

	c, _ := ReadLayers(wpiReader)
	AddLayersToSVG(canvas, c)

	canvas.End()
	f1.Sync()
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"math/rand"
	"net/http"
	"time"
)

type Payload struct {
	Targets []Target
}

type Target struct {
	Destination_Type     string
	Destination_Sub_Type string
	Data                 robification_fdThread
}

type robification_emailMessage struct {
	From       string
	Subject    string
	Body       string
	Recipients []string
}

type robification_fdThread struct {
	Flow_Token         string
	Event              string
	Author             Author
	Title              string
	External_Thread_Id string
	Thread             Thread
}

type Thread struct {
	Title        string
	Fields       []Field
	Body         string
	External_Url string
	Status       ThreadStatus
}

type ThreadStatus struct {
	Color string
	Value string
}

type Field struct {
	Label string
	Value string
}

type Author struct {
	Name   string
	Avatar string
}

func send(token string, external_id string, title string, label_color string, label_value string, fields []Field) {

	url := "http://jrobles.net:1337/send"

	payload := buildPayload(token, external_id, title, label_color, label_value, fields)

	p, err := json.Marshal(payload)
	if err != nil {
		fmt.Println(err)
	}

	req, err := http.NewRequest("POST", url, bytes.NewBuffer(p))
	req.Header.Set("Content-Type", "application/json")
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
}

func buildPayload(flowToken string, threadID string, title string, statusColor string, statusValue string, fields []Field) *Payload {
	fdData := &robification_fdThread{
		Flow_Token: flowToken,
		Event:      "activity",
		Author: Author{
			Name:   "Wallace",
			Avatar: "https://d2cxspbh1aoie1.cloudfront.net/avatars/local/87dee60e5d045f2fa8371a2f3f45b919a0e9cd0209e3689a46951411fef18681/120",
		},
		Title:              title,
		External_Thread_Id: threadID,
		Thread: Thread{
			Title:  title,
			Fields: fields,
			//Body:         "some optional messaging that can be added to the thread as a sub header",
			External_Url: "http://jrobles.net",
			Status: ThreadStatus{
				Color: statusColor,
				Value: statusValue,
			},
		},
	}

	payload := &Payload{
		Targets: []Target{
			Target{
				Destination_Type:     "flowdock",
				Destination_Sub_Type: "new_thread",
				Data:                 *fdData,
			},
		},
	}
	return payload
}
<commit_msg>Changed package name<commit_after>package robification

import (
	"bytes"
	"encoding/json"
	"fmt"
	"math/rand"
	"net/http"
	"time"
)

type Payload struct {
	Targets []Target
}

type Target struct {
	Destination_Type     string
	Destination_Sub_Type string
	Data                 robification_fdThread
}

type robification_emailMessage struct {
	From       string
	Subject    string
	Body       string
	Recipients []string
}

type robification_fdThread struct {
	Flow_Token         string
	Event              string
	Author             Author
	Title              string
	External_Thread_Id string
	Thread             Thread
}

type Thread struct {
	Title        string
	Fields       []Field
	Body         string
	External_Url string
	Status       ThreadStatus
}

type ThreadStatus struct {
	Color string
	Value string
}

type Field struct {
	Label string
	Value string
}

type Author struct {
	Name   string
	Avatar string
}

func send(token string, external_id string, title string, label_color string, label_value string, fields []Field) {

	url := "http://jrobles.net:1337/send"

	payload := buildPayload(token, external_id, title, label_color, label_value, fields)

	p, err := json.Marshal(payload)
	if err != nil {
		fmt.Println(err)
	}

	req, err := http.NewRequest("POST", url, bytes.NewBuffer(p))
	req.Header.Set("Content-Type", "application/json")
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
}

func buildPayload(flowToken string, threadID string, title string, statusColor string, statusValue string, fields []Field) *Payload {
	fdData := &robification_fdThread{
		Flow_Token: flowToken,
		Event:      "activity",
		Author: Author{
			Name:   "Wallace",
			Avatar: "https://d2cxspbh1aoie1.cloudfront.net/avatars/local/87dee60e5d045f2fa8371a2f3f45b919a0e9cd0209e3689a46951411fef18681/120",
		},
		Title:              title,
		External_Thread_Id: threadID,
		Thread: Thread{
			Title:  title,
			Fields: fields,
			//Body:         "some optional messaging that can be added to the thread as a sub header",
			External_Url: "http://jrobles.net",
			Status: ThreadStatus{
				Color: statusColor,
				Value: statusValue,
			},
		},
	}

	payload := &Payload{
		Targets: []Target{
			Target{
				Destination_Type:     "flowdock",
				Destination_Sub_Type: "new_thread",
				Data:                 *fdData,
			},
		},
	}
	return payload
}
<|endoftext|>


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

package main

import (
	"flag"
	"fmt"
	. "github.com/uniqush/uniqush-push/srv"
	"os"
	"runtime"
)

var uniqushPushConfFlags = flag.String("config", "/etc/uniqush/uniqush-push.conf", "Config file path")
var uniqushPushShowVersionFlag = flag.Bool("version", false, "Version info")

var uniqushPushVersion = "uniqush-push 1.5.1a1"

func installPushSrvices() {
	InstallGCM()
	InstallC2DM()
	InstallAPNS()
	InstallADM()
}

func main() {
	flag.Parse()
	if *uniqushPushShowVersionFlag {
		fmt.Printf("%v\n", uniqushPushVersion)
		return
	}
	runtime.GOMAXPROCS(runtime.NumCPU() + 1)
	installPushSrvices()

	err := Run(*uniqushPushConfFlags, uniqushPushVersion)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Cannot start: %v\n", err)
	}
}
<commit_msg>change version number to a2<commit_after>/*
 * Copyright 2011 Nan Deng
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package main

import (
	"flag"
	"fmt"
	. "github.com/uniqush/uniqush-push/srv"
	"os"
	"runtime"
)

var uniqushPushConfFlags = flag.String("config", "/etc/uniqush/uniqush-push.conf", "Config file path")
var uniqushPushShowVersionFlag = flag.Bool("version", false, "Version info")

var uniqushPushVersion = "uniqush-push 1.5.1a2"

func installPushSrvices() {
	InstallGCM()
	InstallC2DM()
	InstallAPNS()
	InstallADM()
}

func main() {
	flag.Parse()
	if *uniqushPushShowVersionFlag {
		fmt.Printf("%v\n", uniqushPushVersion)
		return
	}
	runtime.GOMAXPROCS(runtime.NumCPU() + 1)
	installPushSrvices()

	err := Run(*uniqushPushConfFlags, uniqushPushVersion)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Cannot start: %v\n", err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/dchen496/mpgb/server"
	"github.com/gorilla/mux"
	"log"
	"net/http"
	"runtime"
)

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())

	r := mux.NewRouter()

	// Everything is a WebSockets RPC for simplicity
	r.HandleFunc("/ws", server.WsHandler)

	// Serve static files
	r.PathPrefix("/js/").Handler(http.StripPrefix("/js/", http.FileServer(http.Dir("./js/"))))
	r.PathPrefix("/roms/").Handler(http.StripPrefix("/roms/", http.FileServer(http.Dir("./roms/"))))
	r.PathPrefix("/").Handler(http.FileServer(http.Dir("./static/")))

	http.Handle("/", r)
	addr := ":8080"

	log.Printf("listening on %s\n", addr)
	http.ListenAndServe(addr, nil)
}
<commit_msg>add addr envvar<commit_after>package main

import (
	"github.com/dchen496/mpgb/server"
	"github.com/gorilla/mux"
	"log"
	"net/http"
	"os"
	"runtime"
)

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())

	r := mux.NewRouter()

	// Everything is a WebSockets RPC for simplicity
	r.HandleFunc("/ws", server.WsHandler)

	// Serve static files
	r.PathPrefix("/js/").Handler(http.StripPrefix("/js/", http.FileServer(http.Dir("./js/"))))
	r.PathPrefix("/roms/").Handler(http.StripPrefix("/roms/", http.FileServer(http.Dir("./roms/"))))
	r.PathPrefix("/").Handler(http.FileServer(http.Dir("./static/")))

	http.Handle("/", r)
	addr := os.Getenv("ADDR")
	if addr == "" {
		addr = ":3000"
	}

	log.Printf("listening on %s\n", addr)
	log.Fatalln(http.ListenAndServe(addr, nil))
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/darron/sifter/commands"
	"log"
	"log/syslog"
	"runtime"
)

func main() {
	logwriter, e := syslog.New(syslog.LOG_NOTICE, "sifter")
	if e == nil {
		log.SetOutput(logwriter)
	}
	runtime.GOMAXPROCS(runtime.NumCPU())
	commands.RootCmd.Execute()
}
<commit_msg>Added `-v` and `--version` command.<commit_after>package main

import (
	"fmt"
	"github.com/darron/sifter/commands"
	"log"
	"log/syslog"
	"os"
	"runtime"
)

var (
	// CompileDate tracks when the binary was compiled. It's inserted during a build
	// with build flags. Take a look at the Makefile for information.
	CompileDate = "No date provided."

	// GitCommit tracks the SHA of the built binary. It's inserted during a build
	// with build flags. Take a look at the Makefile for information.
	GitCommit = "No revision provided."

	// Version is the version of the built binary. It's inserted during a build
	// with build flags. Take a look at the Makefile for information.
	Version = "No version provided."

	// GoVersion details the version of Go this was compiled with.
	GoVersion = runtime.Version()
)

func main() {
	logwriter, e := syslog.New(syslog.LOG_NOTICE, "sifter")
	if e == nil {
		log.SetOutput(logwriter)
	}

	args := os.Args[1:]
	for _, arg := range args {
		if arg == "-v" || arg == "--version" {
			fmt.Printf("%-8s : %s\n%-8s : %s\n%-8s : %s\n%-8s : %s\n", "Version", Version, "Revision", GitCommit, "Date", CompileDate, "Go", GoVersion)
			os.Exit(0)
		}
	}

	commands.RootCmd.Execute()
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"net"
	"net/http"
	"time"
)

func setConfig(nsqAddr string, lookupdIPs []net.IP) {
	body, err := json.Marshal(lookupdIPs)
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("setting lookupdIPs: %s", body)

	configAddr := "http://" + nsqAddr + "/config"
	req, err := http.NewRequest("PUT", configAddr, bytes.NewBuffer(body))
	if err != nil {
		log.Fatalf("http.NewRequest error: %s", err)
	}

	client := &http.Client{}
	res, err := client.Do(req)
	if err != nil {
		log.Fatalf("client.Do error: %s", err)
	}

	if res.StatusCode != 200 {
		log.Printf("nsqd responded with status: %d", res.StatusCode)
	}
}

func main() {
	var (
		dnsAddr  = flag.String("lookupd-dns-address", "", "The DNS address of nsqlookupd")
		nsqdAddr = flag.String("nsqd-http-address", "0.0.0.0:4151", "The HTTP address of nsqd")
	)
	flag.Parse()

	if *dnsAddr == "" {
		fmt.Println("Error: required arg -lookupd-dns-address")
		return
	}

	lookupdIPs, err := net.LookupIP(*dnsAddr)
	if err != nil {
		log.Fatalf("net.LookupIP error: %s", err)
	}

	if len(lookupdIPs) == 0 {
		log.Fatalf("no IPs found for %s", *dnsAddr)
	}

	setConfig(*nsqdAddr, lookupdIPs)
	ticker := time.Tick(15 * time.Second)

	for {
		select {
		case <-ticker:
			lookupdIPs, err := net.LookupIP(*dnsAddr)
			if err != nil {
				log.Fatal(err)
			}

			if len(lookupdIPs) == 0 {
				log.Printf("No IP addresses found for %s", *dnsAddr)
				continue
			}

			setConfig(*nsqdAddr, lookupdIPs)
		}
	}
}
<commit_msg>Add the lookupd path to config<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"net"
	"net/http"
	"time"
)

func setConfig(nsqAddr string, lookupdIPs []net.IP) {
	body, err := json.Marshal(lookupdIPs)
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("setting lookupdIPs: %s", body)

	configAddr := "http://" + nsqAddr + "/config/nsqlookupd_tcp_addresses"
	req, err := http.NewRequest("PUT", configAddr, bytes.NewBuffer(body))
	if err != nil {
		log.Fatalf("http.NewRequest error: %s", err)
	}

	client := &http.Client{}
	res, err := client.Do(req)
	if err != nil {
		log.Fatalf("client.Do error: %s", err)
	}

	if res.StatusCode != 200 {
		log.Printf("nsqd responded with status: %d", res.StatusCode)
	}
}

func main() {
	var (
		dnsAddr  = flag.String("lookupd-dns-address", "", "The DNS address of nsqlookupd")
		nsqdAddr = flag.String("nsqd-http-address", "0.0.0.0:4151", "The HTTP address of nsqd")
	)
	flag.Parse()

	if *dnsAddr == "" {
		fmt.Println("Error: required arg -lookupd-dns-address")
		return
	}

	lookupdIPs, err := net.LookupIP(*dnsAddr)
	if err != nil {
		log.Fatalf("net.LookupIP error: %s", err)
	}

	if len(lookupdIPs) == 0 {
		log.Fatalf("no IPs found for %s", *dnsAddr)
	}

	setConfig(*nsqdAddr, lookupdIPs)
	ticker := time.Tick(15 * time.Second)

	for {
		select {
		case <-ticker:
			lookupdIPs, err := net.LookupIP(*dnsAddr)
			if err != nil {
				log.Fatal(err)
			}

			if len(lookupdIPs) == 0 {
				log.Printf("No IP addresses found for %s", *dnsAddr)
				continue
			}

			setConfig(*nsqdAddr, lookupdIPs)
		}
	}
}
<|endoftext|>


<commit_before>package qor

import (
	"fmt"

	"os"
	"runtime"
	"runtime/debug"
	"strings"
)

func filenameWithLineNum() string {
	var total = 10
	var results []string
	for i := 2; i < 15; i++ {
		if _, file, line, ok := runtime.Caller(i); ok {
			total--
			results = append(results[:0],
				append(
					[]string{fmt.Sprintf("%v:%v", strings.TrimPrefix(file, os.Getenv("GOPATH")+"src/"), line)},
					results[0:len(results)]...)...)

			if total == 0 {
				return strings.Join(results, "\n")
			}
		}
	}
	return ""
}

func ExitWithMsg(str string, value ...interface{}) {
	debug.PrintStack()
	fmt.Printf("\n"+filenameWithLineNum()+"\n"+str+"\n", value...)
	os.Exit(1)
}
<commit_msg>ExitWithMsg: print error msg before stacks<commit_after>package qor

import (
	"fmt"

	"os"
	"runtime"
	"runtime/debug"
	"strings"
)

func filenameWithLineNum() string {
	var total = 10
	var results []string
	for i := 2; i < 15; i++ {
		if _, file, line, ok := runtime.Caller(i); ok {
			total--
			results = append(results[:0],
				append(
					[]string{fmt.Sprintf("%v:%v", strings.TrimPrefix(file, os.Getenv("GOPATH")+"src/"), line)},
					results[0:len(results)]...)...)

			if total == 0 {
				return strings.Join(results, "\n")
			}
		}
	}
	return ""
}

func ExitWithMsg(str string, value ...interface{}) {
	fmt.Printf("\n"+filenameWithLineNum()+"\n"+str+"\n", value...)
	debug.PrintStack()
	os.Exit(1)
}
<|endoftext|>