<commit_before>// Copyright 2015-2016 Zack Scholl. All rights reserved.
// Use of this source code is governed by a AGPL
// license that can be found in the LICENSE file.

// fingerprint.go contains structures and functions for handling fingerprints.

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"math"
	"strconv"

	"net/http"
	"path"
	"strings"
	"time"

	"github.com/boltdb/bolt"
	"github.com/gin-gonic/gin"
)

// Fingerprint is the prototypical information from the fingerprinting device
// IF you change Fingerprint, follow these steps to re-generate fingerprint_ffjson.go
// find ./ -name "*.go" -type f | xargs sed -i  's/package main/package main/g'
// Uncomment json.Marshal/Unmarshal functions
// $GOPATH/bin/ffjson fingerprint.go
// find ./ -name "*.go" -type f | xargs sed -i  's/package main/package main/g'
// Comment json.Marshal/Unmarshal functions
type Fingerprint struct {
	Group           string   `json:"group"`
	Username        string   `json:"username"`
	Location        string   `json:"location"`
	Timestamp       int64    `json:"timestamp"`
	WifiFingerprint []Router `json:"wifi-fingerprint"`
}

// Router is the router information for each invdividual mac address
type Router struct {
	Mac  string `json:"mac"`
	Rssi int    `json:"rssi"`
}

var jsonExample = `{
	"group": "whatevergroup",
	"username": "iamauser",
	"location": null,
	"wififingerprint": [{
		"mac": "AA:AA:AA:AA:AA:AA",
		"rssi": -45
	}, {
		"mac": "BB:BB:BB:BB:BB:BB",
		"rssi": -55
	}]
}`

// compression 9 us -> 900 us
func dumpFingerprint(res Fingerprint) []byte {
	dumped, _ := res.MarshalJSON()
	//dumped, _ := json.Marshal(res)
	return compressByte(dumped)
}

// compression 30 us -> 600 us
func loadFingerprint(jsonByte []byte) Fingerprint {
	res := Fingerprint{}
	//json.Unmarshal(decompressByte(jsonByte), res)
	res.UnmarshalJSON(decompressByte(jsonByte))
	return res
}

func cleanFingerprint(res *Fingerprint) {
	res.Group = strings.ToLower(res.Group)
	res.Location = strings.ToLower(res.Location)
	res.Username = strings.ToLower(res.Username)
	deleteIndex := -1
	for r := range res.WifiFingerprint {
		if res.WifiFingerprint[r].Rssi >= 0 { // https://stackoverflow.com/questions/15797920/how-to-convert-wifi-signal-strength-from-quality-percent-to-rssi-dbm
			res.WifiFingerprint[r].Rssi = int(res.WifiFingerprint[r].Rssi/2) - 100
		}
		if res.WifiFingerprint[r].Mac == "00:00:00:00:00:00" {
			deleteIndex = r
		}
	}
	if deleteIndex > -1 {
		res.WifiFingerprint[deleteIndex] = res.WifiFingerprint[len(res.WifiFingerprint)-1]
		res.WifiFingerprint = res.WifiFingerprint[:len(res.WifiFingerprint)-1]
	}
}

func putFingerprintIntoDatabase(res Fingerprint, database string) error {
	db, err := bolt.Open(path.Join(RuntimeArgs.SourcePath, res.Group+".db"), 0600, nil)
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	err = db.Update(func(tx *bolt.Tx) error {
		bucket, err2 := tx.CreateBucketIfNotExists([]byte(database))
		if err2 != nil {
			return fmt.Errorf("create bucket: %s", err2)
		}

		if res.Timestamp == 0 {
			res.Timestamp = time.Now().UnixNano()
		}
		err2 = bucket.Put([]byte(strconv.FormatInt(res.Timestamp, 10)), dumpFingerprint(res))
		if err2 != nil {
			return fmt.Errorf("could add to bucket: %s", err2)
		}
		return err2
	})
	return err
}

func trackFingerprintPOST(c *gin.Context) {
	var jsonFingerprint Fingerprint
	if c.BindJSON(&jsonFingerprint) == nil {
		message, success, locationGuess, bayes, svm := trackFingerprint(jsonFingerprint)
		if success {
			c.JSON(http.StatusOK, gin.H{"message": message, "success": true, "location": locationGuess, "bayes": bayes, "svm": svm})
		} else {
			c.JSON(http.StatusOK, gin.H{"message": message, "success": false})
		}
	} else {
		Warning.Println("Could not bind JSON")
		c.JSON(http.StatusOK, gin.H{"message": "Could not bind JSON", "success": false})
	}
}

func learnFingerprintPOST(c *gin.Context) {
	var jsonFingerprint Fingerprint
	if c.BindJSON(&jsonFingerprint) == nil {
		message, success := learnFingerprint(jsonFingerprint)
		Debug.Println(message)
		if !success {
			Debug.Println(jsonFingerprint)
		}
		c.JSON(http.StatusOK, gin.H{"message": message, "success": success})
	} else {
		Warning.Println("Could not bind JSON")
		c.JSON(http.StatusOK, gin.H{"message": "Could not bind JSON", "success": false})
	}
}

func learnFingerprint(jsonFingerprint Fingerprint) (string, bool) {
	cleanFingerprint(&jsonFingerprint)
	if len(jsonFingerprint.Group) == 0 {
		return "Need to define your group name in request, see API", false
	}
	if len(jsonFingerprint.WifiFingerprint) == 0 {
		return "No fingerprints found to insert, see API", false
	}
	putFingerprintIntoDatabase(jsonFingerprint, "fingerprints")
	isLearning[strings.ToLower(jsonFingerprint.Group)] = true
	message := "Inserted fingerprint containing " + strconv.Itoa(len(jsonFingerprint.WifiFingerprint)) + " APs for " + jsonFingerprint.Username + " at " + jsonFingerprint.Location
	return message, true
}

func trackFingerprint(jsonFingerprint Fingerprint) (string, bool, string, map[string]float64, map[string]float64) {
	bayes := make(map[string]float64)
	svmData := make(map[string]float64)
	cleanFingerprint(&jsonFingerprint)
	if !groupExists(jsonFingerprint.Group) || len(jsonFingerprint.Group) == 0 {
		return "You should insert fingerprints before tracking", false, "", bayes, make(map[string]float64)
	}
	if len(jsonFingerprint.WifiFingerprint) == 0 {
		return "No fingerprints found to track, see API", false, "", bayes, make(map[string]float64)
	}
	if len(jsonFingerprint.Username) == 0 {
		return "No username defined, see API", false, "", bayes, make(map[string]float64)
	}
	if wasLearning, ok := isLearning[strings.ToLower(jsonFingerprint.Group)]; ok {
		if wasLearning {
			Debug.Println("Was learning, calculating priors")
			group := strings.ToLower(jsonFingerprint.Group)
			isLearning[group] = false
			optimizePriorsThreaded(group)
			if RuntimeArgs.Svm {
				dumpFingerprintsSVM(group)
				calculateSVM(group)
			}
			if _, ok := usersCache[group]; ok {
				if len(usersCache[group]) == 0 {
					usersCache[group] = append([]string{}, strings.ToLower(jsonFingerprint.Username))
				}
			}
		}
	}
	locationGuess1, bayes := calculatePosterior(jsonFingerprint, *NewFullParameters())
	percentGuess1 := float64(0)
	total := float64(0)
	for _, locBayes := range bayes {
		total += math.Exp(locBayes)
		if locBayes > percentGuess1 {
			percentGuess1 = locBayes
		}
	}
	percentGuess1 = math.Exp(bayes[locationGuess1]) / total * 100.0

	jsonFingerprint.Location = locationGuess1
	putFingerprintIntoDatabase(jsonFingerprint, "fingerprints-track")

	Debug.Println("Tracking fingerprint containing " + strconv.Itoa(len(jsonFingerprint.WifiFingerprint)) + " APs for " + jsonFingerprint.Username + " (" + jsonFingerprint.Group + ") at " + jsonFingerprint.Location + " (guess)")
	message := "Current location: " + locationGuess1 //+ " (" + strconv.Itoa(int(percentGuess1)) + "% confidence)"

	// Process SVM if needed
	if RuntimeArgs.Svm {
		locationGuess2, svmData2 := classify(jsonFingerprint)
		percentGuess2 := int(100 * math.Exp(svmData2[locationGuess2]))
		if percentGuess2 > 100 {
			percentGuess2 = percentGuess2 / 10
		}
		//message = "NB: " + locationGuess1 + " (" + strconv.Itoa(int(percentGuess1)) + "%)" + ", SVM: " + locationGuess2 + " (" + strconv.Itoa(int(percentGuess2)) + "%)"
		svmData = svmData2
	}

	// Send MQTT if needed
	if RuntimeArgs.Mqtt {
		type FingerprintResponse struct {
			LocationGuess string             `json:"location"`
			Timestamp     int64              `json:"timestamp"`
			Bayes         map[string]float64 `json:"bayes"`
			Svm           map[string]float64 `json:"svm"`
		}
		mqttMessage, _ := json.Marshal(FingerprintResponse{
			LocationGuess: locationGuess1,
			Timestamp:     time.Now().UnixNano(),
			Bayes:         bayes,
			Svm:           svmData,
		})
		go sendMQTTLocation(string(mqttMessage), jsonFingerprint.Group, jsonFingerprint.Username)
	}

	// Send out the final responses
	var userJSON UserPositionJSON
	userJSON.Location = locationGuess1
	userJSON.Bayes = bayes
	userJSON.Svm = svmData
	userJSON.Time = time.Now().String()
	userPositionCache[strings.ToLower(jsonFingerprint.Group)+strings.ToLower(jsonFingerprint.Username)] = userJSON

	return message, true, locationGuess1, bayes, svmData

}
<commit_msg>Fixed timestamp -> time<commit_after>// Copyright 2015-2016 Zack Scholl. All rights reserved.
// Use of this source code is governed by a AGPL
// license that can be found in the LICENSE file.

// fingerprint.go contains structures and functions for handling fingerprints.

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"math"
	"strconv"

	"net/http"
	"path"
	"strings"
	"time"

	"github.com/boltdb/bolt"
	"github.com/gin-gonic/gin"
)

// Fingerprint is the prototypical information from the fingerprinting device
// IF you change Fingerprint, follow these steps to re-generate fingerprint_ffjson.go
// find ./ -name "*.go" -type f | xargs sed -i  's/package main/package main/g'
// Uncomment json.Marshal/Unmarshal functions
// $GOPATH/bin/ffjson fingerprint.go
// find ./ -name "*.go" -type f | xargs sed -i  's/package main/package main/g'
// Comment json.Marshal/Unmarshal functions
type Fingerprint struct {
	Group           string   `json:"group"`
	Username        string   `json:"username"`
	Location        string   `json:"location"`
	Timestamp       int64    `json:"timestamp"`
	WifiFingerprint []Router `json:"wifi-fingerprint"`
}

// Router is the router information for each invdividual mac address
type Router struct {
	Mac  string `json:"mac"`
	Rssi int    `json:"rssi"`
}

var jsonExample = `{
	"group": "whatevergroup",
	"username": "iamauser",
	"location": null,
	"wififingerprint": [{
		"mac": "AA:AA:AA:AA:AA:AA",
		"rssi": -45
	}, {
		"mac": "BB:BB:BB:BB:BB:BB",
		"rssi": -55
	}]
}`

// compression 9 us -> 900 us
func dumpFingerprint(res Fingerprint) []byte {
	dumped, _ := res.MarshalJSON()
	//dumped, _ := json.Marshal(res)
	return compressByte(dumped)
}

// compression 30 us -> 600 us
func loadFingerprint(jsonByte []byte) Fingerprint {
	res := Fingerprint{}
	//json.Unmarshal(decompressByte(jsonByte), res)
	res.UnmarshalJSON(decompressByte(jsonByte))
	return res
}

func cleanFingerprint(res *Fingerprint) {
	res.Group = strings.ToLower(res.Group)
	res.Location = strings.ToLower(res.Location)
	res.Username = strings.ToLower(res.Username)
	deleteIndex := -1
	for r := range res.WifiFingerprint {
		if res.WifiFingerprint[r].Rssi >= 0 { // https://stackoverflow.com/questions/15797920/how-to-convert-wifi-signal-strength-from-quality-percent-to-rssi-dbm
			res.WifiFingerprint[r].Rssi = int(res.WifiFingerprint[r].Rssi/2) - 100
		}
		if res.WifiFingerprint[r].Mac == "00:00:00:00:00:00" {
			deleteIndex = r
		}
	}
	if deleteIndex > -1 {
		res.WifiFingerprint[deleteIndex] = res.WifiFingerprint[len(res.WifiFingerprint)-1]
		res.WifiFingerprint = res.WifiFingerprint[:len(res.WifiFingerprint)-1]
	}
}

func putFingerprintIntoDatabase(res Fingerprint, database string) error {
	db, err := bolt.Open(path.Join(RuntimeArgs.SourcePath, res.Group+".db"), 0600, nil)
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	err = db.Update(func(tx *bolt.Tx) error {
		bucket, err2 := tx.CreateBucketIfNotExists([]byte(database))
		if err2 != nil {
			return fmt.Errorf("create bucket: %s", err2)
		}

		if res.Timestamp == 0 {
			res.Timestamp = time.Now().UnixNano()
		}
		err2 = bucket.Put([]byte(strconv.FormatInt(res.Timestamp, 10)), dumpFingerprint(res))
		if err2 != nil {
			return fmt.Errorf("could add to bucket: %s", err2)
		}
		return err2
	})
	return err
}

func trackFingerprintPOST(c *gin.Context) {
	var jsonFingerprint Fingerprint
	if c.BindJSON(&jsonFingerprint) == nil {
		message, success, locationGuess, bayes, svm := trackFingerprint(jsonFingerprint)
		if success {
			c.JSON(http.StatusOK, gin.H{"message": message, "success": true, "location": locationGuess, "bayes": bayes, "svm": svm})
		} else {
			c.JSON(http.StatusOK, gin.H{"message": message, "success": false})
		}
	} else {
		Warning.Println("Could not bind JSON")
		c.JSON(http.StatusOK, gin.H{"message": "Could not bind JSON", "success": false})
	}
}

