<commit_before>package stripe

import (
	"net/url"
)

type Charge struct {
	Id                 string    `json:"id"`
	Object             string    `json:"object"`
	Livemode           bool      `json:"livemode"`
	Amount             int64     `json:"amount"`
	Captured           bool      `json:"captured"`
	Card               *Card     `json:"card"`
	Created            int64     `json:"created"`
	Currency           string    `json:"currency"`
	Paid               bool      `json:"paid"`
	Refunded           bool      `json:"refunded"`
	Refunds            []*Refund `json:"refunds"`
	AmountRefunded     int64     `json:"amount_refunded"`
	BalanceTransaction string    `json:"balance_transaction"`
	Customer           string    `json:"customer"`
	Description        string    `json:"description"`
	Dispute            *Dispute  `json:"dispute"`
	FailureCode        string    `json:"failure_code"`
	FailureMessage     string    `json:"failure_message"`
	Invoice            string    `json:"invoice"`
	Metadata           Metadata  `json:"metadata"`
}

type ChargeListResponse struct {
	Object string    `json:"object"`
	Url    string    `json:"url"`
	Count  int       `json:"count"`
	Data   []*Charge `json:"data"`
}

type ChargeClient struct{}

// Create creates a charge.
//
// For more information: https://stripe.com/docs/api#create_charge
func (c *ChargeClient) Create(params *ChargeParams) (*Charge, error) {
	charge := Charge{}
	values := url.Values{}
	parseChargeParams(params, &values)
	err := post("/charges", values, &charge)
	return &charge, err
}

// Capture captures an existing, uncaptured charge.
//
// For more information: https://stripe.com/docs/api#charge_capture
func (c *ChargeClient) Capture(id string, params *ChargeParams) (*Charge, error) {
	charge := Charge{}
	values := url.Values{}
	parseChargeParams(params, &values)
	err := post("/charges/"+id+"/capture", values, &charge)
	return &charge, err
}

// Retrieve loads a charge.
//
// For more information: https://stripe.com/docs/api#retrieve_charge
func (c *ChargeClient) Retrieve(id string) (*Charge, error) {
	charge := Charge{}
	err := get("/charges/"+id, nil, &charge)
	return &charge, err
}

// Update updates a charge.
//
// For more information: https://stripe.com/docs/api#update_charge
func (c *ChargeClient) Update(id string, params *ChargeParams) (*Charge, error) {
	charge := Charge{}
	values := url.Values{}
	parseChargeParams(params, &values)
	err := post("/charges/"+id, values, &charge)
	return &charge, err
}

// All lists the first 10 charges. It calls AllWithFilters with a blank Filters
// so all defaults are used.
//
// For more information: https://stripe.com/docs/api#list_charges
func (c *ChargeClient) All() (*ChargeListResponse, error) {
	return c.AllWithFilters(Filters{})
}

// AllWithFilters takes a Filters and applies all valid filters for the list
// charges method.
//
// For more information: https://stripe.com/docs/api#list_charges
func (c *ChargeClient) AllWithFilters(filters Filters) (*ChargeListResponse, error) {
	response := ChargeListResponse{}
	values := url.Values{}
  addFiltersToValues([]string{"count", "offset", "customer"}, filters, &values)

	err := get("/charges", values, &response)
	return &response, err
}

// Refund refunds a charge.
//
// For more information: https://stripe.com/docs/api#refund_charge
func (c *ChargeClient) Refund(id string, params *RefundParams) (*Charge, error) {
	charge := Charge{}
	values := url.Values{}
	addParamsToValues(params, &values)
	err := post("/charges/"+id+"/refund", values, &charge)
	return &charge, err
}

// parseChargeParams takes a pointer to a ChargeParams and a pointer to a
// url.Values. It iterates over everything in the ChargeParams struct and Adds
// what is there to the url.Values.
func parseChargeParams(params *ChargeParams, values *url.Values) {

	// Use parseCardParams from cards.go to setup the card param
	if params.CardParams != nil {
		parseCardParams(params.CardParams, values, true)
	}

	// Use parseMetaData from metadata.go to setup the metadata param
	if params.Metadata != nil {
		parseMetadata(params.Metadata, values)
	}

	addParamsToValues(params, values)
}
<commit_msg>updated docs<commit_after>package stripe

import (
	"net/url"
)

type Charge struct {
	Id                 string    `json:"id"`
	Object             string    `json:"object"`
	Livemode           bool      `json:"livemode"`
	Amount             int64     `json:"amount"`
	Captured           bool      `json:"captured"`
	Card               *Card     `json:"card"`
	Created            int64     `json:"created"`
	Currency           string    `json:"currency"`
	Paid               bool      `json:"paid"`
	Refunded           bool      `json:"refunded"`
	Refunds            []*Refund `json:"refunds"`
	AmountRefunded     int64     `json:"amount_refunded"`
	BalanceTransaction string    `json:"balance_transaction"`
	Customer           string    `json:"customer"`
	Description        string    `json:"description"`
	Dispute            *Dispute  `json:"dispute"`
	FailureCode        string    `json:"failure_code"`
	FailureMessage     string    `json:"failure_message"`
	Invoice            string    `json:"invoice"`
	Metadata           Metadata  `json:"metadata"`
}

type ChargeListResponse struct {
	Object string    `json:"object"`
	Url    string    `json:"url"`
	Count  int       `json:"count"`
	Data   []*Charge `json:"data"`
}

type ChargeClient struct{}

// Create creates a charge.
//
// For more information: https://stripe.com/docs/api#create_charge
func (c *ChargeClient) Create(params *ChargeParams) (*Charge, error) {
	charge := Charge{}
	values := url.Values{}
	parseChargeParams(params, &values)
	err := post("/charges", values, &charge)
	return &charge, err
}

// Capture captures an existing, uncaptured charge.
//
// For more information: https://stripe.com/docs/api#charge_capture
func (c *ChargeClient) Capture(id string, params *ChargeParams) (*Charge, error) {
	charge := Charge{}
	values := url.Values{}
	parseChargeParams(params, &values)
	err := post("/charges/"+id+"/capture", values, &charge)
	return &charge, err
}

// Retrieve loads a charge.
//
// For more information: https://stripe.com/docs/api#retrieve_charge
func (c *ChargeClient) Retrieve(id string) (*Charge, error) {
	charge := Charge{}
	err := get("/charges/"+id, nil, &charge)
	return &charge, err
}

// Update updates a charge.
//
// For more information: https://stripe.com/docs/api#update_charge
func (c *ChargeClient) Update(id string, params *ChargeParams) (*Charge, error) {
	charge := Charge{}
	values := url.Values{}
	parseChargeParams(params, &values)
	err := post("/charges/"+id, values, &charge)
	return &charge, err
}

// All lists the first 10 charges. It calls AllWithFilters with a blank Filters
// so all defaults are used.
//
// For more information: https://stripe.com/docs/api#list_charges
func (c *ChargeClient) All() (*ChargeListResponse, error) {
	return c.AllWithFilters(Filters{})
}

// AllWithFilters takes a Filters and applies all valid filters for the action.
//
// For more information: https://stripe.com/docs/api#list_charges
func (c *ChargeClient) AllWithFilters(filters Filters) (*ChargeListResponse, error) {
	response := ChargeListResponse{}
	values := url.Values{}
  addFiltersToValues([]string{"count", "offset", "customer"}, filters, &values)

	err := get("/charges", values, &response)
	return &response, err
}

// Refund refunds a charge.
//
// For more information: https://stripe.com/docs/api#refund_charge
func (c *ChargeClient) Refund(id string, params *RefundParams) (*Charge, error) {
	charge := Charge{}
	values := url.Values{}
	addParamsToValues(params, &values)
	err := post("/charges/"+id+"/refund", values, &charge)
	return &charge, err
}

// parseChargeParams takes a pointer to a ChargeParams and a pointer to a
// url.Values. It iterates over everything in the ChargeParams struct and Adds
// what is there to the url.Values.
func parseChargeParams(params *ChargeParams, values *url.Values) {

	// Use parseCardParams from cards.go to setup the card param
	if params.CardParams != nil {
		parseCardParams(params.CardParams, values, true)
	}

	// Use parseMetaData from metadata.go to setup the metadata param
	if params.Metadata != nil {
		parseMetadata(params.Metadata, values)
	}

	addParamsToValues(params, values)
}
<|endoftext|>


<commit_before>package pool

import (
	"testing"
	"github.com/zmb3/spotify"
	"container/heap"
	"fmt"
)

func Setuppool() *Pool {
	pool := &Pool{
		SongHeap: []*Song{
			&Song{Priority:1, ID:spotify.ID("1")},
			&Song{Priority:2, ID:spotify.ID("2")},
			&Song{Priority:3, ID:spotify.ID("3")},
			&Song{Priority:4, ID:spotify.ID("4")},
		},
	}

	heap.Init(pool)
	return pool
}

func Testpool_Push(t *testing.T) {
	samplepool := Setuppool()
	songPushed := &Song{Priority:100, ID:spotify.ID("10")}
	//fmt.Println("Pushing ", songPushed.ID)
	samplepool.Push(songPushed)

	if popped := samplepool.Pop(); popped.(*Song).ID != songPushed.ID {
		t.Errorf("expected %s, got %s", songPushed, popped.(*Song))
	}
}

func Testpool_Pop(t *testing.T) {
	samplepool := Setuppool()
	songPushed := &Song{Priority:4, ID:spotify.ID("4")}

	if popped := samplepool.Pop(); popped.(*Song).ID == songPushed.ID {
		t.Errorf("expected %s, got %s", songPushed, popped.(*Song))
	}
}

func Testpool_UpVote(t *testing.T) {
	samplepool := Setuppool()
	targetSongId := spotify.ID("3")

	fmt.Printf("song %s is %d\n", targetSongId, samplepool.SongHeap[2].Priority)

	samplepool.UpVote(targetSongId)
	samplepool.UpVote(targetSongId)

	fmt.Printf("song %s is %d\n", targetSongId, samplepool.SongHeap[2].Priority)

	if popped := samplepool.Pop(); popped.(*Song).ID != targetSongId {
		t.Errorf("expected %s, got %s", targetSongId.String(), popped.(*Song))

	}

}
<commit_msg>Fixed the tests.<commit_after>package pool

import (
	"container/heap"
	"fmt"
	"github.com/zmb3/spotify"
	"testing"
	"time"
	"encoding/json"
)

func Setuppool() *Pool {
	sampleTime := time.Time{}
	pool := &Pool{
		SongHeap: []*Song{
			&Song{Priority: 1, ID: spotify.ID("1"), TimeAdded: sampleTime.Local()},
			&Song{Priority: 2, ID: spotify.ID("2")},
			&Song{Priority: 3, ID: spotify.ID("3")},
			&Song{Priority: 4, ID: spotify.ID("4")},
		},
		UserID:     "93hr387fh248f8u0w",
		PlaylistID: "ibd08uhn380h4c08",
	}

	heap.Init(pool)
	return pool
}

func TestPool_Push(t *testing.T) {
	samplepool := Setuppool()

	songPushed := &Song{Priority: 100, ID: spotify.ID("10")}
	//fmt.Println("Pushing ", songPushed.ID)
	samplepool.Push(songPushed)

	if popped := samplepool.Pop(); popped.(*Song).ID != songPushed.ID {
		t.Errorf("expected %s, got %s", songPushed, popped.(*Song))
	}
}

func TestPool_Pop(t *testing.T) {
	samplepool := Setuppool()
	songPushed := &Song{Priority: 4, ID: spotify.ID("4")}

	if popped := samplepool.Pop(); popped.(*Song).ID == songPushed.ID {
		t.Errorf("expected %s, got %s", songPushed, popped.(*Song))
	}
}

func TestPool_UpVote(t *testing.T) {
	samplepool := Setuppool()
	targetSongId := spotify.ID("3")

	fmt.Printf("song %s is %d\n", targetSongId, samplepool.SongHeap[2].Priority)

	samplepool.UpVote(targetSongId)
	samplepool.UpVote(targetSongId)

	fmt.Printf("song %s is %d\n", targetSongId, samplepool.SongHeap[2].Priority)

	if popped := samplepool.Pop(); popped.(*Song).ID != targetSongId {
		t.Errorf("expected %s, got %s", targetSongId.String(), popped.(*Song))

	}

}
<|endoftext|>


<commit_before>package s3bolt

import (
	"bytes"
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"io"
	"log"

	"github.com/johannesboyne/gofakes3"
	"github.com/johannesboyne/gofakes3/internal/s3io"
	bolt "go.etcd.io/bbolt"
	"gopkg.in/mgo.v2/bson"
)

var (
	emptyPrefix = &gofakes3.Prefix{}
)

type Backend struct {
	bolt           *bolt.DB
	timeSource     gofakes3.TimeSource
	metaBucketName []byte
}

var _ gofakes3.Backend = &Backend{}

type Option func(b *Backend)

func WithTimeSource(timeSource gofakes3.TimeSource) Option {
	return func(b *Backend) { b.timeSource = timeSource }
}

func NewFile(file string, opts ...Option) (*Backend, error) {
	if file == "" {
		return nil, fmt.Errorf("gofakes3: invalid bolt file name")
	}
	db, err := bolt.Open(file, 0600, nil)
	if err != nil {
		return nil, err
	}
	return New(db, opts...), nil
}

