<commit_before>package main

import (
	"bytes"
	"crypto/hmac"
	"crypto/md5"
	"crypto/sha1"
	"crypto/subtle"
	"encoding/base64"
	"fmt"
	"image"
	"image/jpeg"
	"io"
	"log"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/opendoor-labs/gothumb/Godeps/_workspace/src/github.com/julienschmidt/httprouter"
	"github.com/opendoor-labs/gothumb/Godeps/_workspace/src/github.com/nfnt/resize"
	"github.com/opendoor-labs/gothumb/Godeps/_workspace/src/github.com/oliamb/cutter"
	"github.com/opendoor-labs/gothumb/Godeps/_workspace/src/github.com/rlmcpherson/s3gof3r"
)

var (
	maxAge           int
	securityKey      []byte
	resultBucketName string
	useRRS           bool

	httpClient   *http.Client
	resultBucket *s3gof3r.Bucket
)

func main() {
	securityKey = []byte(mustGetenv("SECURITY_KEY"))
	resultBucketName = mustGetenv("RESULT_STORAGE_BUCKET")

	if maxAgeStr := os.Getenv("MAX_AGE"); maxAgeStr != "" {
		var err error
		if maxAge, err = strconv.Atoi(maxAgeStr); err != nil {
			log.Fatal("invalid MAX_AGE setting")
		}
	}
	if rrs := os.Getenv("USE_RRS"); rrs == "true" || rrs == "1" {
		useRRS = true
	}

	keys, err := s3gof3r.EnvKeys()
	if err != nil {
		log.Fatal(err)
	}
	resultBucket = s3gof3r.New(s3gof3r.DefaultDomain, keys).Bucket(resultBucketName)
	resultBucket.Md5Check = true
	httpClient = resultBucket.Client

	router := httprouter.New()
	router.HEAD("/:signature/:size/*source", handleResize)
	router.GET("/:signature/:size/*source", handleResize)
	port := os.Getenv("PORT")
	if port == "" {
		port = "8888"
	}
	log.Fatal(http.ListenAndServe(":"+port, router))
}

func handleResize(w http.ResponseWriter, req *http.Request, params httprouter.Params) {
	log.Printf(req.Method + " " + req.URL.Path)
	sourceURL, err := url.Parse(strings.TrimPrefix(params.ByName("source"), "/"))
	if err != nil || !(sourceURL.Scheme == "http" || sourceURL.Scheme == "https") {
		http.Error(w, "invalid source URL", 400)
		return
	}

	sig := params.ByName("signature")
	pathToVerify := strings.TrimPrefix(req.URL.Path, "/"+sig+"/")
	if err := validateSignature(sig, pathToVerify); err != nil {
		http.Error(w, "invalid signature", 401)
		return
	}

	width, height, err := parseWidthAndHeight(params.ByName("size"))
	if err != nil {
		http.Error(w, "invalid height requested", 400)
		return
	}

	// TODO(bgentry): normalize path. Support for custom root path? ala RESULT_STORAGE_AWS_STORAGE_ROOT_PATH

	// try to get stored result
	r, h, err := resultBucket.GetReader(req.URL.Path, nil)
	if err != nil {
		generateThumbnail(w, req, sourceURL.String(), width, height)
		return
	}
	defer r.Close()

	// return stored result
	length, err := strconv.Atoi(h.Get("Content-Length"))
	if err != nil {
		log.Printf("invalid result content-length: %s", err)
		// TODO: try to generate instead of erroring w/ 500?
		http.Error(w, err.Error(), 500)
		return
	}

	setResultHeaders(w, &result{
		ContentType:   "image/jpeg", // TODO: use stored content type
		ContentLength: length,
		ETag:          strings.Trim(h.Get("Etag"), `"`),
		Path:          req.URL.Path,
	})
	if _, err = io.Copy(w, r); err != nil {
		log.Printf("copying from stored result: %s", err)
		http.Error(w, err.Error(), 500)
		return
	}
	if err = r.Close(); err != nil {
		log.Printf("closing stored result copy: %s", err)
	}
}

func generateThumbnail(w http.ResponseWriter, req *http.Request, sourceURL string, width, height uint) {
	log.Printf("generating %s", req.URL.Path)
	resp, err := httpClient.Get(sourceURL)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}
	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		copyHeader(w.Header(), resp.Header)
		io.Copy(w, resp.Body)
		return
	}

	contentType := resp.Header.Get("Content-Type")
	if !strings.HasPrefix(contentType, "image/") {
		http.Error(w, fmt.Sprintf("invalid content type %q", contentType), 500)
		return
	}

	img, _, err := image.Decode(resp.Body)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	// crop to final aspect ratio before resizing
	croppedImg, err := cutter.Crop(img, cutter.Config{
		Width:   int(width),
		Height:  int(height),
		Mode:    cutter.Centered,
		Options: cutter.Ratio,
	})

	imgResized := resize.Resize(width, height, croppedImg, resize.Bicubic)
	var buf bytes.Buffer
	if err := jpeg.Encode(&buf, imgResized, nil); err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	res := &result{
		ContentType:   "image/jpeg",
		ContentLength: buf.Len(),
		Data:          buf.Bytes(), // TODO: check if I need to copy this
		ETag:          computeHexMD5(buf.Bytes()),
		Path:          req.URL.Path,
	}
	setResultHeaders(w, res)
	if req.Method != "HEAD" {
		if _, err = buf.WriteTo(w); err != nil {
			log.Printf("writing buffer to response: %s", err)
		}
	}

	go storeResult(res)
}

func setResultHeaders(w http.ResponseWriter, result *result) {
	w.Header().Set("Content-Type", result.ContentType)
	w.Header().Set("Content-Length", strconv.Itoa(result.ContentLength))
	w.Header().Set("ETag", `"`+result.ETag+`"`)
	setCacheHeaders(w)
}

func storeResult(res *result) {
	h := make(http.Header)
	h.Set("Content-Type", res.ContentType)
	if useRRS {
		h.Set("x-amz-storage-class", "REDUCED_REDUNDANCY")
	}
	w, err := resultBucket.PutWriter(res.Path, h, nil)
	if err != nil {
		log.Printf("storing result for %s: %s", res.Path, err)
		return
	}
	defer w.Close()
	if _, err = w.Write(res.Data); err != nil {
		log.Printf("storing result for %s: %s", res.Path, err)
		return
	}
	if err = w.Close(); err != nil {
		log.Printf("storing result for %s: %s", res.Path, err)
	}
}

type result struct {
	Data          []byte
	ContentType   string
	ContentLength int
	ETag          string
	Path          string
}

func computeHexMD5(data []byte) string {
	h := md5.New()
	h.Write(data)
	return fmt.Sprintf("%x", h.Sum(nil))
}

func copyHeader(dst, src http.Header) {
	for k, vv := range src {
		for _, v := range vv {
			dst.Add(k, v)
		}
	}
}

func mustGetenv(name string) string {
	value := os.Getenv(name)
	if value == "" {
		log.Fatalf("missing %s env", name)
	}
	return value
}

func parseWidthAndHeight(str string) (width, height uint, err error) {
	sizeParts := strings.Split(str, "x")
	if len(sizeParts) != 2 {
		err = fmt.Errorf("invalid size requested")
		return
	}
	width64, err := strconv.ParseUint(sizeParts[0], 10, 64)
	if err != nil {
		err = fmt.Errorf("invalid width requested")
		return
	}
	height64, err := strconv.ParseUint(sizeParts[1], 10, 64)
	if err != nil {
		err = fmt.Errorf("invalid height requested")
		return
	}
	return uint(width64), uint(height64), nil
}

func setCacheHeaders(w http.ResponseWriter) {
	w.Header().Set("Cache-Control", fmt.Sprintf("max-age=%d,public", maxAge))
	w.Header().Set("Expires", time.Now().UTC().Add(time.Duration(maxAge)*time.Second).Format(http.TimeFormat))
}

func validateSignature(sig, pathPart string) error {
	h := hmac.New(sha1.New, securityKey)
	if _, err := h.Write([]byte(pathPart)); err != nil {
		return err
	}
	actualSig := base64.StdEncoding.EncodeToString(h.Sum(nil))
	// constant-time string comparison
	if subtle.ConstantTimeCompare([]byte(sig), []byte(actualSig)) != 1 {
		return fmt.Errorf("signature mismatch")
	}
	return nil
}
<commit_msg>no Md5Check<commit_after>package main

import (
	"bytes"
	"crypto/hmac"
	"crypto/md5"
	"crypto/sha1"
	"crypto/subtle"
	"encoding/base64"
	"fmt"
	"image"
	"image/jpeg"
	"io"
	"log"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/opendoor-labs/gothumb/Godeps/_workspace/src/github.com/julienschmidt/httprouter"
	"github.com/opendoor-labs/gothumb/Godeps/_workspace/src/github.com/nfnt/resize"
	"github.com/opendoor-labs/gothumb/Godeps/_workspace/src/github.com/oliamb/cutter"
	"github.com/opendoor-labs/gothumb/Godeps/_workspace/src/github.com/rlmcpherson/s3gof3r"
)

var (
	maxAge           int
	securityKey      []byte
	resultBucketName string
	useRRS           bool

	httpClient   *http.Client
	resultBucket *s3gof3r.Bucket
)

func main() {
	securityKey = []byte(mustGetenv("SECURITY_KEY"))
	resultBucketName = mustGetenv("RESULT_STORAGE_BUCKET")

	if maxAgeStr := os.Getenv("MAX_AGE"); maxAgeStr != "" {
		var err error
		if maxAge, err = strconv.Atoi(maxAgeStr); err != nil {
			log.Fatal("invalid MAX_AGE setting")
		}
	}
	if rrs := os.Getenv("USE_RRS"); rrs == "true" || rrs == "1" {
		useRRS = true
	}

	keys, err := s3gof3r.EnvKeys()
	if err != nil {
		log.Fatal(err)
	}
	resultBucket = s3gof3r.New(s3gof3r.DefaultDomain, keys).Bucket(resultBucketName)
	resultBucket.Md5Check = false
	httpClient = resultBucket.Client

	router := httprouter.New()
	router.HEAD("/:signature/:size/*source", handleResize)
	router.GET("/:signature/:size/*source", handleResize)
	port := os.Getenv("PORT")
	if port == "" {
		port = "8888"
	}
	log.Fatal(http.ListenAndServe(":"+port, router))
}

func handleResize(w http.ResponseWriter, req *http.Request, params httprouter.Params) {
	log.Printf(req.Method + " " + req.URL.Path)
	sourceURL, err := url.Parse(strings.TrimPrefix(params.ByName("source"), "/"))
	if err != nil || !(sourceURL.Scheme == "http" || sourceURL.Scheme == "https") {
		http.Error(w, "invalid source URL", 400)
		return
	}

	sig := params.ByName("signature")
	pathToVerify := strings.TrimPrefix(req.URL.Path, "/"+sig+"/")
	if err := validateSignature(sig, pathToVerify); err != nil {
		http.Error(w, "invalid signature", 401)
		return
	}

	width, height, err := parseWidthAndHeight(params.ByName("size"))
	if err != nil {
		http.Error(w, "invalid height requested", 400)
		return
	}

	// TODO(bgentry): normalize path. Support for custom root path? ala RESULT_STORAGE_AWS_STORAGE_ROOT_PATH

	// try to get stored result
	r, h, err := resultBucket.GetReader(req.URL.Path, nil)
	if err != nil {
		generateThumbnail(w, req, sourceURL.String(), width, height)
		return
	}
	defer r.Close()

	// return stored result
	length, err := strconv.Atoi(h.Get("Content-Length"))
	if err != nil {
		log.Printf("invalid result content-length: %s", err)
		// TODO: try to generate instead of erroring w/ 500?
		http.Error(w, err.Error(), 500)
		return
	}

	setResultHeaders(w, &result{
		ContentType:   "image/jpeg", // TODO: use stored content type
		ContentLength: length,
		ETag:          strings.Trim(h.Get("Etag"), `"`),
		Path:          req.URL.Path,
	})
	if _, err = io.Copy(w, r); err != nil {
		log.Printf("copying from stored result: %s", err)
		http.Error(w, err.Error(), 500)
		return
	}
	if err = r.Close(); err != nil {
		log.Printf("closing stored result copy: %s", err)
	}
}

func generateThumbnail(w http.ResponseWriter, req *http.Request, sourceURL string, width, height uint) {
	log.Printf("generating %s", req.URL.Path)
	resp, err := httpClient.Get(sourceURL)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}
	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		copyHeader(w.Header(), resp.Header)
		io.Copy(w, resp.Body)
		return
	}

	contentType := resp.Header.Get("Content-Type")
	if !strings.HasPrefix(contentType, "image/") {
		http.Error(w, fmt.Sprintf("invalid content type %q", contentType), 500)
		return
	}

	img, _, err := image.Decode(resp.Body)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	// crop to final aspect ratio before resizing
	croppedImg, err := cutter.Crop(img, cutter.Config{
		Width:   int(width),
		Height:  int(height),
		Mode:    cutter.Centered,
		Options: cutter.Ratio,
	})

	imgResized := resize.Resize(width, height, croppedImg, resize.Bicubic)
	var buf bytes.Buffer
	if err := jpeg.Encode(&buf, imgResized, nil); err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	res := &result{
		ContentType:   "image/jpeg",
		ContentLength: buf.Len(),
		Data:          buf.Bytes(), // TODO: check if I need to copy this
		ETag:          computeHexMD5(buf.Bytes()),
		Path:          req.URL.Path,
	}
	setResultHeaders(w, res)
	if req.Method != "HEAD" {
		if _, err = buf.WriteTo(w); err != nil {
			log.Printf("writing buffer to response: %s", err)
		}
	}

	go storeResult(res)
}