func learnFingerprintPOST(c *gin.Context) {
	var jsonFingerprint Fingerprint
	if c.BindJSON(&jsonFingerprint) == nil {
		message, success := learnFingerprint(jsonFingerprint)
		Debug.Println(message)
		if !success {
			Debug.Println(jsonFingerprint)
		}
		c.JSON(http.StatusOK, gin.H{"message": message, "success": success})
	} else {
		Warning.Println("Could not bind JSON")
		c.JSON(http.StatusOK, gin.H{"message": "Could not bind JSON", "success": false})
	}
}

func learnFingerprint(jsonFingerprint Fingerprint) (string, bool) {
	cleanFingerprint(&jsonFingerprint)
	if len(jsonFingerprint.Group) == 0 {
		return "Need to define your group name in request, see API", false
	}
	if len(jsonFingerprint.WifiFingerprint) == 0 {
		return "No fingerprints found to insert, see API", false
	}
	putFingerprintIntoDatabase(jsonFingerprint, "fingerprints")
	isLearning[strings.ToLower(jsonFingerprint.Group)] = true
	message := "Inserted fingerprint containing " + strconv.Itoa(len(jsonFingerprint.WifiFingerprint)) + " APs for " + jsonFingerprint.Username + " at " + jsonFingerprint.Location
	return message, true
}

func trackFingerprint(jsonFingerprint Fingerprint) (string, bool, string, map[string]float64, map[string]float64) {
	bayes := make(map[string]float64)
	svmData := make(map[string]float64)
	cleanFingerprint(&jsonFingerprint)
	if !groupExists(jsonFingerprint.Group) || len(jsonFingerprint.Group) == 0 {
		return "You should insert fingerprints before tracking", false, "", bayes, make(map[string]float64)
	}
	if len(jsonFingerprint.WifiFingerprint) == 0 {
		return "No fingerprints found to track, see API", false, "", bayes, make(map[string]float64)
	}
	if len(jsonFingerprint.Username) == 0 {
		return "No username defined, see API", false, "", bayes, make(map[string]float64)
	}
	if wasLearning, ok := isLearning[strings.ToLower(jsonFingerprint.Group)]; ok {
		if wasLearning {
			Debug.Println("Was learning, calculating priors")
			group := strings.ToLower(jsonFingerprint.Group)
			isLearning[group] = false
			optimizePriorsThreaded(group)
			if RuntimeArgs.Svm {
				dumpFingerprintsSVM(group)
				calculateSVM(group)
			}
			if _, ok := usersCache[group]; ok {
				if len(usersCache[group]) == 0 {
					usersCache[group] = append([]string{}, strings.ToLower(jsonFingerprint.Username))
				}
			}
		}
	}
	locationGuess1, bayes := calculatePosterior(jsonFingerprint, *NewFullParameters())
	percentGuess1 := float64(0)
	total := float64(0)
	for _, locBayes := range bayes {
		total += math.Exp(locBayes)
		if locBayes > percentGuess1 {
			percentGuess1 = locBayes
		}
	}
	percentGuess1 = math.Exp(bayes[locationGuess1]) / total * 100.0

	jsonFingerprint.Location = locationGuess1
	putFingerprintIntoDatabase(jsonFingerprint, "fingerprints-track")

	Debug.Println("Tracking fingerprint containing " + strconv.Itoa(len(jsonFingerprint.WifiFingerprint)) + " APs for " + jsonFingerprint.Username + " (" + jsonFingerprint.Group + ") at " + jsonFingerprint.Location + " (guess)")
	message := "Current location: " + locationGuess1 //+ " (" + strconv.Itoa(int(percentGuess1)) + "% confidence)"

	// Process SVM if needed
	if RuntimeArgs.Svm {
		locationGuess2, svmData2 := classify(jsonFingerprint)
		percentGuess2 := int(100 * math.Exp(svmData2[locationGuess2]))
		if percentGuess2 > 100 {
			percentGuess2 = percentGuess2 / 10
		}
		//message = "NB: " + locationGuess1 + " (" + strconv.Itoa(int(percentGuess1)) + "%)" + ", SVM: " + locationGuess2 + " (" + strconv.Itoa(int(percentGuess2)) + "%)"
		svmData = svmData2
	}

	// Send MQTT if needed
	if RuntimeArgs.Mqtt {
		type FingerprintResponse struct {
			LocationGuess string             `json:"location"`
			Timestamp     int64              `json:"time"`
			Bayes         map[string]float64 `json:"bayes"`
			Svm           map[string]float64 `json:"svm"`
		}
		mqttMessage, _ := json.Marshal(FingerprintResponse{
			LocationGuess: locationGuess1,
			Timestamp:     time.Now().UnixNano(),
			Bayes:         bayes,
			Svm:           svmData,
		})
		go sendMQTTLocation(string(mqttMessage), jsonFingerprint.Group, jsonFingerprint.Username)
	}

	// Send out the final responses
	var userJSON UserPositionJSON
	userJSON.Location = locationGuess1
	userJSON.Bayes = bayes
	userJSON.Svm = svmData
	userJSON.Time = time.Now().String()
	userPositionCache[strings.ToLower(jsonFingerprint.Group)+strings.ToLower(jsonFingerprint.Username)] = userJSON

	return message, true, locationGuess1, bayes, svmData

}
<|endoftext|>


<commit_before>package handler

import (
	"errors"
	"os"
	"strings"
	"time"
	"unicode"

	"github.com/knq/xoutil"
)

var (
	// ErrDriverNotAvailable is the driver not available error.
	ErrDriverNotAvailable = errors.New("driver not available")

	// ErrNotConnected is the not connected error.
	ErrNotConnected = errors.New("not connected")

	// ErrNoSuchFileOrDirectory is the no such file or directory error.
	ErrNoSuchFileOrDirectory = errors.New("no such file or directory")

	// ErrCannotIncludeDirectories is the cannot include directories error.
	ErrCannotIncludeDirectories = errors.New("cannot include directories")

	// ErrNoEditorDefined is the no editor defined error.
	ErrNoEditorDefined = errors.New("no editor defined")
)

// Error is a wrapper to standardize errors.
type Error struct {
	Driver string
	Err    error
}

// Error satisfies the error interface.
func (e *Error) Error() string {
	n := "usql"
	s := e.Err.Error()

	if e.Driver != "" {
		n = e.Driver
		s = strings.TrimLeftFunc(strings.TrimPrefix(strings.TrimSpace(s), e.Driver+":"), unicode.IsSpace)
	}

	return n + ": " + s
}

// sqlite3Parse will convert buf matching a time format to a time, and will
// format it according to the handler time settings.
//
// TODO: only do this if the type of the column is a timestamp type.
func sqlite3Parse(buf []byte) string {
	s := string(buf)
	if s != "" && strings.TrimSpace(s) != "" {
		t := &xoutil.SqTime{}
		err := t.Scan(buf)
		if err == nil {
			return t.Format(time.RFC3339Nano)
		}
	}

	return s
}

// addQueryParam conditionally adds a ?name=val style query parameter to the
// end of urlstr if a == b, when urlstr does not already contain name=.
func addQueryParam(a, b, urlstr, name, val string) string {
	if a == b && !strings.Contains(urlstr, name+"=") {
		s := "?"
		if strings.Contains(urlstr, "?") {
			s = "&"
		}
		return urlstr + s + name + "=" + val
	}

	return urlstr
}

var drivers map[string]string

// SetAvailableDrivers sets the known available drivers.
func SetAvailableDrivers(m map[string]string) {
	drivers = m
}

// pop pops the top item off of a if it is present, returning the value and the
// new slice. if a is empty, then v will be the returned value.
func pop(a []string, v string) ([]string, string) {
	if len(a) != 0 {
		return a[1:], a[0]
	}
	return a, v
}

// getenv tries retrieving successive keys from os environment variables.
func getenv(keys ...string) string {
	for _, key := range keys {
		if s := os.Getenv(key); s != "" {
			return s
		}
	}

	return ""
}
<commit_msg>Better standardizing error messages<commit_after>package handler

import (
	"errors"
	"os"
	"strings"
	"time"
	"unicode"

	"github.com/knq/xoutil"
)

var (
	// ErrDriverNotAvailable is the driver not available error.
	ErrDriverNotAvailable = errors.New("driver not available")

	// ErrNotConnected is the not connected error.
	ErrNotConnected = errors.New("not connected")

	// ErrNoSuchFileOrDirectory is the no such file or directory error.
	ErrNoSuchFileOrDirectory = errors.New("no such file or directory")

	// ErrCannotIncludeDirectories is the cannot include directories error.
	ErrCannotIncludeDirectories = errors.New("cannot include directories")

	// ErrNoEditorDefined is the no editor defined error.
	ErrNoEditorDefined = errors.New("no editor defined")
)

// Error is a wrapper to standardize errors.
type Error struct {
	Driver string
	Err    error
}

// Error satisfies the error interface.
func (e *Error) Error() string {
	n := "usql"
	s := e.Err.Error()

	if e.Driver != "" {
		n = e.Driver
		s = strings.TrimLeftFunc(strings.TrimPrefix(strings.TrimSpace(s), e.Driver+":"), unicode.IsSpace)

		switch e.Driver {
		case "ora", "oracle":
			if i := strings.Index(s, "ORA-"); i != -1 {
				s = s[i:]
			}

		case "mysql":
			s = strings.TrimSpace(strings.TrimPrefix(s, "Error "))
		}
	}

	return n + ": " + s
}

// sqlite3Parse will convert buf matching a time format to a time, and will
// format it according to the handler time settings.
//
// TODO: only do this if the type of the column is a timestamp type.
func sqlite3Parse(buf []byte) string {
	s := string(buf)
	if s != "" && strings.TrimSpace(s) != "" {
		t := &xoutil.SqTime{}
		err := t.Scan(buf)
		if err == nil {
			return t.Format(time.RFC3339Nano)
		}
	}

	return s
}

// addQueryParam conditionally adds a ?name=val style query parameter to the
// end of urlstr if a == b, when urlstr does not already contain name=.
func addQueryParam(a, b, urlstr, name, val string) string {
	if a == b && !strings.Contains(urlstr, name+"=") {
		s := "?"
		if strings.Contains(urlstr, "?") {
			s = "&"
		}
		return urlstr + s + name + "=" + val
	}

	return urlstr
}

var drivers map[string]string

// SetAvailableDrivers sets the known available drivers.
func SetAvailableDrivers(m map[string]string) {
	drivers = m
}

// pop pops the top item off of a if it is present, returning the value and the
// new slice. if a is empty, then v will be the returned value.
func pop(a []string, v string) ([]string, string) {
	if len(a) != 0 {
		return a[1:], a[0]
	}
	return a, v
}

// getenv tries retrieving successive keys from os environment variables.
func getenv(keys ...string) string {
	for _, key := range keys {
		if s := os.Getenv(key); s != "" {
			return s
		}
	}

	return ""
}
<|endoftext|>


<commit_before>package util

import (
	"encoding/json"
	"testing"
	"time"
)

func TestISO8601Time(t *testing.T) {
	now := ISO6801Time(time.Now().UTC())

	data, err := json.Marshal(now)
	if err != nil {
		t.Fatal(err)
	}

	_, err = time.Parse(`"`+formatISO8601+`"`, string(data))
	if err != nil {
		t.Fatal(err)
	}

	var now2 ISO6801Time
	err = json.Unmarshal(data, &now2)
	if err != nil {
		t.Fatal(err)
	}

	if now != now2 {
		t.Fatalf("Time %s does not equal expected %s", now2, now)
	}

	if now.String() != now2.String() {
		t.Fatalf("String format for %s does not equal expected %s", now2, now)
	}

	type TestTimeStruct struct {
		A int
		B *ISO6801Time
	}
	var testValue TestTimeStruct
	err = json.Unmarshal([]byte("{\"A\": 1, \"B\":\"\"}"), &testValue)
	if err != nil {
		t.Fatal(err)
	}
	t.Logf("%v", testValue)
	if !testValue.B.IsDefault() {
		t.Fatal("Invaid Unmarshal result for ISO6801Time from empty value")
	}
	t.Logf("ISO6801Time String(): %s", now2.String())
}
<commit_msg>Fix #9<commit_after>package util

import (
	"encoding/json"
	"testing"
	"time"
)

func TestISO8601Time(t *testing.T) {
	now := NewISO6801Time(time.Now().UTC())

	data, err := json.Marshal(now)
	if err != nil {
		t.Fatal(err)
	}

	_, err = time.Parse(`"`+formatISO8601+`"`, string(data))
	if err != nil {
		t.Fatal(err)
	}

	var now2 ISO6801Time
	err = json.Unmarshal(data, &now2)
	if err != nil {
		t.Fatal(err)
	}

	if now != now2 {
		t.Errorf("Time %s does not equal expected %s", now2, now)
	}

	if now.String() != now2.String() {
		t.Fatalf("String format for %s does not equal expected %s", now2, now)
	}

	type TestTimeStruct struct {
		A int
		B *ISO6801Time
	}
	var testValue TestTimeStruct
	err = json.Unmarshal([]byte("{\"A\": 1, \"B\":\"\"}"), &testValue)
	if err != nil {
		t.Fatal(err)
	}
	t.Logf("%v", testValue)
	if !testValue.B.IsDefault() {
		t.Fatal("Invaid Unmarshal result for ISO6801Time from empty value")
	}
	t.Logf("ISO6801Time String(): %s", now2.String())
}
<|endoftext|>


<commit_before>// Copyright 2016 Factom Foundation
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package factom_test

import (
	"testing"

	"fmt"
	"net/http"
	"net/http/httptest"

	. "github.com/FactomProject/factom"
)

