<commit_before>package main

import (
	"bitbucket.org/chrj/smtpd"
	"crypto/tls"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"github.com/miekg/dns"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"net/smtp"
	"os"
	"os/signal"
	"strconv"
	"strings"
	"syscall"
	"time"
)

type Config struct {
	Cert string
	Key  string
	Host string
	Bind string
	Port string
	Tls  string
	Time string
	Url  string
}

type Alias struct {
	Source      string
	Destination string
}

var config_file = flag.String("c", "/etc/relayd/relayd.conf", "config file")
var cert_file = flag.String("cf", "", "certificate file")
var cert_key = flag.String("ck", "", "certificate key file")
var force_tls = flag.Bool("tls", true, "force tls")
var bind_port = flag.Int("p", 25, "server port")
var bind_interface = flag.String("i", "", "server interface")
var hostname = flag.String("h", "localhost.localdomain", "server hostname")
var refresh_time = flag.Int("r", 300, "refresh time in seconds")
var alias_url = flag.String("u", "", "aliases fetch url")
var show_help = flag.Bool("help", false, "show help")
var show_version = flag.Bool("version", false, "print version")

func init() {

}

func GetOutboundIP() string {
	conn, err := net.Dial("udp", "1.2.3.4:80")
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()

	localAddr := conn.LocalAddr().String()
	idx := strings.LastIndex(localAddr, ":")

	return localAddr[0:idx]
}

func fetchEmailAliases(url string) ([]Alias, error) {
	var httpClient = &http.Client{Timeout: 10 * time.Second}
	var aliases []Alias

	response, err := httpClient.Get(url)

	if response != nil {
		defer response.Body.Close()
	}

	if err != nil {
		return nil, err
	}

	if response.StatusCode != 200 {
		return nil, errors.New("failed to fetch aliases")
	}

	data, err := ioutil.ReadAll(response.Body)
	body := string(data)

	lines := strings.Split(body, "\n")

	for _, line := range lines {
		ix := strings.IndexAny(line, " \t")
		if ix > 0 {
			source := strings.TrimSpace(line[:ix])
			dest := strings.TrimSpace(line[ix+1:])
			alias := Alias{source, dest}
			aliases = append(aliases, alias)
		}
	}

	log.Printf("fetched %d aliases", len(aliases))

	return aliases, err
}

func getAlias(aliases []Alias, recipient string) (Alias, error) {
	var err error
	for _, alias := range aliases {
		if alias.Source == recipient {
			return alias, err
		}
	}
	return Alias{}, errors.New("recipient not found in alias table")
}

func getMX(domain_name string) string {
	config, _ := dns.ClientConfigFromFile("/etc/resolv.conf")
	c := new(dns.Client)
	m := new(dns.Msg)
	fqdn := domain_name + "."
	m.SetQuestion(fqdn, dns.TypeMX)
	m.RecursionDesired = true
	r, _, err := c.Exchange(m, config.Servers[0]+":"+config.Port)
	if err != nil {
		log.Println(err)
		return ""
	}
	if r.Rcode != dns.RcodeSuccess {
		log.Println("name lookup failed with code ", r.Rcode)
		return ""
	}

	for _, a := range r.Answer {
		if mx, ok := a.(*dns.MX); ok {
			str := mx.String()
			ix := strings.LastIndexAny(str, " \t")
			if ix > 0 && len(str) > 3 {
				str = strings.TrimSpace(str[ix+1:])
				return str[:len(str)-1]
			}
		}
	}

	return ""
}

func main() {
	var config Config

	flag.Parse()

	if *show_help != false {
		flag.PrintDefaults()
		os.Exit(0)
	}

	if *show_version != false {
		fmt.Println("Relayd v0.1.0")
		os.Exit(0)
	}

	if *config_file != "" {
		log.Println("loading", *config_file)
	}

	json_data, err := ioutil.ReadFile(*config_file)
	json.Unmarshal(json_data, &config)

	if err != nil {
		fmt.Println(err)
		os.Exit(-1)
	}

	if config.Host == "" {
		config.Host = *hostname
	}

	if config.Bind == "" {
		if *bind_interface == "" {
			config.Bind = GetOutboundIP()
		} else {
			config.Bind = *bind_interface
		}
	}

	if config.Port == "" {
		config.Port = strconv.Itoa(*bind_port)
	}

	if *cert_file != "" {
		config.Cert = *cert_file
	}

	if *cert_key != "" {
		config.Key = *cert_key
	}

	if config.Tls != "" {
		if config.Tls == "false" {
			*force_tls = false
		} else if config.Tls == "true" {
			*force_tls = true
		}
	}

	if config.Time != "" {
		i, strerr := strconv.Atoi(config.Time)
		if strerr == nil {
			*refresh_time = i
		}
	}

	if config.Url != "" {
		if *alias_url == "" {
			*alias_url = config.Url
		}
	}

	if *alias_url == "" {
		log.Fatal("need alias fetch url")
		os.Exit(-3)
	}

	log.Println("loading certificate", config.Cert, config.Key)
	cert, err := tls.LoadX509KeyPair(config.Cert, config.Key)

	if err != nil {
		fmt.Println(err)
		os.Exit(-4)
	}

	signal_chan := make(chan os.Signal, 1)
	signal.Notify(signal_chan, syscall.SIGHUP)

	aliases, err := fetchEmailAliases(*alias_url)

	go func() {
		for {
			s := <-signal_chan
			switch s {
			case syscall.SIGHUP:
				aliases, err = fetchEmailAliases(*alias_url)
			}
		}

	}()

	periodic := time.NewTicker(time.Duration(*refresh_time) * time.Second)
	go func() {
		for {
			select {
			case <-periodic.C:
				syscall.Kill(syscall.Getpid(), syscall.SIGHUP)
			}
		}
	}()

	server := &smtpd.Server{

		Hostname: config.Host,

		Handler: func(peer smtpd.Peer, env smtpd.Envelope) error {
			for _, recipient := range env.Recipients {

				alias, err := getAlias(aliases, recipient)

				if err == nil {
					log.Println("received email for " + recipient + " and forwarding to " + alias.Destination)

					ix := strings.Index(alias.Destination, "@")
					domain := alias.Destination[ix+1:]
					relay := getMX(domain)
					recipients := []string{alias.Destination}
					if relay != "" {
						mailhost := relay + ":smtp"
						return smtp.SendMail(
							mailhost,
							nil,
							env.Sender,
							recipients,
							env.Data,
						)
					}
				}
			}
			rcpt := strings.Join(env.Recipients, ",")
			return errors.New("recipient not found for " + rcpt)
		},

		RecipientChecker: func(peer smtpd.Peer, addr string) error {
			return nil
		},

		TLSConfig: &tls.Config{
			Certificates: []tls.Certificate{cert},
		},

		ForceTLS: *force_tls,
	}

	server_bind := config.Bind + ":" + config.Port
	log.Println("listening on " + server_bind)

	err = server.ListenAndServe(server_bind)

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

	log.Println("terminating")
}
<commit_msg>replaced smtp.SendMail<commit_after>package main

import (
	"bitbucket.org/chrj/smtpd"
	"crypto/tls"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"github.com/miekg/dns"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"net/smtp"
	"os"
	"os/signal"
	"strconv"
	"strings"
	"syscall"
	"time"
)

type Config struct {
	Cert string
	Key  string
	Host string
	Bind string
	Port string
	Tls  string
	Time string
	Url  string
}

type Alias struct {
	Source      string
	Destination string
}

var config_file = flag.String("c", "/etc/relayd/relayd.conf", "config file")
var cert_file = flag.String("cf", "", "certificate file")
var cert_key = flag.String("ck", "", "certificate key file")
var force_tls = flag.Bool("tls", true, "force tls")
var bind_port = flag.Int("p", 25, "server port")
var bind_interface = flag.String("i", "", "server interface")
var hostname = flag.String("h", "localhost.localdomain", "server hostname")
var refresh_time = flag.Int("r", 300, "refresh time in seconds")
var alias_url = flag.String("u", "", "aliases fetch url")
var show_help = flag.Bool("help", false, "show help")
var show_version = flag.Bool("version", false, "print version")

func init() {

}

func GetOutboundIP() string {
	conn, err := net.Dial("udp", "1.2.3.4:80")
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()

	localAddr := conn.LocalAddr().String()
	idx := strings.LastIndex(localAddr, ":")

	return localAddr[0:idx]
}

func fetchEmailAliases(url string) ([]Alias, error) {
	var httpClient = &http.Client{Timeout: 10 * time.Second}
	var aliases []Alias

	response, err := httpClient.Get(url)

	if response != nil {
		defer response.Body.Close()
	}

	if err != nil {
		return nil, err
	}

	if response.StatusCode != 200 {
		return nil, errors.New("failed to fetch aliases")
	}

	data, err := ioutil.ReadAll(response.Body)
	body := string(data)

	lines := strings.Split(body, "\n")

	for _, line := range lines {
		ix := strings.IndexAny(line, " \t")
		if ix > 0 {
			source := strings.TrimSpace(line[:ix])
			dest := strings.TrimSpace(line[ix+1:])
			alias := Alias{source, dest}
			aliases = append(aliases, alias)
		}
	}

	log.Printf("fetched %d aliases", len(aliases))

	return aliases, err
}

func getAlias(aliases []Alias, recipient string) (Alias, error) {
	var err error
	for _, alias := range aliases {
		if alias.Source == recipient {
			return alias, err
		}
	}
	return Alias{}, errors.New("recipient not found in alias table")
}

func getMX(domain_name string) string {
	config, _ := dns.ClientConfigFromFile("/etc/resolv.conf")
	c := new(dns.Client)
	m := new(dns.Msg)
	fqdn := domain_name + "."
	m.SetQuestion(fqdn, dns.TypeMX)
	m.RecursionDesired = true
	r, _, err := c.Exchange(m, config.Servers[0]+":"+config.Port)
	if err != nil {
		log.Println(err)
		return ""
	}
	if r.Rcode != dns.RcodeSuccess {
		log.Println("name lookup failed with code ", r.Rcode)
		return ""
	}

	for _, a := range r.Answer {
		if mx, ok := a.(*dns.MX); ok {
			str := mx.String()
			ix := strings.LastIndexAny(str, " \t")
			if ix > 0 && len(str) > 3 {
				str = strings.TrimSpace(str[ix+1:])
				return str[:len(str)-1]
			}
		}
	}

	return ""
}

func main() {
	var config Config

	flag.Parse()

	if *show_help != false {
		flag.PrintDefaults()
		os.Exit(0)
	}

	if *show_version != false {
		fmt.Println("Relayd v0.1.0")
		os.Exit(0)
	}

	if *config_file != "" {
		log.Println("loading", *config_file)
	}

	json_data, err := ioutil.ReadFile(*config_file)
	json.Unmarshal(json_data, &config)

	if err != nil {
		fmt.Println(err)
		os.Exit(-1)
	}

	if config.Host == "" {
		config.Host = *hostname
	}

	if config.Bind == "" {
		if *bind_interface == "" {
			config.Bind = GetOutboundIP()
		} else {
			config.Bind = *bind_interface
		}
	}

	if config.Port == "" {
		config.Port = strconv.Itoa(*bind_port)
	}

	if *cert_file != "" {
		config.Cert = *cert_file
	}

	if *cert_key != "" {
		config.Key = *cert_key
	}

	if config.Tls != "" {
		if config.Tls == "false" {
			*force_tls = false
		} else if config.Tls == "true" {
			*force_tls = true
		}
	}

	if config.Time != "" {
		i, strerr := strconv.Atoi(config.Time)
		if strerr == nil {
			*refresh_time = i
		}
	}

	if config.Url != "" {
		if *alias_url == "" {
			*alias_url = config.Url
		}
	}

	if *alias_url == "" {
		log.Fatal("need alias fetch url")
		os.Exit(-3)
	}

	log.Println("loading certificate", config.Cert, config.Key)
	cert, err := tls.LoadX509KeyPair(config.Cert, config.Key)

	if err != nil {
		fmt.Println(err)
		os.Exit(-4)
	}

	signal_chan := make(chan os.Signal, 1)
	signal.Notify(signal_chan, syscall.SIGHUP)

	aliases, err := fetchEmailAliases(*alias_url)

	go func() {
		for {
			s := <-signal_chan
			switch s {
			case syscall.SIGHUP:
				aliases, err = fetchEmailAliases(*alias_url)
			}
		}

	}()

	periodic := time.NewTicker(time.Duration(*refresh_time) * time.Second)
	go func() {
		for {
			select {
			case <-periodic.C:
				syscall.Kill(syscall.Getpid(), syscall.SIGHUP)
			}
		}
	}()

	server := &smtpd.Server{

		Hostname: config.Host,

		Handler: func(peer smtpd.Peer, env smtpd.Envelope) error {
			for _, recipient := range env.Recipients {

				// get alias email source -> destination
				alias, err := getAlias(aliases, recipient)

				if err == nil {
					ix := strings.Index(alias.Destination, "@")
					domain := alias.Destination[ix+1:]
					servername := getMX(domain)

					if servername != "" {
						log.Println("received email for " + recipient + " and forwarding to " + alias.Destination + " via " + servername)
						mailhost := servername + ":smtp"
						smtpConn, connErr := net.Dial("tcp", mailhost)

						if connErr != nil {
							log.Println("connect error for "+mailhost, connErr)
							return connErr
						}

						client, smtpErr := smtp.NewClient(smtpConn, servername)
						if smtpErr != nil {
							log.Println("failed to create client for "+mailhost, smtpErr)
							return smtpErr
						}
						err = client.Mail(env.Sender)
						if err != nil {
							log.Println("mail-from error", err)
							return err
						}
						err = client.Rcpt(alias.Destination)
						if err != nil {
							log.Println("rcpt-to error", err)
							return err
						}

						data, writeErr := client.Data()

						_, writeErr = data.Write(env.Data)

						if writeErr != nil {
							log.Println("failed to write data to "+mailhost, writeErr)
							return writeErr
						}

						data.Close()
						client.Quit()
					}
				}

			}
			return nil
		},

		RecipientChecker: func(peer smtpd.Peer, addr string) error {
			return nil
		},

		TLSConfig: &tls.Config{
			Certificates: []tls.Certificate{cert},
		},

		ForceTLS: *force_tls,
	}

	server_bind := config.Bind + ":" + config.Port
	log.Println("listening on " + server_bind)

	err = server.ListenAndServe(server_bind)

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

	log.Println("terminating")
}
<|endoftext|>


