<commit_before>package zerolog

import (
	"errors"
	"io/ioutil"
	"testing"
	"time"
)

var (
	errExample  = errors.New("fail")
	fakeMessage = "Test logging, but use a somewhat realistic message length."
)

func BenchmarkLogEmpty(b *testing.B) {
	logger := New(ioutil.Discard)
	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			logger.Log().Msg("")
		}
	})
}

func BenchmarkDisabled(b *testing.B) {
	logger := New(ioutil.Discard).Level(Disabled)
	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			logger.Info().Msg(fakeMessage)
		}
	})
}

func BenchmarkInfo(b *testing.B) {
	logger := New(ioutil.Discard)
	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			logger.Info().Msg(fakeMessage)
		}
	})
}

func BenchmarkContextFields(b *testing.B) {
	logger := New(ioutil.Discard).With().
		Str("string", "four!").
		Time("time", time.Time{}).
		Int("int", 123).
		Float32("float", -2.203230293249593).
		Logger()
	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			logger.Info().Msg(fakeMessage)
		}
	})
}

func BenchmarkContextAppend(b *testing.B) {
	logger := New(ioutil.Discard).With().
		Str("foo", "bar").
		Logger()
	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			logger.With().Str("bar", "baz")
		}
	})
}

func BenchmarkLogFields(b *testing.B) {
	logger := New(ioutil.Discard)
	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			logger.Info().
				Str("string", "four!").
				Time("time", time.Time{}).
				Int("int", 123).
				Float32("float", -2.203230293249593).
				Msg(fakeMessage)
		}
	})
}

type obj struct {
	Pub  string
	Tag  string `json:"tag"`
	priv int
}

func (o obj) MarshalZerologObject(e *Event) {
	e.Str("Pub", o.Pub).
		Str("Tag", o.Tag).
		Int("priv", o.priv)
}

func BenchmarkLogFieldType(b *testing.B) {
	bools := []bool{true, false, true, false, true, false, true, false, true, false}
	ints := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
	floats := []float64{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
	strings := []string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j"}
	durations := []time.Duration{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
	times := []time.Time{
		time.Unix(0, 0),
		time.Unix(1, 0),
		time.Unix(2, 0),
		time.Unix(3, 0),
		time.Unix(4, 0),
		time.Unix(5, 0),
		time.Unix(6, 0),
		time.Unix(7, 0),
		time.Unix(8, 0),
		time.Unix(9, 0),
	}
	interfaces := []struct {
		Pub  string
		Tag  string `json:"tag"`
		priv int
	}{
		{"a", "a", 0},
		{"a", "a", 0},
		{"a", "a", 0},
		{"a", "a", 0},
		{"a", "a", 0},
		{"a", "a", 0},
		{"a", "a", 0},
		{"a", "a", 0},
		{"a", "a", 0},
		{"a", "a", 0},
	}
	objects := []obj{
		obj{"a", "a", 0},
		obj{"a", "a", 0},
		obj{"a", "a", 0},
		obj{"a", "a", 0},
		obj{"a", "a", 0},
		obj{"a", "a", 0},
		obj{"a", "a", 0},
		obj{"a", "a", 0},
		obj{"a", "a", 0},
		obj{"a", "a", 0},
	}
	errs := []error{errors.New("a"), errors.New("b"), errors.New("c"), errors.New("d"), errors.New("e")}
	types := map[string]func(e *Event) *Event{
		"Bool": func(e *Event) *Event {
			return e.Bool("k", bools[0])
		},
		"Bools": func(e *Event) *Event {
			return e.Bools("k", bools)
		},
		"Int": func(e *Event) *Event {
			return e.Int("k", ints[0])
		},
		"Ints": func(e *Event) *Event {
			return e.Ints("k", ints)
		},
		"Float": func(e *Event) *Event {
			return e.Float64("k", floats[0])
		},
		"Floats": func(e *Event) *Event {
			return e.Floats64("k", floats)
		},
		"Str": func(e *Event) *Event {
			return e.Str("k", strings[0])
		},
		"Strs": func(e *Event) *Event {
			return e.Strs("k", strings)
		},
		"Err": func(e *Event) *Event {
			return e.Err(errs[0])
		},
		"Errs": func(e *Event) *Event {
			return e.Errs("k", errs)
		},
		"Time": func(e *Event) *Event {
			return e.Time("k", times[0])
		},
		"Times": func(e *Event) *Event {
			return e.Times("k", times)
		},
		"Dur": func(e *Event) *Event {
			return e.Dur("k", durations[0])
		},
		"Durs": func(e *Event) *Event {
			return e.Durs("k", durations)
		},
		"Interface": func(e *Event) *Event {
			return e.Interface("k", interfaces[0])
		},
		"Interfaces": func(e *Event) *Event {
			return e.Interface("k", interfaces)
		},
		"Interface(Object)": func(e *Event) *Event {
			return e.Interface("k", objects[0])
		},
		"Interface(Objects)": func(e *Event) *Event {
			return e.Interface("k", objects)
		},
		"Object": func(e *Event) *Event {
			return e.Object("k", objects[0])
		},
	}
	logger := New(ioutil.Discard)
	b.ResetTimer()
	for name := range types {
		f := types[name]
		b.Run(name, func(b *testing.B) {
			b.RunParallel(func(pb *testing.PB) {
				for pb.Next() {
					f(logger.Info()).Msg("")
				}
			})
		})
	}
}
<commit_msg>Add benchmarks for context<commit_after>package zerolog

import (
	"errors"
	"io/ioutil"
	"testing"
	"time"
)

var (
	errExample  = errors.New("fail")
	fakeMessage = "Test logging, but use a somewhat realistic message length."
)

func BenchmarkLogEmpty(b *testing.B) {
	logger := New(ioutil.Discard)
	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			logger.Log().Msg("")
		}
	})
}

func BenchmarkDisabled(b *testing.B) {
	logger := New(ioutil.Discard).Level(Disabled)
	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			logger.Info().Msg(fakeMessage)
		}
	})
}

func BenchmarkInfo(b *testing.B) {
	logger := New(ioutil.Discard)
	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			logger.Info().Msg(fakeMessage)
		}
	})
}

func BenchmarkContextFields(b *testing.B) {
	logger := New(ioutil.Discard).With().
		Str("string", "four!").
		Time("time", time.Time{}).
		Int("int", 123).
		Float32("float", -2.203230293249593).
		Logger()
	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			logger.Info().Msg(fakeMessage)
		}
	})
}

func BenchmarkContextAppend(b *testing.B) {
	logger := New(ioutil.Discard).With().
		Str("foo", "bar").
		Logger()
	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			logger.With().Str("bar", "baz")
		}
	})
}

func BenchmarkLogFields(b *testing.B) {
	logger := New(ioutil.Discard)
	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			logger.Info().
				Str("string", "four!").
				Time("time", time.Time{}).
				Int("int", 123).
				Float32("float", -2.203230293249593).
				Msg(fakeMessage)
		}
	})
}

type obj struct {
	Pub  string
	Tag  string `json:"tag"`
	priv int
}

func (o obj) MarshalZerologObject(e *Event) {
	e.Str("Pub", o.Pub).
		Str("Tag", o.Tag).
		Int("priv", o.priv)
}