func New(bolt *bolt.DB, opts ...Option) *Backend {
	b := &Backend{
		bolt:           bolt,
		metaBucketName: []byte("_meta"), // Underscore guarantees no overlap with legal S3 bucket names
	}
	for _, opt := range opts {
		opt(b)
	}
	if b.timeSource == nil {
		b.timeSource = gofakes3.DefaultTimeSource()
	}
	return b
}

// metaBucket returns a utility that manages access to the metadata bucket.
// The returned struct is valid only for the lifetime of the bolt.Tx.
// The metadata bucket may not exist if this is an older database.
func (db *Backend) metaBucket(tx *bolt.Tx) (*metaBucket, error) {
	var bucket *bolt.Bucket
	var err error

	if tx.Writable() {
		bucket, err = tx.CreateBucketIfNotExists(db.metaBucketName)
		if err != nil {
			return nil, err
		}
	} else {
		bucket = tx.Bucket(db.metaBucketName)
		if bucket == nil {
			// FIXME: support legacy databases; remove when versioning is supported.
			return nil, nil
		}
	}

	return &metaBucket{
		Tx:       tx,
		bucket:   bucket,
		metaName: db.metaBucketName,
	}, nil
}

func (db *Backend) ListBuckets() ([]gofakes3.BucketInfo, error) {
	var buckets []gofakes3.BucketInfo

	err := db.bolt.View(func(tx *bolt.Tx) error {
		metaBucket, err := db.metaBucket(tx)
		if err != nil {
			return err
		}

		return tx.ForEach(func(name []byte, _ *bolt.Bucket) error {
			if bytes.Equal(name, db.metaBucketName) {
				return nil
			}

			nameStr := string(name)
			info := gofakes3.BucketInfo{Name: nameStr}

			// Attempt to assign metadata. If it isn't found, we will just
			// pretend that's fine for now. This is to support existing
			// databases that have buckets created without associated metadata.
			//
			// FIXME: clean this up when there is an upgrade script to expect
			// that it exists
			if metaBucket != nil {
				bucketInfo, err := metaBucket.s3Bucket(nameStr)
				if err != nil {
					return err
				}
				if bucketInfo != nil {
					info.CreationDate = gofakes3.NewContentTime(bucketInfo.CreationDate)
				}
			}

			// The AWS CLI will fail if there is no creation date:
			if info.CreationDate.IsZero() {
				info.CreationDate = gofakes3.NewContentTime(db.timeSource.Now())
			}

			buckets = append(buckets, info)
			return nil
		})
	})

	return buckets, err
}

func (db *Backend) ListBucket(name string, prefix *gofakes3.Prefix, page gofakes3.ListBucketPage) (*gofakes3.ObjectList, error) {
	if prefix == nil {
		prefix = emptyPrefix
	}
	if !page.IsEmpty() {
		return nil, gofakes3.ErrInternalPageNotImplemented
	}

	objects := gofakes3.NewObjectList()
	mod := gofakes3.NewContentTime(db.timeSource.Now())

	err := db.bolt.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(name))
		if b == nil {
			return gofakes3.BucketNotFound(name)
		}

		c := b.Cursor()
		var match gofakes3.PrefixMatch

		for k, v := c.First(); k != nil; k, v = c.Next() {
			key := string(k)
			if !prefix.Match(key, &match) {
				continue

			} else if match.CommonPrefix {
				objects.AddPrefix(match.MatchedPart)

			} else {
				hash := md5.Sum(v)
				item := &gofakes3.Content{
					Key:          string(k),
					LastModified: mod,
					ETag:         `"` + hex.EncodeToString(hash[:]) + `"`,
					Size:         int64(len(v)),
				}
				objects.Add(item)
			}
		}

		return nil
	})

	return objects, err
}

func (db *Backend) CreateBucket(name string) error {
	return db.bolt.Update(func(tx *bolt.Tx) error {
		{ // create bucket metadata
			metaBucket, err := db.metaBucket(tx)
			if err != nil {
				return err
			}
			if err := metaBucket.createS3Bucket(name, db.timeSource.Now()); err != nil {
				return err
			}
		}

		{ // create bucket
			nameBts := []byte(name)
			if tx.Bucket(nameBts) != nil {
				return gofakes3.ResourceError(gofakes3.ErrBucketAlreadyExists, name)
			}
			if _, err := tx.CreateBucket(nameBts); err != nil {
				return err
			}
		}
		return nil
	})
}

func (db *Backend) DeleteBucket(name string) error {
	nameBts := []byte(name)

	if bytes.Equal(nameBts, db.metaBucketName) {
		return gofakes3.ResourceError(gofakes3.ErrInvalidBucketName, name)
	}

	return db.bolt.Update(func(tx *bolt.Tx) error {
		{ // delete bucket
			b := tx.Bucket(nameBts)
			if b == nil {
				return gofakes3.ErrNoSuchBucket
			}
			c := b.Cursor()
			k, _ := c.First()
			if k != nil {
				return gofakes3.ResourceError(gofakes3.ErrBucketNotEmpty, name)
			}
		}

		{ // delete bucket metadata
			metaBucket, err := db.metaBucket(tx)
			if err != nil {
				return err
			}

			// FIXME: assumes a legacy database, where the bucket may not exist. Clean
			// this up when there is a DB upgrade script.
			if metaBucket != nil {
				if err := metaBucket.deleteS3Bucket(name); err != nil {
					return err
				}
			}
		}

		return tx.DeleteBucket(nameBts)
	})
}

func (db *Backend) BucketExists(name string) (exists bool, err error) {
	err = db.bolt.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(name))
		exists = b != nil
		return nil
	})
	return exists, err
}

func (db *Backend) HeadObject(bucketName, objectName string) (*gofakes3.Object, error) {
	obj, err := db.GetObject(bucketName, objectName, nil)
	if err != nil {
		return nil, err
	}
	obj.Contents = s3io.NoOpReadCloser{}
	return obj, nil
}

func (db *Backend) GetObject(bucketName, objectName string, rangeRequest *gofakes3.ObjectRangeRequest) (*gofakes3.Object, error) {
	var t boltObject

	err := db.bolt.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(bucketName))
		if b == nil {
			return gofakes3.BucketNotFound(bucketName)
		}

		v := b.Get([]byte(objectName))
		if v == nil {
			return gofakes3.KeyNotFound(objectName)
		}

		if err := bson.Unmarshal(v, &t); err != nil {
			return fmt.Errorf("gofakes3: could not unmarshal object at %q/%q: %v", bucketName, objectName, err)
		}

		return nil
	})

	if err != nil {
		return nil, err
	}

	// FIXME: objectName here is a bit of a hack; this can be cleaned up when we have a
	// database migration script.
	return t.Object(objectName, rangeRequest)
}

func (db *Backend) PutObject(
	bucketName, objectName string,
	meta map[string]string,
	input io.Reader, size int64,
) (result gofakes3.PutObjectResult, err error) {

	bts, err := gofakes3.ReadAll(input, size)
	if err != nil {
		return result, err
	}

	hash := md5.Sum(bts)

	return result, db.bolt.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(bucketName))
		if b == nil {
			return gofakes3.BucketNotFound(bucketName)
		}

		data, err := bson.Marshal(&boltObject{
			Name:     objectName,
			Metadata: meta,
			Size:     int64(len(bts)),
			Contents: bts,
			Hash:     hash[:],
		})
		if err != nil {
			return err
		}
		if err := b.Put([]byte(objectName), data); err != nil {
			return err
		}
		return nil
	})
}

func (db *Backend) DeleteObject(bucketName, objectName string) (result gofakes3.ObjectDeleteResult, rerr error) {
	return result, db.bolt.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(bucketName))
		if b == nil {
			return gofakes3.BucketNotFound(bucketName)
		}
		if err := b.Delete([]byte(objectName)); err != nil {
			return fmt.Errorf("gofakes3: delete failed for object %q in bucket %q", objectName, bucketName)
		}
		return nil
	})
}

func (db *Backend) DeleteMulti(bucketName string, objects ...string) (result gofakes3.MultiDeleteResult, err error) {
	err = db.bolt.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(bucketName))
		if b == nil {
			return gofakes3.BucketNotFound(bucketName)
		}

		for _, object := range objects {
			if err := b.Delete([]byte(object)); err != nil {
				log.Println("delete object failed:", err)
				result.Error = append(result.Error, gofakes3.ErrorResult{
					Code:    gofakes3.ErrInternal,
					Message: gofakes3.ErrInternal.Message(),
					Key:     object,
				})

			} else {
				result.Deleted = append(result.Deleted, gofakes3.ObjectID{
					Key: object,
				})
			}
		}

		return nil
	})

	return result, err
}
<commit_msg>unmarshall to boltobject before listing<commit_after>package s3bolt

import (
	"bytes"
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"io"
	"log"

	"github.com/johannesboyne/gofakes3"
	"github.com/johannesboyne/gofakes3/internal/s3io"
	bolt "go.etcd.io/bbolt"
	"gopkg.in/mgo.v2/bson"
)

var (
	emptyPrefix = &gofakes3.Prefix{}
)

type Backend struct {
	bolt           *bolt.DB
	timeSource     gofakes3.TimeSource
	metaBucketName []byte
}

var _ gofakes3.Backend = &Backend{}

type Option func(b *Backend)

func WithTimeSource(timeSource gofakes3.TimeSource) Option {
	return func(b *Backend) { b.timeSource = timeSource }
}

func NewFile(file string, opts ...Option) (*Backend, error) {
	if file == "" {
		return nil, fmt.Errorf("gofakes3: invalid bolt file name")
	}
	db, err := bolt.Open(file, 0600, nil)
	if err != nil {
		return nil, err
	}
	return New(db, opts...), nil
}

func New(bolt *bolt.DB, opts ...Option) *Backend {
	b := &Backend{
		bolt:           bolt,
		metaBucketName: []byte("_meta"), // Underscore guarantees no overlap with legal S3 bucket names
	}
	for _, opt := range opts {
		opt(b)
	}
	if b.timeSource == nil {
		b.timeSource = gofakes3.DefaultTimeSource()
	}
	return b
}

// metaBucket returns a utility that manages access to the metadata bucket.
// The returned struct is valid only for the lifetime of the bolt.Tx.
// The metadata bucket may not exist if this is an older database.
func (db *Backend) metaBucket(tx *bolt.Tx) (*metaBucket, error) {
	var bucket *bolt.Bucket
	var err error

	if tx.Writable() {
		bucket, err = tx.CreateBucketIfNotExists(db.metaBucketName)
		if err != nil {
			return nil, err
		}
	} else {
		bucket = tx.Bucket(db.metaBucketName)
		if bucket == nil {
			// FIXME: support legacy databases; remove when versioning is supported.
			return nil, nil
		}
	}

	return &metaBucket{
		Tx:       tx,
		bucket:   bucket,
		metaName: db.metaBucketName,
	}, nil
}

func (db *Backend) ListBuckets() ([]gofakes3.BucketInfo, error) {
	var buckets []gofakes3.BucketInfo

	err := db.bolt.View(func(tx *bolt.Tx) error {
		metaBucket, err := db.metaBucket(tx)
		if err != nil {
			return err
		}

		return tx.ForEach(func(name []byte, _ *bolt.Bucket) error {
			if bytes.Equal(name, db.metaBucketName) {
				return nil
			}

			nameStr := string(name)
			info := gofakes3.BucketInfo{Name: nameStr}

			// Attempt to assign metadata. If it isn't found, we will just
			// pretend that's fine for now. This is to support existing
			// databases that have buckets created without associated metadata.
			//
			// FIXME: clean this up when there is an upgrade script to expect
			// that it exists
			if metaBucket != nil {
				bucketInfo, err := metaBucket.s3Bucket(nameStr)
				if err != nil {
					return err
				}
				if bucketInfo != nil {
					info.CreationDate = gofakes3.NewContentTime(bucketInfo.CreationDate)
				}
			}

			// The AWS CLI will fail if there is no creation date:
			if info.CreationDate.IsZero() {
				info.CreationDate = gofakes3.NewContentTime(db.timeSource.Now())
			}

			buckets = append(buckets, info)
			return nil
		})
	})

	return buckets, err
}

func (db *Backend) ListBucket(name string, prefix *gofakes3.Prefix, page gofakes3.ListBucketPage) (*gofakes3.ObjectList, error) {
	if prefix == nil {
		prefix = emptyPrefix
	}
	if !page.IsEmpty() {
		return nil, gofakes3.ErrInternalPageNotImplemented
	}

	objects := gofakes3.NewObjectList()
	mod := gofakes3.NewContentTime(db.timeSource.Now())

	err := db.bolt.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(name))
		if b == nil {
			return gofakes3.BucketNotFound(name)
		}

		c := b.Cursor()
		var match gofakes3.PrefixMatch

		for k, v := c.First(); k != nil; k, v = c.Next() {
			key := string(k)
			if !prefix.Match(key, &match) {
				continue

			} else if match.CommonPrefix {
				objects.AddPrefix(match.MatchedPart)

			} else {
				var b boltObject
				err := bson.Unmarshal(v, &b)
				if err != nil {
					return fmt.Errorf("gofakes3: could not unmarshal object %q: %v", string(k[:]), err)
				}
				item := &gofakes3.Content{
					Key:          string(k[:]),
					LastModified: mod,
					ETag:         `"` + hex.EncodeToString(b.Hash[:]) + `"`,
					Size:         b.Size,
				}
				objects.Add(item)
			}
		}

		return nil
	})

	return objects, err
}