<commit_before>//  Copyright (c) 2014 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 main

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"

	"github.com/blevesearch/bleve"
	"github.com/blevesearch/bleve/document"
)

var bleveClientUnimplementedErr = errors.New("unimplemented")

// BleveClient implements the Search() and DocCount() subset of the
// bleve.Index interface by accessing a remote cbft server via REST
// protocol.  This allows callers to add a BleveClient as a target of
// a bleve.IndexAlias, and implements cbft protocol features like
// query consistency and auth.
//
// TODO: Implement propagating auth info in BleveClient.
type BleveClient struct {
	QueryURL    string
	CountURL    string
	Consistency *ConsistencyParams
}

func (r *BleveClient) Index(id string, data interface{}) error {
	return bleveClientUnimplementedErr
}

func (r *BleveClient) Delete(id string) error {
	return bleveClientUnimplementedErr
}

func (r *BleveClient) Batch(b *bleve.Batch) error {
	return bleveClientUnimplementedErr
}

func (r *BleveClient) Document(id string) (*document.Document, error) {
	return nil, bleveClientUnimplementedErr
}

func (r *BleveClient) DocCount() (uint64, error) {
	if r.CountURL == "" {
		return 0, fmt.Errorf("no CountURL provided")
	}
	resp, err := http.Get(r.CountURL)
	if err != nil {
		return 0, err
	}
	defer resp.Body.Close()
	if resp.StatusCode != 200 {
		return 0, fmt.Errorf("bleveClient.DocCount got status code: %d,"+
			" docCountURL: %s, resp: %#v", resp.StatusCode, r.CountURL, resp)
	}
	respBuf, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return 0, fmt.Errorf("bleveClient.DocCount error reading resp.Body,"+
			" docCountURL: %s, resp: %#v", r.CountURL, resp)
	}
	rv := struct {
		Status string `json:"status"`
		Count  uint64 `json:"count"`
	}{}
	err = json.Unmarshal(respBuf, &rv)
	if err != nil {
		return 0, fmt.Errorf("bleveClient.DocCount error parsing respBuf: %s,"+
			" docCountURL: %s, resp: %#v", respBuf, r.CountURL, resp)
	}
	return rv.Count, nil
}

func (r *BleveClient) Search(req *bleve.SearchRequest) (*bleve.SearchResult, error) {
	if r.QueryURL == "" {
		return nil, fmt.Errorf("no QueryURL provided")
	}

	bleveQueryParams := &BleveQueryParams{
		Query:       req,
		Consistency: r.Consistency,
	}

	buf, err := json.Marshal(bleveQueryParams)
	if err != nil {
		return nil, err
	}
	resp, err := http.Post(r.QueryURL, "application/json", bytes.NewBuffer(buf))
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	if resp.StatusCode != 200 {
		return nil, fmt.Errorf("bleveClient.Search got status code: %d,"+
			" searchURL: %s, req: %#v, resp: %#v",
			resp.StatusCode, r.QueryURL, req, resp)
	}
	respBuf, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("bleveClient.Search error reading resp.Body,"+
			" searchURL: %s, req: %#v, resp: %#v",
			r.QueryURL, req, resp)
	}
	rv := &bleve.SearchResult{}
	err = json.Unmarshal(respBuf, rv)
	if err != nil {
		return nil, fmt.Errorf("bleveClient.Search error parsing respBuf: %s,"+
			" searchURL: %s, req: %#v, resp: %#v",
			respBuf, r.QueryURL, req, resp)
	}
	return rv, nil
}

func (r *BleveClient) Fields() ([]string, error) {
	return nil, bleveClientUnimplementedErr
}

func (r *BleveClient) DumpAll() chan interface{} {
	return nil
}

func (r *BleveClient) DumpDoc(id string) chan interface{} {
	return nil
}

func (r *BleveClient) DumpFields() chan interface{} {
	return nil
}

func (r *BleveClient) Close() error {
	return bleveClientUnimplementedErr
}

func (r *BleveClient) Mapping() *bleve.IndexMapping {
	return nil
}

func (r *BleveClient) Stats() *bleve.IndexStat {
	return nil
}

func (r *BleveClient) GetInternal(key []byte) ([]byte, error) {
	return nil, bleveClientUnimplementedErr
}

func (r *BleveClient) SetInternal(key, val []byte) error {
	return bleveClientUnimplementedErr
}

func (r *BleveClient) DeleteInternal(key []byte) error {
	return bleveClientUnimplementedErr
}
<commit_msg>hook http.Post/Get for testability<commit_after>//  Copyright (c) 2014 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 main

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"

	"github.com/blevesearch/bleve"
	"github.com/blevesearch/bleve/document"
)

var httpPost = http.Post
var httpGet = http.Get

var bleveClientUnimplementedErr = errors.New("unimplemented")

// BleveClient implements the Search() and DocCount() subset of the
// bleve.Index interface by accessing a remote cbft server via REST
// protocol.  This allows callers to add a BleveClient as a target of
// a bleve.IndexAlias, and implements cbft protocol features like
// query consistency and auth.
//
// TODO: Implement propagating auth info in BleveClient.
type BleveClient struct {
	QueryURL    string
	CountURL    string
	Consistency *ConsistencyParams
}

func (r *BleveClient) Index(id string, data interface{}) error {
	return bleveClientUnimplementedErr
}

func (r *BleveClient) Delete(id string) error {
	return bleveClientUnimplementedErr
}

func (r *BleveClient) Batch(b *bleve.Batch) error {
	return bleveClientUnimplementedErr
}

func (r *BleveClient) Document(id string) (*document.Document, error) {
	return nil, bleveClientUnimplementedErr
}

func (r *BleveClient) DocCount() (uint64, error) {
	if r.CountURL == "" {
		return 0, fmt.Errorf("no CountURL provided")
	}
	resp, err := httpGet(r.CountURL)
	if err != nil {
		return 0, err
	}
	defer resp.Body.Close()
	if resp.StatusCode != 200 {
		return 0, fmt.Errorf("bleveClient.DocCount got status code: %d,"+
			" docCountURL: %s, resp: %#v", resp.StatusCode, r.CountURL, resp)
	}
	respBuf, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return 0, fmt.Errorf("bleveClient.DocCount error reading resp.Body,"+
			" docCountURL: %s, resp: %#v", r.CountURL, resp)
	}
	rv := struct {
		Status string `json:"status"`
		Count  uint64 `json:"count"`
	}{}
	err = json.Unmarshal(respBuf, &rv)
	if err != nil {
		return 0, fmt.Errorf("bleveClient.DocCount error parsing respBuf: %s,"+
			" docCountURL: %s, resp: %#v", respBuf, r.CountURL, resp)
	}
	return rv.Count, nil
}

func (r *BleveClient) Search(req *bleve.SearchRequest) (*bleve.SearchResult, error) {
	if r.QueryURL == "" {
		return nil, fmt.Errorf("no QueryURL provided")
	}

	bleveQueryParams := &BleveQueryParams{
		Query:       req,
		Consistency: r.Consistency,
	}

	buf, err := json.Marshal(bleveQueryParams)
	if err != nil {
		return nil, err
	}
	resp, err := httpPost(r.QueryURL, "application/json", bytes.NewBuffer(buf))
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	if resp.StatusCode != 200 {
		return nil, fmt.Errorf("bleveClient.Search got status code: %d,"+
			" searchURL: %s, req: %#v, resp: %#v",
			resp.StatusCode, r.QueryURL, req, resp)
	}
	respBuf, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("bleveClient.Search error reading resp.Body,"+
			" searchURL: %s, req: %#v, resp: %#v",
			r.QueryURL, req, resp)
	}
	rv := &bleve.SearchResult{}
	err = json.Unmarshal(respBuf, rv)
	if err != nil {
		return nil, fmt.Errorf("bleveClient.Search error parsing respBuf: %s,"+
			" searchURL: %s, req: %#v, resp: %#v",
			respBuf, r.QueryURL, req, resp)
	}
	return rv, nil
}

func (r *BleveClient) Fields() ([]string, error) {
	return nil, bleveClientUnimplementedErr
}

func (r *BleveClient) DumpAll() chan interface{} {
	return nil
}

func (r *BleveClient) DumpDoc(id string) chan interface{} {
	return nil
}

func (r *BleveClient) DumpFields() chan interface{} {
	return nil
}

func (r *BleveClient) Close() error {
	return bleveClientUnimplementedErr
}

func (r *BleveClient) Mapping() *bleve.IndexMapping {
	return nil
}

func (r *BleveClient) Stats() *bleve.IndexStat {
	return nil
}

func (r *BleveClient) GetInternal(key []byte) ([]byte, error) {
	return nil, bleveClientUnimplementedErr
}

func (r *BleveClient) SetInternal(key, val []byte) error {
	return bleveClientUnimplementedErr
}

func (r *BleveClient) DeleteInternal(key []byte) error {
	return bleveClientUnimplementedErr
}
<|endoftext|>


<commit_before>package blog

import (
	"fmt"
	"github.com/hoisie/web"
	"github.com/jmoiron/monet/app"
	"github.com/jmoiron/monet/db"
	"github.com/jmoiron/monet/template"
	"github.com/jmoiron/syndicate"
	"labix.org/v2/mgo/bson"
	"time"
)

var base = template.Base{Path: "base.mandira"}

// Attach the blog app frontend
func Attach(url string) {
	web.Get(url+"blog/page/(\\d+)", blogPage)
	web.Get(url+"blog/([^/]+)/", blogDetail)
	web.Get(url+"blog/", blogIndex)
	web.Get(url+"stream/page/(\\d+)", streamPage)
	web.Get(url+"stream/", streamIndex)
	web.Get(url+"blog/rss", rss)
	web.Get(url+"blog/atom", atom)
}

// Render the post, using the cached ContentRendered if available, or generating
// and re-saving it to the database if not
func RenderPost(post *Post) string {
	if len(post.ContentRendered) == 0 {
		db.Upsert(post)
	}
	return template.Render("blog/post.mandira", post)
}

// A Flatpage view.  Attach it via web.Get wherever you want flatpages to be available
func Flatpage(ctx *web.Context, url string) string {
	p := GetPage(url)
	if p == nil {
		ctx.Abort(404, "Page not found")
		return ""
	}

	return template.Render("base.mandira", M{
		"body":        p.ContentRendered,
		"title":       "jmoiron.net",
		"description": "Blog and assorted media from Jason Moiron.",
	})
}

func Index(s string) string {
	var post *Post
	var entry *Entry
	var posts []Post
	var entries []*Entry

	err := db.Latest(post, M{"published": 1}).Limit(7).All(&posts)
	if err != nil {
		fmt.Println(err)
	}
	err = db.Latest(entry, nil).Limit(4).All(&entries)
	if err != nil {
		fmt.Println(err)
	}

	post = &posts[0]
	return base.Render("index.mandira", M{
		"Post":        RenderPost(post),
		"Posts":       posts[1:],
		"Entries":     entries,
		"title":       "jmoiron.net",
		"description": post.Summary})
}

func blogIndex(ctx *web.Context) string {
	return blogPage(ctx, "1")
}

func blogPage(ctx *web.Context, page string) string {
	pn := app.PageNumber(page)
	perPage := 15
	paginator := app.NewPaginator(pn, perPage)
	paginator.Link = "/blog/page/"

	var post *Post
	var posts []Post
	// do a search, if required, of title and content
	var err error
	var numObjects int

	if len(ctx.Params["Search"]) > 0 {
		term := M{"$regex": ctx.Params["Search"]}
		search := M{"published": 1, "$or": []M{M{"title": term}, M{"content": term}}}
		err = db.Latest(post, search).Skip(paginator.Skip).Limit(perPage).All(&posts)
		numObjects, _ = db.Latest(post, search).Count()
	} else {
		err = db.Latest(post, M{"published": 1}).Skip(paginator.Skip).
			Limit(perPage).Iter().All(&posts)
		numObjects, _ = db.Find(post, M{"published": 1}).Count()
	}

	if err != nil {
		fmt.Println(err)
	}

	return base.Render("blog/index.mandira", M{
		"Posts": posts, "Pagination": paginator.Render(numObjects)}, ctx.Params)
}

func _createFeed() *syndicate.Feed {
	var posts []Post
	var post *Post

	err := db.Latest(post, M{"published": 1}).Limit(10).Iter().All(&posts)
	if err != nil {
		fmt.Println(err)
		return nil
	}

	feed := &syndicate.Feed{
		Title:       "jmoiron.net blog",
		Link:        &syndicate.Link{Href: "http://jmoiron.net"},
		Description: "the blog of Jason Moiron, all thoughts his own",
		Author:      &syndicate.Author{"Jason Moiron", "jmoiron@jmoiron.net"},
		Updated:     time.Now(),
	}

	for _, post := range posts {
		feed.Add(&syndicate.Item{
			Title:       post.Title,
			Link:        &syndicate.Link{Href: "http://jmoiron.net/blog/" + post.Slug + "/"},
			Description: post.ContentRendered,
			Created:     time.Unix(int64(post.Timestamp), 0),
		})
	}
	return feed
}