func BenchmarkLogFieldType(b *testing.B) {
	bools := []bool{true, false, true, false, true, false, true, false, true, false}
	ints := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
	floats := []float64{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
	strings := []string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j"}
	durations := []time.Duration{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
	times := []time.Time{
		time.Unix(0, 0),
		time.Unix(1, 0),
		time.Unix(2, 0),
		time.Unix(3, 0),
		time.Unix(4, 0),
		time.Unix(5, 0),
		time.Unix(6, 0),
		time.Unix(7, 0),
		time.Unix(8, 0),
		time.Unix(9, 0),
	}
	interfaces := []struct {
		Pub  string
		Tag  string `json:"tag"`
		priv int
	}{
		{"a", "a", 0},
		{"a", "a", 0},
		{"a", "a", 0},
		{"a", "a", 0},
		{"a", "a", 0},
		{"a", "a", 0},
		{"a", "a", 0},
		{"a", "a", 0},
		{"a", "a", 0},
		{"a", "a", 0},
	}
	objects := []obj{
		obj{"a", "a", 0},
		obj{"a", "a", 0},
		obj{"a", "a", 0},
		obj{"a", "a", 0},
		obj{"a", "a", 0},
		obj{"a", "a", 0},
		obj{"a", "a", 0},
		obj{"a", "a", 0},
		obj{"a", "a", 0},
		obj{"a", "a", 0},
	}
	errs := []error{errors.New("a"), errors.New("b"), errors.New("c"), errors.New("d"), errors.New("e")}
	types := map[string]func(e *Event) *Event{
		"Bool": func(e *Event) *Event {
			return e.Bool("k", bools[0])
		},
		"Bools": func(e *Event) *Event {
			return e.Bools("k", bools)
		},
		"Int": func(e *Event) *Event {
			return e.Int("k", ints[0])
		},
		"Ints": func(e *Event) *Event {
			return e.Ints("k", ints)
		},
		"Float": func(e *Event) *Event {
			return e.Float64("k", floats[0])
		},
		"Floats": func(e *Event) *Event {
			return e.Floats64("k", floats)
		},
		"Str": func(e *Event) *Event {
			return e.Str("k", strings[0])
		},
		"Strs": func(e *Event) *Event {
			return e.Strs("k", strings)
		},
		"Err": func(e *Event) *Event {
			return e.Err(errs[0])
		},
		"Errs": func(e *Event) *Event {
			return e.Errs("k", errs)
		},
		"Time": func(e *Event) *Event {
			return e.Time("k", times[0])
		},
		"Times": func(e *Event) *Event {
			return e.Times("k", times)
		},
		"Dur": func(e *Event) *Event {
			return e.Dur("k", durations[0])
		},
		"Durs": func(e *Event) *Event {
			return e.Durs("k", durations)
		},
		"Interface": func(e *Event) *Event {
			return e.Interface("k", interfaces[0])
		},
		"Interfaces": func(e *Event) *Event {
			return e.Interface("k", interfaces)
		},
		"Interface(Object)": func(e *Event) *Event {
			return e.Interface("k", objects[0])
		},
		"Interface(Objects)": func(e *Event) *Event {
			return e.Interface("k", objects)
		},
		"Object": func(e *Event) *Event {
			return e.Object("k", objects[0])
		},
	}
	logger := New(ioutil.Discard)
	b.ResetTimer()
	for name := range types {
		f := types[name]
		b.Run(name, func(b *testing.B) {
			b.RunParallel(func(pb *testing.PB) {
				for pb.Next() {
					f(logger.Info()).Msg("")
				}
			})
		})
	}
}

func BenchmarkContextFieldType(b *testing.B) {
	oldFormat := TimeFieldFormat
	TimeFieldFormat = ""
	defer func() { TimeFieldFormat = oldFormat }()
	bools := []bool{true, false, true, false, true, false, true, false, true, false}
	ints := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
	floats := []float64{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
	strings := []string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j"}
	durations := []time.Duration{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
	times := []time.Time{
		time.Unix(0, 0),
		time.Unix(1, 0),
		time.Unix(2, 0),
		time.Unix(3, 0),
		time.Unix(4, 0),
		time.Unix(5, 0),
		time.Unix(6, 0),
		time.Unix(7, 0),
		time.Unix(8, 0),
		time.Unix(9, 0),
	}
	interfaces := []struct {
		Pub  string
		Tag  string `json:"tag"`
		priv int
	}{
		{"a", "a", 0},
		{"a", "a", 0},
		{"a", "a", 0},
		{"a", "a", 0},
		{"a", "a", 0},
		{"a", "a", 0},
		{"a", "a", 0},
		{"a", "a", 0},
		{"a", "a", 0},
		{"a", "a", 0},
	}
	objects := []obj{
		obj{"a", "a", 0},
		obj{"a", "a", 0},
		obj{"a", "a", 0},
		obj{"a", "a", 0},
		obj{"a", "a", 0},
		obj{"a", "a", 0},
		obj{"a", "a", 0},
		obj{"a", "a", 0},
		obj{"a", "a", 0},
		obj{"a", "a", 0},
	}
	errs := []error{errors.New("a"), errors.New("b"), errors.New("c"), errors.New("d"), errors.New("e")}
	types := map[string]func(c Context) Context{
		"Bool": func(c Context) Context {
			return c.Bool("k", bools[0])
		},
		"Bools": func(c Context) Context {
			return c.Bools("k", bools)
		},
		"Int": func(c Context) Context {
			return c.Int("k", ints[0])
		},
		"Ints": func(c Context) Context {
			return c.Ints("k", ints)
		},
		"Float": func(c Context) Context {
			return c.Float64("k", floats[0])
		},
		"Floats": func(c Context) Context {
			return c.Floats64("k", floats)
		},
		"Str": func(c Context) Context {
			return c.Str("k", strings[0])
		},
		"Strs": func(c Context) Context {
			return c.Strs("k", strings)
		},
		"Err": func(c Context) Context {
			return c.Err(errs[0])
		},
		"Errs": func(c Context) Context {
			return c.Errs("k", errs)
		},
		"Time": func(c Context) Context {
			return c.Time("k", times[0])
		},
		"Times": func(c Context) Context {
			return c.Times("k", times)
		},
		"Dur": func(c Context) Context {
			return c.Dur("k", durations[0])
		},
		"Durs": func(c Context) Context {
			return c.Durs("k", durations)
		},
		"Interface": func(c Context) Context {
			return c.Interface("k", interfaces[0])
		},
		"Interfaces": func(c Context) Context {
			return c.Interface("k", interfaces)
		},
		"Interface(Object)": func(c Context) Context {
			return c.Interface("k", objects[0])
		},
		"Interface(Objects)": func(c Context) Context {
			return c.Interface("k", objects)
		},
		"Object": func(c Context) Context {
			return c.Object("k", objects[0])
		},
		"Timestamp": func(c Context) Context {
			return c.Timestamp()
		},
	}
	logger := New(ioutil.Discard)
	b.ResetTimer()
	for name := range types {
		f := types[name]
		b.Run(name, func(b *testing.B) {
			b.RunParallel(func(pb *testing.PB) {
				for pb.Next() {
					l := f(logger.With()).Logger()
					l.Info().Msg("")
				}
			})
		})
	}
}
<|endoftext|>


<commit_before>package http

import (
	"sort"
	"strconv"
	"strings"
	"time"

	"github.com/astaxie/beego/orm"
	"github.com/Cepave/open-falcon-backend/modules/query/g"
	"github.com/jasonlvhit/gocron"
	log "github.com/Sirupsen/logrus"
)

type Contacts struct {
	Id      int
	Name    string
	Phone   string
	Email   string
	Updated string
}

type Hosts struct {
	Id        int
	Hostname  string
	Exist     int
	Activate  int
	Platform  string
	Platforms string
	Idc       string
	Ip        string
	Isp       string
	Province  string
	City      string
	Status    string
	Updated   string
}

type Idcs struct {
	Id        int
	Popid     int
	Idc       string
	Bandwidth int
	Count     int
	Area      string
	Province  string
	City      string
	Updated   string
}

type Platforms struct {
	Id        int
	Platform  string
	Contacts  string
	Principal string
	Deputy    string
	Upgrader  string
	Count     int
	Updated   string
}

func SyncHostsAndContactsTable() {
	if g.Config().Hosts.Enabled || g.Config().Contacts.Enabled {
		if g.Config().Hosts.Enabled {
			updateMapData()
			syncHostsTable()
			intervalToSyncHostsTable := uint64(g.Config().Hosts.Interval)
			gocron.Every(intervalToSyncHostsTable).Seconds().Do(syncHostsTable)
		}
		if g.Config().Contacts.Enabled {
			syncContactsTable()
			intervalToSyncContactsTable := uint64(g.Config().Contacts.Interval)
			gocron.Every(intervalToSyncContactsTable).Seconds().Do(syncContactsTable)
		}
		<- gocron.Start()
	}
}

func getIDCMap() map[string]interface{} {
	idcMap := map[string]interface{}{}
	o := orm.NewOrm()
	var idcs []Idc
	sqlcommand := "SELECT pop_id, name, province, city FROM grafana.idc ORDER BY pop_id ASC"
	_, err := o.Raw(sqlcommand).QueryRows(&idcs)
	if err != nil {
		log.Errorf(err.Error())
	}
	for _, idc := range idcs {
		idcMap[strconv.Itoa(idc.Pop_id)] = idc
	}
	return idcMap
}

func updateHostsTable(hostnames []string, hostsMap map[string]map[string]string) {
	log.Debugf("func updateHostsTable()")
	var hosts []Hosts
	o := orm.NewOrm()
	o.Using("boss")
	_, err := o.QueryTable("hosts").All(&hosts)
	if err != nil {
		log.Errorf(err.Error())
	} else {
		format := "2006-01-02 15:04:05"
		for _, host := range hosts {
			updatedTime, _ := time.Parse(format, host.Updated)
			currentTime, _ := time.Parse(format, getNow())
			diff := currentTime.Unix() - updatedTime.Unix()
			if diff > 600 {
				host.Exist = 0
				_, err := o.Update(&host)
				if err != nil {
					log.Errorf(err.Error())
				}
			}
		}
	}

	idcMap := getIDCMap()
	var host Hosts
	for _, hostname := range hostnames {
		item := hostsMap[hostname]
		activate, _ := strconv.Atoi(item["activate"])
		host.Hostname = item["hostname"]
		host.Exist = 1
		host.Activate = activate
		host.Platform = item["platform"]
		host.Ip = item["ip"]
		host.Isp = strings.Split(item["hostname"], "-")[0]
		host.Updated = getNow()
		idcID := item["idcID"]
		if _, ok := idcMap[idcID]; ok {
			idc := idcMap[idcID]
			host.Idc = idc.(Idc).Name
			host.Province = idc.(Idc).Province
			host.City = idc.(Idc).City
		}
		hosts = append(hosts, host)
	}
	for _, item := range hosts {
		err := o.QueryTable("hosts").Filter("hostname", item.Hostname).One(&host)
		if err == orm.ErrNoRows {
			sql := "INSERT INTO boss.hosts("
			sql += "hostname, exist, activate, platform, idc, ip, "
			sql += "isp, province, city, updated) "
			sql += "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
			_, err := o.Raw(sql, item.Hostname, item.Exist, item.Activate, item.Platform, item.Idc, item.Ip, item.Isp, item.Province, item.City, item.Updated).Exec()
			if err != nil {
				log.Errorf(err.Error())
			}
		} else if err != nil {
			log.Errorf(err.Error())
		} else {
			item.Id = host.Id
			_, err := o.Update(&item)
			if err != nil {
				log.Errorf(err.Error())
			}
		}
	}
}

func updatePlatformsTable(platformNames []string, platformsMap map[string]map[string]interface{}) {
	log.Debugf("func updatePlatformsTable()")
	o := orm.NewOrm()
	o.Using("boss")
	var platform Platforms
	for _, platformName := range platformNames {
		group := platformsMap[platformName]
		err := o.QueryTable("platforms").Filter("platform", group["platformName"]).One(&platform)
		if err == orm.ErrNoRows {
			sql := "INSERT INTO boss.platforms(platform, contacts, count, updated) VALUES(?, ?, ?, ?)"
			_, err := o.Raw(sql, group["platformName"], group["contacts"], group["count"], getNow()).Exec()
			if err != nil {
				log.Errorf(err.Error())
			}
		} else if err != nil {
			log.Errorf(err.Error())
		} else {
			platform.Platform = group["platformName"].(string)
			platform.Count = group["count"].(int)
			platform.Updated = getNow()
			_, err := o.Update(&platform)
			if err != nil {
				log.Errorf(err.Error())
			}
		}
	}
}

func updateContactsTable(contactNames []string, contactsMap map[string]map[string]interface{}) {
	log.Debugf("func updateContactsTable()")
	o := orm.NewOrm()
	o.Using("boss")
	var contact Contacts
	for _, contactName := range contactNames {
		user := contactsMap[contactName]
		err := o.QueryTable("contacts").Filter("name", user["name"]).One(&contact)
		if err == orm.ErrNoRows {
			sql := "INSERT INTO boss.contacts(name, phone, email, updated) VALUES(?, ?, ?, ?)"
			_, err := o.Raw(sql, user["name"], user["phone"], user["email"], getNow()).Exec()
			if err != nil {
				log.Errorf(err.Error())
			}
		} else if err != nil {
			log.Errorf(err.Error())
		} else {
			contact.Email = user["email"].(string)
			contact.Phone = user["phone"].(string)
			contact.Updated = getNow()
			_, err := o.Update(&contact)
			if err != nil {
				log.Errorf(err.Error())
			}
		}
	}
}

func addContactsToPlatformsTable(contacts map[string]interface{}) {
	log.Debugf("func addContactsToPlatformsTable()")
	o := orm.NewOrm()
	o.Using("boss")
	var platforms []Platforms
	_, err := o.QueryTable("platforms").All(&platforms)
	if err != nil {
		log.Errorf(err.Error())
	} else {
		for _, platform := range platforms {
			contactsOfPlatform := []string{}
			platformName := platform.Platform
			if users, ok := contacts[platformName]; ok {
				for _, user := range users.([]interface{}) {
					contactName := user.(map[string]interface{})["name"].(string)
					contactsOfPlatform = appendUniqueString(contactsOfPlatform, contactName)
				}
			}
			if len(contactsOfPlatform) > 0 {
				platform.Contacts = strings.Join(contactsOfPlatform, ",")
				platform.Updated = getNow()
				_, err := o.Update(&platform)
				if err != nil {
					log.Errorf(err.Error())
				}
			}
		}
	}
}

func syncHostsTable() {
	o := orm.NewOrm()
	o.Using("boss")
	var rows []orm.Params
	sql := "SELECT updated FROM boss.hosts WHERE exist = 1 ORDER BY updated DESC LIMIT 1"
	num, err := o.Raw(sql).Values(&rows)
	if err != nil {
		log.Errorf(err.Error())
		return
	} else if num > 0 {
		format := "2006-01-02 15:04:05"
		updatedTime, _ := time.Parse(format, rows[0]["updated"].(string))
		currentTime, _ := time.Parse(format, getNow())
		diff := currentTime.Unix() - updatedTime.Unix()
		if int(diff) < g.Config().Hosts.Interval {
			return
		}
	}

	var nodes = make(map[string]interface{})
	errors := []string{}
	var result = make(map[string]interface{})
	result["error"] = errors
	getPlatformJSON(nodes, result)
	if nodes["status"] == nil {
		return
	} else if int(nodes["status"].(float64)) != 1 {
		return
	}
	platformNames := []string{}
	platformsMap := map[string]map[string]interface{}{}
	hostnames := []string{}
	hostsMap := map[string]map[string]string{}
	hostnamesMap := map[string]int{}
	idcIDs := []string{}
	hostname := ""
	for _, platform := range nodes["result"].([]interface{}) {
		countOfHosts := 0
		platformName := platform.(map[string]interface{})["platform"].(string)
		platformNames = appendUniqueString(platformNames, platformName)
		for _, device := range platform.(map[string]interface{})["ip_list"].([]interface{}) {
			hostname = device.(map[string]interface{})["hostname"].(string)
			ip := device.(map[string]interface{})["ip"].(string)
			if len(ip) > 0 && ip == getIPFromHostname(hostname, result) {
				if _, ok := hostnamesMap[hostname]; !ok {
					hostnames = append(hostnames, hostname)
					idcID := device.(map[string]interface{})["pop_id"].(string)
					host := map[string]string{
						"hostname": hostname,
						"activate": device.(map[string]interface{})["ip_status"].(string),
						"platform": platformName,
						"idcID":    idcID,
						"ip":       ip,
					}
					hostsMap[hostname] = host
					idcIDs = appendUniqueString(idcIDs, idcID)
					hostnamesMap[hostname] = 1
					countOfHosts++
				}
			}
		}
		platformsMap[platformName] = map[string]interface{}{
			"platformName": platformName,
			"count": countOfHosts,
			"contacts": "",
		}
	}
	sort.Strings(hostnames)
	sort.Strings(platformNames)
	log.Debugf("platformNames =", platformNames)
	updateHostsTable(hostnames, hostsMap)
	updatePlatformsTable(platformNames, platformsMap)
}

func syncContactsTable() {
	log.Debugf("func syncContactsTable()")
	o := orm.NewOrm()
	o.Using("boss")
	var rows []orm.Params
	sql := "SELECT updated FROM boss.contacts ORDER BY updated DESC LIMIT 1"
	num, err := o.Raw(sql).Values(&rows)
	if err != nil {
		log.Errorf(err.Error())
		return
	} else if num > 0 {
		format := "2006-01-02 15:04:05"
		updatedTime, _ := time.Parse(format, rows[0]["updated"].(string))
		currentTime, _ := time.Parse(format, getNow())
		diff := currentTime.Unix() - updatedTime.Unix()
		if int(diff) < g.Config().Contacts.Interval {
			return
		}
	}

	platformNames := []string{}
	sql = "SELECT DISTINCT platform FROM boss.platforms ORDER BY platform ASC"
	num, err = o.Raw(sql).Values(&rows)
	if err != nil {
		log.Errorf(err.Error())
		return
	} else if num > 0 {
		for _, row := range rows {
			platformNames = append(platformNames, row["platform"].(string))
		}
	}

	var nodes = make(map[string]interface{})
	errors := []string{}
	var result = make(map[string]interface{})
	result["error"] = errors
	getPlatformContact(strings.Join(platformNames, ","), nodes)
	contactNames := []string{}
	contactsMap := map[string]map[string]interface{}{}
	contacts := nodes["result"].(map[string]interface{})["items"].(map[string]interface{})
	for _, platformName := range platformNames {
		if items, ok := contacts[platformName]; ok {
			for _, user := range items.([]interface{}) {
				contactName := user.(map[string]interface{})["name"].(string)
				if _, ok := contactsMap[contactName]; !ok {
					contactsMap[contactName] = user.(map[string]interface{})
					contactNames = append(contactNames, contactName)
				}
			}
		}
	}
	sort.Strings(contactNames)
	updateContactsTable(contactNames, contactsMap)
	addContactsToPlatformsTable(contacts)
}
<commit_msg>[OWL-1165][query] add Ips struct<commit_after>package http

import (
	"sort"
	"strconv"
	"strings"
	"time"

	"github.com/astaxie/beego/orm"
	"github.com/Cepave/open-falcon-backend/modules/query/g"
	"github.com/jasonlvhit/gocron"
	log "github.com/Sirupsen/logrus"
)

type Contacts struct {
	Id      int
	Name    string
	Phone   string
	Email   string
	Updated string
}

type Hosts struct {
	Id        int
	Hostname  string
	Exist     int
	Activate  int
	Platform  string
	Platforms string
	Idc       string
	Ip        string
	Isp       string
	Province  string
	City      string
	Status    string
	Updated   string
}

type Idcs struct {
	Id        int
	Popid     int
	Idc       string
	Bandwidth int
	Count     int
	Area      string
	Province  string
	City      string
	Updated   string
}

type Ips struct {
	Id       int
	Ip       string
	Exist    int
	Status   int
	Hostname string
	Platform string
	Updated  string
}

type Platforms struct {
	Id        int
	Platform  string
	Contacts  string
	Principal string
	Deputy    string
	Upgrader  string
	Count     int
	Updated   string
}

func SyncHostsAndContactsTable() {
	if g.Config().Hosts.Enabled || g.Config().Contacts.Enabled {
		if g.Config().Hosts.Enabled {
			updateMapData()
			syncHostsTable()
			intervalToSyncHostsTable := uint64(g.Config().Hosts.Interval)
			gocron.Every(intervalToSyncHostsTable).Seconds().Do(syncHostsTable)
		}
		if g.Config().Contacts.Enabled {
			syncContactsTable()
			intervalToSyncContactsTable := uint64(g.Config().Contacts.Interval)
			gocron.Every(intervalToSyncContactsTable).Seconds().Do(syncContactsTable)
		}
		<- gocron.Start()
	}
}

func getIDCMap() map[string]interface{} {
	idcMap := map[string]interface{}{}
	o := orm.NewOrm()
	var idcs []Idc
	sqlcommand := "SELECT pop_id, name, province, city FROM grafana.idc ORDER BY pop_id ASC"
	_, err := o.Raw(sqlcommand).QueryRows(&idcs)
	if err != nil {
		log.Errorf(err.Error())
	}
	for _, idc := range idcs {
		idcMap[strconv.Itoa(idc.Pop_id)] = idc
	}
	return idcMap
}

func updateHostsTable(hostnames []string, hostsMap map[string]map[string]string) {
	log.Debugf("func updateHostsTable()")
	var hosts []Hosts
	o := orm.NewOrm()
	o.Using("boss")
	_, err := o.QueryTable("hosts").All(&hosts)
	if err != nil {
		log.Errorf(err.Error())
	} else {
		format := "2006-01-02 15:04:05"
		for _, host := range hosts {
			updatedTime, _ := time.Parse(format, host.Updated)
			currentTime, _ := time.Parse(format, getNow())
			diff := currentTime.Unix() - updatedTime.Unix()
			if diff > 600 {
				host.Exist = 0
				_, err := o.Update(&host)
				if err != nil {
					log.Errorf(err.Error())
				}
			}
		}
	}

	idcMap := getIDCMap()
	var host Hosts
	for _, hostname := range hostnames {
		item := hostsMap[hostname]
		activate, _ := strconv.Atoi(item["activate"])
		host.Hostname = item["hostname"]
		host.Exist = 1
		host.Activate = activate
		host.Platform = item["platform"]
		host.Ip = item["ip"]
		host.Isp = strings.Split(item["hostname"], "-")[0]
		host.Updated = getNow()
		idcID := item["idcID"]
		if _, ok := idcMap[idcID]; ok {
			idc := idcMap[idcID]
			host.Idc = idc.(Idc).Name
			host.Province = idc.(Idc).Province
			host.City = idc.(Idc).City
		}
		hosts = append(hosts, host)
	}
	for _, item := range hosts {
		err := o.QueryTable("hosts").Filter("hostname", item.Hostname).One(&host)
		if err == orm.ErrNoRows {
			sql := "INSERT INTO boss.hosts("
			sql += "hostname, exist, activate, platform, idc, ip, "
			sql += "isp, province, city, updated) "
			sql += "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
			_, err := o.Raw(sql, item.Hostname, item.Exist, item.Activate, item.Platform, item.Idc, item.Ip, item.Isp, item.Province, item.City, item.Updated).Exec()
			if err != nil {
				log.Errorf(err.Error())
			}
		} else if err != nil {
			log.Errorf(err.Error())
		} else {
			item.Id = host.Id
			_, err := o.Update(&item)
			if err != nil {
				log.Errorf(err.Error())
			}
		}
	}
}

func updatePlatformsTable(platformNames []string, platformsMap map[string]map[string]interface{}) {
	log.Debugf("func updatePlatformsTable()")
	o := orm.NewOrm()
	o.Using("boss")
	var platform Platforms
	for _, platformName := range platformNames {
		group := platformsMap[platformName]
		err := o.QueryTable("platforms").Filter("platform", group["platformName"]).One(&platform)
		if err == orm.ErrNoRows {
			sql := "INSERT INTO boss.platforms(platform, contacts, count, updated) VALUES(?, ?, ?, ?)"
			_, err := o.Raw(sql, group["platformName"], group["contacts"], group["count"], getNow()).Exec()
			if err != nil {
				log.Errorf(err.Error())
			}
		} else if err != nil {
			log.Errorf(err.Error())
		} else {
			platform.Platform = group["platformName"].(string)
			platform.Count = group["count"].(int)
			platform.Updated = getNow()
			_, err := o.Update(&platform)
			if err != nil {
				log.Errorf(err.Error())
			}
		}
	}
}

func updateContactsTable(contactNames []string, contactsMap map[string]map[string]interface{}) {
	log.Debugf("func updateContactsTable()")
	o := orm.NewOrm()
	o.Using("boss")
	var contact Contacts
	for _, contactName := range contactNames {
		user := contactsMap[contactName]
		err := o.QueryTable("contacts").Filter("name", user["name"]).One(&contact)
		if err == orm.ErrNoRows {
			sql := "INSERT INTO boss.contacts(name, phone, email, updated) VALUES(?, ?, ?, ?)"
			_, err := o.Raw(sql, user["name"], user["phone"], user["email"], getNow()).Exec()
			if err != nil {
				log.Errorf(err.Error())
			}
		} else if err != nil {
			log.Errorf(err.Error())
		} else {
			contact.Email = user["email"].(string)
			contact.Phone = user["phone"].(string)
			contact.Updated = getNow()
			_, err := o.Update(&contact)
			if err != nil {
				log.Errorf(err.Error())
			}
		}
	}
}

func addContactsToPlatformsTable(contacts map[string]interface{}) {
	log.Debugf("func addContactsToPlatformsTable()")
	o := orm.NewOrm()
	o.Using("boss")
	var platforms []Platforms
	_, err := o.QueryTable("platforms").All(&platforms)
	if err != nil {
		log.Errorf(err.Error())
	} else {
		for _, platform := range platforms {
			contactsOfPlatform := []string{}
			platformName := platform.Platform
			if users, ok := contacts[platformName]; ok {
				for _, user := range users.([]interface{}) {
					contactName := user.(map[string]interface{})["name"].(string)
					contactsOfPlatform = appendUniqueString(contactsOfPlatform, contactName)
				}
			}
			if len(contactsOfPlatform) > 0 {
				platform.Contacts = strings.Join(contactsOfPlatform, ",")
				platform.Updated = getNow()
				_, err := o.Update(&platform)
				if err != nil {
					log.Errorf(err.Error())
				}
			}
		}
	}
}

func syncHostsTable() {
	o := orm.NewOrm()
	o.Using("boss")
	var rows []orm.Params
	sql := "SELECT updated FROM boss.hosts WHERE exist = 1 ORDER BY updated DESC LIMIT 1"
	num, err := o.Raw(sql).Values(&rows)
	if err != nil {
		log.Errorf(err.Error())
		return
	} else if num > 0 {
		format := "2006-01-02 15:04:05"
		updatedTime, _ := time.Parse(format, rows[0]["updated"].(string))
		currentTime, _ := time.Parse(format, getNow())
		diff := currentTime.Unix() - updatedTime.Unix()
		if int(diff) < g.Config().Hosts.Interval {
			return
		}
	}

	var nodes = make(map[string]interface{})
	errors := []string{}
	var result = make(map[string]interface{})
	result["error"] = errors
	getPlatformJSON(nodes, result)
	if nodes["status"] == nil {
		return
	} else if int(nodes["status"].(float64)) != 1 {
		return
	}
	platformNames := []string{}
	platformsMap := map[string]map[string]interface{}{}
	hostnames := []string{}
	hostsMap := map[string]map[string]string{}
	hostnamesMap := map[string]int{}
	idcIDs := []string{}
	hostname := ""
	for _, platform := range nodes["result"].([]interface{}) {
		countOfHosts := 0
		platformName := platform.(map[string]interface{})["platform"].(string)
		platformNames = appendUniqueString(platformNames, platformName)
		for _, device := range platform.(map[string]interface{})["ip_list"].([]interface{}) {
			hostname = device.(map[string]interface{})["hostname"].(string)
			ip := device.(map[string]interface{})["ip"].(string)
			if len(ip) > 0 && ip == getIPFromHostname(hostname, result) {
				if _, ok := hostnamesMap[hostname]; !ok {
					hostnames = append(hostnames, hostname)
					idcID := device.(map[string]interface{})["pop_id"].(string)
					host := map[string]string{
						"hostname": hostname,
						"activate": device.(map[string]interface{})["ip_status"].(string),
						"platform": platformName,
						"idcID":    idcID,
						"ip":       ip,
					}
					hostsMap[hostname] = host
					idcIDs = appendUniqueString(idcIDs, idcID)
					hostnamesMap[hostname] = 1
					countOfHosts++
				}
			}
		}
		platformsMap[platformName] = map[string]interface{}{
			"platformName": platformName,
			"count": countOfHosts,
			"contacts": "",
		}
	}
	sort.Strings(hostnames)
	sort.Strings(platformNames)
	log.Debugf("platformNames =", platformNames)
	updateHostsTable(hostnames, hostsMap)
	updatePlatformsTable(platformNames, platformsMap)
}

func syncContactsTable() {
	log.Debugf("func syncContactsTable()")
	o := orm.NewOrm()
	o.Using("boss")
	var rows []orm.Params
	sql := "SELECT updated FROM boss.contacts ORDER BY updated DESC LIMIT 1"
	num, err := o.Raw(sql).Values(&rows)
	if err != nil {
		log.Errorf(err.Error())
		return
	} else if num > 0 {
		format := "2006-01-02 15:04:05"
		updatedTime, _ := time.Parse(format, rows[0]["updated"].(string))
		currentTime, _ := time.Parse(format, getNow())
		diff := currentTime.Unix() - updatedTime.Unix()
		if int(diff) < g.Config().Contacts.Interval {
			return
		}
	}

	platformNames := []string{}
	sql = "SELECT DISTINCT platform FROM boss.platforms ORDER BY platform ASC"
	num, err = o.Raw(sql).Values(&rows)
	if err != nil {
		log.Errorf(err.Error())
		return
	} else if num > 0 {
		for _, row := range rows {
			platformNames = append(platformNames, row["platform"].(string))
		}
	}

	var nodes = make(map[string]interface{})
	errors := []string{}
	var result = make(map[string]interface{})
	result["error"] = errors
	getPlatformContact(strings.Join(platformNames, ","), nodes)
	contactNames := []string{}
	contactsMap := map[string]map[string]interface{}{}
	contacts := nodes["result"].(map[string]interface{})["items"].(map[string]interface{})
	for _, platformName := range platformNames {
		if items, ok := contacts[platformName]; ok {
			for _, user := range items.([]interface{}) {
				contactName := user.(map[string]interface{})["name"].(string)
				if _, ok := contactsMap[contactName]; !ok {
					contactsMap[contactName] = user.(map[string]interface{})
					contactNames = append(contactNames, contactName)
				}
			}
		}
	}
	sort.Strings(contactNames)
	updateContactsTable(contactNames, contactsMap)
	addContactsToPlatformsTable(contacts)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net/url"
	"os"
	"path"
	"path/filepath"
	"sort"
	"strings"
)

type LocalRepository struct {
	FullPath  string
	RelPath   string
	RootPath  string
	PathParts []string

	repoPath   string
	vcsBackend *VCSBackend
}

func (repo *LocalRepository) RepoPath() string {
	if repo.repoPath != "" {
		return repo.repoPath
	}
	return repo.FullPath
}

func LocalRepositoryFromFullPath(fullPath string, backend *VCSBackend) (*LocalRepository, error) {
	var relPath string

	roots, err := localRepositoryRoots()
	if err != nil {
		return nil, err
	}
	var root string
	for _, root = range roots {
		if !strings.HasPrefix(fullPath, root) {
			continue
		}

		var err error
		relPath, err = filepath.Rel(root, fullPath)
		if err == nil {
			break
		}
	}

	if relPath == "" {
		return nil, fmt.Errorf("no local repository found for: %s", fullPath)
	}

	pathParts := strings.Split(relPath, string(filepath.Separator))

	return &LocalRepository{
		FullPath:   fullPath,
		RelPath:    filepath.ToSlash(relPath),
		RootPath:   root,
		PathParts:  pathParts,
		vcsBackend: backend,
	}, nil
}

func LocalRepositoryFromURL(remoteURL *url.URL) (*LocalRepository, error) {
	pathParts := append(
		[]string{remoteURL.Host}, strings.Split(remoteURL.Path, "/")...,
	)
	relPath := strings.TrimSuffix(path.Join(pathParts...), ".git")

	var localRepository *LocalRepository

	// Find existing local repository first
	if err := walkLocalRepositories(func(repo *LocalRepository) {
		if repo.RelPath == relPath {
			localRepository = repo
		}
	}); err != nil {
		return nil, err
	}

	if localRepository != nil {
		return localRepository, nil
	}

	prim, err := primaryLocalRepositoryRoot()
	if err != nil {
		return nil, err
	}
	// No local repository found, returning new one
	return &LocalRepository{
		FullPath:  path.Join(prim, relPath),
		RelPath:   relPath,
		RootPath:  prim,
		PathParts: pathParts,
	}, nil
}

// Subpaths returns lists of tail parts of relative path from the root directory (shortest first)
// for example, {"ghq", "motemen/ghq", "github.com/motemen/ghq"} for $root/github.com/motemen/ghq.
func (repo *LocalRepository) Subpaths() []string {
	tails := make([]string, len(repo.PathParts))

	for i := range repo.PathParts {
		tails[i] = strings.Join(repo.PathParts[len(repo.PathParts)-(i+1):], "/")
	}

	return tails
}

func (repo *LocalRepository) NonHostPath() string {
	return strings.Join(repo.PathParts[1:], "/")
}

func (repo *LocalRepository) IsUnderPrimaryRoot() bool {
	prim, err := primaryLocalRepositoryRoot()
	if err != nil {
		return false
	}
	return strings.HasPrefix(repo.FullPath, prim)
}

// Matches checks if any subpath of the local repository equals the query.
func (repo *LocalRepository) Matches(pathQuery string) bool {
	for _, p := range repo.Subpaths() {
		if p == pathQuery {
			return true
		}
	}

	return false
}

func (repo *LocalRepository) VCS() (*VCSBackend, string) {
	if repo.vcsBackend == nil {
		repo.vcsBackend = findVCSBackend(repo.FullPath)
	}
	return repo.vcsBackend, repo.RepoPath()
}

var vcsContentsMap = map[string]*VCSBackend{
	".git/svn":       GitsvnBackend,
	".git":           GitBackend,
	".svn":           SubversionBackend,
	".hg":            MercurialBackend,
	"_darcs":         DarcsBackend,
	".fslckout":      FossilBackend, // file
	"_FOSSIL_":       FossilBackend, // file
	"CVS/Repository": cvsDummyBackend,
	".bzr":           BazaarBackend,
}

var vcsContents = make([]string, 0, len(vcsContentsMap))

func init() {
	for k := range vcsContentsMap {
		vcsContents = append(vcsContents, k)
	}
	// Sort in order of length.
	// This is to check git/svn before git.
	sort.Slice(vcsContents, func(i, j int) bool {
		return len(vcsContents[i]) > len(vcsContents[j])
	})
}

func findVCSBackend(fpath string) *VCSBackend {
	for _, d := range vcsContents {
		if _, err := os.Stat(filepath.Join(fpath, d)); err == nil {
			return vcsContentsMap[d]
		}
	}
	return nil
}

func walkLocalRepositories(callback func(*LocalRepository)) error {
	roots, err := localRepositoryRoots()
	if err != nil {
		return err
	}
	for _, root := range roots {
		if err := filepath.Walk(root, func(fpath string, fileInfo os.FileInfo, err error) error {
			if err != nil || fileInfo == nil {
				return nil
			}

			if fileInfo.Mode()&os.ModeSymlink == os.ModeSymlink {
				realpath, err := filepath.EvalSymlinks(fpath)
				if err != nil {
					return nil
				}
				fileInfo, err = os.Stat(realpath)
				if err != nil {
					return nil
				}
			}
			if !fileInfo.IsDir() {
				return nil
			}
			vcsBackend := findVCSBackend(fpath)
			if vcsBackend == nil {
				return nil
			}

			repo, err := LocalRepositoryFromFullPath(fpath, vcsBackend)
			if err != nil {
				return nil
			}

			if repo == nil {
				return nil
			}
			callback(repo)
			return filepath.SkipDir
		}); err != nil {
			return err
		}
	}
	return nil
}

var _localRepositoryRoots []string

// localRepositoryRoots returns locally cloned repositories' root directories.
// The root dirs are determined as following:
//
//   - If GHQ_ROOT environment variable is nonempty, use it as the only root dir.
//   - Otherwise, use the result of `git config --get-all ghq.root` as the dirs.
//   - Otherwise, fallback to the default root, `~/.ghq`.
func localRepositoryRoots() ([]string, error) {
	if len(_localRepositoryRoots) != 0 {
		return _localRepositoryRoots, nil
	}

	envRoot := os.Getenv("GHQ_ROOT")
	if envRoot != "" {
		_localRepositoryRoots = filepath.SplitList(envRoot)
	} else {
		var err error
		if _localRepositoryRoots, err = GitConfigAll("ghq.root"); err != nil {
			return nil, err
		}
	}

	if len(_localRepositoryRoots) == 0 {
		homeDir, err := os.UserHomeDir()
		if err != nil {
			return nil, err
		}
		_localRepositoryRoots = []string{filepath.Join(homeDir, ".ghq")}
	}

	for i, v := range _localRepositoryRoots {
		path := filepath.Clean(v)
		if _, err := os.Stat(path); err == nil {
			if path, err = filepath.EvalSymlinks(path); err != nil {
				return nil, err
			}
		}
		if !filepath.IsAbs(path) {
			var err error
			if path, err = filepath.Abs(path); err != nil {
				return nil, err
			}
		}
		_localRepositoryRoots[i] = path
	}

	return _localRepositoryRoots, nil
}

func primaryLocalRepositoryRoot() (string, error) {
	roots, err := localRepositoryRoots()
	if err != nil {
		return "", err
	}
	return roots[0], nil
}
<commit_msg>walk up directory when finding VCS of LocalRepository<commit_after>package main

import (
	"fmt"
	"net/url"
	"os"
	"path"
	"path/filepath"
	"sort"
	"strings"
)

type LocalRepository struct {
	FullPath  string
	RelPath   string
	RootPath  string
	PathParts []string

	repoPath   string
	vcsBackend *VCSBackend
}

func (repo *LocalRepository) RepoPath() string {
	if repo.repoPath != "" {
		return repo.repoPath
	}
	return repo.FullPath
}

func LocalRepositoryFromFullPath(fullPath string, backend *VCSBackend) (*LocalRepository, error) {
	var relPath string

	roots, err := localRepositoryRoots()
	if err != nil {
		return nil, err
	}
	var root string
	for _, root = range roots {
		if !strings.HasPrefix(fullPath, root) {
			continue
		}

		var err error
		relPath, err = filepath.Rel(root, fullPath)
		if err == nil {
			break
		}
	}

	if relPath == "" {
		return nil, fmt.Errorf("no local repository found for: %s", fullPath)
	}

	pathParts := strings.Split(relPath, string(filepath.Separator))

	return &LocalRepository{
		FullPath:   fullPath,
		RelPath:    filepath.ToSlash(relPath),
		RootPath:   root,
		PathParts:  pathParts,
		vcsBackend: backend,
	}, nil
}

func LocalRepositoryFromURL(remoteURL *url.URL) (*LocalRepository, error) {
	pathParts := append(
		[]string{remoteURL.Host}, strings.Split(remoteURL.Path, "/")...,
	)
	relPath := strings.TrimSuffix(path.Join(pathParts...), ".git")

	var localRepository *LocalRepository

	// Find existing local repository first
	if err := walkLocalRepositories(func(repo *LocalRepository) {
		if repo.RelPath == relPath {
			localRepository = repo
		}
	}); err != nil {
		return nil, err
	}

	if localRepository != nil {
		return localRepository, nil
	}

	prim, err := primaryLocalRepositoryRoot()
	if err != nil {
		return nil, err
	}
	// No local repository found, returning new one
	return &LocalRepository{
		FullPath:  path.Join(prim, relPath),
		RelPath:   relPath,
		RootPath:  prim,
		PathParts: pathParts,
	}, nil
}

// Subpaths returns lists of tail parts of relative path from the root directory (shortest first)
// for example, {"ghq", "motemen/ghq", "github.com/motemen/ghq"} for $root/github.com/motemen/ghq.
func (repo *LocalRepository) Subpaths() []string {
	tails := make([]string, len(repo.PathParts))

	for i := range repo.PathParts {
		tails[i] = strings.Join(repo.PathParts[len(repo.PathParts)-(i+1):], "/")
	}

	return tails
}

func (repo *LocalRepository) NonHostPath() string {
	return strings.Join(repo.PathParts[1:], "/")
}

func (repo *LocalRepository) repoRootCandidates() []string {
	hostRoot := filepath.Join(repo.RootPath, repo.PathParts[0])
	nonHostParts := repo.PathParts[1:]
	candidates := make([]string, len(nonHostParts))
	for i := 0; i < len(nonHostParts); i++ {
		candidates[i] = filepath.Join(append(
			[]string{hostRoot}, nonHostParts[0:len(nonHostParts)-i]...)...)
	}
	return candidates
}

func (repo *LocalRepository) IsUnderPrimaryRoot() bool {
	prim, err := primaryLocalRepositoryRoot()
	if err != nil {
		return false
	}
	return strings.HasPrefix(repo.FullPath, prim)
}

// Matches checks if any subpath of the local repository equals the query.
func (repo *LocalRepository) Matches(pathQuery string) bool {
	for _, p := range repo.Subpaths() {
		if p == pathQuery {
			return true
		}
	}

	return false
}

func (repo *LocalRepository) VCS() (*VCSBackend, string) {
	if repo.vcsBackend == nil {
		for _, dir := range repo.repoRootCandidates() {
			backend := findVCSBackend(dir)
			if backend != nil {
				repo.vcsBackend = backend
				repo.repoPath = dir
				break
			}
		}
	}
	return repo.vcsBackend, repo.RepoPath()
}

var vcsContentsMap = map[string]*VCSBackend{
	".git/svn":       GitsvnBackend,
	".git":           GitBackend,
	".svn":           SubversionBackend,
	".hg":            MercurialBackend,
	"_darcs":         DarcsBackend,
	".fslckout":      FossilBackend, // file
	"_FOSSIL_":       FossilBackend, // file
	"CVS/Repository": cvsDummyBackend,
	".bzr":           BazaarBackend,
}

var vcsContents = make([]string, 0, len(vcsContentsMap))

func init() {
	for k := range vcsContentsMap {
		vcsContents = append(vcsContents, k)
	}
	// Sort in order of length.
	// This is to check git/svn before git.
	sort.Slice(vcsContents, func(i, j int) bool {
		return len(vcsContents[i]) > len(vcsContents[j])
	})
}

func findVCSBackend(fpath string) *VCSBackend {
	for _, d := range vcsContents {
		if _, err := os.Stat(filepath.Join(fpath, d)); err == nil {
			return vcsContentsMap[d]
		}
	}
	return nil
}

func walkLocalRepositories(callback func(*LocalRepository)) error {
	roots, err := localRepositoryRoots()
	if err != nil {
		return err
	}
	for _, root := range roots {
		if err := filepath.Walk(root, func(fpath string, fileInfo os.FileInfo, err error) error {
			if err != nil || fileInfo == nil {
				return nil
			}

			if fileInfo.Mode()&os.ModeSymlink == os.ModeSymlink {
				realpath, err := filepath.EvalSymlinks(fpath)
				if err != nil {
					return nil
				}
				fileInfo, err = os.Stat(realpath)
				if err != nil {
					return nil
				}
			}
			if !fileInfo.IsDir() {
				return nil
			}
			vcsBackend := findVCSBackend(fpath)
			if vcsBackend == nil {
				return nil
			}

			repo, err := LocalRepositoryFromFullPath(fpath, vcsBackend)
			if err != nil {
				return nil
			}

			if repo == nil {
				return nil
			}
			callback(repo)
			return filepath.SkipDir
		}); err != nil {
			return err
		}
	}
	return nil
}

var _localRepositoryRoots []string

// localRepositoryRoots returns locally cloned repositories' root directories.
// The root dirs are determined as following:
//
//   - If GHQ_ROOT environment variable is nonempty, use it as the only root dir.
//   - Otherwise, use the result of `git config --get-all ghq.root` as the dirs.
//   - Otherwise, fallback to the default root, `~/.ghq`.
func localRepositoryRoots() ([]string, error) {
	if len(_localRepositoryRoots) != 0 {
		return _localRepositoryRoots, nil
	}

	envRoot := os.Getenv("GHQ_ROOT")
	if envRoot != "" {
		_localRepositoryRoots = filepath.SplitList(envRoot)
	} else {
		var err error
		if _localRepositoryRoots, err = GitConfigAll("ghq.root"); err != nil {
			return nil, err
		}
	}

	if len(_localRepositoryRoots) == 0 {
		homeDir, err := os.UserHomeDir()
		if err != nil {
			return nil, err
		}
		_localRepositoryRoots = []string{filepath.Join(homeDir, ".ghq")}
	}

	for i, v := range _localRepositoryRoots {
		path := filepath.Clean(v)
		if _, err := os.Stat(path); err == nil {
			if path, err = filepath.EvalSymlinks(path); err != nil {
				return nil, err
			}
		}
		if !filepath.IsAbs(path) {
			var err error
			if path, err = filepath.Abs(path); err != nil {
				return nil, err
			}
		}
		_localRepositoryRoots[i] = path
	}

	return _localRepositoryRoots, nil
}

func primaryLocalRepositoryRoot() (string, error) {
	roots, err := localRepositoryRoots()
	if err != nil {
		return "", err
	}
	return roots[0], nil
}
<|endoftext|>


<commit_before>package main

import (
	_ "github.com/gliderlabs/logspout/transports/udp"
	_ "github.com/looplab/logspout-logstash"
)
<commit_msg>adding back logspout/httpstream to go module<commit_after>package main

import (
	_ "github.com/gliderlabs/logspout/transports/udp"
	_ "github.com/gliderlabs/logspout/httpstream"
	_ "github.com/looplab/logspout-logstash"
)
<|endoftext|>


<commit_before>package cloudformation

var AWSTemplateFormatVersion = "2010-09-09"

type Template struct {
	AWSTemplateFormatVersion string `json:"AWSTemplateFormatVersion,omitempty"`
	Description              string `json:"Description,omitempty"`

	Parameters map[string]*Parameter `json:"Parameters,omitempty"`
	Resources  Resources             `json:"Resources,omitempty"`
}

type Resources map[string]interface{}

type Resource struct {
	Type         string      `json:"Type,omitempty"`
	Properties   interface{} `json:"Properties,omitempty"`
	UpdatePolicy interface{} `json:"UpdatePolicy,omitempty"`
}

func NewResource(theType string, properties interface{}) *Resource {
	return &Resource{
		Type: theType, Properties: properties,
	}
}

type Properties struct {
	Type       string      `json:"Type,omitempty"`
	Properties *Properties `json:"Properties,omitempty"`
	MinValue   int         `json:"MinValue,omitempty"`
}

// AWS::ElasticLoadBalancing::LoadBalancer

type LoadBalancer struct {
	LoadBalancerName interface{}  `json:"LoadBalancerName,omitempty"`
	CrossZone        interface{}  `json:"CrossZone,omitempty"`
	HealthCheck      *HealthCheck `json:"HealthCheck,omitempty"`
	Listeners        []*Listener  `json:"Listeners,omitempty"`
}

type HealthCheck struct {
	HealthyThreshold   interface{} `json:"HealthyThreshold,omitempty"`
	Interval           interface{} `json:"Interval,omitempty"`
	Target             interface{} `json:"Target,omitempty"`
	Timeout            interface{} `json:"Timeout,omitempty"`
	UnhealthyThreshold interface{} `json:"UnhealthyThreshold,omitempty"`
}

type Listener struct {
	InstancePort     interface{}   `json:"InstancePort,omitempty"`
	LoadBalancerPort interface{}   `json:"LoadBalancerPort,omitempty"`
	Protocol         interface{}   `json:"Protocol,omitempty"`
	InstanceProtocol interface{}   `json:"InstanceProtocol,omitempty"`
	SSLCertificateId interface{}   `json:"SSLCertificateId,omitempty"`
	PolicyNames      []interface{} `json:"PolicyNames,omitempty"`
}

type Policy struct {
	PolicyName interface{}        `json:"PolicyName,omitempty"`
	PolicyType interface{}        `json:"PolicyType,omitempty"`
	Attributes []*PolicyAttribute `json:"Attributes,omitempty"`
}

// AWS::AutoScaling::LaunchConfiguration
type LaunchConfiguration struct {
	InstanceType        interface{}           `json:"InstanceType,omitempty"`
	ImageId             interface{}           `json:"ImageId,omitempty"`
	KeyName             interface{}           `json:"KeyName,omitempty"`
	SecurityGroups      []interface{}         `json:"SecurityGroups,omitempty"`
	UserData            interface{}           `json:"UserData,omitempty"`
	BlockDeviceMappings []*BlockDeviceMapping `json:"BlockDeviceMappings,omitempty"`
}

// AWS::AutoScaling::AutoScalingGroup",
type AutoScalingGroup struct {
	AvailabilityZones       []interface{} `json:"AvailabilityZones,omitempty"`
	Cooldown                interface{}   `json:"Cooldown,omitempty"`
	DesiredCapacity         interface{}   `json:"DesiredCapacity,omitempty"`
	HealthCheckGracePeriod  interface{}   `json:"HealthCheckGracePeriod,omitempty"`
	HealthCheckType         interface{}   `json:"HealthCheckType,omitempty"`
	LaunchConfigurationName interface{}   `json:"LaunchConfigurationName,omitempty"`
	LoadBalancerNames       []interface{} `json:"LoadBalancerNames,omitempty"`
	MaxSize                 interface{}   `json:"MaxSize,omitempty"`
	MinSize                 interface{}   `json:"MinSize,omitempty"`
}

type NotificationConfiguration struct {
	TopicARN          interface{}   `json:"TopicARN,omitempty"`
	NotificationTypes []interface{} `json:"NotificationTypes,omitempty"`
	Tags              []*Tag        `json:"Tags,omitempty"`
}

type Tag struct {
	Key               interface{} `json:"Key,omitempty"`
	Value             interface{} `json:"Value,omitempty"`
	PropagateAtLaunch interface{} `json:"PropagateAtLaunch,omitempty"`
	VPCZoneIdentifier interface{} `json:"VPCZoneIdentifier,omitempty"`
}

// AWS::CloudWatch::Alarm
type Alarm struct {
	ActionsEnabled     interface{}   `json:"ActionsEnabled,omitempty"`
	ComparisonOperator interface{}   `json:"ComparisonOperator,omitempty"`
	EvaluationPeriods  interface{}   `json:"EvaluationPeriods,omitempty"`
	MetricName         interface{}   `json:"MetricName,omitempty"`
	Namespace          interface{}   `json:"Namespace,omitempty"`
	Period             interface{}   `json:"Period,omitempty"`
	Statistic          interface{}   `json:"Statistic,omitempty"`
	Threshold          interface{}   `json:"Threshold,omitempty"`
	AlarmActions       []interface{} `json:"AlarmActions,omitempty"`
}

type BlockDeviceMapping struct {
	DeviceName interface{} `json:"DeviceName,omitempty"`
	Ebs        *Ebs        `json:"Ebs,omitempty"`
}

type Ebs struct {
	VolumeSize interface{} `json:"VolumeSize,omitempty"`
}

type PolicyAttribute struct {
	Name           string        `json:"Name,omitempty"`
	Value          string        `json:"Value,omitempty"`
	SecurityGroups []interface{} `json:"SecurityGroups,omitempty"`
	Subnets        interface{}   `json:"Subnets,omitempty"`
}

// AWS::EC2::SecurityGroup
type SecurityGroupProperties struct {
	GroupDescription     interface{}     `json:"GroupDescription,omitempty"`
	VpcId                interface{}     `json:"VpcId,omitempty"`
	SecurityGroupIngress []SecurityGroup `json:"SecurityGroupIngress,omitempty"`
	SecurityGroupEgress  []SecurityGroup `json:"SecurityGroupEgress,omitempty"`
}

type SecurityGroup struct {
	VpcId                interface{}          `json:"VpcId,omitempty"`
	GroupDescription     interface{}          `json:"GroupDescription,omitempty"`
	SecurityGroupEgress  []*SecurityGroupRule `json:"SecurityGroupEgress,omitempty"`
	SecurityGroupIngress []*SecurityGroupRule `json:"SecurityGroupIngress,omitempty"`
	Tags                 []*Tag               `json:"Tags,omitempty"`
}

type SecurityGroupRule struct {
	GroupId                    interface{} `json:"GroupId,omitempty"`
	IpProtocol                 string      `json:"IpProtocol,omitempty"`
	FromPort                   string      `json:"FromPort,omitempty"`
	ToPort                     string      `json:"ToPort,omitempty"`
	CidrIp                     string      `json:"CidrIp,omitempty"`
	SourceSecurityGroupId      interface{} `json:"SourceSecurityGroupId,omitempty"`
	SourceSecurityGroupOwnerId interface{} `json:"SourceSecurityGroupOwnerId,omitempty"`
}

// AWS::RDS::DBSubnetGroup
type DBSubnetGroup struct {
	DBSubnetGroupDescription interface{} `json:"DBSubnetGroupDescription,omitempty"`
	SubnetIds                interface{} `json:"SubnetIds,omitempty"`
}

// AWS::SNS::Topic
type Topic struct {
	DisplayName string `json:"DisplayName,omitempty"`
}

// AWS::ElastiCache::CacheCluster
type CacheClusterProperties struct {
	AutoMinorVersionUpgrade    interface{}   `json:"AutoMinorVersionUpgrade,omitempty"`
	CacheNodeType              interface{}   `json:"CacheNodeType,omitempty"`
	ClusterName                interface{}   `json:"ClusterName,omitempty"`
	Engine                     interface{}   `json:"Engine,omitempty"`
	EngineVersion              interface{}   `json:"EngineVersion,omitempty"`
	NotificationTopicArn       interface{}   `json:"NotificationTopicArn,omitempty"`
	NumCacheNodes              interface{}   `json:"NumCacheNodes,omitempty"`
	PreferredAvailabilityZone  interface{}   `json:"PreferredAvailabilityZone,omitempty"`
	PreferredMaintenanceWindow interface{}   `json:"PreferredMaintenanceWindow,omitempty"`
	VpcSecurityGroupIds        []interface{} `json:"VpcSecurityGroupIds,omitempty"`
}

// AWS::RDS::DBParameterGroup
type DBParameterGroup struct {
	Description                interface{}       `json:"Description,omitempty"`
	Family                     interface{}       `json:"Family,omitempty"`
	DBParameterGroupParameters map[string]string `json:"DBParameterGroupParameters,omitempty"`
}

// AWS::RDS::DBInstance
type DBInstance struct {
	AllocatedStorage           interface{}   `json:"	AllocatedStorage,omitempty"`
	AutoMinorVersionUpgrade    interface{}   `json:"	AutoMinorVersionUpgrade,omitempty"`
	BackupRetentionPeriod      interface{}   `json:"	BackupRetentionPeriod,omitempty"`
	DBSubnetGroupName          interface{}   `json:"	DBSubnetGroupName,omitempty"`
	DBInstanceClass            interface{}   `json:"	DBInstanceClass,omitempty"`
	DBInstanceIdentifier       interface{}   `json:"	DBInstanceIdentifier,omitempty"`
	DBName                     interface{}   `json:"	DBName,omitempty"`
	Engine                     interface{}   `json:"	Engine,omitempty"`
	EngineVersion              interface{}   `json:"	EngineVersion,omitempty"`
	LicenseModel               interface{}   `json:"	LicenseModel,omitempty"`
	MasterUsername             interface{}   `json:"	MasterUsername,omitempty"`
	MasterUserPassword         interface{}   `json:"	MasterUserPassword,omitempty"`
	MultiAZ                    interface{}   `json:"	MultiAZ,omitempty"`
	Port                       interface{}   `json:"	Port,omitempty"`
	PreferredBackupWindow      interface{}   `json:"	PreferredBackupWindow,omitempty"`
	PreferredMaintenanceWindow interface{}   `json:"	PreferredMaintenanceWindow,omitempty"`
	Tags                       []interface{} `json:"	Tags,omitempty"`
	VPCSecurityGroups          []interface{} `json:"	VPCSecurityGroups,omitempty"`
}

type Property struct {
	Type string `json:"Type,omitempty"`
}

type Parameter struct {
	Type    string `json:"Type,omitempty"`
	Default string `json:"Default,omitempty"`
}
<commit_msg>make some mappings more generic<commit_after>package cloudformation

var AWSTemplateFormatVersion = "2010-09-09"

type Template struct {
	AWSTemplateFormatVersion string `json:"AWSTemplateFormatVersion,omitempty"`
	Description              string `json:"Description,omitempty"`

	Parameters map[string]*Parameter `json:"Parameters,omitempty"`
	Resources  Resources             `json:"Resources,omitempty"`
}

type Resources map[string]interface{}

type Resource struct {
	Type         string      `json:"Type,omitempty"`
	Properties   interface{} `json:"Properties,omitempty"`
	UpdatePolicy interface{} `json:"UpdatePolicy,omitempty"`
}

func NewResource(theType string, properties interface{}) *Resource {
	return &Resource{
		Type: theType, Properties: properties,
	}
}

type Properties struct {
	Type       string      `json:"Type,omitempty"`
	Properties *Properties `json:"Properties,omitempty"`
	MinValue   int         `json:"MinValue,omitempty"`
}

// AWS::ElasticLoadBalancing::LoadBalancer

type LoadBalancer struct {
	LoadBalancerName interface{}  `json:"LoadBalancerName,omitempty"`
	CrossZone        interface{}  `json:"CrossZone,omitempty"`
	HealthCheck      *HealthCheck `json:"HealthCheck,omitempty"`
	Listeners        []*Listener  `json:"Listeners,omitempty"`
}

type HealthCheck struct {
	HealthyThreshold   interface{} `json:"HealthyThreshold,omitempty"`
	Interval           interface{} `json:"Interval,omitempty"`
	Target             interface{} `json:"Target,omitempty"`
	Timeout            interface{} `json:"Timeout,omitempty"`
	UnhealthyThreshold interface{} `json:"UnhealthyThreshold,omitempty"`
}

type Listener struct {
	InstancePort     interface{}   `json:"InstancePort,omitempty"`
	LoadBalancerPort interface{}   `json:"LoadBalancerPort,omitempty"`
	Protocol         interface{}   `json:"Protocol,omitempty"`
	InstanceProtocol interface{}   `json:"InstanceProtocol,omitempty"`
	SSLCertificateId interface{}   `json:"SSLCertificateId,omitempty"`
	PolicyNames      []interface{} `json:"PolicyNames,omitempty"`
}

type Policy struct {
	PolicyName interface{}        `json:"PolicyName,omitempty"`
	PolicyType interface{}        `json:"PolicyType,omitempty"`
	Attributes []*PolicyAttribute `json:"Attributes,omitempty"`
}

// AWS::AutoScaling::LaunchConfiguration
type LaunchConfiguration struct {
	InstanceType        interface{}           `json:"InstanceType,omitempty"`
	ImageId             interface{}           `json:"ImageId,omitempty"`
	KeyName             interface{}           `json:"KeyName,omitempty"`
	SecurityGroups      []interface{}         `json:"SecurityGroups,omitempty"`
	UserData            interface{}           `json:"UserData,omitempty"`
	BlockDeviceMappings []*BlockDeviceMapping `json:"BlockDeviceMappings,omitempty"`
}

// AWS::AutoScaling::AutoScalingGroup",
type AutoScalingGroup struct {
	AvailabilityZones       []interface{} `json:"AvailabilityZones,omitempty"`
	Cooldown                interface{}   `json:"Cooldown,omitempty"`
	DesiredCapacity         interface{}   `json:"DesiredCapacity,omitempty"`
	HealthCheckGracePeriod  interface{}   `json:"HealthCheckGracePeriod,omitempty"`
	HealthCheckType         interface{}   `json:"HealthCheckType,omitempty"`
	LaunchConfigurationName interface{}   `json:"LaunchConfigurationName,omitempty"`
	LoadBalancerNames       []interface{} `json:"LoadBalancerNames,omitempty"`
	MaxSize                 interface{}   `json:"MaxSize,omitempty"`
	MinSize                 interface{}   `json:"MinSize,omitempty"`
}

type NotificationConfiguration struct {
	TopicARN          interface{}   `json:"TopicARN,omitempty"`
	NotificationTypes []interface{} `json:"NotificationTypes,omitempty"`
	Tags              []*Tag        `json:"Tags,omitempty"`
}

type Tag struct {
	Key               interface{} `json:"Key,omitempty"`
	Value             interface{} `json:"Value,omitempty"`
	PropagateAtLaunch interface{} `json:"PropagateAtLaunch,omitempty"`
	VPCZoneIdentifier interface{} `json:"VPCZoneIdentifier,omitempty"`
}

// AWS::CloudWatch::Alarm
type Alarm struct {
	ActionsEnabled     interface{}   `json:"ActionsEnabled,omitempty"`
	ComparisonOperator interface{}   `json:"ComparisonOperator,omitempty"`
	EvaluationPeriods  interface{}   `json:"EvaluationPeriods,omitempty"`
	MetricName         interface{}   `json:"MetricName,omitempty"`
	Namespace          interface{}   `json:"Namespace,omitempty"`
	Period             interface{}   `json:"Period,omitempty"`
	Statistic          interface{}   `json:"Statistic,omitempty"`
	Threshold          interface{}   `json:"Threshold,omitempty"`
	AlarmActions       []interface{} `json:"AlarmActions,omitempty"`
}

type BlockDeviceMapping struct {
	DeviceName interface{} `json:"DeviceName,omitempty"`
	Ebs        *Ebs        `json:"Ebs,omitempty"`
}

type Ebs struct {
	VolumeSize interface{} `json:"VolumeSize,omitempty"`
}

type PolicyAttribute struct {
	Name           interface{}   `json:"Name,omitempty"`
	Value          interface{}   `json:"Value,omitempty"`
	SecurityGroups []interface{} `json:"SecurityGroups,omitempty"`
	Subnets        interface{}   `json:"Subnets,omitempty"`
}

// AWS::EC2::SecurityGroup
type SecurityGroupProperties struct {
	GroupDescription     interface{}     `json:"GroupDescription,omitempty"`
	VpcId                interface{}     `json:"VpcId,omitempty"`
	SecurityGroupIngress []SecurityGroup `json:"SecurityGroupIngress,omitempty"`
	SecurityGroupEgress  []SecurityGroup `json:"SecurityGroupEgress,omitempty"`
}

type SecurityGroup struct {
	VpcId                interface{}          `json:"VpcId,omitempty"`
	GroupDescription     interface{}          `json:"GroupDescription,omitempty"`
	SecurityGroupEgress  []*SecurityGroupRule `json:"SecurityGroupEgress,omitempty"`
	SecurityGroupIngress []*SecurityGroupRule `json:"SecurityGroupIngress,omitempty"`
	Tags                 []*Tag               `json:"Tags,omitempty"`
}

type SecurityGroupRule struct {
	GroupId                    interface{} `json:"GroupId,omitempty"`
	IpProtocol                 interface{} `json:"IpProtocol,omitempty"`
	FromPort                   interface{} `json:"FromPort,omitempty"`
	ToPort                     interface{} `json:"ToPort,omitempty"`
	CidrIp                     interface{} `json:"CidrIp,omitempty"`
	SourceSecurityGroupId      interface{} `json:"SourceSecurityGroupId,omitempty"`
	SourceSecurityGroupOwnerId interface{} `json:"SourceSecurityGroupOwnerId,omitempty"`
}

// AWS::RDS::DBSubnetGroup
type DBSubnetGroup struct {
	DBSubnetGroupDescription interface{} `json:"DBSubnetGroupDescription,omitempty"`
	SubnetIds                interface{} `json:"SubnetIds,omitempty"`
}

// AWS::SNS::Topic
type Topic struct {
	DisplayName string `json:"DisplayName,omitempty"`
}

// AWS::ElastiCache::CacheCluster
type CacheClusterProperties struct {
	AutoMinorVersionUpgrade    interface{}   `json:"AutoMinorVersionUpgrade,omitempty"`
	CacheNodeType              interface{}   `json:"CacheNodeType,omitempty"`
	ClusterName                interface{}   `json:"ClusterName,omitempty"`
	Engine                     interface{}   `json:"Engine,omitempty"`
	EngineVersion              interface{}   `json:"EngineVersion,omitempty"`
	NotificationTopicArn       interface{}   `json:"NotificationTopicArn,omitempty"`
	NumCacheNodes              interface{}   `json:"NumCacheNodes,omitempty"`
	PreferredAvailabilityZone  interface{}   `json:"PreferredAvailabilityZone,omitempty"`
	PreferredMaintenanceWindow interface{}   `json:"PreferredMaintenanceWindow,omitempty"`
	VpcSecurityGroupIds        []interface{} `json:"VpcSecurityGroupIds,omitempty"`
}

// AWS::RDS::DBParameterGroup
type DBParameterGroup struct {
	Description                interface{}       `json:"Description,omitempty"`
	Family                     interface{}       `json:"Family,omitempty"`
	DBParameterGroupParameters map[string]string `json:"DBParameterGroupParameters,omitempty"`
}

// AWS::RDS::DBInstance
type DBInstance struct {
	AllocatedStorage           interface{}   `json:"	AllocatedStorage,omitempty"`
	AutoMinorVersionUpgrade    interface{}   `json:"	AutoMinorVersionUpgrade,omitempty"`
	BackupRetentionPeriod      interface{}   `json:"	BackupRetentionPeriod,omitempty"`
	DBSubnetGroupName          interface{}   `json:"	DBSubnetGroupName,omitempty"`
	DBInstanceClass            interface{}   `json:"	DBInstanceClass,omitempty"`
	DBInstanceIdentifier       interface{}   `json:"	DBInstanceIdentifier,omitempty"`
	DBName                     interface{}   `json:"	DBName,omitempty"`
	Engine                     interface{}   `json:"	Engine,omitempty"`
	EngineVersion              interface{}   `json:"	EngineVersion,omitempty"`
	LicenseModel               interface{}   `json:"	LicenseModel,omitempty"`
	MasterUsername             interface{}   `json:"	MasterUsername,omitempty"`
	MasterUserPassword         interface{}   `json:"	MasterUserPassword,omitempty"`
	MultiAZ                    interface{}   `json:"	MultiAZ,omitempty"`
	Port                       interface{}   `json:"	Port,omitempty"`
	PreferredBackupWindow      interface{}   `json:"	PreferredBackupWindow,omitempty"`
	PreferredMaintenanceWindow interface{}   `json:"	PreferredMaintenanceWindow,omitempty"`
	Tags                       []interface{} `json:"	Tags,omitempty"`
	VPCSecurityGroups          []interface{} `json:"	VPCSecurityGroups,omitempty"`
}

type Property struct {
	Type string `json:"Type,omitempty"`
}

type Parameter struct {
	Type    string `json:"Type,omitempty"`
	Default string `json:"Default,omitempty"`
}
<|endoftext|>


<commit_before>package mail_test

import (
	"io"
	"io/ioutil"
	"log"
	"strings"
	"testing"

	"github.com/emersion/go-messages/mail"
)

func ExampleReader() {
	// Let's assume r is an io.Reader that contains a mail.
	var r io.Reader

	// Create a new mail reader
	mr, err := mail.CreateReader(r)
	if err != nil {
		log.Fatal(err)
	}

	// Read each mail's part
	for {
		p, err := mr.NextPart()
		if err == io.EOF {
			break
		} else if err != nil {
			log.Fatal(err)
		}

		switch h := p.Header.(type) {
		case mail.TextHeader:
			b, _ := ioutil.ReadAll(p.Body)
			log.Println("Got text: %v", string(b))
		case mail.AttachmentHeader:
			filename, _ := h.Filename()
			log.Println("Got attachment: %v", filename)
		}
	}
}

func testReader(t *testing.T, r io.Reader) {
	mr, err := mail.CreateReader(r)
	if err != nil {
		log.Fatal(err)
	}
	defer mr.Close()

	i := 0
	for {
		p, err := mr.NextPart()
		if err == io.EOF {
			break
		} else if err != nil {
			log.Fatal(err)
		}

		var expectedBody string
		switch i {
		case 0:
			h, ok := p.Header.(mail.TextHeader)
			if !ok {
				t.Fatalf("Expected a TextHeader, but got a %T", p.Header)
			}

			if h.IsHTML() {
				t.Errorf("Expected a plaintext part, not an HTML part")
			}

			expectedBody = "Who are you?"
		case 1:
			h, ok := p.Header.(mail.AttachmentHeader)
			if !ok {
				t.Fatalf("Expected an AttachmentHeader, but got a %T", p.Header)
			}

			if filename, err := h.Filename(); err != nil {
				t.Error("Expected no error while parsing filename, but got:", err)
			} else if filename != "note.txt" {
				t.Errorf("Expected filename to be %q but got %q", "note.txt", filename)
			}

			expectedBody = "I'm Mitsuha."
		}

		if b, err := ioutil.ReadAll(p.Body); err != nil {
			t.Error("Expected no error while reading part body, but got:", err)
		} else if string(b) != expectedBody {
			t.Errorf("Expected part body to be:\n%v\nbut got:\n%v", expectedBody, string(b))
		}

		i++
	}

	if i != 2 {
		t.Errorf("Expected exactly two parts but got %v", i)
	}
}

func TestReader(t *testing.T) {
	testReader(t, strings.NewReader(mailString))
}
<commit_msg>mail: adds non-multipart test for Reader<commit_after>package mail_test

import (
	"io"
	"io/ioutil"
	"log"
	"strings"
	"testing"

	"github.com/emersion/go-messages/mail"
)

func ExampleReader() {
	// Let's assume r is an io.Reader that contains a mail.
	var r io.Reader

	// Create a new mail reader
	mr, err := mail.CreateReader(r)
	if err != nil {
		log.Fatal(err)
	}

	// Read each mail's part
	for {
		p, err := mr.NextPart()
		if err == io.EOF {
			break
		} else if err != nil {
			log.Fatal(err)
		}

		switch h := p.Header.(type) {
		case mail.TextHeader:
			b, _ := ioutil.ReadAll(p.Body)
			log.Println("Got text: %v", string(b))
		case mail.AttachmentHeader:
			filename, _ := h.Filename()
			log.Println("Got attachment: %v", filename)
		}
	}
}

func testReader(t *testing.T, r io.Reader) {
	mr, err := mail.CreateReader(r)
	if err != nil {
		log.Fatal(err)
	}
	defer mr.Close()

	i := 0
	for {
		p, err := mr.NextPart()
		if err == io.EOF {
			break
		} else if err != nil {
			log.Fatal(err)
		}

		var expectedBody string
		switch i {
		case 0:
			h, ok := p.Header.(mail.TextHeader)
			if !ok {
				t.Fatalf("Expected a TextHeader, but got a %T", p.Header)
			}

			if h.IsHTML() {
				t.Errorf("Expected a plaintext part, not an HTML part")
			}

			expectedBody = "Who are you?"
		case 1:
			h, ok := p.Header.(mail.AttachmentHeader)
			if !ok {
				t.Fatalf("Expected an AttachmentHeader, but got a %T", p.Header)
			}

			if filename, err := h.Filename(); err != nil {
				t.Error("Expected no error while parsing filename, but got:", err)
			} else if filename != "note.txt" {
				t.Errorf("Expected filename to be %q but got %q", "note.txt", filename)
			}

			expectedBody = "I'm Mitsuha."
		}

		if b, err := ioutil.ReadAll(p.Body); err != nil {
			t.Error("Expected no error while reading part body, but got:", err)
		} else if string(b) != expectedBody {
			t.Errorf("Expected part body to be:\n%v\nbut got:\n%v", expectedBody, string(b))
		}

		i++
	}

	if i != 2 {
		t.Errorf("Expected exactly two parts but got %v", i)
	}
}

func TestReader(t *testing.T) {
	testReader(t, strings.NewReader(mailString))
}

func TestReader_nonMultipart(t *testing.T) {
	s := "Content-Type: text/plain\r\n" +
		"\r\n" +
		"Who are you?"

	mr, err := mail.CreateReader(strings.NewReader(s))
	if err != nil {
		log.Fatal(err)
	}
	defer mr.Close()

	p, err := mr.NextPart()
	if err != nil {
		t.Fatal("Expected no error while reading part, got:", err)
	}

	if _, ok := p.Header.(mail.TextHeader); !ok {
		t.Fatalf("Expected a TextHeader, but got a %T", p.Header)
	}

	expectedBody := "Who are you?"
	if b, err := ioutil.ReadAll(p.Body); err != nil {
		t.Error("Expected no error while reading part body, but got:", err)
	} else if string(b) != expectedBody {
		t.Errorf("Expected part body to be:\n%v\nbut got:\n%v", expectedBody, string(b))
	}

	if _, err := mr.NextPart(); err != io.EOF {
		t.Fatal("Expected io.EOF while reading part, but got:", err)
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package benchmarks

import (
	"errors"
	"testing"
	"time"

	"github.com/uber-common/zap"
)

var errExample = errors.New("fail")

type user struct {
	Name      string    `json:"name"`
	Email     string    `json:"email"`
	CreatedAt time.Time `json:"created_at"`
}

func (u user) MarshalLog(kv zap.KeyValue) error {
	kv.AddString("name", u.Name)
	kv.AddString("email", u.Email)
	kv.AddInt64("created_at", u.CreatedAt.UnixNano())
	return nil
}

var _jane = user{
	Name:      "Jane Doe",
	Email:     "jane@test.com",
	CreatedAt: time.Date(1980, 1, 1, 12, 0, 0, 0, time.UTC),
}

func BenchmarkZapAddingFields(b *testing.B) {
	logger := zap.NewJSON(zap.All, zap.Output(zap.Discard))
	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			logger.Info("Go fast.",
				zap.Int("int", 1),
				zap.Int64("int64", 2),
				zap.Float64("float", 3.0),
				zap.String("string", "four!"),
				zap.Bool("bool", true),
				zap.Time("time", time.Unix(0, 0)),
				zap.Err(errExample),
				zap.Duration("duration", time.Second),
				zap.Marshaler("user-defined type", _jane),
				zap.String("another string", "done!"),
			)
		}
	})
}

func BenchmarkZapWithAccumulatedContext(b *testing.B) {
	logger := zap.NewJSON(zap.All, zap.Output(zap.Discard), zap.Fields(
		zap.Int("int", 1),
		zap.Int64("int64", 2),
		zap.Float64("float", 3.0),
		zap.String("string", "four!"),
		zap.Bool("bool", true),
		zap.Time("time", time.Unix(0, 0)),
		zap.Err(errExample),
		zap.Duration("duration", time.Second),
		zap.Marshaler("user-defined type", _jane),
		zap.String("another string", "done!"),
	))
	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			logger.Info("Go really fast.")
		}
	})
}