func setResultHeaders(w http.ResponseWriter, result *result) {
	w.Header().Set("Content-Type", result.ContentType)
	w.Header().Set("Content-Length", strconv.Itoa(result.ContentLength))
	w.Header().Set("ETag", `"`+result.ETag+`"`)
	setCacheHeaders(w)
}

func storeResult(res *result) {
	h := make(http.Header)
	h.Set("Content-Type", res.ContentType)
	if useRRS {
		h.Set("x-amz-storage-class", "REDUCED_REDUNDANCY")
	}
	w, err := resultBucket.PutWriter(res.Path, h, nil)
	if err != nil {
		log.Printf("storing result for %s: %s", res.Path, err)
		return
	}
	defer w.Close()
	if _, err = w.Write(res.Data); err != nil {
		log.Printf("storing result for %s: %s", res.Path, err)
		return
	}
	if err = w.Close(); err != nil {
		log.Printf("storing result for %s: %s", res.Path, err)
	}
}

type result struct {
	Data          []byte
	ContentType   string
	ContentLength int
	ETag          string
	Path          string
}

func computeHexMD5(data []byte) string {
	h := md5.New()
	h.Write(data)
	return fmt.Sprintf("%x", h.Sum(nil))
}

func copyHeader(dst, src http.Header) {
	for k, vv := range src {
		for _, v := range vv {
			dst.Add(k, v)
		}
	}
}

func mustGetenv(name string) string {
	value := os.Getenv(name)
	if value == "" {
		log.Fatalf("missing %s env", name)
	}
	return value
}

func parseWidthAndHeight(str string) (width, height uint, err error) {
	sizeParts := strings.Split(str, "x")
	if len(sizeParts) != 2 {
		err = fmt.Errorf("invalid size requested")
		return
	}
	width64, err := strconv.ParseUint(sizeParts[0], 10, 64)
	if err != nil {
		err = fmt.Errorf("invalid width requested")
		return
	}
	height64, err := strconv.ParseUint(sizeParts[1], 10, 64)
	if err != nil {
		err = fmt.Errorf("invalid height requested")
		return
	}
	return uint(width64), uint(height64), nil
}

func setCacheHeaders(w http.ResponseWriter) {
	w.Header().Set("Cache-Control", fmt.Sprintf("max-age=%d,public", maxAge))
	w.Header().Set("Expires", time.Now().UTC().Add(time.Duration(maxAge)*time.Second).Format(http.TimeFormat))
}

func validateSignature(sig, pathPart string) error {
	h := hmac.New(sha1.New, securityKey)
	if _, err := h.Write([]byte(pathPart)); err != nil {
		return err
	}
	actualSig := base64.StdEncoding.EncodeToString(h.Sum(nil))
	// constant-time string comparison
	if subtle.ConstantTimeCompare([]byte(sig), []byte(actualSig)) != 1 {
		return fmt.Errorf("signature mismatch")
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"os"
)

var (
	name    = "msub"
	version = "0.2.1"

	flagset     = flag.NewFlagSet(name, flag.ContinueOnError)
	useBoundary = flagset.Bool("boundary", false, "")
	isHelp      = flagset.Bool("help", false, "")
	isVersion   = flagset.Bool("version", false, "")
)

func init() {
	flagset.SetOutput(ioutil.Discard)
	flagset.BoolVar(useBoundary, "b", false, "")
	flagset.BoolVar(isHelp, "h", false, "")
	flagset.BoolVar(isVersion, "v", false, "")
}

func usage() {
	fmt.Fprintf(os.Stderr, `
Usage: %[1]s [OPTION]... FROM TO [FILE]...
Substitute multiple words at once
by FROM and TO patterns.

Options:
  -b, --boundary    use word boundary in matcher
  -h, --help        show this help message
  -v, --version     output version information and exit

Syntax:
  pattern = group {"/" group}
  group   = branch {"," branch}
  branch  = {letter | "\/" | "\,"}

Examples:
  %[1]s true,false false,true ./file
  %[1]s dog,cat/s cat,dog/s ~/Document/questionnaire
`[1:], name)
}

func printVersion() {
	fmt.Fprintln(os.Stderr, version)
}

func printError(err interface{}) {
	fmt.Fprintf(os.Stderr, "%s: %s\n", name, err)
}

func do(r *Replacer, src io.Reader) error {
	b := bufio.NewScanner(src)
	for b.Scan() {
		fmt.Println(r.ReplaceAll(b.Text()))
	}
	return b.Err()
}

func _main() int {
	if err := flagset.Parse(os.Args[1:]); err != nil {
		printError(err)
		return 2
	}
	switch {
	case *isHelp:
		usage()
		return 0
	case *isVersion:
		printVersion()
		return 0
	}

	switch flagset.NArg() {
	case 0:
		printError("no specify FROM and TO")
		return 2
	case 1:
		printError("no specify TO")
		return 2
	}
	from, to := flagset.Arg(0), flagset.Arg(1)

	r, err := NewReplacer(from, to, *useBoundary)
	if err != nil {
		printError(err)
		return 2
	}

	if flagset.NArg() < 3 {
		if err = do(r, os.Stdin); err != nil {
			printError(err)
			return 1
		}
		return 0
	}

	var srcls []io.Reader
	for _, file := range flagset.Args()[2:] {
		src, err := os.Open(file)
		if err != nil {
			printError(err)
			return 1
		}
		defer src.Close()
		srcls = append(srcls, src)
	}
	if err = do(r, io.MultiReader(srcls...)); err != nil {
		printError(err)
		return 1
	}
	return 0
}

func main() {
	e := _main()
	os.Exit(e)
}
<commit_msg>s/printError/printErr/<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"os"
)

var (
	name    = "msub"
	version = "0.2.1"

	flagset     = flag.NewFlagSet(name, flag.ContinueOnError)
	useBoundary = flagset.Bool("boundary", false, "")
	isHelp      = flagset.Bool("help", false, "")
	isVersion   = flagset.Bool("version", false, "")
)

func init() {
	flagset.SetOutput(ioutil.Discard)
	flagset.BoolVar(useBoundary, "b", false, "")
	flagset.BoolVar(isHelp, "h", false, "")
	flagset.BoolVar(isVersion, "v", false, "")
}

func usage() {
	fmt.Fprintf(os.Stderr, `
Usage: %[1]s [OPTION]... FROM TO [FILE]...
Substitute multiple words at once
by FROM and TO patterns.

Options:
  -b, --boundary    use word boundary in matcher
  -h, --help        show this help message
  -v, --version     output version information and exit

Syntax:
  pattern = group {"/" group}
  group   = branch {"," branch}
  branch  = {letter | "\/" | "\,"}

Examples:
  %[1]s true,false false,true ./file
  %[1]s dog,cat/s cat,dog/s ~/Document/questionnaire
`[1:], name)
}

func printVersion() {
	fmt.Fprintln(os.Stderr, version)
}

func printErr(err interface{}) {
	fmt.Fprintf(os.Stderr, "%s: %s\n", name, err)
}

func do(r *Replacer, src io.Reader) error {
	b := bufio.NewScanner(src)
	for b.Scan() {
		fmt.Println(r.ReplaceAll(b.Text()))
	}
	return b.Err()
}

func _main() int {
	if err := flagset.Parse(os.Args[1:]); err != nil {
		printErr(err)
		return 2
	}
	switch {
	case *isHelp:
		usage()
		return 0
	case *isVersion:
		printVersion()
		return 0
	}

	switch flagset.NArg() {
	case 0:
		printErr("no specify FROM and TO")
		return 2
	case 1:
		printErr("no specify TO")
		return 2
	}
	from, to := flagset.Arg(0), flagset.Arg(1)

	r, err := NewReplacer(from, to, *useBoundary)
	if err != nil {
		printErr(err)
		return 2
	}

	if flagset.NArg() < 3 {
		if err = do(r, os.Stdin); err != nil {
			printErr(err)
			return 1
		}
		return 0
	}

	var srcls []io.Reader
	for _, file := range flagset.Args()[2:] {
		src, err := os.Open(file)
		if err != nil {
			printErr(err)
			return 1
		}
		defer src.Close()
		srcls = append(srcls, src)
	}
	if err = do(r, io.MultiReader(srcls...)); err != nil {
		printErr(err)
		return 1
	}
	return 0
}

func main() {
	e := _main()
	os.Exit(e)
}
<|endoftext|>


<commit_before>package main

import (
	"log"

	"github.com/samuel/go-opencl/cl"
)

func main() {

	platforms, err := cl.GetPlatforms()
	if err != nil {
		log.Panic(err)
	}
	for _, platform := range platforms {
		log.Println("Platform", platform.Name())
		devices, err := cl.GetDevices(platform, cl.DeviceTypeAll)
		if err != nil {
			log.Panic(err)
		}
		log.Println(len(devices), "device(s) found:")
		for i, device := range devices {
			log.Println(i, "-", device.Type(), "-", device.Name())
		}
	}
}
<commit_msg>Initial miner poc<commit_after>package main

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"math"
	"net/http"
	"time"
	"unsafe"

	"github.com/samuel/go-opencl/cl"
)

var kernelSource = `
static inline ulong rotr64( __const ulong w, __const unsigned c ) { return ( w >> c ) | ( w << ( 64 - c ) ); }

__constant static const uchar blake2b_sigma[12][16] = {
	{ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15 } ,
	{ 14, 10, 4,  8,  9,  15, 13, 6,  1,  12, 0,  2,  11, 7,  5,  3  } ,
	{ 11, 8,  12, 0,  5,  2,  15, 13, 10, 14, 3,  6,  7,  1,  9,  4  } ,
	{ 7,  9,  3,  1,  13, 12, 11, 14, 2,  6,  5,  10, 4,  0,  15, 8  } ,
	{ 9,  0,  5,  7,  2,  4,  10, 15, 14, 1,  11, 12, 6,  8,  3,  13 } ,
	{ 2,  12, 6,  10, 0,  11, 8,  3,  4,  13, 7,  5,  15, 14, 1,  9  } ,
	{ 12, 5,  1,  15, 14, 13, 4,  10, 0,  7,  6,  3,  9,  2,  8,  11 } ,
	{ 13, 11, 7,  14, 12, 1,  3,  9,  5,  0,  15, 4,  8,  6,  2,  10 } ,
	{ 6,  15, 14, 9,  11, 3,  0,  8,  12, 2,  13, 7,  1,  4,  10, 5  } ,
	{ 10, 2,  8,  4,  7,  6,  1,  5,  15, 11, 9,  14, 3,  12, 13, 0  } ,
	{ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15 } ,
	{ 14, 10, 4,  8,  9,  15, 13, 6,  1,  12, 0,  2,  11, 7,  5,  3  } };

// Target is passed in via headerIn[32 - 29]
__kernel void nonceGrind(__global ulong *headerIn, __global ulong *nonceOut) {
	ulong target = headerIn[4];
	ulong m[16] = {	headerIn[0], headerIn[1],
	                headerIn[2], headerIn[3],
	                (ulong)get_global_id(0), headerIn[5],
	                headerIn[6], headerIn[7],
	                headerIn[8], headerIn[9], 0, 0, 0, 0, 0, 0 };

	ulong v[16] = { 0x6a09e667f2bdc928, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
	                0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179,
	                0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
	                0x510e527fade68281, 0x9b05688c2b3e6c1f, 0xe07c265404be4294, 0x5be0cd19137e2179 };

#define G(r,i,a,b,c,d) \
	a = a + b + m[blake2b_sigma[r][2*i]]; \
	d = rotr64(d ^ a, 32); \
	c = c + d; \
	b = rotr64(b ^ c, 24); \
	a = a + b + m[blake2b_sigma[r][2*i+1]]; \
	d = rotr64(d ^ a, 16); \
	c = c + d; \
	b = rotr64(b ^ c, 63);

#define ROUND(r)                    \
	G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
	G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
	G(r,2,v[ 2],v[ 6],v[10],v[14]); \
	G(r,3,v[ 3],v[ 7],v[11],v[15]); \
	G(r,4,v[ 0],v[ 5],v[10],v[15]); \
	G(r,5,v[ 1],v[ 6],v[11],v[12]); \
	G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
	G(r,7,v[ 3],v[ 4],v[ 9],v[14]);

	ROUND( 0 );
	ROUND( 1 );
	ROUND( 2 );
	ROUND( 3 );
	ROUND( 4 );
	ROUND( 5 );
	ROUND( 6 );
	ROUND( 7 );
	ROUND( 8 );
	ROUND( 9 );
	ROUND( 10 );
	ROUND( 11 );
#undef G
#undef ROUND

	if (as_ulong(as_uchar8(0x6a09e667f2bdc928 ^ v[0] ^ v[8]).s76543210) < target) {
		*nonceOut = m[4];
		return;
	}
}
`

var getworkurl = "http://localhost:9980/miner/headerforwork"
var submitblockurl = "http://localhost:9980/miner/submitheader"
var intensity = 10
var localItemSize = 8

func loadCLProgramSource() (sources []string) {
	filename := "sia-gpu-miner.cl"

	buf, err := ioutil.ReadFile(filename)
	if err != nil {
		panic(err)
	}
	sources = []string{string(buf)}
	return
}