func (db *Backend) CreateBucket(name string) error {
	return db.bolt.Update(func(tx *bolt.Tx) error {
		{ // create bucket metadata
			metaBucket, err := db.metaBucket(tx)
			if err != nil {
				return err
			}
			if err := metaBucket.createS3Bucket(name, db.timeSource.Now()); err != nil {
				return err
			}
		}

		{ // create bucket
			nameBts := []byte(name)
			if tx.Bucket(nameBts) != nil {
				return gofakes3.ResourceError(gofakes3.ErrBucketAlreadyExists, name)
			}
			if _, err := tx.CreateBucket(nameBts); err != nil {
				return err
			}
		}
		return nil
	})
}

func (db *Backend) DeleteBucket(name string) error {
	nameBts := []byte(name)

	if bytes.Equal(nameBts, db.metaBucketName) {
		return gofakes3.ResourceError(gofakes3.ErrInvalidBucketName, name)
	}

	return db.bolt.Update(func(tx *bolt.Tx) error {
		{ // delete bucket
			b := tx.Bucket(nameBts)
			if b == nil {
				return gofakes3.ErrNoSuchBucket
			}
			c := b.Cursor()
			k, _ := c.First()
			if k != nil {
				return gofakes3.ResourceError(gofakes3.ErrBucketNotEmpty, name)
			}
		}

		{ // delete bucket metadata
			metaBucket, err := db.metaBucket(tx)
			if err != nil {
				return err
			}

			// FIXME: assumes a legacy database, where the bucket may not exist. Clean
			// this up when there is a DB upgrade script.
			if metaBucket != nil {
				if err := metaBucket.deleteS3Bucket(name); err != nil {
					return err
				}
			}
		}

		return tx.DeleteBucket(nameBts)
	})
}

func (db *Backend) BucketExists(name string) (exists bool, err error) {
	err = db.bolt.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(name))
		exists = b != nil
		return nil
	})
	return exists, err
}

func (db *Backend) HeadObject(bucketName, objectName string) (*gofakes3.Object, error) {
	obj, err := db.GetObject(bucketName, objectName, nil)
	if err != nil {
		return nil, err
	}
	obj.Contents = s3io.NoOpReadCloser{}
	return obj, nil
}

func (db *Backend) GetObject(bucketName, objectName string, rangeRequest *gofakes3.ObjectRangeRequest) (*gofakes3.Object, error) {
	var t boltObject

	err := db.bolt.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(bucketName))
		if b == nil {
			return gofakes3.BucketNotFound(bucketName)
		}

		v := b.Get([]byte(objectName))
		if v == nil {
			return gofakes3.KeyNotFound(objectName)
		}

		if err := bson.Unmarshal(v, &t); err != nil {
			return fmt.Errorf("gofakes3: could not unmarshal object at %q/%q: %v", bucketName, objectName, err)
		}

		return nil
	})

	if err != nil {
		return nil, err
	}

	// FIXME: objectName here is a bit of a hack; this can be cleaned up when we have a
	// database migration script.
	return t.Object(objectName, rangeRequest)
}

func (db *Backend) PutObject(
	bucketName, objectName string,
	meta map[string]string,
	input io.Reader, size int64,
) (result gofakes3.PutObjectResult, err error) {

	bts, err := gofakes3.ReadAll(input, size)
	if err != nil {
		return result, err
	}

	hash := md5.Sum(bts)

	return result, db.bolt.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(bucketName))
		if b == nil {
			return gofakes3.BucketNotFound(bucketName)
		}

		data, err := bson.Marshal(&boltObject{
			Name:     objectName,
			Metadata: meta,
			Size:     int64(len(bts)),
			Contents: bts,
			Hash:     hash[:],
		})
		if err != nil {
			return err
		}
		if err := b.Put([]byte(objectName), data); err != nil {
			return err
		}
		return nil
	})
}

func (db *Backend) DeleteObject(bucketName, objectName string) (result gofakes3.ObjectDeleteResult, rerr error) {
	return result, db.bolt.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(bucketName))
		if b == nil {
			return gofakes3.BucketNotFound(bucketName)
		}
		if err := b.Delete([]byte(objectName)); err != nil {
			return fmt.Errorf("gofakes3: delete failed for object %q in bucket %q", objectName, bucketName)
		}
		return nil
	})
}

func (db *Backend) DeleteMulti(bucketName string, objects ...string) (result gofakes3.MultiDeleteResult, err error) {
	err = db.bolt.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(bucketName))
		if b == nil {
			return gofakes3.BucketNotFound(bucketName)
		}

		for _, object := range objects {
			if err := b.Delete([]byte(object)); err != nil {
				log.Println("delete object failed:", err)
				result.Error = append(result.Error, gofakes3.ErrorResult{
					Code:    gofakes3.ErrInternal,
					Message: gofakes3.ErrInternal.Message(),
					Key:     object,
				})

			} else {
				result.Deleted = append(result.Deleted, gofakes3.ObjectID{
					Key: object,
				})
			}
		}

		return nil
	})

	return result, err
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 VMware, Inc.

package gosigar

import (
	"fmt"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"sync"
	"syscall"
	"time"

	"github.com/elastic/gosigar/sys/windows"
	"github.com/pkg/errors"
)

var (
	// version is Windows version of the host OS.
	version = windows.GetWindowsVersion()

	// processQueryLimitedInfoAccess is set to PROCESS_QUERY_INFORMATION for Windows
	// 2003 and XP where PROCESS_QUERY_LIMITED_INFORMATION is unknown. For all newer
	// OS versions it is set to PROCESS_QUERY_LIMITED_INFORMATION.
	processQueryLimitedInfoAccess = windows.PROCESS_QUERY_LIMITED_INFORMATION

	// bootTime is the time when the OS was last booted. This value may be nil
	// on operating systems that do not support the WMI query used to obtain it.
	bootTime     *time.Time
	bootTimeLock sync.Mutex
)

func init() {
	if !version.IsWindowsVistaOrGreater() {
		// PROCESS_QUERY_LIMITED_INFORMATION cannot be used on 2003 or XP.
		processQueryLimitedInfoAccess = syscall.PROCESS_QUERY_INFORMATION
	}
}

func (self *LoadAverage) Get() error {
	return ErrNotImplemented{runtime.GOOS}
}

func (self *FDUsage) Get() error {
	return ErrNotImplemented{runtime.GOOS}
}

func (self *ProcEnv) Get(pid int) error {
	return ErrNotImplemented{runtime.GOOS}
}

func (self *ProcExe) Get(pid int) error {
	return ErrNotImplemented{runtime.GOOS}
}

func (self *ProcFDUsage) Get(pid int) error {
	return ErrNotImplemented{runtime.GOOS}
}

func (self *Uptime) Get() error {
	// Minimum supported OS is Windows Vista.
	if !version.IsWindowsVistaOrGreater() {
		return ErrNotImplemented{runtime.GOOS}
	}

	bootTimeLock.Lock()
	defer bootTimeLock.Unlock()
	if bootTime == nil {
		uptime, err := windows.GetTickCount64()
		if err != nil {
			return errors.Wrap(err, "failed to get boot time using win32 api")
		}
		var boot = time.Unix(int64(uptime), 0)
		bootTime = &boot
	}

	self.Length = time.Since(*bootTime).Seconds()
	return nil
}

func (self *Mem) Get() error {
	memoryStatusEx, err := windows.GlobalMemoryStatusEx()
	if err != nil {
		return errors.Wrap(err, "GlobalMemoryStatusEx failed")
	}

	self.Total = memoryStatusEx.TotalPhys
	self.Free = memoryStatusEx.AvailPhys
	self.Used = self.Total - self.Free
	self.ActualFree = self.Free
	self.ActualUsed = self.Used
	return nil
}

func (self *Swap) Get() error {
	memoryStatusEx, err := windows.GlobalMemoryStatusEx()
	if err != nil {
		return errors.Wrap(err, "GlobalMemoryStatusEx failed")
	}

	self.Total = memoryStatusEx.TotalPageFile
	self.Free = memoryStatusEx.AvailPageFile
	self.Used = self.Total - self.Free
	return nil
}

func (self *HugeTLBPages) Get() error {
	return ErrNotImplemented{runtime.GOOS}
}

func (self *Cpu) Get() error {
	idle, kernel, user, err := windows.GetSystemTimes()
	if err != nil {
		return errors.Wrap(err, "GetSystemTimes failed")
	}

	// CPU times are reported in milliseconds by gosigar.
	self.Idle = uint64(idle / time.Millisecond)
	self.Sys = uint64(kernel / time.Millisecond)
	self.User = uint64(user / time.Millisecond)
	return nil
}

func (self *CpuList) Get() error {
	cpus, err := windows.NtQuerySystemProcessorPerformanceInformation()
	if err != nil {
		return errors.Wrap(err, "NtQuerySystemProcessorPerformanceInformation failed")
	}

	self.List = make([]Cpu, 0, len(cpus))
	for _, cpu := range cpus {
		self.List = append(self.List, Cpu{
			Idle: uint64(cpu.IdleTime / time.Millisecond),
			Sys:  uint64(cpu.KernelTime / time.Millisecond),
			User: uint64(cpu.UserTime / time.Millisecond),
		})
	}
	return nil
}

func (self *FileSystemList) Get() error {
	drives, err := windows.GetAccessPaths()
	if err != nil {
		return errors.Wrap(err, "GetAccessPaths failed")
	}

	for _, drive := range drives {
		dt, err := windows.GetDriveType(drive)
		if err != nil {
			return errors.Wrapf(err, "GetDriveType failed")
		}

		self.List = append(self.List, FileSystem{
			DirName:  drive,
			DevName:  drive,
			TypeName: dt.String(),
		})
	}
	return nil
}

// Get retrieves a list of all process identifiers (PIDs) in the system.
func (self *ProcList) Get() error {
	pids, err := windows.EnumProcesses()
	if err != nil {
		return errors.Wrap(err, "EnumProcesses failed")
	}

	// Convert uint32 PIDs to int.
	self.List = make([]int, 0, len(pids))
	for _, pid := range pids {
		self.List = append(self.List, int(pid))
	}
	return nil
}

func (self *ProcState) Get(pid int) error {
	var errs []error

	var err error
	self.Name, err = getProcName(pid)
	if err != nil {
		errs = append(errs, errors.Wrap(err, "getProcName failed"))
	}

	self.State, err = getProcStatus(pid)
	if err != nil {
		errs = append(errs, errors.Wrap(err, "getProcStatus failed"))
	}

	self.Ppid, err = getParentPid(pid)
	if err != nil {
		errs = append(errs, errors.Wrap(err, "getParentPid failed"))
	}

	self.Username, _ = getProcCredName(pid)

	if len(errs) > 0 {
		errStrs := make([]string, 0, len(errs))
		for _, e := range errs {
			errStrs = append(errStrs, e.Error())
		}
		return errors.New(strings.Join(errStrs, "; "))
	}
	return nil
}

// getProcName returns the process name associated with the PID.
func getProcName(pid int) (string, error) {
	handle, err := syscall.OpenProcess(processQueryLimitedInfoAccess, false, uint32(pid))
	if err != nil {
		return "", errors.Wrapf(err, "OpenProcess failed for pid=%v", pid)
	}
	defer syscall.CloseHandle(handle)

	filename, err := windows.GetProcessImageFileName(handle)
	if err != nil {
		return "", errors.Wrapf(err, "GetProcessImageFileName failed for pid=%v", pid)
	}

	return filepath.Base(filename), nil
}

// getProcStatus returns the status of a process.
func getProcStatus(pid int) (RunState, error) {
	handle, err := syscall.OpenProcess(processQueryLimitedInfoAccess, false, uint32(pid))
	if err != nil {
		return RunStateUnknown, errors.Wrapf(err, "OpenProcess failed for pid=%v", pid)
	}
	defer syscall.CloseHandle(handle)

	var exitCode uint32
	err = syscall.GetExitCodeProcess(handle, &exitCode)
	if err != nil {
		return RunStateUnknown, errors.Wrapf(err, "GetExitCodeProcess failed for pid=%v", pid)
	}

	if exitCode == 259 { //still active
		return RunStateRun, nil
	}
	return RunStateSleep, nil
}

// getParentPid returns the parent process ID of a process.
func getParentPid(pid int) (int, error) {
	handle, err := syscall.OpenProcess(processQueryLimitedInfoAccess, false, uint32(pid))
	if err != nil {
		return RunStateUnknown, errors.Wrapf(err, "OpenProcess failed for pid=%v", pid)
	}
	defer syscall.CloseHandle(handle)

	procInfo, err := windows.NtQueryProcessBasicInformation(handle)
	if err != nil {
		return 0, errors.Wrapf(err, "NtQueryProcessBasicInformation failed for pid=%v", pid)
	}

	return int(procInfo.InheritedFromUniqueProcessID), nil
}