func TestGetHeights(t *testing.T) {
	simlatedFactomdResponse := `{
       "jsonrpc":"2.0",
       "id":0,
       "result":{
          "directoryblockheight":72498,
          "leaderheight":72498,
          "entryblockheight":72498,
          "entryheight":72498
       }
    }`

	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")
		fmt.Fprintln(w, simlatedFactomdResponse)
	}))
	defer ts.Close()

	url := ts.URL[7:]
	SetFactomdServer(url)

	response, err := GetHeights()
	if err != nil {
		t.Error(err)
	}

	//fmt.Println(response)
	expectedResponse := `DirectoryBlockHeight: 72498
LeaderHeight: 72498
EntryBlockHeight: 72498
EntryHeight: 72498
`

	if expectedResponse != response.String() {
		t.Errorf("expected:%s\nrecieved:%s", expectedResponse, response)
	}
	t.Log(response)
}
<commit_msg>updated test for heights<commit_after>// Copyright 2016 Factom Foundation
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package factom_test

import (
	"fmt"
	"net/http"
	"net/http/httptest"

	. "github.com/FactomProject/factom"

	"testing"
)

func TestGetHeights(t *testing.T) {
	factomdResponse := `{
       "jsonrpc":"2.0",
       "id":0,
       "result":{
          "directoryblockheight":72498,
          "leaderheight":72498,
          "entryblockheight":72498,
          "entryheight":72498
       }
    }`
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")
		fmt.Fprintln(w, factomdResponse)
	}))
	defer ts.Close()

	SetFactomdServer(ts.URL[7:])

	response, err := GetHeights()
	if err != nil {
		t.Error(err)
	}

	expectedResponse := `DirectoryBlockHeight: 72498
LeaderHeight: 72498
EntryBlockHeight: 72498
EntryHeight: 72498
`

	if expectedResponse != response.String() {
		t.Errorf("expected:%s\nrecieved:%s", expectedResponse, response)
	}
	t.Log(response)
}
<|endoftext|>


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

package rest

import (
	"crypto/sha1"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
	"runtime"
	"runtime/pprof"
	"strconv"

	"github.com/couchbaselabs/sync_gateway/base"
	"github.com/couchbaselabs/sync_gateway/db"
)

const ServerName = "Couchbase Sync Gateway"
const VersionNumberString = "0.93"
const VersionString = ServerName + "/" + VersionNumberString

// HTTP handler for the root ("/")
func (h *handler) handleRoot() error {
	response := map[string]interface{}{
		"couchdb": "Welcome",
		"version": VersionString,
		"vendor":  db.Body{"name": ServerName, "version": VersionNumberString},
	}
	if h.privs == adminPrivs {
		response["ADMIN"] = true
	}
	h.writeJSON(response)
	return nil
}

func (h *handler) handleAllDbs() error {
	h.writeJSON(h.server.AllDatabaseNames())
	return nil
}

func (h *handler) handleCompact() error {
	revsDeleted, err := h.db.Compact()
	if err != nil {
		return err
	}
	h.writeJSON(db.Body{"revs": revsDeleted})
	return nil
}

func (h *handler) handleVacuum() error {
	attsDeleted, err := db.VacuumAttachments(h.db.Bucket)
	if err != nil {
		return err
	}
	h.writeJSON(db.Body{"atts": attsDeleted})
	return nil
}

func (h *handler) instanceStartTime() json.Number {
	return json.Number(strconv.FormatInt(h.db.StartTime.UnixNano()/1000, 10))
}

func (h *handler) handleGetDB() error {
	if h.rq.Method == "HEAD" {
		return nil
	}
	lastSeq, err := h.db.LastSequence()
	if err != nil {
		return err
	}
	response := db.Body{
		"db_name":              h.db.Name,
		"doc_count":            h.db.DocCount(),
		"update_seq":           lastSeq,
		"committed_update_seq": lastSeq,
		"instance_start_time":  h.instanceStartTime(),
		"compact_running":      false, // TODO: Implement this
		"purge_seq":            0,     // TODO: Should track this value
		"disk_format_version":  0,     // Probably meaningless, but add for compatibility
	}
	h.writeJSON(response)
	return nil
}

func (h *handler) handleEFC() error { // Handles _ensure_full_commit.
	// no-op. CouchDB's replicator sends this, so don't barf. Status must be 201.
	h.writeJSONStatus(http.StatusCreated, db.Body{
		"ok": true,
		"instance_start_time": h.instanceStartTime(),
	})
	return nil
}

func (h *handler) handleDesign() error {
	designDocID := h.PathVar("docid")
	if designDocID == "sync_gateway" {
		// we serve this content here so that CouchDB 1.2 has something to
		// hash into the replication-id, to correspond to our filter.
		filter := "ok"
		if h.db.DatabaseContext.ChannelMapper != nil {
			hash := sha1.New()
			io.WriteString(hash, h.db.DatabaseContext.ChannelMapper.Function())
			filter = fmt.Sprint(hash.Sum(nil))
		}
		h.writeJSON(db.Body{"filters": db.Body{"bychannel": filter}})
		return nil
	} else {
		h.SetPathVar("docid", "_design/"+designDocID)
		return h.handleGetDoc()
	}
}

func (h *handler) handlePutDesign() error {
	designDocID := h.PathVar("docid")
	if designDocID == "sync_gateway" {
		return base.HTTPErrorf(http.StatusForbidden, "forbidden")
	} else {
		h.SetPathVar("docid", "_design/"+designDocID)
		if h.rq.Method == "DELETE" {
			return h.handleDeleteDoc()
		} else {
			return h.handlePutDoc()
		}
	}
}

// ADMIN API to turn Go CPU profiling on/off
func (h *handler) handleProfiling() error {
	profileName := h.PathVar("name")
	var params struct {
		File string `json:"file"`
	}
	body, err := h.readBody()
	if err != nil {
		return err
	}
	if len(body) > 0 {
		if err = json.Unmarshal(body, &params); err != nil {
			return err
		}
	}

	if params.File != "" {
		f, err := os.Create(params.File)
		if err != nil {
			return err
		}
		if profileName != "" {
			defer f.Close()
			if profile := pprof.Lookup(profileName); profile != nil {
				profile.WriteTo(f, 0)
				base.Log("Wrote %s profile to %s", profileName, params.File)
			} else {
				return base.HTTPErrorf(http.StatusNotFound, "No such profile %q", profileName)
			}
		} else {
			base.Log("Starting CPU profile to %s ...", params.File)
			pprof.StartCPUProfile(f)
		}
	} else {
		if profileName != "" {
			return base.HTTPErrorf(http.StatusBadRequest, "Missing JSON 'file' parameter")
		} else {
			base.Log("...ending CPU profile.")
			pprof.StopCPUProfile()
		}
	}
	return nil
}

// ADMIN API to dump Go heap profile
func (h *handler) handleHeapProfiling() error {
	var params struct {
		File string `json:"file"`
	}
	body, err := h.readBody()
	if err != nil {
		return err
	}
	if err = json.Unmarshal(body, &params); err != nil {
		return err
	}

	base.Log("Dumping heap profile to %s ...", params.File)
	f, err := os.Create(params.File)
	if err != nil {
		return err
	}
	pprof.WriteHeapProfile(f)
	f.Close()
	return nil
}

type stats struct {
	MemStats runtime.MemStats
}

// ADMIN API to expose runtime and other stats
func (h *handler) handleStats() error {
	st := stats{}
	runtime.ReadMemStats(&st.MemStats)

	h.writeJSON(st)
	return nil
}
<commit_msg>Don't return doc_count in GET /db: it's too expensive to compute<commit_after>//  Copyright (c) 2012 Couchbase, Inc.
//  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
//  except in compliance with the License. You may obtain a copy of the License at
//    http://www.apache.org/licenses/LICENSE-2.0
//  Unless required by applicable law or agreed to in writing, software distributed under the
//  License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
//  either express or implied. See the License for the specific language governing permissions
//  and limitations under the License.

package rest

import (
	"crypto/sha1"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
	"runtime"
	"runtime/pprof"
	"strconv"

	"github.com/couchbaselabs/sync_gateway/base"
	"github.com/couchbaselabs/sync_gateway/db"
)

const ServerName = "Couchbase Sync Gateway"
const VersionNumberString = "0.93"
const VersionString = ServerName + "/" + VersionNumberString

// HTTP handler for the root ("/")
func (h *handler) handleRoot() error {
	response := map[string]interface{}{
		"couchdb": "Welcome",
		"version": VersionString,
		"vendor":  db.Body{"name": ServerName, "version": VersionNumberString},
	}
	if h.privs == adminPrivs {
		response["ADMIN"] = true
	}
	h.writeJSON(response)
	return nil
}

func (h *handler) handleAllDbs() error {
	h.writeJSON(h.server.AllDatabaseNames())
	return nil
}

func (h *handler) handleCompact() error {
	revsDeleted, err := h.db.Compact()
	if err != nil {
		return err
	}
	h.writeJSON(db.Body{"revs": revsDeleted})
	return nil
}

func (h *handler) handleVacuum() error {
	attsDeleted, err := db.VacuumAttachments(h.db.Bucket)
	if err != nil {
		return err
	}
	h.writeJSON(db.Body{"atts": attsDeleted})
	return nil
}

func (h *handler) instanceStartTime() json.Number {
	return json.Number(strconv.FormatInt(h.db.StartTime.UnixNano()/1000, 10))
}

func (h *handler) handleGetDB() error {
	if h.rq.Method == "HEAD" {
		return nil
	}
	lastSeq, err := h.db.LastSequence()
	if err != nil {
		return err
	}
	response := db.Body{
		"db_name":              h.db.Name,
		"update_seq":           lastSeq,
		"committed_update_seq": lastSeq,
		"instance_start_time":  h.instanceStartTime(),
		"compact_running":      false, // TODO: Implement this
		"purge_seq":            0,     // TODO: Should track this value
		"disk_format_version":  0,     // Probably meaningless, but add for compatibility
		//"doc_count":          h.db.DocCount(), // Removed: too expensive to compute (#278)
	}
	h.writeJSON(response)
	return nil
}

func (h *handler) handleEFC() error { // Handles _ensure_full_commit.
	// no-op. CouchDB's replicator sends this, so don't barf. Status must be 201.
	h.writeJSONStatus(http.StatusCreated, db.Body{
		"ok": true,
		"instance_start_time": h.instanceStartTime(),
	})
	return nil
}

func (h *handler) handleDesign() error {
	designDocID := h.PathVar("docid")
	if designDocID == "sync_gateway" {
		// we serve this content here so that CouchDB 1.2 has something to
		// hash into the replication-id, to correspond to our filter.
		filter := "ok"
		if h.db.DatabaseContext.ChannelMapper != nil {
			hash := sha1.New()
			io.WriteString(hash, h.db.DatabaseContext.ChannelMapper.Function())
			filter = fmt.Sprint(hash.Sum(nil))
		}
		h.writeJSON(db.Body{"filters": db.Body{"bychannel": filter}})
		return nil
	} else {
		h.SetPathVar("docid", "_design/"+designDocID)
		return h.handleGetDoc()
	}
}

func (h *handler) handlePutDesign() error {
	designDocID := h.PathVar("docid")
	if designDocID == "sync_gateway" {
		return base.HTTPErrorf(http.StatusForbidden, "forbidden")
	} else {
		h.SetPathVar("docid", "_design/"+designDocID)
		if h.rq.Method == "DELETE" {
			return h.handleDeleteDoc()
		} else {
			return h.handlePutDoc()
		}
	}
}

// ADMIN API to turn Go CPU profiling on/off
func (h *handler) handleProfiling() error {
	profileName := h.PathVar("name")
	var params struct {
		File string `json:"file"`
	}
	body, err := h.readBody()
	if err != nil {
		return err
	}
	if len(body) > 0 {
		if err = json.Unmarshal(body, &params); err != nil {
			return err
		}
	}

	if params.File != "" {
		f, err := os.Create(params.File)
		if err != nil {
			return err
		}
		if profileName != "" {
			defer f.Close()
			if profile := pprof.Lookup(profileName); profile != nil {
				profile.WriteTo(f, 0)
				base.Log("Wrote %s profile to %s", profileName, params.File)
			} else {
				return base.HTTPErrorf(http.StatusNotFound, "No such profile %q", profileName)
			}
		} else {
			base.Log("Starting CPU profile to %s ...", params.File)
			pprof.StartCPUProfile(f)
		}
	} else {
		if profileName != "" {
			return base.HTTPErrorf(http.StatusBadRequest, "Missing JSON 'file' parameter")
		} else {
			base.Log("...ending CPU profile.")
			pprof.StopCPUProfile()
		}
	}
	return nil
}

// ADMIN API to dump Go heap profile
func (h *handler) handleHeapProfiling() error {
	var params struct {
		File string `json:"file"`
	}
	body, err := h.readBody()
	if err != nil {
		return err
	}
	if err = json.Unmarshal(body, &params); err != nil {
		return err
	}

	base.Log("Dumping heap profile to %s ...", params.File)
	f, err := os.Create(params.File)
	if err != nil {
		return err
	}
	pprof.WriteHeapProfile(f)
	f.Close()
	return nil
}

type stats struct {
	MemStats runtime.MemStats
}

// ADMIN API to expose runtime and other stats
func (h *handler) handleStats() error {
	st := stats{}
	runtime.ReadMemStats(&st.MemStats)

	h.writeJSON(st)
	return nil
}
<|endoftext|>


<commit_before>package action

import (
    "github.com/spf13/cobra"
    "net/http"
    "net"
    "context"
    "fmt"
)

var VersionCmd = &cobra.Command{
    Use: "version",
    Short: "show the Jwt version information",
    Long: "show the Jwt version information",
    RunE: func(cmd *cobra.Command, args []string) error {
        client := &http.Client{
            Transport: &http.Transport{
                DialContext:func(ctx context.Context,network, addr string) (net.Conn, error) {
                    return net.Dial("unix", RootCmd.Args.SockFile)
                },
            },
        }

        reps, _ := client.Get("http://" + RootCmd.Args.SockFile + "/v1/version")
        fmt.Println(reps)
        return nil
    },
}<commit_msg>fix bug<commit_after>package action