func getHeaderForWork() (target, header []byte, err error) {
	resp, err := http.Get(getworkurl)
	if err != nil {
		return
	}
	defer resp.Body.Close()
	buf := make([]byte, 113)
	n, err := resp.Body.Read(buf)
	if err != nil && err != io.EOF {
		return
	}
	if n < 112 {
		err = errors.New("Invalid response")
	} else {
		err = nil
	}

	target = buf[:32]
	header = buf[32:112]
	//TODO: check for invalid target
	return
}

func submitHeader(header []byte) (err error) {
	_, err = http.Post(submitblockurl, "", bytes.NewReader(header))
	return
}

func enqueueWriteBufferByte(q *cl.CommandQueue, buffer *cl.MemObject, blocking bool, offset int, data []byte, eventWaitList []*cl.Event) (*cl.Event, error) {
	dataPtr := unsafe.Pointer(&data[0])
	dataSize := int(unsafe.Sizeof(data[0])) * len(data)
	return q.EnqueueWriteBuffer(buffer, blocking, offset, dataSize, dataPtr, eventWaitList)
}

func mine(clDevice *cl.Device, minerID int) {
	log.Println(minerID, "- Initializing", clDevice.Type(), "-", clDevice.Name())

	context, err := cl.CreateContext([]*cl.Device{clDevice})
	if err != nil {
		log.Fatalln(minerID, "-", err)
	}
	defer context.Release()

	commandQueue, err := context.CreateCommandQueue(clDevice, 0)
	if err != nil {
		log.Fatalln(minerID, "-", err)
	}
	defer commandQueue.Release()

	program, err := context.CreateProgramWithSource([]string{kernelSource})
	if err != nil {
		log.Fatalln(minerID, "-", err)
	}
	defer program.Release()

	err = program.BuildProgram([]*cl.Device{clDevice}, "")
	if err != nil {
		log.Fatalln(minerID, "-", err)
	}

	kernel, err := program.CreateKernel("nonceGrind")
	if err != nil {
		log.Fatalln(minerID, "-", err)
	}
	defer kernel.Release()

	blockHeaderObj, err := context.CreateEmptyBuffer(cl.MemReadOnly, 80)
	if err != nil {
		log.Fatalln(minerID, "-", err)
	}
	defer blockHeaderObj.Release()
	kernel.SetArgBuffer(0, blockHeaderObj)

	nonceOutObj, err := context.CreateEmptyBuffer(cl.MemReadWrite, 8)
	if err != nil {
		log.Fatalln(minerID, "-", err)
	}
	defer nonceOutObj.Release()
	kernel.SetArgBuffer(1, nonceOutObj)

	log.Println(minerID, "- Started mining on", clDevice.Type(), "-", clDevice.Name())

	globalItemSize := int(math.Exp2(float64(intensity)))
	for {
		start := time.Now()

		target, header, err := getHeaderForWork()
		if err != nil {
			log.Println(minerID, "- ERROR ", err)
			continue
		}
		//copy target to header
		for i := 0; i < 8; i++ {
			header[i+32] = target[7-i]
		}
		//TODO: offset

		//Copy input to kernel args
		if _, err = enqueueWriteBufferByte(commandQueue, blockHeaderObj, true, 0, header, nil); err != nil {
			log.Fatalln(minerID, "-", err)
		}

		nonceOut := make([]byte, 8, 8) //TODO: get this out of the for loop
		if _, err = enqueueWriteBufferByte(commandQueue, nonceOutObj, true, 0, nonceOut, nil); err != nil {
			log.Fatalln(minerID, "-", err)
		}

		//Run the kernel
		//globalIDOffset := globalItemSize
		log.Println(minerID, "- global item size:", globalItemSize, "- local item size:", localItemSize)
		if _, err = commandQueue.EnqueueNDRangeKernel(kernel, nil, []int{globalItemSize}, []int{localItemSize}, nil); err != nil {
			log.Fatalln(minerID, "-", err)
		}
		//Get output
		dataSize := int(unsafe.Sizeof(nonceOut[0])) * len(nonceOut)
		if _, err = commandQueue.EnqueueReadBuffer(nonceOutObj, true, 0, dataSize, unsafe.Pointer(&nonceOut[0]), nil); err != nil {
			log.Fatalln(minerID, "_", err)
		}
		//Check if match found
		if nonceOut[0] != 0 {
			log.Println(minerID, "-", "Yay, block found!")
			// Copy nonce to header.
			for i := 0; i < 8; i++ {
				header[i+32] = nonceOut[i]
			}
			if err = submitHeader(header); err != nil {
				log.Println(minerID, "- Error submitting block -", err)
			}
		}

		hashRate := float64(globalItemSize) / (time.Since(start).Seconds() * 1000000)
		log.Printf("%d - Mining at %.3f MH/s", minerID, hashRate)

	}

}

func main() {

	platforms, err := cl.GetPlatforms()
	if err != nil {
		log.Panic(err)
	}

	clDevices := make([]*cl.Device, 0, 4)
	for _, platform := range platforms {
		log.Println("Platform", platform.Name())
		platormDevices, err := cl.GetDevices(platform, cl.DeviceTypeAll)
		if err != nil {
			log.Panic(err)
		}
		log.Println(len(platormDevices), "device(s) found:")
		for i, device := range platormDevices {
			log.Println(i, "-", device.Type(), "-", device.Name(), "- Compiler Available: ", device.CompilerAvailable())
			log.Println(i, "- Max work dimensions", device.MaxWorkItemDimensions())
			log.Println(i, "- Max work item sizes", device.MaxWorkItemSizes())
			log.Println(i, "- OpenCL C Version", device.OpenCLCVersion())
			log.Println(i, "- Max Work Group Size", device.MaxWorkGroupSize())
			//TODO: filter devices on type
			clDevices = append(clDevices, device)
		}
	}

	for i, device := range clDevices {
		go mine(device, i)
	}

	var input string
	fmt.Scanln(&input)
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"math"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"strings"
	"sync"
	"time"

	"code.google.com/p/gogoprotobuf/proto"

	pb "github.com/dgryski/carbonzipper/carbonzipperpb"
)

type zipper string

var Zipper zipper

var timeFormats = []string{"15:04 20060102", "20060102", "01/02/06"}

// dateParamToEpoch turns a passed string parameter into an epoch we can send to the Zipper
func dateParamToEpoch(s string, d int64) string {

	if s == "" {
		// return the default if nothing was passed
		return strconv.Itoa(int(d))
	}

	// relative timestamp
	if s[0] == '-' {

		offset, err := intervalString(s[1:])
		if err != nil {
			return strconv.Itoa(int(d))
		}

		return strconv.Itoa(int(timeNow().Add(-time.Duration(offset) * time.Second).Unix()))
	}

	_, err := strconv.Atoi(s)
	if err == nil && len(s) > 8 {
		return s // We got a timestamp so returning it
	}

	if strings.Contains(s, "_") {
		s = strings.Replace(s, "_", " ", 1) // Go can't parse _ in date strings
	}

	for _, format := range timeFormats {
		t, err := time.Parse(format, s)
		if err == nil {
			return strconv.Itoa(int(t.Unix()))
		}
	}
	return strconv.Itoa(int(d))
}

func intervalString(s string) (int32, error) {

	var j int

	for j < len(s) && s[j] >= '0' && s[j] <= '9' {
		j++
	}
	offsetStr, unitStr := s[:j], s[j:]

	var units int
	switch unitStr {
	case "s", "sec", "secs", "second", "seconds":
		units = 1
	case "min", "minute", "minutes":
		units = 60
	case "h", "hour", "hours":
		units = 60 * 60
	case "d", "day", "days":
		units = 24 * 60 * 60
	case "w", "week", "weeks":
		units = 7 * 24 * 60 * 60
	case "mon", "month", "months":
		units = 30 * 24 * 60 * 60
	case "y", "year", "years":
		units = 365 * 24 * 60 * 60
	default:
		return 0, errors.New("unknown time units")
	}

	offset, err := strconv.Atoi(offsetStr)
	if err != nil {
		return 0, err
	}

	return int32(offset * units), nil
}

// FIXME(dgryski): extract the http.Get + unproto code into its own function

func (z zipper) Find(metric string) (pb.GlobResponse, error) {

	u, _ := url.Parse(string(z) + "/metrics/find/")

	u.RawQuery = url.Values{
		"query":  []string{metric},
		"format": []string{"protobuf"},
	}.Encode()

	resp, err := http.Get(u.String())
	if err != nil {
		log.Printf("Find: http.Get: %+v\n", err)
		return pb.GlobResponse{}, err
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Printf("Find: ioutil.ReadAll: %+v\n", err)
		return pb.GlobResponse{}, err
	}

	var pbresp pb.GlobResponse

	err = proto.Unmarshal(body, &pbresp)
	if err != nil {
		log.Printf("Find: proto.Unmarshal: %+v\n", err)
		return pb.GlobResponse{}, err
	}

	return pbresp, nil
}

func (z zipper) Render(metric, from, until string) (pb.FetchResponse, error) {

	u, _ := url.Parse(string(z) + "/render/")

	u.RawQuery = url.Values{
		"target": []string{metric},
		"format": []string{"protobuf"},
		"from":   []string{from},
		"until":  []string{until},
	}.Encode()

	resp, err := http.Get(u.String())
	if err != nil {
		log.Printf("Render: http.Get: %s: %+v\n", metric, err)
		return pb.FetchResponse{}, err
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Printf("Render: ioutil.ReadAll: %s: %+v\n", metric, err)
		return pb.FetchResponse{}, err
	}

	var pbresp pb.FetchResponse

	err = proto.Unmarshal(body, &pbresp)
	if err != nil {
		log.Printf("Render: proto.Unmarshal: %s: %+v\n", metric, err)
		return pb.FetchResponse{}, err
	}

	return pbresp, nil
}

type limiter chan struct{}

func (l limiter) enter() { l <- struct{}{} }
func (l limiter) leave() { <-l }

var Limiter limiter

// for testing
var timeNow = time.Now

type graphitePoint struct {
	value float64
	t     int32
}

func (g graphitePoint) MarshalJSON() ([]byte, error) {
	// TODO(dgryski): fmt.Sprintf() is slow, use strconv.Append{Float,Int}
	if math.IsNaN(g.value) {
		return []byte(fmt.Sprintf("[null,%d]", g.t)), nil
	}
	return []byte(fmt.Sprintf("[%g,%d]", g.value, g.t)), nil
}

type jsonResponse struct {
	Target     string          `json:"target"`
	Datapoints []graphitePoint `json:"datapoints"`
}

func renderHandler(w http.ResponseWriter, r *http.Request) {

	r.ParseForm()
	targets := r.Form["target"]
	from := r.FormValue("from")
	until := r.FormValue("until")

	cacheKey := r.Form.Encode()

	if response, ok := queryCache.get(cacheKey); ok {
		w.Header().Set("Content-Type", "application/json")
		w.Write(response.([]byte))
		return
	}

	// normalize from and until values
	from = dateParamToEpoch(from, timeNow().Add(-24*time.Hour).Unix())
	until = dateParamToEpoch(until, timeNow().Unix())

	var results []*pb.FetchResponse

	for _, target := range targets {

		exp, e, err := parseExpr(target)
		if err != nil || e != "" {
			http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
			return
		}

		metricMap := make(map[string][]*pb.FetchResponse)

		for _, metric := range exp.metrics() {

			var glob pb.GlobResponse

			if response, ok := findCache.get(metric); ok {
				glob = response.(pb.GlobResponse)
			} else {
				var err error
				glob, err = Zipper.Find(metric)
				if err != nil {
					continue
				}
				findCache.set(metric, glob)
			}

			// for each server in find response query render
			rch := make(chan *pb.FetchResponse, len(glob.GetMatches()))
			for _, m := range glob.GetMatches() {
				go func(m *pb.GlobMatch) {
					Limiter.enter()
					var rptr *pb.FetchResponse
					if m.GetIsLeaf() {
						r, err := Zipper.Render(m.GetPath(), from, until)
						if err == nil {
							rptr = &r
						}
					}
					rch <- rptr
					Limiter.leave()
				}(m)
			}

			for i := 0; i < len(glob.GetMatches()); i++ {
				r := <-rch
				if r != nil {
					metricMap[metric] = append(metricMap[metric], r)
				}
			}
		}

		exprs := evalExpr(exp, metricMap)
		results = append(results, exprs...)
	}

	var jresults []jsonResponse

	for _, r := range results {
		if r == nil {
			log.Println("skipping nil result")
		}
		datapoints := make([]graphitePoint, 0, len(r.Values))
		t := *r.StartTime
		for i, v := range r.Values {
			if r.IsAbsent[i] {
				v = math.NaN()
			}
			datapoints = append(datapoints, graphitePoint{value: v, t: t})
			t += *r.StepTime
		}
		jresults = append(jresults, jsonResponse{Target: r.GetName(), Datapoints: datapoints})
	}

	jout, err := json.Marshal(jresults)
	if err != nil {
		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	}

	queryCache.set(cacheKey, jout)

	w.Header().Set("Content-Type", "application/json")
	w.Write(jout)
}

var queryCache *expireCache
var findCache *expireCache

type cacheElement struct {
	validUntil time.Time
	data       interface{}
}

type expireCache struct {
	sync.Mutex
	cache map[string]cacheElement
}

func (ec *expireCache) get(k string) (interface{}, bool) {
	ec.Lock()
	v, ok := ec.cache[k]
	ec.Unlock()
	if !ok || v.validUntil.Before(time.Now()) {
		return nil, false
	}
	return v.data, ok
}

func (ec *expireCache) set(k string, v interface{}) {
	ec.Lock()
	ec.cache[k] = cacheElement{validUntil: time.Now().Add(60 * time.Second), data: v}
	ec.Unlock()
}