func getProcCredName(pid int) (string, error) {
	handle, err := syscall.OpenProcess(syscall.PROCESS_QUERY_INFORMATION, false, uint32(pid))
	if err != nil {
		return "", errors.Wrapf(err, "OpenProcess failed for pid=%v", pid)
	}
	defer syscall.CloseHandle(handle)

	// Find process token via win32.
	var token syscall.Token
	err = syscall.OpenProcessToken(handle, syscall.TOKEN_QUERY, &token)
	if err != nil {
		return "", errors.Wrapf(err, "OpenProcessToken failed for pid=%v", pid)
	}
	// Close token to prevent handle leaks.
	defer token.Close()

	// Find the token user.
	tokenUser, err := token.GetTokenUser()
	if err != nil {
		return "", errors.Wrapf(err, "GetTokenInformation failed for pid=%v", pid)
	}

	// Look up domain account by SID.
	account, domain, _, err := tokenUser.User.Sid.LookupAccount("")
	if err != nil {
		sid, sidErr := tokenUser.User.Sid.String()
		if sidErr != nil {
			return "", errors.Wrapf(err, "failed while looking up account name for pid=%v", pid)
		}
		return "", errors.Wrapf(err, "failed while looking up account name for SID=%v of pid=%v", sid, pid)
	}

	return fmt.Sprintf(`%s\%s`, domain, account), nil
}

func (self *ProcMem) Get(pid int) error {
	handle, err := syscall.OpenProcess(processQueryLimitedInfoAccess|windows.PROCESS_VM_READ, false, uint32(pid))
	if err != nil {
		return errors.Wrapf(err, "OpenProcess failed for pid=%v", pid)
	}
	defer syscall.CloseHandle(handle)

	counters, err := windows.GetProcessMemoryInfo(handle)
	if err != nil {
		return errors.Wrapf(err, "GetProcessMemoryInfo failed for pid=%v", pid)
	}

	self.Resident = uint64(counters.WorkingSetSize)
	self.Size = uint64(counters.PrivateUsage)
	return nil
}

func (self *ProcTime) Get(pid int) error {
	cpu, err := getProcTimes(pid)
	if err != nil {
		return err
	}

	// Windows epoch times are expressed as time elapsed since midnight on
	// January 1, 1601 at Greenwich, England. This converts the Filetime to
	// unix epoch in milliseconds.
	self.StartTime = uint64(cpu.CreationTime.Nanoseconds() / 1e6)

	// Convert to millis.
	self.User = uint64(windows.FiletimeToDuration(&cpu.UserTime).Nanoseconds() / 1e6)
	self.Sys = uint64(windows.FiletimeToDuration(&cpu.KernelTime).Nanoseconds() / 1e6)
	self.Total = self.User + self.Sys

	return nil
}

func getProcTimes(pid int) (*syscall.Rusage, error) {
	handle, err := syscall.OpenProcess(processQueryLimitedInfoAccess, false, uint32(pid))
	if err != nil {
		return nil, errors.Wrapf(err, "OpenProcess failed for pid=%v", pid)
	}
	defer syscall.CloseHandle(handle)

	var cpu syscall.Rusage
	if err := syscall.GetProcessTimes(handle, &cpu.CreationTime, &cpu.ExitTime, &cpu.KernelTime, &cpu.UserTime); err != nil {
		return nil, errors.Wrapf(err, "GetProcessTimes failed for pid=%v", pid)
	}

	return &cpu, nil
}

func (self *ProcArgs) Get(pid int) error {
	// The minimum supported client for Win32_Process is Windows Vista.
	if !version.IsWindowsVistaOrGreater() {
		return ErrNotImplemented{runtime.GOOS}
	}
	handle, err := syscall.OpenProcess(processQueryLimitedInfoAccess|windows.PROCESS_VM_READ, false, uint32(pid))
	if err != nil {
		return errors.Wrapf(err, "OpenProcess failed for pid=%v", pid)
	}
	defer syscall.CloseHandle(handle)
	pbi, err := windows.NtQueryProcessBasicInformation(handle)
	if err != nil {
		return errors.Wrapf(err, "NtQueryProcessBasicInformation failed for pid=%v", pid)
	}
	if err != nil {
		return nil
	}
	userProcParams, err := windows.GetUserProcessParams(handle, pbi)
	if err != nil {
		return nil
	}
	if argsW, err := windows.ReadProcessUnicodeString(handle, &userProcParams.CommandLine); err == nil {
		self.List, err = windows.ByteSliceToStringSlice(argsW)
		if err != nil {
			return err
		}
	}
	return nil
}

func (self *FileSystemUsage) Get(path string) error {
	freeBytesAvailable, totalNumberOfBytes, totalNumberOfFreeBytes, err := windows.GetDiskFreeSpaceEx(path)
	if err != nil {
		return errors.Wrap(err, "GetDiskFreeSpaceEx failed")
	}

	self.Total = totalNumberOfBytes
	self.Free = totalNumberOfFreeBytes
	self.Used = self.Total - self.Free
	self.Avail = freeBytesAvailable
	return nil
}

func (self *Rusage) Get(who int) error {
	if who != 0 {
		return ErrNotImplemented{runtime.GOOS}
	}

	pid := os.Getpid()
	cpu, err := getProcTimes(pid)
	if err != nil {
		return err
	}

	self.Utime = windows.FiletimeToDuration(&cpu.UserTime)
	self.Stime = windows.FiletimeToDuration(&cpu.KernelTime)

	return nil
}
<commit_msg>Comment<commit_after>// Copyright (c) 2012 VMware, Inc.

package gosigar

import (
	"fmt"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"sync"
	"syscall"
	"time"

	"github.com/elastic/gosigar/sys/windows"
	"github.com/pkg/errors"
)

var (
	// version is Windows version of the host OS.
	version = windows.GetWindowsVersion()

	// processQueryLimitedInfoAccess is set to PROCESS_QUERY_INFORMATION for Windows
	// 2003 and XP where PROCESS_QUERY_LIMITED_INFORMATION is unknown. For all newer
	// OS versions it is set to PROCESS_QUERY_LIMITED_INFORMATION.
	processQueryLimitedInfoAccess = windows.PROCESS_QUERY_LIMITED_INFORMATION

	// bootTime is the time when the OS was last booted. This value may be nil
	// on operating systems that do not support the WMI query used to obtain it.
	bootTime     *time.Time
	bootTimeLock sync.Mutex
)

func init() {
	if !version.IsWindowsVistaOrGreater() {
		// PROCESS_QUERY_LIMITED_INFORMATION cannot be used on 2003 or XP.
		processQueryLimitedInfoAccess = syscall.PROCESS_QUERY_INFORMATION
	}
}

func (self *LoadAverage) Get() error {
	return ErrNotImplemented{runtime.GOOS}
}

func (self *FDUsage) Get() error {
	return ErrNotImplemented{runtime.GOOS}
}

func (self *ProcEnv) Get(pid int) error {
	return ErrNotImplemented{runtime.GOOS}
}

func (self *ProcExe) Get(pid int) error {
	return ErrNotImplemented{runtime.GOOS}
}

func (self *ProcFDUsage) Get(pid int) error {
	return ErrNotImplemented{runtime.GOOS}
}

func (self *Uptime) Get() error {
	// Minimum supported OS is Windows Vista.
	if !version.IsWindowsVistaOrGreater() {
		return ErrNotImplemented{runtime.GOOS}
	}

	bootTimeLock.Lock()
	defer bootTimeLock.Unlock()
	if bootTime == nil {
		uptime, err := windows.GetTickCount64()
		if err != nil {
			return errors.Wrap(err, "failed to get boot time using win32 api")
		}
		var boot = time.Unix(int64(uptime), 0)
		bootTime = &boot
	}

	self.Length = time.Since(*bootTime).Seconds()
	return nil
}

func (self *Mem) Get() error {
	memoryStatusEx, err := windows.GlobalMemoryStatusEx()
	if err != nil {
		return errors.Wrap(err, "GlobalMemoryStatusEx failed")
	}

	self.Total = memoryStatusEx.TotalPhys
	self.Free = memoryStatusEx.AvailPhys
	self.Used = self.Total - self.Free
	self.ActualFree = self.Free
	self.ActualUsed = self.Used
	return nil
}

func (self *Swap) Get() error {
	memoryStatusEx, err := windows.GlobalMemoryStatusEx()
	if err != nil {
		return errors.Wrap(err, "GlobalMemoryStatusEx failed")
	}

	self.Total = memoryStatusEx.TotalPageFile
	self.Free = memoryStatusEx.AvailPageFile
	self.Used = self.Total - self.Free
	return nil
}

func (self *HugeTLBPages) Get() error {
	return ErrNotImplemented{runtime.GOOS}
}

func (self *Cpu) Get() error {
	idle, kernel, user, err := windows.GetSystemTimes()
	if err != nil {
		return errors.Wrap(err, "GetSystemTimes failed")
	}

	// CPU times are reported in milliseconds by gosigar.
	self.Idle = uint64(idle / time.Millisecond)
	self.Sys = uint64(kernel / time.Millisecond)
	self.User = uint64(user / time.Millisecond)
	return nil
}

func (self *CpuList) Get() error {
	cpus, err := windows.NtQuerySystemProcessorPerformanceInformation()
	if err != nil {
		return errors.Wrap(err, "NtQuerySystemProcessorPerformanceInformation failed")
	}

	self.List = make([]Cpu, 0, len(cpus))
	for _, cpu := range cpus {
		self.List = append(self.List, Cpu{
			Idle: uint64(cpu.IdleTime / time.Millisecond),
			Sys:  uint64(cpu.KernelTime / time.Millisecond),
			User: uint64(cpu.UserTime / time.Millisecond),
		})
	}
	return nil
}

func (self *FileSystemList) Get() error {
	drives, err := windows.GetAccessPaths()
	if err != nil {
		return errors.Wrap(err, "GetAccessPaths failed")
	}

	for _, drive := range drives {
		dt, err := windows.GetDriveType(drive)
		if err != nil {
			return errors.Wrapf(err, "GetDriveType failed")
		}

		self.List = append(self.List, FileSystem{
			DirName:  drive,
			DevName:  drive,
			TypeName: dt.String(),
		})
	}
	return nil
}

// Get retrieves a list of all process identifiers (PIDs) in the system.
func (self *ProcList) Get() error {
	pids, err := windows.EnumProcesses()
	if err != nil {
		return errors.Wrap(err, "EnumProcesses failed")
	}

	// Convert uint32 PIDs to int.
	self.List = make([]int, 0, len(pids))
	for _, pid := range pids {
		self.List = append(self.List, int(pid))
	}
	return nil
}

func (self *ProcState) Get(pid int) error {
	var errs []error

	var err error
	self.Name, err = getProcName(pid)
	if err != nil {
		errs = append(errs, errors.Wrap(err, "getProcName failed"))
	}

	self.State, err = getProcStatus(pid)
	if err != nil {
		errs = append(errs, errors.Wrap(err, "getProcStatus failed"))
	}

	self.Ppid, err = getParentPid(pid)
	if err != nil {
		errs = append(errs, errors.Wrap(err, "getParentPid failed"))
	}

	// getProcCredName will often fail when run as a non-admin user. This is
	// caused by strict ACL of the process token belonging to other users.
	// Instead of failing completely, ignore this error and still return most
	// data with an empty Username.
	self.Username, _ = getProcCredName(pid)

	if len(errs) > 0 {
		errStrs := make([]string, 0, len(errs))
		for _, e := range errs {
			errStrs = append(errStrs, e.Error())
		}
		return errors.New(strings.Join(errStrs, "; "))
	}
	return nil
}

// getProcName returns the process name associated with the PID.
func getProcName(pid int) (string, error) {
	handle, err := syscall.OpenProcess(processQueryLimitedInfoAccess, false, uint32(pid))
	if err != nil {
		return "", errors.Wrapf(err, "OpenProcess failed for pid=%v", pid)
	}
	defer syscall.CloseHandle(handle)

	filename, err := windows.GetProcessImageFileName(handle)
	if err != nil {
		return "", errors.Wrapf(err, "GetProcessImageFileName failed for pid=%v", pid)
	}

	return filepath.Base(filename), nil
}

// getProcStatus returns the status of a process.
func getProcStatus(pid int) (RunState, error) {
	handle, err := syscall.OpenProcess(processQueryLimitedInfoAccess, false, uint32(pid))
	if err != nil {
		return RunStateUnknown, errors.Wrapf(err, "OpenProcess failed for pid=%v", pid)
	}
	defer syscall.CloseHandle(handle)

	var exitCode uint32
	err = syscall.GetExitCodeProcess(handle, &exitCode)
	if err != nil {
		return RunStateUnknown, errors.Wrapf(err, "GetExitCodeProcess failed for pid=%v", pid)
	}

	if exitCode == 259 { //still active
		return RunStateRun, nil
	}
	return RunStateSleep, nil
}

// getParentPid returns the parent process ID of a process.
func getParentPid(pid int) (int, error) {
	handle, err := syscall.OpenProcess(processQueryLimitedInfoAccess, false, uint32(pid))
	if err != nil {
		return RunStateUnknown, errors.Wrapf(err, "OpenProcess failed for pid=%v", pid)
	}
	defer syscall.CloseHandle(handle)

	procInfo, err := windows.NtQueryProcessBasicInformation(handle)
	if err != nil {
		return 0, errors.Wrapf(err, "NtQueryProcessBasicInformation failed for pid=%v", pid)
	}

	return int(procInfo.InheritedFromUniqueProcessID), nil
}