import (
    "github.com/spf13/cobra"
    "net/http"
    "net"
    "context"
    "fmt"
)

var VersionCmd = &cobra.Command{
    Use: "version",
    Short: "show the Jwt version information",
    Long: "show the Jwt version information",
    RunE: func(cmd *cobra.Command, args []string) error {
        client := &http.Client{
            Transport: &http.Transport{
                DialContext:func(ctx context.Context, network, addr string) (net.Conn, error) {
                    return net.Dial("unix", RootCmd.Args.SockFile)
                },
            },
        }

        reps, _ := client.Get("http://unix/v1/version")
        fmt.Println(reps)
        return nil
    },
}<|endoftext|>


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

//
// formatifier is a library to easily format strings in a user defined and predefined manner.
//
// Examples:
// Phone:
// URL: http://play.golang.org/p/W_hL358mUa
// SSN: http://play.golang.org/p/iMmK9SL_jS
// Lock: http://play.golang.org/p/_5wf5YyEUw
// ISBN: http://play.golang.org/p/k27ZRvCeo7
// Morse: http://play.golang.org/p/M_xtujXwwC
// Pirate:
// Leet: http://play.golang.org/p/I6g21KKdjk
// IRSA: http://play.golang.org/p/_nRQwWywKW
//

package formatifier

import (
	"errors"
	"fmt"
	"strings"
)

// Format the provided string as a Phone Number.  Sticking to the ISO
// standard for country abbreviations.
/*
 China 1234 5678
 France  01–23–45–67–89
 Poland  (12) 345.67.89
 Singapore 123 4567
 Thailand  (01) 234–5678 or (012) 34–5678
 United Kingdom  0123 456 7890 or 01234 567890
 United States 1 (123) 456 7890
*/
func (f *Formatifier) ToPhone(geo string, international string, delimiter string) (string, error) {
	if len(geo) != 2 {
		return nil, errors.New("ERROR: Incorrect GEO code format")
	}

	f.removeNonDigits()

	return "", nil
}

// Format the provided string as a URL.  HTTP and HTTPS
// are the only supported protocols at this time.
func (f *Formatifier) ToURL(secure bool, subdomain string) (string, error) {
	if len(f.theString) < 1 {
		return "", errors.New("ERROR: URL needs to be longer than 0 characters.")
	}

	f.makeLower()

	if secure {
		if len(subdomain) > 0 {
			return fmt.Sprintf("https://%s.%s", subdomain, f.theString), nil
		} else {
			return fmt.Sprintf("https://%s", f.theString), nil
		}
	} else {
		if len(subdomain) > 0 {
			return fmt.Sprintf("http://%s.%s", subdomain, f.theString), nil
		} else {
			return fmt.Sprintf("http://%s", f.theString), nil
		}
	}
}

// Format the provided string as a SSN.
func (f *Formatifier) ToSSN(delimiter string) (string, error) {
	f.removeNonDigits()

	if len(f.theString) != 9 {
		return "", errors.New("ERROR: String needs to be 9 digits for Social Security Numbers.")
	}

	var buffer bytes.Buffer
	count := 0

	for _, i := range f.theString {
		count++

		buffer.WriteString(string(i))

		if count == 3 || count == 5 {
			buffer.WriteString(delimiter)
		}
	}
	return buffer.String(), nil
}

// Format the provided string as a Lock Combo.
func (f *Formatifier) ToLockCombo(delimiter string) (string, error) {
	f.removeNonDigits()

	if len(f.theString) != 9 {
		return "", errors.New("ERROR: String needs to be 6 digits for Lock Combo format.")
	}

	var buffer bytes.Buffer
	count := 0

	for _, i := range f.theString {
		count++

		buffer.WriteString(string(i))

		if count == 2 || count == 4 {
			buffer.WriteString(delimiter)
		}
	}
	return buffer.String(), nil
}

// Format the provided string in International Standard Book Number
// (ISBN) format.
func (f *Formatifier) ToISBN(delimiter string) (string, error) {
	f.removeNonDigits()

	if len(f.theString) != 13 {
		return "", errors.New("ERROR: string needs to be 13 characters.")
	}

	var buffer bytes.Buffer
	count := 0

	for _, i := range f.theString {
		count++

		buffer.WriteString(string(i))

		if count == 3 || count == 4 || count == 6 || count == 12 {
			buffer.WriteString(delimiter)
		}
	}
	return buffer.String(), nil
}

// Format the provided string in Morse Code.
func (f *Formatifier) ToMorseCode() (string, error) {
	if len(f.theString) < 1 {
		return "", errors.New("ERROR: String not long enough to convert.")
	}

	f.makeLower()

	var buffer bytes.Buffer

	for _, i := range f.theString {
		key := string(i)
		if _, ok := morse[key]; ok {
			buffer.WriteString(morse[key])
		} else if key == " " {
			buffer.WriteString(" ")
		}
	}
	return buffer.String(), nil
}

// Format the provided string in Pirate Speak.
func (f *Formatifier) ToPirateSpeak() (string, error) {
	if len(f.theString) < 1 {
		return "", errors.New("ERROR: String not long enough to convert.")
	}

	return "", nil
}

// Format the provided string in IRSA.
// International Radio-Telephony Spelling Alphabet
func (f *Formatifier) ToIRSA() (string, error) {
	if len(f.theString) < 1 {
		return "", errors.New("ERROR: Incorrect format for IRSA conversion.")
	}

	f.makeLower()

	var buffer bytes.Buffer

	for _, i := range f.theString {
		key := strings.ToLower(string(i))
		if _, ok := irsa[key]; ok {
			buffer.WriteString(irsa[key] + " ")
		}
	}
	return buffer.String(), nil
}

// Format the provided string in Leet Speak.
func (f *Formatifier) ToLeet() (string, error) {
	if len(f.theString) < 1 {
		return "", errors.New("ERROR: String not long enough to conver.")
	}

	f.makeLower()

	words := strings.Fields(f.theString)
	var buffer bytes.Buffer

	for _, word := range words {
		key := string(word)
		if _, ok := leet[word]; ok {
			buffer.WriteString(leet[key][0] + " ")
		} else {
			for _, i := range word {
				letter := string(i)
				if _, ok := leet[letter]; ok {
					buffer.WriteString(leet[letter][0])
				}
			}
			buffer.WriteString(" ")
		}
	}
	return buffer.String(), nil
}

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

//
// formatifier is a library to easily format strings in a user defined and predefined manner.
//
// Examples:
// Phone:
// URL: http://play.golang.org/p/W_hL358mUa
// SSN: http://play.golang.org/p/iMmK9SL_jS
// Lock: http://play.golang.org/p/_5wf5YyEUw
// ISBN: http://play.golang.org/p/k27ZRvCeo7
// Morse: http://play.golang.org/p/M_xtujXwwC
// Pirate:
// Leet: http://play.golang.org/p/I6g21KKdjk
// IRSA: http://play.golang.org/p/_nRQwWywKW
//

package formatifier

import (
	"errors"
	"fmt"
	"strings"
)

// Format the provided string as a Phone Number.  Sticking to the ISO
// standard for country abbreviations.
/*
 China 1234 5678
 France  01–23–45–67–89
 Poland  (12) 345.67.89
 Singapore 123 4567
 Thailand  (01) 234–5678 or (012) 34–5678
 United Kingdom  0123 456 7890 or 01234 567890
 United States 1 (123) 456 7890
*/
func (f *Formatifier) ToPhone(geo string, international string, delimiter string) (string, error) {
	if len(geo) != 2 {
		return nil, errors.New("ERROR: Incorrect GEO code format")
	}

	f.removeNonDigits()

	return "", nil
}

// Format the provided string as a URL.  HTTP and HTTPS
// are the only supported protocols at this time.
func (f *Formatifier) ToURL(secure bool, subdomain string) (string, error) {
	if len(f.theString) < 1 {
		return "", errors.New("ERROR: URL needs to be longer than 0 characters.")
	}

	f.makeLower()

	if secure {
		if len(subdomain) > 0 {
			return fmt.Sprintf("https://%s.%s", subdomain, f.theString), nil
		} else {
			return fmt.Sprintf("https://%s", f.theString), nil
		}
	} else {
		if len(subdomain) > 0 {
			return fmt.Sprintf("http://%s.%s", subdomain, f.theString), nil
		} else {
			return fmt.Sprintf("http://%s", f.theString), nil
		}
	}
}

// Format the provided string as a SSN.
func (f *Formatifier) ToSSN(delimiter string) (string, error) {
	f.removeNonDigits()

	if len(f.theString) != 9 {
		return "", errors.New("ERROR: String needs to be 9 digits for Social Security Numbers.")
	}

	var buffer bytes.Buffer
	count := 0

	for _, i := range f.theString {
		count++

		buffer.WriteString(string(i))

		if count == 3 || count == 5 {
			buffer.WriteString(delimiter)
		}
	}
	return buffer.String(), nil
}

// Format the provided string as a Lock Combo.
func (f *Formatifier) ToLockCombo(delimiter string) (string, error) {
	f.removeNonDigits()

	if len(f.theString) != 9 {
		return "", errors.New("ERROR: String needs to be 6 digits for Lock Combo format.")
	}

	var buffer bytes.Buffer
	count := 0

	for _, i := range f.theString {
		count++

		buffer.WriteString(string(i))

		if count == 2 || count == 4 {
			buffer.WriteString(delimiter)
		}
	}
	return buffer.String(), nil
}

// Format the provided string in International Standard Book Number
// (ISBN) format.
func (f *Formatifier) ToISBN(delimiter string) (string, error) {
	f.removeNonDigits()

	if len(f.theString) != 13 {
		return "", errors.New("ERROR: string needs to be 13 characters.")
	}

	var buffer bytes.Buffer
	count := 0

	for _, i := range f.theString {
		count++

		buffer.WriteString(string(i))

		if count == 3 || count == 4 || count == 6 || count == 12 {
			buffer.WriteString(delimiter)
		}
	}
	return buffer.String(), nil
}

// Format the provided string in Morse Code.
func (f *Formatifier) ToMorseCode() (string, error) {
	if len(f.theString) < 1 {
		return "", errors.New("ERROR: String not long enough to convert.")
	}

	f.makeLower()

	var buffer bytes.Buffer

	for _, i := range f.theString {
		key := string(i)
		if _, ok := morse[key]; ok {
			buffer.WriteString(morse[key])
		} else if key == " " {
			buffer.WriteString(" ")
		}
	}
	return buffer.String(), nil
}

// Format the provided string in Pirate Speak.
func (f *Formatifier) ToPirateSpeak() (string, error) {
	if len(f.theString) < 1 {
		return "", errors.New("ERROR: String not long enough to convert.")
	}

	return "", nil
}

// Format the provided string in IRSA.
// International Radio-Telephony Spelling Alphabet
func (f *Formatifier) ToIRSA() (string, error) {
	if len(f.theString) < 1 {
		return "", errors.New("ERROR: Incorrect format for IRSA conversion.")
	}

	f.makeLower()

	var buffer bytes.Buffer

	for _, i := range f.theString {
		key := strings.ToLower(string(i))
		if _, ok := irsa[key]; ok {
			buffer.WriteString(irsa[key] + " ")
		}
	}
	return buffer.String(), nil
}

// Format the provided string in Leet Speak.
// TODO(bdowns328) Make select post match random.
func (f *Formatifier) ToLeet() (string, error) {
	if len(f.theString) < 1 {
		return "", errors.New("ERROR: String not long enough to conver.")
	}

	f.makeLower()

	words := strings.Fields(f.theString)
	var buffer bytes.Buffer

	for _, word := range words {
		key := string(word)
		if _, ok := leet[word]; ok {
			buffer.WriteString(leet[key][0] + " ")
		} else {
			for _, i := range word {
				letter := string(i)
				if _, ok := leet[letter]; ok {
					buffer.WriteString(leet[letter][0])
				}
			}
			buffer.WriteString(" ")
		}
	}
	return buffer.String(), nil
}
<|endoftext|>


<commit_before>// +build go1.12

package gmf

/*
#cgo pkg-config: libavcodec libavutil

#include "libavcodec/avcodec.h"
#include "libavutil/frame.h"
#include "libavutil/imgutils.h"
#include "libavutil/timestamp.h"

void gmf_set_frame_data(AVFrame *frame, int idx, int l_size, uint8_t data) {
    if(!frame) {
        fprintf(stderr, "frame is NULL\n");
    }

    frame->data[idx][l_size] = data;
}

int gmf_get_frame_line_size(AVFrame *frame, int idx) {
	return frame->linesize[idx];
}

void gmf_free_data(AVFrame *frame) {
	av_freep(&frame->data[0]);
}

*/
import "C"

import (
	"errors"
	"fmt"
	"syscall"
	"unsafe"
)

const (
	AV_PICTURE_TYPE_NONE = iota // Undefined
	AV_PICTURE_TYPE_I           // Intra
	AV_PICTURE_TYPE_P           // Predicted
	AV_PICTURE_TYPE_B           // Bi-dir predicted
	AV_PICTURE_TYPE_S           // S(GMC)-VOP MPEG-4
	AV_PICTURE_TYPE_SI          // Switching Intra
	AV_PICTURE_TYPE_SP          // Switching Predicted
	AV_PICTURE_TYPE_BI          // BI type
)

type Frame struct {
	avFrame   *C.struct_AVFrame
	samples   *C.uint8_t
	mediaType int32
	err       error
	freeData  bool
}

func NewFrame() *Frame {
	return &Frame{avFrame: C.av_frame_alloc()}
}

func (f *Frame) Encode(enc *CodecCtx) (*Packet, error) {
	pkt := NewPacket()
	if pkt == nil {
		return nil, fmt.Errorf("unable to initialize new packet")
	}

	if ret := int(C.avcodec_send_frame(enc.avCodecCtx, f.avFrame)); ret < 0 {
		return nil, fmt.Errorf("error sending frame - %v", AvErrno(ret))
	}

	for {
		ret := int(C.avcodec_receive_packet(enc.avCodecCtx, &pkt.avPacket))
		if AvErrno(ret) == syscall.EAGAIN {
			return nil, nil
		}
		if ret < 0 {
			return nil, fmt.Errorf("%v", AvErrno(ret))
		}
		if ret >= 0 {
			break
		}
	}

	return pkt, nil
}