func (ec *expireCache) cleaner() {

	var keys []string

	for {
		time.Sleep(5 * time.Minute)

		now := time.Now()
		ec.Lock()

		for k, v := range ec.cache {
			if v.validUntil.Before(now) {
				keys = append(keys, k)
			}
		}

		for _, k := range keys {
			delete(ec.cache, k)
		}

		keys = keys[:0]
		ec.Unlock()
	}
}

func main() {

	z := flag.String("z", "", "zipper")
	port := flag.Int("p", 8080, "port")
	l := flag.Int("l", 20, "concurrency limit")

	flag.Parse()

	if *z == "" {
		log.Fatal("no zipper (-z) provided")
	}

	if p := os.Getenv("PORT"); p != "" {
		*port, _ = strconv.Atoi(p)
	}

	Limiter = make(chan struct{}, *l)

	if *z == "" {
		log.Fatal("no zipper provided")
	}

	if _, err := url.Parse(*z); err != nil {
		log.Fatal("unable to parze zipper:", err)
	}

	log.Println("using zipper", *z)

	queryCache = &expireCache{cache: make(map[string]cacheElement)}
	go queryCache.cleaner()

	findCache = &expireCache{cache: make(map[string]cacheElement)}
	go findCache.cleaner()

	Zipper = zipper(*z)

	http.HandleFunc("/render/", renderHandler)

	log.Println("listening on port", *port)
	log.Fatalln(http.ListenAndServe(":"+strconv.Itoa(*port), nil))

}
<commit_msg>Allow disabling cached query responses with noCache<commit_after>package main

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"math"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"strings"
	"sync"
	"time"

	"code.google.com/p/gogoprotobuf/proto"

	pb "github.com/dgryski/carbonzipper/carbonzipperpb"
)

type zipper string

var Zipper zipper

var timeFormats = []string{"15:04 20060102", "20060102", "01/02/06"}

// dateParamToEpoch turns a passed string parameter into an epoch we can send to the Zipper
func dateParamToEpoch(s string, d int64) string {

	if s == "" {
		// return the default if nothing was passed
		return strconv.Itoa(int(d))
	}

	// relative timestamp
	if s[0] == '-' {

		offset, err := intervalString(s[1:])
		if err != nil {
			return strconv.Itoa(int(d))
		}

		return strconv.Itoa(int(timeNow().Add(-time.Duration(offset) * time.Second).Unix()))
	}

	_, err := strconv.Atoi(s)
	if err == nil && len(s) > 8 {
		return s // We got a timestamp so returning it
	}

	if strings.Contains(s, "_") {
		s = strings.Replace(s, "_", " ", 1) // Go can't parse _ in date strings
	}

	for _, format := range timeFormats {
		t, err := time.Parse(format, s)
		if err == nil {
			return strconv.Itoa(int(t.Unix()))
		}
	}
	return strconv.Itoa(int(d))
}

func intervalString(s string) (int32, error) {

	var j int

	for j < len(s) && s[j] >= '0' && s[j] <= '9' {
		j++
	}
	offsetStr, unitStr := s[:j], s[j:]

	var units int
	switch unitStr {
	case "s", "sec", "secs", "second", "seconds":
		units = 1
	case "min", "minute", "minutes":
		units = 60
	case "h", "hour", "hours":
		units = 60 * 60
	case "d", "day", "days":
		units = 24 * 60 * 60
	case "w", "week", "weeks":
		units = 7 * 24 * 60 * 60
	case "mon", "month", "months":
		units = 30 * 24 * 60 * 60
	case "y", "year", "years":
		units = 365 * 24 * 60 * 60
	default:
		return 0, errors.New("unknown time units")
	}

	offset, err := strconv.Atoi(offsetStr)
	if err != nil {
		return 0, err
	}

	return int32(offset * units), nil
}

// FIXME(dgryski): extract the http.Get + unproto code into its own function

func (z zipper) Find(metric string) (pb.GlobResponse, error) {

	u, _ := url.Parse(string(z) + "/metrics/find/")

	u.RawQuery = url.Values{
		"query":  []string{metric},
		"format": []string{"protobuf"},
	}.Encode()

	resp, err := http.Get(u.String())
	if err != nil {
		log.Printf("Find: http.Get: %+v\n", err)
		return pb.GlobResponse{}, err
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Printf("Find: ioutil.ReadAll: %+v\n", err)
		return pb.GlobResponse{}, err
	}

	var pbresp pb.GlobResponse

	err = proto.Unmarshal(body, &pbresp)
	if err != nil {
		log.Printf("Find: proto.Unmarshal: %+v\n", err)
		return pb.GlobResponse{}, err
	}

	return pbresp, nil
}

func (z zipper) Render(metric, from, until string) (pb.FetchResponse, error) {

	u, _ := url.Parse(string(z) + "/render/")

	u.RawQuery = url.Values{
		"target": []string{metric},
		"format": []string{"protobuf"},
		"from":   []string{from},
		"until":  []string{until},
	}.Encode()

	resp, err := http.Get(u.String())
	if err != nil {
		log.Printf("Render: http.Get: %s: %+v\n", metric, err)
		return pb.FetchResponse{}, err
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Printf("Render: ioutil.ReadAll: %s: %+v\n", metric, err)
		return pb.FetchResponse{}, err
	}

	var pbresp pb.FetchResponse

	err = proto.Unmarshal(body, &pbresp)
	if err != nil {
		log.Printf("Render: proto.Unmarshal: %s: %+v\n", metric, err)
		return pb.FetchResponse{}, err
	}

	return pbresp, nil
}

type limiter chan struct{}

func (l limiter) enter() { l <- struct{}{} }
func (l limiter) leave() { <-l }

var Limiter limiter

// for testing
var timeNow = time.Now

type graphitePoint struct {
	value float64
	t     int32
}

func (g graphitePoint) MarshalJSON() ([]byte, error) {
	// TODO(dgryski): fmt.Sprintf() is slow, use strconv.Append{Float,Int}
	if math.IsNaN(g.value) {
		return []byte(fmt.Sprintf("[null,%d]", g.t)), nil
	}
	return []byte(fmt.Sprintf("[%g,%d]", g.value, g.t)), nil
}

type jsonResponse struct {
	Target     string          `json:"target"`
	Datapoints []graphitePoint `json:"datapoints"`
}

func renderHandler(w http.ResponseWriter, r *http.Request) {

	r.ParseForm()
	targets := r.Form["target"]
	from := r.FormValue("from")
	until := r.FormValue("until")
	useCache := r.FormValue("noCache") == ""

	// make sure the cache key doesn't say noCache, because it will never hit
	r.Form.Del("noCache")

	cacheKey := r.Form.Encode()

	if response, ok := queryCache.get(cacheKey); useCache && ok {
		w.Header().Set("Content-Type", "application/json")
		w.Write(response.([]byte))
		return
	}

	// normalize from and until values
	from = dateParamToEpoch(from, timeNow().Add(-24*time.Hour).Unix())
	until = dateParamToEpoch(until, timeNow().Unix())

	var results []*pb.FetchResponse

	for _, target := range targets {

		exp, e, err := parseExpr(target)
		if err != nil || e != "" {
			http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
			return
		}

		metricMap := make(map[string][]*pb.FetchResponse)

		for _, metric := range exp.metrics() {

			var glob pb.GlobResponse

			if response, ok := findCache.get(metric); ok {
				glob = response.(pb.GlobResponse)
			} else {
				var err error
				glob, err = Zipper.Find(metric)
				if err != nil {
					continue
				}
				findCache.set(metric, glob)
			}

			// for each server in find response query render
			rch := make(chan *pb.FetchResponse, len(glob.GetMatches()))
			for _, m := range glob.GetMatches() {
				go func(m *pb.GlobMatch) {
					Limiter.enter()
					var rptr *pb.FetchResponse
					if m.GetIsLeaf() {
						r, err := Zipper.Render(m.GetPath(), from, until)
						if err == nil {
							rptr = &r
						}
					}
					rch <- rptr
					Limiter.leave()
				}(m)
			}

			for i := 0; i < len(glob.GetMatches()); i++ {
				r := <-rch
				if r != nil {
					metricMap[metric] = append(metricMap[metric], r)
				}
			}
		}

		exprs := evalExpr(exp, metricMap)
		results = append(results, exprs...)
	}

	var jresults []jsonResponse

	for _, r := range results {
		if r == nil {
			log.Println("skipping nil result")
		}
		datapoints := make([]graphitePoint, 0, len(r.Values))
		t := *r.StartTime
		for i, v := range r.Values {
			if r.IsAbsent[i] {
				v = math.NaN()
			}
			datapoints = append(datapoints, graphitePoint{value: v, t: t})
			t += *r.StepTime
		}
		jresults = append(jresults, jsonResponse{Target: r.GetName(), Datapoints: datapoints})
	}

	jout, err := json.Marshal(jresults)
	if err != nil {
		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	}

	queryCache.set(cacheKey, jout)

	w.Header().Set("Content-Type", "application/json")
	w.Write(jout)
}

var queryCache *expireCache
var findCache *expireCache

type cacheElement struct {
	validUntil time.Time
	data       interface{}
}

type expireCache struct {
	sync.Mutex
	cache map[string]cacheElement
}

func (ec *expireCache) get(k string) (interface{}, bool) {
	ec.Lock()
	v, ok := ec.cache[k]
	ec.Unlock()
	if !ok || v.validUntil.Before(time.Now()) {
		return nil, false
	}
	return v.data, ok
}

func (ec *expireCache) set(k string, v interface{}) {
	ec.Lock()
	ec.cache[k] = cacheElement{validUntil: time.Now().Add(60 * time.Second), data: v}
	ec.Unlock()
}

func (ec *expireCache) cleaner() {

	var keys []string

	for {
		time.Sleep(5 * time.Minute)

		now := time.Now()
		ec.Lock()

		for k, v := range ec.cache {
			if v.validUntil.Before(now) {
				keys = append(keys, k)
			}
		}

		for _, k := range keys {
			delete(ec.cache, k)
		}

		keys = keys[:0]
		ec.Unlock()
	}
}

func main() {

	z := flag.String("z", "", "zipper")
	port := flag.Int("p", 8080, "port")
	l := flag.Int("l", 20, "concurrency limit")

	flag.Parse()

	if *z == "" {
		log.Fatal("no zipper (-z) provided")
	}

	if p := os.Getenv("PORT"); p != "" {
		*port, _ = strconv.Atoi(p)
	}

	Limiter = make(chan struct{}, *l)

	if *z == "" {
		log.Fatal("no zipper provided")
	}

	if _, err := url.Parse(*z); err != nil {
		log.Fatal("unable to parze zipper:", err)
	}

	log.Println("using zipper", *z)

	queryCache = &expireCache{cache: make(map[string]cacheElement)}
	go queryCache.cleaner()

	findCache = &expireCache{cache: make(map[string]cacheElement)}
	go findCache.cleaner()

	Zipper = zipper(*z)

	http.HandleFunc("/render/", renderHandler)

	log.Println("listening on port", *port)
	log.Fatalln(http.ListenAndServe(":"+strconv.Itoa(*port), nil))

}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"

	"github.com/CiscoCloud/consul-cli/commands"
)

const Name = "consul-cli"
const Version = "0.3.1"

func main() {
	log.SetOutput(ioutil.Discard)

	root := commands.Init(Name, Version)
	if err := root.Execute(); err != nil {
		fmt.Fprintln(root.Err, err)
		os.Exit(1)
	}

	os.Exit(0)
}
<commit_msg>CiscoCloud -> ChrisAubuchon<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"

	"github.com/ChrisAubuchon/consul-cli/commands"
)

const Name = "consul-cli"
const Version = "0.3.1"

func main() {
	log.SetOutput(ioutil.Discard)

	root := commands.Init(Name, Version)
	if err := root.Execute(); err != nil {
		fmt.Fprintln(root.Err, err)
		os.Exit(1)
	}

	os.Exit(0)
}
<|endoftext|>


<commit_before>package main

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

	"github.com/nlopes/slack"
)

var SLACK_TOKEN = os.Getenv("SLACK_TOKEN")

func main() {
	if SLACK_TOKEN == "" {
		log.Fatal("Missing SLACK_TOKEN env var")
	}

	fmt.Println(SLACK_TOKEN)

	api := slack.New(SLACK_TOKEN)
	rtm := api.NewRTM()
	go rtm.ManageConnection()

Loop:
	for {
		select {
		case msg := <-rtm.IncomingEvents:
			fmt.Print("Event Received: ")
			switch ev := msg.Data.(type) {
			case *slack.ConnectedEvent:
				fmt.Println("Connection counter:", ev.ConnectionCount)

			case *slack.MessageEvent:
				fmt.Printf("Message: %v\n", ev)
				info := rtm.GetInfo()
				prefix := fmt.Sprintf("<@%s> ", info.User.ID)

				if ev.User != info.User.ID && strings.HasPrefix(ev.Text, prefix) {
					rtm.SendMessage(rtm.NewOutgoingMessage("What's up buddy!?!?", ev.Channel))
				}

			case *slack.RTMError:
				fmt.Printf("Error: %s\n", ev.Error())

			case *slack.InvalidAuthEvent:
				fmt.Printf("Invalid credentials")
				break Loop

			default:
				//Take no action
			}
		}
	}
}
<commit_msg>Added conversational patterns<commit_after>package main

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

	"github.com/nlopes/slack"
)

var SLACK_TOKEN = os.Getenv("SLACK_TOKEN")