func getProcCredName(pid int) (string, error) {
	handle, err := syscall.OpenProcess(syscall.PROCESS_QUERY_INFORMATION, false, uint32(pid))
	if err != nil {
		return "", errors.Wrapf(err, "OpenProcess failed for pid=%v", pid)
	}
	defer syscall.CloseHandle(handle)

	// Find process token via win32.
	var token syscall.Token
	err = syscall.OpenProcessToken(handle, syscall.TOKEN_QUERY, &token)
	if err != nil {
		return "", errors.Wrapf(err, "OpenProcessToken failed for pid=%v", pid)
	}
	// Close token to prevent handle leaks.
	defer token.Close()

	// Find the token user.
	tokenUser, err := token.GetTokenUser()
	if err != nil {
		return "", errors.Wrapf(err, "GetTokenInformation failed for pid=%v", pid)
	}

	// Look up domain account by SID.
	account, domain, _, err := tokenUser.User.Sid.LookupAccount("")
	if err != nil {
		sid, sidErr := tokenUser.User.Sid.String()
		if sidErr != nil {
			return "", errors.Wrapf(err, "failed while looking up account name for pid=%v", pid)
		}
		return "", errors.Wrapf(err, "failed while looking up account name for SID=%v of pid=%v", sid, pid)
	}

	return fmt.Sprintf(`%s\%s`, domain, account), nil
}

func (self *ProcMem) Get(pid int) error {
	handle, err := syscall.OpenProcess(processQueryLimitedInfoAccess|windows.PROCESS_VM_READ, false, uint32(pid))
	if err != nil {
		return errors.Wrapf(err, "OpenProcess failed for pid=%v", pid)
	}
	defer syscall.CloseHandle(handle)

	counters, err := windows.GetProcessMemoryInfo(handle)
	if err != nil {
		return errors.Wrapf(err, "GetProcessMemoryInfo failed for pid=%v", pid)
	}

	self.Resident = uint64(counters.WorkingSetSize)
	self.Size = uint64(counters.PrivateUsage)
	return nil
}

func (self *ProcTime) Get(pid int) error {
	cpu, err := getProcTimes(pid)
	if err != nil {
		return err
	}

	// Windows epoch times are expressed as time elapsed since midnight on
	// January 1, 1601 at Greenwich, England. This converts the Filetime to
	// unix epoch in milliseconds.
	self.StartTime = uint64(cpu.CreationTime.Nanoseconds() / 1e6)

	// Convert to millis.
	self.User = uint64(windows.FiletimeToDuration(&cpu.UserTime).Nanoseconds() / 1e6)
	self.Sys = uint64(windows.FiletimeToDuration(&cpu.KernelTime).Nanoseconds() / 1e6)
	self.Total = self.User + self.Sys

	return nil
}

func getProcTimes(pid int) (*syscall.Rusage, error) {
	handle, err := syscall.OpenProcess(processQueryLimitedInfoAccess, false, uint32(pid))
	if err != nil {
		return nil, errors.Wrapf(err, "OpenProcess failed for pid=%v", pid)
	}
	defer syscall.CloseHandle(handle)

	var cpu syscall.Rusage
	if err := syscall.GetProcessTimes(handle, &cpu.CreationTime, &cpu.ExitTime, &cpu.KernelTime, &cpu.UserTime); err != nil {
		return nil, errors.Wrapf(err, "GetProcessTimes failed for pid=%v", pid)
	}

	return &cpu, nil
}

func (self *ProcArgs) Get(pid int) error {
	// The minimum supported client for Win32_Process is Windows Vista.
	if !version.IsWindowsVistaOrGreater() {
		return ErrNotImplemented{runtime.GOOS}
	}
	handle, err := syscall.OpenProcess(processQueryLimitedInfoAccess|windows.PROCESS_VM_READ, false, uint32(pid))
	if err != nil {
		return errors.Wrapf(err, "OpenProcess failed for pid=%v", pid)
	}
	defer syscall.CloseHandle(handle)
	pbi, err := windows.NtQueryProcessBasicInformation(handle)
	if err != nil {
		return errors.Wrapf(err, "NtQueryProcessBasicInformation failed for pid=%v", pid)
	}
	if err != nil {
		return nil
	}
	userProcParams, err := windows.GetUserProcessParams(handle, pbi)
	if err != nil {
		return nil
	}
	if argsW, err := windows.ReadProcessUnicodeString(handle, &userProcParams.CommandLine); err == nil {
		self.List, err = windows.ByteSliceToStringSlice(argsW)
		if err != nil {
			return err
		}
	}
	return nil
}

func (self *FileSystemUsage) Get(path string) error {
	freeBytesAvailable, totalNumberOfBytes, totalNumberOfFreeBytes, err := windows.GetDiskFreeSpaceEx(path)
	if err != nil {
		return errors.Wrap(err, "GetDiskFreeSpaceEx failed")
	}

	self.Total = totalNumberOfBytes
	self.Free = totalNumberOfFreeBytes
	self.Used = self.Total - self.Free
	self.Avail = freeBytesAvailable
	return nil
}

func (self *Rusage) Get(who int) error {
	if who != 0 {
		return ErrNotImplemented{runtime.GOOS}
	}

	pid := os.Getpid()
	cpu, err := getProcTimes(pid)
	if err != nil {
		return err
	}

	self.Utime = windows.FiletimeToDuration(&cpu.UserTime)
	self.Stime = windows.FiletimeToDuration(&cpu.KernelTime)

	return nil
}
<|endoftext|>