func (f *Frame) Pts() int64 {
	return int64(f.avFrame.pts)
}

func (f *Frame) Unref() {
	C.av_frame_unref(f.avFrame)
}

func (f *Frame) SetPts(val int64) {
	f.avFrame.pts = (C.int64_t)(val)
}

// AVPixelFormat for video frames, AVSampleFormat for audio
func (f *Frame) Format() int {
	return int(f.avFrame.format)
}

func (f *Frame) Width() int {
	return int(f.avFrame.width)
}

func (f *Frame) Height() int {
	return int(f.avFrame.height)
}

func (f *Frame) PktPts() int64 {
	return int64(f.avFrame.pkt_pts)
}

func (f *Frame) SetPktPts(val int64) {
	f.avFrame.pkt_pts = (C.int64_t)(val)
}

func (f *Frame) PktDts() int {
	return int(f.avFrame.pkt_dts)
}

func (f *Frame) SetPktDts(val int) {
	f.avFrame.pkt_dts = (C.int64_t)(val)
}

func (f *Frame) KeyFrame() int {
	return int(f.avFrame.key_frame)
}

func (f *Frame) NbSamples() int {
	return int(f.avFrame.nb_samples)
}

func (f *Frame) Channels() int {
	return int(f.avFrame.channels)
}

func (f *Frame) SetFormat(val int32) *Frame {
	f.avFrame.format = C.int(val)
	return f
}

func (f *Frame) SetWidth(val int) *Frame {
	f.avFrame.width = C.int(val)
	return f
}

func (f *Frame) SetHeight(val int) *Frame {
	f.avFrame.height = C.int(val)
	return f
}

func (f *Frame) ImgAlloc() error {
	if ret := int(C.av_image_alloc(
		(**C.uint8_t)(unsafe.Pointer(&f.avFrame.data)),
		(*C.int)(unsafe.Pointer(&f.avFrame.linesize)),
		C.int(f.Width()), C.int(f.Height()), int32(f.Format()), 32)); ret < 0 {
		return errors.New(fmt.Sprintf("Unable to allocate raw image buffer: %v", AvError(ret)))
	}

	f.freeData = true

	return nil
}

func NewAudioFrame(sampleFormat int32, channels, nb_samples int) (*Frame, error) {
	f := NewFrame()
	f.mediaType = AVMEDIA_TYPE_AUDIO
	f.SetNbSamples(nb_samples)
	f.SetFormat(sampleFormat)
	f.SetChannels(channels)

	//the codec gives us the frame size, in samples,
	//we calculate the size of the samples buffer in bytes
	size := C.av_samples_get_buffer_size(nil, C.int(channels), C.int(nb_samples),
		sampleFormat, 0)
	if size < 0 {
		return nil, errors.New("could not get sample buffer size")
	}

	f.samples = (*C.uint8_t)(C.av_malloc(C.size_t(size)))
	if f.samples == nil {
		return nil, errors.New(fmt.Sprintf("could not allocate %d bytes for samples buffer", size))
	}

	//setup the data pointers in the AVFrame
	ret := int(C.avcodec_fill_audio_frame(f.avFrame, C.int(channels), sampleFormat,
		f.samples, C.int(size), 0))
	if ret < 0 {
		return nil, errors.New("could not setup audio frame")
	}

	f.freeData = true

	return f, nil
}

func (f *Frame) SetData(idx int, lineSize int, data int) *Frame {
	C.gmf_set_frame_data(f.avFrame, C.int(idx), C.int(lineSize), (C.uint8_t)(data))

	return f
}

func (f *Frame) LineSize(idx int) int {
	return int(C.gmf_get_frame_line_size(f.avFrame, C.int(idx)))
}

func (f *Frame) Dump() {
	fmt.Printf("%v\n", f.avFrame)
}

func (f *Frame) CloneNewFrame() *Frame {
	return &Frame{avFrame: C.av_frame_clone(f.avFrame)}
}

func (f *Frame) Free() {
	if f.freeData && f.avFrame != nil {
		C.gmf_free_data(f.avFrame)
	}
	if f.avFrame != nil {
		C.av_frame_free(&f.avFrame)
	}
}

func (f *Frame) SetNbSamples(val int) *Frame {
	f.avFrame.nb_samples = C.int(val)
	return f
}

func (f *Frame) SetChannelLayout(val int) *Frame {
	f.avFrame.channel_layout = (C.uint64_t)(val)
	return f
}

func (f *Frame) GetChannelLayout() int {
	return int(f.avFrame.channel_layout)
}

func (f *Frame) SetChannels(val int) *Frame {
	f.avFrame.channels = C.int(val)
	return f
}

func (f *Frame) SetQuality(val int) *Frame {
	f.avFrame.quality = C.int(val)
	return f
}

func (f *Frame) SetPictType(val uint32) {
	f.avFrame.pict_type = val
}

func (f *Frame) IsNil() bool {
	if f.avFrame == nil {
		return true
	}

	return false
}

func (f *Frame) GetRawFrame() *C.struct_AVFrame {
	return f.avFrame
}

func (f *Frame) Time(timebase AVRational) int {
	return int(float64(timebase.AVR().Num) / float64(timebase.AVR().Den) * float64(f.Pts()))
}
<commit_msg>added method to get raw audio data from a frame<commit_after>// +build go1.12

package gmf

/*
#cgo pkg-config: libavcodec libavutil

#include "libavcodec/avcodec.h"
#include "libavutil/frame.h"
#include "libavutil/imgutils.h"
#include "libavutil/timestamp.h"

void gmf_set_frame_data(AVFrame *frame, int idx, int l_size, uint8_t data) {
    if(!frame) {
        fprintf(stderr, "frame is NULL\n");
    }

    frame->data[idx][l_size] = data;
}

int gmf_get_frame_line_size(AVFrame *frame, int idx) {
	return frame->linesize[idx];
}

void gmf_free_data(AVFrame *frame) {
	av_freep(&frame->data[0]);
}

*/
import "C"

import (
	"errors"
	"fmt"
	"syscall"
	"unsafe"
)

const (
	AV_PICTURE_TYPE_NONE = iota // Undefined
	AV_PICTURE_TYPE_I           // Intra
	AV_PICTURE_TYPE_P           // Predicted
	AV_PICTURE_TYPE_B           // Bi-dir predicted
	AV_PICTURE_TYPE_S           // S(GMC)-VOP MPEG-4
	AV_PICTURE_TYPE_SI          // Switching Intra
	AV_PICTURE_TYPE_SP          // Switching Predicted
	AV_PICTURE_TYPE_BI          // BI type
)

type Frame struct {
	avFrame   *C.struct_AVFrame
	samples   *C.uint8_t
	mediaType int32
	err       error
	freeData  bool
}

func NewFrame() *Frame {
	return &Frame{avFrame: C.av_frame_alloc()}
}

func (f *Frame) Encode(enc *CodecCtx) (*Packet, error) {
	pkt := NewPacket()
	if pkt == nil {
		return nil, fmt.Errorf("unable to initialize new packet")
	}

	if ret := int(C.avcodec_send_frame(enc.avCodecCtx, f.avFrame)); ret < 0 {
		return nil, fmt.Errorf("error sending frame - %v", AvErrno(ret))
	}

	for {
		ret := int(C.avcodec_receive_packet(enc.avCodecCtx, &pkt.avPacket))
		if AvErrno(ret) == syscall.EAGAIN {
			return nil, nil
		}
		if ret < 0 {
			return nil, fmt.Errorf("%v", AvErrno(ret))
		}
		if ret >= 0 {
			break
		}
	}

	return pkt, nil
}

func (f *Frame) Pts() int64 {
	return int64(f.avFrame.pts)
}

func (f *Frame) Unref() {
	C.av_frame_unref(f.avFrame)
}

func (f *Frame) SetPts(val int64) {
	f.avFrame.pts = (C.int64_t)(val)
}

// AVPixelFormat for video frames, AVSampleFormat for audio
func (f *Frame) Format() int {
	return int(f.avFrame.format)
}

func (f *Frame) Width() int {
	return int(f.avFrame.width)
}

func (f *Frame) Height() int {
	return int(f.avFrame.height)
}

func (f *Frame) PktPts() int64 {
	return int64(f.avFrame.pkt_pts)
}

func (f *Frame) SetPktPts(val int64) {
	f.avFrame.pkt_pts = (C.int64_t)(val)
}

func (f *Frame) PktDts() int {
	return int(f.avFrame.pkt_dts)
}

func (f *Frame) SetPktDts(val int) {
	f.avFrame.pkt_dts = (C.int64_t)(val)
}

func (f *Frame) KeyFrame() int {
	return int(f.avFrame.key_frame)
}

func (f *Frame) NbSamples() int {
	return int(f.avFrame.nb_samples)
}

func (f *Frame) Channels() int {
	return int(f.avFrame.channels)
}

func (f *Frame) SetFormat(val int32) *Frame {
	f.avFrame.format = C.int(val)
	return f
}

func (f *Frame) SetWidth(val int) *Frame {
	f.avFrame.width = C.int(val)
	return f
}

func (f *Frame) SetHeight(val int) *Frame {
	f.avFrame.height = C.int(val)
	return f
}

func (f *Frame) ImgAlloc() error {
	if ret := int(C.av_image_alloc(
		(**C.uint8_t)(unsafe.Pointer(&f.avFrame.data)),
		(*C.int)(unsafe.Pointer(&f.avFrame.linesize)),
		C.int(f.Width()), C.int(f.Height()), int32(f.Format()), 32)); ret < 0 {
		return errors.New(fmt.Sprintf("Unable to allocate raw image buffer: %v", AvError(ret)))
	}

	f.freeData = true

	return nil
}

func NewAudioFrame(sampleFormat int32, channels, nb_samples int) (*Frame, error) {
	f := NewFrame()
	f.mediaType = AVMEDIA_TYPE_AUDIO
	f.SetNbSamples(nb_samples)
	f.SetFormat(sampleFormat)
	f.SetChannels(channels)

	//the codec gives us the frame size, in samples,
	//we calculate the size of the samples buffer in bytes
	size := C.av_samples_get_buffer_size(nil, C.int(channels), C.int(nb_samples),
		sampleFormat, 0)
	if size < 0 {
		return nil, errors.New("could not get sample buffer size")
	}

	f.samples = (*C.uint8_t)(C.av_malloc(C.size_t(size)))
	if f.samples == nil {
		return nil, errors.New(fmt.Sprintf("could not allocate %d bytes for samples buffer", size))
	}

	//setup the data pointers in the AVFrame
	ret := int(C.avcodec_fill_audio_frame(f.avFrame, C.int(channels), sampleFormat,
		f.samples, C.int(size), 0))
	if ret < 0 {
		return nil, errors.New("could not setup audio frame")
	}

	f.freeData = true

	return f, nil
}

func (f *Frame) SetData(idx int, lineSize int, data int) *Frame {
	C.gmf_set_frame_data(f.avFrame, C.int(idx), C.int(lineSize), (C.uint8_t)(data))

	return f
}

func (f *Frame) LineSize(idx int) int {
	return int(C.gmf_get_frame_line_size(f.avFrame, C.int(idx)))
}

func (f *Frame) Dump() {
	fmt.Printf("%v\n", f.avFrame)
}

func (f *Frame) CloneNewFrame() *Frame {
	return &Frame{avFrame: C.av_frame_clone(f.avFrame)}
}

func (f *Frame) Free() {
	if f.freeData && f.avFrame != nil {
		C.gmf_free_data(f.avFrame)
	}
	if f.avFrame != nil {
		C.av_frame_free(&f.avFrame)
	}
}

func (f *Frame) SetNbSamples(val int) *Frame {
	f.avFrame.nb_samples = C.int(val)
	return f
}

func (f *Frame) SetChannelLayout(val int) *Frame {
	f.avFrame.channel_layout = (C.uint64_t)(val)
	return f
}

func (f *Frame) GetChannelLayout() int {
	return int(f.avFrame.channel_layout)
}

func (f *Frame) SetChannels(val int) *Frame {
	f.avFrame.channels = C.int(val)
	return f
}

func (f *Frame) SetQuality(val int) *Frame {
	f.avFrame.quality = C.int(val)
	return f
}

func (f *Frame) SetPictType(val uint32) {
	f.avFrame.pict_type = val
}

func (f *Frame) IsNil() bool {
	if f.avFrame == nil {
		return true
	}

	return false
}

func (f *Frame) GetRawFrame() *C.struct_AVFrame {
	return f.avFrame
}

func (f *Frame) GetRawAudioData(plane int) []byte {
	return C.GoBytes(unsafe.Pointer(f.avFrame.data[plane]), C.int(f.LineSize(plane)))
}

func (f *Frame) Time(timebase AVRational) int {
	return int(float64(timebase.AVR().Num) / float64(timebase.AVR().Den) * float64(f.Pts()))
}
<|endoftext|>


<commit_before>// Package dual provides an implementaiton of a split or "dual" dht, where two parallel instances
// are maintained for the global internet and the local LAN respectively.
package dual

import (
	"context"
	"sync"

	"github.com/ipfs/go-cid"
	ci "github.com/libp2p/go-libp2p-core/crypto"
	"github.com/libp2p/go-libp2p-core/host"
	"github.com/libp2p/go-libp2p-core/peer"
	"github.com/libp2p/go-libp2p-core/protocol"
	"github.com/libp2p/go-libp2p-core/routing"
	dht "github.com/libp2p/go-libp2p-kad-dht"
	helper "github.com/libp2p/go-libp2p-routing-helpers"

	"github.com/hashicorp/go-multierror"
)