func BenchmarkZapWithoutFields(b *testing.B) {
	logger := zap.NewJSON(zap.All, zap.Output(zap.Discard))
	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			logger.Info("Go fast.")
		}
	})
}
<commit_msg>Add a benchmark for disabled log levels (#39)<commit_after>// Copyright (c) 2016 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package benchmarks

import (
	"errors"
	"testing"
	"time"

	"github.com/uber-common/zap"
)

var errExample = errors.New("fail")

type user struct {
	Name      string    `json:"name"`
	Email     string    `json:"email"`
	CreatedAt time.Time `json:"created_at"`
}

func (u user) MarshalLog(kv zap.KeyValue) error {
	kv.AddString("name", u.Name)
	kv.AddString("email", u.Email)
	kv.AddInt64("created_at", u.CreatedAt.UnixNano())
	return nil
}

var _jane = user{
	Name:      "Jane Doe",
	Email:     "jane@test.com",
	CreatedAt: time.Date(1980, 1, 1, 12, 0, 0, 0, time.UTC),
}

func fakeFields() []zap.Field {
	return []zap.Field{
		zap.Int("int", 1),
		zap.Int64("int64", 2),
		zap.Float64("float", 3.0),
		zap.String("string", "four!"),
		zap.Bool("bool", true),
		zap.Time("time", time.Unix(0, 0)),
		zap.Err(errExample),
		zap.Duration("duration", time.Second),
		zap.Marshaler("user-defined type", _jane),
		zap.String("another string", "done!"),
	}
}

func BenchmarkZapDisabledLevelsWithoutFields(b *testing.B) {
	logger := zap.NewJSON(zap.Error, zap.Output(zap.Discard))
	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			logger.Info("Should be discarded.")
		}
	})
}