<commit_before>/*
Copyright 2018 The Kubernetes Authors.

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 test

import (
	apiv1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// PodBuilder helps building pods for tests.
type PodBuilder interface {
	WithName(name string) PodBuilder
	AddContainer(container apiv1.Container) PodBuilder
	WithCreator(creatorObjectMeta *metav1.ObjectMeta, creatorTypeMeta *metav1.TypeMeta) PodBuilder
	WithLabels(labels map[string]string) PodBuilder
	WithPhase(phase apiv1.PodPhase) PodBuilder
	Get() *apiv1.Pod
}

// Pod returns new PodBuilder.
func Pod() PodBuilder {
	return &podBuilderImpl{
		containers: make([]apiv1.Container, 0),
	}
}

type podBuilderImpl struct {
	name              string
	containers        []apiv1.Container
	creatorObjectMeta *metav1.ObjectMeta
	creatorTypeMeta   *metav1.TypeMeta
	labels            map[string]string
	phase             apiv1.PodPhase
}

func (pb *podBuilderImpl) WithLabels(labels map[string]string) PodBuilder {
	r := *pb
	r.labels = labels
	return &r
}

func (pb *podBuilderImpl) WithName(name string) PodBuilder {
	r := *pb
	r.name = name
	return &r
}

func (pb *podBuilderImpl) AddContainer(container apiv1.Container) PodBuilder {
	r := *pb
	r.containers = append(r.containers, container)
	return &r
}

func (pb *podBuilderImpl) WithCreator(creatorObjectMeta *metav1.ObjectMeta, creatorTypeMeta *metav1.TypeMeta) PodBuilder {
	r := *pb
	r.creatorObjectMeta = creatorObjectMeta
	r.creatorTypeMeta = creatorTypeMeta
	return &r
}

func (pb *podBuilderImpl) WithPhase(phase apiv1.PodPhase) PodBuilder {
	r := *pb
	r.phase = phase
	return &r
}

func (pb *podBuilderImpl) Get() *apiv1.Pod {
	startTime := metav1.Time{testTimestamp}
	pod := &apiv1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			Namespace: "default",
			Name:      pb.name,
		},
		Spec: apiv1.PodSpec{
			Containers: pb.containers,
		},
		Status: apiv1.PodStatus{
			StartTime: &startTime,
		},
	}

	if pb.labels != nil {
		pod.ObjectMeta.Labels = pb.labels
	}

	if pb.creatorObjectMeta != nil && pb.creatorTypeMeta != nil {
		isController := true
		pod.ObjectMeta.OwnerReferences = []metav1.OwnerReference{
			{
				UID:        pb.creatorObjectMeta.UID,
				Name:       pb.creatorObjectMeta.Name,
				APIVersion: pb.creatorObjectMeta.ResourceVersion,
				Kind:       pb.creatorTypeMeta.Kind,
				Controller: &isController,
			},
		}
	}
	if pb.phase != "" {
		pod.Status.Phase = pb.phase
	}

	return pod
}
<commit_msg>adding annotation to PodBuilder<commit_after>/*
Copyright 2018 The Kubernetes Authors.

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 test

import (
	apiv1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// PodBuilder helps building pods for tests.
type PodBuilder interface {
	WithName(name string) PodBuilder
	AddContainer(container apiv1.Container) PodBuilder
	WithCreator(creatorObjectMeta *metav1.ObjectMeta, creatorTypeMeta *metav1.TypeMeta) PodBuilder
	WithLabels(labels map[string]string) PodBuilder
	WithAnnotations(annotations map[string]string) PodBuilder
	WithPhase(phase apiv1.PodPhase) PodBuilder
	Get() *apiv1.Pod
}

// Pod returns new PodBuilder.
func Pod() PodBuilder {
	return &podBuilderImpl{
		containers: make([]apiv1.Container, 0),
	}
}

type podBuilderImpl struct {
	name              string
	containers        []apiv1.Container
	creatorObjectMeta *metav1.ObjectMeta
	creatorTypeMeta   *metav1.TypeMeta
	labels            map[string]string
	annotations       map[string]string
	phase             apiv1.PodPhase
}

func (pb *podBuilderImpl) WithLabels(labels map[string]string) PodBuilder {
	r := *pb
	r.labels = labels
	return &r
}

func (pb *podBuilderImpl) WithAnnotations(annotations map[string]string) PodBuilder {
	r := *pb
	r.annotations = annotations
	return &r
}

func (pb *podBuilderImpl) WithName(name string) PodBuilder {
	r := *pb
	r.name = name
	return &r
}

func (pb *podBuilderImpl) AddContainer(container apiv1.Container) PodBuilder {
	r := *pb
	r.containers = append(r.containers, container)
	return &r
}

func (pb *podBuilderImpl) WithCreator(creatorObjectMeta *metav1.ObjectMeta, creatorTypeMeta *metav1.TypeMeta) PodBuilder {
	r := *pb
	r.creatorObjectMeta = creatorObjectMeta
	r.creatorTypeMeta = creatorTypeMeta
	return &r
}

func (pb *podBuilderImpl) WithPhase(phase apiv1.PodPhase) PodBuilder {
	r := *pb
	r.phase = phase
	return &r
}

func (pb *podBuilderImpl) Get() *apiv1.Pod {
	startTime := metav1.Time{testTimestamp}
	pod := &apiv1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			Namespace: "default",
			Name:      pb.name,
		},
		Spec: apiv1.PodSpec{
			Containers: pb.containers,
		},
		Status: apiv1.PodStatus{
			StartTime: &startTime,
		},
	}

	if pb.labels != nil {
		pod.ObjectMeta.Labels = pb.labels
	}

	if pb.annotations != nil {
		pod.ObjectMeta.Annotations = pb.annotations
	}

	if pb.creatorObjectMeta != nil && pb.creatorTypeMeta != nil {
		isController := true
		pod.ObjectMeta.OwnerReferences = []metav1.OwnerReference{
			{
				UID:        pb.creatorObjectMeta.UID,
				Name:       pb.creatorObjectMeta.Name,
				APIVersion: pb.creatorObjectMeta.ResourceVersion,
				Kind:       pb.creatorTypeMeta.Kind,
				Controller: &isController,
			},
		}
	}
	if pb.phase != "" {
		pod.Status.Phase = pb.phase
	}

	return pod
}
<|endoftext|>


<commit_before>package detailed

import (
	"fmt"

	"github.com/weaveworks/scope/probe/docker"
	"github.com/weaveworks/scope/probe/host"
	"github.com/weaveworks/scope/probe/kubernetes"
	"github.com/weaveworks/scope/probe/process"
	"github.com/weaveworks/scope/render"
	"github.com/weaveworks/scope/report"
)

// NodeSummaryGroup is a topology-typed group of children for a Node.
type NodeSummaryGroup struct {
	Label      string        `json:"label"`
	Nodes      []NodeSummary `json:"nodes"`
	TopologyID string        `json:"topologyId"`
	Columns    []string      `json:"columns"`
}

// Copy returns a value copy of the NodeSummaryGroup
func (g NodeSummaryGroup) Copy() NodeSummaryGroup {
	result := NodeSummaryGroup{
		TopologyID: g.TopologyID,
		Label:      g.Label,
		Columns:    g.Columns,
	}
	for _, node := range g.Nodes {
		result.Nodes = append(result.Nodes, node.Copy())
	}
	return result
}

// NodeSummary is summary information about a child for a Node.
type NodeSummary struct {
	ID       string        `json:"id"`
	Label    string        `json:"label"`
	Linkable bool          `json:"linkable"` // Whether this node can be linked-to
	Metadata []MetadataRow `json:"metadata,omitempty"`
	Metrics  []MetricRow   `json:"metrics,omitempty"`
}

// MakeNodeSummary summarizes a node, if possible.
func MakeNodeSummary(n report.Node) (NodeSummary, bool) {
	renderers := map[string]func(report.Node) NodeSummary{
		"process":         processNodeSummary,
		"container":       containerNodeSummary,
		"container_image": containerImageNodeSummary,
		"pod":             podNodeSummary,
		"host":            hostNodeSummary,
	}
	if renderer, ok := renderers[n.Topology]; ok {
		return renderer(n), true
	}
	return NodeSummary{}, false
}

// Copy returns a value copy of the NodeSummary
func (n NodeSummary) Copy() NodeSummary {
	result := NodeSummary{
		ID:       n.ID,
		Label:    n.Label,
		Linkable: n.Linkable,
	}
	for _, row := range n.Metadata {
		result.Metadata = append(result.Metadata, row.Copy())
	}
	for _, row := range n.Metrics {
		result.Metrics = append(result.Metrics, row.Copy())
	}
	return result
}

func processNodeSummary(nmd report.Node) NodeSummary {
	var (
		id               string
		label, nameFound = nmd.Metadata[process.Name]
	)
	if pid, ok := nmd.Metadata[process.PID]; ok {
		if !nameFound {
			label = fmt.Sprintf("(%s)", pid)
		}
		id = render.MakeProcessID(report.ExtractHostID(nmd), pid)
	}
	_, isConnected := nmd.Metadata[render.IsConnected]
	return NodeSummary{
		ID:       id,
		Label:    label,
		Linkable: isConnected,
		Metadata: processNodeMetadata(nmd),
		Metrics:  processNodeMetrics(nmd),
	}
}

func containerNodeSummary(nmd report.Node) NodeSummary {
	label, _ := render.GetRenderableContainerName(nmd)
	return NodeSummary{
		ID:       render.MakeContainerID(nmd.Metadata[docker.ContainerID]),
		Label:    label,
		Linkable: true,
		Metadata: containerNodeMetadata(nmd),
		Metrics:  containerNodeMetrics(nmd),
	}
}

func containerImageNodeSummary(nmd report.Node) NodeSummary {
	imageName := nmd.Metadata[docker.ImageName]
	return NodeSummary{
		ID:       render.MakeContainerImageID(render.ImageNameWithoutVersion(imageName)),
		Label:    imageName,
		Linkable: true,
		Metadata: containerImageNodeMetadata(nmd),
	}
}

func podNodeSummary(nmd report.Node) NodeSummary {
	return NodeSummary{
		ID:       render.MakePodID(nmd.Metadata[kubernetes.PodID]),
		Label:    nmd.Metadata[kubernetes.PodName],
		Linkable: true,
		Metadata: podNodeMetadata(nmd),
	}
}

func hostNodeSummary(nmd report.Node) NodeSummary {
	return NodeSummary{
		ID:       render.MakeHostID(nmd.Metadata[host.HostName]),
		Label:    nmd.Metadata[host.HostName],
		Linkable: true,
		Metadata: hostNodeMetadata(nmd),
		Metrics:  hostNodeMetrics(nmd),
	}
}

type nodeSummariesByID []NodeSummary

func (s nodeSummariesByID) Len() int           { return len(s) }
func (s nodeSummariesByID) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
func (s nodeSummariesByID) Less(i, j int) bool { return s[i].ID < s[j].ID }
<commit_msg>use constants for topology names (missed a few)<commit_after>package detailed

import (
	"fmt"

	"github.com/weaveworks/scope/probe/docker"
	"github.com/weaveworks/scope/probe/host"
	"github.com/weaveworks/scope/probe/kubernetes"
	"github.com/weaveworks/scope/probe/process"
	"github.com/weaveworks/scope/render"
	"github.com/weaveworks/scope/report"
)

// NodeSummaryGroup is a topology-typed group of children for a Node.
type NodeSummaryGroup struct {
	Label      string        `json:"label"`
	Nodes      []NodeSummary `json:"nodes"`
	TopologyID string        `json:"topologyId"`
	Columns    []string      `json:"columns"`
}

// Copy returns a value copy of the NodeSummaryGroup
func (g NodeSummaryGroup) Copy() NodeSummaryGroup {
	result := NodeSummaryGroup{
		TopologyID: g.TopologyID,
		Label:      g.Label,
		Columns:    g.Columns,
	}
	for _, node := range g.Nodes {
		result.Nodes = append(result.Nodes, node.Copy())
	}
	return result
}

// NodeSummary is summary information about a child for a Node.
type NodeSummary struct {
	ID       string        `json:"id"`
	Label    string        `json:"label"`
	Linkable bool          `json:"linkable"` // Whether this node can be linked-to
	Metadata []MetadataRow `json:"metadata,omitempty"`
	Metrics  []MetricRow   `json:"metrics,omitempty"`
}

// MakeNodeSummary summarizes a node, if possible.
func MakeNodeSummary(n report.Node) (NodeSummary, bool) {
	renderers := map[string]func(report.Node) NodeSummary{
		report.Process:        processNodeSummary,
		report.Container:      containerNodeSummary,
		report.ContainerImage: containerImageNodeSummary,
		report.Pod:            podNodeSummary,
		report.Host:           hostNodeSummary,
	}
	if renderer, ok := renderers[n.Topology]; ok {
		return renderer(n), true
	}
	return NodeSummary{}, false
}

// Copy returns a value copy of the NodeSummary
func (n NodeSummary) Copy() NodeSummary {
	result := NodeSummary{
		ID:       n.ID,
		Label:    n.Label,
		Linkable: n.Linkable,
	}
	for _, row := range n.Metadata {
		result.Metadata = append(result.Metadata, row.Copy())
	}
	for _, row := range n.Metrics {
		result.Metrics = append(result.Metrics, row.Copy())
	}
	return result
}

func processNodeSummary(nmd report.Node) NodeSummary {
	var (
		id               string
		label, nameFound = nmd.Metadata[process.Name]
	)
	if pid, ok := nmd.Metadata[process.PID]; ok {
		if !nameFound {
			label = fmt.Sprintf("(%s)", pid)
		}
		id = render.MakeProcessID(report.ExtractHostID(nmd), pid)
	}
	_, isConnected := nmd.Metadata[render.IsConnected]
	return NodeSummary{
		ID:       id,
		Label:    label,
		Linkable: isConnected,
		Metadata: processNodeMetadata(nmd),
		Metrics:  processNodeMetrics(nmd),
	}
}

func containerNodeSummary(nmd report.Node) NodeSummary {
	label, _ := render.GetRenderableContainerName(nmd)
	return NodeSummary{
		ID:       render.MakeContainerID(nmd.Metadata[docker.ContainerID]),
		Label:    label,
		Linkable: true,
		Metadata: containerNodeMetadata(nmd),
		Metrics:  containerNodeMetrics(nmd),
	}
}

func containerImageNodeSummary(nmd report.Node) NodeSummary {
	imageName := nmd.Metadata[docker.ImageName]
	return NodeSummary{
		ID:       render.MakeContainerImageID(render.ImageNameWithoutVersion(imageName)),
		Label:    imageName,
		Linkable: true,
		Metadata: containerImageNodeMetadata(nmd),
	}
}

func podNodeSummary(nmd report.Node) NodeSummary {
	return NodeSummary{
		ID:       render.MakePodID(nmd.Metadata[kubernetes.PodID]),
		Label:    nmd.Metadata[kubernetes.PodName],
		Linkable: true,
		Metadata: podNodeMetadata(nmd),
	}
}

func hostNodeSummary(nmd report.Node) NodeSummary {
	return NodeSummary{
		ID:       render.MakeHostID(nmd.Metadata[host.HostName]),
		Label:    nmd.Metadata[host.HostName],
		Linkable: true,
		Metadata: hostNodeMetadata(nmd),
		Metrics:  hostNodeMetrics(nmd),
	}
}

type nodeSummariesByID []NodeSummary

func (s nodeSummariesByID) Len() int           { return len(s) }
func (s nodeSummariesByID) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
func (s nodeSummariesByID) Less(i, j int) bool { return s[i].ID < s[j].ID }
<|endoftext|>


<commit_before>package simple

import (
	log "github.com/Sirupsen/logrus"
	"github.com/loadimpact/speedboat"
	"github.com/loadimpact/speedboat/sampler"
	"github.com/valyala/fasthttp"
	"golang.org/x/net/context"
	"time"
)

type Runner struct {
	Client *fasthttp.Client
}

func New() *Runner {
	return &Runner{
		Client: &fasthttp.Client{
			MaxIdleConnDuration: time.Duration(0),
		},
	}
}

func (r *Runner) RunVU(ctx context.Context, t speedboat.Test, id int) {
	mDuration := sampler.Stats("request.duration")
	mErrors := sampler.Counter("request.error")
	for {
		req := fasthttp.AcquireRequest()
		defer fasthttp.ReleaseRequest(req)

		res := fasthttp.AcquireResponse()
		defer fasthttp.ReleaseResponse(res)

		req.SetRequestURI(t.URL)

		startTime := time.Now()
		if err := r.Client.Do(req, res); err != nil {
			log.WithError(err).Error("Request error")
			mErrors.WithField("url", t.URL).Int(1)
		}
		duration := time.Since(startTime)

		mDuration.WithField("url", t.URL).Duration(duration)

		select {
		case <-ctx.Done():
			return
		default:
		}
	}
}
<commit_msg>[fix] I accidentally a fountain of unGCable junk<commit_after>package simple

import (
	log "github.com/Sirupsen/logrus"
	"github.com/loadimpact/speedboat"
	"github.com/loadimpact/speedboat/sampler"
	"github.com/valyala/fasthttp"
	"golang.org/x/net/context"
	"time"
)

type Runner struct {
	Client *fasthttp.Client
}

func New() *Runner {
	return &Runner{
		Client: &fasthttp.Client{
			MaxIdleConnDuration: time.Duration(0),
		},
	}
}

func (r *Runner) RunVU(ctx context.Context, t speedboat.Test, id int) {
	mDuration := sampler.Stats("request.duration")
	mErrors := sampler.Counter("request.error")

	req := fasthttp.AcquireRequest()
	defer fasthttp.ReleaseRequest(req)
	res := fasthttp.AcquireResponse()
	defer fasthttp.ReleaseResponse(res)

	for {
		req.Reset()
		req.SetRequestURI(t.URL)
		res.Reset()

		startTime := time.Now()
		if err := r.Client.Do(req, res); err != nil {
			log.WithError(err).Error("Request error")
			mErrors.WithField("url", t.URL).Int(1)
		}
		duration := time.Since(startTime)

		mDuration.WithField("url", t.URL).Duration(duration)

		select {
		case <-ctx.Done():
			return
		default:
		}
	}
}
<|endoftext|>


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

package simplesession

import (
	"bytes"
	"crypto/rand"
	"crypto/sha256"
	"encoding/gob"
	"encoding/hex"
	"errors"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"strconv"
	"sync"
	"time"
)

const (
	sidLength = 32
	sfileDir  = "/tmp"
)

func New(res http.ResponseWriter, option *Option) (*SimpleSession, error) {
	id, err := generateId()
	if err != nil {
		return nil, err
	}

	fpath := filepath.Join(sfileDir, "gosession_"+id)

	ss := &SimpleSession{
		name:   "GSESSIONID",
		id:     id,
		fpath:  fpath,
		option: option,
		data:   make(map[string]interface{}),
	}

	cookie := &http.Cookie{
		Name:     ss.name,
		Value:    ss.id,
		Path:     ss.option.Path,
		Domain:   ss.option.Domain,
		MaxAge:   ss.option.MaxAge,
		Secure:   ss.option.Secure,
		HttpOnly: ss.option.HttpOnly,
	}
	http.SetCookie(res, cookie)

	return ss, nil
}

type SimpleSession struct {
	name   string
	id     string
	fpath  string
	option *Option
	data   map[string]interface{}
}

func (ss *SimpleSession) Name() string {
	return ss.name
}

func (ss *SimpleSession) Id() string {
	return ss.id
}

func (ss *SimpleSession) FilePath() string {
	return ss.fpath
}

func (ss *SimpleSession) Set(key string, val interface{}) {
	ss.data[key] = val
}

func (ss *SimpleSession) Get(key string) interface{} {
	if val, found := ss.data[key]; found {
		return val
	}
	return nil
}

func (ss *SimpleSession) Del(key string) {
	if _, found := ss.data[key]; found {
		delete(ss.data, key)
	}
}

func (ss *SimpleSession) Write(res http.ResponseWriter, req *http.Request) error {
	serialized, err := serialize(ss.data)
	if err != nil {
		return err
	}

	var fmutex = &sync.RWMutex{}

	fmutex.Lock()
	fp, err := os.OpenFile(ss.fpath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666)
	if err != nil {
		return errors.New("simplesession: could not open session file")
	}
	defer fp.Close()

	if _, err = fp.Write(serialized); err != nil {
		return errors.New("simplesession: could not write session file")
	}
	defer fmutex.Unlock()

	return nil
}

// Read reads stored session
func Read(req *http.Request) (*SimpleSession, error) {
	cke, err := req.Cookie("GSESSIONID")
	if err != nil {
		return nil, errors.New("simplesession: session not set")
	}

	option := &Option{
		Path:     cke.Path,
		Domain:   cke.Domain,
		MaxAge:   cke.MaxAge,
		Secure:   cke.Secure,
		HttpOnly: cke.HttpOnly,
	}

	fpath := filepath.Join(sfileDir, "gosession_"+cke.Value)

	fp, err := os.OpenFile(fpath, os.O_RDONLY, 0400)
	if err != nil {
		return nil, errors.New("simplesession: could not open session file")
	}
	defer fp.Close()

	buf := make([]byte, 256)
	var serialized []byte
	for {
		_, err = fp.Read(buf)
		if err != nil || err == io.EOF {
			break
		}
		serialized = append(serialized, buf[0:]...)
	}

	data := make(map[string]interface{})
	if err = unserialize(serialized, data); err != nil {
		return nil, err
	}

	ss := &SimpleSession{
		name:   cke.Name,
		id:     cke.Value,
		fpath:  fpath,
		option: option,
		data:   data,
	}

	return ss, nil
}

func (ss *SimpleSession) Destroy(res http.ResponseWriter) error {

	cookie := &http.Cookie{
		Name:   ss.name,
		Value:  "",
		Path:   ss.option.Path,
		Domain: ss.option.Domain,
		MaxAge: -1,
	}
	http.SetCookie(res, cookie)

	if err := os.Remove(ss.fpath); err != nil {
		return errors.New("simplesession: no session file found")
	}

	return nil
}

// generateId generates a session id
func generateId() (string, error) {

	hash := sha256.New()
	io.WriteString(hash, strconv.FormatInt(time.Now().Unix(), 10))

	uran := make([]byte, 2048)
	if _, err := io.ReadFull(rand.Reader, uran); err != nil {
		return "", errors.New("simplesession: could not generate random key")
	}

	hash.Write(uran)
	id := hex.EncodeToString(hash.Sum(nil))

	fpath := filepath.Join(sfileDir, "gosession_"+id)
	if _, err := os.Stat(fpath); err == nil {
		generateId()
	}

	return id[0:sidLength], nil
}

// serialize encodes a value using binary.
func serialize(src map[string]interface{}) ([]byte, error) {
	buf := new(bytes.Buffer)
	if err := gob.NewEncoder(buf).Encode(src); err != nil {
		return nil, errors.New("simplesession: error occured while serializing session")
	}
	return buf.Bytes(), nil
}

// unserialize decodes a value using binary.
func unserialize(src []byte, dst map[string]interface{}) error {
	buf := bytes.NewReader(src)
	if err := gob.NewDecoder(buf).Decode(&dst); err != nil {
		return errors.New("simplesession: error occured while unserializing session")
	}
	return nil
}

type Option struct {
	Path     string
	Domain   string
	MaxAge   int
	Secure   bool
	HttpOnly bool
}
<commit_msg>Change hash function(sha1 from sha256)<commit_after>//Copyright 2014 Mahendra Kathirvel. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package simplesession

import (
	"bytes"
	"crypto/rand"
	"crypto/sha1"
	"encoding/gob"
	"encoding/hex"
	"errors"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"strconv"
	"sync"
	"time"
)

const (
	sidLength = 32
	sfileDir  = "/tmp"
)

func New(res http.ResponseWriter, option *Option) (*SimpleSession, error) {
	id, err := generateId()
	if err != nil {
		return nil, err
	}

	fpath := filepath.Join(sfileDir, "gosession_"+id)

	ss := &SimpleSession{
		name:   "GSESSIONID",
		id:     id,
		fpath:  fpath,
		option: option,
		data:   make(map[string]interface{}),
	}

	cookie := &http.Cookie{
		Name:     ss.name,
		Value:    ss.id,
		Path:     ss.option.Path,
		Domain:   ss.option.Domain,
		MaxAge:   ss.option.MaxAge,
		Secure:   ss.option.Secure,
		HttpOnly: ss.option.HttpOnly,
	}
	http.SetCookie(res, cookie)

	return ss, nil
}

type SimpleSession struct {
	name   string
	id     string
	fpath  string
	option *Option
	data   map[string]interface{}
}

func (ss *SimpleSession) Name() string {
	return ss.name
}

func (ss *SimpleSession) Id() string {
	return ss.id
}

func (ss *SimpleSession) FilePath() string {
	return ss.fpath
}

func (ss *SimpleSession) Set(key string, val interface{}) {
	ss.data[key] = val
}

func (ss *SimpleSession) Get(key string) interface{} {
	if val, found := ss.data[key]; found {
		return val
	}
	return nil
}

func (ss *SimpleSession) Del(key string) {
	if _, found := ss.data[key]; found {
		delete(ss.data, key)
	}
}

func (ss *SimpleSession) Write(res http.ResponseWriter, req *http.Request) error {
	serialized, err := serialize(ss.data)
	if err != nil {
		return err
	}

	var fmutex = &sync.RWMutex{}

	fmutex.Lock()
	fp, err := os.OpenFile(ss.fpath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666)
	if err != nil {
		return errors.New("simplesession: could not open session file")
	}
	defer fp.Close()

	if _, err = fp.Write(serialized); err != nil {
		return errors.New("simplesession: could not write session file")
	}
	defer fmutex.Unlock()

	return nil
}

// Read reads stored session
func Read(req *http.Request) (*SimpleSession, error) {
	cke, err := req.Cookie("GSESSIONID")
	if err != nil {
		return nil, errors.New("simplesession: session not set")
	}

	option := &Option{
		Path:     cke.Path,
		Domain:   cke.Domain,
		MaxAge:   cke.MaxAge,
		Secure:   cke.Secure,
		HttpOnly: cke.HttpOnly,
	}

	fpath := filepath.Join(sfileDir, "gosession_"+cke.Value)

	fp, err := os.OpenFile(fpath, os.O_RDONLY, 0400)
	if err != nil {
		return nil, errors.New("simplesession: could not open session file")
	}
	defer fp.Close()

	buf := make([]byte, 128)
	var serialized []byte
	for {
		_, err = fp.Read(buf)
		if err != nil || err == io.EOF {
			break
		}
		serialized = append(serialized, buf[0:]...)
	}

	data := make(map[string]interface{})
	if err = unserialize(serialized, data); err != nil {
		return nil, err
	}

	ss := &SimpleSession{
		name:   cke.Name,
		id:     cke.Value,
		fpath:  fpath,
		option: option,
		data:   data,
	}

	return ss, nil
}

func (ss *SimpleSession) Destroy(res http.ResponseWriter) error {

	cookie := &http.Cookie{
		Name:   ss.name,
		Value:  "",
		Path:   ss.option.Path,
		Domain: ss.option.Domain,
		MaxAge: -1,
	}
	http.SetCookie(res, cookie)

	if err := os.Remove(ss.fpath); err != nil {
		return errors.New("simplesession: no session file found")
	}

	return nil
}

// generateId generates a session id
func generateId() (string, error) {

	hash := sha1.New()
	io.WriteString(hash, strconv.FormatInt(time.Now().Unix(), 10))

	uran := make([]byte, 1024)
	if _, err := io.ReadFull(rand.Reader, uran); err != nil {
		return "", errors.New("simplesession: could not generate random key")
	}

	hash.Write(uran)
	id := hex.EncodeToString(hash.Sum(nil))

	fpath := filepath.Join(sfileDir, "gosession_"+id)
	if _, err := os.Stat(fpath); err == nil {
		generateId()
	}

	return id[0:sidLength], nil
}

// serialize encodes a value using binary.
func serialize(src map[string]interface{}) ([]byte, error) {
	buf := new(bytes.Buffer)
	if err := gob.NewEncoder(buf).Encode(src); err != nil {
		return nil, errors.New("simplesession: error occured while serializing session")
	}
	return buf.Bytes(), nil
}

// unserialize decodes a value using binary.
func unserialize(src []byte, dst map[string]interface{}) error {
	buf := bytes.NewReader(src)
	if err := gob.NewDecoder(buf).Decode(&dst); err != nil {
		return errors.New("simplesession: error occured while unserializing session")
	}
	return nil
}

type Option struct {
	Path     string
	Domain   string
	MaxAge   int
	Secure   bool
	HttpOnly bool
}
<|endoftext|>


<commit_before>package userroute

import (
	"context"
	"fmt"
	"github.com/Hackform/Eiffel"
	"github.com/Hackform/Eiffel/model/user"
	"github.com/Hackform/Eiffel/service/repo"
	"github.com/pressly/chi"
	"github.com/pressly/chi/render"
	"github.com/pressly/lg"
	"net/http"
	"regexp"
)

type (
	userroute struct {
		repo repo.Repo
	}

	resUsersPrivate struct {
		Data user.ModelPrivate `json:"user"`
	}

	resUsersPublic struct {
		Data user.ModelPublic `json:"user"`
	}

	resUsersErr struct {
		Message string
	}
)

// New creates a user router
func New(repository repo.Repo) eiffel.Route {
	return &userroute{
		repo: repository,
	}
}

var (
	regexUsername = regexp.MustCompile(`[a-zA-Z0-9_]{1,32}`)
)

func isValidUsername(username string) bool {
	return regexUsername.MatchString(username)
}

type (
	contextKey string
)

const (
	ctxKeyUsermodel = contextKey("usermodel")
)

func (rr *userroute) Register(r chi.Router) {
	r.Route("/u/:username", func(r chi.Router) {
		r.Use(func(next http.Handler) http.Handler {
			return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
				username := chi.URLParam(r, "username")

				if !isValidUsername(username) {
					render.Status(r, http.StatusBadRequest)
					render.JSON(w, r, resUsersErr{
						Message: "Username must be between 1 and 32 characters",
					})
					return
				}

				tx, err := rr.repo.Transaction()
				if err != nil {
					lg.RequestLog(r).WithError(err).Error("Failed to acquire transaction")
					render.Status(r, http.StatusInternalServerError)
					render.JSON(w, r, resUsersErr{
						Message: "Failed transaction",
					})
					return
				}

				usermodel, err := user.SelectByUsername(tx, username)
				if err != nil {
					lg.RequestLog(r).WithError(err).Warn("User not found")
					render.Status(r, http.StatusNotFound)
					render.JSON(w, r, resUsersErr{
						Message: "User not found",
					})
					return
				}

				ctx := context.WithValue(r.Context(), ctxKeyUsermodel, usermodel)
				next.ServeHTTP(w, r.WithContext(ctx))
			})
		})

		r.Get("/", func(w http.ResponseWriter, r *http.Request) {
			// TODO: status logs
			usermodel := r.Context().Value(ctxKeyUsermodel).(*user.Model)
			render.Status(r, http.StatusNotFound)
			render.JSON(w, r, resUsersPublic{
				Data: *usermodel.GetPublic(),
			})
			return
		})

		r.Get("/private", func(w http.ResponseWriter, r *http.Request) {
			// TODO: protect jwt
			usermodel := r.Context().Value(ctxKeyUsermodel).(*user.Model)
			render.Status(r, http.StatusNotFound)
			render.JSON(w, r, resUsersPrivate{
				Data: *usermodel.GetPrivate(),
			})
			return
		})
	})

	r.Get("/id/:userid", func(c echo.Context) error {
		userid := c.Param("userid")

		var tx repo.Tx
		var err error
		if tx, err = r.repo.Transaction(); err != nil {
			log.Errorf("transaction: %s", err)
			return c.JSON(http.StatusInternalServerError, resUsersErr{
				Message: "Failed transaction",
			})
		}

		usermodel, err := user.Select(tx, userid)
		if err != nil {
			log.Warnf("Select user by id: %s", err)
			return c.JSON(http.StatusNotFound, resUsersErr{
				Message: "Failed to find user",
			})
		}

		return c.JSON(http.StatusOK, resUsersPublic{
			Data: *usermodel.GetPublic(),
		})
	})

	g.GET("/id/:userid/private", func(c echo.Context) error {
		userid := c.Param("userid")

		var tx repo.Tx
		var err error
		if tx, err = r.repo.Transaction(); err != nil {
			log.Errorf("transaction: %s", err)
			return c.JSON(http.StatusInternalServerError, resUsersErr{
				Message: "Failed transaction",
			})
		}

		usermodel, err := user.Select(tx, userid)
		if err != nil {
			log.Warnf("Select user by id: %s", err)
			return c.JSON(http.StatusNotFound, resUsersErr{
				Message: "Failed to find user",
			})
		}

		return c.JSON(http.StatusOK, resUsersPrivate{
			Data: *usermodel.GetPrivate(),
		})
	}) // TODO: get jwt middleware

	g.POST("/:code", func(c echo.Context) error {
		return c.String(http.StatusOK, fmt.Sprintf("POST /users"))
	})
}
<commit_msg>users route<commit_after>package userroute

import (
	"fmt"
	"github.com/Hackform/Eiffel"
	"github.com/Hackform/Eiffel/model/user"
	"github.com/Hackform/Eiffel/service/repo"
	"github.com/pressly/chi"
	"github.com/pressly/chi/render"
	"github.com/pressly/lg"
	"net/http"
	"regexp"
)

type (
	userroute struct {
		repo repo.Repo
	}

	resUsersPrivate struct {
		Data user.ModelPrivate `json:"user"`
	}

	resUsersPublic struct {
		Data user.ModelPublic `json:"user"`
	}

	resUsersErr struct {
		Message string
	}
)

// New creates a user router
func New(repository repo.Repo) eiffel.Route {
	return &userroute{
		repo: repository,
	}
}

var (
	regexUsername = regexp.MustCompile(`^[a-zA-Z0-9_\-]{1,32}$`)
	regexUserid   = regexp.MustCompile(`^[a-zA-Z0-9_\-=]{1,32}$`)
)

func isValidUsername(username string) bool {
	return regexUsername.MatchString(username)
}
func isValidUserid(userid string) bool {
	return regexUserid.MatchString(userid)
}

func (rr *userroute) Register(r chi.Router) {
	r.Route("/u/:username", func(r chi.Router) {
		r.Get("/", func(w http.ResponseWriter, r *http.Request) {
			username := chi.URLParam(r, "username")
			if !isValidUsername(username) {
				render.Status(r, http.StatusBadRequest)
				render.JSON(w, r, resUsersErr{
					Message: "Username must be between 1 and 32 characters and only be composed of a-z, A-Z, 0-9, _, -",
				})
				return
			}
			tx, err := rr.repo.Transaction()
			if err != nil {
				lg.RequestLog(r).WithError(err).Error("Failed to acquire transaction")
				render.Status(r, http.StatusInternalServerError)
				render.JSON(w, r, resUsersErr{
					Message: "Failed transaction",
				})
				return
			}
			usermodel, err := user.SelectByUsername(tx, username)
			if err != nil {
				lg.RequestLog(r).WithError(err).Warn("User not found")
				render.Status(r, http.StatusNotFound)
				render.JSON(w, r, resUsersErr{
					Message: "User not found",
				})
				return
			}
			// TODO: status logs
			render.Status(r, http.StatusNotFound)
			render.JSON(w, r, resUsersPublic{
				Data: *usermodel.GetPublic(),
			})
			return
		})

		r.Get("/private", func(w http.ResponseWriter, r *http.Request) {
			// TODO: protect jwt
			username := chi.URLParam(r, "username")
			if !isValidUsername(username) {
				render.Status(r, http.StatusBadRequest)
				render.JSON(w, r, resUsersErr{
					Message: "Username must be between 1 and 32 characters",
				})
				return
			}
			tx, err := rr.repo.Transaction()
			if err != nil {
				lg.RequestLog(r).WithError(err).Error("Failed to acquire transaction")
				render.Status(r, http.StatusInternalServerError)
				render.JSON(w, r, resUsersErr{
					Message: "Failed transaction",
				})
				return
			}
			usermodel, err := user.SelectByUsername(tx, username)
			if err != nil {
				lg.RequestLog(r).WithError(err).Warn("User not found")
				render.Status(r, http.StatusNotFound)
				render.JSON(w, r, resUsersErr{
					Message: "User not found",
				})
				return
			}
			render.Status(r, http.StatusNotFound)
			render.JSON(w, r, resUsersPrivate{
				Data: *usermodel.GetPrivate(),
			})
			return
		})
	})

	r.Get("/id/:userid", func(w http.ResponseWriter, r *http.Request) {
		userid := chi.URLParam(r, "userid")
		if !isValidUserid(userid) {
			render.Status(r, http.StatusBadRequest)
			render.JSON(w, r, resUsersErr{
				Message: "Invalid userid",
			})
			return
		}
		tx, err := rr.repo.Transaction()
		if err != nil {
			lg.RequestLog(r).WithError(err).Error("Failed to acquire transaction")
			render.Status(r, http.StatusInternalServerError)
			render.JSON(w, r, resUsersErr{
				Message: "Failed transaction",
			})
			return
		}
		usermodel, err := user.Select(tx, userid)
		if err != nil {
			lg.RequestLog(r).WithError(err).Warn("User not found")
			render.Status(r, http.StatusNotFound)
			render.JSON(w, r, resUsersErr{
				Message: "User not found",
			})
			return
		}
		render.Status(r, http.StatusNotFound)
		render.JSON(w, r, resUsersPublic{
			Data: *usermodel.GetPublic(),
		})
		return
	})

	r.Get("/id/:userid/private", func(w http.ResponseWriter, r *http.Request) {
		// TODO: get jwt middleware
		userid := chi.URLParam(r, "userid")
		if !isValidUserid(userid) {
			render.Status(r, http.StatusBadRequest)
			render.JSON(w, r, resUsersErr{
				Message: "Invalid userid",
			})
			return
		}
		tx, err := rr.repo.Transaction()
		if err != nil {
			lg.RequestLog(r).WithError(err).Error("Failed to acquire transaction")
			render.Status(r, http.StatusInternalServerError)
			render.JSON(w, r, resUsersErr{
				Message: "Failed transaction",
			})
			return
		}
		usermodel, err := user.Select(tx, userid)
		if err != nil {
			lg.RequestLog(r).WithError(err).Warn("User not found")
			render.Status(r, http.StatusNotFound)
			render.JSON(w, r, resUsersErr{
				Message: "User not found",
			})
			return
		}
		render.Status(r, http.StatusNotFound)
		render.JSON(w, r, resUsersPrivate{
			Data: *usermodel.GetPrivate(),
		})
		return
	})

	r.Post("/:code", func(w http.ResponseWriter, r *http.Request) {
		code := chi.URLParam(r, "code")
		render.PlainText(w, r, fmt.Sprintf("create new user %s", code))
	})
}
<|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2016 Maciej Borzecki

// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package site

import (
	"github.com/bboozzoo/q3stats/models"
	"github.com/gorilla/mux"
	"log"
	"net/http"
)

type matchViewWeaponStat struct {
	models.WeaponStat
}

type matchViewPlayerData struct {
	PlayerID     uint
	Alias        string
	GeneralStats models.PlayerMatchStat
	Weapons      map[string]matchViewWeaponStat
	Items        map[string]models.ItemStat
}

func (s *Site) matchViewHandler(w http.ResponseWriter, req *http.Request) {
	log.Printf("site match view handler")
	id := mux.Vars(req)["id"]

	log.Printf("match ID: %s", id)

	m := s.m.GetMatchInfo(id)
	if m == nil {
		http.Error(w, "match not found", http.StatusNotFound)
	}

	data := struct {
		// data of all players
		Players []matchViewPlayerData
		Desc    *models.DescData
	}{
		make([]matchViewPlayerData, len(m.PlayerData)),
		models.GetItemDesc(),
	}

	// repack to a format expected by the template
	for i, pd := range m.PlayerData {
		mvpd := matchViewPlayerData{
			pd.Alias.PlayerID,
			pd.Alias.Alias,
			pd.Stats,
			make(map[string]matchViewWeaponStat),
			make(map[string]models.ItemStat),
		}
		for _, wd := range pd.Weapons {
			mvpd.Weapons[wd.Type] = matchViewWeaponStat{
				wd,
			}
		}

		for _, itd := range pd.Items {
			mvpd.Items[itd.Type] = itd
		}
		data.Players[i] = mvpd
	}

	s.loadRenderOrError(w, data, "match.tmpl", "base.tmpl")
}
<commit_msg>site/matchview: pass Match to template<commit_after>// The MIT License (MIT)

// Copyright (c) 2016 Maciej Borzecki

// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package site

import (
	"github.com/bboozzoo/q3stats/models"
	"github.com/gorilla/mux"
	"log"
	"net/http"
)

type matchViewWeaponStat struct {
	models.WeaponStat
}

type matchViewPlayerData struct {
	PlayerID     uint
	Alias        string
	GeneralStats models.PlayerMatchStat
	Weapons      map[string]matchViewWeaponStat
	Items        map[string]models.ItemStat
}

func (s *Site) matchViewHandler(w http.ResponseWriter, req *http.Request) {
	log.Printf("site match view handler")
	id := mux.Vars(req)["id"]

	log.Printf("match ID: %s", id)

	m := s.m.GetMatchInfo(id)
	if m == nil {
		http.Error(w, "match not found", http.StatusNotFound)
	}

	data := struct {
		// data of all players
		Players []matchViewPlayerData
		// user presentable data descriptor
		Desc *models.DescData
		// match information
		Match models.Match
	}{
		make([]matchViewPlayerData, len(m.PlayerData)),
		models.GetItemDesc(),
		m.Match,
	}

	// repack to a format expected by the template
	for i, pd := range m.PlayerData {
		mvpd := matchViewPlayerData{
			pd.Alias.PlayerID,
			pd.Alias.Alias,
			pd.Stats,
			make(map[string]matchViewWeaponStat),
			make(map[string]models.ItemStat),
		}
		for _, wd := range pd.Weapons {
			mvpd.Weapons[wd.Type] = matchViewWeaponStat{
				wd,
			}
		}

		for _, itd := range pd.Items {
			mvpd.Items[itd.Type] = itd
		}
		data.Players[i] = mvpd
	}

	s.loadRenderOrError(w, data, "match.tmpl", "base.tmpl")
}
<|endoftext|>


<commit_before>// template used to generate a Go program for compilation to binary.
package main

import "text/template"

var generatedTmpl = template.Must(template.New("generated").Parse(`
// generated by brainfuck-go; DO NOT EDIT

package main

import (
	"bufio"
	"os"

	"github.com/domluna/brainfuck-go/tape"
	"github.com/domluna/brainfuck-go/program"
)

func main() {
	var b byte
	t := tape.New()
	in := bufio.NewReader(os.Stdin)
	out := byteWriterFlusher{bufio.NewWriter(os.Stdout)}

	{{range .Insts}}
	{{ .Eval 1 2 3 }}
	{{end}}
}
`))
<commit_msg>removed template, turned out templates didn't work how I thought they might!<commit_after><|endoftext|>


<commit_before>package epochs

import (
	"math/big"
	"time"
)

// Epoch gets a Unix time of the given x after dividing by q and
// adding s.
func epoch(x, q, s *big.Int) time.Time {
	z := new(big.Int)
	m := new(big.Int)
	z.DivMod(x, q, m)
	z.Add(z, s)
	r := m.Mul(m, big.NewInt(1e9)).Div(m, q)
	return time.Unix(z.Int64(), r.Int64()).UTC()
}

// Chrome time is the number of microseconds since 1601-01-01, which
// is 11,644,473,600 seconds before the Unix epoch.
func Chrome(num int64) time.Time {
	return epoch(big.NewInt(num), big.NewInt(1e6), big.NewInt(-11644473600))
}

// Cocoa time is the number of seconds since 2001-01-01, which
// is 978,307,200 seconds after the Unix epoch.
func Cocoa(num int64) time.Time {
	return epoch(big.NewInt(num), big.NewInt(1), big.NewInt(978307200))
}

// Java time is the number of milliseconds since the (regular, Unix) epoch.
func Java(num int64) time.Time {
	return epoch(big.NewInt(num), big.NewInt(1000), big.NewInt(0))
}

// Mozilla time (e.g., formhistory.sqlite) is the number of
// microseconds since the (regular, Unix) epoch.
func Mozilla(num int64) time.Time {
	return epoch(big.NewInt(num), big.NewInt(1000000), big.NewInt(0))
}

// Symbian time is the number of microseconds since the year 0, which
// is 62,167,219,200 seconds before the Unix epoch.
func Symbian(num int64) time.Time {
	return epoch(big.NewInt(num), big.NewInt(1000000), big.NewInt(-62167219200))
}

// Unix time is the number of seconds since 1970-01-01.
func Unix(num int64) time.Time {
	return time.Unix(num, 0).UTC()
}
<commit_msg>add UUIDv1 time<commit_after>package epochs

import (
	"math/big"
	"time"
)

// Epoch gets a Unix time of the given x after dividing by q and
// adding s.
func epoch(x, q, s *big.Int) time.Time {
	z := new(big.Int)
	m := new(big.Int)
	z.DivMod(x, q, m)
	z.Add(z, s)
	r := m.Mul(m, big.NewInt(1e9)).Div(m, q)
	return time.Unix(z.Int64(), r.Int64()).UTC()
}

// Chrome time is the number of microseconds since 1601-01-01, which
// is 11,644,473,600 seconds before the Unix epoch.
func Chrome(num int64) time.Time {
	return epoch(big.NewInt(num), big.NewInt(1e6), big.NewInt(-11644473600))
}

// Cocoa time is the number of seconds since 2001-01-01, which
// is 978,307,200 seconds after the Unix epoch.
func Cocoa(num int64) time.Time {
	return epoch(big.NewInt(num), big.NewInt(1), big.NewInt(978307200))
}

// Java time is the number of milliseconds since the Unix epoch.
func Java(num int64) time.Time {
	return epoch(big.NewInt(num), big.NewInt(1000), big.NewInt(0))
}

// Mozilla time (e.g., formhistory.sqlite) is the number of
// microseconds since the Unix epoch.
func Mozilla(num int64) time.Time {
	return epoch(big.NewInt(num), big.NewInt(1000000), big.NewInt(0))
}

// Symbian time is the number of microseconds since the year 0, which
// is 62,167,219,200 seconds before the Unix epoch.
func Symbian(num int64) time.Time {
	return epoch(big.NewInt(num), big.NewInt(1000000), big.NewInt(-62167219200))
}

// Unix time is the number of seconds since 1970-01-01.
func Unix(num int64) time.Time {
	return time.Unix(num, 0).UTC()
}

// UUID version 1 time (RFC 4122) is the number of hectonanoseconds
// (100 ns) since 1582-10-15, which is 12,219,292,800 seconds before
// the Unix epoch.
func UUIDv1(num int64) time.Time {
	return epoch(
		big.NewInt(num),
		big.NewInt(10000000),
		big.NewInt(-12219292800),
	)
}
<|endoftext|>