func atom(ctx *web.Context) string {
	feed := _createFeed()
	ctx.Header().Set("Content-Type", "application/xml")
	if feed == nil {
		return "<!-- error -->"
	}
	a := &syndicate.Atom{feed}
	af := a.AtomFeed()
	for _, e := range af.Entries {
		e.Content = e.Summary.Content
		e.Summary = nil
	}
	text, err := syndicate.ToXML(af)
	if err != nil {
		fmt.Println(err)
		return "<!-- error -->"
	}
	return text
}

func rss(ctx *web.Context) string {
	feed := _createFeed()
	ctx.Header().Set("Content-Type", "application/xml")
	if feed == nil {
		return "<!-- error -->"
	}
	text, err := feed.ToRss()
	if err != nil {
		fmt.Println(err)
		return "<!-- error -->"
	}
	return text
}

func blogDetail(ctx *web.Context, slug string) string {
	var post = new(Post)
	err := db.Find(post, M{"slug": slug}).One(&post)
	if err != nil {
		fmt.Println(err)
		ctx.Abort(404, "Page not found")
		return ""
	}

	return template.Render("base.mandira", M{
		"body":        RenderPost(post),
		"title":       post.Title,
		"description": post.Summary})
}

func streamIndex(ctx *web.Context) string {
	return streamPage(ctx, "1")
}

func streamPage(ctx *web.Context, page string) string {
	num := app.PageNumber(page)
	perPage := 25
	paginator := app.NewPaginator(num, perPage)
	paginator.Link = "/stream/page/"

	var entry *Entry
	var entries []*Entry

	// do a search, if required, of title and content
	var err error
	var numObjects int

	if len(ctx.Params["Search"]) > 0 {
		re := new(bson.RegEx)
		re.Pattern = ctx.Params["Search"]
		re.Options = "i"
		term := M{"$regex": re}
		search := M{"summaryrendered": term}
		//search := M{"$or": []M{M{"title": term}, M{"summaryrendered": term}}}
		err = db.Latest(entry, search).Skip(paginator.Skip).Limit(perPage).All(&entries)
		numObjects, _ = db.Latest(entry, search).Count()
	} else {
		err = db.Latest(entry, nil).Skip(paginator.Skip).Limit(perPage).Iter().All(&entries)
		numObjects, _ = db.Cursor(entry).Count()
	}

	if err != nil {
		fmt.Println(err)
	}

	return base.Render("blog/stream/index.mandira", M{
		"Entries":    entries,
		"Pagination": paginator.Render(numObjects),
		"title":      "Lifestream"}, ctx.Params)
}
<commit_msg>support new version of syndicate which uses content instead of summary and defaults to html type<commit_after>package blog

import (
	"fmt"
	"github.com/hoisie/web"
	"github.com/jmoiron/monet/app"
	"github.com/jmoiron/monet/db"
	"github.com/jmoiron/monet/template"
	"github.com/jmoiron/syndicate"
	"labix.org/v2/mgo/bson"
	"time"
)

var base = template.Base{Path: "base.mandira"}

// Attach the blog app frontend
func Attach(url string) {
	web.Get(url+"blog/page/(\\d+)", blogPage)
	web.Get(url+"blog/([^/]+)/", blogDetail)
	web.Get(url+"blog/", blogIndex)
	web.Get(url+"stream/page/(\\d+)", streamPage)
	web.Get(url+"stream/", streamIndex)
	web.Get(url+"blog/rss", rss)
	web.Get(url+"blog/atom", atom)
}

// Render the post, using the cached ContentRendered if available, or generating
// and re-saving it to the database if not
func RenderPost(post *Post) string {
	if len(post.ContentRendered) == 0 {
		db.Upsert(post)
	}
	return template.Render("blog/post.mandira", post)
}

// A Flatpage view.  Attach it via web.Get wherever you want flatpages to be available
func Flatpage(ctx *web.Context, url string) string {
	p := GetPage(url)
	if p == nil {
		ctx.Abort(404, "Page not found")
		return ""
	}

	return template.Render("base.mandira", M{
		"body":        p.ContentRendered,
		"title":       "jmoiron.net",
		"description": "Blog and assorted media from Jason Moiron.",
	})
}

func Index(s string) string {
	var post *Post
	var entry *Entry
	var posts []Post
	var entries []*Entry

	err := db.Latest(post, M{"published": 1}).Limit(7).All(&posts)
	if err != nil {
		fmt.Println(err)
	}
	err = db.Latest(entry, nil).Limit(4).All(&entries)
	if err != nil {
		fmt.Println(err)
	}

	post = &posts[0]
	return base.Render("index.mandira", M{
		"Post":        RenderPost(post),
		"Posts":       posts[1:],
		"Entries":     entries,
		"title":       "jmoiron.net",
		"description": post.Summary})
}

func blogIndex(ctx *web.Context) string {
	return blogPage(ctx, "1")
}

func blogPage(ctx *web.Context, page string) string {
	pn := app.PageNumber(page)
	perPage := 15
	paginator := app.NewPaginator(pn, perPage)
	paginator.Link = "/blog/page/"

	var post *Post
	var posts []Post
	// do a search, if required, of title and content
	var err error
	var numObjects int

	if len(ctx.Params["Search"]) > 0 {
		term := M{"$regex": ctx.Params["Search"]}
		search := M{"published": 1, "$or": []M{M{"title": term}, M{"content": term}}}
		err = db.Latest(post, search).Skip(paginator.Skip).Limit(perPage).All(&posts)
		numObjects, _ = db.Latest(post, search).Count()
	} else {
		err = db.Latest(post, M{"published": 1}).Skip(paginator.Skip).
			Limit(perPage).Iter().All(&posts)
		numObjects, _ = db.Find(post, M{"published": 1}).Count()
	}

	if err != nil {
		fmt.Println(err)
	}

	return base.Render("blog/index.mandira", M{
		"Posts": posts, "Pagination": paginator.Render(numObjects)}, ctx.Params)
}

func _createFeed() *syndicate.Feed {
	var posts []Post
	var post *Post

	err := db.Latest(post, M{"published": 1}).Limit(10).Iter().All(&posts)
	if err != nil {
		fmt.Println(err)
		return nil
	}

	feed := &syndicate.Feed{
		Title:       "jmoiron.net blog",
		Link:        &syndicate.Link{Href: "http://jmoiron.net"},
		Description: "the blog of Jason Moiron, all thoughts his own",
		Author:      &syndicate.Author{"Jason Moiron", "jmoiron@jmoiron.net"},
		Updated:     time.Now(),
	}

	for _, post := range posts {
		feed.Add(&syndicate.Item{
			Title:       post.Title,
			Link:        &syndicate.Link{Href: "http://jmoiron.net/blog/" + post.Slug + "/"},
			Description: post.ContentRendered,
			Created:     time.Unix(int64(post.Timestamp), 0),
		})
	}
	return feed
}

func atom(ctx *web.Context) string {
	feed := _createFeed()
	ctx.Header().Set("Content-Type", "application/xml")
	if feed == nil {
		return "<!-- error -->"
	}
	text, err := feed.ToAtom()
	if err != nil {
		fmt.Println(err)
		return "<!-- error -->"
	}
	return text
}

func rss(ctx *web.Context) string {
	feed := _createFeed()
	ctx.Header().Set("Content-Type", "application/xml")
	if feed == nil {
		return "<!-- error -->"
	}
	text, err := feed.ToRss()
	if err != nil {
		fmt.Println(err)
		return "<!-- error -->"
	}
	return text
}

func blogDetail(ctx *web.Context, slug string) string {
	var post = new(Post)
	err := db.Find(post, M{"slug": slug}).One(&post)
	if err != nil {
		fmt.Println(err)
		ctx.Abort(404, "Page not found")
		return ""
	}

	return template.Render("base.mandira", M{
		"body":        RenderPost(post),
		"title":       post.Title,
		"description": post.Summary})
}

func streamIndex(ctx *web.Context) string {
	return streamPage(ctx, "1")
}

func streamPage(ctx *web.Context, page string) string {
	num := app.PageNumber(page)
	perPage := 25
	paginator := app.NewPaginator(num, perPage)
	paginator.Link = "/stream/page/"

	var entry *Entry
	var entries []*Entry

	// do a search, if required, of title and content
	var err error
	var numObjects int

	if len(ctx.Params["Search"]) > 0 {
		re := new(bson.RegEx)
		re.Pattern = ctx.Params["Search"]
		re.Options = "i"
		term := M{"$regex": re}
		search := M{"summaryrendered": term}
		//search := M{"$or": []M{M{"title": term}, M{"summaryrendered": term}}}
		err = db.Latest(entry, search).Skip(paginator.Skip).Limit(perPage).All(&entries)
		numObjects, _ = db.Latest(entry, search).Count()
	} else {
		err = db.Latest(entry, nil).Skip(paginator.Skip).Limit(perPage).Iter().All(&entries)
		numObjects, _ = db.Cursor(entry).Count()
	}

	if err != nil {
		fmt.Println(err)
	}

	return base.Render("blog/stream/index.mandira", M{
		"Entries":    entries,
		"Pagination": paginator.Render(numObjects),
		"title":      "Lifestream"}, ctx.Params)
}
<|endoftext|>


<commit_before>// Copyright (c) 2015, Peter Mrekaj. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE.txt file.

package ptypes

import (
	"math"
	"testing"
)

func TestReverseInt(t *testing.T) {
	for _, test := range []struct {
		in   int64
		want int64
		ok   bool
	}{
		{0, 0, true},
		{1, 1, true},
		{-1, -1, true},
		{-10, -1, true},
		{1234, 4321, true},
		{-1234, -4321, true},
		{math.MaxInt64, 7085774586302733229, true},
		{7085774586302733229, math.MaxInt64, true},
		{math.MinInt64, -8085774586302733229, true},
		{-8085774586302733229, math.MinInt64, true},
		{8085774586302733229, 0, false},
		{-9085774586302733229, 0, false},
	} {
		if got, ok := ReverseInt(test.in); got != test.want || ok != test.ok {
			t.Errorf("ReverseInt(%d) = %d, %t; want %d, %t", test.in, got, ok, test.want, test.ok)
		}
	}
}

func benchReverseInt(b *testing.B, size int) {
	x := int64(size)
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		ReverseInt(x)
	}
}

func BenchmarkReverseInt1e6(b *testing.B)  { benchReverseInt(b, 1e6) }
func BenchmarkReverseInt1e12(b *testing.B) { benchReverseInt(b, 1e12) }
func BenchmarkReverseInt1e18(b *testing.B) { benchReverseInt(b, 1e18) }
<commit_msg>Remove unnecessary casting<commit_after>// Copyright (c) 2015, Peter Mrekaj. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE.txt file.

package ptypes

import (
	"math"
	"testing"
)

func TestReverseInt(t *testing.T) {
	for _, test := range []struct {
		in   int64
		want int64
		ok   bool
	}{
		{0, 0, true},
		{1, 1, true},
		{-1, -1, true},
		{-10, -1, true},
		{1234, 4321, true},
		{-1234, -4321, true},
		{math.MaxInt64, 7085774586302733229, true},
		{7085774586302733229, math.MaxInt64, true},
		{math.MinInt64, -8085774586302733229, true},
		{-8085774586302733229, math.MinInt64, true},
		{8085774586302733229, 0, false},
		{-9085774586302733229, 0, false},
	} {
		if got, ok := ReverseInt(test.in); got != test.want || ok != test.ok {
			t.Errorf("ReverseInt(%d) = %d, %t; want %d, %t", test.in, got, ok, test.want, test.ok)
		}
	}
}

func benchReverseInt(b *testing.B, size int64) {
	for i := 0; i < b.N; i++ {
		ReverseInt(size)
	}
}

func BenchmarkReverseInt1e6(b *testing.B)  { benchReverseInt(b, 1e6) }
func BenchmarkReverseInt1e12(b *testing.B) { benchReverseInt(b, 1e12) }
func BenchmarkReverseInt1e18(b *testing.B) { benchReverseInt(b, 1e18) }
<|endoftext|>


<commit_before>// Copyright 2015 Ka-Hing Cheung
// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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 internal

import (
	"os"
	"strings"
	"time"

	"github.com/codegangsta/cli"
)

// Set up custom help text for goofys; in particular the usage section.
func init() {
	cli.AppHelpTemplate = `NAME:
   {{.Name}} - {{.Usage}}

USAGE:
   {{.Name}} {{if .Flags}}[global options]{{end}} bucket mountpoint
   {{if .Version}}
VERSION:
   {{.Version}}
   {{end}}{{if len .Authors}}
AUTHOR(S):
   {{range .Authors}}{{ . }}{{end}}
   {{end}}{{if .Commands}}
COMMANDS:
   {{range .Commands}}{{join .Names ", "}}{{ "\t" }}{{.Usage}}
   {{end}}{{end}}{{if .Flags}}
GLOBAL OPTIONS:
   {{range .Flags}}{{.}}
   {{end}}{{end}}{{if .Copyright }}
COPYRIGHT:
   {{.Copyright}}
   {{end}}
`
}