func BenchmarkZapDisabledLevelsAccumulatedContext(b *testing.B) {
	context := fakeFields()
	logger := zap.NewJSON(zap.Error, zap.Output(zap.Discard), zap.Fields(context...))
	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			logger.Info("Should be discarded.")
		}
	})
}

func BenchmarkZapDisabledLevelsAddingFields(b *testing.B) {
	logger := zap.NewJSON(zap.Error, zap.Output(zap.Discard))
	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			logger.Info("Should be discarded.", fakeFields()...)
		}
	})
}
func BenchmarkZapAddingFields(b *testing.B) {
	logger := zap.NewJSON(zap.All, zap.Output(zap.Discard))
	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			logger.Info("Go fast.", fakeFields()...)
		}
	})
}

func BenchmarkZapWithAccumulatedContext(b *testing.B) {
	context := fakeFields()
	logger := zap.NewJSON(zap.All, zap.Output(zap.Discard), zap.Fields(context...))
	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			logger.Info("Go really fast.")
		}
	})
}

func BenchmarkZapWithoutFields(b *testing.B) {
	logger := zap.NewJSON(zap.All, zap.Output(zap.Discard))
	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			logger.Info("Go fast.")
		}
	})
}
<|endoftext|>


<commit_before>package grep

import (
	"flag"
	"fmt"
	"github.com/surma/gobox/pkg/common"
	"io"
	"os"
	"regexp"
)

