<commit_before>package gofpdf

/*
 * Copyright (c) 2015 Kurt Jung (Gmail: kurt.w.jung),
 *   Marcus Downing, Jan Slabon (Setasign)
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

// newTpl creates a template, copying graphics settings from a template if one is given
func newTpl(corner PointType, size SizeType, unitStr, fontDirStr string, fn func(*Tpl), copyFrom *Fpdf) Template {
	orientationStr := "p"
	if size.Wd > size.Ht {
		orientationStr = "l"
	}
	sizeStr := ""

	fpdf := fpdfNew(orientationStr, unitStr, sizeStr, fontDirStr, size)
	tpl := Tpl{*fpdf}
	if copyFrom != nil {
		tpl.loadParamsFromFpdf(copyFrom)
	}
	tpl.Fpdf.SetAutoPageBreak(false, 0)
	tpl.Fpdf.AddPage()
	fn(&tpl)
	bytes := tpl.Fpdf.pages[tpl.Fpdf.page].Bytes()
	templates := make([]Template, 0, len(tpl.Fpdf.templates))
	for _, key := range templateKeyList(tpl.Fpdf.templates, true) {
		templates = append(templates, tpl.Fpdf.templates[key])
	}
	images := tpl.Fpdf.images

	id := GenerateTemplateID()
	template := FpdfTpl{id, corner, size, bytes, images, templates}
	return &template
}

// FpdfTpl is a concrete implementation of the Template interface.
type FpdfTpl struct {
	id        int64
	corner    PointType
	size      SizeType
	bytes     []byte
	images    map[string]*ImageInfoType
	templates []Template
}

// ID returns the global template identifier
func (t *FpdfTpl) ID() int64 {
	return t.id
}

// Size gives the bounding dimensions of this template
func (t *FpdfTpl) Size() (corner PointType, size SizeType) {
	return t.corner, t.size
}

// Bytes returns the actual template data, not including resources
func (t *FpdfTpl) Bytes() []byte {
	return t.bytes
}

// Images returns a list of the images used in this template
func (t *FpdfTpl) Images() map[string]*ImageInfoType {
	return t.images
}

// Templates returns a list of templates used in this template
func (t *FpdfTpl) Templates() []Template {
	return t.templates
}

// Tpl is an Fpdf used for writing a template.
// It has most of the facilities of an Fpdf,but cannot add more pages.
// Tpl is used directly only during the limited time a template is writable.
type Tpl struct {
	Fpdf
}

func (t *Tpl) loadParamsFromFpdf(f *Fpdf) {
	t.Fpdf.compress = false

	t.Fpdf.k = f.k
	t.Fpdf.x = f.x
	t.Fpdf.y = f.y
	t.Fpdf.lineWidth = f.lineWidth
	t.Fpdf.capStyle = f.capStyle
	t.Fpdf.joinStyle = f.joinStyle

	t.Fpdf.color.draw = f.color.draw
	t.Fpdf.color.fill = f.color.fill
	t.Fpdf.color.text = f.color.text

	t.Fpdf.currentFont = f.currentFont
	t.Fpdf.fontFamily = f.fontFamily
	t.Fpdf.fontSize = f.fontSize
	t.Fpdf.fontSizePt = f.fontSizePt
	t.Fpdf.fontStyle = f.fontStyle
	t.Fpdf.ws = f.ws
}

// AddPage does nothing because you cannot add pages to a template
func (t *Tpl) AddPage() {
}

// AddPageFormat does nothign becasue you cannot add pages to a template
func (t *Tpl) AddPageFormat(orientationStr string, size SizeType) {
}

// SetAutoPageBreak does nothing because you cannot add pages to a template
func (t *Tpl) SetAutoPageBreak(auto bool, margin float64) {
}
<commit_msg>Copy fonts maps to template in order for font styles to work. Thanks, geekpex.<commit_after>package gofpdf

/*
 * Copyright (c) 2015 Kurt Jung (Gmail: kurt.w.jung),
 *   Marcus Downing, Jan Slabon (Setasign)
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

// newTpl creates a template, copying graphics settings from a template if one is given
func newTpl(corner PointType, size SizeType, unitStr, fontDirStr string, fn func(*Tpl), copyFrom *Fpdf) Template {
	orientationStr := "p"
	if size.Wd > size.Ht {
		orientationStr = "l"
	}
	sizeStr := ""

	fpdf := fpdfNew(orientationStr, unitStr, sizeStr, fontDirStr, size)
	tpl := Tpl{*fpdf}
	if copyFrom != nil {
		tpl.loadParamsFromFpdf(copyFrom)
	}
	tpl.Fpdf.SetAutoPageBreak(false, 0)
	tpl.Fpdf.AddPage()
	fn(&tpl)
	bytes := tpl.Fpdf.pages[tpl.Fpdf.page].Bytes()
	templates := make([]Template, 0, len(tpl.Fpdf.templates))
	for _, key := range templateKeyList(tpl.Fpdf.templates, true) {
		templates = append(templates, tpl.Fpdf.templates[key])
	}
	images := tpl.Fpdf.images

	id := GenerateTemplateID()
	template := FpdfTpl{id, corner, size, bytes, images, templates}
	return &template
}

// FpdfTpl is a concrete implementation of the Template interface.
type FpdfTpl struct {
	id        int64
	corner    PointType
	size      SizeType
	bytes     []byte
	images    map[string]*ImageInfoType
	templates []Template
}

// ID returns the global template identifier
func (t *FpdfTpl) ID() int64 {
	return t.id
}

// Size gives the bounding dimensions of this template
func (t *FpdfTpl) Size() (corner PointType, size SizeType) {
	return t.corner, t.size
}

// Bytes returns the actual template data, not including resources
func (t *FpdfTpl) Bytes() []byte {
	return t.bytes
}

// Images returns a list of the images used in this template
func (t *FpdfTpl) Images() map[string]*ImageInfoType {
	return t.images
}

// Templates returns a list of templates used in this template
func (t *FpdfTpl) Templates() []Template {
	return t.templates
}

// Tpl is an Fpdf used for writing a template. It has most of the facilities of
// an Fpdf, but cannot add more pages. Tpl is used directly only during the
// limited time a template is writable.
type Tpl struct {
	Fpdf
}

func (t *Tpl) loadParamsFromFpdf(f *Fpdf) {
	t.Fpdf.compress = false

	t.Fpdf.k = f.k
	t.Fpdf.x = f.x
	t.Fpdf.y = f.y
	t.Fpdf.lineWidth = f.lineWidth
	t.Fpdf.capStyle = f.capStyle
	t.Fpdf.joinStyle = f.joinStyle

	t.Fpdf.color.draw = f.color.draw
	t.Fpdf.color.fill = f.color.fill
	t.Fpdf.color.text = f.color.text

	t.Fpdf.fonts = f.fonts
	t.Fpdf.currentFont = f.currentFont
	t.Fpdf.fontFamily = f.fontFamily
	t.Fpdf.fontSize = f.fontSize
	t.Fpdf.fontSizePt = f.fontSizePt
	t.Fpdf.fontStyle = f.fontStyle
	t.Fpdf.ws = f.ws
}

// AddPage does nothing because you cannot add pages to a template
func (t *Tpl) AddPage() {
}

// AddPageFormat does nothign becasue you cannot add pages to a template
func (t *Tpl) AddPageFormat(orientationStr string, size SizeType) {
}

// SetAutoPageBreak does nothing because you cannot add pages to a template
func (t *Tpl) SetAutoPageBreak(auto bool, margin float64) {
}
<|endoftext|>


<commit_before>package commands

import (
	"fmt"
	"strings"
	"sync"
	"time"

	"github.com/camd67/moebot/moebot_bot/bot/permissions"
	"github.com/camd67/moebot/moebot_bot/util/db"
)

const (
	maxWrites     = 4               // Number of times to write out the time
	writeInterval = 5 * time.Second // Time between each write
)

type TimerCommand struct {
	chTimers syncChannelTimerMap
	Checker  permissions.PermissionChecker
}

func NewTimerCommand() *TimerCommand {
	tc := &TimerCommand{}
	tc.chTimers = syncChannelTimerMap{
		RWMutex: sync.RWMutex{},
		M:       make(map[string]*channelTimer),
	}
	return tc
}

func (tc *TimerCommand) Execute(pack *CommPackage) {
	channelID := pack.message.ChannelID
	if len(pack.params) > 0 && strings.EqualFold(pack.params[0], "start") {
		// Make sure the user has at least mod-level permissions before starting the timer
		if tc.Checker.HasPermission(pack.message.Author.ID, pack.member.Roles, pack.guild, db.PermMod) {
			tc.chTimers.Lock()

			// If this channel timer is currently writing out, tell it to stop
			if chTimer, ok := tc.chTimers.M[channelID]; ok {
				chTimer.Lock()
				if chTimer.isWriting {
					close(chTimer.requestCh)
				}
				chTimer.Unlock()
			}

			// Create a new timer
			tc.chTimers.M[channelID] = &channelTimer{
				time:      time.Now(),
				writes:    0,
				isWriting: false,
				requestCh: make(chan string, 10),
			}

			tc.chTimers.Unlock()
			pack.session.ChannelMessageSend(pack.message.ChannelID, "Timer started!")
		} else {
			pack.session.ChannelMessageSend(pack.message.ChannelID, pack.message.Author.Mention()+", you... you don't have permission to do that!")
		}
	} else {
		tc.chTimers.RLock()
		if chTimer, ok := tc.chTimers.M[channelID]; ok {
			chTimer.Lock()
			// Reset the number of writes
			chTimer.writes = 0

			// If the time is not writing, start it
			if !chTimer.isWriting {
				go chTimer.writeTimes(pack)
				chTimer.isWriting = true
			}
			chTimer.Unlock()
		} else {
			pack.session.ChannelMessageSend(pack.message.ChannelID, "No timer started for this channel...")
		}
		tc.chTimers.RUnlock()
	}
}

func (ct *channelTimer) writeTimes(pack *CommPackage) {
	duration := time.Since(ct.time)

	// Write the time once right away
	go func() {
		pack.session.ChannelMessageSend(pack.message.ChannelID, fmtDuration(duration))
		ct.Lock()
		ct.writes++
		ct.Unlock()
	}()

	// Synchronize the writes to be divisible by the interval (works well when interval is 5 so we get writes at times like 0:30, 0:35, 0:40, etc.)
	timeToSync := writeInterval - (duration % writeInterval)
	time.Sleep(timeToSync)
	duration += timeToSync

	// Write again if we spent a sufficient time syncing, otherwise just wait until the next write interval
	go func() {
		if timeToSync > time.Second {
			ct.Lock()
			pack.session.ChannelMessageSend(pack.message.ChannelID, fmtDuration(duration))
			ct.writes++
			ct.Unlock()
		}
	}()

	// Start writing until we reach the max number of writes or get a message to stop
	for {
		select {
		case _, chOpen := <-ct.requestCh:
			// Break out of this loop if the channel was closed
			if !chOpen {
				ct.Lock()
				ct.isWriting = false
				ct.Unlock()
				return
			}

		case <-time.After(writeInterval):
			// Increment the duration and write time to the channel
			duration += writeInterval
			go func() {
				pack.session.ChannelMessageSend(pack.message.ChannelID, fmtDuration(duration))
			}()

			// Exit once we've reached the max write count
			ct.Lock()
			ct.writes++
			if ct.writes >= maxWrites {
				ct.isWriting = false
				ct.Unlock()
				return
			}
			ct.Unlock()
		}
	}
}

// fmtDuration formats a duration into a hh:mm:ss format
func fmtDuration(dur time.Duration) string {
	remainingDur := dur.Round(time.Second)
	hours := remainingDur / time.Hour
	remainingDur -= hours * time.Hour
	minutes := remainingDur / time.Minute
	remainingDur -= minutes * time.Minute
	seconds := remainingDur / time.Second
	return fmt.Sprintf("%02d:%02d:%02d", hours, minutes, seconds)
}

func (tc *TimerCommand) GetPermLevel() db.Permission {
	return db.PermAll
}

func (tc *TimerCommand) GetCommandKeys() []string {
	return []string{"TIMER"}
}

func (tc *TimerCommand) GetCommandHelp(commPrefix string) string {
	return fmt.Sprintf("`%[1]s timer` - Checks the timer. Moderators may provide the `start` option to start (or restart) the timer.", commPrefix)
}

type syncChannelTimerMap struct {
	sync.RWMutex
	M map[string]*channelTimer
}

type channelTimer struct {
	sync.Mutex
	time      time.Time
	writes    int
	isWriting bool
	requestCh chan string
}
<commit_msg>Extended timer alternative (#64)<commit_after>package commands

import (
	"fmt"
	"strings"
	"sync"
	"time"

	"github.com/camd67/moebot/moebot_bot/bot/permissions"
	"github.com/camd67/moebot/moebot_bot/util/db"
)

const (
	maxWrites     = 4               // Number of times to write out the time
	writeInterval = 5 * time.Second // Time between each write
)

type TimerCommand struct {
	chTimers syncChannelTimerMap
	Checker  permissions.PermissionChecker
}

func NewTimerCommand() *TimerCommand {
	tc := &TimerCommand{}
	tc.chTimers = syncChannelTimerMap{
		Mutex: sync.Mutex{},
		M:     make(map[string]*channelTimer),
	}
	return tc
}

func (tc *TimerCommand) Execute(pack *CommPackage) {
	channelID := pack.message.ChannelID
	if len(pack.params) > 0 {
		// Make sure the user has at least mod-level permissions before starting the timer
		if tc.Checker.HasPermission(pack.message.Author.ID, pack.member.Roles, pack.guild, db.PermMod) {
			tc.chTimers.Lock()

			if strings.EqualFold(pack.params[0], "start") {
				// If this channel timer is currently writing out, tell it to stop
				if chTimer, ok := tc.chTimers.M[channelID]; ok {
					// Stop existing writer
					if chTimer.requestCh != nil {
						close(chTimer.requestCh)
					}
				}

				// Create a new timer
				tc.chTimers.M[channelID] = &channelTimer{
					time:      time.Now(),
					requestCh: nil,
				}

				pack.session.ChannelMessageSend(pack.message.ChannelID, "Timer started!")
			} else if strings.EqualFold(pack.params[0], "stop") {
				if chTimer, ok := tc.chTimers.M[channelID]; ok {
					// Stop existing writer
					if chTimer.requestCh != nil {
						close(chTimer.requestCh)
					}
					delete(tc.chTimers.M, channelID)
					pack.session.ChannelMessageSend(pack.message.ChannelID, "Timer stopped.")
				} else {
					pack.session.ChannelMessageSend(pack.message.ChannelID, "No timer running.")
				}
			}

			tc.chTimers.Unlock()
		} else {
			pack.session.ChannelMessageSend(pack.message.ChannelID, pack.message.Author.Mention()+", you... you don't have permission to do that!")
		}
	} else {
		tc.chTimers.Lock()
		if chTimer, ok := tc.chTimers.M[channelID]; ok {
			// Close existing writer, then start a new one
			if chTimer.requestCh != nil {
				close(chTimer.requestCh)
			}
			chTimer.requestCh = make(chan string, 10)
			go writeTimes(pack, chTimer.time, chTimer.requestCh)
		} else {
			pack.session.ChannelMessageSend(pack.message.ChannelID, "No timer started for this channel...")
		}
		tc.chTimers.Unlock()
	}
}

func writeTimes(pack *CommPackage, startTime time.Time, reqCh <-chan string) {
	duration := time.Since(startTime)
	writes := 0
	currentWriteInterval := writeInterval

	// Write the time once right away
	go func() {
		pack.session.ChannelMessageSend(pack.message.ChannelID, fmtDuration(duration))
	}()
	writes++

	// Synchronize the writes to be divisible by the interval
	// (works well when interval is 5 so we get writes at times like 0:30, 0:35, 0:40, etc.)
	timeToSync := writeInterval - (duration % writeInterval)
	time.Sleep(timeToSync)
	duration += timeToSync

	// Set the interval to a short duration if we are going to do an "after-sync" write so that messages sent to the receiver will be handled first, and then do the write shortly afterwards.
	if timeToSync > time.Second {
		currentWriteInterval = 50 * time.Millisecond
	}

	// Start writing until we reach the max number of writes or get a message to stop
	for {
		select {
		case _, chOpen := <-reqCh:
			// Break out of this loop if the channel was closed
			if !chOpen {
				return
			}

		case <-time.After(currentWriteInterval):
			// Increment the duration and write time to the channel
			duration += currentWriteInterval
			go func() {
				pack.session.ChannelMessageSend(pack.message.ChannelID, fmtDuration(duration))
			}()
			writes++

			// Exit once we've reached the max write count
			if writes >= maxWrites {
				return
			}

			// Reset write interval in case it was changed to do an "after-sync" write
			currentWriteInterval = writeInterval
		}
	}
}

// fmtDuration formats a duration into a hh:mm:ss format
func fmtDuration(dur time.Duration) string {
	remainingDur := dur.Round(time.Second)
	hours := remainingDur / time.Hour
	remainingDur -= hours * time.Hour
	minutes := remainingDur / time.Minute
	remainingDur -= minutes * time.Minute
	seconds := remainingDur / time.Second
	return fmt.Sprintf("%02d:%02d:%02d", hours, minutes, seconds)
}

func (tc *TimerCommand) GetPermLevel() db.Permission {
	return db.PermAll
}

func (tc *TimerCommand) GetCommandKeys() []string {
	return []string{"TIMER"}
}

func (tc *TimerCommand) GetCommandHelp(commPrefix string) string {
	return fmt.Sprintf("`%[1]s timer` - Checks the timer. Moderators may provide the `start` option to start (or restart) the timer.", commPrefix)
}

type syncChannelTimerMap struct {
	sync.Mutex
	M map[string]*channelTimer
}

type channelTimer struct {
	time      time.Time
	requestCh chan string
}
<|endoftext|>


<commit_before>package spec

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
	"time"

	"github.com/mackerelio/mackerel-agent/logging"
)

// This Generator collects metadata about cloud instances.
// Currently only EC2 is supported.
// EC2: http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AESDG-chapter-instancedata.html
// GCE: https://developers.google.com/compute/docs/metadata
// DigitalOcean: https://developers.digitalocean.com/metadata/

// CloudGenerator definition
type CloudGenerator struct {
	CloudMetaGenerator
}

// CloudMetaGenerator interface of metadata generator for each cloud platform
type CloudMetaGenerator interface {
	Generate() (interface{}, error)
}

// Key is a root key for the generator.
func (g *CloudGenerator) Key() string {
	return "cloud"
}

var cloudLogger = logging.GetLogger("spec.cloud")

const (
	ec2BaseURL          = "http://169.254.169.254/latest/meta-data"
	gceMetaURL          = "http://metadata.google.internal/computeMetadata/v1/?recursive=true"
	digitalOceanBaseURL = "http://169.254.169.254/metadata/v1" // has not been yet used
)

var timeout = 100 * time.Millisecond

// SuggestCloudGenerator returns suitable CloudGenerator
func SuggestCloudGenerator() *CloudGenerator {
	if isEC2() {
		return &CloudGenerator{NewEC2Generator()}
	}

	return nil
}

func isEC2() bool {
	cl := http.Client{
		Timeout: timeout,
	}
	// '/ami-id` is may be aws specific URL
	resp, err := cl.Get(ec2BaseURL + "/ami-id")
	if err != nil {
		return false
	}
	defer resp.Body.Close()

	return resp.StatusCode == 200
}

func isGCE() bool {
	_, err := requestGCEMeta(gceMetaURL)
	if err != nil {
		return false
	}
	return true
}

func requestGCEMeta(u string) ([]byte, error) {
	cl := http.Client{
		Timeout: timeout,
	}
	req, err := http.NewRequest("GET", u, nil)
	if err != nil {
		return nil, err
	}
	req.Header.Set("Metadata-Flavor", "Google")

	resp, err := cl.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		return nil, fmt.Errorf("failed to request gce meta. response code: %d", resp.StatusCode)
	}
	return ioutil.ReadAll(resp.Body)
}

// EC2Generator meta generator for EC2
type EC2Generator struct {
	baseURL *url.URL
}

// NewEC2Generator returns new instance of EC2Generator
func NewEC2Generator() *EC2Generator {
	url, _ := url.Parse(ec2BaseURL)
	return &EC2Generator{url}
}

// Generate collects metadata from cloud platform.
func (g *EC2Generator) Generate() (interface{}, error) {
	client := http.Client{
		Timeout: timeout,
	}

	metadataKeys := []string{
		"instance-id",
		"instance-type",
		"placement/availability-zone",
		"security-groups",
		"ami-id",
		"hostname",
		"local-hostname",
		"public-hostname",
		"local-ipv4",
		"public-keys",
		"public-ipv4",
		"reservation-id",
	}

	metadata := make(map[string]string)

	for _, key := range metadataKeys {
		resp, err := client.Get(g.baseURL.String() + "/" + key)
		if err != nil {
			cloudLogger.Debugf("This host may not be running on EC2. Error while reading '%s'", key)
			return nil, nil
		}
		defer resp.Body.Close()
		if resp.StatusCode == 200 {
			body, err := ioutil.ReadAll(resp.Body)
			if err != nil {
				cloudLogger.Errorf("Results of requesting metadata cannot be read: '%s'", err)
				break
			}
			metadata[key] = string(body)
			cloudLogger.Debugf("results %s:%s", key, string(body))
		} else {
			cloudLogger.Warningf("Status code of the result of requesting metadata '%s' is '%d'", key, resp.StatusCode)
		}
	}

	results := make(map[string]interface{})
	results["provider"] = "ec2"
	results["metadata"] = metadata

	return results, nil
}

type gceInstance struct {
	Zone         string
	InstanceType string `json:"machineType"`
	Hostname     string
	InstanceID   uint64 `json:"id"`
}

type gceProject struct {
	ProjectID        string
	NumericProjectId uint64
}

type gceMeta struct {
	Instance *gceInstance
	Project  *gceProject
}

func (g gceMeta) toGeneratorMeta() map[string]string {
	meta := make(map[string]string)

	lastS := func(s string) string {
		ss := strings.Split(s, "/")
		return ss[len(ss)-1]
	}

	if ins := g.Instance; ins != nil {
		meta["hostname"] = ins.Hostname
		meta["instance-id"] = fmt.Sprint(ins.InstanceID)
		meta["instance-type"] = lastS(ins.InstanceType)
		meta["zone"] = lastS(ins.Zone)
	}

	if proj := g.Project; proj != nil {
		meta["projectId"] = proj.ProjectID
	}

	return meta
}

func (g gceMeta) toGeneratorResults() interface{} {
	results := make(map[string]interface{})
	results["provider"] = "gce"
	results["metadata"] = g.toGeneratorMeta()

	return results
}
<commit_msg>collect gce meta<commit_after>package spec

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
	"time"

	"github.com/mackerelio/mackerel-agent/logging"
)

// This Generator collects metadata about cloud instances.
// Currently only EC2 is supported.
// EC2: http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AESDG-chapter-instancedata.html
// GCE: https://developers.google.com/compute/docs/metadata
// DigitalOcean: https://developers.digitalocean.com/metadata/

// CloudGenerator definition
type CloudGenerator struct {
	CloudMetaGenerator
}

// CloudMetaGenerator interface of metadata generator for each cloud platform
type CloudMetaGenerator interface {
	Generate() (interface{}, error)
}

// Key is a root key for the generator.
func (g *CloudGenerator) Key() string {
	return "cloud"
}

var cloudLogger = logging.GetLogger("spec.cloud")

const (
	ec2BaseURL          = "http://169.254.169.254/latest/meta-data"
	gceMetaURL          = "http://metadata.google.internal/computeMetadata/v1/?recursive=true"
	digitalOceanBaseURL = "http://169.254.169.254/metadata/v1" // has not been yet used
)

var timeout = 100 * time.Millisecond

// SuggestCloudGenerator returns suitable CloudGenerator
func SuggestCloudGenerator() *CloudGenerator {
	if isEC2() {
		return &CloudGenerator{NewEC2Generator()}
	}
	if isGCE() {
		return &CloudGenerator{NewGCEGenerator()}
	}

	return nil
}

func isEC2() bool {
	cl := http.Client{
		Timeout: timeout,
	}
	// '/ami-id` is may be aws specific URL
	resp, err := cl.Get(ec2BaseURL + "/ami-id")
	if err != nil {
		return false
	}
	defer resp.Body.Close()

	return resp.StatusCode == 200
}

func isGCE() bool {
	_, err := requestGCEMeta(gceMetaURL)
	if err != nil {
		return false
	}
	return true
}

func requestGCEMeta(u string) ([]byte, error) {
	cl := http.Client{
		Timeout: timeout,
	}
	req, err := http.NewRequest("GET", u, nil)
	if err != nil {
		return nil, err
	}
	req.Header.Set("Metadata-Flavor", "Google")

	resp, err := cl.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		return nil, fmt.Errorf("failed to request gce meta. response code: %d", resp.StatusCode)
	}
	return ioutil.ReadAll(resp.Body)
}

// EC2Generator meta generator for EC2
type EC2Generator struct {
	baseURL *url.URL
}

// NewEC2Generator returns new instance of EC2Generator
func NewEC2Generator() *EC2Generator {
	url, _ := url.Parse(ec2BaseURL)
	return &EC2Generator{url}
}

// Generate collects metadata from cloud platform.
func (g *EC2Generator) Generate() (interface{}, error) {
	client := http.Client{
		Timeout: timeout,
	}

	metadataKeys := []string{
		"instance-id",
		"instance-type",
		"placement/availability-zone",
		"security-groups",
		"ami-id",
		"hostname",
		"local-hostname",
		"public-hostname",
		"local-ipv4",
		"public-keys",
		"public-ipv4",
		"reservation-id",
	}

	metadata := make(map[string]string)

	for _, key := range metadataKeys {
		resp, err := client.Get(g.baseURL.String() + "/" + key)
		if err != nil {
			cloudLogger.Debugf("This host may not be running on EC2. Error while reading '%s'", key)
			return nil, nil
		}
		defer resp.Body.Close()
		if resp.StatusCode == 200 {
			body, err := ioutil.ReadAll(resp.Body)
			if err != nil {
				cloudLogger.Errorf("Results of requesting metadata cannot be read: '%s'", err)
				break
			}
			metadata[key] = string(body)
			cloudLogger.Debugf("results %s:%s", key, string(body))
		} else {
			cloudLogger.Warningf("Status code of the result of requesting metadata '%s' is '%d'", key, resp.StatusCode)
		}
	}

	results := make(map[string]interface{})
	results["provider"] = "ec2"
	results["metadata"] = metadata

	return results, nil
}

// GCEGenerator generate for GCE
type GCEGenerator struct {
	metaURL *url.URL
}

// NewGCEGenerator returns new GCEGenerator
func NewGCEGenerator() *GCEGenerator {
	url, _ := url.Parse(gceMetaURL)
	return &GCEGenerator{url}
}

// Generate collects metadata from cloud platform.
func (g *GCEGenerator) Generate() (interface{}, error) {
	bytes, err := requestGCEMeta(g.metaURL.String())
	if err != nil {
		return nil, err
	}
	var data gceMeta
	json.Unmarshal(bytes, &data)
	return data.toGeneratorResults(), nil
}

type gceInstance struct {
	Zone         string
	InstanceType string `json:"machineType"`
	Hostname     string
	InstanceID   uint64 `json:"id"`
}

type gceProject struct {
	ProjectID        string
	NumericProjectId uint64
}

type gceMeta struct {
	Instance *gceInstance
	Project  *gceProject
}

func (g gceMeta) toGeneratorMeta() map[string]string {
	meta := make(map[string]string)

	lastS := func(s string) string {
		ss := strings.Split(s, "/")
		return ss[len(ss)-1]
	}

	if ins := g.Instance; ins != nil {
		meta["hostname"] = ins.Hostname
		meta["instance-id"] = fmt.Sprint(ins.InstanceID)
		meta["instance-type"] = lastS(ins.InstanceType)
		meta["zone"] = lastS(ins.Zone)
	}

	if proj := g.Project; proj != nil {
		meta["projectId"] = proj.ProjectID
	}

	return meta
}

func (g gceMeta) toGeneratorResults() interface{} {
	results := make(map[string]interface{})
	results["provider"] = "gce"
	results["metadata"] = g.toGeneratorMeta()

	return results
}
<|endoftext|>


<commit_before>/*-
 * Copyright (c) 2016, Jörg Pernfuß <joerg.pernfuss@1und1.de>
 * All rights reserved
 *
 * Use of this source code is governed by a 2-clause BSD license
 * that can be found in the LICENSE file.
 */