// DHT implements the routing interface to provide two concrete DHT implementationts for use
// in IPFS that are used to support both global network users and disjoint LAN usecases.
type DHT struct {
	WAN *dht.IpfsDHT
	LAN *dht.IpfsDHT
}

// LanExtension is used to differentiate local protocol requests from those on the WAN DHT.
const LanExtension protocol.ID = "/lan"

// Assert that IPFS assumptions about interfaces aren't broken. These aren't a
// guarantee, but we can use them to aid refactoring.
var (
	_ routing.ContentRouting = (*DHT)(nil)
	_ routing.Routing        = (*DHT)(nil)
	_ routing.PeerRouting    = (*DHT)(nil)
	_ routing.PubKeyFetcher  = (*DHT)(nil)
	_ routing.ValueStore     = (*DHT)(nil)
)

// New creates a new DualDHT instance. Options provided are forwarded on to the two concrete
// IpfsDHT internal constructions, modulo additional options used by the Dual DHT to enforce
// the LAN-vs-WAN distinction.
// Note: query or routing table functional options provided as arguments to this function
// will be overriden by this constructor.
func New(ctx context.Context, h host.Host, options ...dht.Option) (*DHT, error) {
	wanOpts := append(options,
		dht.QueryFilter(dht.PublicQueryFilter),
		dht.RoutingTableFilter(dht.PublicRoutingTableFilter),
	)
	wan, err := dht.New(ctx, h, wanOpts...)
	if err != nil {
		return nil, err
	}

	// Unless overridden by user supplied options, the LAN DHT should default
	// to 'AutoServer' mode.
	lanOpts := append(options,
		dht.ProtocolExtension(LanExtension),
		dht.QueryFilter(dht.PrivateQueryFilter),
		dht.RoutingTableFilter(dht.PrivateRoutingTableFilter),
	)
	if wan.Mode() != dht.ModeClient {
		lanOpts = append(lanOpts, dht.Mode(dht.ModeServer))
	}
	lan, err := dht.New(ctx, h, lanOpts...)
	if err != nil {
		return nil, err
	}

	impl := DHT{wan, lan}
	return &impl, nil
}

// Close closes the DHT context.
func (dht *DHT) Close() error {
	return multierror.Append(dht.WAN.Close(), dht.LAN.Close()).ErrorOrNil()
}

func (dht *DHT) activeWAN() bool {
	return dht.WAN.RoutingTable().Size() > 0
}

// Provide adds the given cid to the content routing system.
func (dht *DHT) Provide(ctx context.Context, key cid.Cid, announce bool) error {
	if dht.activeWAN() {
		return dht.WAN.Provide(ctx, key, announce)
	}
	return dht.LAN.Provide(ctx, key, announce)
}

// FindProvidersAsync searches for peers who are able to provide a given key
func (dht *DHT) FindProvidersAsync(ctx context.Context, key cid.Cid, count int) <-chan peer.AddrInfo {
	reqCtx, cancel := context.WithCancel(ctx)
	outCh := make(chan peer.AddrInfo)
	wanCh := dht.WAN.FindProvidersAsync(reqCtx, key, count)
	lanCh := dht.LAN.FindProvidersAsync(reqCtx, key, count)
	go func() {
		defer cancel()
		defer close(outCh)

		found := make(map[peer.ID]struct{}, count)
		var pi peer.AddrInfo
		for count > 0 && (wanCh != nil || lanCh != nil) {
			var ok bool
			select {
			case pi, ok = <-wanCh:
				if !ok {
					wanCh = nil
					continue
				}
			case pi, ok = <-lanCh:
				if !ok {
					lanCh = nil
					continue
				}
			}
			// already found
			if _, ok = found[pi.ID]; ok {
				continue
			}

			select {
			case outCh <- pi:
				found[pi.ID] = struct{}{}
				count--
			case <-ctx.Done():
				return
			}
		}
	}()
	return outCh
}

// FindPeer searches for a peer with given ID
// Note: with signed peer records, we can change this to short circuit once either DHT returns.
func (dht *DHT) FindPeer(ctx context.Context, pid peer.ID) (peer.AddrInfo, error) {
	var wg sync.WaitGroup
	wg.Add(2)
	var wanInfo, lanInfo peer.AddrInfo
	var wanErr, lanErr error
	go func() {
		defer wg.Done()
		wanInfo, wanErr = dht.WAN.FindPeer(ctx, pid)
	}()
	go func() {
		defer wg.Done()
		lanInfo, lanErr = dht.LAN.FindPeer(ctx, pid)
	}()

	wg.Wait()

	return peer.AddrInfo{
		ID:    pid,
		Addrs: append(wanInfo.Addrs, lanInfo.Addrs...),
	}, multierror.Append(wanErr, lanErr).ErrorOrNil()
}

// Bootstrap allows callers to hint to the routing system to get into a
// Boostrapped state and remain there.
func (dht *DHT) Bootstrap(ctx context.Context) error {
	erra := dht.WAN.Bootstrap(ctx)
	errb := dht.LAN.Bootstrap(ctx)
	return multierror.Append(erra, errb).ErrorOrNil()
}

// PutValue adds value corresponding to given Key.
func (dht *DHT) PutValue(ctx context.Context, key string, val []byte, opts ...routing.Option) error {
	if dht.activeWAN() {
		return dht.WAN.PutValue(ctx, key, val, opts...)
	}
	return dht.LAN.PutValue(ctx, key, val, opts...)
}

// GetValue searches for the value corresponding to given Key.
func (d *DHT) GetValue(ctx context.Context, key string, opts ...routing.Option) ([]byte, error) {
	lanCtx, cancelLan := context.WithCancel(ctx)
	defer cancelLan()

	var (
		lanVal    []byte
		lanErr    error
		lanWaiter sync.WaitGroup
	)
	lanWaiter.Add(1)
	go func() {
		defer lanWaiter.Done()
		lanVal, lanErr = d.LAN.GetValue(lanCtx, key, opts...)
	}()

	wanVal, wanErr := d.WAN.GetValue(ctx, key, opts...)
	if wanErr == nil {
		cancelLan()
	}
	lanWaiter.Wait()
	if wanErr != nil {
		if lanErr != nil {
			return nil, multierror.Append(wanErr, lanErr).ErrorOrNil()
		}
		return lanVal, nil
	}
	return wanVal, nil
}

// SearchValue searches for better values from this value
func (dht *DHT) SearchValue(ctx context.Context, key string, opts ...routing.Option) (<-chan []byte, error) {
	p := helper.Parallel{Routers: []routing.Routing{dht.WAN, dht.LAN}, Validator: dht.WAN.Validator}
	return p.SearchValue(ctx, key, opts...)
}

// GetPublicKey returns the public key for the given peer.
func (dht *DHT) GetPublicKey(ctx context.Context, pid peer.ID) (ci.PubKey, error) {
	p := helper.Parallel{Routers: []routing.Routing{dht.WAN, dht.LAN}, Validator: dht.WAN.Validator}
	return p.GetPublicKey(ctx, pid)
}
<commit_msg>fix bug in count=0 findProviders<commit_after>// Package dual provides an implementaiton of a split or "dual" dht, where two parallel instances
// are maintained for the global internet and the local LAN respectively.
package dual

import (
	"context"
	"sync"

	"github.com/ipfs/go-cid"
	ci "github.com/libp2p/go-libp2p-core/crypto"
	"github.com/libp2p/go-libp2p-core/host"
	"github.com/libp2p/go-libp2p-core/peer"
	"github.com/libp2p/go-libp2p-core/protocol"
	"github.com/libp2p/go-libp2p-core/routing"
	dht "github.com/libp2p/go-libp2p-kad-dht"
	helper "github.com/libp2p/go-libp2p-routing-helpers"

	"github.com/hashicorp/go-multierror"
)

// DHT implements the routing interface to provide two concrete DHT implementationts for use
// in IPFS that are used to support both global network users and disjoint LAN usecases.
type DHT struct {
	WAN *dht.IpfsDHT
	LAN *dht.IpfsDHT
}

// LanExtension is used to differentiate local protocol requests from those on the WAN DHT.
const LanExtension protocol.ID = "/lan"

// Assert that IPFS assumptions about interfaces aren't broken. These aren't a
// guarantee, but we can use them to aid refactoring.
var (
	_ routing.ContentRouting = (*DHT)(nil)
	_ routing.Routing        = (*DHT)(nil)
	_ routing.PeerRouting    = (*DHT)(nil)
	_ routing.PubKeyFetcher  = (*DHT)(nil)
	_ routing.ValueStore     = (*DHT)(nil)
)

// New creates a new DualDHT instance. Options provided are forwarded on to the two concrete
// IpfsDHT internal constructions, modulo additional options used by the Dual DHT to enforce
// the LAN-vs-WAN distinction.
// Note: query or routing table functional options provided as arguments to this function
// will be overriden by this constructor.
func New(ctx context.Context, h host.Host, options ...dht.Option) (*DHT, error) {
	wanOpts := append(options,
		dht.QueryFilter(dht.PublicQueryFilter),
		dht.RoutingTableFilter(dht.PublicRoutingTableFilter),
	)
	wan, err := dht.New(ctx, h, wanOpts...)
	if err != nil {
		return nil, err
	}

	// Unless overridden by user supplied options, the LAN DHT should default
	// to 'AutoServer' mode.
	lanOpts := append(options,
		dht.ProtocolExtension(LanExtension),
		dht.QueryFilter(dht.PrivateQueryFilter),
		dht.RoutingTableFilter(dht.PrivateRoutingTableFilter),
	)
	if wan.Mode() != dht.ModeClient {
		lanOpts = append(lanOpts, dht.Mode(dht.ModeServer))
	}
	lan, err := dht.New(ctx, h, lanOpts...)
	if err != nil {
		return nil, err
	}

	impl := DHT{wan, lan}
	return &impl, nil
}

// Close closes the DHT context.
func (dht *DHT) Close() error {
	return multierror.Append(dht.WAN.Close(), dht.LAN.Close()).ErrorOrNil()
}

func (dht *DHT) activeWAN() bool {
	return dht.WAN.RoutingTable().Size() > 0
}

// Provide adds the given cid to the content routing system.
func (dht *DHT) Provide(ctx context.Context, key cid.Cid, announce bool) error {
	if dht.activeWAN() {
		return dht.WAN.Provide(ctx, key, announce)
	}
	return dht.LAN.Provide(ctx, key, announce)
}

// FindProvidersAsync searches for peers who are able to provide a given key
func (dht *DHT) FindProvidersAsync(ctx context.Context, key cid.Cid, count int) <-chan peer.AddrInfo {
	reqCtx, cancel := context.WithCancel(ctx)
	outCh := make(chan peer.AddrInfo)
	wanCh := dht.WAN.FindProvidersAsync(reqCtx, key, count)
	lanCh := dht.LAN.FindProvidersAsync(reqCtx, key, count)
	zeroCount := (count == 0)
	go func() {
		defer cancel()
		defer close(outCh)

		found := make(map[peer.ID]struct{}, count)
		var pi peer.AddrInfo
		for (zeroCount || count > 0) && (wanCh != nil || lanCh != nil) {
			var ok bool
			select {
			case pi, ok = <-wanCh:
				if !ok {
					wanCh = nil
					continue
				}
			case pi, ok = <-lanCh:
				if !ok {
					lanCh = nil
					continue
				}
			}
			// already found
			if _, ok = found[pi.ID]; ok {
				continue
			}

			select {
			case outCh <- pi:
				found[pi.ID] = struct{}{}
				count--
			case <-ctx.Done():
				return
			}
		}
	}()
	return outCh
}

// FindPeer searches for a peer with given ID
// Note: with signed peer records, we can change this to short circuit once either DHT returns.
func (dht *DHT) FindPeer(ctx context.Context, pid peer.ID) (peer.AddrInfo, error) {
	var wg sync.WaitGroup
	wg.Add(2)
	var wanInfo, lanInfo peer.AddrInfo
	var wanErr, lanErr error
	go func() {
		defer wg.Done()
		wanInfo, wanErr = dht.WAN.FindPeer(ctx, pid)
	}()
	go func() {
		defer wg.Done()
		lanInfo, lanErr = dht.LAN.FindPeer(ctx, pid)
	}()

	wg.Wait()

	return peer.AddrInfo{
		ID:    pid,
		Addrs: append(wanInfo.Addrs, lanInfo.Addrs...),
	}, multierror.Append(wanErr, lanErr).ErrorOrNil()
}

// Bootstrap allows callers to hint to the routing system to get into a
// Boostrapped state and remain there.
func (dht *DHT) Bootstrap(ctx context.Context) error {
	erra := dht.WAN.Bootstrap(ctx)
	errb := dht.LAN.Bootstrap(ctx)
	return multierror.Append(erra, errb).ErrorOrNil()
}

// PutValue adds value corresponding to given Key.
func (dht *DHT) PutValue(ctx context.Context, key string, val []byte, opts ...routing.Option) error {
	if dht.activeWAN() {
		return dht.WAN.PutValue(ctx, key, val, opts...)
	}
	return dht.LAN.PutValue(ctx, key, val, opts...)
}

// GetValue searches for the value corresponding to given Key.
func (d *DHT) GetValue(ctx context.Context, key string, opts ...routing.Option) ([]byte, error) {
	lanCtx, cancelLan := context.WithCancel(ctx)
	defer cancelLan()

	var (
		lanVal    []byte
		lanErr    error
		lanWaiter sync.WaitGroup
	)
	lanWaiter.Add(1)
	go func() {
		defer lanWaiter.Done()
		lanVal, lanErr = d.LAN.GetValue(lanCtx, key, opts...)
	}()

	wanVal, wanErr := d.WAN.GetValue(ctx, key, opts...)
	if wanErr == nil {
		cancelLan()
	}
	lanWaiter.Wait()
	if wanErr != nil {
		if lanErr != nil {
			return nil, multierror.Append(wanErr, lanErr).ErrorOrNil()
		}
		return lanVal, nil
	}
	return wanVal, nil
}