func NewApp() (app *cli.App) {
	uid, gid := MyUserAndGroup()

	app = &cli.App{
		Name:     "goofys",
		Version:  "0.0.4",
		Usage:    "Mount an S3 bucket locally",
		HideHelp: true,
		Writer:   os.Stderr,
		Flags: []cli.Flag{

			cli.BoolFlag{
				Name:  "help, h",
				Usage: "Print this help text and exit successfuly.",
			},

			/////////////////////////
			// File system
			/////////////////////////

			cli.StringSliceFlag{
				Name:  "o",
				Usage: "Additional system-specific mount options. Be careful!",
			},

			cli.IntFlag{
				Name:  "dir-mode",
				Value: 0755,
				Usage: "Permissions bits for directories. (default: 0755)",
			},

			cli.IntFlag{
				Name:  "file-mode",
				Value: 0644,
				Usage: "Permission bits for files (default: 0644)",
			},

			cli.IntFlag{
				Name:  "uid",
				Value: uid,
				Usage: "UID owner of all inodes.",
			},

			cli.IntFlag{
				Name:  "gid",
				Value: gid,
				Usage: "GID owner of all inodes.",
			},

			/////////////////////////
			// S3
			/////////////////////////

			cli.StringFlag{
				Name:  "endpoint",
				Value: "",
				Usage: "The non-AWS endpoint to connect to." +
					" Possible values: http://127.0.0.1:8081/",
			},

			cli.StringFlag{
				Name:  "region",
				Value: "us-west-2",
				Usage: "The non-AWS endpoint to connect to." +
					" Possible values: us-east-1, us-west-1, us-west-2, eu-west-1, " +
					"eu-central-1, ap-southeast-1, ap-southeast-2, ap-northeast-1, " +
					"sa-east-1, cn-north-1",
			},

			cli.StringFlag{
				Name:  "storage-class",
				Value: "STANDARD",
				Usage: "The type of storage to use when writing objects." +
					" Possible values: REDUCED_REDUNDANCY, STANDARD (default), STANDARD_IA.",
			},

			cli.BoolFlag{
				Name: "use-path-request",
				Usage: "Use a path-style request instead of virtual host-style." +
					" (deprecated, always on)",
			},

			cli.StringFlag{
				Name:  "profile",
				Usage: "Use a named profile from $HOME/.aws/credentials instead of \"default\"",
			},

			/////////////////////////
			// Tuning
			/////////////////////////

			cli.DurationFlag{
				Name:  "stat-cache-ttl",
				Value: time.Minute,
				Usage: "How long to cache StatObject results and inode attributes.",
			},

			cli.DurationFlag{
				Name:  "type-cache-ttl",
				Value: time.Minute,
				Usage: "How long to cache name -> file/dir mappings in directory " +
					"inodes.",
			},

			/////////////////////////
			// Debugging
			/////////////////////////

			cli.BoolFlag{
				Name:  "debug_fuse",
				Usage: "Enable fuse-related debugging output.",
			},

			cli.BoolFlag{
				Name:  "debug_s3",
				Usage: "Enable S3-related debugging output.",
			},

			cli.BoolFlag{
				Name:  "f",
				Usage: "Run goofys in foreground.",
			},
		},
	}

	return
}

type FlagStorage struct {
	// File system
	MountOptions map[string]string
	DirMode      os.FileMode
	FileMode     os.FileMode
	Uid          uint32
	Gid          uint32

	// S3
	Endpoint       string
	Region         string
	StorageClass   string
	UsePathRequest bool
	Profile        string

	// Tuning
	StatCacheTTL time.Duration
	TypeCacheTTL time.Duration

	// Debugging
	DebugFuse  bool
	DebugS3    bool
	Foreground bool
}

func parseOptions(m map[string]string, s string) {
	// NOTE(jacobsa): The man pages don't define how escaping works, and as far
	// as I can tell there is no way to properly escape or quote a comma in the
	// options list for an fstab entry. So put our fingers in our ears and hope
	// that nobody needs a comma.
	for _, p := range strings.Split(s, ",") {
		var name string
		var value string

		// Split on the first equals sign.
		if equalsIndex := strings.IndexByte(p, '='); equalsIndex != -1 {
			name = p[:equalsIndex]
			value = p[equalsIndex+1:]
		} else {
			name = p
		}

		m[name] = value
	}

	return
}

// Add the flags accepted by run to the supplied flag set, returning the
// variables into which the flags will parse.
func PopulateFlags(c *cli.Context) (flags *FlagStorage) {
	flags = &FlagStorage{
		// File system
		MountOptions: make(map[string]string),
		DirMode:      os.FileMode(c.Int("dir-mode")),
		FileMode:     os.FileMode(c.Int("file-mode")),
		Uid:          uint32(c.Int("uid")),
		Gid:          uint32(c.Int("gid")),

		// Tuning,
		StatCacheTTL: c.Duration("stat-cache-ttl"),
		TypeCacheTTL: c.Duration("type-cache-ttl"),

		// S3
		Endpoint:       c.String("endpoint"),
		Region:         c.String("region"),
		StorageClass:   c.String("storage-class"),
		UsePathRequest: c.Bool("use-path-request"),
		Profile:        c.String("profile"),

		// Debugging,
		DebugFuse:  c.Bool("debug_fuse"),
		DebugS3:    c.Bool("debug_s3"),
		Foreground: c.Bool("f"),
	}

	// Handle the repeated "-o" flag.
	for _, o := range c.StringSlice("o") {
		parseOptions(flags.MountOptions, o)
	}
	return
}

func MassageMountFlags(args []string) (ret []string) {
	if len(args) == 5 && args[3] == "-o" {
		// looks like it's coming from fstab!
		mountOptions := ""
		ret = append(ret, args[0])

		for _, p := range strings.Split(args[4], ",") {
			if strings.HasPrefix(p, "-") {
				ret = append(ret, p)
			} else {
				mountOptions += p
				mountOptions += ","
			}
		}

		if len(mountOptions) != 0 {
			// remove trailing ,
			mountOptions = mountOptions[:len(mountOptions)-1]
			ret = append(ret, "-o")
			ret = append(ret, mountOptions)
		}

		ret = append(ret, args[1])
		ret = append(ret, args[2])
	} else {
		return args
	}

	return
}
<commit_msg>v0.0.5<commit_after>// Copyright 2015 Ka-Hing Cheung
// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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 internal

import (
	"os"
	"strings"
	"time"

	"github.com/codegangsta/cli"
)

// Set up custom help text for goofys; in particular the usage section.
func init() {
	cli.AppHelpTemplate = `NAME:
   {{.Name}} - {{.Usage}}

USAGE:
   {{.Name}} {{if .Flags}}[global options]{{end}} bucket mountpoint
   {{if .Version}}
VERSION:
   {{.Version}}
   {{end}}{{if len .Authors}}
AUTHOR(S):
   {{range .Authors}}{{ . }}{{end}}
   {{end}}{{if .Commands}}
COMMANDS:
   {{range .Commands}}{{join .Names ", "}}{{ "\t" }}{{.Usage}}
   {{end}}{{end}}{{if .Flags}}
GLOBAL OPTIONS:
   {{range .Flags}}{{.}}
   {{end}}{{end}}{{if .Copyright }}
COPYRIGHT:
   {{.Copyright}}
   {{end}}
`
}

func NewApp() (app *cli.App) {
	uid, gid := MyUserAndGroup()

	app = &cli.App{
		Name:     "goofys",
		Version:  "0.0.5",
		Usage:    "Mount an S3 bucket locally",
		HideHelp: true,
		Writer:   os.Stderr,
		Flags: []cli.Flag{

			cli.BoolFlag{
				Name:  "help, h",
				Usage: "Print this help text and exit successfuly.",
			},

			/////////////////////////
			// File system
			/////////////////////////

			cli.StringSliceFlag{
				Name:  "o",
				Usage: "Additional system-specific mount options. Be careful!",
			},

			cli.IntFlag{
				Name:  "dir-mode",
				Value: 0755,
				Usage: "Permissions bits for directories. (default: 0755)",
			},

			cli.IntFlag{
				Name:  "file-mode",
				Value: 0644,
				Usage: "Permission bits for files (default: 0644)",
			},

			cli.IntFlag{
				Name:  "uid",
				Value: uid,
				Usage: "UID owner of all inodes.",
			},

			cli.IntFlag{
				Name:  "gid",
				Value: gid,
				Usage: "GID owner of all inodes.",
			},

			/////////////////////////
			// S3
			/////////////////////////

			cli.StringFlag{
				Name:  "endpoint",
				Value: "",
				Usage: "The non-AWS endpoint to connect to." +
					" Possible values: http://127.0.0.1:8081/",
			},

			cli.StringFlag{
				Name:  "region",
				Value: "us-west-2",
				Usage: "The non-AWS endpoint to connect to." +
					" Possible values: us-east-1, us-west-1, us-west-2, eu-west-1, " +
					"eu-central-1, ap-southeast-1, ap-southeast-2, ap-northeast-1, " +
					"sa-east-1, cn-north-1",
			},

			cli.StringFlag{
				Name:  "storage-class",
				Value: "STANDARD",
				Usage: "The type of storage to use when writing objects." +
					" Possible values: REDUCED_REDUNDANCY, STANDARD (default), STANDARD_IA.",
			},

			cli.BoolFlag{
				Name: "use-path-request",
				Usage: "Use a path-style request instead of virtual host-style." +
					" (deprecated, always on)",
			},

			cli.StringFlag{
				Name:  "profile",
				Usage: "Use a named profile from $HOME/.aws/credentials instead of \"default\"",
			},

			/////////////////////////
			// Tuning
			/////////////////////////

			cli.DurationFlag{
				Name:  "stat-cache-ttl",
				Value: time.Minute,
				Usage: "How long to cache StatObject results and inode attributes.",
			},

			cli.DurationFlag{
				Name:  "type-cache-ttl",
				Value: time.Minute,
				Usage: "How long to cache name -> file/dir mappings in directory " +
					"inodes.",
			},

			/////////////////////////
			// Debugging
			/////////////////////////

			cli.BoolFlag{
				Name:  "debug_fuse",
				Usage: "Enable fuse-related debugging output.",
			},

			cli.BoolFlag{
				Name:  "debug_s3",
				Usage: "Enable S3-related debugging output.",
			},

			cli.BoolFlag{
				Name:  "f",
				Usage: "Run goofys in foreground.",
			},
		},
	}

	return
}

type FlagStorage struct {
	// File system
	MountOptions map[string]string
	DirMode      os.FileMode
	FileMode     os.FileMode
	Uid          uint32
	Gid          uint32

	// S3
	Endpoint       string
	Region         string
	StorageClass   string
	UsePathRequest bool
	Profile        string

	// Tuning
	StatCacheTTL time.Duration
	TypeCacheTTL time.Duration

	// Debugging
	DebugFuse  bool
	DebugS3    bool
	Foreground bool
}

func parseOptions(m map[string]string, s string) {
	// NOTE(jacobsa): The man pages don't define how escaping works, and as far
	// as I can tell there is no way to properly escape or quote a comma in the
	// options list for an fstab entry. So put our fingers in our ears and hope
	// that nobody needs a comma.
	for _, p := range strings.Split(s, ",") {
		var name string
		var value string

		// Split on the first equals sign.
		if equalsIndex := strings.IndexByte(p, '='); equalsIndex != -1 {
			name = p[:equalsIndex]
			value = p[equalsIndex+1:]
		} else {
			name = p
		}

		m[name] = value
	}

	return
}

// Add the flags accepted by run to the supplied flag set, returning the
// variables into which the flags will parse.
func PopulateFlags(c *cli.Context) (flags *FlagStorage) {
	flags = &FlagStorage{
		// File system
		MountOptions: make(map[string]string),
		DirMode:      os.FileMode(c.Int("dir-mode")),
		FileMode:     os.FileMode(c.Int("file-mode")),
		Uid:          uint32(c.Int("uid")),
		Gid:          uint32(c.Int("gid")),

		// Tuning,
		StatCacheTTL: c.Duration("stat-cache-ttl"),
		TypeCacheTTL: c.Duration("type-cache-ttl"),

		// S3
		Endpoint:       c.String("endpoint"),
		Region:         c.String("region"),
		StorageClass:   c.String("storage-class"),
		UsePathRequest: c.Bool("use-path-request"),
		Profile:        c.String("profile"),

		// Debugging,
		DebugFuse:  c.Bool("debug_fuse"),
		DebugS3:    c.Bool("debug_s3"),
		Foreground: c.Bool("f"),
	}

	// Handle the repeated "-o" flag.
	for _, o := range c.StringSlice("o") {
		parseOptions(flags.MountOptions, o)
	}
	return
}

func MassageMountFlags(args []string) (ret []string) {
	if len(args) == 5 && args[3] == "-o" {
		// looks like it's coming from fstab!
		mountOptions := ""
		ret = append(ret, args[0])

		for _, p := range strings.Split(args[4], ",") {
			if strings.HasPrefix(p, "-") {
				ret = append(ret, p)
			} else {
				mountOptions += p
				mountOptions += ","
			}
		}

		if len(mountOptions) != 0 {
			// remove trailing ,
			mountOptions = mountOptions[:len(mountOptions)-1]
			ret = append(ret, "-o")
			ret = append(ret, mountOptions)
		}

		ret = append(ret, args[1])
		ret = append(ret, args[2])
	} else {
		return args
	}

	return
}
<|endoftext|>


<commit_before>// Copyright © 2017 Kent Gibson <warthog618@gmail.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

//
// Test suite for interrupt module.
//
// Tests use Raspberry Pi J8 pins 15 and 16 which must be jumpered together.
//
package gpio

import (
	"errors"
	"testing"
	"time"
)

func waitInterrupt(ch chan int, timeout time.Duration) (int, error) {
	expired := make(chan bool)
	go func() {
		time.Sleep(timeout)
		close(expired)
	}()
	select {
	case v := <-ch:
		return v, nil
	case <-expired:
		return 0, errors.New("timeout")
	}
}

func setupIntr(t *testing.T) (pinIn *Pin, pinOut *Pin, watcher *Watcher) {
	if err := Open(); err != nil {
		t.Fatal("Open returned error", err)
	}
	pinIn = NewPin(J8p15)
	pinOut = NewPin(J8p16)
	watcher = getDefaultWatcher()
	pinIn.SetMode(Input)
	pinOut.Write(Low)
	pinOut.SetMode(Output)
	return
}

func teardownIntr(pinIn *Pin, pinOut *Pin, watcher *Watcher) {
	pinOut.SetMode(Input)
	watcher.UnregisterPin(pinIn)
	Close()
}