var (
	flagSet  = flag.NewFlagSet("grep", flag.PanicOnError)
	helpFlag = flagSet.Bool("help", false, "Show this help")
)

func Grep(call []string) error {
	e := flagSet.Parse(call[1:])
	if e != nil {
		return e
	}

	if flagSet.NArg() < 1 || *helpFlag {
		println("`grep` <pattern> [<file>...]")
		flagSet.PrintDefaults()
		return nil
	}

	pattern, err := regexp.Compile(flagSet.Arg(0))
	if err != nil {
		return err
	}

	if flagSet.NArg() == 1 {
		doGrep(pattern, os.Stdin, "<stdin>", false)
	} else {
		for _, fn := range flagSet.Args()[1:] {
			if fh, err := os.Open(fn); err == nil {
				func() {
					defer fh.Close()
					doGrep(pattern, fh, fn, flagSet.NArg() > 2)
				}()
			} else {
				fmt.Fprintf(os.Stderr, "grep: %s: %v\n", fn, err)
			}
		}
	}

	return nil
}

func doGrep(pattern *regexp.Regexp, fh io.Reader, fn string, print_fn bool) {
	buf := common.NewBufferedReader(fh)

	for {
		line, err := buf.ReadWholeLine()
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error while reading from %s: %v\n", fn, err)
			return
		}
		if line == "" {
			continue
		}

		if pattern.MatchString(line) {
			if print_fn {
				fmt.Printf("%s:", fn)
			}
			fmt.Printf("%s\n", line)
		}
	}
}
<commit_msg>Exit on EOF.<commit_after>package grep