package msg

import (
)

type Supervisor struct {
	Verdict    uint16
	RemoteAddr string
	// Fields for encrypted requests
	KexId string
	Data  []byte
	Kex   auth.Kex
	// Fields for basic authentication requests
	BasicAuthUser  string
	BasicAuthToken string
	Restricted     bool
	// Fields for permission authorization requests
	PermAction     string
	PermRepository string
	PermMonitoring string
	PermNode       string
	// Fields for map update notifications
	Action string
	Object string
	User   proto.User
	Team   proto.Team
}

// vim: ts=4 sw=4 sts=4 noet fenc=utf-8 ffs=unix
<commit_msg>Add field to indicate admin permission<commit_after>/*-
 * Copyright (c) 2016, Jörg Pernfuß <joerg.pernfuss@1und1.de>
 * All rights reserved
 *
 * Use of this source code is governed by a 2-clause BSD license
 * that can be found in the LICENSE file.
 */

package msg

import (
)

type Supervisor struct {
	Verdict     uint16
	VerictAdmin bool
	RemoteAddr  string
	// Fields for encrypted requests
	KexId string
	Data  []byte
	Kex   auth.Kex
	// Fields for basic authentication requests
	BasicAuthUser  string
	BasicAuthToken string
	Restricted     bool
	// Fields for permission authorization requests
	PermAction     string
	PermRepository string
	PermMonitoring string
	PermNode       string
	// Fields for map update notifications
	Action string
	Object string
	User   proto.User
	Team   proto.Team
}