func TestRegister(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	defer teardownIntr(pinIn, pinOut, watcher)
	ich := make(chan int)
	count := 0
	err := watcher.RegisterPin(pinIn, EdgeRising, func(pin *Pin) {
		count++
		ich <- count
	})
	if err != nil {
		t.Fatal("Registration failed", err)
	}
	v, err := waitInterrupt(ich, time.Millisecond)
	if err != nil {
		t.Error("No initial interrupt")
	}
	if v != 1 {
		t.Error("Incorrect count", v)
	}
	_, err = waitInterrupt(ich, time.Millisecond)
	if err == nil {
		t.Error("Spurious interrupt")
	}
}

func TestReregister(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	defer teardownIntr(pinIn, pinOut, watcher)
	ich := make(chan int)
	if err := watcher.RegisterPin(pinIn, EdgeRising, func(pin *Pin) {
		ich <- 1
	}); err != nil {
		t.Fatal("Registration failed", err)
	}
	v, err := waitInterrupt(ich, time.Millisecond)
	if err != nil {
		t.Error("No initial interrupt")
	}
	if v != 1 {
		t.Error("Incorrect count", v)
	}
	if err = watcher.RegisterPin(pinIn, EdgeRising, func(pin *Pin) {
		ich <- 2
	}); err == nil {
		t.Fatal("Reregistration didn't fail.")
	}
	pinOut.High()
	v, err = waitInterrupt(ich, time.Millisecond)
	switch {
	case err != nil:
		t.Error("Didn't call handler")
	case v != 1:
		t.Error("Called new handler")
	}
}

func TestUnregister(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	defer teardownIntr(pinIn, pinOut, watcher)
	ich := make(chan int)
	err := watcher.RegisterPin(pinIn, EdgeRising, func(pin *Pin) {
		ich <- 1
	})
	if err != nil {
		t.Fatal("Registration failed", err)
	}
	v, err := waitInterrupt(ich, time.Millisecond)
	if err != nil {
		t.Error("No initial interrupt")
	}
	if v != 1 {
		t.Error("Incorrect count", v)
	}
	watcher.UnregisterPin(pinIn)
	pinOut.High()
	_, err = waitInterrupt(ich, time.Millisecond)
	if err == nil {
		t.Error("Called old handler")
	}
	// And again just for coverage.
	watcher.UnregisterPin(pinIn)
}

func TestEdgeRising(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	defer teardownIntr(pinIn, pinOut, watcher)
	ich := make(chan int)
	err := watcher.RegisterPin(pinIn, EdgeRising, func(pin *Pin) {
		if pin.Read() == High {
			ich <- 1
		} else {
			ich <- 0
		}
	})
	if err != nil {
		t.Fatal("Registration failed", err)
	}
	v, err := waitInterrupt(ich, time.Millisecond)
	if err != nil {
		t.Error("No initial interrupt")
	}
	if v != 0 {
		t.Error("Incorrect initial value", v)
	}
	// Can take a while for the init to be applied before it starts triggering
	// interrupts, so wait a bit...
	time.Sleep(time.Millisecond)
	for i := 0; i < 10; i++ {
		pinOut.High()
		v, err := waitInterrupt(ich, time.Millisecond)
		if err != nil {
			t.Error("Missed high at", i)
		} else if v == 0 {
			t.Error("Triggered while low at", i)
		}
		pinOut.Low()
		_, err = waitInterrupt(ich, time.Millisecond)
		if err == nil {
			t.Error("Spurious or delayed trigger at", i)
		}
	}
}

func TestEdgeFalling(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	defer teardownIntr(pinIn, pinOut, watcher)
	ich := make(chan int)
	err := watcher.RegisterPin(pinIn, EdgeFalling, func(pin *Pin) {
		if pin.Read() == High {
			ich <- 1
		} else {
			ich <- 0
		}
	})
	if err != nil {
		t.Fatal("Registration failed", err)
	}
	v, err := waitInterrupt(ich, time.Millisecond)
	if err != nil {
		t.Error("No initial interrupt")
	}
	if v != 0 {
		t.Error("Incorrect initial value", v)
	}
	for i := 0; i < 10; i++ {
		pinOut.High()
		_, err := waitInterrupt(ich, time.Millisecond)
		if err == nil {
			t.Error("Spurious or delayed trigger at", i)
		}
		pinOut.Low()
		v, err = waitInterrupt(ich, time.Millisecond)
		if err != nil {
			t.Error("Missed low at", i)
		} else if v == 1 {
			t.Error("Triggered while low at", i)
		}
	}
}

func TestEdgeBoth(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	defer teardownIntr(pinIn, pinOut, watcher)
	ich := make(chan int)
	err := watcher.RegisterPin(pinIn, EdgeBoth, func(pin *Pin) {
		if pin.Read() == High {
			ich <- 1
		} else {
			ich <- 0
		}
	})
	if err != nil {
		t.Fatal("Registration failed", err)
	}
	v, err := waitInterrupt(ich, time.Millisecond)
	if err != nil {
		t.Error("No initial interrupt")
	}
	if v != 0 {
		t.Error("Incorrect initial value", v)
	}
	for i := 0; i < 10; i++ {
		pinOut.High()
		v, err := waitInterrupt(ich, time.Millisecond)
		if err != nil {
			t.Error("Missed high at", i)
		} else if v == 0 {
			t.Error("Triggered while low at", i)
		}
		pinOut.Low()
		v, err = waitInterrupt(ich, time.Millisecond)
		if err != nil {
			t.Error("Missed low at", i)
		} else if v == 1 {
			t.Error("Triggered while high at", i)
		}
	}
}

func TestEdgeNone(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	defer teardownIntr(pinIn, pinOut, watcher)
	ich := make(chan int)
	err := watcher.RegisterPin(pinIn, EdgeNone, func(pin *Pin) {
		if pin.Read() == High {
			ich <- 1
		} else {
			ich <- 0
		}
	})
	if err != nil {
		t.Fatal("Registration failed", err)
	}
	v, err := waitInterrupt(ich, time.Millisecond)
	if err != nil {
		t.Error("No initial interrupt")
	}
	if v != 0 {
		t.Error("Incorrect initial value", v)
	}
	for i := 0; i < 10; i++ {
		pinOut.High()
		v, err := waitInterrupt(ich, time.Millisecond)
		if err == nil {
			t.Error("Spurious or delayed trigger at", i, v)
		}
		pinOut.Low()
		v, err = waitInterrupt(ich, time.Millisecond)
		if err == nil {
			t.Error("Spurious or delayed trigger at", i, v)
		}
	}
}

func TestUnexportedEdge(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	err := setEdge(pinIn, EdgeNone)
	if err == nil {
		t.Error("Edge should fail unless pin exported first.")
	}
	defer teardownIntr(pinIn, pinOut, watcher)
}

func TestCloseInterrupts(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	defer teardownIntr(pinIn, pinOut, watcher)
	ich := make(chan int)
	err := watcher.RegisterPin(pinIn, EdgeNone, func(pin *Pin) {
		if pin.Read() == High {
			ich <- 1
		} else {
			ich <- 0
		}
	})
	if err != nil {
		t.Fatal("Registration failed", err)
	}
	closeInterrupts()
	v, err := waitInterrupt(ich, time.Millisecond)
	if err == nil {
		t.Error("Spurious interrupt during close", v)
	}
	pinOut.High()
	v, err = waitInterrupt(ich, time.Millisecond)
	if err == nil {
		t.Error("Interrupts still active after close", v)
	}
}

func TestWatchExists(t *testing.T) {
	if err := Open(); err != nil {
		t.Fatal("Open returned error", err)
	}
	defer Close()
	pinIn := NewPin(J8p15)
	pinIn.SetMode(Input)
	count := 0
	if err := pinIn.Watch(EdgeFalling, func(pin *Pin) {
		count++
	}); err != nil {
		t.Fatal("Watch returned error", err)
	}
	if err := pinIn.Watch(EdgeFalling, func(pin *Pin) {
		count++
	}); err == nil {
		t.Error("Watch didn't return error")
	}
	time.Sleep(2 * time.Millisecond)
	if count != 1 {
		t.Error("Second handler called")
	}
}

// Looped tests require a jumper across Raspberry Pi J8 pins 15 and 16.
// This is just a smoke test for the Watch and Unwatch methods.
func TestWatchLooped(t *testing.T) {
	if err := Open(); err != nil {
		t.Fatal("Open returned error", err)
	}
	defer Close()
	pinIn := NewPin(J8p15)
	pinOut := NewPin(J8p16)
	pinIn.SetMode(Input)
	defer pinOut.SetMode(Input)
	pinOut.Write(Low)
	pinOut.SetMode(Output)
	mode := pinOut.Mode()
	if mode != Output {
		t.Fatal("Failed to set output")
	}
	called := false
	if err := pinIn.Watch(EdgeFalling, func(pin *Pin) {
		called = true
	}); err != nil {
		t.Fatal("Watch returned error", err)
	}
	time.Sleep(2 * time.Millisecond)
	if called == false {
		t.Error("Watcher not called with initial value.")
	}
	called = false
	pinOut.High()
	time.Sleep(2 * time.Millisecond)
	if called {
		t.Error("Spurious Watcher called.")
		called = false
	}
	pinOut.Low()
	time.Sleep(2 * time.Millisecond)
	if called == false {
		t.Error("Watcher not called.")
	}
	pinIn.Unwatch()
	called = false
	pinOut.High()
	pinOut.Low()
	time.Sleep(2 * time.Millisecond)
	if called != false {
		t.Error("Watcher called after unwatch.")
	}
}

// This provides a coarse estimate of the interrupt latency,
// i.e. the time between an interrupt being triggered and handled.
// There is some overhead in there due to the handshaking via a channel etc...
// so this provides an upper bound.
func BenchmarkInterruptLatency(b *testing.B) {
	if err := Open(); err != nil {
		b.Fatal("Open returned error", err)
	}
	defer Close()
	pinIn := NewPin(J8p15)
	pinOut := NewPin(J8p16)
	pinIn.SetMode(Input)
	defer pinOut.SetMode(Input)
	pinOut.Write(Low)
	pinOut.SetMode(Output)
	mode := pinOut.Mode()
	if mode != Output {
		b.Fatal("Failed to set output")
	}
	ich := make(chan int)
	err := pinIn.Watch(EdgeBoth, func(pin *Pin) {
		ich <- 1
	})
	if err != nil {
		b.Fatal("Registration failed", err)
	}
	defer pinIn.Unwatch()
	for i := 0; i < b.N; i++ {
		pinOut.Toggle()
		waitInterrupt(ich, 5*time.Millisecond)
	}
}
<commit_msg>Increase timeouts in tests to allow for slower devices such as Pi Zero<commit_after>// Copyright © 2017 Kent Gibson <warthog618@gmail.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

//
// Test suite for interrupt module.
//
// Tests use Raspberry Pi J8 pins 15 and 16 which must be jumpered together.
//
package gpio

import (
	"errors"
	"testing"
	"time"
)

func waitInterrupt(ch chan int, timeout time.Duration) (int, error) {
	expired := make(chan bool)
	go func() {
		time.Sleep(timeout)
		close(expired)
	}()
	select {
	case v := <-ch:
		return v, nil
	case <-expired:
		return 0, errors.New("timeout")
	}
}

func setupIntr(t *testing.T) (pinIn *Pin, pinOut *Pin, watcher *Watcher) {
	if err := Open(); err != nil {
		t.Fatal("Open returned error", err)
	}
	pinIn = NewPin(J8p15)
	pinOut = NewPin(J8p16)
	watcher = getDefaultWatcher()
	pinIn.SetMode(Input)
	pinOut.Write(Low)
	pinOut.SetMode(Output)
	return
}

func teardownIntr(pinIn *Pin, pinOut *Pin, watcher *Watcher) {
	pinOut.SetMode(Input)
	watcher.UnregisterPin(pinIn)
	Close()
}

func TestRegister(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	defer teardownIntr(pinIn, pinOut, watcher)
	ich := make(chan int)
	count := 0
	err := watcher.RegisterPin(pinIn, EdgeRising, func(pin *Pin) {
		count++
		ich <- count
	})
	if err != nil {
		t.Fatal("Registration failed", err)
	}
	v, err := waitInterrupt(ich, 10*time.Millisecond)
	if err != nil {
		t.Error("No initial interrupt")
	}
	if v != 1 {
		t.Error("Incorrect count", v)
	}
	_, err = waitInterrupt(ich, 10*time.Millisecond)
	if err == nil {
		t.Error("Spurious interrupt")
	}
}

func TestReregister(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	defer teardownIntr(pinIn, pinOut, watcher)
	ich := make(chan int)
	if err := watcher.RegisterPin(pinIn, EdgeRising, func(pin *Pin) {
		ich <- 1
	}); err != nil {
		t.Fatal("Registration failed", err)
	}
	v, err := waitInterrupt(ich, 10*time.Millisecond)
	if err != nil {
		t.Error("No initial interrupt")
	}
	if v != 1 {
		t.Error("Incorrect count", v)
	}
	if err = watcher.RegisterPin(pinIn, EdgeRising, func(pin *Pin) {
		ich <- 2
	}); err == nil {
		t.Fatal("Reregistration didn't fail.")
	}
	pinOut.High()
	v, err = waitInterrupt(ich, 10*time.Millisecond)
	switch {
	case err != nil:
		t.Error("Didn't call handler")
	case v != 1:
		t.Error("Called new handler")
	}
}