func main() {

	if SLACK_TOKEN == "" {
		log.Fatal("Missing SLACK_TOKEN env var")
	}

	api := slack.New(SLACK_TOKEN)
	api.SetDebug(true)

	rtm := api.NewRTM()
	go rtm.ManageConnection()

Loop:
	for {
		select {
		case msg := <-rtm.IncomingEvents:
			fmt.Print("Event Received: ")
			switch ev := msg.Data.(type) {
			case *slack.ConnectedEvent:
				fmt.Println("Connection counter:", ev.ConnectionCount)

			case *slack.MessageEvent:
				fmt.Printf("Message: %v\n", ev)
				info := rtm.GetInfo()
				prefix := fmt.Sprintf("<@%s> ", info.User.ID)

				if ev.User != info.User.ID && strings.HasPrefix(ev.Text, prefix) {
					respond(rtm, ev, prefix)
				}

			case *slack.RTMError:
				fmt.Printf("Error: %s\n", ev.Error())

			case *slack.InvalidAuthEvent:
				fmt.Printf("Invalid credentials")
				break Loop

			default:
				//Take no action
			}
		}
	}
}

func respond(rtm *slack.RTM, msg *slack.MessageEvent, prefix string) {
	var response string
	text := msg.Text
	text = strings.TrimPrefix(text, prefix)
	text = strings.TrimSpace(text)
	text = strings.ToLower(text)

	acceptedGreetings := map[string]bool{
		"what's up?": true,
		"hey!":       true,
		"yo":         true,
		"hi!":        true,
	}
	acceptedHowAreYou := map[string]bool{
		"how's it going?": true,
		"how are ya?":     true,
		"feeling okay?":   true,
	}

	if acceptedGreetings[text] {
		response = "What's up buddy!?!?!"
		rtm.SendMessage(rtm.NewOutgoingMessage(response, msg.Channel))
	} else if acceptedHowAreYou[text] {
		response = "Good. How are you?"
		rtm.SendMessage(rtm.NewOutgoingMessage(response, msg.Channel))
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/skelterjohn/go.matrix" // daa59528eefd43623a4c8e36373a86f9eef870a2
	"github.com/youpy/go-wav"
	"io"
	"log"
	"os"
)

func main() {
	// I have no idea what I am doing
	fmt.Println("Bop")
	if len(os.Args) <= 1 {
		log.Fatal("You need to tell me what file to encode.")
	}
	file, _ := os.Open(os.Args[1])

	output, _ := os.OpenFile("./out.wav", os.O_CREATE, 600)

	reader := wav.NewReader(file)

	// Settings for output
	var numSamples uint32 = 999999
	var numChannels uint16 = 2
	var sampleRate uint32 = 44100
	var bitsPerSample uint16 = 16
	writer := wav.NewWriter(output, numSamples, numChannels, sampleRate, bitsPerSample)
	BlockesProcessed := 0
	// End of settings for output
	var SampleBlock []float64
	SampleBlock = make([]float64, 8)
	for {
		samplez := make([]wav.Sample, 0)
		samples, err := reader.ReadSamples()
		// Samples will return (usally) 2048 samples in a single sitting

		log.Println(BlockesProcessed)
		if err == io.EOF {
			break
		}

		BlockesProcessed++
		var SamplePointer int = 0 // max is 8
		for _, sample := range samples {
			sam := wav.Sample{}
			L := reader.IntValue(sample, 0)
			R := reader.IntValue(sample, 1)
			MonoVal := (L + R) / 2

			// Now we add it to the staging array
			SampleBlock[SamplePointer] = float64(MonoVal)
			SamplePointer++
			if SamplePointer == 8 {
				GetPolyResults([]float64{0, 1, 2, 3, 4, 5, 6, 7}, SampleBlock)
				SamplePointer = 0
			}
			sam.Values[0] = L
			sam.Values[0] = R
			samplez = append(samplez, sam)
		}

		// fmt.Println(len(samplez), len(samples))
		writer.WriteSamples(samplez)
	}

}

var degree = 5

func GetPolyResults(xGiven []float64, yGiven []float64) []float64 {
	m := len(yGiven)
	if m != len(xGiven) {
		return []float64{0, 0, 0, 0, 0} // Send it back, There is nothing sane here.
	}
	if m < 5 {
		// Prevent the processing of really small datasets, This is becauase there
		// appears to be a bug in the libary that will trigger a crash in the go.matrix
		// if some (small) amount of values are entered. I don't know why this happens
		// (Otherwise I would have fixed it) but the URL for the github issue is:
		// https://github.com/skelterjohn/go.matrix/issues/11
		return []float64{0, 0, 0, 0, 0} // Send it back, There is nothing sane here.
	}
	n := degree + 1
	y := matrix.MakeDenseMatrix(yGiven, m, 1)
	x := matrix.Zeros(m, n)
	for i := 0; i < m; i++ {
		ip := float64(1)
		for j := 0; j < n; j++ {
			x.Set(i, j, ip)
			ip *= xGiven[i]
		}
	}

	q, r := x.QR()
	qty, err := q.Transpose().Times(y)
	if err != nil {
		log.Println(err)
		return []float64{0, 0, 0, 0, 0} // Send it back, There is nothing sane here.
	}
	c := make([]float64, n)
	for i := n - 1; i >= 0; i-- {
		c[i] = qty.Get(i, 0)
		for j := i + 1; j < n; j++ {
			c[i] -= c[j] * r.Get(i, j)
		}
		c[i] /= r.Get(i, i)
	}
	// log.Println(c)
	return c
}
<commit_msg>It now writes its outputs<commit_after>package main

import (
	"fmt"
	"github.com/skelterjohn/go.matrix" // daa59528eefd43623a4c8e36373a86f9eef870a2
	"github.com/youpy/go-wav"
	"io"
	"log"
	"os"
)

func main() {
	// I have no idea what I am doing
	fmt.Println("Bop")
	if len(os.Args) <= 1 {
		log.Fatal("You need to tell me what file to encode.")
	}
	file, _ := os.Open(os.Args[1])

	output, _ := os.OpenFile("./out.wav", os.O_CREATE, 600)
	outputpac, _ := os.OpenFile("./out.pac", os.O_CREATE, 600)

	reader := wav.NewReader(file)

	// Settings for output
	var numSamples uint32 = 999999
	var numChannels uint16 = 2
	var sampleRate uint32 = 44100
	var bitsPerSample uint16 = 16
	writer := wav.NewWriter(output, numSamples, numChannels, sampleRate, bitsPerSample)
	BlockesProcessed := 0
	// End of settings for output
	var SampleBlock []float64
	SampleBlock = make([]float64, 8)
	for {
		samplez := make([]wav.Sample, 0)
		samples, err := reader.ReadSamples()
		// Samples will return (usally) 2048 samples in a single sitting

		log.Println(BlockesProcessed)
		if err == io.EOF {
			break
		}

		BlockesProcessed++
		var SamplePointer int = 0 // max is 8
		for _, sample := range samples {
			sam := wav.Sample{}
			L := reader.IntValue(sample, 0)
			R := reader.IntValue(sample, 1)
			MonoVal := (L + R) / 2

			// Now we add it to the staging array
			SampleBlock[SamplePointer] = float64(MonoVal)
			SamplePointer++
			if SamplePointer == 8 {
				out := GetPolyResults([]float64{0, 1, 2, 3, 4, 5, 6, 7}, SampleBlock)
				Line := fmt.Sprintf("%f,%f,%f,%f,%f\n", out[0], out[1], out[2], out[3], out[4])
				outputpac.Write([]byte(Line))
				SamplePointer = 0
			}
			sam.Values[0] = L
			sam.Values[0] = R
			samplez = append(samplez, sam)
		}

		// fmt.Println(len(samplez), len(samples))
		writer.WriteSamples(samplez)
	}

}

var degree = 5

func GetPolyResults(xGiven []float64, yGiven []float64) []float64 {
	m := len(yGiven)
	if m != len(xGiven) {
		return []float64{0, 0, 0, 0, 0} // Send it back, There is nothing sane here.
	}
	if m < 5 {
		// Prevent the processing of really small datasets, This is becauase there
		// appears to be a bug in the libary that will trigger a crash in the go.matrix
		// if some (small) amount of values are entered. I don't know why this happens
		// (Otherwise I would have fixed it) but the URL for the github issue is:
		// https://github.com/skelterjohn/go.matrix/issues/11
		return []float64{0, 0, 0, 0, 0} // Send it back, There is nothing sane here.
	}
	n := degree + 1
	y := matrix.MakeDenseMatrix(yGiven, m, 1)
	x := matrix.Zeros(m, n)
	for i := 0; i < m; i++ {
		ip := float64(1)
		for j := 0; j < n; j++ {
			x.Set(i, j, ip)
			ip *= xGiven[i]
		}
	}

	q, r := x.QR()
	qty, err := q.Transpose().Times(y)
	if err != nil {
		log.Println(err)
		return []float64{0, 0, 0, 0, 0} // Send it back, There is nothing sane here.
	}
	c := make([]float64, n)
	for i := n - 1; i >= 0; i-- {
		c[i] = qty.Get(i, 0)
		for j := i + 1; j < n; j++ {
			c[i] -= c[j] * r.Get(i, j)
		}
		c[i] /= r.Get(i, i)
	}
	// log.Println(c)
	return c
}
<|endoftext|>


<commit_before>// Copyright 2014 Manu Martinez-Almeida.  All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.

package gin

import (
	"fmt"
	"os"
)

const GIN_MODE = "GIN_MODE"

const (
	DebugMode   string = "debug"
	ReleaseMode string = "release"
	TestMode    string = "test"
)
const (
	debugCode   = iota
	releaseCode = iota
	testCode    = iota
)

var gin_mode int = debugCode
var mode_name string = DebugMode

func init() {
	value := os.Getenv(GIN_MODE)
	if len(value) == 0 {
		SetMode(DebugMode)
	} else {
		SetMode(value)
	}
}

func SetMode(value string) {
	switch value {
	case DebugMode:
		gin_mode = debugCode
	case ReleaseMode:
		gin_mode = releaseCode
	case TestMode:
		gin_mode = testCode
	default:
		panic("gin mode unknown: " + value)
	}
	mode_name = value
}

func Mode() string {
	return mode_name
}

func IsDebugging() bool {
	return gin_mode == debugCode
}

func debugPrint(format string, values ...interface{}) {
	if IsDebugging() {
		fmt.Printf("[GIN-debug] "+format, values)
	}
}
<commit_msg>fixed debugPrint<commit_after>// Copyright 2014 Manu Martinez-Almeida.  All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.

package gin

import (
	"fmt"
	"os"
)

const GIN_MODE = "GIN_MODE"

const (
	DebugMode   string = "debug"
	ReleaseMode string = "release"
	TestMode    string = "test"
)
const (
	debugCode   = iota
	releaseCode = iota
	testCode    = iota
)

var gin_mode int = debugCode
var mode_name string = DebugMode

func init() {
	value := os.Getenv(GIN_MODE)
	if len(value) == 0 {
		SetMode(DebugMode)
	} else {
		SetMode(value)
	}
}

func SetMode(value string) {
	switch value {
	case DebugMode:
		gin_mode = debugCode
	case ReleaseMode:
		gin_mode = releaseCode
	case TestMode:
		gin_mode = testCode
	default:
		panic("gin mode unknown: " + value)
	}
	mode_name = value
}

func Mode() string {
	return mode_name
}

func IsDebugging() bool {
	return gin_mode == debugCode
}

func debugPrint(format string, values ...interface{}) {
	if IsDebugging() {
		fmt.Printf("[GIN-debug] "+format, values...)
	}
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2016 Michael McConville <mmcco@mykolab.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package main

import (
	"bufio"
	"fmt"
	"log"
	"os"
	"time"
)

func main() {
	var metainfo *bufio.Reader

	switch len(os.Args) {
	case 1:
		metainfo = bufio.NewReader(os.Stdin)
	case 2:
		file, err := os.Open(os.Args[1])
		if err != nil {
			log.Fatalln(err)
		}
		metainfo = bufio.NewReader(file)
	default:
		log.Fatalln("torrent-parse [metainfo-file]")
	}

	err, d := ParseDict(metainfo)
	if err != nil {
		log.Fatalln(err)
	}
	pretty_print(d)
}

func pretty_print(metainfo map[string]interface{}) {
	for k, v := range metainfo {
		switch k {
		case "announce":
			switch s := v.(type) {
			case string:
				fmt.Printf("\ntracker URL:\t\t%s\n", s)
			default:
				fmt.Println("\ntracker URL:\t\t[unexpected value type]")
			}
		case "info":
			d, ok := v.(map[string]interface{})
			if !ok {
				log.Fatalln("'info' value in metainfo dictionary has unexpected type")
			}

			for ki, vi := range d {
				if ki == "length" {
					switch flen := vi.(type) {
					case int64:
						fmt.Printf("\nfile length:\t\t%d\n", flen)
					default:
						fmt.Println("\nfile length:\t\t[unexpected value type]")
					}
				} else if ki == "files" {
					files, ok := vi.([]interface{})
					if !ok {
						log.Fatalln("'files' value in metainfo dictionary has unexpected type")
					}
					for _, file := range files {
						f, ok := file.(map[string]interface{})
						if !ok {
							log.Fatalln("item in 'files' list has unexpected type")
						}
						fpath, ok := f["path"].([]interface{})
						if !ok {
							log.Fatalln("file in 'files' list has a path of unexpected type")
						}
						// hack to avoid converting and using strings.Join
						for i, dir := range fpath {
							if i == 0 {
								fmt.Print("\n\t")
							} else {
								fmt.Print("/")
							}
							fmt.Print(dir)
						}
						fmt.Println()
						fmt.Printf("\tfile size:\t\t%d\n", f["length"])
					}
				}
			}
		case "created by":
			fmt.Printf("\ncreated with:\t\t%s\n", v)
		case "creation date":
			date, ok := v.(int64)
			if !ok {
				log.Fatalln("torrent creation date has unexpected type")
			}
			fmt.Printf("\ncreation date:\t\t%s\n", time.Unix(date, 0).String())
		case "comment":
			fmt.Printf("\ncomment:\t\t%s\n", v)
		case "encoding":
			fmt.Printf("\nencoding:\t\t%s\n", v)
		case "announce-list":
			fmt.Printf("\nannounce list:\t\t%s\n", v)
		case "url-list":
			fmt.Printf("\nURL list:\t\t%s\n", v)
		case "errors":
			fmt.Printf("\nerrors:\t\t%s\n", v)
		case "err_callback":
			fmt.Printf("\nerror callback:\t\t%s\n", v)
		case "log_callback":
			fmt.Printf("\nlog callback:\t\t%s\n", v)
		case "httpseeds":
			fmt.Printf("\nHTTP seeds:\t\t%s\n", v)
		default:
			fmt.Fprintln(os.Stderr, "\nencountered additional top-level dictionary key:", k)
		}
	}
	fmt.Println()
}
<commit_msg>Actually print filename when there's only one<commit_after>/*
 * Copyright (c) 2016 Michael McConville <mmcco@mykolab.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package main

import (
	"bufio"
	"fmt"
	"log"
	"os"
	"time"
)

func main() {
	var metainfo *bufio.Reader

	switch len(os.Args) {
	case 1:
		metainfo = bufio.NewReader(os.Stdin)
	case 2:
		file, err := os.Open(os.Args[1])
		if err != nil {
			log.Fatalln(err)
		}
		metainfo = bufio.NewReader(file)
	default:
		log.Fatalln("torrent-parse [metainfo-file]")
	}

	err, d := ParseDict(metainfo)
	if err != nil {
		log.Fatalln(err)
	}
	pretty_print(d)
}

func pretty_print(metainfo map[string]interface{}) {
	for k, v := range metainfo {
		switch k {
		case "announce":
			switch s := v.(type) {
			case string:
				fmt.Printf("\ntracker URL:\t\t%s\n", s)
			default:
				fmt.Println("\ntracker URL:\t\t[unexpected value type]")
			}
		case "info":
			d, ok := v.(map[string]interface{})
			if !ok {
				log.Fatalln("'info' value in metainfo dictionary has unexpected type")
			}

			for ki, vi := range d {
				if ki == "length" {
					switch flen := vi.(type) {
					case int64:
						fmt.Printf("\nfile length:\t\t%d\n", flen)
					default:
						fmt.Println("\nfile length:\t\t[unexpected value type]")
					}
				} else if ki == "name" {
					switch fname := vi.(type) {
					case string:
						fmt.Printf("\nsole filename:\t\t%s\n", fname)
					default:
						fmt.Println("\nsole filename:\t\t[unexpected value type]\n")
					}
				} else if ki == "files" {
					files, ok := vi.([]interface{})
					if !ok {
						log.Fatalln("'files' value in metainfo dictionary has unexpected type")
					}
					for _, file := range files {
						f, ok := file.(map[string]interface{})
						if !ok {
							log.Fatalln("item in 'files' list has unexpected type")
						}
						fpath, ok := f["path"].([]interface{})
						if !ok {
							log.Fatalln("file in 'files' list has a path of unexpected type")
						}
						// hack to avoid converting and using strings.Join
						for i, dir := range fpath {
							if i == 0 {
								fmt.Print("\n\t")
							} else {
								fmt.Print("/")
							}
							fmt.Print(dir)
						}
						fmt.Println()
						fmt.Printf("\tfile size:\t\t%d\n", f["length"])
					}
				}
			}
		case "created by":
			fmt.Printf("\ncreated with:\t\t%s\n", v)
		case "creation date":
			date, ok := v.(int64)
			if !ok {
				log.Fatalln("torrent creation date has unexpected type")
			}
			fmt.Printf("\ncreation date:\t\t%s\n", time.Unix(date, 0).String())
		case "comment":
			fmt.Printf("\ncomment:\t\t%s\n", v)
		case "encoding":
			fmt.Printf("\nencoding:\t\t%s\n", v)
		case "announce-list":
			fmt.Printf("\nannounce list:\t\t%s\n", v)
		case "url-list":
			fmt.Printf("\nURL list:\t\t%s\n", v)
		case "errors":
			fmt.Printf("\nerrors:\t\t%s\n", v)
		case "err_callback":
			fmt.Printf("\nerror callback:\t\t%s\n", v)
		case "log_callback":
			fmt.Printf("\nlog callback:\t\t%s\n", v)
		case "httpseeds":
			fmt.Printf("\nHTTP seeds:\t\t%s\n", v)
		default:
			fmt.Fprintln(os.Stderr, "\nencountered additional top-level dictionary key:", k)
		}
	}
	fmt.Println()
}
<|endoftext|>


<commit_before>package main

import (
	"log"
)

func main() {
	//	print("start")
	//
	//		http.Handle("/", http.FileServer(http.Dir("/Users/zhengsai/Downloads/")))
	//	http.Handle("/curl/", http.StripPrefix("/curl/", http.FileServer(http.Dir("/Users/zhengsai/Downloads/curl"))))
	//	http.Handle("/make/", http.StripPrefix("/make/", http.FileServer(http.Dir("/Users/zhengsai/Downloads/make"))))
	//
	//	log.Fatalln(http.ListenAndServe(":9000", nil))

	//	var input string
	//	fmt.Scanln(&input)
	//	log.Println(input)

	//	s := "b"
	//	ss := &s
	//	log.Printf("%p", &s)
	//	log.Printf("%p", ss)
	//	log.Printf("%p", &ss)

	a := []int{1, 2, 3}

	log.Printf("%T", a)
	log.Printf("%p", &a)
	test(a)

	bb := [3]int{1, 2, 3}
	aa := AA{p: &bb, len: 3, cap: 3}
	log.Printf("%p", &aa)
	test1(&aa)
}

func test(a []int) {
	log.Printf("%p", a)
	log.Printf("%p", &a)
	a = nil
	log.Printf("%p", a)
	log.Printf("%p", &a)
}

func test1(aa *AA) {
	log.Printf("%p", &aa)
	aa = nil
	log.Printf("%p", &aa)
}

type AA struct {
	p   *[3]int
	len int
	cap int
}
<commit_msg>modify main<commit_after>package main

import (
	"log"
)

func main() {
	//	print("start")
	//
	//		http.Handle("/", http.FileServer(http.Dir("/Users/zhengsai/Downloads/")))
	//	http.Handle("/curl/", http.StripPrefix("/curl/", http.FileServer(http.Dir("/Users/zhengsai/Downloads/curl"))))
	//	http.Handle("/make/", http.StripPrefix("/make/", http.FileServer(http.Dir("/Users/zhengsai/Downloads/make"))))
	//
	//	log.Fatalln(http.ListenAndServe(":9000", nil))

	//	var input string
	//	fmt.Scanln(&input)
	//	log.Println(input)

	//	s := "b"
	//	ss := &s
	//	log.Printf("%p", &s)
	//	log.Printf("%p", ss)
	//	log.Printf("%p", &ss)

	//	a := []int{1, 2, 3}
	//
	//	log.Printf("%T", a)
	//	log.Printf("%p", &a)
	//	test(a)
	//
	//	bb := [3]int{1, 2, 3}
	//	aa := AA{p: &bb, len: 3, cap: 3}
	//	log.Printf("%p", &aa)
	//	test1(&aa)

	s := "aaaD"
	ss := &s
	log.Printf("%q", ss)
	test(ss)
}

func test(s *string) {
	log.Printf("%q", *s)
}

//func test(a []int) {
//	log.Printf("%p", a)
//	log.Printf("%p", &a)
//	a = nil
//	log.Printf("%p", a)
//	log.Printf("%p", &a)
//}

func test1(aa *AA) {
	log.Printf("%p", &aa)
	aa = nil
	log.Printf("%p", &aa)
}

type AA struct {
	p   *[3]int
	len int
	cap int
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"log"
	"net"
	"time"

	"github.com/dasfoo/i2c"
	"github.com/dasfoo/rover/bb"
	"github.com/dasfoo/rover/mc"
	"golang.org/x/net/context"

	"google.golang.org/grpc"

	pb "github.com/dasfoo/rover/proto"
)

// server is used to implement roverserver.RoverServiceServer.
type server struct{}

var (
	board  *bb.BB
	motors *mc.MC
)

// MoveRover implements
func (s *server) MoveRover(ctx context.Context,
	in *pb.RoverWheelRequest) (*pb.RoverWheelResponse, error) {
	_ = motors.Left(int8(in.Left)) //TODO error check
	_ = motors.Right(int8(in.Right))
	time.Sleep(1 * time.Second)

	_ = motors.Left(0)
	_ = motors.Right(0)
	return &pb.RoverWheelResponse{}, nil
}

func (s *server) GetBatteryPercentage(ctx context.Context,
	in *pb.BatteryPercentageRequest) (*pb.BatteryPercentageResponse, error) {
	var batteryPercentage byte
	var e error
	if batteryPercentage, e = board.GetBatteryPercentage(); e != nil {
		return nil, e
	}
	return &pb.BatteryPercentageResponse{
		Battery: int32(batteryPercentage),
	}, nil
}

func (s *server) GetAmbientLight(ctx context.Context,
	in *pb.AmbientLightRequest) (*pb.AmbientLightResponse, error) {
	var light uint16
	var e error
	if light, e = board.GetAmbientLight(); e != nil {
		return nil, e
	}
	return &pb.AmbientLightResponse{
		Light: int32(light),
	}, nil
}

func (s *server) GetTemperatureAndHumidity(ctx context.Context,
	in *pb.TemperatureAndHumidityRequest) (*pb.TemperatureAndHumidityResponse, error) {
	var t, h byte
	var e error
	if t, h, e = board.GetTemperatureAndHumidity(); e != nil {
		return nil, e
	}
	return &pb.TemperatureAndHumidityResponse{
		Temperature: int32(t), // TODO: check byte in proto
		Humidity:    int32(h),
	}, nil
}

func (s *server) ReadEncoders(ctx context.Context,
	in *pb.ReadEncodersRequest) (*pb.ReadEncodersResponse, error) {
	var leftFront, leftBack, rightFront, rightBack int32
	var e error
	if leftFront, e = motors.ReadEncoder(mc.EncoderLeftFront); e != nil {
		return nil, e
	}
	if leftBack, e = motors.ReadEncoder(mc.EncoderLeftBack); e != nil {
		return nil, e
	}
	if rightFront, e = motors.ReadEncoder(mc.EncoderRightFront); e != nil {
		return nil, e
	}
	if rightBack, e = motors.ReadEncoder(mc.EncoderRightBack); e != nil {
		return nil, e
	}
	return &pb.ReadEncodersResponse{
		LeftFront:  leftFront,
		LeftBack:   leftBack,
		RightFront: rightFront,
		RightBack:  rightBack,
	}, nil
}

func main() {

	log.SetFlags(log.LstdFlags | log.Lshortfile | log.Lmicroseconds)
	var laddr = flag.String("laddr", "", "laddr")
	var test = flag.Bool("test", false, "Flag for startup script")
	flag.Parse()
	log.Println("Properties from command line:", *laddr)
	log.Println("Flag for startup script", *test)
	if bus, err := i2c.NewBus(1); err != nil {
		log.Fatal(err)
	} else {
		// Silence i2c bus log
		//bus.Log = func(string, ...interface{}) {}

		board = bb.NewBB(bus, bb.Address)
		motors = mc.NewMC(bus, mc.Address)
	}
	lis, err := net.Listen("tcp", *laddr)
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}
	log.Println("Server started")
	s := grpc.NewServer()
	pb.RegisterRoverServiceServer(s, &server{})
	if err := s.Serve(lis); err != nil {
		log.Fatal(err)
	}
}
<commit_msg>Add unavailable error for all devices<commit_after>package main

import (
	"flag"
	"log"
	"net"
	"time"

	"github.com/dasfoo/i2c"
	"github.com/dasfoo/rover/bb"
	"github.com/dasfoo/rover/mc"
	"golang.org/x/net/context"

	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"

	pb "github.com/dasfoo/rover/proto"
)

// server is used to implement roverserver.RoverServiceServer.
type server struct{}

var (
	board  *bb.BB
	motors *mc.MC
)

func getError(e error) error {
	return grpc.Errorf(codes.Unavailable, e.Error())
}

// MoveRover implements
func (s *server) MoveRover(ctx context.Context,
	in *pb.RoverWheelRequest) (*pb.RoverWheelResponse, error) {
	_ = motors.Left(int8(in.Left)) //TODO error check
	_ = motors.Right(int8(in.Right))
	time.Sleep(1 * time.Second)

	_ = motors.Left(0)
	_ = motors.Right(0)
	return &pb.RoverWheelResponse{}, nil
}

func (s *server) GetBatteryPercentage(ctx context.Context,
	in *pb.BatteryPercentageRequest) (*pb.BatteryPercentageResponse, error) {
	var batteryPercentage byte
	var e error
	if batteryPercentage, e = board.GetBatteryPercentage(); e != nil {
		return nil, getError(e)
	}
	return &pb.BatteryPercentageResponse{
		Battery: int32(batteryPercentage),
	}, nil
}

func (s *server) GetAmbientLight(ctx context.Context,
	in *pb.AmbientLightRequest) (*pb.AmbientLightResponse, error) {
	var light uint16
	var e error
	if light, e = board.GetAmbientLight(); e != nil {
		return nil, getError(e)
	}
	return &pb.AmbientLightResponse{
		Light: int32(light),
	}, nil
}

func (s *server) GetTemperatureAndHumidity(ctx context.Context,
	in *pb.TemperatureAndHumidityRequest) (*pb.TemperatureAndHumidityResponse, error) {
	var t, h byte
	var e error
	if t, h, e = board.GetTemperatureAndHumidity(); e != nil {
		return nil, getError(e)
	}
	return &pb.TemperatureAndHumidityResponse{
		Temperature: int32(t),
		Humidity:    int32(h),
	}, nil
}

func (s *server) ReadEncoders(ctx context.Context,
	in *pb.ReadEncodersRequest) (*pb.ReadEncodersResponse, error) {
	var leftFront, leftBack, rightFront, rightBack int32
	var e error
	if leftFront, e = motors.ReadEncoder(mc.EncoderLeftFront); e != nil {
		return nil, getError(e)
	}
	if leftBack, e = motors.ReadEncoder(mc.EncoderLeftBack); e != nil {
		return nil, getError(e)
	}
	if rightFront, e = motors.ReadEncoder(mc.EncoderRightFront); e != nil {
		return nil, getError(e)
	}
	if rightBack, e = motors.ReadEncoder(mc.EncoderRightBack); e != nil {
		return nil, getError(e)
	}
	return &pb.ReadEncodersResponse{
		LeftFront:  leftFront,
		LeftBack:   leftBack,
		RightFront: rightFront,
		RightBack:  rightBack,
	}, nil
}

func main() {

	log.SetFlags(log.LstdFlags | log.Lshortfile | log.Lmicroseconds)
	var laddr = flag.String("laddr", "", "laddr")
	var test = flag.Bool("test", false, "Flag for startup script")
	flag.Parse()
	log.Println("Properties from command line:", *laddr)
	log.Println("Flag for startup script", *test)
	if bus, err := i2c.NewBus(1); err != nil {
		log.Fatal(err)
	} else {
		// Silence i2c bus log
		//bus.Log = func(string, ...interface{}) {}

		board = bb.NewBB(bus, bb.Address)
		motors = mc.NewMC(bus, mc.Address)
	}
	lis, err := net.Listen("tcp", *laddr)
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}
	log.Println("Server started")
	s := grpc.NewServer()
	pb.RegisterRoverServiceServer(s, &server{})
	if err := s.Serve(lis); err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"mayday/core"
	"os"
)