// vim: ts=4 sw=4 sts=4 noet fenc=utf-8 ffs=unix
<|endoftext|>


<commit_before>//
// Here we implement extra flags to extend pflag/viper binding.
//
// https://godoc.org/github.com/spf13/pflag#Value
//
// type Value interface {
//     String() string
//     Set(string) error
//     Type() string
// }
//

package venom

import (
	"time"
)

var (
	DefaultTimeFormat = time.RFC3339
)

//
// time.Time
//
type timeValue time.Time

func newTimeValue(val time.Time, p *time.Time) *timeValue {
	*p = val
	return (*timeValue)(p)
}

func (v *timeValue) Set(s string) error {
	val, err := time.Parse(s, DefaultTimeFormat)
	*v = timeValue(val)
	return err
}

func (v *timeValue) Type() string {
	return "time"
}

func (v *timeValue) String() string {
	return time.Time(*v).Format(DefaultTimeFormat)
}

//
// time.Duration
//
type durationValue time.Duration

func newDurationValue(val time.Duration, p *time.Duration) *durationValue {
	*p = val
	return (*durationValue)(p)
}

func (v *durationValue) Set(s string) error {
	val, err := time.ParseDuration(s)
	*v = durationValue(val)
	return err
}

func (v *durationValue) Type() string {
	return "duration"
}

func (v *durationValue) String() string {
	return time.Duration(*v).String()
}
<commit_msg>Fix args parsing<commit_after>//
// Here we implement extra flags to extend pflag/viper binding.
//
// https://godoc.org/github.com/spf13/pflag#Value
//
// type Value interface {
//     String() string
//     Set(string) error
//     Type() string
// }
//

package venom

import (
	"time"
)

var (
	DefaultTimeFormat = time.RFC3339
)

//
// time.Time
//
type timeValue time.Time

func newTimeValue(val time.Time, p *time.Time) *timeValue {
	*p = val
	return (*timeValue)(p)
}

func (v *timeValue) Set(s string) error {
	val, err := time.Parse(DefaultTimeFormat, s)
	*v = timeValue(val)
	return err
}

func (v *timeValue) Type() string {
	return "time"
}

func (v *timeValue) String() string {
	return time.Time(*v).Format(DefaultTimeFormat)
}

//
// time.Duration
//
type durationValue time.Duration

func newDurationValue(val time.Duration, p *time.Duration) *durationValue {
	*p = val
	return (*durationValue)(p)
}

func (v *durationValue) Set(s string) error {
	val, err := time.ParseDuration(s)
	*v = durationValue(val)
	return err
}

func (v *durationValue) Type() string {
	return "duration"
}

func (v *durationValue) String() string {
	return time.Duration(*v).String()
}
<|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 main

import (
	"os"
	"time"

	"github.com/codegangsta/cli"
)

// Set up custom help text for gcsfuse; 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) {
	app = &cli.App{
		Name:     "goofys",
		Version:  "0.0.1",
		Usage:    "Mount a GCS 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: -1,
				Usage: "UID owner of all inodes.",
			},

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

			cli.BoolFlag{
				Name: "implicit-dirs",
				Usage: "Implicitly define directories based on content. See" +
					"docs/semantics.md",
			},

			/////////////////////////
			// GCS
			/////////////////////////

			cli.StringFlag{
				Name:  "key-file",
				Value: "",
				Usage: "Path to JSON key file for use with GCS. " +
					"(default: none, Google application default credentials used)",
			},

			cli.Float64Flag{
				Name:  "limit-bytes-per-sec",
				Value: -1,
				Usage: "Bandwidth limit for reading data, measured over a 30-second " +
					"window. (use -1 for no limit)",
			},

			cli.Float64Flag{
				Name:  "limit-ops-per-sec",
				Value: 5.0,
				Usage: "Operations per second limit, measured over a 30-second window " +
					"(use -1 for no limit)",
			},

			/////////////////////////
			// 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.",
			},

			cli.StringFlag{
				Name:  "temp-dir",
				Value: "",
				Usage: "Temporary directory for local GCS object copies. " +
					"(default: system default, likely /tmp)",
			},

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

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

			cli.BoolFlag{
				Name:  "debug_gcs",
				Usage: "Print GCS request and timing information.",
			},

			cli.BoolFlag{
				Name:  "debug_http",
				Usage: "Dump HTTP requests and responses to/from GCS.",
			},

			cli.BoolFlag{
				Name:  "debug_invariants",
				Usage: "Panic when internal invariants are violated.",
			},
		},
	}

	return
}

type flagStorage struct {
	// File system
	MountOptions map[string]string
	DirMode      os.FileMode
	FileMode     os.FileMode
	Uid          int64
	Gid          int64
	ImplicitDirs bool

	// GCS
	KeyFile                            string
	EgressBandwidthLimitBytesPerSecond float64
	OpRateLimitHz                      float64

	// Tuning
	StatCacheTTL time.Duration
	TypeCacheTTL time.Duration
	TempDir      string

	// Debugging
	DebugFuse       bool
	DebugGCS        bool
	DebugHTTP       bool
	DebugInvariants bool
}

// 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:          int64(c.Int("uid")),
		Gid:          int64(c.Int("gid")),

		// GCS,
		KeyFile: c.String("key-file"),
		EgressBandwidthLimitBytesPerSecond: c.Float64("limit-bytes-per-sec"),
		OpRateLimitHz:                      c.Float64("limit-ops-per-sec"),

		// Tuning,
		StatCacheTTL: c.Duration("stat-cache-ttl"),
		TypeCacheTTL: c.Duration("type-cache-ttl"),
		TempDir:      c.String("temp-dir"),
		ImplicitDirs: c.Bool("implicit-dirs"),

		// Debugging,
		DebugFuse:       c.Bool("debug_fuse"),
		DebugGCS:        c.Bool("debug_gcs"),
		DebugHTTP:       c.Bool("debug_http"),
		DebugInvariants: c.Bool("debug_invariants"),
	}

/*
	// Handle the repeated "-o" flag.
	for _, o := range c.StringSlice("o") {
		mountpkg.ParseOptions(flags.MountOptions, o)
	}
*/
	return
}
<commit_msg>Remove GCS references<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 main

import (
	"os"
	"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) {
	app = &cli.App{
		Name:     "goofys",
		Version:  "0.0.1",
		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: -1,
				Usage: "UID owner of all inodes.",
			},

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

			cli.BoolFlag{
				Name: "implicit-dirs",
				Usage: "Implicitly define directories based on content. See" +
					"docs/semantics.md",
			},

			/////////////////////////
			// Goofys
			/////////////////////////

			cli.Float64Flag{
				Name:  "limit-bytes-per-sec",
				Value: -1,
				Usage: "Bandwidth limit for reading data, measured over a 30-second " +
					"window. (use -1 for no limit)",
			},

			cli.Float64Flag{
				Name:  "limit-ops-per-sec",
				Value: 5.0,
				Usage: "Operations per second limit, measured over a 30-second window " +
					"(use -1 for no limit)",
			},

			/////////////////////////
			// 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_invariants",
				Usage: "Panic when internal invariants are violated.",
			},
		},
	}

	return
}

type flagStorage struct {
	// File system
	MountOptions map[string]string
	DirMode      os.FileMode
	FileMode     os.FileMode
	Uid          int64
	Gid          int64
	ImplicitDirs bool

	// Goofys
	EgressBandwidthLimitBytesPerSecond float64
	OpRateLimitHz                      float64

	// Tuning
	StatCacheTTL time.Duration
	TypeCacheTTL time.Duration

	// Debugging
	DebugFuse       bool
	DebugInvariants bool
}