func TestUnregister(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	defer teardownIntr(pinIn, pinOut, watcher)
	ich := make(chan int)
	err := watcher.RegisterPin(pinIn, EdgeRising, func(pin *Pin) {
		ich <- 1
	})
	if err != nil {
		t.Fatal("Registration failed", err)
	}
	v, err := waitInterrupt(ich, 10*time.Millisecond)
	if err != nil {
		t.Error("No initial interrupt")
	}
	if v != 1 {
		t.Error("Incorrect count", v)
	}
	watcher.UnregisterPin(pinIn)
	pinOut.High()
	_, err = waitInterrupt(ich, 10*time.Millisecond)
	if err == nil {
		t.Error("Called old handler")
	}
	// And again just for coverage.
	watcher.UnregisterPin(pinIn)
}

func TestEdgeRising(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	defer teardownIntr(pinIn, pinOut, watcher)
	ich := make(chan int)
	err := watcher.RegisterPin(pinIn, EdgeRising, func(pin *Pin) {
		if pin.Read() == High {
			ich <- 1
		} else {
			ich <- 0
		}
	})
	if err != nil {
		t.Fatal("Registration failed", err)
	}
	v, err := waitInterrupt(ich, 10*time.Millisecond)
	if err != nil {
		t.Error("No initial interrupt")
	}
	if v != 0 {
		t.Error("Incorrect initial value", v)
	}
	// Can take a while for the init to be applied before it starts triggering
	// interrupts, so wait a bit...
	time.Sleep(time.Millisecond)
	for i := 0; i < 10; i++ {
		pinOut.High()
		v, err := waitInterrupt(ich, 10*time.Millisecond)
		if err != nil {
			t.Error("Missed high at", i)
		} else if v == 0 {
			t.Error("Triggered while low at", i)
		}
		pinOut.Low()
		_, err = waitInterrupt(ich, 10*time.Millisecond)
		if err == nil {
			t.Error("Spurious or delayed trigger at", i)
		}
	}
}

func TestEdgeFalling(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	defer teardownIntr(pinIn, pinOut, watcher)
	ich := make(chan int)
	err := watcher.RegisterPin(pinIn, EdgeFalling, func(pin *Pin) {
		if pin.Read() == High {
			ich <- 1
		} else {
			ich <- 0
		}
	})
	if err != nil {
		t.Fatal("Registration failed", err)
	}
	v, err := waitInterrupt(ich, 10*time.Millisecond)
	if err != nil {
		t.Error("No initial interrupt")
	}
	if v != 0 {
		t.Error("Incorrect initial value", v)
	}
	for i := 0; i < 10; i++ {
		pinOut.High()
		_, err := waitInterrupt(ich, 10*time.Millisecond)
		if err == nil {
			t.Error("Spurious or delayed trigger at", i)
		}
		pinOut.Low()
		v, err = waitInterrupt(ich, 10*time.Millisecond)
		if err != nil {
			t.Error("Missed low at", i)
		} else if v == 1 {
			t.Error("Triggered while low at", i)
		}
	}
}

func TestEdgeBoth(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	defer teardownIntr(pinIn, pinOut, watcher)
	ich := make(chan int)
	err := watcher.RegisterPin(pinIn, EdgeBoth, func(pin *Pin) {
		if pin.Read() == High {
			ich <- 1
		} else {
			ich <- 0
		}
	})
	if err != nil {
		t.Fatal("Registration failed", err)
	}
	v, err := waitInterrupt(ich, 10*time.Millisecond)
	if err != nil {
		t.Error("No initial interrupt")
	}
	if v != 0 {
		t.Error("Incorrect initial value", v)
	}
	for i := 0; i < 10; i++ {
		pinOut.High()
		v, err := waitInterrupt(ich, 10*time.Millisecond)
		if err != nil {
			t.Error("Missed high at", i)
		} else if v == 0 {
			t.Error("Triggered while low at", i)
		}
		pinOut.Low()
		v, err = waitInterrupt(ich, 10*time.Millisecond)
		if err != nil {
			t.Error("Missed low at", i)
		} else if v == 1 {
			t.Error("Triggered while high at", i)
		}
	}
}

func TestEdgeNone(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	defer teardownIntr(pinIn, pinOut, watcher)
	ich := make(chan int)
	err := watcher.RegisterPin(pinIn, EdgeNone, func(pin *Pin) {
		if pin.Read() == High {
			ich <- 1
		} else {
			ich <- 0
		}
	})
	if err != nil {
		t.Fatal("Registration failed", err)
	}
	v, err := waitInterrupt(ich, 10*time.Millisecond)
	if err != nil {
		t.Error("No initial interrupt")
	}
	if v != 0 {
		t.Error("Incorrect initial value", v)
	}
	for i := 0; i < 10; i++ {
		pinOut.High()
		v, err := waitInterrupt(ich, 10*time.Millisecond)
		if err == nil {
			t.Error("Spurious or delayed trigger at", i, v)
		}
		pinOut.Low()
		v, err = waitInterrupt(ich, 10*time.Millisecond)
		if err == nil {
			t.Error("Spurious or delayed trigger at", i, v)
		}
	}
}

func TestUnexportedEdge(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	err := setEdge(pinIn, EdgeNone)
	if err == nil {
		t.Error("Edge should fail unless pin exported first.")
	}
	defer teardownIntr(pinIn, pinOut, watcher)
}

func TestCloseInterrupts(t *testing.T) {
	pinIn, pinOut, watcher := setupIntr(t)
	defer teardownIntr(pinIn, pinOut, watcher)
	ich := make(chan int)
	err := watcher.RegisterPin(pinIn, EdgeNone, func(pin *Pin) {
		if pin.Read() == High {
			ich <- 1
		} else {
			ich <- 0
		}
	})
	if err != nil {
		t.Fatal("Registration failed", err)
	}
	closeInterrupts()
	v, err := waitInterrupt(ich, 10*time.Millisecond)
	if err == nil {
		t.Error("Spurious interrupt during close", v)
	}
	pinOut.High()
	v, err = waitInterrupt(ich, 10*time.Millisecond)
	if err == nil {
		t.Error("Interrupts still active after close", v)
	}
}

func TestWatchExists(t *testing.T) {
	if err := Open(); err != nil {
		t.Fatal("Open returned error", err)
	}
	defer Close()
	pinIn := NewPin(J8p15)
	pinIn.SetMode(Input)
	count := 0
	if err := pinIn.Watch(EdgeFalling, func(pin *Pin) {
		count++
	}); err != nil {
		t.Fatal("Watch returned error", err)
	}
	if err := pinIn.Watch(EdgeFalling, func(pin *Pin) {
		count++
	}); err == nil {
		t.Error("Watch didn't return error")
	}
	time.Sleep(2 * time.Millisecond)
	if count != 1 {
		t.Error("Second handler called")
	}
}

// Looped tests require a jumper across Raspberry Pi J8 pins 15 and 16.
// This is just a smoke test for the Watch and Unwatch methods.
func TestWatchLooped(t *testing.T) {
	if err := Open(); err != nil {
		t.Fatal("Open returned error", err)
	}
	defer Close()
	pinIn := NewPin(J8p15)
	pinOut := NewPin(J8p16)
	pinIn.SetMode(Input)
	defer pinOut.SetMode(Input)
	pinOut.Write(Low)
	pinOut.SetMode(Output)
	mode := pinOut.Mode()
	if mode != Output {
		t.Fatal("Failed to set output")
	}
	called := false
	if err := pinIn.Watch(EdgeFalling, func(pin *Pin) {
		called = true
	}); err != nil {
		t.Fatal("Watch returned error", err)
	}
	time.Sleep(2 * time.Millisecond)
	if called == false {
		t.Error("Watcher not called with initial value.")
	}
	called = false
	pinOut.High()
	time.Sleep(2 * time.Millisecond)
	if called {
		t.Error("Spurious Watcher called.")
		called = false
	}
	pinOut.Low()
	time.Sleep(2 * time.Millisecond)
	if called == false {
		t.Error("Watcher not called.")
	}
	pinIn.Unwatch()
	called = false
	pinOut.High()
	pinOut.Low()
	time.Sleep(2 * time.Millisecond)
	if called != false {
		t.Error("Watcher called after unwatch.")
	}
}

// This provides a coarse estimate of the interrupt latency,
// i.e. the time between an interrupt being triggered and handled.
// There is some overhead in there due to the handshaking via a channel etc...
// so this provides an upper bound.
func BenchmarkInterruptLatency(b *testing.B) {
	if err := Open(); err != nil {
		b.Fatal("Open returned error", err)
	}
	defer Close()
	pinIn := NewPin(J8p15)
	pinOut := NewPin(J8p16)
	pinIn.SetMode(Input)
	defer pinOut.SetMode(Input)
	pinOut.Write(Low)
	pinOut.SetMode(Output)
	mode := pinOut.Mode()
	if mode != Output {
		b.Fatal("Failed to set output")
	}
	ich := make(chan int)
	err := pinIn.Watch(EdgeBoth, func(pin *Pin) {
		ich <- 1
	})
	if err != nil {
		b.Fatal("Registration failed", err)
	}
	defer pinIn.Unwatch()
	for i := 0; i < b.N; i++ {
		pinOut.Toggle()
		waitInterrupt(ich, 10*time.Millisecond)
	}
}
<|endoftext|>


<commit_before>package dbmagic

import (
	"database/sql"
	"database/sql/driver"
	"fmt"
)

type DataSource struct {
	Host         string
	Port         int
	User         string
	Password     string
	Socket       string
	Charset      string
	DatabaseName string
}

type DbMagic struct {
	Db *sql.DB
}

func (dbm *DbMagic) Open(driverName string, settings DataSource) (DbSession, error) {
	dataSourceName := config(driverName, settings)
	if err != nil {
		return nil, err
	}
	return conn, nil
}

func config(driverName string, settings DataSource) string {
	if settings.Host == "" {
		if settings.Socket == "" {
			settings.Host = "127.0.0.1"
		}
	}

}
<commit_msg>complete open and close func<commit_after>package dbmagic

import (
	"database/sql"
	"database/sql/driver"
	"errors"
	"fmt"
)

type DataSource struct {
	Host         string
	Port         int
	User         string
	Password     string
	Socket       string
	Charset      string
	DatabaseName string
}

var (
	ErrMissingDatabaseName = errors.New(`Missing database name.`)
	ErrSockerHost          = errors.New(`Can not setting socket and host both.`)
)

type DbMagic struct {
	Db *sql.DB
	Tx *sql.Tx
}

func Open(driverName string, settings DataSource) (*DbMagic, error) {
	var err error
	dataSourceName := config(settings)
	dbm := new(DbMagic)
	dbm.Db, err = sql.Open(driverName, dataSourceName)
	if err != nil {
		return nil, err
	}
	return dbm, nil
}

func (dbm *DbMagic) Close() error {
	return dbm.Db.Close()
}

func config(settings DataSource) string {
	if settings.Host == "" {
		if settings.Socket == "" {
			settings.Host = "127.0.0.1"
		}
	}
	if settings.Port == 0 {
		settings.Port = 3306
	}

	if settings.DatabaseName == "" {
		return ErrMissingDatabaseName
	}

	if settings.Host != "" && settings.Socket != "" {
		return ErrSockerHost
	}

	if settings.Charset == "" {
		settings.Charset = "utf8"
	}
	var dataSourceName string
	if settings.Host != "" {
		dataSourceName = fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=%s", settings.User, settings.Password, settings.Host, settings.Port, settings.DatabaseName, settings.Charset)
	} else if settings.Socket != "" {
		dataSourceName = fmt.Sprintf("%s:%s@unix(%s)/%s?charset=%s", settings.User, settings.Password, settings.Socket, settings.DatabaseName, settings.Charset)
	}
	return dataSourceName
}
<|endoftext|>


<commit_before>package uic

import (
	"github.com/Cepave/fe/http/base"
	"github.com/Cepave/fe/model/uic"
	"github.com/Cepave/fe/utils"
)

type SsoController struct {
	base.BaseController
}

func (this *SsoController) Sig() {
	this.Ctx.Output.Body([]byte(utils.GenerateUUID()))
}

func (this *SsoController) User() {
	sig := this.Ctx.Input.Param(":sig")
	if sig == "" {
		this.NotFound("sig is blank")
		return
	}

	s := uic.ReadSessionBySig(sig)
	if s == nil {
		this.NotFound("no such sig")
		return
	}

	u := uic.ReadUserById(s.Uid)
	if u == nil {
		this.NotFound("no such user")
		return
	}

	this.Data["json"] = map[string]interface{}{
		"user": u,
	}
	this.ServeJson()
}

func (this *SsoController) Logout() {
	sig := this.Ctx.Input.Param(":sig")
	if sig == "" {
		this.ServeErrJson("sig is blank")
		return
	}

	s := uic.ReadSessionBySig(sig)
	if s != nil {
		uic.RemoveSessionByUid(s.Uid)
	}

	this.ServeOKJson()
}
<commit_msg>Change the variable's name<commit_after>package uic

import (
	"github.com/Cepave/fe/http/base"
	"github.com/Cepave/fe/model/uic"
	"github.com/Cepave/fe/utils"
)

type SsoController struct {
	base.BaseController
}

func (this *SsoController) Sig() {
	this.Ctx.Output.Body([]byte(utils.GenerateUUID()))
}

func (this *SsoController) User() {
	sig := this.Ctx.Input.Param(":sig")
	if sig == "" {
		this.NotFound("sig is blank")
		return
	}

	sessionObj := uic.ReadSessionBySig(sig)
	if sessionObj == nil {
		this.NotFound("no such sig")
		return
	}

	u := uic.ReadUserById(sessionObj.Uid)
	if u == nil {
		this.NotFound("no such user")
		return
	}

	this.Data["json"] = map[string]interface{}{
		"user": u,
	}
	this.ServeJson()
}