type subCommand interface {
	Name() string
	DefineFlags(*flag.FlagSet)
	Run()
}

type subCommandParser struct {
	cmd subCommand
	fs  *flag.FlagSet
}

func Parse(commands ...subCommand) {
	scp := make(map[string]*subCommandParser, len(commands))
	for _, cmd := range commands {
		name := cmd.Name()
		scp[name] = &subCommandParser{cmd, flag.NewFlagSet(name, flag.ExitOnError)}
		cmd.DefineFlags(scp[name].fs)
	}

	oldUsage := flag.Usage
	flag.Usage = func() {
		oldUsage()
		fmt.Println(scp)
		for name, sc := range scp {
			fmt.Fprintf(os.Stderr, "\n# %s %s\n", os.Args[0], name)
			sc.fs.PrintDefaults()
			fmt.Fprintf(os.Stderr, "\n")
		}
	}

	flag.Parse()

	if flag.NArg() < 1 {
		flag.Usage()
		os.Exit(1)
	}

	cmdname := flag.Arg(0)
	if sc, ok := scp[cmdname]; ok {
		sc.fs.Parse(flag.Args()[1:])
		sc.cmd.Run()
	} else {
		fmt.Fprintf(os.Stderr, "error: %s is not a valid command", cmdname)
		flag.Usage()
		os.Exit(1)
	}
}