// 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:          int64(c.Int("uid")),
		Gid:          int64(c.Int("gid")),

		// Goofys,
		EgressBandwidthLimitBytesPerSecond: c.Float64("limit-bytes-per-sec"),
		OpRateLimitHz:                      c.Float64("limit-ops-per-sec"),

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

		// Debugging,
		DebugFuse:       c.Bool("debug_fuse"),
		DebugInvariants: c.Bool("debug_invariants"),
	}

/*
	// Handle the repeated "-o" flag.
	for _, o := range c.StringSlice("o") {
		mountpkg.ParseOptions(flags.MountOptions, o)
	}
*/
	return
}
<|endoftext|>


<commit_before>package main

import (
	"eaciit/gdrj/model"
	"eaciit/gdrj/modules"
	"os"

	"time"

	"github.com/eaciit/dbox"
	"github.com/eaciit/orm/v1"
	"github.com/eaciit/toolkit"
)

var conn dbox.IConnection
var count int
var ratioTableName string

var (
	ratiototrf      = float64(0.392)
	sourcetablename = "salespls-summary"
	calctablename   = "salespls-summary"
	desttablename   = "salespls-summary"
	t0              time.Time
	masters         = toolkit.M{}
	sgaalloc        = map[string]float64{
		"EXP": 0.08,
		"I4":  0.08,
		"I6":  0.105,
	}
)

type plalloc struct {
	ID                     string `bson:"_id" json:"_id"`
	Key                    string
	Key1, Key2, Key3       string
	Ref1                   float64
	Current                float64
	Expect                 float64
	Absorbed               float64
	Ratio1, Ratio2, Ratio3 float64
}

type allocmap map[string]*plalloc

var (
	rdfiscals    = allocmap{}
	branchtotals = allocmap{}
	trxsrc       = "pushrdreversesbymks"
)

func main() {
	setinitialconnection()
	prepmastercalc()
	//buildratio()
	processTable()
}

func processTable() {
	connsave, _ := modules.GetDboxIConnection("db_godrej")
	defer connsave.Close()
	qsave := connsave.NewQuery().SetConfig("multiexec", true).From(desttablename).Save()

	connselect, _ := modules.GetDboxIConnection("db_godrej")
	defer connselect.Close()

	cursor, _ := connselect.NewQuery().
		From(calctablename).
		Where(dbox.Ne("key.trxsrc", trxsrc)).
		Select().Cursor(nil)
	defer cursor.Close()

	i := 0
	count := cursor.Count()
	mstone := 0
	t0 = time.Now()
	for {
		mr := toolkit.M{}
		e := cursor.Fetch(&mr, 1, false)
		if e != nil || i >= count {
			break
		}
		i++
		makeProgressLog("Processing", i, count, 5, &mstone, t0)

		key := mr.Get("key", toolkit.M{}).(toolkit.M)
		subchannel := key.GetString("customer_reportsubchannel")
		keyaccounttype := key.GetString("customer_keyaccount")

		if subchannel != "Hyper" {
			if keyaccounttype == "GNT" {
				key.Set("customer_channelid", "I2")
				key.Set("customer_reportchannel", "I2")
				key.Set("customer_channename", "GT")
				key.Set("customer_reportsubchannel", "R3")
			}
			mr.Set("key", key)

			esave := qsave.Exec(toolkit.M{}.Set("data", mr))
			if esave != nil {
				toolkit.Printfn("Error saving: %s", esave.Error())
				os.Exit(100)
			}
		}
	}
}

func adjustAllocs(allocsmap *allocmap, key string, current, expect, absorbed, ref1 float64) {
	allocs := *allocsmap
	alloc := allocs[key]
	if alloc == nil {
		alloc = new(plalloc)
		alloc.Key = key
		alloc.ID = key
	}
	alloc.Current += current
	alloc.Expect += expect
	alloc.Ref1 += ref1
	alloc.Absorbed += absorbed
	allocs[key] = alloc
	*allocsmap = allocs
}

func makeProgressLog(reference string, i, count, step int, current *int, tstart time.Time) int {
	perstep := count * step / 100
	icurrent := *current
	if icurrent == 0 {
		icurrent = perstep
	}
	pct := i * 100 / count
	if i >= icurrent {
		toolkit.Printfn("%s, %d of %d [%d pct] in %s",
			reference, i, count, pct, time.Since(tstart).String())
		icurrent += perstep
	}
	*current = icurrent
	return icurrent
}

func buildmap(holder interface{},
	fnModel func() orm.IModel,
	filter *dbox.Filter,
	fnIter func(holder interface{}, obj interface{})) interface{} {
	crx, ecrx := gdrj.Find(fnModel(), filter, nil)
	if ecrx != nil {
		toolkit.Printfn("Cursor Error: %s", ecrx.Error())
		os.Exit(100)
	}
	defer crx.Close()
	for {
		s := fnModel()
		e := crx.Fetch(s, 1, false)
		if e != nil {
			break
		}
		fnIter(holder, s)
	}
	return holder
}

var branchgroups = map[string]toolkit.M{}

func prepmastercalc() {
	toolkit.Println("--> PL MODEL")
	masters.Set("plmodel", buildmap(map[string]*gdrj.PLModel{},
		func() orm.IModel {
			return new(gdrj.PLModel)
		},
		nil,
		func(holder, obj interface{}) {
			h := holder.(map[string]*gdrj.PLModel)
			o := obj.(*gdrj.PLModel)
			h[o.ID] = o
		}).(map[string]*gdrj.PLModel))

	cbg, _ := conn.NewQuery().From("branchgroup").Select().Cursor(nil)
	defer cbg.Close()

	for {
		bg := toolkit.M{}
		if e := cbg.Fetch(&bg, 1, false); e != nil {
			break
		}
		id := bg.GetString("_id")
		branchgroups[id] = bg
	}
}

func setinitialconnection() {
	var err error
	conn, err = modules.GetDboxIConnection("db_godrej")

	if err != nil {
		toolkit.Println("Initial connection found : ", err)
		os.Exit(1)
	}

	err = gdrj.SetDb(conn)
	if err != nil {
		toolkit.Println("Initial connection found : ", err)
		os.Exit(1)
	}
}
<commit_msg>upd sby mks<commit_after>package main

import (
	"eaciit/gdrj/model"
	"eaciit/gdrj/modules"
	"os"

	"time"

	"github.com/eaciit/dbox"
	"github.com/eaciit/orm/v1"
	"github.com/eaciit/toolkit"
)

var conn dbox.IConnection
var count int
var ratioTableName string

var (
	ratiototrf      = float64(0.392)
	sourcetablename = "salespls-summary"
	calctablename   = "salespls-summary"
	desttablename   = "salespls-summary"
	t0              time.Time
	masters         = toolkit.M{}
	sgaalloc        = map[string]float64{
		"EXP": 0.08,
		"I4":  0.08,
		"I6":  0.105,
	}
)

type plalloc struct {
	ID                     string `bson:"_id" json:"_id"`
	Key                    string
	Key1, Key2, Key3       string
	Ref1                   float64
	Current                float64
	Expect                 float64
	Absorbed               float64
	Ratio1, Ratio2, Ratio3 float64
}

type allocmap map[string]*plalloc

var (
	rdfiscals    = allocmap{}
	branchtotals = allocmap{}
	trxsrc       = "pushrdreversesbymks"
)

func main() {
	setinitialconnection()
	prepmastercalc()
	//buildratio()
	processTable()
}

func processTable() {
	connsave, _ := modules.GetDboxIConnection("db_godrej")
	defer connsave.Close()
	qsave := connsave.NewQuery().SetConfig("multiexec", true).From(desttablename).Save()

	connselect, _ := modules.GetDboxIConnection("db_godrej")
	defer connselect.Close()

	cursor, _ := connselect.NewQuery().
		From(calctablename).
		Where(dbox.Eq("key.trxsrc", trxsrc)).
		Select().Cursor(nil)
	defer cursor.Close()

	i := 0
	count := cursor.Count()
	mstone := 0
	t0 = time.Now()
	for {
		mr := toolkit.M{}
		e := cursor.Fetch(&mr, 1, false)
		if e != nil || i >= count {
			break
		}
		i++
		makeProgressLog("Processing", i, count, 5, &mstone, t0)

		key := mr.Get("key", toolkit.M{}).(toolkit.M)
		subchannel := key.GetString("customer_reportsubchannel")
		keyaccounttype := key.GetString("customer_keyaccount")

		if subchannel != "Hyper" {
			if keyaccounttype == "GNT" {
				key.Set("customer_channelid", "I2")
				key.Set("customer_reportchannel", "I2")
				key.Set("customer_channename", "GT")
				key.Set("customer_reportsubchannel", "R3")
			}
			mr.Set("key", key)

			esave := qsave.Exec(toolkit.M{}.Set("data", mr))
			if esave != nil {
				toolkit.Printfn("Error saving: %s", esave.Error())
				os.Exit(100)
			}
		}
	}
}

func adjustAllocs(allocsmap *allocmap, key string, current, expect, absorbed, ref1 float64) {
	allocs := *allocsmap
	alloc := allocs[key]
	if alloc == nil {
		alloc = new(plalloc)
		alloc.Key = key
		alloc.ID = key
	}
	alloc.Current += current
	alloc.Expect += expect
	alloc.Ref1 += ref1
	alloc.Absorbed += absorbed
	allocs[key] = alloc
	*allocsmap = allocs
}

func makeProgressLog(reference string, i, count, step int, current *int, tstart time.Time) int {
	perstep := count * step / 100
	icurrent := *current
	if icurrent == 0 {
		icurrent = perstep
	}
	pct := i * 100 / count
	if i >= icurrent {
		toolkit.Printfn("%s, %d of %d [%d pct] in %s",
			reference, i, count, pct, time.Since(tstart).String())
		icurrent += perstep
	}
	*current = icurrent
	return icurrent
}

func buildmap(holder interface{},
	fnModel func() orm.IModel,
	filter *dbox.Filter,
	fnIter func(holder interface{}, obj interface{})) interface{} {
	crx, ecrx := gdrj.Find(fnModel(), filter, nil)
	if ecrx != nil {
		toolkit.Printfn("Cursor Error: %s", ecrx.Error())
		os.Exit(100)
	}
	defer crx.Close()
	for {
		s := fnModel()
		e := crx.Fetch(s, 1, false)
		if e != nil {
			break
		}
		fnIter(holder, s)
	}
	return holder
}

var branchgroups = map[string]toolkit.M{}

func prepmastercalc() {
	toolkit.Println("--> PL MODEL")
	masters.Set("plmodel", buildmap(map[string]*gdrj.PLModel{},
		func() orm.IModel {
			return new(gdrj.PLModel)
		},
		nil,
		func(holder, obj interface{}) {
			h := holder.(map[string]*gdrj.PLModel)
			o := obj.(*gdrj.PLModel)
			h[o.ID] = o
		}).(map[string]*gdrj.PLModel))

	cbg, _ := conn.NewQuery().From("branchgroup").Select().Cursor(nil)
	defer cbg.Close()

	for {
		bg := toolkit.M{}
		if e := cbg.Fetch(&bg, 1, false); e != nil {
			break
		}
		id := bg.GetString("_id")
		branchgroups[id] = bg
	}
}