func (this *SsoController) Logout() {
	sig := this.Ctx.Input.Param(":sig")
	if sig == "" {
		this.ServeErrJson("sig is blank")
		return
	}

	sessionObj := uic.ReadSessionBySig(sig)
	if sessionObj != nil {
		uic.RemoveSessionByUid(s.Uid)
	}

	this.ServeOKJson()
}
<|endoftext|>


<commit_before>package bot

import (
	"errors"
	"fmt"
	"gitlab.transip.us/swiltink/go-MusicBot/player"
	"gitlab.transip.us/swiltink/go-MusicBot/songplayer"
	"gitlab.transip.us/swiltink/go-MusicBot/util"
	"strings"
	"time"
)

const (
	NORMAL_CHARACTER    = string('\u000F')
	BOLD_CHARACTER      = string('\u0002')
	UNDERLINE_CHARACTER = string('\u001F')
	ITALIC_CHARACTER    = string('\u001D')
	INVERSE_CHARACTER   = string('\u0016')
	COLOUR_CHARACTER    = string('\u0003')
)

type Color string

const (
	COLOUR_WHITE       Color = "00"
	COLOUR_BLACK       Color = "01"
	COLOUR_BLUE        Color = "02"
	COLOUR_GREEN       Color = "03"
	COLOUR_RED         Color = "04"
	COLOUR_BROWN       Color = "05"
	COLOUR_PURPLE      Color = "06"
	COLOUR_ORANGE      Color = "07"
	COLOUR_YELLOW      Color = "08"
	COLOUR_LIGHT_GREEN Color = "09"
	COLOUR_TEAL        Color = "10"
	COLOUR_CYAN        Color = "11"
	COLOUR_LIGHT_BLUE  Color = "12"
	COLOUR_PINK        Color = "13"
	COLOUR_GREY        Color = "14"
	COLOUR_LIGHT_GREY  Color = "15"
	COLOUR_DEFAULT     Color = "99"
	COLOUR_NONE        Color = ""
)

func boldText(s string) (bs string) {
	return BOLD_CHARACTER + s + BOLD_CHARACTER
}

func underlineText(s string) (us string) {
	return UNDERLINE_CHARACTER + s + UNDERLINE_CHARACTER
}

func italicText(s string) (us string) {
	return ITALIC_CHARACTER + s + ITALIC_CHARACTER
}

func inverseText(s string) (is string) {
	return INVERSE_CHARACTER + s + INVERSE_CHARACTER
}

func getColourCode(foreground, background Color) (code string) {
	if foreground == COLOUR_NONE {
		return
	}
	if background == COLOUR_NONE {
		code = fmt.Sprintf("%s%s", COLOUR_CHARACTER, foreground)
		return
	}
	code = fmt.Sprintf("%s%s,%s", COLOUR_CHARACTER, foreground, background)
	return
}

func colourText(foreground, backgroundColor Color, s string) (cs string) {
	cc := getColourCode(foreground, backgroundColor)
	endCode := getColourCode(COLOUR_DEFAULT, COLOUR_DEFAULT)
	cs = cc + s + endCode
	return
}

func formatSong(song songplayer.Playable) (s string) {
	s = fmt.Sprintf("%s %s%s%s", song.GetTitle(), getColourCode(COLOUR_TEAL, COLOUR_NONE), util.FormatSongLength(song.GetDuration()), getColourCode(COLOUR_DEFAULT, COLOUR_NONE))
	return
}

func progressString(total, remaining time.Duration) (progress string) {
	percent := int(float64(total-remaining) / float64(total) * 100)

	for i := 1; i < percent; i++ {
		progress += "_"
	}
	progress += "#"
	if percent < 100 {
		for i := percent + 1; i <= 100; i++ {
			progress += "_"
		}
	}
	return
}

func searchSongs(player player.MusicPlayer, parameters []string, limit int) (results map[string][]songplayer.PlayableSearchResult, err error) {
	results = make(map[string][]songplayer.PlayableSearchResult)

	searchType := songplayer.SEARCH_TYPE_TRACK
	ok, searchType := songplayer.GetSearchType(parameters[0])
	if ok {
		parameters = parameters[1:] // cut off the searchType parameter
		if len(parameters) < 1 {
			err = errors.New("Missing search parameter")
			return
		}
	}

	plyr := player.GetSongPlayer(parameters[0])
	if plyr != nil {
		parameters = parameters[1:] // cut off the player parameter
		if len(parameters) < 1 {
			err = errors.New("Missing search parameter")
			return
		}
	}

	searchFunc := func(songPlayer songplayer.SongPlayer, searchStr string) (err error) {
		var items []songplayer.PlayableSearchResult
		items, err = songPlayer.Search(searchType, searchStr, limit)
		if err != nil {
			return
		}
		for _, item := range items {
			results[songPlayer.Name()] = append(results[songPlayer.Name()], item)
		}
		return
	}

	if plyr != nil {
		searchErr := searchFunc(plyr, strings.Join(parameters, " "))
		if searchErr != nil {
			fmt.Sprintf("[%s] Error searching [%d | %v] %v", plyr.Name(), searchType, parameters, searchErr)
		}
		return
	}

	for _, songPlayer := range player.GetSongPlayers() {
		searchErr := searchFunc(songPlayer, strings.Join(parameters, " "))
		if searchErr != nil {
			fmt.Sprintf("[%s] Error searching [%d | %v] %v", songPlayer.Name(), searchType, parameters, searchErr)
		}
	}
	return
}
<commit_msg>Fix progress a bit<commit_after>package bot

import (
	"errors"
	"fmt"
	"gitlab.transip.us/swiltink/go-MusicBot/player"
	"gitlab.transip.us/swiltink/go-MusicBot/songplayer"
	"gitlab.transip.us/swiltink/go-MusicBot/util"
	"strings"
	"time"
)

const (
	NORMAL_CHARACTER    = string('\u000F')
	BOLD_CHARACTER      = string('\u0002')
	UNDERLINE_CHARACTER = string('\u001F')
	ITALIC_CHARACTER    = string('\u001D')
	INVERSE_CHARACTER   = string('\u0016')
	COLOUR_CHARACTER    = string('\u0003')
)

type Color string

const (
	COLOUR_WHITE       Color = "00"
	COLOUR_BLACK       Color = "01"
	COLOUR_BLUE        Color = "02"
	COLOUR_GREEN       Color = "03"
	COLOUR_RED         Color = "04"
	COLOUR_BROWN       Color = "05"
	COLOUR_PURPLE      Color = "06"
	COLOUR_ORANGE      Color = "07"
	COLOUR_YELLOW      Color = "08"
	COLOUR_LIGHT_GREEN Color = "09"
	COLOUR_TEAL        Color = "10"
	COLOUR_CYAN        Color = "11"
	COLOUR_LIGHT_BLUE  Color = "12"
	COLOUR_PINK        Color = "13"
	COLOUR_GREY        Color = "14"
	COLOUR_LIGHT_GREY  Color = "15"
	COLOUR_DEFAULT     Color = "99"
	COLOUR_NONE        Color = ""
)

func boldText(s string) (bs string) {
	return BOLD_CHARACTER + s + BOLD_CHARACTER
}

func underlineText(s string) (us string) {
	return UNDERLINE_CHARACTER + s + UNDERLINE_CHARACTER
}

func italicText(s string) (us string) {
	return ITALIC_CHARACTER + s + ITALIC_CHARACTER
}

func inverseText(s string) (is string) {
	return INVERSE_CHARACTER + s + INVERSE_CHARACTER
}

func getColourCode(foreground, background Color) (code string) {
	if foreground == COLOUR_NONE {
		return
	}
	if background == COLOUR_NONE {
		code = fmt.Sprintf("%s%s", COLOUR_CHARACTER, foreground)
		return
	}
	code = fmt.Sprintf("%s%s,%s", COLOUR_CHARACTER, foreground, background)
	return
}

func colourText(foreground, backgroundColor Color, s string) (cs string) {
	cc := getColourCode(foreground, backgroundColor)
	endCode := getColourCode(COLOUR_DEFAULT, COLOUR_DEFAULT)
	cs = cc + s + endCode
	return
}

func formatSong(song songplayer.Playable) (s string) {
	s = fmt.Sprintf("%s %s%s%s", song.GetTitle(), getColourCode(COLOUR_TEAL, COLOUR_NONE), util.FormatSongLength(song.GetDuration()), getColourCode(COLOUR_DEFAULT, COLOUR_NONE))
	return
}

func progressString(total, remaining time.Duration) (progress string) {
	percent := int(float64(total-remaining) / float64(total) * 100)

	progress = "+"
	for i := 0; i < percent; i++ {
		progress += "-"
	}
	progress += "#"
	if percent < 100 {
		for i := percent + 1; i < 100; i++ {
			progress += "-"
		}
	}
	progress += "+"
	return
}

func searchSongs(player player.MusicPlayer, parameters []string, limit int) (results map[string][]songplayer.PlayableSearchResult, err error) {
	results = make(map[string][]songplayer.PlayableSearchResult)

	searchType := songplayer.SEARCH_TYPE_TRACK
	ok, searchType := songplayer.GetSearchType(parameters[0])
	if ok {
		parameters = parameters[1:] // cut off the searchType parameter
		if len(parameters) < 1 {
			err = errors.New("Missing search parameter")
			return
		}
	}

	plyr := player.GetSongPlayer(parameters[0])
	if plyr != nil {
		parameters = parameters[1:] // cut off the player parameter
		if len(parameters) < 1 {
			err = errors.New("Missing search parameter")
			return
		}
	}

	searchFunc := func(songPlayer songplayer.SongPlayer, searchStr string) (err error) {
		var items []songplayer.PlayableSearchResult
		items, err = songPlayer.Search(searchType, searchStr, limit)
		if err != nil {
			return
		}
		for _, item := range items {
			results[songPlayer.Name()] = append(results[songPlayer.Name()], item)
		}
		return
	}

	if plyr != nil {
		searchErr := searchFunc(plyr, strings.Join(parameters, " "))
		if searchErr != nil {
			fmt.Sprintf("[%s] Error searching [%d | %v] %v", plyr.Name(), searchType, parameters, searchErr)
		}
		return
	}

	for _, songPlayer := range player.GetSongPlayers() {
		searchErr := searchFunc(songPlayer, strings.Join(parameters, " "))
		if searchErr != nil {
			fmt.Sprintf("[%s] Error searching [%d | %v] %v", songPlayer.Name(), searchType, parameters, searchErr)
		}
	}
	return
}
<|endoftext|>


<commit_before>// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package autolog

import (
	"net/http"

	"rsc.io/tmp/httplogger"
)

func init() {
	http.DefaultTransport = httplogger.New(http.DefaultTransport)
}
<commit_msg>httplogger/autolog: only if $HTTPLOG=1<commit_after>// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package autolog

import (
	"net/http"
	"os"

	"rsc.io/tmp/httplogger"
)

func init() {
	if os.Getenv("HTTPLOG") == "1" {
		http.DefaultTransport = httplogger.New(http.DefaultTransport)
	}
}
<|endoftext|>


<commit_before>package fs

import (
	//"bufio"
	"fmt"
	"github.com/Sirupsen/logrus"
	//"github.com/docker/libcontainer/cgroups"
	"github.com/memoryLimitBySijan"
	"os"
	//"path/filepath"

	"strconv"
)

func SijanAnanya(d *data) {
	dir, err := d.join("memory")

	defer func() {
		if err != nil {
			os.RemoveAll(dir)
		}
	}()

	logrus.Debugf("!!!!!calledSijanAnanya")
	fmt.Println("This is going t change thewhole code")
	si := memoryLimitBySijan.Get()
	TotalMemory := si.TotalRam
	logrus.Debugf("!!!!!!!!!!!!!!!!!!calledSijanAnanya%v\n", si.TotalRam)
	//fmt.Printf("%v\n", si.TotalRam)
	//	logrus.Debugf(reflect.TypeOf(si.TotalRam))
	LimitForEachContainer := TotalMemory * 20 / 100
	ByteConverter := 10000 * LimitForEachContainer
	var a int64
	a = Num64(ByteConverter)
	str := strconv.FormatInt(a, 10)
	writeFile(dir, "memory.limit_in_bytes", str)
	//s	str := strconv.FormatUInt(ByteConverter, 10)

	//fmt.Println(reflect.TypeOf(strval))
}
func Num64(n interface{}) int64 {
	s := fmt.Sprintf("%d", n)
	i, err := strconv.ParseInt(s, 10, 64)
	if err != nil {
		return 0
	} else {
		return i
	}
}
<commit_msg>chanedto 0<commit_after>package fs

import (
	//"bufio"
	"fmt"
	"github.com/Sirupsen/logrus"
	//"github.com/docker/libcontainer/cgroups"
	"github.com/memoryLimitBySijan"
	"os"
	//"path/filepath"

	"strconv"
)

func SijanAnanya(d *data) {
	dir, err := d.join("memory")

	defer func() {
		if err != nil {
			os.RemoveAll(dir)
		}
	}()

	logrus.Debugf("!!!!!calledSijanAnanya")
	fmt.Println("This is going t change thewhole code")
	si := memoryLimitBySijan.Get()
	TotalMemory := si.TotalRam
	logrus.Debugf("!!!!!!!!!!!!!!!!!!calledSijanAnanya%v\n", si.TotalRam)
	//fmt.Printf("%v\n", si.TotalRam)
	//	logrus.Debugf(reflect.TypeOf(si.TotalRam))
	LimitForEachContainer := TotalMemory * 20 / 100
	ByteConverter := 1000 * LimitForEachContainer
	var a int64
	a = Num64(ByteConverter)
	str := strconv.FormatInt(a, 10)
	writeFile(dir, "memory.limit_in_bytes", str)
	//s	str := strconv.FormatUInt(ByteConverter, 10)

	//fmt.Println(reflect.TypeOf(strval))
}
func Num64(n interface{}) int64 {
	s := fmt.Sprintf("%d", n)
	i, err := strconv.ParseInt(s, 10, 64)
	if err != nil {
		return 0
	} else {
		return i
	}
}
<|endoftext|>