type push struct {
	pgpkeyid *string
	server   *string
	uuid     *string
}

func (cmd *push) Name() string {
	return "push"
}

func (cmd *push) DefineFlags(fs *flag.FlagSet) {
	cmd.uuid = fs.String("uuid", "", "PGP KeyID to sign the new configuration")
	cmd.pgpkeyid = fs.String("pgp-keyid", "", "PGP KeyID to sign the new configuration")
	cmd.server = fs.String("server", core.DefaultAPIBaseURL, "Mayday server address")
}

func (cmd *push) Run() {
	// real stuff
}

type pull struct {
	token  *string
	uuid   *string
	server *string
}

func (cmd *pull) Name() string {
	return "pull"
}

func (cmd *pull) DefineFlags(fs *flag.FlagSet) {
	cmd.uuid = fs.String("uuid", "", "PGP KeyID to sign the new configuration")
	cmd.token = fs.String("token", "", "PGP KeyID to sign the new configuration")
	cmd.server = fs.String("server", core.DefaultAPIBaseURL, "Mayday server address")
}

func (cmd *pull) Run() {
	// real stuff
}

type run struct {
	pgp    *bool
	uuid   *string
	server *string
	auth   *string
	upload *bool
}

func (cmd *run) Name() string {
	return "run"
}

func (cmd *run) DefineFlags(fs *flag.FlagSet) {
	cmd.pgp = fs.Bool("no-pgp", false, "Disable pgp signature validation")
	cmd.upload = fs.Bool("no-upload", false, "Don't upload generated reports")
	cmd.uuid = fs.String("uuid", "", "Mayday server address")
	cmd.server = fs.String("server", core.DefaultAPIBaseURL, "Mayday server address")
	cmd.auth = fs.String("auth", "", "PGP KeyID to sign the new configuration")
}

func (cmd *run) Run() {
	if *cmd.uuid == "" {
		fmt.Println("Please specify a case UUID --uuid UUID\n")
		os.Exit(1)
	}

	if *cmd.auth == "" {
		fmt.Println("Please specify the case auth token --auth TOKEN\n")
		os.Exit(1)
	}
	mayday, err := core.NewClient(*cmd.server, *cmd.uuid, *cmd.auth)
	if err != nil {
		fmt.Println(err)
	}

	err = mayday.Run(!*cmd.pgp, *cmd.upload)
	if err != nil {
		fmt.Println(err)
	}

	// fmt.Println("Viva la vida")
	// real stuff

}

func main() {
	Parse(new(run), new(push), new(pull))
}

// func main() {

// 	subcommands := make(map[string]*flag.FlagSet, 3)

// 	flag.Bool("run", false, "test")
// 	flag.Bool("push", false, "test")
// 	flag.Bool("pull", false, "test")

// 	flag.Parse()

// 	if flag.NArg() < 1 {
// 		flag.Usage()
// 		os.Exit(1)
// 	}

// 	cmdName := flag.Arg(0)

// 	config, err := core.NewConfig("./config.yaml", "./freyes.config.yaml.sig")

// 	if err != nil {
// 		fmt.Printf("Error %s\n", err)
// 		return
// 	}

// 	mayday, err := core.NewClient(config)
// 	mayday.Run()

// }
<commit_msg>[core/commands] refactored the command parser to a more elegant interface<commit_after>package main

import (
	"mayday/core/commands"
)

func main() {
	commands.Parse(
		new(commands.RunCommand),
		new(commands.PushCommand),
		new(commands.PullCommand),
	)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"
	"strings"
	"time"

	"github.com/rackspace/gophercloud"
	osV2Servers "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
	"github.com/rackspace/gophercloud/pagination"
	rsV2Servers "github.com/rackspace/gophercloud/rackspace/compute/v2/servers"
	"github.com/rackspace/gophercloud/rackspace/identity/v2/tokens"
	"github.com/smashwilson/gophercloud/rackspace"
	rsV1Servers "github.com/smashwilson/gophercloud/rackspace/compute/v1/servers"
)

const (
	metadataKey     = "rax:reboot_window"
	metadataTimeFmt = "2006-01-02T15:04:05Z"
	appVer = "0.9"
)

func main() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr,"cs-reboot-info v%s\n",appVer)
		fmt.Fprintf(os.Stderr, "Usage: %s [--csv] username apikey\n\n", os.Args[0])

		flag.CommandLine.PrintDefaults()
	}

	outputToCSV := flag.Bool("csv", false,
		"Output a CSV file to 'cs-reboot-info-output.csv' in the current directory.")
	flag.Parse()

	if flag.NArg() != 2 {
		fmt.Println("You must supply a username and API key as the last two arguments.")
		flag.Usage()
		os.Exit(1)
	}

	username, apiKey := flag.Arg(0), flag.Arg(1)

	opts := gophercloud.AuthOptions{
		Username: username,
		APIKey:   apiKey,
	}

	provider, err := rackspace.AuthenticatedClient(opts)
	if err != nil {
		fmt.Printf("Unable to authenticate: %v\n", err)
		os.Exit(1)
	}

	provider.UserAgent.Prepend("cs-reboot-info/1.0")

	regions, fg := Regions(provider, opts)

	fmt.Printf("Regions with a Cloud Servers endpoint: %s\n", strings.Join(regions, ", "))
	if fg {
		fmt.Println("Found both First and Next Generation endpoints.")
	}

	var entries []entry

	// Iterate through regions with an NG compute endpoint. Collect data about each server.
	for _, region := range regions {
		compute, err := rackspace.NewComputeV2(provider, gophercloud.EndpointOpts{
			Region: region,
		})
		if err != nil {
			fmt.Printf("Unable to locate a Next Gen Cloud Servers endpoint in region %s: %v\n", region, err)
			continue
		}

		err = rsV2Servers.List(compute, nil).EachPage(func(page pagination.Page) (bool, error) {
			s, err := osV2Servers.ExtractServers(page)
			if err != nil {
				return false, err
			}

			for _, server := range s {
				entry, err := ConstructEntry(server, "Next Gen", region)
				if err != nil {
					if strings.Contains(err.Error(), "not present") {
						continue
					}
					fmt.Printf("%s\n", err)
					continue
				} else {
					entries = append(entries, *entry)
				}
			}

			return true, nil
		})
	}

	// Iterate through regions with an FG compute endpoint. Collect data about each server.
	compute, err := rackspace.NewComputeV1(provider, gophercloud.EndpointOpts{
		Availability: gophercloud.AvailabilityPublic,
	})
	if err != nil {
		fmt.Printf("Unable to locate a First Gen Cloud Servers endpoint. Skipping...\n")
	} else {
		err = rsV1Servers.List(compute, rsV1Servers.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
			s, err := osV2Servers.ExtractServers(page)
			if err != nil {
				return false, err
			}

			for _, server := range s {
				entry, err := ConstructEntry(server, "First Gen", "DFW")
				if err != nil {
					if strings.Contains(err.Error(), "not present") {
						continue
					}
					fmt.Printf("%s\n", err)
					continue
				} else {
					entries = append(entries, *entry)
				}
			}

			return true, nil
		})
		if err != nil {
			fmt.Printf("Error listing servers: %+v\n", err)
		}
	}

	if len(entries) > 0 {
		if *outputToCSV {
			outputCSV(entries)
		} else {
			fmt.Printf("The following %d Cloud Servers have an automated reboot scheduled:", len(entries))
			outputTabular(entries)
		}
	}
}

// Regions acquires the service catalog and returns a slice of every region that contains a next-gen
// server endpoint, and a boolean indicating whether or not this customer has access to FG servers.
func Regions(provider *gophercloud.ProviderClient, opts gophercloud.AuthOptions) ([]string, bool) {
	service := rackspace.NewIdentityV2(provider)

	result := tokens.Create(service, tokens.WrapOptions(opts))
	catalog, err := result.ExtractServiceCatalog()
	if err != nil {
		fmt.Printf("Unable to retrieve the service catalog: %v\n", err)
		os.Exit(1)
	}

	var regions []string
	var fg bool
	for _, entry := range catalog.Entries {
		if entry.Type == "compute" {
			for _, endpoint := range entry.Endpoints {
				if endpoint.Region == "" {
					fg = true
				} else {
					regions = append(regions, endpoint.Region)
				}
			}
		}
	}
	return regions, fg
}

// ConstructEntry extracts the metadata key and builds an entry for a server.
func ConstructEntry(server osV2Servers.Server, genType, region string) (*entry, error) {
	window, ok := server.Metadata[metadataKey]
	if !ok {
		return nil, fmt.Errorf("Metadatum %s was not present in the result for server %s", metadataKey, server.ID)
	}

	windowString, ok := window.(string)
	if !ok {
		return nil, fmt.Errorf("Metadatum %s for server %s was not a string: %#v", metadataKey, server.ID, window)
	}

	// Expected format: 2014-01-28T00:00:00Z;2014-01-28T03:00:00Z

	parts := strings.Split(windowString, ";")
	if len(parts) != 2 {
		return nil, fmt.Errorf("Unexpected metadatum format for server %s: %s", server.ID, windowString)
	}

	start, err := time.Parse(metadataTimeFmt, parts[0])
	if err != nil {
		return nil, fmt.Errorf("Unable to parse window start time for server %s: %s", server.ID, parts[0])
	}

	end, err := time.Parse(metadataTimeFmt, parts[1])
	if err != nil {
		return nil, fmt.Errorf("Unable to parse window end time for server %s: %s", server.ID, parts[1])
	}

	e := &entry{
		Server:      server,
		Region:      region,
		GenType:     genType,
		WindowStart: start,
		WindowEnd:   end,
	}
	return e, nil
}
<commit_msg>Use the appVer constant in the user agent.<commit_after>package main