import (
	"flag"
	"fmt"
	"github.com/surma/gobox/pkg/common"
	"io"
	"os"
	"regexp"
)

var (
	flagSet  = flag.NewFlagSet("grep", flag.PanicOnError)
	helpFlag = flagSet.Bool("help", false, "Show this help")
)

func Grep(call []string) error {
	e := flagSet.Parse(call[1:])
	if e != nil {
		return e
	}

	if flagSet.NArg() < 1 || *helpFlag {
		println("`grep` <pattern> [<file>...]")
		flagSet.PrintDefaults()
		return nil
	}

	pattern, err := regexp.Compile(flagSet.Arg(0))
	if err != nil {
		return err
	}

	if flagSet.NArg() == 1 {
		doGrep(pattern, os.Stdin, "<stdin>", false)
	} else {
		for _, fn := range flagSet.Args()[1:] {
			if fh, err := os.Open(fn); err == nil {
				func() {
					defer fh.Close()
					doGrep(pattern, fh, fn, flagSet.NArg() > 2)
				}()
			} else {
				fmt.Fprintf(os.Stderr, "grep: %s: %v\n", fn, err)
			}
		}
	}

	return nil
}

func doGrep(pattern *regexp.Regexp, fh io.Reader, fn string, print_fn bool) {
	buf := common.NewBufferedReader(fh)

	for {
		line, err := buf.ReadWholeLine()
		if err == io.EOF {
			return
		}
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error while reading from %s: %v\n", fn, err)
			return
		}
		if line == "" {
			continue
		}

		if pattern.MatchString(line) {
			if print_fn {
				fmt.Printf("%s:", fn)
			}
			fmt.Printf("%s\n", line)
		}
	}
}
<|endoftext|>