// SearchValue searches for better values from this value
func (dht *DHT) SearchValue(ctx context.Context, key string, opts ...routing.Option) (<-chan []byte, error) {
	p := helper.Parallel{Routers: []routing.Routing{dht.WAN, dht.LAN}, Validator: dht.WAN.Validator}
	return p.SearchValue(ctx, key, opts...)
}

// GetPublicKey returns the public key for the given peer.
func (dht *DHT) GetPublicKey(ctx context.Context, pid peer.ID) (ci.PubKey, error) {
	p := helper.Parallel{Routers: []routing.Routing{dht.WAN, dht.LAN}, Validator: dht.WAN.Validator}
	return p.GetPublicKey(ctx, pid)
}
<|endoftext|>


<commit_before>package dupfinder

import (
	"os"
	"bytes"
	"io"
)

const chunkSize = 64000

func chunker(r io.Reader, ch chan []byte) {
	for {
		buf := make([]byte, chunkSize)
		_, err := r.Read(buf)

		if err != nil {
			close(ch)
			return
		}

		ch <- buf
	}
}

func CompareFiles(path1, path2 string) (int, error) {
	fd1, err := os.Open(path1)
	defer fd1.Close()
	if err != nil {
		return 0, err
	}

	fd2, err := os.Open(path2)
	defer fd2.Close()
	if err != nil {
		return 0, err
	}

	return CompareReaders(fd1, fd2)
}

func CompareReaders(fd1, fd2 io.Reader) (int, error) {
	ch1 := make(chan []byte)
	ch2 := make(chan []byte)

	go chunker(fd1, ch1)
	go chunker(fd2, ch2)

	for {
		buf1 := <-ch1
		buf2 := <-ch2

		cmp := bytes.Compare(buf1, buf2)
		if cmp != 0 {
			return cmp, nil
		}

		if len(buf1) == 0 {
			return 0, nil
		}
	}
}
<commit_msg>Clarify send-only channel<commit_after>package dupfinder

import (
	"os"
	"bytes"
	"io"
)

const chunkSize = 64000

func chunker(r io.Reader, ch chan <- []byte) {
	for {
		buf := make([]byte, chunkSize)
		_, err := r.Read(buf)

		if err != nil {
			close(ch)
			return
		}

		ch <- buf
	}
}

func CompareFiles(path1, path2 string) (int, error) {
	fd1, err := os.Open(path1)
	defer fd1.Close()
	if err != nil {
		return 0, err
	}

	fd2, err := os.Open(path2)
	defer fd2.Close()
	if err != nil {
		return 0, err
	}

	return CompareReaders(fd1, fd2)
}