import (
	"flag"
	"fmt"
	"os"
	"strings"
	"time"

	"github.com/rackspace/gophercloud"
	osV2Servers "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
	"github.com/rackspace/gophercloud/pagination"
	rsV2Servers "github.com/rackspace/gophercloud/rackspace/compute/v2/servers"
	"github.com/rackspace/gophercloud/rackspace/identity/v2/tokens"
	"github.com/smashwilson/gophercloud/rackspace"
	rsV1Servers "github.com/smashwilson/gophercloud/rackspace/compute/v1/servers"
)

const (
	metadataKey     = "rax:reboot_window"
	metadataTimeFmt = "2006-01-02T15:04:05Z"
	appVer          = "0.9"
)

func main() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "cs-reboot-info v%s\n", appVer)
		fmt.Fprintf(os.Stderr, "Usage: %s [--csv] username apikey\n\n", os.Args[0])

		flag.CommandLine.PrintDefaults()
	}

	outputToCSV := flag.Bool("csv", false,
		"Output a CSV file to 'cs-reboot-info-output.csv' in the current directory.")
	flag.Parse()

	if flag.NArg() != 2 {
		fmt.Println("You must supply a username and API key as the last two arguments.")
		flag.Usage()
		os.Exit(1)
	}

	username, apiKey := flag.Arg(0), flag.Arg(1)

	opts := gophercloud.AuthOptions{
		Username: username,
		APIKey:   apiKey,
	}

	provider, err := rackspace.AuthenticatedClient(opts)
	if err != nil {
		fmt.Printf("Unable to authenticate: %v\n", err)
		os.Exit(1)
	}

	provider.UserAgent.Prepend(fmt.Sprintf("cs-reboot-info/%s", appVer))

	regions, fg := Regions(provider, opts)

	fmt.Printf("Regions with a Cloud Servers endpoint: %s\n", strings.Join(regions, ", "))
	if fg {
		fmt.Println("Found both First and Next Generation endpoints.")
	}

	var entries []entry

	// Iterate through regions with an NG compute endpoint. Collect data about each server.
	for _, region := range regions {
		compute, err := rackspace.NewComputeV2(provider, gophercloud.EndpointOpts{
			Region: region,
		})
		if err != nil {
			fmt.Printf("Unable to locate a Next Gen Cloud Servers endpoint in region %s: %v\n", region, err)
			continue
		}

		err = rsV2Servers.List(compute, nil).EachPage(func(page pagination.Page) (bool, error) {
			s, err := osV2Servers.ExtractServers(page)
			if err != nil {
				return false, err
			}

			for _, server := range s {
				entry, err := ConstructEntry(server, "Next Gen", region)
				if err != nil {
					if strings.Contains(err.Error(), "not present") {
						continue
					}
					fmt.Printf("%s\n", err)
					continue
				} else {
					entries = append(entries, *entry)
				}
			}

			return true, nil
		})
	}

	// Iterate through regions with an FG compute endpoint. Collect data about each server.
	compute, err := rackspace.NewComputeV1(provider, gophercloud.EndpointOpts{
		Availability: gophercloud.AvailabilityPublic,
	})
	if err != nil {
		fmt.Printf("Unable to locate a First Gen Cloud Servers endpoint. Skipping...\n")
	} else {
		err = rsV1Servers.List(compute, rsV1Servers.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
			s, err := osV2Servers.ExtractServers(page)
			if err != nil {
				return false, err
			}

			for _, server := range s {
				entry, err := ConstructEntry(server, "First Gen", "DFW")
				if err != nil {
					if strings.Contains(err.Error(), "not present") {
						continue
					}
					fmt.Printf("%s\n", err)
					continue
				} else {
					entries = append(entries, *entry)
				}
			}

			return true, nil
		})
		if err != nil {
			fmt.Printf("Error listing servers: %+v\n", err)
		}
	}

	if len(entries) > 0 {
		if *outputToCSV {
			outputCSV(entries)
		} else {
			fmt.Printf("The following %d Cloud Servers have an automated reboot scheduled:", len(entries))
			outputTabular(entries)
		}
	}
}

// Regions acquires the service catalog and returns a slice of every region that contains a next-gen
// server endpoint, and a boolean indicating whether or not this customer has access to FG servers.
func Regions(provider *gophercloud.ProviderClient, opts gophercloud.AuthOptions) ([]string, bool) {
	service := rackspace.NewIdentityV2(provider)

	result := tokens.Create(service, tokens.WrapOptions(opts))
	catalog, err := result.ExtractServiceCatalog()
	if err != nil {
		fmt.Printf("Unable to retrieve the service catalog: %v\n", err)
		os.Exit(1)
	}

	var regions []string
	var fg bool
	for _, entry := range catalog.Entries {
		if entry.Type == "compute" {
			for _, endpoint := range entry.Endpoints {
				if endpoint.Region == "" {
					fg = true
				} else {
					regions = append(regions, endpoint.Region)
				}
			}
		}
	}
	return regions, fg
}

// ConstructEntry extracts the metadata key and builds an entry for a server.
func ConstructEntry(server osV2Servers.Server, genType, region string) (*entry, error) {
	window, ok := server.Metadata[metadataKey]
	if !ok {
		return nil, fmt.Errorf("Metadatum %s was not present in the result for server %s", metadataKey, server.ID)
	}

	windowString, ok := window.(string)
	if !ok {
		return nil, fmt.Errorf("Metadatum %s for server %s was not a string: %#v", metadataKey, server.ID, window)
	}

	// Expected format: 2014-01-28T00:00:00Z;2014-01-28T03:00:00Z

	parts := strings.Split(windowString, ";")
	if len(parts) != 2 {
		return nil, fmt.Errorf("Unexpected metadatum format for server %s: %s", server.ID, windowString)
	}

	start, err := time.Parse(metadataTimeFmt, parts[0])
	if err != nil {
		return nil, fmt.Errorf("Unable to parse window start time for server %s: %s", server.ID, parts[0])
	}

	end, err := time.Parse(metadataTimeFmt, parts[1])
	if err != nil {
		return nil, fmt.Errorf("Unable to parse window end time for server %s: %s", server.ID, parts[1])
	}

	e := &entry{
		Server:      server,
		Region:      region,
		GenType:     genType,
		WindowStart: start,
		WindowEnd:   end,
	}
	return e, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/facebookgo/grace/gracehttp"
	"github.com/gin-gonic/gin"
	"net/http"
	"runtime"

	"github.com/techjanitor/pram-libs/auth"
	"github.com/techjanitor/pram-libs/config"
	"github.com/techjanitor/pram-libs/cors"
	"github.com/techjanitor/pram-libs/db"
	"github.com/techjanitor/pram-libs/validate"

	local "github.com/techjanitor/pram-post/config"
	c "github.com/techjanitor/pram-post/controllers"
	m "github.com/techjanitor/pram-post/middleware"
	u "github.com/techjanitor/pram-post/utils"
)

func init() {

	dbase := db.Database{
		// Database connection settings
		User:           local.Settings.Database.User,
		Password:       local.Settings.Database.Password,
		Proto:          local.Settings.Database.Proto,
		Host:           local.Settings.Database.Host,
		Database:       local.Settings.Database.Database,
		MaxIdle:        local.Settings.Database.MaxIdle,
		MaxConnections: local.Settings.Database.MaxConnections,
	}

	// Set up DB connection
	dbase.NewDb()

	// Get limits and stuff from database
	db.GetDatabaseSettings()

	// Set up Redis connection
	u.NewRedisCache()

	// Print out config
	config.Print()

	// Print out config
	local.Print()

	// set auth middleware secret
	auth.Secret = local.Settings.Session.Secret

	// Print capabilities
	u.Services.Print()

}

func main() {
	r := gin.Default()

	r.Use(cors.CORS())

	r.NoRoute(c.ErrorController)

	// all users
	public := r.Group("/")
	public.Use(auth.Auth(auth.All))

	public.POST("/thread/new", m.GetAntiSpamCookie(), c.ThreadController)
	public.POST("/thread/reply", m.GetAntiSpamCookie(), c.ReplyController)
	public.POST("/tag/new", m.GetAntiSpamCookie(), c.NewTagController)
	public.POST("/tag/add", m.GetAntiSpamCookie(), c.AddTagController)
	public.POST("/register", c.RegisterController)
	public.POST("/login", c.LoginController)

	// requires user perms
	users := r.Group("/user")
	users.Use(auth.Auth(auth.Registered))

	users.POST("/favorite", c.FavoritesController)
	users.POST("/password", c.PasswordController)
	users.POST("/email", c.EmailController)

	// requires mod perms
	mod := r.Group("/mod")
	mod.Use(validate.ValidateParams())
	mod.Use(auth.Auth(auth.Moderators))

	mod.DELETE("/tag/:id", c.DeleteTagController)
	mod.DELETE("/imagetag/:image/:tag", c.DeleteImageTagController)
	mod.DELETE("/thread/:id", c.DeleteThreadController)
	mod.DELETE("/post/:thread/:id", c.DeletePostController)
	mod.POST("/sticky/:thread", c.StickyThreadController)
	mod.POST("/close/:thread", c.CloseThreadController)

	// requires admin perms
	admin := r.Group("/admin")
	admin.Use(validate.ValidateParams())
	admin.Use(auth.Auth(auth.Admins))

	admin.DELETE("/thread/:id", c.PurgeThreadController)
	admin.DELETE("/post/:thread/:id", c.PurgePostController)
	//admin.POST("/ban/:ip", c.BanIpController)
	//admin.DELETE("/flushcache", c.DeleteCacheController)

	s := &http.Server{
		Addr:    fmt.Sprintf("%s:%d", local.Settings.Post.Address, local.Settings.Post.Port),
		Handler: r,
	}

	gracehttp.Serve(s)

}
<commit_msg>add local config<commit_after>package main

import (
	"fmt"
	"github.com/facebookgo/grace/gracehttp"
	"github.com/gin-gonic/gin"
	"net/http"
	"runtime"

	"github.com/techjanitor/pram-libs/auth"
	"github.com/techjanitor/pram-libs/config"
	"github.com/techjanitor/pram-libs/cors"
	"github.com/techjanitor/pram-libs/db"
	"github.com/techjanitor/pram-libs/validate"

	local "github.com/techjanitor/pram-post/config"
	c "github.com/techjanitor/pram-post/controllers"
	m "github.com/techjanitor/pram-post/middleware"
	u "github.com/techjanitor/pram-post/utils"
)

func init() {

	dbase := db.Database{
		// Database connection settings
		User:           local.Settings.Database.User,
		Password:       local.Settings.Database.Password,
		Proto:          local.Settings.Database.Proto,
		Host:           local.Settings.Database.Host,
		Database:       local.Settings.Database.Database,
		MaxIdle:        local.Settings.Database.MaxIdle,
		MaxConnections: local.Settings.Database.MaxConnections,
	}

	// Set up DB connection
	dbase.NewDb()

	// Get limits and stuff from database
	db.GetDatabaseSettings()

	// Set up Redis connection
	u.NewRedisCache()

	// Print out config
	config.Print()

	// Print out config
	local.Print()

	// set auth middleware secret
	auth.Secret = local.Settings.Session.Secret

	// set cors domains
	cors.Domains = local.Settings.CORS.Sites

	// Print capabilities
	u.Services.Print()

}

func main() {
	r := gin.Default()

	r.Use(cors.CORS())

	r.NoRoute(c.ErrorController)

	// all users
	public := r.Group("/")
	public.Use(auth.Auth(auth.All))

	public.POST("/thread/new", m.GetAntiSpamCookie(), c.ThreadController)
	public.POST("/thread/reply", m.GetAntiSpamCookie(), c.ReplyController)
	public.POST("/tag/new", m.GetAntiSpamCookie(), c.NewTagController)
	public.POST("/tag/add", m.GetAntiSpamCookie(), c.AddTagController)
	public.POST("/register", c.RegisterController)
	public.POST("/login", c.LoginController)

	// requires user perms
	users := r.Group("/user")
	users.Use(auth.Auth(auth.Registered))

	users.POST("/favorite", c.FavoritesController)
	users.POST("/password", c.PasswordController)
	users.POST("/email", c.EmailController)

	// requires mod perms
	mod := r.Group("/mod")
	mod.Use(validate.ValidateParams())
	mod.Use(auth.Auth(auth.Moderators))

	mod.DELETE("/tag/:id", c.DeleteTagController)
	mod.DELETE("/imagetag/:image/:tag", c.DeleteImageTagController)
	mod.DELETE("/thread/:id", c.DeleteThreadController)
	mod.DELETE("/post/:thread/:id", c.DeletePostController)
	mod.POST("/sticky/:thread", c.StickyThreadController)
	mod.POST("/close/:thread", c.CloseThreadController)

	// requires admin perms
	admin := r.Group("/admin")
	admin.Use(validate.ValidateParams())
	admin.Use(auth.Auth(auth.Admins))

	admin.DELETE("/thread/:id", c.PurgeThreadController)
	admin.DELETE("/post/:thread/:id", c.PurgePostController)
	//admin.POST("/ban/:ip", c.BanIpController)
	//admin.DELETE("/flushcache", c.DeleteCacheController)

	s := &http.Server{
		Addr:    fmt.Sprintf("%s:%d", local.Settings.Post.Address, local.Settings.Post.Port),
		Handler: r,
	}

	gracehttp.Serve(s)

}
<|endoftext|>