func setinitialconnection() {
	var err error
	conn, err = modules.GetDboxIConnection("db_godrej")

	if err != nil {
		toolkit.Println("Initial connection found : ", err)
		os.Exit(1)
	}

	err = gdrj.SetDb(conn)
	if err != nil {
		toolkit.Println("Initial connection found : ", err)
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>// Package main provides ...
package main

import (
	"bytes"
	"encoding/hex"
	"encoding/json"
	"flag"
	"os"
	"strconv"
	"sync"

	log "github.com/cihub/seelog"
	"github.com/jonaz/goenocean"
	"github.com/stampzilla/stampzilla-go/nodes/basenode"
	"github.com/stampzilla/stampzilla-go/protocol"
	"github.com/stampzilla/stampzilla-go/protocol/devices"
)

var VERSION string = "dev"
var BUILD_DATE string = ""

var state *State

func main() {

	node := protocol.NewNode("enocean")
	node.Version = VERSION
	node.BuildDate = BUILD_DATE

	flag.Parse()

	//Setup Config
	config := basenode.NewConfig()
	basenode.SetConfig(config)

	//Start communication with the server
	//serverSendChannel = make(chan interface{})
	//serverRecvChannel = make(chan protocol.Command)
	connection := basenode.Connect()
	go monitorState(node, connection)
	go serverRecv(connection)

	// Describe available actions
	node.AddAction("set", "Set", []string{"Devices.Id"})
	node.AddAction("toggle", "Toggle", []string{"Devices.Id"})
	node.AddAction("dim", "Dim", []string{"Devices.Id", "value"})

	// Describe available layouts
	node.AddLayout("1", "switch", "toggle", "Devices", []string{"on"}, "Switches")
	node.AddLayout("2", "slider", "dim", "Devices", []string{"dim"}, "Dimmers")
	node.AddLayout("3", "slider", "dim", "Devices", []string{"dim"}, "Specials")

	node.AddElement(&protocol.Element{
		Type: protocol.ElementTypeToggle,
		Name: "Lamp 0186ff7d",
		Command: &protocol.Command{
			Cmd:  "toggle",
			Args: []string{"0186ff7d"},
		},
		Feedback: `Devices["0186ff7d"].On`,
	})
	node.AddElement(&protocol.Element{
		Type: protocol.ElementTypeText,
		Name: "Lamp 0186ff7d power",
		//Command: &protocol.Command{
		//Cmd:  "toggle",
		//Args: []string{"0186ff7d"},
		//},
		Feedback: `Devices["0186ff7d"].PowerW`,
	})

	//Setup state
	state = NewState()
	state.Devices = readConfigFromFile()
	node.SetState(state)

	//TODO remove element generator and AddElement and AddLayout and AddAction. Devices will superseed that.
	elementGenerator := &ElementGenerator{}
	elementGenerator.State = state
	elementGenerator.Node = node
	elementGenerator.Run()

	for _, dev := range state.Devices {
		// TODO if RecvEEPs is f60201 then its a button and not lamp
		node.Devices().Add(&devices.Device{
			Type:   "lamp",
			Name:   dev.Name,
			Id:     dev.IdString(),
			Online: true,
			Node:   config.Uuid,
			StateMap: map[string]string{
				"On": "Devices[" + dev.IdString() + "]" + ".On",
			},
		})
	}

	checkDuplicateSenderIds()

	setupEnoceanCommunication(node, connection)
}

func monitorState(node *protocol.Node, connection basenode.Connection) {
	for s := range connection.State() {
		switch s {
		case basenode.ConnectionStateConnected:
			connection.Send(node)
		case basenode.ConnectionStateDisconnected:
		}
	}
}

func serverRecv(connection basenode.Connection) {
	for d := range connection.Receive() {
		processCommand(d)
	}
}

func checkDuplicateSenderIds() {
	for _, d := range state.Devices {
		id1 := d.Id()[3] & 0x7f
		for _, d1 := range state.Devices {
			if d.Id() == d1.Id() {
				continue
			}
			id2 := d1.Id()[3] & 0x7f
			if id2 == id1 {
				log.Error("DUPLICATE ID FOUND when generating senderIds for eltako devices")
			}
		}
	}
}

func processCommand(cmd protocol.Command) {
	log.Debug("INCOMING COMMAND", cmd)
	if len(cmd.Args) == 0 {
		log.Error("Missing device ID in arguments")
		return
	}

	device := state.DeviceByString(cmd.Args[0])
	if device == nil {
		log.Errorf("Device %s does not exist", device)
		return
	}
	switch cmd.Cmd {
	case "toggle":
		device.CmdToggle()
	case "on":
		device.CmdOn()
	case "off":
		device.CmdOff()
	case "dim":
		lvl, _ := strconv.Atoi(cmd.Args[1])
		device.CmdDim(lvl)
	case "learn":
		device.CmdLearn()
	}
}

var enoceanSend chan goenocean.Encoder

func setupEnoceanCommunication(node *protocol.Node, connection basenode.Connection) {

	enoceanSend = make(chan goenocean.Encoder, 100)
	recv := make(chan goenocean.Packet, 100)
	goenocean.Serial(enoceanSend, recv)

	getIDBase()
	reciever(node, connection, recv)
}

func getIDBase() {
	p := goenocean.NewPacket()
	p.SetPacketType(goenocean.PacketTypeCommonCommand)
	p.SetData([]byte{0x08})
	enoceanSend <- p
}

var usb300SenderId [4]byte

func reciever(node *protocol.Node, connection basenode.Connection, recv chan goenocean.Packet) {
	for p := range recv {
		if p.PacketType() == goenocean.PacketTypeResponse && len(p.Data()) == 5 {
			copy(usb300SenderId[:], p.Data()[1:4])
			log.Debugf("senderid: % x ( % x )", usb300SenderId, p.Data())
			continue
		}
		if p.SenderId() != [4]byte{0, 0, 0, 0} {
			incomingPacket(node, connection, p)
		}
	}
}

func incomingPacket(node *protocol.Node, connection basenode.Connection, p goenocean.Packet) {

	var d *Device
	if d = state.Device(p.SenderId()); d == nil {
		//Add unknown device
		d = state.AddDevice(p.SenderId(), "UNKNOWN", nil, false)
		//TODO add to devices list aswell? Maybe we need to configure it first?
		saveDevicesToFile()
		connection.Send(node)
	}

	log.Debug("Incoming packet")
	if t, ok := p.(goenocean.Telegram); ok {
		log.Debug("Packet is goenocean.Telegram")
		for _, deviceEep := range d.RecvEEPs {
			if deviceEep[0:2] != hex.EncodeToString([]byte{t.TelegramType()}) {
				log.Debug("Packet is wrong deviceEep ", deviceEep, t.TelegramType())
				continue
			}

			if h := handlers.getHandler(deviceEep); h != nil {
				h.Process(d, t)
				log.Info("Incoming packet processed from", d.IdString())
				//TODO add return bool in process and to send depending on that!
				connection.Send(node)
				return
			}
		}
	}

	//fmt.Println("Unknown packet")

}

var devFileMutex sync.Mutex

func saveDevicesToFile() {
	devFileMutex.Lock()
	defer devFileMutex.Unlock()
	configFile, err := os.Create("devices.json")
	if err != nil {
		log.Error("creating config file", err.Error())
	}
	var out bytes.Buffer
	b, err := json.MarshalIndent(state.Devices, "", "\t")
	if err != nil {
		log.Error("error marshal json", err)
	}
	json.Indent(&out, b, "", "\t")
	out.WriteTo(configFile)
}
func readConfigFromFile() map[string]*Device {
	devFileMutex.Lock()
	defer devFileMutex.Unlock()
	configFile, err := os.Open("devices.json")
	if err != nil {
		log.Error("opening config file", err.Error())
	}

	config := make(map[string]*Device)
	jsonParser := json.NewDecoder(configFile)
	if err = jsonParser.Decode(&config); err != nil {
		log.Error("parsing config file", err.Error())
	}

	return config
}
<commit_msg>fix statemap enocean<commit_after>// Package main provides ...
package main

import (
	"bytes"
	"encoding/hex"
	"encoding/json"
	"flag"
	"os"
	"strconv"
	"sync"

	log "github.com/cihub/seelog"
	"github.com/jonaz/goenocean"
	"github.com/stampzilla/stampzilla-go/nodes/basenode"
	"github.com/stampzilla/stampzilla-go/protocol"
	"github.com/stampzilla/stampzilla-go/protocol/devices"
)

var VERSION string = "dev"
var BUILD_DATE string = ""

var state *State

func main() {

	node := protocol.NewNode("enocean")
	node.Version = VERSION
	node.BuildDate = BUILD_DATE

	flag.Parse()

	//Setup Config
	config := basenode.NewConfig()
	basenode.SetConfig(config)

	//Start communication with the server
	//serverSendChannel = make(chan interface{})
	//serverRecvChannel = make(chan protocol.Command)
	connection := basenode.Connect()
	go monitorState(node, connection)
	go serverRecv(connection)

	// Describe available actions
	node.AddAction("set", "Set", []string{"Devices.Id"})
	node.AddAction("toggle", "Toggle", []string{"Devices.Id"})
	node.AddAction("dim", "Dim", []string{"Devices.Id", "value"})

	// Describe available layouts
	node.AddLayout("1", "switch", "toggle", "Devices", []string{"on"}, "Switches")
	node.AddLayout("2", "slider", "dim", "Devices", []string{"dim"}, "Dimmers")
	node.AddLayout("3", "slider", "dim", "Devices", []string{"dim"}, "Specials")

	node.AddElement(&protocol.Element{
		Type: protocol.ElementTypeToggle,
		Name: "Lamp 0186ff7d",
		Command: &protocol.Command{
			Cmd:  "toggle",
			Args: []string{"0186ff7d"},
		},
		Feedback: `Devices["0186ff7d"].On`,
	})
	node.AddElement(&protocol.Element{
		Type: protocol.ElementTypeText,
		Name: "Lamp 0186ff7d power",
		//Command: &protocol.Command{
		//Cmd:  "toggle",
		//Args: []string{"0186ff7d"},
		//},
		Feedback: `Devices["0186ff7d"].PowerW`,
	})

	//Setup state
	state = NewState()
	state.Devices = readConfigFromFile()
	node.SetState(state)

	//TODO remove element generator and AddElement and AddLayout and AddAction. Devices will superseed that.
	elementGenerator := &ElementGenerator{}
	elementGenerator.State = state
	elementGenerator.Node = node
	elementGenerator.Run()

	for _, dev := range state.Devices {
		// TODO if RecvEEPs is f60201 then its a button and not lamp
		node.Devices().Add(&devices.Device{
			Type:   "lamp",
			Name:   dev.Name,
			Id:     dev.IdString(),
			Online: true,
			Node:   config.Uuid,
			StateMap: map[string]string{
				"On": "Devices." + dev.IdString() + "." + ".On",
			},
		})
	}

	checkDuplicateSenderIds()

	setupEnoceanCommunication(node, connection)
}

func monitorState(node *protocol.Node, connection basenode.Connection) {
	for s := range connection.State() {
		switch s {
		case basenode.ConnectionStateConnected:
			connection.Send(node)
		case basenode.ConnectionStateDisconnected:
		}
	}
}

func serverRecv(connection basenode.Connection) {
	for d := range connection.Receive() {
		processCommand(d)
	}
}

func checkDuplicateSenderIds() {
	for _, d := range state.Devices {
		id1 := d.Id()[3] & 0x7f
		for _, d1 := range state.Devices {
			if d.Id() == d1.Id() {
				continue
			}
			id2 := d1.Id()[3] & 0x7f
			if id2 == id1 {
				log.Error("DUPLICATE ID FOUND when generating senderIds for eltako devices")
			}
		}
	}
}

func processCommand(cmd protocol.Command) {
	log.Debug("INCOMING COMMAND", cmd)
	if len(cmd.Args) == 0 {
		log.Error("Missing device ID in arguments")
		return
	}

	device := state.DeviceByString(cmd.Args[0])
	if device == nil {
		log.Errorf("Device %s does not exist", device)
		return
	}
	switch cmd.Cmd {
	case "toggle":
		device.CmdToggle()
	case "on":
		device.CmdOn()
	case "off":
		device.CmdOff()
	case "dim":
		lvl, _ := strconv.Atoi(cmd.Args[1])
		device.CmdDim(lvl)
	case "learn":
		device.CmdLearn()
	}
}

var enoceanSend chan goenocean.Encoder

func setupEnoceanCommunication(node *protocol.Node, connection basenode.Connection) {

	enoceanSend = make(chan goenocean.Encoder, 100)
	recv := make(chan goenocean.Packet, 100)
	goenocean.Serial(enoceanSend, recv)

	getIDBase()
	reciever(node, connection, recv)
}

func getIDBase() {
	p := goenocean.NewPacket()
	p.SetPacketType(goenocean.PacketTypeCommonCommand)
	p.SetData([]byte{0x08})
	enoceanSend <- p
}

var usb300SenderId [4]byte

func reciever(node *protocol.Node, connection basenode.Connection, recv chan goenocean.Packet) {
	for p := range recv {
		if p.PacketType() == goenocean.PacketTypeResponse && len(p.Data()) == 5 {
			copy(usb300SenderId[:], p.Data()[1:4])
			log.Debugf("senderid: % x ( % x )", usb300SenderId, p.Data())
			continue
		}
		if p.SenderId() != [4]byte{0, 0, 0, 0} {
			incomingPacket(node, connection, p)
		}
	}
}

func incomingPacket(node *protocol.Node, connection basenode.Connection, p goenocean.Packet) {

	var d *Device
	if d = state.Device(p.SenderId()); d == nil {
		//Add unknown device
		d = state.AddDevice(p.SenderId(), "UNKNOWN", nil, false)
		//TODO add to devices list aswell? Maybe we need to configure it first?
		saveDevicesToFile()
		connection.Send(node)
	}

	log.Debug("Incoming packet")
	if t, ok := p.(goenocean.Telegram); ok {
		log.Debug("Packet is goenocean.Telegram")
		for _, deviceEep := range d.RecvEEPs {
			if deviceEep[0:2] != hex.EncodeToString([]byte{t.TelegramType()}) {
				log.Debug("Packet is wrong deviceEep ", deviceEep, t.TelegramType())
				continue
			}

			if h := handlers.getHandler(deviceEep); h != nil {
				h.Process(d, t)
				log.Info("Incoming packet processed from", d.IdString())
				//TODO add return bool in process and to send depending on that!
				connection.Send(node)
				return
			}
		}
	}

	//fmt.Println("Unknown packet")

}

var devFileMutex sync.Mutex

func saveDevicesToFile() {
	devFileMutex.Lock()
	defer devFileMutex.Unlock()
	configFile, err := os.Create("devices.json")
	if err != nil {
		log.Error("creating config file", err.Error())
	}
	var out bytes.Buffer
	b, err := json.MarshalIndent(state.Devices, "", "\t")
	if err != nil {
		log.Error("error marshal json", err)
	}
	json.Indent(&out, b, "", "\t")
	out.WriteTo(configFile)
}
func readConfigFromFile() map[string]*Device {
	devFileMutex.Lock()
	defer devFileMutex.Unlock()
	configFile, err := os.Open("devices.json")
	if err != nil {
		log.Error("opening config file", err.Error())
	}

	config := make(map[string]*Device)
	jsonParser := json.NewDecoder(configFile)
	if err = jsonParser.Decode(&config); err != nil {
		log.Error("parsing config file", err.Error())
	}

	return config
}
<|endoftext|>


<commit_before>package reporter

import (
	"errors"
	"fmt"
	"time"

	"github.com/onsi/ginkgo/config"
	"github.com/onsi/ginkgo/types"
	"github.com/pivotal-golang/lager"
	"github.com/zorkian/go-datadog-api"
)

type DataDogReporterInfo struct {
	MetricName string
}

type DataDogReporter struct {
	logger        lager.Logger
	metricPrefix  string
	dataDogClient *datadog.Client
}

func NewDataDogReporter(
	logger lager.Logger,
	metricPrefix string,
	dataDogClient *datadog.Client,
) DataDogReporter {
	return DataDogReporter{
		logger:        logger,
		metricPrefix:  metricPrefix,
		dataDogClient: dataDogClient,
	}
}

func (r *DataDogReporter) SpecSuiteWillBegin(config config.GinkgoConfigType, summary *types.SuiteSummary) {
}

func (r *DataDogReporter) BeforeSuiteDidRun(setupSummary *types.SetupSummary) {
}

func (r *DataDogReporter) AfterSuiteDidRun(setupSummary *types.SetupSummary) {
}

func (r *DataDogReporter) SpecWillRun(specSummary *types.SpecSummary) {
}

func (r *DataDogReporter) SpecDidComplete(specSummary *types.SpecSummary) {
	if specSummary.Passed() && specSummary.IsMeasurement {
		for _, measurement := range specSummary.Measurements {
			info, ok := measurement.Info.(DataDogReporterInfo)
			if !ok {
				r.logger.Error("failed-type-assertion-on-measurement-info", errors.New("type-assertion-failed"))
				continue
			}

			if info.MetricName == "" {
				r.logger.Error("failed-blank-metric-name", errors.New("blank-metric-name"))
				continue
			}

			timestamp := float64(time.Now().Unix())
			err := r.dataDogClient.PostMetrics([]datadog.Metric{
				{
					Metric: fmt.Sprintf("%s.%s", r.metricPrefix, info.MetricName),
					Points: []datadog.DataPoint{
						{timestamp, measurement.Average},
					},
				},
			})
			if err != nil {
				r.logger.Error("failed-sending-metrics-to-datadog", err)
				continue
			}
		}
	}
}

func (r *DataDogReporter) SpecSuiteDidEnd(summary *types.SuiteSummary) {
}
<commit_msg>Add session to datadog reporter<commit_after>package reporter

import (
	"errors"
	"fmt"
	"time"

	"github.com/onsi/ginkgo/config"
	"github.com/onsi/ginkgo/types"
	"github.com/pivotal-golang/lager"
	"github.com/zorkian/go-datadog-api"
)

type DataDogReporterInfo struct {
	MetricName string
}

type DataDogReporter struct {
	logger        lager.Logger
	metricPrefix  string
	dataDogClient *datadog.Client
}

func NewDataDogReporter(
	logger lager.Logger,
	metricPrefix string,
	dataDogClient *datadog.Client,
) DataDogReporter {
	return DataDogReporter{
		logger:        logger.Session("datadog-reporter"),
		metricPrefix:  metricPrefix,
		dataDogClient: dataDogClient,
	}
}

func (r *DataDogReporter) SpecSuiteWillBegin(config config.GinkgoConfigType, summary *types.SuiteSummary) {
}

func (r *DataDogReporter) BeforeSuiteDidRun(setupSummary *types.SetupSummary) {
}

func (r *DataDogReporter) AfterSuiteDidRun(setupSummary *types.SetupSummary) {
}

func (r *DataDogReporter) SpecWillRun(specSummary *types.SpecSummary) {
}

func (r *DataDogReporter) SpecDidComplete(specSummary *types.SpecSummary) {
	if specSummary.Passed() && specSummary.IsMeasurement {
		for _, measurement := range specSummary.Measurements {
			info, ok := measurement.Info.(DataDogReporterInfo)
			if !ok {
				r.logger.Error("failed-type-assertion-on-measurement-info", errors.New("type-assertion-failed"))
				continue
			}

			if info.MetricName == "" {
				r.logger.Error("failed-blank-metric-name", errors.New("blank-metric-name"))
				continue
			}

			timestamp := float64(time.Now().Unix())
			err := r.dataDogClient.PostMetrics([]datadog.Metric{
				{
					Metric: fmt.Sprintf("%s.%s", r.metricPrefix, info.MetricName),
					Points: []datadog.DataPoint{
						{timestamp, measurement.Average},
					},
				},
			})
			if err != nil {
				r.logger.Error("failed-sending-metrics-to-datadog", err)
				continue
			}
		}
	}
}

func (r *DataDogReporter) SpecSuiteDidEnd(summary *types.SuiteSummary) {
}
<|endoftext|>


<commit_before>package main

import (
	"io/ioutil"
	"os"
	"os/exec"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"github.com/vito/cmdtest"
	. "github.com/vito/cmdtest/matchers"
)

var _ = Describe("Running spiff", func() {
	spiff, err := cmdtest.Build(".")
	if err != nil {
		panic(err)
	}

	Describe("merge", func() {
		var merge *cmdtest.Session

		Context("when given a bad file path", func() {
			BeforeEach(func() {
				merge, err = cmdtest.Start(exec.Command(spiff, "merge", "foo.yml"))
				Expect(err).NotTo(HaveOccured())
			})

			It("says file not found", func() {
				Expect(merge).To(SayError("foo.yml: no such file or directory"))
				Expect(merge).To(ExitWith(1))
			})
		})

		Context("when given a single file", func() {
			basicTemplate, err := ioutil.TempFile(os.TempDir(), "basic.yml")
			if err != nil {
				panic(err)
			}

			basicTemplate.Write([]byte(`
---
foo: bar
`))

			BeforeEach(func() {
				merge, err = cmdtest.Start(exec.Command(spiff, "merge", basicTemplate.Name()))
				Expect(err).NotTo(HaveOccured())
			})

			It("resolves the template and prints it out", func() {
				Expect(merge).To(Say(`foo: bar`))
				Expect(merge).To(ExitWith(0))
			})
		})
	})
})
<commit_msg>HaveOccured -> HaveOccurred<commit_after>package main

import (
	"io/ioutil"
	"os"
	"os/exec"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"github.com/vito/cmdtest"
	. "github.com/vito/cmdtest/matchers"
)

var _ = Describe("Running spiff", func() {
	spiff, err := cmdtest.Build(".")
	if err != nil {
		panic(err)
	}

	Describe("merge", func() {
		var merge *cmdtest.Session

		Context("when given a bad file path", func() {
			BeforeEach(func() {
				merge, err = cmdtest.Start(exec.Command(spiff, "merge", "foo.yml"))
				Expect(err).NotTo(HaveOccurred())
			})

			It("says file not found", func() {
				Expect(merge).To(SayError("foo.yml: no such file or directory"))
				Expect(merge).To(ExitWith(1))
			})
		})

		Context("when given a single file", func() {
			basicTemplate, err := ioutil.TempFile(os.TempDir(), "basic.yml")
			if err != nil {
				panic(err)
			}

			basicTemplate.Write([]byte(`
---
foo: bar
`))

			BeforeEach(func() {
				merge, err = cmdtest.Start(exec.Command(spiff, "merge", basicTemplate.Name()))
				Expect(err).NotTo(HaveOccurred())
			})

			It("resolves the template and prints it out", func() {
				Expect(merge).To(Say(`foo: bar`))
				Expect(merge).To(ExitWith(0))
			})
		})
	})
})
<|endoftext|>


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

package commands

import (
	"bytes"
	"errors"
	"fmt"
	"go/build"
	"os"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"

	"github.com/garyburd/neovim-go/vim"
	"github.com/garyburd/neovim-go/vim/plugin"
	"github.com/rogpeppe/godef/go/ast"
	"github.com/rogpeppe/godef/go/parser"
	"github.com/rogpeppe/godef/go/printer"
	"github.com/rogpeppe/godef/go/token"
	"github.com/rogpeppe/godef/go/types"

	"nvim-go/gb"
	"nvim-go/nvim"
)

var (
	defFiler      = "go#def#filer"
	vDefFiler     interface{}
	defFilerMode  = "go#def#filer_mode"
	vDefFilerMode interface{}
	defDebug      = "go#def#debug"
	vDefDebug     interface{}
)

func init() {
	plugin.HandleCommand("Godef", &plugin.CommandOptions{NArgs: "?", Eval: "expand('%:p')"}, cmdDef)
}

func cmdDef(v *vim.Vim, args []string, file string) {
	go Def(v, args, file)
}

func Def(v *vim.Vim, args []string, file string) error {
	dir, _ := filepath.Split(file)
	defer gb.WithGoBuildForPath(dir)()
	gopath := strings.Split(build.Default.GOPATH, ":")
	for i, d := range gopath {
		gopath[i] = filepath.Join(d, "src")
	}
	types.GoPath = gopath

	v.Var(defDebug, &vDefDebug)
	if vDefDebug == int64(1) {
		types.Debug = true
	}

	var (
		b vim.Buffer
		w vim.Window
	)
	p := v.NewPipeline()
	p.CurrentBuffer(&b)
	p.CurrentWindow(&w)
	if err := p.Wait(); err != nil {
		return err
	}

	buf, err := v.BufferLineSlice(b, 0, -1, true, true)
	if err != nil {
		return err
	}
	src := bytes.Join(buf, []byte{'\n'})

	searchpos, err := nvim.ByteOffset(p)
	if err != nil {
		return v.WriteErr("cannot get current buffer byte offset")
	}

	pkgScope := ast.NewScope(parser.Universe)
	f, err := parser.ParseFile(types.FileSet, file, src, 0, pkgScope)
	if f == nil {
		nvim.Echomsg(v, "Godef: cannot parse %s: %v", file, err)
	}

	o := findIdentifier(v, f, searchpos)

	switch e := o.(type) {

	case *ast.ImportSpec:
		path := importPath(v, e)
		pkg, err := build.Default.Import(path, "", build.FindOnly)
		if err != nil {
			nvim.Echomsg(v, "Godef: error finding import path for %s: %s", path, err)
		}

		v.Var(defFilerMode, &vDefFilerMode)
		if vDefFilerMode.(string) != "" {
			v.Command(vDefFilerMode.(string))
		}
		v.Var(defFiler, &vDefFiler)
		return v.Command(vDefFiler.(string) + " " + pkg.Dir)

	case ast.Expr:
		if err := parseLocalPackage(file, f, pkgScope); err != nil {
			nvim.Echomsg(v, "Godef: error parseLocalPackage %v", err)
		}
		obj, _ := types.ExprType(e, types.DefaultImporter)
		if obj != nil {
			pos := types.FileSet.Position(types.DeclPos(obj))
			var loclist []*nvim.ErrorlistData
			loclist = append(loclist, &nvim.ErrorlistData{
				FileName: pos.Filename,
				LNum:     pos.Line,
				Col:      pos.Column,
				Text:     pos.Filename,
			})
			if err := nvim.SetLoclist(p, loclist); err != nil {
				nvim.Echomsg(v, "Godef: %s", err)
			}

			v.Command("silent ll 1")
			v.Feedkeys("zz", "normal", false)
		} else {
			nvim.Echomsg(v, "Godef: not found of obj")
		}
	default:
		nvim.Echomsg(v, "Godef: no declaration found for %v", pretty{e})
	}
	return nil
}

func typeStrMap(obj *ast.Object, typ types.Type) map[string]string {
	switch obj.Kind {
	case ast.Fun, ast.Var:
		dict := map[string]string{
			"Object.Kind":   obj.Kind.String(),
			"Object.Name":   obj.Name,
			"Type.Kind":     typ.Kind.String(),
			"Type.Pkg":      typ.Pkg,
			"Type.String()": typ.String(),
			// "Object.Decl": obj.Decl,
			// "Object.Data":   obj.Data,
			// "Object.Type":   obj.Type,
			// "Object.Pos()":  obj.Pos(),
			// "Type.Node":     typ.Node,
		}
		return dict
		// 	return fmt.Sprintf("%s %v", typ.obj.Name, prettyType{typ})
		// case ast.Pkg:
		// 	return fmt.Sprintf("import (%s %s)", obj.Name, typ.Node.(*ast.ImportSpec).Path.Value)
		// case ast.Con:
		// 	if decl, ok := obj.Decl.(*ast.ValueSpec); ok {
		// 		return fmt.Sprintf("const %s %v = %s", obj.Name, prettyType{typ}, pretty{decl.Values[0]})
		// 	}
		// 	return fmt.Sprintf("const %s %v", obj.Name, prettyType{typ})
		// case ast.Lbl:
		// 	return fmt.Sprintf("label %s", obj.Name)
		// case ast.Typ:
		// 	typ = typ.Underlying(false, types.DefaultImporter)
		// 	return fmt.Sprintf("type %s %v", obj.Name, prettyType{typ})
		// }
		// return fmt.Sprintf("unknown %s %v", obj.Name, typ.Kind)
	}
	return map[string]string{}
}

func typeStr(obj *ast.Object, typ types.Type) string {
	switch obj.Kind {
	case ast.Fun, ast.Var:
		return fmt.Sprintf("%s %v", obj.Name, prettyType{typ})
	case ast.Pkg:
		return fmt.Sprintf("import (%s %s)", obj.Name, typ.Node.(*ast.ImportSpec).Path.Value)
	case ast.Con:
		if decl, ok := obj.Decl.(*ast.ValueSpec); ok {
			return fmt.Sprintf("const %s %v = %s", obj.Name, prettyType{typ}, pretty{decl.Values[0]})
		}
		return fmt.Sprintf("const %s %v", obj.Name, prettyType{typ})
	case ast.Lbl:
		return fmt.Sprintf("label %s", obj.Name)
	case ast.Typ:
		typ = typ.Underlying(false, types.DefaultImporter)
		return fmt.Sprintf("type %s %v", obj.Name, prettyType{typ})
	}
	return fmt.Sprintf("unknown %s %v", obj.Name, typ.Kind)
}

type orderedObjects []*ast.Object

func (o orderedObjects) Less(i, j int) bool { return o[i].Name < o[j].Name }
func (o orderedObjects) Len() int           { return len(o) }
func (o orderedObjects) Swap(i, j int)      { o[i], o[j] = o[j], o[i] }

func importPath(v *vim.Vim, n *ast.ImportSpec) string {
	p, err := strconv.Unquote(n.Path.Value)
	if err != nil {
		nvim.Echomsg(v, "Godef: invalid string literal %q in ast.ImportSpec", n.Path.Value)
	}
	return p
}

// findIdentifier looks for an identifier at byte-offset searchpos
// inside the parsed source represented by node.
// If it is part of a selector expression, it returns
// that expression rather than the identifier itself.
//
// As a special case, if it finds an import spec, it returns ImportSpec.
func findIdentifier(v *vim.Vim, f *ast.File, searchpos int) ast.Node {
	ec := make(chan ast.Node)
	found := func(startPos, endPos token.Pos) bool {
		start := types.FileSet.Position(startPos).Offset
		end := start + int(endPos-startPos)
		return start <= searchpos && searchpos <= end
	}
	go func() {
		var visit func(ast.Node) bool
		visit = func(n ast.Node) bool {
			var startPos token.Pos
			switch n := n.(type) {
			default:
				return true
			case *ast.Ident:
				startPos = n.NamePos
			case *ast.SelectorExpr:
				startPos = n.Sel.NamePos
			case *ast.ImportSpec:
				startPos = n.Pos()
			case *ast.StructType:
				// If we find an anonymous bare field in a
				// struct type, its definition points to itself,
				// but we actually want to go elsewhere,
				// so assume (dubiously) that the expression
				// works globally and return a new node for it.
				for _, field := range n.Fields.List {
					if field.Names != nil {
						continue
					}
					t := field.Type
					if pt, ok := field.Type.(*ast.StarExpr); ok {
						t = pt.X
					}
					if id, ok := t.(*ast.Ident); ok {
						if found(id.NamePos, id.End()) {
							ec <- parseExpr(v, f.Scope, id.Name)
							runtime.Goexit()
						}
					}
				}
				return true
			}
			if found(startPos, n.End()) {
				ec <- n
				runtime.Goexit()
			}
			return true
		}
		ast.Walk(FVisitor(visit), f)
		ec <- nil
	}()
	ev := <-ec
	if ev == nil {
		nvim.Echomsg(v, "Godef: no identifier found")
	}
	return ev
}

func parseExpr(v *vim.Vim, s *ast.Scope, expr string) ast.Expr {
	n, err := parser.ParseExpr(types.FileSet, "<arg>", expr, s)
	if err != nil {
		nvim.Echomsg(v, "Godef: cannot parse expression: %v", err)
	}
	switch n := n.(type) {
	case *ast.Ident, *ast.SelectorExpr:
		return n
	}
	nvim.Echomsg(v, "Godef: no identifier found in expression")
	return nil
}

type FVisitor func(n ast.Node) bool

func (f FVisitor) Visit(n ast.Node) ast.Visitor {
	if f(n) {
		return f
	}
	return nil
}

var errNoPkgFiles = errors.New("no more package files found")

// parseLocalPackage reads and parses all go files from the
// current directory that implement the same package name
// the principal source file, except the original source file
// itself, which will already have been parsed.
//
func parseLocalPackage(filename string, src *ast.File, pkgScope *ast.Scope) error {
	pkg := &ast.Package{src.Name.Name, pkgScope, nil, map[string]*ast.File{filename: src}}
	d, f := filepath.Split(filename)
	if d == "" {
		d = "./"
	}
	fd, err := os.Open(d)
	if err != nil {
		return errNoPkgFiles
	}
	defer fd.Close()

	list, err := fd.Readdirnames(-1)
	if err != nil {
		return errNoPkgFiles
	}

	for _, pf := range list {
		file := filepath.Join(d, pf)
		if !strings.HasSuffix(pf, ".go") ||
			pf == f ||
			pkgName(file) != pkg.Name {
			continue
		}
		src, err := parser.ParseFile(types.FileSet, file, nil, 0, pkg.Scope)
		if err == nil {
			pkg.Files[file] = src
		}
	}
	if len(pkg.Files) == 1 {
		return errNoPkgFiles
	}
	return nil
}

// pkgName returns the package name implemented by the go source filename
func pkgName(filename string) string {
	prog, _ := parser.ParseFile(types.FileSet, filename, nil, parser.PackageClauseOnly, nil)
	if prog != nil {
		return prog.Name.Name
	}
	return ""
}

func hasSuffix(s, suff string) bool {
	return len(s) >= len(suff) && s[len(s)-len(suff):] == suff
}

type pretty struct {
	n interface{}
}

func (p pretty) String() string {
	var b bytes.Buffer
	printer.Fprint(&b, types.FileSet, p.n)
	return b.String()
}

type prettyType struct {
	n types.Type
}

func (p prettyType) String() string {
	// TODO print path package when appropriate.
	// Current issues with using p.n.Pkg:
	//	- we should actually print the local package identifier
	//	rather than the package path when possible.
	//	- p.n.Pkg is non-empty even when
	//	the type is not relative to the package.
	return pretty{p.n.Node}.String()
}
<commit_msg>Fix return value to nil<commit_after>// Copyright 2016 Koichi Shiraishi. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package commands

import (
	"bytes"
	"fmt"
	"go/build"
	"os"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"

	"github.com/garyburd/neovim-go/vim"
	"github.com/garyburd/neovim-go/vim/plugin"
	"github.com/rogpeppe/godef/go/ast"
	"github.com/rogpeppe/godef/go/parser"
	"github.com/rogpeppe/godef/go/printer"
	"github.com/rogpeppe/godef/go/token"
	"github.com/rogpeppe/godef/go/types"

	"nvim-go/gb"
	"nvim-go/nvim"
)

var (
	defFiler      = "go#def#filer"
	vDefFiler     interface{}
	defFilerMode  = "go#def#filer_mode"
	vDefFilerMode interface{}
	defDebug      = "go#def#debug"
	vDefDebug     interface{}
)

func init() {
	plugin.HandleCommand("Godef", &plugin.CommandOptions{NArgs: "?", Eval: "expand('%:p')"}, cmdDef)
}

func cmdDef(v *vim.Vim, args []string, file string) {
	go Def(v, args, file)
}

func Def(v *vim.Vim, args []string, file string) error {
	dir, _ := filepath.Split(file)
	defer gb.WithGoBuildForPath(dir)()
	gopath := strings.Split(build.Default.GOPATH, ":")
	for i, d := range gopath {
		gopath[i] = filepath.Join(d, "src")
	}
	types.GoPath = gopath

	v.Var(defDebug, &vDefDebug)
	if vDefDebug == int64(1) {
		types.Debug = true
	}

	var (
		b vim.Buffer
		w vim.Window
	)
	p := v.NewPipeline()
	p.CurrentBuffer(&b)
	p.CurrentWindow(&w)
	if err := p.Wait(); err != nil {
		return err
	}

	buf, err := v.BufferLineSlice(b, 0, -1, true, true)
	if err != nil {
		return err
	}
	src := bytes.Join(buf, []byte{'\n'})

	searchpos, err := nvim.ByteOffset(p)
	if err != nil {
		return v.WriteErr("cannot get current buffer byte offset")
	}

	pkgScope := ast.NewScope(parser.Universe)
	f, err := parser.ParseFile(types.FileSet, file, src, 0, pkgScope)
	if f == nil {
		nvim.Echomsg(v, "Godef: cannot parse %s: %v", file, err)
	}

	o := findIdentifier(v, f, searchpos)

	switch e := o.(type) {

	case *ast.ImportSpec:
		path := importPath(v, e)
		pkg, err := build.Default.Import(path, "", build.FindOnly)
		if err != nil {
			nvim.Echomsg(v, "Godef: error finding import path for %s: %s", path, err)
		}

		v.Var(defFilerMode, &vDefFilerMode)
		if vDefFilerMode.(string) != "" {
			v.Command(vDefFilerMode.(string))
		}
		v.Var(defFiler, &vDefFiler)
		return v.Command(vDefFiler.(string) + " " + pkg.Dir)

	case ast.Expr:
		if err := parseLocalPackage(file, f, pkgScope); err != nil {
			nvim.Echomsg(v, "Godef: error parseLocalPackage %v", err)
		}
		obj, _ := types.ExprType(e, types.DefaultImporter)
		if obj != nil {
			pos := types.FileSet.Position(types.DeclPos(obj))
			var loclist []*nvim.ErrorlistData
			loclist = append(loclist, &nvim.ErrorlistData{
				FileName: pos.Filename,
				LNum:     pos.Line,
				Col:      pos.Column,
				Text:     pos.Filename,
			})
			if err := nvim.SetLoclist(p, loclist); err != nil {
				nvim.Echomsg(v, "Godef: %s", err)
			}

			v.Command("silent ll 1")
			v.Feedkeys("zz", "normal", false)
		} else {
			nvim.Echomsg(v, "Godef: not found of obj")
		}
	default:
		nvim.Echomsg(v, "Godef: no declaration found for %v", pretty{e})
	}
	return nil
}

func typeStrMap(obj *ast.Object, typ types.Type) map[string]string {
	switch obj.Kind {
	case ast.Fun, ast.Var:
		dict := map[string]string{
			"Object.Kind":   obj.Kind.String(),
			"Object.Name":   obj.Name,
			"Type.Kind":     typ.Kind.String(),
			"Type.Pkg":      typ.Pkg,
			"Type.String()": typ.String(),
			// "Object.Decl": obj.Decl,
			// "Object.Data":   obj.Data,
			// "Object.Type":   obj.Type,
			// "Object.Pos()":  obj.Pos(),
			// "Type.Node":     typ.Node,
		}
		return dict
		// 	return fmt.Sprintf("%s %v", typ.obj.Name, prettyType{typ})
		// case ast.Pkg:
		// 	return fmt.Sprintf("import (%s %s)", obj.Name, typ.Node.(*ast.ImportSpec).Path.Value)
		// case ast.Con:
		// 	if decl, ok := obj.Decl.(*ast.ValueSpec); ok {
		// 		return fmt.Sprintf("const %s %v = %s", obj.Name, prettyType{typ}, pretty{decl.Values[0]})
		// 	}
		// 	return fmt.Sprintf("const %s %v", obj.Name, prettyType{typ})
		// case ast.Lbl:
		// 	return fmt.Sprintf("label %s", obj.Name)
		// case ast.Typ:
		// 	typ = typ.Underlying(false, types.DefaultImporter)
		// 	return fmt.Sprintf("type %s %v", obj.Name, prettyType{typ})
		// }
		// return fmt.Sprintf("unknown %s %v", obj.Name, typ.Kind)
	}
	return map[string]string{}
}

func typeStr(obj *ast.Object, typ types.Type) string {
	switch obj.Kind {
	case ast.Fun, ast.Var:
		return fmt.Sprintf("%s %v", obj.Name, prettyType{typ})
	case ast.Pkg:
		return fmt.Sprintf("import (%s %s)", obj.Name, typ.Node.(*ast.ImportSpec).Path.Value)
	case ast.Con:
		if decl, ok := obj.Decl.(*ast.ValueSpec); ok {
			return fmt.Sprintf("const %s %v = %s", obj.Name, prettyType{typ}, pretty{decl.Values[0]})
		}
		return fmt.Sprintf("const %s %v", obj.Name, prettyType{typ})
	case ast.Lbl:
		return fmt.Sprintf("label %s", obj.Name)
	case ast.Typ:
		typ = typ.Underlying(false, types.DefaultImporter)
		return fmt.Sprintf("type %s %v", obj.Name, prettyType{typ})
	}
	return fmt.Sprintf("unknown %s %v", obj.Name, typ.Kind)
}

type orderedObjects []*ast.Object

func (o orderedObjects) Less(i, j int) bool { return o[i].Name < o[j].Name }
func (o orderedObjects) Len() int           { return len(o) }
func (o orderedObjects) Swap(i, j int)      { o[i], o[j] = o[j], o[i] }

func importPath(v *vim.Vim, n *ast.ImportSpec) string {
	p, err := strconv.Unquote(n.Path.Value)
	if err != nil {
		nvim.Echomsg(v, "Godef: invalid string literal %q in ast.ImportSpec", n.Path.Value)
	}
	return p
}

// findIdentifier looks for an identifier at byte-offset searchpos
// inside the parsed source represented by node.
// If it is part of a selector expression, it returns
// that expression rather than the identifier itself.
//
// As a special case, if it finds an import spec, it returns ImportSpec.
func findIdentifier(v *vim.Vim, f *ast.File, searchpos int) ast.Node {
	ec := make(chan ast.Node)
	found := func(startPos, endPos token.Pos) bool {
		start := types.FileSet.Position(startPos).Offset
		end := start + int(endPos-startPos)
		return start <= searchpos && searchpos <= end
	}
	go func() {
		var visit func(ast.Node) bool
		visit = func(n ast.Node) bool {
			var startPos token.Pos
			switch n := n.(type) {
			default:
				return true
			case *ast.Ident:
				startPos = n.NamePos
			case *ast.SelectorExpr:
				startPos = n.Sel.NamePos
			case *ast.ImportSpec:
				startPos = n.Pos()
			case *ast.StructType:
				// If we find an anonymous bare field in a
				// struct type, its definition points to itself,
				// but we actually want to go elsewhere,
				// so assume (dubiously) that the expression
				// works globally and return a new node for it.
				for _, field := range n.Fields.List {
					if field.Names != nil {
						continue
					}
					t := field.Type
					if pt, ok := field.Type.(*ast.StarExpr); ok {
						t = pt.X
					}
					if id, ok := t.(*ast.Ident); ok {
						if found(id.NamePos, id.End()) {
							ec <- parseExpr(v, f.Scope, id.Name)
							runtime.Goexit()
						}
					}
				}
				return true
			}
			if found(startPos, n.End()) {
				ec <- n
				runtime.Goexit()
			}
			return true
		}
		ast.Walk(FVisitor(visit), f)
		ec <- nil
	}()
	ev := <-ec
	if ev == nil {
		nvim.Echomsg(v, "Godef: no identifier found")
	}
	return ev
}

func parseExpr(v *vim.Vim, s *ast.Scope, expr string) ast.Expr {
	n, err := parser.ParseExpr(types.FileSet, "<arg>", expr, s)
	if err != nil {
		nvim.Echomsg(v, "Godef: cannot parse expression: %v", err)
	}
	switch n := n.(type) {
	case *ast.Ident, *ast.SelectorExpr:
		return n
	}
	nvim.Echomsg(v, "Godef: no identifier found in expression")
	return nil
}

type FVisitor func(n ast.Node) bool

func (f FVisitor) Visit(n ast.Node) ast.Visitor {
	if f(n) {
		return f
	}
	return nil
}

// var errNoPkgFiles = errors.New("no more package files found")

// parseLocalPackage reads and parses all go files from the
// current directory that implement the same package name
// the principal source file, except the original source file
// itself, which will already have been parsed.
//
func parseLocalPackage(filename string, src *ast.File, pkgScope *ast.Scope) error {
	pkg := &ast.Package{src.Name.Name, pkgScope, nil, map[string]*ast.File{filename: src}}
	d, f := filepath.Split(filename)
	if d == "" {
		d = "./"
	}
	fd, err := os.Open(d)
	if err != nil {
		return nil
	}
	defer fd.Close()

	list, err := fd.Readdirnames(-1)
	if err != nil {
		return nil
	}

	for _, pf := range list {
		file := filepath.Join(d, pf)
		if !strings.HasSuffix(pf, ".go") ||
			pf == f ||
			pkgName(file) != pkg.Name {
			continue
		}
		src, err := parser.ParseFile(types.FileSet, file, nil, 0, pkg.Scope)
		if err == nil {
			pkg.Files[file] = src
		}
	}
	if len(pkg.Files) == 1 {
		return nil
	}
	return nil
}

// pkgName returns the package name implemented by the go source filename
func pkgName(filename string) string {
	prog, _ := parser.ParseFile(types.FileSet, filename, nil, parser.PackageClauseOnly, nil)
	if prog != nil {
		return prog.Name.Name
	}
	return ""
}

func hasSuffix(s, suff string) bool {
	return len(s) >= len(suff) && s[len(s)-len(suff):] == suff
}

type pretty struct {
	n interface{}
}

func (p pretty) String() string {
	var b bytes.Buffer
	printer.Fprint(&b, types.FileSet, p.n)
	return b.String()
}

type prettyType struct {
	n types.Type
}

func (p prettyType) String() string {
	// TODO print path package when appropriate.
	// Current issues with using p.n.Pkg:
	//	- we should actually print the local package identifier
	//	rather than the package path when possible.
	//	- p.n.Pkg is non-empty even when
	//	the type is not relative to the package.
	return pretty{p.n.Node}.String()
}
<|endoftext|>


<commit_before>// This file definse the logOuter interface and several types of logOuter.
//
// emptyOuter = logOuter where both Out and Outf are noops
// lineOuter = logOuter where a newline is inserted after every call to
//			   Out and Outf
// fatalLineOuter = logOuter that logs message with inserted newline then
//					exits with call to os.EXIT(1)

package golog

import (
	"bytes"
	"goprotobuf.googlecode.com/hg/proto"
	"os"
	"strconv"
	"time"
)

type LogOuter interface {
	Output(*LogMessage)
	FailNow()
}

func formatLogMessage(m *LogMessage, insertNewline bool) string {
	var buf bytes.Buffer
	buf.WriteString(levelStrings[int(proto.GetInt32(m.Level))])
	t := time.NanosecondsToLocalTime(proto.GetInt64(m.Nanoseconds))
	buf.WriteString(t.Format(" 15:04:05.000000 "))
	if m.Location != nil {
		l := *m.Location
		if l.Package != nil {
			buf.WriteString(*l.Package)
		}
		if l.File != nil {
			buf.WriteString(*l.File)
		}
		if l.Function != nil {
			buf.WriteString(*l.Function)
		}
		if l.Line != nil {
			buf.WriteString(strconv.Itoa(
				int(proto.GetInt32(l.Line))))
		}
	}
	buf.WriteString("] ")
	buf.WriteString(proto.GetString(m.Message))
	if insertNewline {
		buf.WriteString("\n")
	}
	return buf.String()
}

type fileLogOuter struct {
	// TODO Insert mutex?
	*os.File
}

func (f *fileLogOuter) Output(m *LogMessage) {
	// TODO Grab mutex?
	// Make sure to insert a newline.
	f.WriteString(formatLogMessage(m, true))
	f.Sync()
}

func (f *fileLogOuter) FailNow() {
	// TODO Grab mutex?
	f.Close()
	os.Exit(1)
}

func NewFileLogOuter(f *os.File) LogOuter {
	return &fileLogOuter{f}
}

// We want to allow an abitrary testing framework.
type TestController interface {
	// We will assume that testers insert newlines in manner similar to
	// the FEATURE of testing.T where it inserts extra newlines. >.<
	Log(...interface{})
	FailNow()
}

type testLogOuter struct {
	TestController
}

func (t *testLogOuter) Output(m *LogMessage) {
	// Don't insert an additional log message since the tester inserts them
	// for us.
	t.Log(formatLogMessage(m, false))
}

func NewTestLogOuter(t TestController) LogOuter {
	return &testLogOuter{t}
}
<commit_msg>Prettier printing of log message<commit_after>// This file definse the logOuter interface and several types of logOuter.
//
// emptyOuter = logOuter where both Out and Outf are noops
// lineOuter = logOuter where a newline is inserted after every call to
//			   Out and Outf
// fatalLineOuter = logOuter that logs message with inserted newline then
//					exits with call to os.EXIT(1)

package golog

import (
	"bytes"
	"goprotobuf.googlecode.com/hg/proto"
	"os"
	"strconv"
	"time"
)

type LogOuter interface {
	Output(*LogMessage)
	FailNow()
}

func formatLogMessage(m *LogMessage, insertNewline bool) string {
	var buf bytes.Buffer
	buf.WriteString(levelStrings[int(proto.GetInt32(m.Level))])
	t := time.NanosecondsToLocalTime(proto.GetInt64(m.Nanoseconds))
	buf.WriteString(t.Format(" 15:04:05.000000"))
	if m.Location != nil {
		buf.WriteString(" ")
		l := *m.Location
		if l.Package != nil {
			buf.WriteString(*l.Package)
		}
		if l.File != nil {
			buf.WriteString(*l.File)
		}
		if l.Function != nil {
			buf.WriteString(*l.Function)
		}
		if l.Line != nil {
			buf.WriteString(strconv.Itoa(
				int(proto.GetInt32(l.Line))))
		}
	}
	buf.WriteString("] ")
	buf.WriteString(proto.GetString(m.Message))
	if insertNewline {
		buf.WriteString("\n")
	}
	return buf.String()
}

type fileLogOuter struct {
	// TODO Insert mutex?
	*os.File
}

func (f *fileLogOuter) Output(m *LogMessage) {
	// TODO Grab mutex?
	// Make sure to insert a newline.
	f.WriteString(formatLogMessage(m, true))
	f.Sync()
}

func (f *fileLogOuter) FailNow() {
	// TODO Grab mutex?
	f.Close()
	os.Exit(1)
}

func NewFileLogOuter(f *os.File) LogOuter {
	return &fileLogOuter{f}
}

// We want to allow an abitrary testing framework.
type TestController interface {
	// We will assume that testers insert newlines in manner similar to
	// the FEATURE of testing.T where it inserts extra newlines. >.<
	Log(...interface{})
	FailNow()
}

type testLogOuter struct {
	TestController
}

func (t *testLogOuter) Output(m *LogMessage) {
	// Don't insert an additional log message since the tester inserts them
	// for us.
	t.Log(formatLogMessage(m, false))
}

func NewTestLogOuter(t TestController) LogOuter {
	return &testLogOuter{t}
}
<|endoftext|>