func CompareReaders(fd1, fd2 io.Reader) (int, error) {
	ch1 := make(chan []byte)
	ch2 := make(chan []byte)

	go chunker(fd1, ch1)
	go chunker(fd2, ch2)

	for {
		buf1 := <-ch1
		buf2 := <-ch2

		cmp := bytes.Compare(buf1, buf2)
		if cmp != 0 {
			return cmp, nil
		}

		if len(buf1) == 0 {
			return 0, nil
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/base64"
	"fmt"
	"log"
	"net/mail"
	"net/smtp"
	"strings"
)

func encodeRFC2047(String string) string {
	// use mail's rfc2047 to encode any string
	addr := mail.Address{String, ""}
	return strings.Trim(addr.String(), " <>")
}

func main() {
	// Set up authentication information.
//	smtpServer := "192.241.204.134"
    smtpServer := "127.0.0.1"
	auth := smtp.PlainAuth(
		"",
		"",
		"",
		smtpServer,
	)

	from := mail.Address{"", "+14257772300@smtp.zipwhip.com"}
	to := mail.Address{"Cell", "+12068597896@smtp.zipwhip.com"}

	//title := "8ef1211f-d9f2-4c81-906f-7d27da5a32f8:309626613"
    title := "+14257772300@smtp.ziphip.com"
	body := "Hello World\n\nHow are you today?\n\nGood Thanks!"

	header := make(map[string]string)
	header["From"] = from.String()
	header["To"] = to.String()
	header["Subject"] = encodeRFC2047(title)
	header["Zipwhip-Auth"] = "asdfasdf"

	message := ""
	for k, v := range header {
		message += fmt.Sprintf("%s: %s\r\n", k, v)
	}
	message += "\r\n" + base64.StdEncoding.EncodeToString([]byte(body))

	// Connect to the server, authenticate, set the sender and recipient,
	// and send the email all in one step.
	err := smtp.SendMail(
		//smtpServer+":25",
        smtpServer+":10025",
		auth,
		from.Address,
		[]string{to.Address},
		[]byte(message),
	//[]byte("This is the email body."),
	)
	if err != nil {
		log.Fatal(err)
	}
}
<commit_msg>Updating test script to try the new parsing feature.<commit_after>package main

import (
	"encoding/base64"
	"fmt"
	"log"
	"net/mail"
	"net/smtp"
	"strings"
)

func encodeRFC2047(String string) string {
	// use mail's rfc2047 to encode any string
	addr := mail.Address{String, ""}
	return strings.Trim(addr.String(), " <>")
}

func main() {
	// Set up authentication information.
//	smtpServer := "192.241.204.134"
    smtpServer := "127.0.0.1"
	auth := smtp.PlainAuth(
		"",
		"",
		"",
		smtpServer,
	)

	from := mail.Address{"", "+14257772300@smtp.zipwhip.com"}
	to := mail.Address{"Cell", "+12068597896@smtp.zipwhip.com"}

	title := "8ef1211f-d9f2-4c81-906f-7d27da5a32f8:309626613"
//    title := "asdfasdf::+14257772300@smtp.zipwhip.com"
	body := "Hello World\n\nHow are you today?\n\nGood Thanks!"

	header := make(map[string]string)
	header["From"] = from.String()
	header["To"] = to.String()
	header["Subject"] = encodeRFC2047(title)
	//header["Zipwhip-Auth"] = "asdfasdf"

	message := ""
	for k, v := range header {
		message += fmt.Sprintf("%s: %s\r\n", k, v)
	}
	message += "\r\n" + base64.StdEncoding.EncodeToString([]byte(body))

	// Connect to the server, authenticate, set the sender and recipient,
	// and send the email all in one step.
	err := smtp.SendMail(
		//smtpServer+":25",
        smtpServer+":10025",
		auth,
		from.Address,
		[]string{to.Address},
		[]byte(message),
	//[]byte("This is the email body."),
	)
	if err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package kafka

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"sync"

	"github.com/Shopify/sarama"
	"github.com/localhots/satan"
)

// ConsumerState contains data that is required to create a Kafka consumer.
type ConsumerState struct {
	Partition int32 `json:"partition"`
	Offset    int64 `json:"offset"`
}

// Stream is an implementation of satan.Stremer for Kafka messaging queue.
type Stream struct {
	messages chan []byte
	shutdown chan struct{}
	wg       sync.WaitGroup
}

const (
	consumerStateFile = "tmp/consumers.json"
)

var (
	kafkaClient   sarama.Client
	kafkaConsumer sarama.Consumer
	consumers     = map[string]map[string]ConsumerState{}
)

// Initialize sets up the kafka package.
func Initialize(brokers []string) {
	conf := sarama.NewConfig()
	conf.ClientID = "Satan Example"

	var err error
	if kafkaClient, err = sarama.NewClient(brokers, conf); err != nil {
		panic(err)
	}
	if kafkaConsumer, err = sarama.NewConsumerFromClient(kafkaClient); err != nil {
		panic(err)
	}

	loadConsumerConfig()
}

// Shutdown shuts down the kafka package.
func Shutdown() {
	if err := kafkaConsumer.Close(); err != nil {
		panic(err)
	}
	if err := kafkaClient.Close(); err != nil {
		panic(err)
	}
}

// Subscribe creates a satan.Streamer implementation for Kafka messaging queue.
func Subscribe(consumer, topic string) satan.Streamer {
	c, ok := consumers[consumer]
	if !ok {
		panic(fmt.Errorf("Consumer %q has no config", consumer))
	}
	t, ok := c[topic]
	if !ok {
		panic(fmt.Errorf("Consumer %q has no config for topic %q", consumer, topic))
	}

	pc, err := kafkaConsumer.ConsumePartition(topic, t.Partition, t.Offset)
	if err != nil {
		panic(err)
	}

	stream := &Stream{
		messages: make(chan []byte),
		shutdown: make(chan struct{}),
	}
	go func() {
		stream.wg.Add(1)
		defer stream.wg.Done()
		defer pc.Close()
		for {
			select {
			case msg := <-pc.Messages():
				select {
				case stream.messages <- msg.Value:
					t.Offset = msg.Offset
				case <-stream.shutdown:
					return
				}
			case err := <-pc.Errors():
				log.Println("Kafka error:", err.Error())
			case <-stream.shutdown:
				return
			}
		}
	}()

	return stream
}

// Messages returns a channel that stream messages.
func (s *Stream) Messages() <-chan []byte {
	return s.messages
}

// Close stops Kafka partition consumer.
func (s *Stream) Close() {
	close(s.shutdown)
	s.wg.Wait()
}

func loadConsumerConfig() {
	if b, err := ioutil.ReadFile(consumerStateFile); err != nil {
		fmt.Println(`Kafka consumers state file was not found at ` + consumerStateFile + `
Please create one in order to proceed with this example.
Config file contents should look like this:
{
    "ConsumerName": {
        "TopicName": {
            "partition": 0,
            "offset": 12345
        }
    }
}`)
		os.Exit(1)
	} else {
		if err = json.Unmarshal(b, &consumers); err != nil {
			panic(err)
		}
	}
}
<commit_msg>Log messages on Kafka startup/shutdown<commit_after>package kafka

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"sync"

	"github.com/Shopify/sarama"
	"github.com/localhots/satan"
)

// ConsumerState contains data that is required to create a Kafka consumer.
type ConsumerState struct {
	Partition int32 `json:"partition"`
	Offset    int64 `json:"offset"`
}

// Stream is an implementation of satan.Stremer for Kafka messaging queue.
type Stream struct {
	messages chan []byte
	shutdown chan struct{}
	wg       sync.WaitGroup
}

const (
	consumerStateFile = "tmp/consumers.json"
)

var (
	kafkaClient   sarama.Client
	kafkaConsumer sarama.Consumer
	consumers     = map[string]map[string]ConsumerState{}
)

// Initialize sets up the kafka package.
func Initialize(brokers []string) {
	log.Println("Initializing Kafka")
	defer log.Println("Kafka is initialized")

	conf := sarama.NewConfig()
	conf.ClientID = "Satan Example"

	var err error
	if kafkaClient, err = sarama.NewClient(brokers, conf); err != nil {
		panic(err)
	}
	if kafkaConsumer, err = sarama.NewConsumerFromClient(kafkaClient); err != nil {
		panic(err)
	}

	loadConsumerConfig()
}

// Shutdown shuts down the kafka package.
func Shutdown() {
	log.Println("Shutting down Kafka")
	defer log.Println("Kafka was shut down")

	if err := kafkaConsumer.Close(); err != nil {
		panic(err)
	}
	if err := kafkaClient.Close(); err != nil {
		panic(err)
	}
}

// Subscribe creates a satan.Streamer implementation for Kafka messaging queue.
func Subscribe(consumer, topic string) satan.Streamer {
	c, ok := consumers[consumer]
	if !ok {
		panic(fmt.Errorf("Consumer %q has no config", consumer))
	}
	t, ok := c[topic]
	if !ok {
		panic(fmt.Errorf("Consumer %q has no config for topic %q", consumer, topic))
	}

	pc, err := kafkaConsumer.ConsumePartition(topic, t.Partition, t.Offset)
	if err != nil {
		panic(err)
	}

	stream := &Stream{
		messages: make(chan []byte),
		shutdown: make(chan struct{}),
	}
	go func() {
		stream.wg.Add(1)
		defer stream.wg.Done()
		defer pc.Close()
		for {
			select {
			case msg := <-pc.Messages():
				select {
				case stream.messages <- msg.Value:
					t.Offset = msg.Offset
				case <-stream.shutdown:
					return
				}
			case err := <-pc.Errors():
				log.Println("Kafka error:", err.Error())
			case <-stream.shutdown:
				return
			}
		}
	}()

	return stream
}

// Messages returns a channel that stream messages.
func (s *Stream) Messages() <-chan []byte {
	return s.messages
}

// Close stops Kafka partition consumer.
func (s *Stream) Close() {
	close(s.shutdown)
	s.wg.Wait()
}

func loadConsumerConfig() {
	if b, err := ioutil.ReadFile(consumerStateFile); err != nil {
		fmt.Println(`Kafka consumers state file was not found at ` + consumerStateFile + `
Please create one in order to proceed with this example.
Config file contents should look like this:
{
    "ConsumerName": {
        "TopicName": {
            "partition": 0,
            "offset": 12345
        }
    }
}`)
		os.Exit(1)
	} else {
		if err = json.Unmarshal(b, &consumers); err != nil {
			panic(err)
		}
	}
}
<|endoftext|>


<commit_before>package edc

import "log"

// Education - struct for education
type Education struct {
	ID        int64  `sql:"id" json:"id" `
	StartDate string `sql:"start_date" json:"start_date"`
	EndDate   string `sql:"end_date" json:"end_date"`
	StartStr  string `sql:"-" json:"start_str"`
	EndStr    string `sql:"-" json:"end_str"`
	Note      string `sql:"note, null" json:"note"`
	CreatedAt string `sql:"created_at" json:"created_at"`
	UpdatedAt string `sql:"updated_at" json:"updated_at"`
}

// GetEducation - get education by id
func (e *Edb) GetEducation(id int64) (Education, error) {
	var education Education
	if id == 0 {
		return education, nil
	}
	err := e.db.Model(&education).Where(`id = ?`, id).Select()
	if err != nil {
		errmsg("GetEducation select", err)
	}
	return education, err
}

// GetEducationList - get all education for list
func (e *Edb) GetEducationList() ([]Education, error) {
	var educations []Education
	err := e.db.Model(&educations).
		Where("educations.id", "educations.start_date", "educations.end_date", "educations.note").
		Order("educations.start_date").
		Select()
	if err != nil {
		errmsg("GetEducationList select", err)
		return educations, err
	}
	for i := range educations {
		educations[i].StartStr = setStrMonth(educations[i].StartDate)
		educations[i].EndStr = setStrMonth(educations[i].EndDate)
	}
	return educations, err
}

// GetEducationSelect - get all education for select
func (e *Edb) GetEducationSelect() ([]Education, error) {
	var educations []Education
	err := e.db.Model(&educations).
		Where("educations.id", "educations.start_date", "educations.end_date").
		Order("educations.start_date").
		Select()
	if err != nil {
		errmsg("GetEducationSelect select", err)
		return educations, err
	}

	for i := range educations {
		educations[i].StartStr = setStrMonth(educations[i].StartDate)
		educations[i].EndStr = setStrMonth(educations[i].EndDate)
	}
	return educations, err
}

// CreateEducation - create new education
func (e *Edb) CreateEducation(education Education) (int64, error) {
	err := e.db.Insert(&education)
	if err != nil {
		log.Println("CreateEducation e.db.Insert ", err)
		return 0, err
	}
	return education.ID, err
}

// UpdateEducation - save changes to education
func (e *Edb) UpdateEducation(education Education) error {
	stmt, err := e.db.Prepare(`
		UPDATE
			educations
		SET
			start_date = $2,
			end_date = $3,
			note = $4,
			updated_at = now()
		WHERE
			id = $1
	`)
	if err != nil {
		log.Println("UpdateEducation e.db.Prepare ", err)
		return err
	}
	_, err = stmt.Exec(education.ID, sd2n(education.StartDate), sd2n(education.EndDate), s2n(education.Note))
	return err
}

// DeleteEducation - delete education by id
func (e *Edb) DeleteEducation(id int64) error {
	if id == 0 {
		return nil
	}
	_, err := e.db.Exec(`
		DELETE FROM
			educations
		WHERE
			id = $1
	`, id)
	if err != nil {
		log.Println("DeleteEducation ", id, err)
	}
	return err
}

func (e *Edb) educationCreateTable() error {
	str := `
		CREATE TABLE IF NOT EXISTS
			educations (
				id bigserial primary key,
				start_date date,
				end_date date,
				note text,
				created_at TIMESTAMP without time zone,
				updated_at TIMESTAMP without time zone
			)
	`
	_, err := e.db.Exec(str)
	if err != nil {
		log.Println("educationCreateTable ", err)
	}
	return err
}
<commit_msg>continue migrate<commit_after>package edc

// Education - struct for education
type Education struct {
	ID        int64  `sql:"id" json:"id" `
	StartDate string `sql:"start_date" json:"start_date"`
	EndDate   string `sql:"end_date" json:"end_date"`
	StartStr  string `sql:"-" json:"start_str"`
	EndStr    string `sql:"-" json:"end_str"`
	Note      string `sql:"note, null" json:"note"`
	CreatedAt string `sql:"created_at" json:"created_at"`
	UpdatedAt string `sql:"updated_at" json:"updated_at"`
}

// GetEducation - get education by id
func (e *Edb) GetEducation(id int64) (Education, error) {
	var education Education
	if id == 0 {
		return education, nil
	}
	err := e.db.Model(&education).Where(`id = ?`, id).Select()
	if err != nil {
		errmsg("GetEducation select", err)
	}
	return education, err
}

// GetEducationList - get all education for list
func (e *Edb) GetEducationList() ([]Education, error) {
	var educations []Education
	err := e.db.Model(&educations).
		Where("educations.id", "educations.start_date", "educations.end_date", "educations.note").
		Order("educations.start_date").
		Select()
	if err != nil {
		errmsg("GetEducationList select", err)
		return educations, err
	}
	for i := range educations {
		educations[i].StartStr = setStrMonth(educations[i].StartDate)
		educations[i].EndStr = setStrMonth(educations[i].EndDate)
	}
	return educations, err
}

// GetEducationSelect - get all education for select
func (e *Edb) GetEducationSelect() ([]Education, error) {
	var educations []Education
	err := e.db.Model(&educations).
		Where("educations.id", "educations.start_date", "educations.end_date").
		Order("educations.start_date").
		Select()
	if err != nil {
		errmsg("GetEducationSelect select", err)
		return educations, err
	}
	for i := range educations {
		educations[i].StartStr = setStrMonth(educations[i].StartDate)
		educations[i].EndStr = setStrMonth(educations[i].EndDate)
	}
	return educations, err
}

// CreateEducation - create new education
func (e *Edb) CreateEducation(education Education) (int64, error) {
	err := e.db.Insert(&education)
	if err != nil {
		errmsg("CreateEducation insert", err)
	}
	return education.ID, err
}

// UpdateEducation - save changes to education
func (e *Edb) UpdateEducation(education Education) error {
	err := e.db.Update(&education)
	if err != nil {
		errmsg("UpdateEducation update", err)
	}
	return err
}

// DeleteEducation - delete education by id
func (e *Edb) DeleteEducation(id int64) error {
	if id == 0 {
		return nil
	}
	_, err := e.db.Model(&Education{}).Where("id = ?", id).Delete()
	if err != nil {
		errmsg("DeleteEducation delete", err)
	}
	return err
}

func (e *Edb) educationCreateTable() error {
	str := `
		CREATE TABLE IF NOT EXISTS
			educations (
				id bigserial primary key,
				start_date date,
				end_date date,
				note text,
				created_at TIMESTAMP without time zone,
				updated_at TIMESTAMP without time zone
			)
	`
	_, err := e.db.Exec(str)
	if err != nil {
		errmsg("educationCreateTable exec", err)
	}
	return err
}
<|endoftext|>


<commit_before>package streamer

import (
	"io"
	"time"
)

var _ io.ReadCloser = &TailReader{}

type TailReader struct {
	r    io.Reader
	quit chan struct{}
}

/*
	Proxies another reader, disregarding EOFs and blocking instead until
	the user closes.
*/
func NewTailReader(r io.Reader) *TailReader {
	return &TailReader{
		r:    r,
		quit: make(chan struct{}),
	}
}

func (r *TailReader) Read(msg []byte) (n int, err error) {
	for n == 0 && err == nil {
		n, err = r.r.Read(msg)
		if err == io.EOF {
			// We don't pass EOF up until we're commanded to be closed.
			// This could be a "temporary" EOF and appends will still be incoming.
			if n > 0 {
				// If any bytes, pass them up immediately.
				return n, nil
			}
			// We're effectively required to block here, because otherwise the reader may spin;
			// this is not a clueful wait; but it does prevent pegging a core.
			// Quite dumb in this case is also quite fool-proof.
			err = nil
			select {
			case <-time.After(1 * time.Millisecond):
			case <-r.quit:
				return 0, io.EOF
			}
		}
	}
	// anything other than an eof, we have no behavioral changes to make; pass up.
	return n, err
}

/*
	Breaks any readers currently blocked.
*/
func (r *TailReader) Close() error {
	close(r.quit)
	return nil
}
<commit_msg>Change streamer.TailReader to drain the file instead of aborting immediately on close.<commit_after>package streamer

import (
	"fmt"
	"io"
	"sync/atomic"
	"time"
)

var _ io.ReadCloser = &TailReader{}

var ErrAlreadyClosed = fmt.Errorf("TailReader already closed")

type TailReader struct {
	r     io.Reader
	drain int32
}

/*
	Proxies another reader, disregarding EOFs and blocking instead until
	the user closes.
*/
func NewTailReader(r io.Reader) *TailReader {
	return &TailReader{
		r: r,
	}
}

func (r *TailReader) Read(msg []byte) (n int, err error) {
	for n == 0 && err == nil {
		n, err = r.r.Read(msg)
		if err == io.EOF {
			// We don't pass EOF up until we're commanded to be closed.
			// This could be a "temporary" EOF and appends will still be incoming.
			if n > 0 {
				// If any bytes, pass them up immediately.
				return n, nil
			}
			// If we got EOF, have no buffer, and are at this instant closed, leave.
			if r.drain > 0 {
				return 0, io.EOF
			}
			// Pause before retrying.
			// We're effectively required to block here, because otherwise the reader may spin;
			// this is not a clueful wait; but it does prevent pegging a core.
			// Quite dumb in this case is also quite fool-proof.
			err = nil
			<-time.After(1 * time.Millisecond)
		}
	}
	// anything other than an eof, we have no behavioral changes to make; pass up.
	return n, err
}

/*
	Breaks any readers currently blocked.
*/
func (r *TailReader) Close() error {
	if swapped := atomic.CompareAndSwapInt32(&r.drain, 0, 1); swapped != true {
		return ErrAlreadyClosed
	}
	return nil
}
<|endoftext|>


<commit_before>package expr

import (
	"fmt"
	"math"

	"github.com/grafana/metrictank/api/models"
)

var results []models.Series

func equalOutput(exp, got []models.Series, expErr, gotErr error) error {
	if expErr == nil && gotErr != nil {
		return fmt.Errorf("err should be nil. got %q", gotErr)
	}
	if expErr != nil && gotErr == nil {
		return fmt.Errorf("err should be error %v. got %q", expErr, gotErr)
	}
	if len(got) != len(exp) {
		return fmt.Errorf("perSecond len output expected %d, got %d", len(exp), len(got))
	}
	for i, _ := range got {
		if err := equalSeries(exp[i], got[i]); err != nil {
			return fmt.Errorf("series %d: %s", i, err)
		}
	}
	return nil
}

// cannot just use reflect.DeepEqual because NaN != NaN, whereas we want NaN == NaN
// https://github.com/golang/go/issues/12025
func equalSeries(exp, got models.Series) error {
	if got.Target != exp.Target {
		return fmt.Errorf("Target %q, got %q", exp.Target, got.Target)
	}
	if got.Interval != exp.Interval {
		return fmt.Errorf("Interval %d, got %d", exp.Interval, got.Interval)
	}
	if got.QueryPatt != exp.QueryPatt {
		return fmt.Errorf("QueryPatt %q, got %q", exp.QueryPatt, got.QueryPatt)
	}
	if got.QueryFrom != exp.QueryFrom {
		return fmt.Errorf("QueryFrom %d, got %d", exp.QueryFrom, got.QueryFrom)
	}
	if got.QueryTo != exp.QueryTo {
		return fmt.Errorf("QueryTo %d, got %d", exp.QueryTo, got.QueryTo)
	}
	if got.QueryCons != exp.QueryCons {
		return fmt.Errorf("QueryCons %v, got %v", exp.QueryCons, got.QueryCons)
	}
	if got.Consolidator != exp.Consolidator {
		return fmt.Errorf("Consolidator %v, got %v", exp.Consolidator, got.Consolidator)
	}
	if len(got.Datapoints) != len(exp.Datapoints) {
		return fmt.Errorf("output expected %d, got %d", len(exp.Datapoints), len(got.Datapoints))
	}
	for j, p := range got.Datapoints {
		bothNaN := math.IsNaN(p.Val) && math.IsNaN(exp.Datapoints[j].Val)
		if (bothNaN || p.Val == exp.Datapoints[j].Val) && p.Ts == exp.Datapoints[j].Ts {
			continue
		}
		return fmt.Errorf("point %d - expected %v got %v", j, exp.Datapoints[j], p)
	}
	return nil
}
<commit_msg>formatting<commit_after>package expr

import (
	"fmt"
	"math"

	"github.com/grafana/metrictank/api/models"
)

var results []models.Series

func equalOutput(exp, got []models.Series, expErr, gotErr error) error {
	if expErr == nil && gotErr != nil {
		return fmt.Errorf("err should be nil. got %q", gotErr)
	}
	if expErr != nil && gotErr == nil {
		return fmt.Errorf("err should be error %v. got %q", expErr, gotErr)
	}
	if len(got) != len(exp) {
		return fmt.Errorf("perSecond len output expected %d, got %d", len(exp), len(got))
	}
	for i := range got {
		if err := equalSeries(exp[i], got[i]); err != nil {
			return fmt.Errorf("series %d: %s", i, err)
		}
	}
	return nil
}

// cannot just use reflect.DeepEqual because NaN != NaN, whereas we want NaN == NaN
// https://github.com/golang/go/issues/12025
func equalSeries(exp, got models.Series) error {
	if got.Target != exp.Target {
		return fmt.Errorf("Target %q, got %q", exp.Target, got.Target)
	}
	if got.Interval != exp.Interval {
		return fmt.Errorf("Interval %d, got %d", exp.Interval, got.Interval)
	}
	if got.QueryPatt != exp.QueryPatt {
		return fmt.Errorf("QueryPatt %q, got %q", exp.QueryPatt, got.QueryPatt)
	}
	if got.QueryFrom != exp.QueryFrom {
		return fmt.Errorf("QueryFrom %d, got %d", exp.QueryFrom, got.QueryFrom)
	}
	if got.QueryTo != exp.QueryTo {
		return fmt.Errorf("QueryTo %d, got %d", exp.QueryTo, got.QueryTo)
	}
	if got.QueryCons != exp.QueryCons {
		return fmt.Errorf("QueryCons %v, got %v", exp.QueryCons, got.QueryCons)
	}
	if got.Consolidator != exp.Consolidator {
		return fmt.Errorf("Consolidator %v, got %v", exp.Consolidator, got.Consolidator)
	}
	if len(got.Datapoints) != len(exp.Datapoints) {
		return fmt.Errorf("output expected %d, got %d", len(exp.Datapoints), len(got.Datapoints))
	}
	for j, p := range got.Datapoints {
		bothNaN := math.IsNaN(p.Val) && math.IsNaN(exp.Datapoints[j].Val)
		if (bothNaN || p.Val == exp.Datapoints[j].Val) && p.Ts == exp.Datapoints[j].Ts {
			continue
		}
		return fmt.Errorf("point %d - expected %v got %v", j, exp.Datapoints[j], p)
	}
	return nil
}
<|endoftext|>