<commit_before>package pairing_heap

import (
	"math/rand"
	"testing"
)

var chars = []byte("01234567890abcdefghijklmnopqrstuvwxyz")

type testArray [1000][]string

func TestBasic(t *testing.T) {
	h := NewPairingHeap()

	if !h.Empty() {
		t.Error("Expected empty to be true, was false")
	}

	h.Insert(7, "seven")
	if h.Empty() {
		t.Error("Expected empty to be false, was true")
	}
	if n := h.DeleteMin(); n.Key != 7 || n.Value != "seven" {
		t.Errorf("Expected (n.Key, n.Value) to be (7, \"seven\"), was (%d, %q)", n.Key, n.Value)
	}
	if !h.Empty() {
		t.Error("Expected empty to be true, was false")
	}

	h.Insert(3, "three")
	if h.Empty() {
		t.Error("Expected empty to be false, was true")
	}

	h.Insert(8, "eight")
	if h.Empty() {
		t.Error("Expected empty to be false, was true")
	}

	h.Insert(3, "three again")
	if h.Empty() {
		t.Error("Expected empty to be false, was true")
	}

	n1 := h.DeleteMin()
	if h.Empty() {
		t.Error("Expected empty to be false, was true")
	}

	n2 := h.DeleteMin()
	if h.Empty() {
		t.Error("Expected empty to be false, was true")
	}

	if n1.Key != 3 || n2.Key != 3 ||
		!(n1.Value == "three" && n2.Value == "three again" ||
			n1.Value == "three again" && n2.Value == "three") {
		t.Errorf("Expected (n1.Key, n1.Value) and (n2.Key, n2.Value) to be (3, \"three\") and "+
			"(3, \"three again\") in any order, was (%d, %q) and (%d, %q)",
			n1.Key, n1.Value, n2.Key, n2.Value)
	}

	if n := h.DeleteMin(); n.Key != 8 || n.Value != "eight" {
		t.Errorf("Expected (n.Key, n.Value) to be (8, \"eight\"), was (%d, %q)", n.Key, n.Value)
	}
	if !h.Empty() {
		t.Error("Expected empty to be true, was false")
	}
}

func TestDecreaseKey(t *testing.T) {
	h := NewPairingHeap()

	h.Insert(7, "seven")
	nine := h.Insert(9, "nine then two")
	h.DecreaseKey(nine, 2)

	if n := h.DeleteMin(); n.Key != 2 || n.Value != "nine then two" {
		t.Errorf("Expected (n.Key, n.Value) to be (2, \"nine then two\"), was (%d, %q)",
			n.Key, n.Value)
	}
}

func TestMerge(t *testing.T) {
	a := NewPairingHeap()
	b := NewPairingHeap()

	a.Insert(7, "seven")
	a.Insert(3, "three")
	a.Insert(2, "two")

	b.Insert(4, "four")
	a.Insert(3, "three again")

	a.Merge(b)

	if n := a.DeleteMin(); n.Key != 2 || n.Value != "two" {
		t.Errorf("Expected (n.Key, n.Value) to be (2, \"two\"), was (%d, %q)", n.Key, n.Value)
	}

	n1 := a.DeleteMin()
	n2 := a.DeleteMin()
	if n1.Key != 3 || n2.Key != 3 ||
		!(n1.Value == "three" && n2.Value == "three again" ||
			n1.Value == "three again" && n2.Value == "three") {
		t.Errorf("Expected (n1.Key, n1.Value) and (n2.Key, n2.Value) to be (3, \"three\") and "+
			"(3, \"three again\") in any order, was (%d, %q) and (%d, %q)",
			n1.Key, n1.Value, n2.Key, n2.Value)
	}

	if n := a.DeleteMin(); n.Key != 4 || n.Value != "four" {
		t.Errorf("Expected (n.Key, n.Value) to be (4, \"four\"), was (%d, %q)", n.Key, n.Value)
	}

	if n := a.DeleteMin(); n.Key != 7 || n.Value != "seven" {
		t.Errorf("Expected (n.Key, n.Value) to be (7, \"seven\"), was (%d, %q)", n.Key, n.Value)
	}

	if !a.Empty() {
		t.Error("Expected empty to be true, was false")
	}
}

func TestRandom(t *testing.T) {
	for i := 0; i < 100 && !t.Failed(); i++ {
		runRandomTest(t)
	}
}

func runRandomTest(t *testing.T) {
	h := NewPairingHeap()
	p := &testArray{}

	count := rand.Intn(10000)
	var n *Node
	for i := 0; i < count; i++ {
		r := rand.Float32()
		switch {
		case r < 0.2 && n != nil && n.Key > 0:
			decreaseKey(h, p, n)
			n = nil
		case 0.2 <= r && r < 0.4 && !h.Empty():
			if d := deleteMin(t, h, p); d == n {
				n = nil
			}
		default:
			n = insertRandom(h, p)
		}
	}

	check(t, h, p)
}

func check(t *testing.T, h *PairingHeap, p *testArray) {
	if !validHeap(h.root) {
		t.Errorf("Heap structure not respected")
	}
	for !h.Empty() {
		deleteMin(t, h, p)
	}
	for i, v := range p {
		if len(v) > 0 {
			t.Errorf("Array at index #%d is not empty: %v", i, v)
		}
	}
}

func validHeap(n *Node) bool {
	if n == nil {
		return true
	}
	for _, c := range n.children {
		if c != nil && n.Key > c.Key || !validHeap(c) {
			return false
		}
	}
	return true
}

func insertRandom(h *PairingHeap, p *testArray) *Node {
	k := randomKey(len(p))
	v := randomValue()
	n := h.Insert(k, v)
	p[k] = append(p[k], v)
	return n
}

func decreaseKey(h *PairingHeap, p *testArray, n *Node) {
	oldKey := n.Key
	newKey := rand.Intn(n.Key)
	value := n.Value.(string)

	p[oldKey] = removeString(p[oldKey], value)
	p[newKey] = append(p[newKey], value)

	h.DecreaseKey(n, newKey)
}

func deleteMin(t *testing.T, h *PairingHeap, p *testArray) *Node {
	n := h.DeleteMin()
	a := p[n.Key]
	b := removeString(a, n.Value.(string))
	if len(b) >= len(a) {
		t.Errorf("Could not remove (%d, %q) from array", n.Key, n.Value)
	}
	p[n.Key] = b
	return n
}

func removeString(a []string, s string) []string {
	for i, v := range a {
		if v == s {
			last := len(a) - 1
			a[i] = a[last]
			return a[:last]
		}
	}
	return a
}

func randomKey(max int) int {
	return rand.Intn(max)
}

func randomValue() string {
	l := len(chars)
	s := []byte{}
	for i := 0; i < 6; i++ {
		s = append(s, chars[rand.Intn(l)])
	}
	return string(s)
}
<commit_msg>[pairing_heap/go] Cleanup test<commit_after>package pairing_heap

import (
	"math/rand"
	"testing"
)

var chars = []byte("01234567890abcdefghijklmnopqrstuvwxyz")

type testArray [1000][]string

func TestBasic(t *testing.T) {
	h := NewPairingHeap()

	if !h.Empty() {
		t.Error("Expected empty to be true, was false")
	}

	h.Insert(7, "seven")
	if h.Empty() {
		t.Error("Expected empty to be false, was true")
	}
	if n := h.DeleteMin(); n.Key != 7 || n.Value != "seven" {
		t.Errorf("Expected (n.Key, n.Value) to be (7, \"seven\"), was (%d, %q)", n.Key, n.Value)
	}
	if !h.Empty() {
		t.Error("Expected empty to be true, was false")
	}

	h.Insert(3, "three")
	if h.Empty() {
		t.Error("Expected empty to be false, was true")
	}

	h.Insert(8, "eight")
	if h.Empty() {
		t.Error("Expected empty to be false, was true")
	}

	h.Insert(3, "three again")
	if h.Empty() {
		t.Error("Expected empty to be false, was true")
	}

	n1 := h.DeleteMin()
	if h.Empty() {
		t.Error("Expected empty to be false, was true")
	}

	n2 := h.DeleteMin()
	if h.Empty() {
		t.Error("Expected empty to be false, was true")
	}

	if n1.Key != 3 || n2.Key != 3 ||
		!(n1.Value == "three" && n2.Value == "three again" ||
			n1.Value == "three again" && n2.Value == "three") {
		t.Errorf("Expected (n1.Key, n1.Value) and (n2.Key, n2.Value) to be (3, \"three\") and "+
			"(3, \"three again\") in any order, was (%d, %q) and (%d, %q)",
			n1.Key, n1.Value, n2.Key, n2.Value)
	}

	if n := h.DeleteMin(); n.Key != 8 || n.Value != "eight" {
		t.Errorf("Expected (n.Key, n.Value) to be (8, \"eight\"), was (%d, %q)", n.Key, n.Value)
	}
	if !h.Empty() {
		t.Error("Expected empty to be true, was false")
	}
}

func TestDecreaseKey(t *testing.T) {
	h := NewPairingHeap()

	h.Insert(7, "seven")
	nine := h.Insert(9, "nine then two")
	h.DecreaseKey(nine, 2)

	if n := h.DeleteMin(); n.Key != 2 || n.Value != "nine then two" {
		t.Errorf("Expected (n.Key, n.Value) to be (2, \"nine then two\"), was (%d, %q)",
			n.Key, n.Value)
	}
}

func TestMerge(t *testing.T) {
	a := NewPairingHeap()
	b := NewPairingHeap()

	a.Insert(7, "seven")
	a.Insert(3, "three")
	a.Insert(2, "two")

	b.Insert(4, "four")
	a.Insert(3, "three again")

	a.Merge(b)

	if n := a.DeleteMin(); n.Key != 2 || n.Value != "two" {
		t.Errorf("Expected (n.Key, n.Value) to be (2, \"two\"), was (%d, %q)", n.Key, n.Value)
	}

	n1 := a.DeleteMin()
	n2 := a.DeleteMin()
	if n1.Key != 3 || n2.Key != 3 ||
		!(n1.Value == "three" && n2.Value == "three again" ||
			n1.Value == "three again" && n2.Value == "three") {
		t.Errorf("Expected (n1.Key, n1.Value) and (n2.Key, n2.Value) to be (3, \"three\") and "+
			"(3, \"three again\") in any order, was (%d, %q) and (%d, %q)",
			n1.Key, n1.Value, n2.Key, n2.Value)
	}

	if n := a.DeleteMin(); n.Key != 4 || n.Value != "four" {
		t.Errorf("Expected (n.Key, n.Value) to be (4, \"four\"), was (%d, %q)", n.Key, n.Value)
	}

	if n := a.DeleteMin(); n.Key != 7 || n.Value != "seven" {
		t.Errorf("Expected (n.Key, n.Value) to be (7, \"seven\"), was (%d, %q)", n.Key, n.Value)
	}

	if !a.Empty() {
		t.Error("Expected empty to be true, was false")
	}
}

func TestRandom(t *testing.T) {
	for i := 0; i < 100 && !t.Failed(); i++ {
		runRandomTest(t)
	}
}

func runRandomTest(t *testing.T) {
	h := NewPairingHeap()
	p := &testArray{}

	count := rand.Intn(10000)
	var n *Node
	for i := 0; i < count; i++ {
		n = randomRound(t, h, p, n)
	}

	check(t, h, p)
}

func randomRound(t *testing.T, h *PairingHeap, p *testArray, n *Node) *Node {
	r := rand.Float32()
	switch {
	case r < 0.2 && n != nil && n.Key > 0:
		decreaseKey(h, p, n)
		return nil

	case 0.2 <= r && r < 0.4 && !h.Empty():
		if d := deleteMin(t, h, p); d == n {
			return nil
		}
		return n

	default:
		return insertRandom(h, p)
	}
}

func check(t *testing.T, h *PairingHeap, p *testArray) {
	if !validHeap(h.root) {
		t.Errorf("Heap structure not respected")
	}
	for !h.Empty() {
		deleteMin(t, h, p)
	}
	for i, v := range p {
		if len(v) > 0 {
			t.Errorf("Array at index #%d is not empty: %v", i, v)
		}
	}
}

func validHeap(n *Node) bool {
	if n == nil {
		return true
	}
	for _, c := range n.children {
		if c != nil && n.Key > c.Key || !validHeap(c) {
			return false
		}
	}
	return true
}

func insertRandom(h *PairingHeap, p *testArray) *Node {
	k := randomKey(len(p))
	v := randomValue()
	n := h.Insert(k, v)
	p[k] = append(p[k], v)
	return n
}

func decreaseKey(h *PairingHeap, p *testArray, n *Node) {
	oldKey := n.Key
	newKey := rand.Intn(n.Key)
	value := n.Value.(string)

	p[oldKey] = removeString(p[oldKey], value)
	p[newKey] = append(p[newKey], value)

	h.DecreaseKey(n, newKey)
}

func deleteMin(t *testing.T, h *PairingHeap, p *testArray) *Node {
	n := h.DeleteMin()
	a := p[n.Key]
	b := removeString(a, n.Value.(string))
	if len(b) >= len(a) {
		t.Errorf("Could not remove (%d, %q) from array", n.Key, n.Value)
	}
	p[n.Key] = b
	return n
}

func removeString(a []string, s string) []string {
	for i, v := range a {
		if v == s {
			last := len(a) - 1
			a[i] = a[last]
			return a[:last]
		}
	}
	return a
}

func randomKey(max int) int {
	return rand.Intn(max)
}

func randomValue() string {
	l := len(chars)
	s := []byte{}
	for i := 0; i < 6; i++ {
		s = append(s, chars[rand.Intn(l)])
	}
	return string(s)
}
<|endoftext|>