<commit_before>package models

import (
	"errors"
	"fmt"

	"github.com/jinzhu/gorm"
	"github.com/koding/bongo"
)

type Account struct {
	// unique id of the account
	Id int64 `json:"id,string"`

	// old id of the account, which is originally
	// perisisted in mongo
	// mongo ids has 24 char
	OldId string `json:"oldId"      sql:"NOT NULL;UNIQUE;TYPE:VARCHAR(24);"`
}

func NewAccount() *Account {
	return &Account{}
}

func (a Account) GetId() int64 {
	return a.Id
}

func (a Account) TableName() string {
	return "api.account"
}

func (a *Account) One(q *bongo.Query) error {
	return bongo.B.One(a, a, q)
}

func (a *Account) ById(id int64) error {
	return bongo.B.ById(a, id)
}

func (a *Account) FetchOrCreate() error {
	if a.OldId == "" {
		return errors.New("old id is not set")
	}

	selector := map[string]interface{}{
		"old_id": a.OldId,
	}

	err := a.One(bongo.NewQS(selector))
	// if we dont get any error
	// it means we found the record in our db
	if err == nil {
		return nil
	}

	// first check if the err is not found err
	if err == gorm.RecordNotFound {
		if err := a.Create(); err != nil {
			return err
		}
		return nil
	}

	return err
}

func (a *Account) Create() error {
	if a.OldId == "" {
		return errors.New("old id is not set")
	}

	return bongo.B.Create(a)
}

func (a *Account) Some(data interface{}, q *bongo.Query) error {
	return bongo.B.Some(a, data, q)
}

func (a *Account) FetchChannels(q *Query) ([]Channel, error) {
	cp := NewChannelParticipant()
	// fetch channel ids
	cids, err := cp.FetchParticipatedChannelIds(a, q)
	if err != nil {
		return nil, err
	}

	// fetch channels by their ids
	channels, err := NewChannel().FetchByIds(cids)
	if err != nil {
		return nil, err
	}

	return channels, nil
}

func (a *Account) Follow(targetId int64) (*ChannelParticipant, error) {
	c, err := a.FetchChannel(Channel_TYPE_FOLLOWERS)
	if err == nil {
		return c.AddParticipant(targetId)
	}

	if err == gorm.RecordNotFound {
		c, err := a.CreateFollowingFeedChannel()
		if err != nil {
			return nil, err
		}
		return c.AddParticipant(targetId)
	}

	return nil, err
}

func (a *Account) Unfollow(targetId int64) (*Account, error) {
	c, err := a.FetchChannel(Channel_TYPE_FOLLOWERS)
	if err != nil {
		return nil, err
	}

	return a, c.RemoveParticipant(targetId)
}

func (a *Account) FetchFollowerIds() ([]int64, error) {
	followerIds := make([]int64, 0)
	if a.Id == 0 {
		return nil, errors.New(
			"Account id is not set for FetchFollowerChannelIds function ",
		)
	}

	c, err := a.FetchChannel(Channel_TYPE_FOLLOWERS)
	if err != nil {
		return followerIds, err
	}

	participants, err := c.FetchParticipantIds()
	if err != nil {
		return followerIds, err
	}

	return participants, nil
}

func (a *Account) FetchChannel(channelType string) (*Channel, error) {
	if a.Id == 0 {
		return nil, errors.New("Account id is not set")
	}

	c := NewChannel()
	selector := map[string]interface{}{
		"creator_id":    a.Id,
		"type_constant": channelType,
	}

	if err := c.One(bongo.NewQS(selector)); err != nil {
		return nil, err
	}

	return c, nil
}

func (a *Account) CreateFollowingFeedChannel() (*Channel, error) {
	if a.Id == 0 {
		return nil, errors.New("Account id is not set")
	}

	c := NewChannel()
	c.CreatorId = a.Id
	c.Name = fmt.Sprintf("%d-FollowingFeedChannel", a.Id)
	c.GroupName = Channel_KODING_NAME
	c.Purpose = "Following Feed for Me"
	c.TypeConstant = Channel_TYPE_FOLLOWERS
	if err := c.Create(); err != nil {
		return nil, err
	}

	return c, nil
}

func (a *Account) FetchFollowerChannelIds() ([]int64, error) {

	followerIds, err := a.FetchFollowerIds()
	if err != nil {
		return nil, err
	}

	cp := NewChannelParticipant()
	var channelIds []int64
	res := bongo.B.DB.
		Table(cp.TableName()).
		Where(
		"creator_id IN (?) and type_constant = ?",
		followerIds,
		Channel_TYPE_FOLLOWINGFEED,
	).Find(&channelIds)

	if err := bongo.CheckErr(res); err != nil {
		return nil, err
	}

	return channelIds, nil
}

func FetchOldIdByAccountId(accountId int64) (string, error) {

	a := NewAccount()
	var data []string
	q := &bongo.Query{
		Selector: map[string]interface{}{
			"id": accountId,
		},
		Pluck:      "old_id",
		Pagination: *bongo.NewPagination(1, 0),
	}
	err := a.Some(&data, q)
	if err != nil {
		return "", err
	}

	if len(data) == 0 {
		return "", nil
	}

	return data[0], nil
}

func FetchOldIdsByAccountIds(accountIds []int64) ([]string, error) {
	var oldIds []string
	if len(accountIds) == 0 {
		return make([]string, 0), nil
	}

	res := bongo.B.DB.
		Table(Account{}.TableName()).
		Where("id IN (?)", accountIds).
		Pluck("old_id", &oldIds)

	if err := bongo.CheckErr(res); err != nil {
		return nil, err
	}

	if len(oldIds) == 0 {
		return make([]string, 0), nil
	}

	return oldIds, err
}
<commit_msg>social: return nil istead of err at the end of the function<commit_after>package models

import (
	"errors"
	"fmt"

	"github.com/jinzhu/gorm"
	"github.com/koding/bongo"
)

type Account struct {
	// unique id of the account
	Id int64 `json:"id,string"`

	// old id of the account, which is originally
	// perisisted in mongo
	// mongo ids has 24 char
	OldId string `json:"oldId"      sql:"NOT NULL;UNIQUE;TYPE:VARCHAR(24);"`
}

func NewAccount() *Account {
	return &Account{}
}

func (a Account) GetId() int64 {
	return a.Id
}

func (a Account) TableName() string {
	return "api.account"
}

func (a *Account) One(q *bongo.Query) error {
	return bongo.B.One(a, a, q)
}

func (a *Account) ById(id int64) error {
	return bongo.B.ById(a, id)
}

func (a *Account) FetchOrCreate() error {
	if a.OldId == "" {
		return errors.New("old id is not set")
	}

	selector := map[string]interface{}{
		"old_id": a.OldId,
	}

	err := a.One(bongo.NewQS(selector))
	// if we dont get any error
	// it means we found the record in our db
	if err == nil {
		return nil
	}

	// first check if the err is not found err
	if err == gorm.RecordNotFound {
		if err := a.Create(); err != nil {
			return err
		}
		return nil
	}

	return err
}

func (a *Account) Create() error {
	if a.OldId == "" {
		return errors.New("old id is not set")
	}

	return bongo.B.Create(a)
}

func (a *Account) Some(data interface{}, q *bongo.Query) error {
	return bongo.B.Some(a, data, q)
}

func (a *Account) FetchChannels(q *Query) ([]Channel, error) {
	cp := NewChannelParticipant()
	// fetch channel ids
	cids, err := cp.FetchParticipatedChannelIds(a, q)
	if err != nil {
		return nil, err
	}

	// fetch channels by their ids
	channels, err := NewChannel().FetchByIds(cids)
	if err != nil {
		return nil, err
	}

	return channels, nil
}

func (a *Account) Follow(targetId int64) (*ChannelParticipant, error) {
	c, err := a.FetchChannel(Channel_TYPE_FOLLOWERS)
	if err == nil {
		return c.AddParticipant(targetId)
	}

	if err == gorm.RecordNotFound {
		c, err := a.CreateFollowingFeedChannel()
		if err != nil {
			return nil, err
		}
		return c.AddParticipant(targetId)
	}

	return nil, err
}

func (a *Account) Unfollow(targetId int64) (*Account, error) {
	c, err := a.FetchChannel(Channel_TYPE_FOLLOWERS)
	if err != nil {
		return nil, err
	}

	return a, c.RemoveParticipant(targetId)
}

func (a *Account) FetchFollowerIds() ([]int64, error) {
	followerIds := make([]int64, 0)
	if a.Id == 0 {
		return nil, errors.New(
			"Account id is not set for FetchFollowerChannelIds function ",
		)
	}

	c, err := a.FetchChannel(Channel_TYPE_FOLLOWERS)
	if err != nil {
		return followerIds, err
	}

	participants, err := c.FetchParticipantIds()
	if err != nil {
		return followerIds, err
	}

	return participants, nil
}

func (a *Account) FetchChannel(channelType string) (*Channel, error) {
	if a.Id == 0 {
		return nil, errors.New("Account id is not set")
	}

	c := NewChannel()
	selector := map[string]interface{}{
		"creator_id":    a.Id,
		"type_constant": channelType,
	}

	if err := c.One(bongo.NewQS(selector)); err != nil {
		return nil, err
	}

	return c, nil
}

func (a *Account) CreateFollowingFeedChannel() (*Channel, error) {
	if a.Id == 0 {
		return nil, errors.New("Account id is not set")
	}

	c := NewChannel()
	c.CreatorId = a.Id
	c.Name = fmt.Sprintf("%d-FollowingFeedChannel", a.Id)
	c.GroupName = Channel_KODING_NAME
	c.Purpose = "Following Feed for Me"
	c.TypeConstant = Channel_TYPE_FOLLOWERS
	if err := c.Create(); err != nil {
		return nil, err
	}

	return c, nil
}

func (a *Account) FetchFollowerChannelIds() ([]int64, error) {

	followerIds, err := a.FetchFollowerIds()
	if err != nil {
		return nil, err
	}

	cp := NewChannelParticipant()
	var channelIds []int64
	res := bongo.B.DB.
		Table(cp.TableName()).
		Where(
		"creator_id IN (?) and type_constant = ?",
		followerIds,
		Channel_TYPE_FOLLOWINGFEED,
	).Find(&channelIds)

	if err := bongo.CheckErr(res); err != nil {
		return nil, err
	}

	return channelIds, nil
}

func FetchOldIdByAccountId(accountId int64) (string, error) {

	a := NewAccount()
	var data []string
	q := &bongo.Query{
		Selector: map[string]interface{}{
			"id": accountId,
		},
		Pluck:      "old_id",
		Pagination: *bongo.NewPagination(1, 0),
	}
	err := a.Some(&data, q)
	if err != nil {
		return "", err
	}

	if len(data) == 0 {
		return "", nil
	}

	return data[0], nil
}

func FetchOldIdsByAccountIds(accountIds []int64) ([]string, error) {
	var oldIds []string
	if len(accountIds) == 0 {
		return make([]string, 0), nil
	}

	res := bongo.B.DB.
		Table(Account{}.TableName()).
		Where("id IN (?)", accountIds).
		Pluck("old_id", &oldIds)

	if err := bongo.CheckErr(res); err != nil {
		return nil, err
	}

	if len(oldIds) == 0 {
		return make([]string, 0), nil
	}

	return oldIds, nil
}
<|endoftext|>


<commit_before>package models

import (
	"errors"
	"fmt"
	"strings"
	"time"

	"github.com/jinzhu/gorm"
	"github.com/koding/bongo"
)

type Channel struct {
	// unique identifier of the channel
	Id int64 `json:"id,string"`

	// Name of the channel
	Name string `json:"name"                         sql:"NOT NULL;TYPE:VARCHAR(200);"`

	// Creator of the channel
	CreatorId int64 `json:"creatorId,string"         sql:"NOT NULL"`

	// Name of the group which channel is belong to
	GroupName string `json:"groupName"               sql:"NOT NULL;TYPE:VARCHAR(200);"`

	// Purpose of the channel
	Purpose string `json:"purpose"`

	// Secret key of the channel for event propagation purposes
	// we can put this key into another table?
	SecretKey string `json:"-"`

	// Type of the channel
	TypeConstant string `json:"typeConstant"         sql:"NOT NULL;TYPE:VARCHAR(100);"`

	// Privacy constant of the channel
	PrivacyConstant string `json:"privacyConstant"   sql:"NOT NULL;TYPE:VARCHAR(100);"`

	// Creation date of the channel
	CreatedAt time.Time `json:"createdAt"            sql:"NOT NULL"`

	// Modification date of the channel
	UpdatedAt time.Time `json:"updatedAt"            sql:"NOT NULL"`

	// Deletion date of the channel
	DeletedAt time.Time `json:"deletedAt"`
}

// to-do check for allowed channels
const (
	// TYPES
	Channel_TYPE_GROUP           = "group"
	Channel_TYPE_TOPIC           = "topic"
	Channel_TYPE_FOLLOWINGFEED   = "followingfeed"
	Channel_TYPE_FOLLOWERS       = "followers"
	Channel_TYPE_CHAT            = "chat"
	Channel_TYPE_PINNED_ACTIVITY = "pinnedactivity"
	Channel_TYPE_PRIVATE_MESSAGE = "privatemessage"
	Channel_TYPE_DEFAULT         = "default"
	// Privacy
	Channel_PRIVACY_PUBLIC  = "public"
	Channel_PRIVACY_PRIVATE = "private"
	// Koding Group Name
	Channel_KODING_NAME = "koding"
)

func NewChannel() *Channel {
	return &Channel{
		Name:            "Channel" + RandomName(),
		CreatorId:       0,
		GroupName:       Channel_KODING_NAME,
		Purpose:         "",
		SecretKey:       "",
		TypeConstant:    Channel_TYPE_DEFAULT,
		PrivacyConstant: Channel_PRIVACY_PRIVATE,
	}
}

func NewPrivateMessageChannel(creatorId int64, groupName string) *Channel {
	c := NewChannel()
	c.GroupName = groupName
	c.CreatorId = creatorId
	c.Name = RandomName()
	c.TypeConstant = Channel_TYPE_PRIVATE_MESSAGE
	c.PrivacyConstant = Channel_PRIVACY_PRIVATE
	c.Purpose = ""
	return c
}

func (c *Channel) BeforeCreate() {
	c.CreatedAt = time.Now().UTC()
	c.UpdatedAt = time.Now().UTC()
	c.DeletedAt = ZeroDate()
}

func (c *Channel) BeforeUpdate() {
	c.UpdatedAt = time.Now()
}

func (c Channel) GetId() int64 {
	return c.Id
}

func (c Channel) TableName() string {
	return "api.channel"
}

func (c *Channel) AfterCreate() {
	bongo.B.AfterCreate(c)
}

func (c *Channel) AfterUpdate() {
	bongo.B.AfterUpdate(c)
}

func (c Channel) AfterDelete() {
	bongo.B.AfterDelete(c)
}

func (c *Channel) Update() error {
	if c.Name == "" || c.GroupName == "" {
		return fmt.Errorf("Validation failed %s - %s", c.Name, c.GroupName)
	}

	return bongo.B.Update(c)
}

func (c *Channel) Create() error {
	if c.Name == "" || c.GroupName == "" || c.TypeConstant == "" {
		return fmt.Errorf("Validation failed %s - %s -%s", c.Name, c.GroupName, c.TypeConstant)
	}

	// golang returns -1 if item not in the string
	if strings.Index(c.Name, " ") > -1 {
		return fmt.Errorf("Channel name %q has empty space in it", c.Name)
	}

	if c.TypeConstant == Channel_TYPE_GROUP ||
		c.TypeConstant == Channel_TYPE_FOLLOWERS /* we can add more types here */ {

		var selector map[string]interface{}
		switch c.TypeConstant {
		case Channel_TYPE_GROUP:
			selector = map[string]interface{}{
				"group_name":    c.GroupName,
				"type_constant": c.TypeConstant,
			}
		case Channel_TYPE_FOLLOWERS:
			selector = map[string]interface{}{
				"creator_id":    c.CreatorId,
				"type_constant": c.TypeConstant,
			}
		}

		// if err is nil
		// it means we already have that channel
		err := c.One(bongo.NewQS(selector))
		if err == nil {
			return nil
			// return fmt.Errorf("%s typed channel is already created before for %s group", c.TypeConstant, c.GroupName)
		}

		if err != gorm.RecordNotFound {
			return err
		}

	}

	return bongo.B.Create(c)
}

func (c *Channel) Delete() error {
	return bongo.B.Delete(c)
}

func (c *Channel) ById(id int64) error {
	return bongo.B.ById(c, id)
}

func (c *Channel) One(q *bongo.Query) error {
	return bongo.B.One(c, c, q)
}

func (c *Channel) Some(data interface{}, q *bongo.Query) error {
	return bongo.B.Some(c, data, q)
}

func (c *Channel) FetchByIds(ids []int64) ([]Channel, error) {
	var channels []Channel

	if len(ids) == 0 {
		return channels, nil
	}

	if err := bongo.B.FetchByIds(c, &channels, ids); err != nil {
		return nil, err
	}
	return channels, nil
}

func (c *Channel) AddParticipant(participantId int64) (*ChannelParticipant, error) {
	if c.Id == 0 {
		return nil, errors.New("Channel Id is not set")
	}

	cp := NewChannelParticipant()
	cp.ChannelId = c.Id
	cp.AccountId = participantId

	err := cp.FetchParticipant()
	if err != nil && err != gorm.RecordNotFound {
		return nil, err
	}

	// if we have this record in DB
	if cp.Id != 0 {
		// if status is not active
		if cp.StatusConstant == ChannelParticipant_STATUS_ACTIVE {
			return nil, errors.New(fmt.Sprintf("Account %d is already a participant of channel %d", cp.AccountId, cp.ChannelId))
		}
		cp.StatusConstant = ChannelParticipant_STATUS_ACTIVE
		if err := cp.Update(); err != nil {
			return nil, err
		}
		return cp, nil
	}

	cp.StatusConstant = ChannelParticipant_STATUS_ACTIVE

	if err := cp.Create(); err != nil {
		return nil, err
	}

	return cp, nil
}

func (c *Channel) RemoveParticipant(participantId int64) error {
	if c.Id == 0 {
		return errors.New("Channel Id is not set")
	}

	cp := NewChannelParticipant()
	cp.ChannelId = c.Id
	cp.AccountId = participantId

	err := cp.FetchParticipant()
	// if user is not in this channel, do nothing
	if err == gorm.RecordNotFound {
		return nil
	}

	if err != nil {
		return err
	}

	if cp.StatusConstant == ChannelParticipant_STATUS_LEFT {
		return nil
	}

	cp.StatusConstant = ChannelParticipant_STATUS_LEFT
	if err := cp.Update(); err != nil {
		return err
	}

	return nil
}

func (c *Channel) FetchParticipantIds() ([]int64, error) {
	var participantIds []int64

	if c.Id == 0 {
		return participantIds, errors.New("Channel Id is not set")
	}

	query := &bongo.Query{
		Selector: map[string]interface{}{
			"channel_id":      c.Id,
			"status_constant": ChannelParticipant_STATUS_ACTIVE,
		},
		Pluck: "account_id",
	}

	cp := NewChannelParticipant()
	err := cp.Some(&participantIds, query)
	if err != nil {
		return nil, err
	}

	return participantIds, nil
}

func (c *Channel) AddMessage(messageId int64) (*ChannelMessageList, error) {
	cml, err := c.FetchMessageList(messageId)
	if err == nil {
		return nil, errors.New("Message is already in the channel")
	}

	// silence record not found err
	if err != gorm.RecordNotFound {
		return nil, err
	}

	cml.ChannelId = c.Id
	cml.MessageId = messageId

	if err := cml.Create(); err != nil {
		return nil, err
	}

	return cml, nil
}

func (c *Channel) RemoveMessage(messageId int64) (*ChannelMessageList, error) {
	cml, err := c.FetchMessageList(messageId)
	if err != nil {
		return nil, err
	}

	if err := cml.Delete(); err != nil {
		return nil, err
	}

	return cml, nil
}

func (c *Channel) FetchMessageList(messageId int64) (*ChannelMessageList, error) {
	if c.Id == 0 {
		return nil, errors.New("Channel Id is not set")
	}

	cml := NewChannelMessageList()
	selector := map[string]interface{}{
		"channel_id": c.Id,
		"message_id": messageId,
	}

	return cml, cml.One(bongo.NewQS(selector))
}

func (c *Channel) FetchChannelIdByNameAndGroupName(name, groupName string) (int64, error) {
	query := &bongo.Query{
		Selector: map[string]interface{}{
			"name":       name,
			"group_name": groupName,
		},
		Pagination: *bongo.NewPagination(1, 0),
		Pluck:      "id",
	}
	var ids []int64
	if err := c.Some(&ids, query); err != nil {
		return 0, err
	}

	if ids == nil {
		return 0, gorm.RecordNotFound
	}

	if len(ids) == 0 {
		return 0, gorm.RecordNotFound
	}

	return ids[0], nil
}

func (c *Channel) Search(q *Query) ([]Channel, error) {

	if q.GroupName == "" {
		return nil, fmt.Errorf("Query doesnt have any Group info %+v", q)
	}

	var channels []Channel

	query := bongo.B.DB.Table(c.TableName()).Limit(q.Limit)

	query = query.Where("type_constant = ?", q.Type)
	query = query.Where("privacy_constant = ?", Channel_PRIVACY_PUBLIC)
	query = query.Where("group_name = ?", q.GroupName)
	query = query.Where("name like ?", q.Name+"%")

	if err := query.Find(&channels).Error; err != nil {
		return nil, err
	}

	if channels == nil {
		return make([]Channel, 0), nil
	}

	return channels, nil
}

func (c *Channel) ByName(q *Query) (Channel, error) {
	fmt.Println("-------- FIX THIS PART ------")
	fmt.Println("TODO - check permissions here")
	fmt.Println("-------- FIX THIS PART ------")
	var channel Channel

	if q.GroupName == "" {
		return channel, fmt.Errorf("Query doesnt have any Group info %+v", q)
	}

	query := bongo.B.DB.Table(c.TableName()).Limit(q.Limit)

	query = query.Where("type_constant = ?", q.Type)
	query = query.Where("group_name = ?", q.GroupName)
	query = query.Where("name = ?", q.Name)

	return channel, query.Find(&channel).Error
}

func (c *Channel) List(q *Query) ([]Channel, error) {

	if q.GroupName == "" {
		return nil, fmt.Errorf("Query doesnt have any Group info %+v", q)
	}

	var channels []Channel

	query := &bongo.Query{
		Selector: map[string]interface{}{
			"group_name": q.GroupName,
		},
		Pagination: *bongo.NewPagination(q.Limit, q.Skip),
	}

	if q.Type != "" {
		query.Selector["type_constant"] = q.Type
	}

	err := c.Some(&channels, query)
	if err != nil {
		return nil, err
	}

	if channels == nil {
		return make([]Channel, 0), nil
	}

	return channels, nil
}

func (c *Channel) FetchLastMessage() (*ChannelMessage, error) {
	if c.Id == 0 {
		return nil, errors.New("Channel Id is not set")
	}

	cml := NewChannelMessageList()
	query := &bongo.Query{
		Selector: map[string]interface{}{
			"channel_id": c.Id,
		},
		Sort: map[string]string{
			"added_at": "DESC",
		},
		Pagination: *bongo.NewPagination(1, 0),
		Pluck:      "message_id",
	}

	var messageIds []int64
	err := cml.Some(&messageIds, query)
	if err != nil {
		return nil, err
	}

	if messageIds == nil || len(messageIds) == 0 {
		return nil, nil
	}

	cm := NewChannelMessage()
	if err := cm.ById(messageIds[0]); err != nil {
		return nil, err
	}

	return cm, nil
}

func (c *Channel) FetchPinnedActivityChannel(accountId int64, groupName string) error {
	query := &bongo.Query{
		Selector: map[string]interface{}{
			"creator_id":    accountId,
			"group_name":    groupName,
			"type_constant": Channel_TYPE_PINNED_ACTIVITY,
		},
	}

	return c.One(query)
}
<commit_msg>social: gorm returns error when slice is empty<commit_after>package models

import (
	"errors"
	"fmt"
	"strings"
	"time"

	"github.com/jinzhu/gorm"
	"github.com/koding/bongo"
)

type Channel struct {
	// unique identifier of the channel
	Id int64 `json:"id,string"`

	// Name of the channel
	Name string `json:"name"                         sql:"NOT NULL;TYPE:VARCHAR(200);"`

	// Creator of the channel
	CreatorId int64 `json:"creatorId,string"         sql:"NOT NULL"`

	// Name of the group which channel is belong to
	GroupName string `json:"groupName"               sql:"NOT NULL;TYPE:VARCHAR(200);"`

	// Purpose of the channel
	Purpose string `json:"purpose"`

	// Secret key of the channel for event propagation purposes
	// we can put this key into another table?
	SecretKey string `json:"-"`

	// Type of the channel
	TypeConstant string `json:"typeConstant"         sql:"NOT NULL;TYPE:VARCHAR(100);"`

	// Privacy constant of the channel
	PrivacyConstant string `json:"privacyConstant"   sql:"NOT NULL;TYPE:VARCHAR(100);"`

	// Creation date of the channel
	CreatedAt time.Time `json:"createdAt"            sql:"NOT NULL"`

	// Modification date of the channel
	UpdatedAt time.Time `json:"updatedAt"            sql:"NOT NULL"`

	// Deletion date of the channel
	DeletedAt time.Time `json:"deletedAt"`
}

// to-do check for allowed channels
const (
	// TYPES
	Channel_TYPE_GROUP           = "group"
	Channel_TYPE_TOPIC           = "topic"
	Channel_TYPE_FOLLOWINGFEED   = "followingfeed"
	Channel_TYPE_FOLLOWERS       = "followers"
	Channel_TYPE_CHAT            = "chat"
	Channel_TYPE_PINNED_ACTIVITY = "pinnedactivity"
	Channel_TYPE_PRIVATE_MESSAGE = "privatemessage"
	Channel_TYPE_DEFAULT         = "default"
	// Privacy
	Channel_PRIVACY_PUBLIC  = "public"
	Channel_PRIVACY_PRIVATE = "private"
	// Koding Group Name
	Channel_KODING_NAME = "koding"
)

func NewChannel() *Channel {
	return &Channel{
		Name:            "Channel" + RandomName(),
		CreatorId:       0,
		GroupName:       Channel_KODING_NAME,
		Purpose:         "",
		SecretKey:       "",
		TypeConstant:    Channel_TYPE_DEFAULT,
		PrivacyConstant: Channel_PRIVACY_PRIVATE,
	}
}

func NewPrivateMessageChannel(creatorId int64, groupName string) *Channel {
	c := NewChannel()
	c.GroupName = groupName
	c.CreatorId = creatorId
	c.Name = RandomName()
	c.TypeConstant = Channel_TYPE_PRIVATE_MESSAGE
	c.PrivacyConstant = Channel_PRIVACY_PRIVATE
	c.Purpose = ""
	return c
}

func (c *Channel) BeforeCreate() {
	c.CreatedAt = time.Now().UTC()
	c.UpdatedAt = time.Now().UTC()
	c.DeletedAt = ZeroDate()
}

func (c *Channel) BeforeUpdate() {
	c.UpdatedAt = time.Now()
}

func (c Channel) GetId() int64 {
	return c.Id
}

func (c Channel) TableName() string {
	return "api.channel"
}

func (c *Channel) AfterCreate() {
	bongo.B.AfterCreate(c)
}

func (c *Channel) AfterUpdate() {
	bongo.B.AfterUpdate(c)
}

func (c Channel) AfterDelete() {
	bongo.B.AfterDelete(c)
}

func (c *Channel) Update() error {
	if c.Name == "" || c.GroupName == "" {
		return fmt.Errorf("Validation failed %s - %s", c.Name, c.GroupName)
	}

	return bongo.B.Update(c)
}

func (c *Channel) Create() error {
	if c.Name == "" || c.GroupName == "" || c.TypeConstant == "" {
		return fmt.Errorf("Validation failed %s - %s -%s", c.Name, c.GroupName, c.TypeConstant)
	}

	// golang returns -1 if item not in the string
	if strings.Index(c.Name, " ") > -1 {
		return fmt.Errorf("Channel name %q has empty space in it", c.Name)
	}

	if c.TypeConstant == Channel_TYPE_GROUP ||
		c.TypeConstant == Channel_TYPE_FOLLOWERS /* we can add more types here */ {

		var selector map[string]interface{}
		switch c.TypeConstant {
		case Channel_TYPE_GROUP:
			selector = map[string]interface{}{
				"group_name":    c.GroupName,
				"type_constant": c.TypeConstant,
			}
		case Channel_TYPE_FOLLOWERS:
			selector = map[string]interface{}{
				"creator_id":    c.CreatorId,
				"type_constant": c.TypeConstant,
			}
		}

		// if err is nil
		// it means we already have that channel
		err := c.One(bongo.NewQS(selector))
		if err == nil {
			return nil
			// return fmt.Errorf("%s typed channel is already created before for %s group", c.TypeConstant, c.GroupName)
		}

		if err != gorm.RecordNotFound {
			return err
		}

	}

	return bongo.B.Create(c)
}

func (c *Channel) Delete() error {
	return bongo.B.Delete(c)
}

func (c *Channel) ById(id int64) error {
	return bongo.B.ById(c, id)
}

func (c *Channel) One(q *bongo.Query) error {
	return bongo.B.One(c, c, q)
}

func (c *Channel) Some(data interface{}, q *bongo.Query) error {
	return bongo.B.Some(c, data, q)
}

func (c *Channel) FetchByIds(ids []int64) ([]Channel, error) {
	var channels []Channel

	if len(ids) == 0 {
		return channels, nil
	}

	if err := bongo.B.FetchByIds(c, &channels, ids); err != nil {
		return nil, err
	}
	return channels, nil
}

func (c *Channel) AddParticipant(participantId int64) (*ChannelParticipant, error) {
	if c.Id == 0 {
		return nil, errors.New("Channel Id is not set")
	}

	cp := NewChannelParticipant()
	cp.ChannelId = c.Id
	cp.AccountId = participantId

	err := cp.FetchParticipant()
	if err != nil && err != gorm.RecordNotFound {
		return nil, err
	}

	// if we have this record in DB
	if cp.Id != 0 {
		// if status is not active
		if cp.StatusConstant == ChannelParticipant_STATUS_ACTIVE {
			return nil, errors.New(fmt.Sprintf("Account %d is already a participant of channel %d", cp.AccountId, cp.ChannelId))
		}
		cp.StatusConstant = ChannelParticipant_STATUS_ACTIVE
		if err := cp.Update(); err != nil {
			return nil, err
		}
		return cp, nil
	}

	cp.StatusConstant = ChannelParticipant_STATUS_ACTIVE

	if err := cp.Create(); err != nil {
		return nil, err
	}

	return cp, nil
}

func (c *Channel) RemoveParticipant(participantId int64) error {
	if c.Id == 0 {
		return errors.New("Channel Id is not set")
	}

	cp := NewChannelParticipant()
	cp.ChannelId = c.Id
	cp.AccountId = participantId

	err := cp.FetchParticipant()
	// if user is not in this channel, do nothing
	if err == gorm.RecordNotFound {
		return nil
	}

	if err != nil {
		return err
	}

	if cp.StatusConstant == ChannelParticipant_STATUS_LEFT {
		return nil
	}

	cp.StatusConstant = ChannelParticipant_STATUS_LEFT
	if err := cp.Update(); err != nil {
		return err
	}

	return nil
}

func (c *Channel) FetchParticipantIds() ([]int64, error) {
	var participantIds []int64

	if c.Id == 0 {
		return participantIds, errors.New("Channel Id is not set")
	}

	query := &bongo.Query{
		Selector: map[string]interface{}{
			"channel_id":      c.Id,
			"status_constant": ChannelParticipant_STATUS_ACTIVE,
		},
		Pluck: "account_id",
	}

	cp := NewChannelParticipant()
	err := cp.Some(&participantIds, query)
	if err != nil {
		return nil, err
	}

	return participantIds, nil
}

func (c *Channel) AddMessage(messageId int64) (*ChannelMessageList, error) {
	cml, err := c.FetchMessageList(messageId)
	if err == nil {
		return nil, errors.New("Message is already in the channel")
	}

	// silence record not found err
	if err != gorm.RecordNotFound {
		return nil, err
	}

	cml.ChannelId = c.Id
	cml.MessageId = messageId

	if err := cml.Create(); err != nil {
		return nil, err
	}

	return cml, nil
}

func (c *Channel) RemoveMessage(messageId int64) (*ChannelMessageList, error) {
	cml, err := c.FetchMessageList(messageId)
	if err != nil {
		return nil, err
	}

	if err := cml.Delete(); err != nil {
		return nil, err
	}

	return cml, nil
}

func (c *Channel) FetchMessageList(messageId int64) (*ChannelMessageList, error) {
	if c.Id == 0 {
		return nil, errors.New("Channel Id is not set")
	}

	cml := NewChannelMessageList()
	selector := map[string]interface{}{
		"channel_id": c.Id,
		"message_id": messageId,
	}

	return cml, cml.One(bongo.NewQS(selector))
}

func (c *Channel) FetchChannelIdByNameAndGroupName(name, groupName string) (int64, error) {
	query := &bongo.Query{
		Selector: map[string]interface{}{
			"name":       name,
			"group_name": groupName,
		},
		Pagination: *bongo.NewPagination(1, 0),
		Pluck:      "id",
	}
	var ids []int64
	if err := c.Some(&ids, query); err != nil {
		return 0, err
	}

	if ids == nil {
		return 0, gorm.RecordNotFound
	}

	if len(ids) == 0 {
		return 0, gorm.RecordNotFound
	}

	return ids[0], nil
}

func (c *Channel) Search(q *Query) ([]Channel, error) {

	if q.GroupName == "" {
		return nil, fmt.Errorf("Query doesnt have any Group info %+v", q)
	}

	var channels []Channel

	query := bongo.B.DB.Table(c.TableName()).Limit(q.Limit)

	query = query.Where("type_constant = ?", q.Type)
	query = query.Where("privacy_constant = ?", Channel_PRIVACY_PUBLIC)
	query = query.Where("group_name = ?", q.GroupName)
	query = query.Where("name like ?", q.Name+"%")

	if err := query.Find(&channels).Error; err != gorm.RecordNotFound && err != nil {
		return nil, err
	}

	if channels == nil {
		return make([]Channel, 0), nil
	}

	return channels, nil
}

func (c *Channel) ByName(q *Query) (Channel, error) {
	fmt.Println("-------- FIX THIS PART ------")
	fmt.Println("TODO - check permissions here")
	fmt.Println("-------- FIX THIS PART ------")
	var channel Channel

	if q.GroupName == "" {
		return channel, fmt.Errorf("Query doesnt have any Group info %+v", q)
	}

	query := bongo.B.DB.Table(c.TableName()).Limit(q.Limit)

	query = query.Where("type_constant = ?", q.Type)
	query = query.Where("group_name = ?", q.GroupName)
	query = query.Where("name = ?", q.Name)

	return channel, query.Find(&channel).Error
}

func (c *Channel) List(q *Query) ([]Channel, error) {

	if q.GroupName == "" {
		return nil, fmt.Errorf("Query doesnt have any Group info %+v", q)
	}

	var channels []Channel

	query := &bongo.Query{
		Selector: map[string]interface{}{
			"group_name": q.GroupName,
		},
		Pagination: *bongo.NewPagination(q.Limit, q.Skip),
	}

	if q.Type != "" {
		query.Selector["type_constant"] = q.Type
	}

	err := c.Some(&channels, query)
	if err != nil {
		return nil, err
	}

	if channels == nil {
		return make([]Channel, 0), nil
	}

	return channels, nil
}

func (c *Channel) FetchLastMessage() (*ChannelMessage, error) {
	if c.Id == 0 {
		return nil, errors.New("Channel Id is not set")
	}

	cml := NewChannelMessageList()
	query := &bongo.Query{
		Selector: map[string]interface{}{
			"channel_id": c.Id,
		},
		Sort: map[string]string{
			"added_at": "DESC",
		},
		Pagination: *bongo.NewPagination(1, 0),
		Pluck:      "message_id",
	}

	var messageIds []int64
	err := cml.Some(&messageIds, query)
	if err != nil {
		return nil, err
	}

	if messageIds == nil || len(messageIds) == 0 {
		return nil, nil
	}

	cm := NewChannelMessage()
	if err := cm.ById(messageIds[0]); err != nil {
		return nil, err
	}

	return cm, nil
}

func (c *Channel) FetchPinnedActivityChannel(accountId int64, groupName string) error {
	query := &bongo.Query{
		Selector: map[string]interface{}{
			"creator_id":    accountId,
			"group_name":    groupName,
			"type_constant": Channel_TYPE_PINNED_ACTIVITY,
		},
	}

	return c.One(query)
}
<|endoftext|>


<commit_before>package main

import (
	"./dns"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"math/rand"
	"os"
	"strings"
	"sync"
)

type WorkerInput struct {
	Name string
	Type uint16
}

type WorkerOutput struct {
	Name   string
	Error  error
	Answer []dns.RR
}

type WorkerPool struct {
	Input  chan WorkerInput
	Output chan WorkerOutput
	wg     sync.WaitGroup
}

type DNSError struct {
	Rcode int
}

var dnsConf *dns.ClientConfig
var workerPool *WorkerPool

func newWorkerPool(workers int) *WorkerPool {
	wp := &WorkerPool{}
	wp.Input = make(chan WorkerInput, 100)
	wp.Output = make(chan WorkerOutput, 100)
	for i := 0; i < workers; i++ {
		wp.wg.Add(1)
		go wp.worker()
	}

	return wp
}

func (wp *WorkerPool) Shutdown() {
	close(wp.Input)
	wp.wg.Wait()
	close(wp.Output)
}

func (wp *WorkerPool) worker() {
	c := new(dns.Client)

	for in, ok := <-wp.Input; ok; in, ok = <-wp.Input {
		m := new(dns.Msg)
		m.SetQuestion(in.Name, in.Type)
		m.MsgHdr.RecursionDesired = true

		var r *dns.Msg
		for {
			srv := dnsConf.Servers[rand.Intn(len(dnsConf.Servers))]
			var err error
			r, err = c.Exchange(m, srv+":"+dnsConf.Port)

			if err == nil {
				break
			}
		}

		if r.Rcode == dns.RcodeSuccess {
			wp.Output <- WorkerOutput{Name: in.Name, Answer: r.Answer}
		} else {
			wp.Output <- WorkerOutput{Name: in.Name, Error: &DNSError{Rcode: r.Rcode}}
		}
	}
	wp.wg.Done()
}

func (err *DNSError) Error() string {
	return dns.Rcode_str[err.Rcode]
}

func loadConfigFromServersFile(fn string) error {
	c := new(dns.ClientConfig)
	c.Search = make([]string, 0)
	c.Port = "53"
	c.Ndots = 1
	c.Timeout = 5
	c.Attempts = 2

	b, err := ioutil.ReadFile(fn)
	if err != nil {
		return err
	}

	c.Servers = strings.Split(string(b), "\n")
	dnsConf = c
	return nil
}

func loadConfigFromSystem() error {
	c, err := dns.ClientConfigFromFile("/etc/resolv.conf")
	if err == nil {
		dnsConf = c
	}
	return err
}

func usage(w io.Writer) {
	fmt.Fprintln(w, "Usage: dnsmop COMMAND")
	fmt.Fprintln(w, "")
	fmt.Fprintln(w, "Commands:")
	fmt.Fprintln(w, "help                  print this help")
	fmt.Fprintln(w, "zone example.com      scan a zone for subdomains using a word list")
	fmt.Fprintln(w, "subnet 1.2.3.4/24     map a subnet with reverse DNS queries")
	fmt.Fprintln(w, "wildcard example.com  test a domain for a wildcard record")
	fmt.Fprintln(w, "")
}

var flags *flag.FlagSet

func main() {
	if len(os.Args) < 2 {
		usage(os.Stderr)
		os.Exit(1)
	}

	cmd := os.Args[1]
	flags = flag.NewFlagSet(cmd, flag.ExitOnError)
	var srvFn string
	flags.StringVar(&srvFn, "srv-file", "", "File with one DNS server per line")

	var wordsFn string
	switch cmd {
	case "help":
		usage(os.Stdout)
		os.Exit(0)
	case "zone":
		flags.StringVar(&wordsFn, "words-file", "/usr/share/dict/words", "Word list file")
	case "subnet":
	case "wildcard":
	default:
		usage(os.Stderr)
		os.Exit(1)
	}

	flags.Parse(os.Args[2:])

	var err error
	if len(srvFn) > 0 {
		err = loadConfigFromServersFile(srvFn)
	} else {
		err = loadConfigFromSystem()
	}
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return
	}

	workerPool = newWorkerPool(10)

	a := flags.Arg(0)
	if len(a) == 0 {
		usage(os.Stderr)
		os.Exit(1)
	}

	switch cmd {
	case "zone":
		zoneCmd(a, wordsFn)
	case "subnet":
		subnetCmd(a)
	case "wildcard":
		wildcardCmd(a)
	}
}
<commit_msg>Make flagset a local variable<commit_after>package main

import (
	"./dns"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"math/rand"
	"os"
	"strings"
	"sync"
)

type WorkerInput struct {
	Name string
	Type uint16
}

type WorkerOutput struct {
	Name   string
	Error  error
	Answer []dns.RR
}

type WorkerPool struct {
	Input  chan WorkerInput
	Output chan WorkerOutput
	wg     sync.WaitGroup
}

type DNSError struct {
	Rcode int
}

var dnsConf *dns.ClientConfig
var workerPool *WorkerPool

func newWorkerPool(workers int) *WorkerPool {
	wp := &WorkerPool{}
	wp.Input = make(chan WorkerInput, 100)
	wp.Output = make(chan WorkerOutput, 100)
	for i := 0; i < workers; i++ {
		wp.wg.Add(1)
		go wp.worker()
	}

	return wp
}

func (wp *WorkerPool) Shutdown() {
	close(wp.Input)
	wp.wg.Wait()
	close(wp.Output)
}

func (wp *WorkerPool) worker() {
	c := new(dns.Client)

	for in, ok := <-wp.Input; ok; in, ok = <-wp.Input {
		m := new(dns.Msg)
		m.SetQuestion(in.Name, in.Type)
		m.MsgHdr.RecursionDesired = true

		var r *dns.Msg
		for {
			srv := dnsConf.Servers[rand.Intn(len(dnsConf.Servers))]
			var err error
			r, err = c.Exchange(m, srv+":"+dnsConf.Port)

			if err == nil {
				break
			}
		}

		if r.Rcode == dns.RcodeSuccess {
			wp.Output <- WorkerOutput{Name: in.Name, Answer: r.Answer}
		} else {
			wp.Output <- WorkerOutput{Name: in.Name, Error: &DNSError{Rcode: r.Rcode}}
		}
	}
	wp.wg.Done()
}

func (err *DNSError) Error() string {
	return dns.Rcode_str[err.Rcode]
}

func loadConfigFromServersFile(fn string) error {
	c := new(dns.ClientConfig)
	c.Search = make([]string, 0)
	c.Port = "53"
	c.Ndots = 1
	c.Timeout = 5
	c.Attempts = 2

	b, err := ioutil.ReadFile(fn)
	if err != nil {
		return err
	}

	c.Servers = strings.Split(string(b), "\n")
	dnsConf = c
	return nil
}

func loadConfigFromSystem() error {
	c, err := dns.ClientConfigFromFile("/etc/resolv.conf")
	if err == nil {
		dnsConf = c
	}
	return err
}

func usage(w io.Writer) {
	fmt.Fprintln(w, "Usage: dnsmop COMMAND")
	fmt.Fprintln(w, "")
	fmt.Fprintln(w, "Commands:")
	fmt.Fprintln(w, "help                  print this help")
	fmt.Fprintln(w, "zone example.com      scan a zone for subdomains using a word list")
	fmt.Fprintln(w, "subnet 1.2.3.4/24     map a subnet with reverse DNS queries")
	fmt.Fprintln(w, "wildcard example.com  test a domain for a wildcard record")
	fmt.Fprintln(w, "")
}

func main() {
	if len(os.Args) < 2 {
		usage(os.Stderr)
		os.Exit(1)
	}

	cmd := os.Args[1]
	fs := flag.NewFlagSet(cmd, flag.ExitOnError)
	var srvFn string
	fs.StringVar(&srvFn, "srv-file", "", "File with one DNS server per line")

	var wordsFn string
	switch cmd {
	case "help":
		usage(os.Stdout)
		os.Exit(0)
	case "zone":
		fs.StringVar(&wordsFn, "words-file", "/usr/share/dict/words", "Word list file")
	case "subnet":
	case "wildcard":
	default:
		usage(os.Stderr)
		os.Exit(1)
	}

	fs.Parse(os.Args[2:])

	var err error
	if len(srvFn) > 0 {
		err = loadConfigFromServersFile(srvFn)
	} else {
		err = loadConfigFromSystem()
	}
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return
	}

	workerPool = newWorkerPool(10)

	a := fs.Arg(0)
	if len(a) == 0 {
		usage(os.Stderr)
		os.Exit(1)
	}

	switch cmd {
	case "zone":
		zoneCmd(a, wordsFn)
	case "subnet":
		subnetCmd(a)
	case "wildcard":
		wildcardCmd(a)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"github.com/dotcloud/docker/pkg/libcontainer"
	"github.com/dotcloud/docker/pkg/libcontainer/nsinit"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strconv"
)

var (
	root, console string
	pipeFd        int
)

func registerFlags() {
	flag.StringVar(&console, "console", "", "console (pty slave) path")
	flag.IntVar(&pipeFd, "pipe", 0, "sync pipe fd")
	flag.StringVar(&root, "root", ".", "root for storing configuration data")

	flag.Parse()
}

func main() {
	registerFlags()

	if flag.NArg() < 1 {
		log.Fatalf("wrong number of argments %d", flag.NArg())
	}
	container, err := loadContainer()
	if err != nil {
		log.Fatal(err)
	}
	ns, err := newNsInit()
	if err != nil {
		log.Fatal(err)
	}

	switch flag.Arg(0) {
	case "exec": // this is executed outside of the namespace in the cwd
		var exitCode int
		nspid, err := readPid()
		if err != nil {
			if !os.IsNotExist(err) {
				log.Fatal(err)
			}
		}
		if nspid > 0 {
			exitCode, err = ns.ExecIn(container, nspid, flag.Args()[1:])
		} else {
			term := nsinit.NewTerminal(os.Stdin, os.Stdout, os.Stderr, container.Tty)
			exitCode, err = ns.Exec(container, term, flag.Args()[1:])
		}
		if err != nil {
			log.Fatal(err)
		}
		os.Exit(exitCode)
	case "init": // this is executed inside of the namespace to setup the container
		cwd, err := os.Getwd()
		if err != nil {
			log.Fatal(err)
		}
		if flag.NArg() < 2 {
			log.Fatalf("wrong number of argments %d", flag.NArg())
		}
		syncPipe, err := nsinit.NewSyncPipeFromFd(0, uintptr(pipeFd))
		if err != nil {
			log.Fatal(err)
		}
		if err := ns.Init(container, cwd, console, syncPipe, flag.Args()[1:]); err != nil {
			log.Fatal(err)
		}
	default:
		log.Fatalf("command not supported for nsinit %s", flag.Arg(0))
	}
}

func loadContainer() (*libcontainer.Container, error) {
	f, err := os.Open(filepath.Join(root, "container.json"))
	if err != nil {
		return nil, err
	}
	defer f.Close()

	var container *libcontainer.Container
	if err := json.NewDecoder(f).Decode(&container); err != nil {
		return nil, err
	}
	return container, nil
}

func readPid() (int, error) {
	data, err := ioutil.ReadFile(filepath.Join(root, "pid"))
	if err != nil {
		return -1, err
	}
	pid, err := strconv.Atoi(string(data))
	if err != nil {
		return -1, err
	}
	return pid, nil
}

func newNsInit() (nsinit.NsInit, error) {
	return nsinit.NewNsInit(&nsinit.DefaultCommandFactory{root}, &nsinit.DefaultStateWriter{root}), nil
}
<commit_msg>nsinit: prefix errors with their source<commit_after>package main

import (
	"encoding/json"
	"flag"
	"github.com/dotcloud/docker/pkg/libcontainer"
	"github.com/dotcloud/docker/pkg/libcontainer/nsinit"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strconv"
)

var (
	root, console string
	pipeFd        int
)

func registerFlags() {
	flag.StringVar(&console, "console", "", "console (pty slave) path")
	flag.IntVar(&pipeFd, "pipe", 0, "sync pipe fd")
	flag.StringVar(&root, "root", ".", "root for storing configuration data")

	flag.Parse()
}

func main() {
	registerFlags()

	if flag.NArg() < 1 {
		log.Fatalf("wrong number of argments %d", flag.NArg())
	}
	container, err := loadContainer()
	if err != nil {
		log.Fatalf("Unable to load container: %s", err)
	}
	ns, err := newNsInit()
	if err != nil {
		log.Fatalf("Unable to initialize nsinit: %s", err)
	}

	switch flag.Arg(0) {
	case "exec": // this is executed outside of the namespace in the cwd
		var exitCode int
		nspid, err := readPid()
		if err != nil {
			if !os.IsNotExist(err) {
				log.Fatalf("Unable to read pid: %s", err)
			}
		}
		if nspid > 0 {
			exitCode, err = ns.ExecIn(container, nspid, flag.Args()[1:])
		} else {
			term := nsinit.NewTerminal(os.Stdin, os.Stdout, os.Stderr, container.Tty)
			exitCode, err = ns.Exec(container, term, flag.Args()[1:])
		}
		if err != nil {
			log.Fatalf("Failed to exec: %s", err)
		}
		os.Exit(exitCode)
	case "init": // this is executed inside of the namespace to setup the container
		cwd, err := os.Getwd()
		if err != nil {
			log.Fatal(err)
		}
		if flag.NArg() < 2 {
			log.Fatalf("wrong number of argments %d", flag.NArg())
		}
		syncPipe, err := nsinit.NewSyncPipeFromFd(0, uintptr(pipeFd))
		if err != nil {
			log.Fatalf("Unable to create sync pipe: %s", err)
		}
		if err := ns.Init(container, cwd, console, syncPipe, flag.Args()[1:]); err != nil {
			log.Fatalf("Unable to initialize for container: %s", err)
		}
	default:
		log.Fatalf("command not supported for nsinit %s", flag.Arg(0))
	}
}

func loadContainer() (*libcontainer.Container, error) {
	f, err := os.Open(filepath.Join(root, "container.json"))
	if err != nil {
		return nil, err
	}
	defer f.Close()

	var container *libcontainer.Container
	if err := json.NewDecoder(f).Decode(&container); err != nil {
		return nil, err
	}
	return container, nil
}

func readPid() (int, error) {
	data, err := ioutil.ReadFile(filepath.Join(root, "pid"))
	if err != nil {
		return -1, err
	}
	pid, err := strconv.Atoi(string(data))
	if err != nil {
		return -1, err
	}
	return pid, nil
}

func newNsInit() (nsinit.NsInit, error) {
	return nsinit.NewNsInit(&nsinit.DefaultCommandFactory{root}, &nsinit.DefaultStateWriter{root}), nil
}
<|endoftext|>


<commit_before>package object

type RObject struct {
	Class             *RClass
	InstanceVariables *Environment
	Scope             *Scope
	InitializeMethod  *Method
}

func (bo *RObject) Type() ObjectType {
	return BASE_OBJECT_OBJ
}

func (bo *RObject) Inspect() string {
	return "<Instance of: " + bo.Class.Name.Value + ">"
}
<commit_msg>Create BaseObject interface.<commit_after>package object

type BaseObject interface {
	ReturnClass() Class
	Object
}

type RObject struct {
	Class             *RClass
	InstanceVariables *Environment
	Scope             *Scope
	InitializeMethod  *Method
}

func (ro *RObject) Type() ObjectType {
	return BASE_OBJECT_OBJ
}

func (ro *RObject) Inspect() string {
	return "<Instance of: " + ro.Class.Name.Value + ">"
}

func (ro *RObject) ReturnClass() Class {
	return ro.Class
}<|endoftext|>


<commit_before>package cache

import (
	"errors"
	"time"
)

const CACHE_TTL = 1 * time.Hour

type Cache struct {
	data map[string][][]string
	date *time.Time
}

func New(cached map[string][][]string) *Cache {
	now := time.Now().UTC()
	return &Cache{cached, &now}
}

func NewWithTime(cached map[string][][]string, t time.Time) *Cache {
	return &Cache{cached, &t}
}

func (c *Cache) Get() (mappings map[string][][]string, err error) {
	mappings = c.data
	if c.IsValid() {
		return
	}
	return nil, errors.New("cache is not valid!")
}

func (c *Cache) Update(mappings map[string][][]string) {
	now := time.Now().UTC()
	c.data = mappings
	c.date = &now
}

func (c *Cache) IsValid() bool {
	return !c.IsEmpty() && !c.IsOutdated()
}

func (c *Cache) IsOutdated() bool {
	now := time.Now().UTC()
	expiration := c.date.Add(CACHE_TTL)
	dObj := &expiration
	return dObj.Before(now)
}

func (c *Cache) IsEmpty() bool {
	return c.data == nil || c.date == nil
}
<commit_msg>TTPD-174: improves mappings caching<commit_after>package cache

import (
	"errors"
	"time"
)

const CACHE_TTL = 1 * time.Hour

type Cache struct {
	data map[string][][]string
	date *time.Time
}

func New(cached map[string][][]string) *Cache {
	now := time.Now().UTC()
	return &Cache{cached, &now}
}

func NewWithTime(cached map[string][][]string, t time.Time) *Cache {
	return &Cache{cached, &t}
}

func (c *Cache) Get() (mappings map[string][][]string, err error) {
	mappings = c.data
	if c.IsValid() {
		return
	}
	return nil, errors.New("cache is not valid!")
}

func (c *Cache) Update(mappings map[string][][]string) {
	now := time.Now().UTC()
	c.data = mappings
	c.date = &now
}

func (c *Cache) IsValid() bool {
	return !c.IsEmpty() && !c.IsOutdated()
}

func (c *Cache) IsOutdated() bool {
	now := time.Now().UTC()
	if c.date != nil {
		expiration := c.date.Add(CACHE_TTL)
		dObj := &expiration
		return dObj.Before(now)
	}
	return true
}

func (c *Cache) IsEmpty() bool {
	return c.data == nil || c.date == nil
}
<|endoftext|>


<commit_before>package cf

import (
	"os"
	"path/filepath"
)

const (
	Version = "6.0.0-SHA"
	Usage   = "A command line tool to interact with Cloud Foundry"
)

func Name() string {
	return filepath.Base(os.Args[0])
}
<commit_msg>Update version number<commit_after>package cf

import (
	"os"
	"path/filepath"
)

const (
	Version = "6.0.1-SHA"
	Usage   = "A command line tool to interact with Cloud Foundry"
)

func Name() string {
	return filepath.Base(os.Args[0])
}
<|endoftext|>


<commit_before>package sourcegraph

import (
	"sourcegraph.com/sourcegraph/go-sourcegraph/router"
)

// SearchService communicates with the search-related endpoints in
// the Sourcegraph API.
type SearchService interface {
	// Search searches the full index.
	Search(opt *SearchOptions) (*SearchResults, Response, error)

	// Complete completes the token at the RawQuery's InsertionPoint.
	Complete(q RawQuery) (*Completions, Response, error)
}

type SearchResults struct {
	Defs   []*Def    `json:",omitempty"`
	People []*Person `json:",omitempty"`
	Repos  []*Repo   `json:",omitempty"`

	// RawQuery is the raw query passed to search.
	RawQuery RawQuery

	// Tokens are the unresolved tokens.
	Tokens Tokens `json:",omitempty"`

	// Plan is the query plan used to fetch the results.
	Plan *Plan `json:",omitempty"`

	// ResolvedTokens holds the resolved tokens from the original query
	// string.
	ResolvedTokens Tokens

	ResolveErrors []TokenError `json:",omitempty"`

	// Tips are helpful tips for the user about their query. They are
	// not errors per se, but they use the TokenError type because it
	// allows us to associate a message with a particular token (and
	// JSON de/serialize that).
	Tips []TokenError `json:",omitempty"`
}

// Empty is whether there are no search results for any result type.
func (r *SearchResults) Empty() bool {
	return len(r.Defs) == 0 && len(r.People) == 0 && len(r.Repos) == 0
}

// searchService implements SearchService.
type searchService struct {
	client *Client
}

var _ SearchService = &searchService{}

type SearchOptions struct {
	Query string `url:"q" schema:"q"`

	Defs   bool
	Repos  bool
	People bool

	ListOptions
}

func (s *searchService) Search(opt *SearchOptions) (*SearchResults, Response, error) {
	url, err := s.client.URL(router.Search, nil, opt)
	if err != nil {
		return nil, nil, err
	}

	req, err := s.client.NewRequest("GET", url.String(), nil)
	if err != nil {
		return nil, nil, err
	}

	var results *SearchResults
	resp, err := s.client.Do(req, &results)
	if err != nil {
		return nil, resp, err
	}

	return results, resp, nil
}

// Completions holds search query completions.
type Completions struct {
	// TokenCompletions are suggested completions for the token at the
	// raw query's InsertionPoint.
	TokenCompletions Tokens

	// ResolvedTokens is the resolution of the original query's tokens
	// used to produce the completions. It is useful for debugging.
	ResolvedTokens Tokens

	ResolveErrors   []TokenError `json:",omitempty"`
	ResolutionFatal bool         `json:",omitempty"`
}

func (s *searchService) Complete(q RawQuery) (*Completions, Response, error) {
	url, err := s.client.URL(router.SearchComplete, nil, q)
	if err != nil {
		return nil, nil, err
	}

	req, err := s.client.NewRequest("GET", url.String(), nil)
	if err != nil {
		return nil, nil, err
	}

	var comps *Completions
	resp, err := s.client.Do(req, &comps)
	if err != nil {
		return nil, resp, err
	}

	return comps, resp, nil
}

type MockSearchService struct {
	Search_   func(opt *SearchOptions) (*SearchResults, Response, error)
	Complete_ func(q RawQuery) (*Completions, Response, error)
}

var _ SearchService = MockSearchService{}

func (s MockSearchService) Search(opt *SearchOptions) (*SearchResults, Response, error) {
	return s.Search_(opt)
}

func (s MockSearchService) Complete(q RawQuery) (*Completions, Response, error) {
	return s.Complete_(q)
}
<commit_msg>add SearchResults.Canceled<commit_after>package sourcegraph

import (
	"sourcegraph.com/sourcegraph/go-sourcegraph/router"
)

// SearchService communicates with the search-related endpoints in
// the Sourcegraph API.
type SearchService interface {
	// Search searches the full index.
	Search(opt *SearchOptions) (*SearchResults, Response, error)

	// Complete completes the token at the RawQuery's InsertionPoint.
	Complete(q RawQuery) (*Completions, Response, error)
}

type SearchResults struct {
	Defs   []*Def    `json:",omitempty"`
	People []*Person `json:",omitempty"`
	Repos  []*Repo   `json:",omitempty"`

	// RawQuery is the raw query passed to search.
	RawQuery RawQuery

	// Tokens are the unresolved tokens.
	Tokens Tokens `json:",omitempty"`

	// Plan is the query plan used to fetch the results.
	Plan *Plan `json:",omitempty"`

	// ResolvedTokens holds the resolved tokens from the original query
	// string.
	ResolvedTokens Tokens

	ResolveErrors []TokenError `json:",omitempty"`

	// Tips are helpful tips for the user about their query. They are
	// not errors per se, but they use the TokenError type because it
	// allows us to associate a message with a particular token (and
	// JSON de/serialize that).
	Tips []TokenError `json:",omitempty"`

	// Canceled is true if the query was canceled. More information
	// about how to correct the issue can be found in the
	// ResolveErrors and Tips.
	Canceled bool
}

// Empty is whether there are no search results for any result type.
func (r *SearchResults) Empty() bool {
	return len(r.Defs) == 0 && len(r.People) == 0 && len(r.Repos) == 0
}

// searchService implements SearchService.
type searchService struct {
	client *Client
}

var _ SearchService = &searchService{}

type SearchOptions struct {
	Query string `url:"q" schema:"q"`

	Defs   bool
	Repos  bool
	People bool

	ListOptions
}

func (s *searchService) Search(opt *SearchOptions) (*SearchResults, Response, error) {
	url, err := s.client.URL(router.Search, nil, opt)
	if err != nil {
		return nil, nil, err
	}

	req, err := s.client.NewRequest("GET", url.String(), nil)
	if err != nil {
		return nil, nil, err
	}

	var results *SearchResults
	resp, err := s.client.Do(req, &results)
	if err != nil {
		return nil, resp, err
	}

	return results, resp, nil
}

// Completions holds search query completions.
type Completions struct {
	// TokenCompletions are suggested completions for the token at the
	// raw query's InsertionPoint.
	TokenCompletions Tokens

	// ResolvedTokens is the resolution of the original query's tokens
	// used to produce the completions. It is useful for debugging.
	ResolvedTokens Tokens

	ResolveErrors   []TokenError `json:",omitempty"`
	ResolutionFatal bool         `json:",omitempty"`
}

func (s *searchService) Complete(q RawQuery) (*Completions, Response, error) {
	url, err := s.client.URL(router.SearchComplete, nil, q)
	if err != nil {
		return nil, nil, err
	}

	req, err := s.client.NewRequest("GET", url.String(), nil)
	if err != nil {
		return nil, nil, err
	}

	var comps *Completions
	resp, err := s.client.Do(req, &comps)
	if err != nil {
		return nil, resp, err
	}

	return comps, resp, nil
}

type MockSearchService struct {
	Search_   func(opt *SearchOptions) (*SearchResults, Response, error)
	Complete_ func(q RawQuery) (*Completions, Response, error)
}

var _ SearchService = MockSearchService{}

func (s MockSearchService) Search(opt *SearchOptions) (*SearchResults, Response, error) {
	return s.Search_(opt)
}

func (s MockSearchService) Complete(q RawQuery) (*Completions, Response, error) {
	return s.Complete_(q)
}
<|endoftext|>


<commit_before>package app

import (
	log "github.com/cihub/seelog"
	car "github.com/mohae/carchivum"
	contour "github.com/mohae/contourp"
)

var (
	// Name is the name of the application
	Name string = "car"

	// ConfigFile is the name of the configuration file for the application.
	ConfigFile string = "app.json"

	// LogConfigFile is the name for the log configuration file.
	LogConfigFile string = "seelog.xml"
)

// Variables for configuration entries, or just hard code them.
var (
	CfgConfigFile    string = "configfile"
	CfgLogConfigFile string = "logconfigfile"
	CfgLog           string = "log"
	CfgFormat        string = "format"
	CfgType          string = "type"
)

// Application config.
var Config = contour.AppConfig()

// set-up the application defaults and let contour know about the app.
// Setting also saves them to their relative environment variable.
func init() {
	// Calling Register* saves the configuration setting information
	// without writing it to its respective environment variable. This
	// allows any already set environment variables to override non-core
	// vars.
	//
	// Only settings that have been initialized are recognized by contour.

	// The config filename is handled differently, calling this function
	// also sets the ConfigFile format automatically,based on the
	// extension, if it can be determined. If it cannot, the extension is
	// left blank and must be set.
	contour.RegisterConfigFilename(ConfigFile)

	//// Alternative way, manually setting the values
	//contour.RegisterString("configfilename", ConfigFilename)
	//contour.RegisterString("configfileext", "json")

	// Core settings are only settable by the application, and once set are
	// immutable
	contour.RegisterStringCore("name", Name)

	// Immutable settings are only settable once. If its value isn't set
	// during registration, it can be set at a later time. Once it is set,
	// immutable values cannot be changed. Because of this, and the fact
	// that initialization causes bools to be set, bools cannot be made
	// immutable.

	// Set*Flag allows you to add settings that are also exposed as
	// command-line flags. Default implicit values to settings:
	//	IsFlag = true
	//	IsIdempotent = false
	//	IsCore = false
	// The shortcode, 2nd parameter, can be left as an empty string, ""
	// if this flag doesn't support a shortcode.

	// Logging and output related
	contour.RegisterBoolFlag(CfgLog, "l", false, "enable/disable logging")
	contour.RegisterStringFlag(CfgLogConfigFile, "g", LogConfigFile, "name of the log configuration file")

	// AddSettingAlias sets an alias for the setting.
	// contour doesn't support alias yet
	//	contour.AddSettingAlias(CfgLog, "logenabled")
	initApp()

	// Now that the configuration in
}

// InitApp is the best place to add custom defaults for your application,
func initApp() {
	contour.RegisterStringFlag(CfgFormat, "f", "tar", "create an archive using the tar format")
	contour.RegisterStringFlag(CfgType, "t", "gzip", "create an archive using the zip format")

	// Create operation modifiers
	contour.RegisterIntFlag("owner", "", 0, "force UID as owner for added files")
	contour.RegisterIntFlag("group", "", 0, "force GID as group for added files")
	contour.RegisterInt64Flag("mode", "", 0, "force MASK as mode for added files")

//	contour.RegisterBoolFlag("usefullpath", "u", false, ")

	// Extract Operation Modifiers
//	contour.RegisterBoolFlag("keep-old-files", "k", false, "don't replace existing files when extracting")
//	contour.RegisterBoolFlag("keep-newer-files", "", false, "don't replace existing files that are newer than their archive copies")
//	contour.RegisterBoolFlag("overwrite", "", true, "overwrite existing files when extracting")
////	contour.RegisterBoolFlag("atime-preserve", "", true)
//	contour.RegisterBoolFlag("modification-time", "m", false, "don't extract file modified time")
//	contour.RegisterBoolFlag("same-owner", "", true, "try extracting files with the same ownership")
//	contour.RegisterBoolFlag("no-same-owner", "", false, "extract files as yourself")
//	contour.RegisterBoolFlag("numeric-owner", "", true, "always use numbers for user/group names")
//	contour.RegisterBoolFlag("same-permissions", "p", true, "extract permissions information")
//	contour.RegisterBoolFlag("no-same-permissions", "", false, "do not extract permissions information")

	// Create Operation Local file selection
	contour.RegisterBoolFlag("delete-files", "D", false, "remove files after adding them to the archive")
	contour.RegisterStringFlag("exclude", "", "", "exclude files, given as a PATTERN")
	contour.RegisterStringFlag("exclude-ext", "e", "", "exclude files with EXTENSIONS")
	contour.RegisterStringFlag("exclude-anchored", "", "", "exclude patterns match file name start")
	contour.RegisterStringFlag("include", "", "", "include files, given as a PATTERN")
	contour.RegisterStringFlag("include-ext", "i", "", "include files with EXTNESIONS")
	contour.RegisterStringFlag("include-anchored", "", "", "include patterns match file name start")
//	contour.RegisterBoolFlag("wildcards", "", false, "patterns use wildcards")
//	contour.RegisterBoolFlag("no-wildcards", "", true, "patters do not use wildcards")
	contour.RegisterStringFlag("newer", "N", "", "only store files newer than DATE or File")
	contour.RegisterStringFlag("newer-mtime", "M", "", "only store files modified since DATE")
//	contour.RegisterStringFlag("newer-file", "", "only store files newere than the DATE for FILENAMEE")

	// Register option aliases
	//	contour.RegisterFlagAlias("newer-date", "after-date")
	//	contour.RegisterFlagAlias("same-permissions", "preserve-permissions")
}

// InitConfig initialized the application's configuration. When the config is
// has been initialized, the preset-enivronment variables, application
// defaults, and your application's configuration file, should it have one,
// will all be merged according to the setting properties.
//
// After this, only overrides can occur via command flags.
func SetConfig() error {
	// Set config:
	//    Checks environment variables for settings, follows update rules.
	//    Retrieves config file and applies those settings, if and where
	//      applicable.
	//    Writes the resulting configuration settings to their env vars.
	//  After set config, only command flags can override the settings.
	//  If this is an interactive application, preference changes would
	//    also override certain settings. It may necessitate an additional
	//    flag or two.
	return contour.SetConfig()
}

// SetAppLog sets the logger for package loggers and allow for custom-
// ization of the applications log. This is where app specific code for
// setting up the application's log should be.
//
// SetAppLog assumes that log is enabled if it has been called as its
// caller should be SetLog(). If you are going to call this from elsewhere,
// first make sure that log is enabled.
//
// This uses seelog.
func SetAppLogging() {
	contour.UseLogger(logger)
	car.UseLogger(logger)
	return
}

func DisableAppLogging() {
	contour.DisableLog()
	car.DisableLog()
	return
}

func AppFlushLog() {
	contour.FlushLog()
	car.FlushLog()
	log.Flush()
}
<commit_msg>fix calls for settig time flags<commit_after>package app

import (
	"time"

	log "github.com/cihub/seelog"
	car "github.com/mohae/carchivum"
	contour "github.com/mohae/contourp"
)

var (
	// Name is the name of the application
	Name string = "car"

	// ConfigFile is the name of the configuration file for the application.
	ConfigFile string = "app.json"

	// LogConfigFile is the name for the log configuration file.
	LogConfigFile string = "seelog.xml"
)

// Variables for configuration entries, or just hard code them.
var (
	CfgConfigFile    string = "configfile"
	CfgLogConfigFile string = "logconfigfile"
	CfgLog           string = "log"
	CfgFormat        string = "format"
	CfgType          string = "type"
)

// Application config.
var Config = contour.AppConfig()
var unsetTime time.Time
// set-up the application defaults and let contour know about the app.
// Setting also saves them to their relative environment variable.
func init() {
	// Calling Register* saves the configuration setting information
	// without writing it to its respective environment variable. This
	// allows any already set environment variables to override non-core
	// vars.
	//
	// Only settings that have been initialized are recognized by contour.

	// The config filename is handled differently, calling this function
	// also sets the ConfigFile format automatically,based on the
	// extension, if it can be determined. If it cannot, the extension is
	// left blank and must be set.
	contour.RegisterConfigFilename(ConfigFile)

	//// Alternative way, manually setting the values
	//contour.RegisterString("configfilename", ConfigFilename)
	//contour.RegisterString("configfileext", "json")

	// Core settings are only settable by the application, and once set are
	// immutable
	contour.RegisterStringCore("name", Name)

	// Immutable settings are only settable once. If its value isn't set
	// during registration, it can be set at a later time. Once it is set,
	// immutable values cannot be changed. Because of this, and the fact
	// that initialization causes bools to be set, bools cannot be made
	// immutable.

	// Set*Flag allows you to add settings that are also exposed as
	// command-line flags. Default implicit values to settings:
	//	IsFlag = true
	//	IsIdempotent = false
	//	IsCore = false
	// The shortcode, 2nd parameter, can be left as an empty string, ""
	// if this flag doesn't support a shortcode.

	// Logging and output related
	contour.RegisterBoolFlag(CfgLog, "l", false, "enable/disable logging")
	contour.RegisterStringFlag(CfgLogConfigFile, "g", LogConfigFile, "name of the log configuration file")

	// AddSettingAlias sets an alias for the setting.
	// contour doesn't support alias yet
	//	contour.AddSettingAlias(CfgLog, "logenabled")
	initApp()

	// Now that the configuration in
}

// InitApp is the best place to add custom defaults for your application,
func initApp() {
	contour.RegisterStringFlag(CfgFormat, "f", "tar", "create an archive using the tar format")
	contour.RegisterStringFlag(CfgType, "t", "gzip", "create an archive using the zip format")

	// Create operation modifiers
	contour.RegisterIntFlag("owner", "", 0, "force UID as owner for added files")
	contour.RegisterIntFlag("group", "", 0, "force GID as group for added files")
	contour.RegisterInt64Flag("mode", "", 0, "force MASK as mode for added files")

//	contour.RegisterBoolFlag("usefullpath", "u", false, ")

	// Extract Operation Modifiers
//	contour.RegisterBoolFlag("keep-old-files", "k", false, "don't replace existing files when extracting")
//	contour.RegisterBoolFlag("keep-newer-files", "", false, "don't replace existing files that are newer than their archive copies")
//	contour.RegisterBoolFlag("overwrite", "", true, "overwrite existing files when extracting")
////	contour.RegisterBoolFlag("atime-preserve", "", true)
//	contour.RegisterBoolFlag("modification-time", "m", false, "don't extract file modified time")
//	contour.RegisterBoolFlag("same-owner", "", true, "try extracting files with the same ownership")
//	contour.RegisterBoolFlag("no-same-owner", "", false, "extract files as yourself")
//	contour.RegisterBoolFlag("numeric-owner", "", true, "always use numbers for user/group names")
//	contour.RegisterBoolFlag("same-permissions", "p", true, "extract permissions information")
//	contour.RegisterBoolFlag("no-same-permissions", "", false, "do not extract permissions information")

	// Create Operation Local file selection
	contour.RegisterBoolFlag("delete-files", "D", false, "remove files after adding them to the archive")
	contour.RegisterStringFlag("exclude", "", "", "exclude files, given as a PATTERN")
	contour.RegisterStringFlag("exclude-ext", "e", "", "exclude files with EXTENSIONS")
	contour.RegisterStringFlag("exclude-anchored", "", "", "exclude patterns match file name start")
	contour.RegisterStringFlag("include", "", "", "include files, given as a PATTERN")
	contour.RegisterStringFlag("include-ext", "i", "", "include files with EXTNESIONS")
	contour.RegisterStringFlag("include-anchored", "", "", "include patterns match file name start")
//	contour.RegisterBoolFlag("wildcards", "", false, "patterns use wildcards")
//	contour.RegisterBoolFlag("no-wildcards", "", true, "patters do not use wildcards")
	contour.RegisterTimeFlag("newer", "N", unsetTime, "only store files newer than DATE or File")
	contour.RegisterTimeFlag("newer-mtime", "M", unsetTime, "only store files modified since DATE")
//	contour.RegisterStringFlag("newer-file", "", "only store files newere than the DATE for FILENAMEE")

	// Register option aliases
	//	contour.RegisterFlagAlias("newer-date", "after-date")
	//	contour.RegisterFlagAlias("same-permissions", "preserve-permissions")
}

// InitConfig initialized the application's configuration. When the config is
// has been initialized, the preset-enivronment variables, application
// defaults, and your application's configuration file, should it have one,
// will all be merged according to the setting properties.
//
// After this, only overrides can occur via command flags.
func SetConfig() error {
	// Set config:
	//    Checks environment variables for settings, follows update rules.
	//    Retrieves config file and applies those settings, if and where
	//      applicable.
	//    Writes the resulting configuration settings to their env vars.
	//  After set config, only command flags can override the settings.
	//  If this is an interactive application, preference changes would
	//    also override certain settings. It may necessitate an additional
	//    flag or two.
	return contour.SetConfig()
}

// SetAppLog sets the logger for package loggers and allow for custom-
// ization of the applications log. This is where app specific code for
// setting up the application's log should be.
//
// SetAppLog assumes that log is enabled if it has been called as its
// caller should be SetLog(). If you are going to call this from elsewhere,
// first make sure that log is enabled.
//
// This uses seelog.
func SetAppLogging() {
	contour.UseLogger(logger)
	car.UseLogger(logger)
	return
}

func DisableAppLogging() {
	contour.DisableLog()
	car.DisableLog()
	return
}

func AppFlushLog() {
	contour.FlushLog()
	car.FlushLog()
	log.Flush()
}
<|endoftext|>


<commit_before>package app

import (
	"net/http"

	"github.com/gilcrest/go-api-basic/datastore"
	"github.com/rs/zerolog"
)

// Application is the main server struct for Guestbook. It contains the state of
// the most recently read message of the day.
type Application struct {
	EnvName EnvName
	// PostgreSQL database
	DS datastore.Datastore
	// Logger
	Logger zerolog.Logger
}

// ProvideApplication creates a new application struct
func ProvideApplication(en EnvName, ds datastore.Datastore, log zerolog.Logger) *Application {
	return &Application{
		EnvName: en,
		DS:      ds,
		Logger:  log,
	}
}

// EnvName is the environment Name int representation
// Using iota, 1 (Production) is the lowest,
// 2 (Staging) is 2nd lowest, and so on...
type EnvName uint8

// EnvName of environment.
const (
	Production EnvName = iota + 1 // Production (1)
	Staging                       // Staging (2)
	QA                            // QA (3)
	Dev                           // Dev (4)
)

func (n EnvName) String() string {
	switch n {
	case Production:
		return "Production"
	case Staging:
		return "Staging"
	case QA:
		return "QA"
	case Dev:
		return "Dev"
	}
	return "unknown_name"
}

// StdResponseHeader middleware is used to add
// standard HTTP response headers
func (app *Application) StdResponseHeader(h http.Handler) http.Handler {
	return http.HandlerFunc(
		func(w http.ResponseWriter, r *http.Request) {
			w.Header().Add("Content-Type", "application/json")
			h.ServeHTTP(w, r) // call original
		})
}
<commit_msg>Name change for readability<commit_after>package app

import (
	"net/http"

	"github.com/gilcrest/go-api-basic/datastore"
	"github.com/rs/zerolog"
)

// Application is the main server struct for Guestbook. It contains the state of
// the most recently read message of the day.
type Application struct {
	EnvName EnvName
	// PostgreSQL database
	DS datastore.Datastore
	// Logger
	Logger zerolog.Logger
}

// AddStandardResponseHeaders middleware is used to add any
// standard HTTP response headers
func (app *Application) AddStandardResponseHeaders(h http.Handler) http.Handler {
	return http.HandlerFunc(
		func(w http.ResponseWriter, r *http.Request) {
			w.Header().Add("Content-Type", "application/json")
			h.ServeHTTP(w, r) // call original
		})
}

// ProvideApplication creates a new application struct
func ProvideApplication(en EnvName, ds datastore.Datastore, log zerolog.Logger) *Application {
	return &Application{
		EnvName: en,
		DS:      ds,
		Logger:  log,
	}
}

// EnvName is the environment Name int representation
// Using iota, 1 (Production) is the lowest,
// 2 (Staging) is 2nd lowest, and so on...
type EnvName uint8

// EnvName of environment.
const (
	Production EnvName = iota + 1 // Production (1)
	Staging                       // Staging (2)
	QA                            // QA (3)
	Dev                           // Dev (4)
)

func (n EnvName) String() string {
	switch n {
	case Production:
		return "Production"
	case Staging:
		return "Staging"
	case QA:
		return "QA"
	case Dev:
		return "Dev"
	}
	return "unknown_name"
}
<|endoftext|>


<commit_before>// Copyright © 2017 Circonus, Inc. <support@circonus.com>
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//

// +build windows

package wmi

import (
	"regexp"
	"strings"
	"time"

	"github.com/StackExchange/wmi"
	"github.com/circonus-labs/circonus-agent/internal/builtins/collector"
	"github.com/circonus-labs/circonus-agent/internal/config"
	"github.com/circonus-labs/circonus-agent/internal/tags"
	cgm "github.com/circonus-labs/circonus-gometrics/v3"
	"github.com/pkg/errors"
	"github.com/rs/zerolog/log"
)

// Win32_PerfFormattedData_PerfOS_Cache defines the metrics to collect
// https://wutils.com/wmi/root/cimv2/win32_perfformatteddata_perfos_cache/
type Win32_PerfFormattedData_PerfOS_Cache struct {
	AsyncCopyReadsPersec         uint32
	AsyncDataMapsPersec          uint32
	AsyncFastReadsPersec         uint32
	AsyncMDLReadsPersec          uint32
	AsyncPinReadsPersec          uint32
	CopyReadHitsPercent          uint32
	CopyReadsPersec              uint32
	DataFlushesPersec            uint32
	DataFlushPagesPersec         uint32
	DataMapHitsPercent           uint32
	DataMapPinsPersec            uint32
	DataMapsPersec               uint32
	DirtyPages                   uint64
	DirtyPageThreshold           uint64
	FastReadNotPossiblesPersec   uint32
	FastReadResourceMissesPersec uint32
	FastReadsPersec              uint32
	LazyWriteFlushesPersec       uint32
	LazyWritePagesPersec         uint32
	MDLReadHitsPercent           uint32
	MDLReadsPersec               uint32
	PinReadHitsPercent           uint32
	PinReadsPersec               uint32
	ReadAheadsPersec             uint32
	SyncCopyReadsPersec          uint32
	SyncDataMapsPersec           uint32
	SyncFastReadsPersec          uint32
	SyncMDLReadsPersec           uint32
	SyncPinReadsPersec           uint32
}

// Cache metrics from the Windows Management Interface (wmi)
type Cache struct {
	wmicommon
}

// cacheOptions defines what elements can be overridden in a config file
type cacheOptions struct {
	ID              string `json:"id" toml:"id" yaml:"id"`
	MetricNameRegex string `json:"metric_name_regex" toml:"metric_name_regex" yaml:"metric_name_regex"`
	MetricNameChar  string `json:"metric_name_char" toml:"metric_name_char" yaml:"metric_name_char"`
	RunTTL          string `json:"run_ttl" toml:"run_ttl" yaml:"run_ttl"`
}

// NewCacheCollector creates new wmi collector
func NewCacheCollector(cfgBaseName string) (collector.Collector, error) {
	c := Cache{}
	c.id = "cache"
	c.pkgID = pkgName + "." + c.id
	c.logger = log.With().Str("pkg", pkgName).Str("id", c.id).Logger()
	c.metricDefaultActive = true
	c.metricNameChar = defaultMetricChar
	c.metricNameRegex = defaultMetricNameRegex
	c.baseTags = tags.FromList(tags.GetBaseTags())

	if cfgBaseName == "" {
		return &c, nil
	}

	var cfg cacheOptions
	err := config.LoadConfigFile(cfgBaseName, &cfg)
	if err != nil {
		if strings.Contains(err.Error(), "no config found matching") {
			return &c, nil
		}
		c.logger.Debug().Err(err).Str("file", cfgBaseName).Msg("loading config file")
		return nil, errors.Wrapf(err, "%s config", c.pkgID)
	}

	c.logger.Debug().Interface("config", cfg).Msg("loaded config")

	if cfg.ID != "" {
		c.id = cfg.ID
	}

	if cfg.MetricNameRegex != "" {
		rx, err := regexp.Compile(cfg.MetricNameRegex)
		if err != nil {
			return nil, errors.Wrapf(err, "%s compile metric_name_regex", c.pkgID)
		}
		c.metricNameRegex = rx
	}

	if cfg.MetricNameChar != "" {
		c.metricNameChar = cfg.MetricNameChar
	}

	if cfg.RunTTL != "" {
		dur, err := time.ParseDuration(cfg.RunTTL)
		if err != nil {
			return nil, errors.Wrapf(err, "%s parsing run_ttl", c.pkgID)
		}
		c.runTTL = dur
	}

	return &c, nil
}

// Collect metrics from the wmi resource
func (c *Cache) Collect() error {
	metrics := cgm.Metrics{}

	c.Lock()

	if c.runTTL > time.Duration(0) {
		if time.Since(c.lastEnd) < c.runTTL {
			c.logger.Warn().Msg(collector.ErrTTLNotExpired.Error())
			c.Unlock()
			return collector.ErrTTLNotExpired
		}
	}
	if c.running {
		c.logger.Warn().Msg(collector.ErrAlreadyRunning.Error())
		c.Unlock()
		return collector.ErrAlreadyRunning
	}

	c.running = true
	c.lastStart = time.Now()
	c.Unlock()

	metricType := "L"
	tagUnitsOperations := cgm.Tag{Category: "units", Value: "operations"}
	tagUnitsPercent := cgm.Tag{Category: "units", Value: "percent"}

	var dst []Win32_PerfFormattedData_PerfOS_Cache
	qry := wmi.CreateQuery(dst, "")
	if err := wmi.Query(qry, &dst); err != nil {
		c.logger.Error().Err(err).Str("query", qry).Msg("wmi query error")
		c.setStatus(metrics, err)
		return errors.Wrap(err, c.pkgID)
	}

	for _, item := range dst {
		_ = c.addMetric(&metrics, "", "AsyncCopyReadsPersec", metricType, item.AsyncCopyReadsPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "AsyncDataMapsPersec", metricType, item.AsyncDataMapsPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "AsyncFastReadsPersec", metricType, item.AsyncFastReadsPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "AsyncMDLReadsPersec", metricType, item.AsyncMDLReadsPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "AsyncPinReadsPersec", metricType, item.AsyncPinReadsPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "CopyReadHitsPercent", metricType, item.CopyReadHitsPercent, cgm.Tags{tagUnitsPercent})
		_ = c.addMetric(&metrics, "", "CopyReadsPersec", metricType, item.CopyReadsPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "DataFlushesPersec", metricType, item.DataFlushesPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "DataFlushPagesPersec", metricType, item.DataFlushPagesPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "DataMapHitsPercent", metricType, item.DataMapHitsPercent, cgm.Tags{tagUnitsPercent})
		_ = c.addMetric(&metrics, "", "DataMapPinsPersec", metricType, item.DataMapPinsPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "DataMapsPersec", metricType, item.DataMapsPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "DirtyPages", "I", item.DirtyPages, cgm.Tags{tagUnitsOperations})                 // uint64
		_ = c.addMetric(&metrics, "", "DirtyPageThreshold", "I", item.DirtyPageThreshold, cgm.Tags{tagUnitsOperations}) // uint64
		_ = c.addMetric(&metrics, "", "FastReadNotPossiblesPersec", metricType, item.FastReadNotPossiblesPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "FastReadResourceMissesPersec", metricType, item.FastReadResourceMissesPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "FastReadsPersec", metricType, item.FastReadsPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "LazyWriteFlushesPersec", metricType, item.LazyWriteFlushesPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "LazyWritePagesPersec", metricType, item.LazyWritePagesPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "MDLReadHitsPercent", metricType, item.MDLReadHitsPercent, cgm.Tags{tagUnitsPercent})
		_ = c.addMetric(&metrics, "", "MDLReadsPersec", metricType, item.MDLReadsPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "PinReadHitsPercent", metricType, item.PinReadHitsPercent, cgm.Tags{tagUnitsPercent})
		_ = c.addMetric(&metrics, "", "PinReadsPersec", metricType, item.PinReadsPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "ReadAheadsPersec", metricType, item.ReadAheadsPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "SyncCopyReadsPersec", metricType, item.SyncCopyReadsPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "SyncDataMapsPersec", metricType, item.SyncDataMapsPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "SyncFastReadsPersec", metricType, item.SyncFastReadsPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "SyncMDLReadsPersec", metricType, item.SyncMDLReadsPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "SyncPinReadsPersec", metricType, item.SyncPinReadsPersec, cgm.Tags{tagUnitsOperations})
	}

	c.setStatus(metrics, nil)
	return nil
}
<commit_msg>upd: remove deprecated setting<commit_after>// Copyright © 2017 Circonus, Inc. <support@circonus.com>
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//

// +build windows

package wmi

import (
	"regexp"
	"strings"
	"time"

	"github.com/StackExchange/wmi"
	"github.com/circonus-labs/circonus-agent/internal/builtins/collector"
	"github.com/circonus-labs/circonus-agent/internal/config"
	"github.com/circonus-labs/circonus-agent/internal/tags"
	cgm "github.com/circonus-labs/circonus-gometrics/v3"
	"github.com/pkg/errors"
	"github.com/rs/zerolog/log"
)

// Win32_PerfFormattedData_PerfOS_Cache defines the metrics to collect
// https://wutils.com/wmi/root/cimv2/win32_perfformatteddata_perfos_cache/
type Win32_PerfFormattedData_PerfOS_Cache struct {
	AsyncCopyReadsPersec         uint32
	AsyncDataMapsPersec          uint32
	AsyncFastReadsPersec         uint32
	AsyncMDLReadsPersec          uint32
	AsyncPinReadsPersec          uint32
	CopyReadHitsPercent          uint32
	CopyReadsPersec              uint32
	DataFlushesPersec            uint32
	DataFlushPagesPersec         uint32
	DataMapHitsPercent           uint32
	DataMapPinsPersec            uint32
	DataMapsPersec               uint32
	DirtyPages                   uint64
	DirtyPageThreshold           uint64
	FastReadNotPossiblesPersec   uint32
	FastReadResourceMissesPersec uint32
	FastReadsPersec              uint32
	LazyWriteFlushesPersec       uint32
	LazyWritePagesPersec         uint32
	MDLReadHitsPercent           uint32
	MDLReadsPersec               uint32
	PinReadHitsPercent           uint32
	PinReadsPersec               uint32
	ReadAheadsPersec             uint32
	SyncCopyReadsPersec          uint32
	SyncDataMapsPersec           uint32
	SyncFastReadsPersec          uint32
	SyncMDLReadsPersec           uint32
	SyncPinReadsPersec           uint32
}

// Cache metrics from the Windows Management Interface (wmi)
type Cache struct {
	wmicommon
}

// cacheOptions defines what elements can be overridden in a config file
type cacheOptions struct {
	ID              string `json:"id" toml:"id" yaml:"id"`
	MetricNameRegex string `json:"metric_name_regex" toml:"metric_name_regex" yaml:"metric_name_regex"`
	MetricNameChar  string `json:"metric_name_char" toml:"metric_name_char" yaml:"metric_name_char"`
	RunTTL          string `json:"run_ttl" toml:"run_ttl" yaml:"run_ttl"`
}

// NewCacheCollector creates new wmi collector
func NewCacheCollector(cfgBaseName string) (collector.Collector, error) {
	c := Cache{}
	c.id = "cache"
	c.pkgID = pkgName + "." + c.id
	c.logger = log.With().Str("pkg", pkgName).Str("id", c.id).Logger()
	c.metricNameChar = defaultMetricChar
	c.metricNameRegex = defaultMetricNameRegex
	c.baseTags = tags.FromList(tags.GetBaseTags())

	if cfgBaseName == "" {
		return &c, nil
	}

	var cfg cacheOptions
	err := config.LoadConfigFile(cfgBaseName, &cfg)
	if err != nil {
		if strings.Contains(err.Error(), "no config found matching") {
			return &c, nil
		}
		c.logger.Debug().Err(err).Str("file", cfgBaseName).Msg("loading config file")
		return nil, errors.Wrapf(err, "%s config", c.pkgID)
	}

	c.logger.Debug().Interface("config", cfg).Msg("loaded config")

	if cfg.ID != "" {
		c.id = cfg.ID
	}

	if cfg.MetricNameRegex != "" {
		rx, err := regexp.Compile(cfg.MetricNameRegex)
		if err != nil {
			return nil, errors.Wrapf(err, "%s compile metric_name_regex", c.pkgID)
		}
		c.metricNameRegex = rx
	}

	if cfg.MetricNameChar != "" {
		c.metricNameChar = cfg.MetricNameChar
	}

	if cfg.RunTTL != "" {
		dur, err := time.ParseDuration(cfg.RunTTL)
		if err != nil {
			return nil, errors.Wrapf(err, "%s parsing run_ttl", c.pkgID)
		}
		c.runTTL = dur
	}

	return &c, nil
}

// Collect metrics from the wmi resource
func (c *Cache) Collect() error {
	metrics := cgm.Metrics{}

	c.Lock()

	if c.runTTL > time.Duration(0) {
		if time.Since(c.lastEnd) < c.runTTL {
			c.logger.Warn().Msg(collector.ErrTTLNotExpired.Error())
			c.Unlock()
			return collector.ErrTTLNotExpired
		}
	}
	if c.running {
		c.logger.Warn().Msg(collector.ErrAlreadyRunning.Error())
		c.Unlock()
		return collector.ErrAlreadyRunning
	}

	c.running = true
	c.lastStart = time.Now()
	c.Unlock()

	metricType := "L"
	tagUnitsOperations := cgm.Tag{Category: "units", Value: "operations"}
	tagUnitsPercent := cgm.Tag{Category: "units", Value: "percent"}

	var dst []Win32_PerfFormattedData_PerfOS_Cache
	qry := wmi.CreateQuery(dst, "")
	if err := wmi.Query(qry, &dst); err != nil {
		c.logger.Error().Err(err).Str("query", qry).Msg("wmi query error")
		c.setStatus(metrics, err)
		return errors.Wrap(err, c.pkgID)
	}

	for _, item := range dst {
		_ = c.addMetric(&metrics, "", "AsyncCopyReadsPersec", metricType, item.AsyncCopyReadsPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "AsyncDataMapsPersec", metricType, item.AsyncDataMapsPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "AsyncFastReadsPersec", metricType, item.AsyncFastReadsPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "AsyncMDLReadsPersec", metricType, item.AsyncMDLReadsPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "AsyncPinReadsPersec", metricType, item.AsyncPinReadsPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "CopyReadHitsPercent", metricType, item.CopyReadHitsPercent, cgm.Tags{tagUnitsPercent})
		_ = c.addMetric(&metrics, "", "CopyReadsPersec", metricType, item.CopyReadsPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "DataFlushesPersec", metricType, item.DataFlushesPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "DataFlushPagesPersec", metricType, item.DataFlushPagesPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "DataMapHitsPercent", metricType, item.DataMapHitsPercent, cgm.Tags{tagUnitsPercent})
		_ = c.addMetric(&metrics, "", "DataMapPinsPersec", metricType, item.DataMapPinsPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "DataMapsPersec", metricType, item.DataMapsPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "DirtyPages", "I", item.DirtyPages, cgm.Tags{tagUnitsOperations})                 // uint64
		_ = c.addMetric(&metrics, "", "DirtyPageThreshold", "I", item.DirtyPageThreshold, cgm.Tags{tagUnitsOperations}) // uint64
		_ = c.addMetric(&metrics, "", "FastReadNotPossiblesPersec", metricType, item.FastReadNotPossiblesPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "FastReadResourceMissesPersec", metricType, item.FastReadResourceMissesPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "FastReadsPersec", metricType, item.FastReadsPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "LazyWriteFlushesPersec", metricType, item.LazyWriteFlushesPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "LazyWritePagesPersec", metricType, item.LazyWritePagesPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "MDLReadHitsPercent", metricType, item.MDLReadHitsPercent, cgm.Tags{tagUnitsPercent})
		_ = c.addMetric(&metrics, "", "MDLReadsPersec", metricType, item.MDLReadsPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "PinReadHitsPercent", metricType, item.PinReadHitsPercent, cgm.Tags{tagUnitsPercent})
		_ = c.addMetric(&metrics, "", "PinReadsPersec", metricType, item.PinReadsPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "ReadAheadsPersec", metricType, item.ReadAheadsPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "SyncCopyReadsPersec", metricType, item.SyncCopyReadsPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "SyncDataMapsPersec", metricType, item.SyncDataMapsPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "SyncFastReadsPersec", metricType, item.SyncFastReadsPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "SyncMDLReadsPersec", metricType, item.SyncMDLReadsPersec, cgm.Tags{tagUnitsOperations})
		_ = c.addMetric(&metrics, "", "SyncPinReadsPersec", metricType, item.SyncPinReadsPersec, cgm.Tags{tagUnitsOperations})
	}

	c.setStatus(metrics, nil)
	return nil
}
<|endoftext|>


<commit_before>package twitter

import (
	"fmt"

	log "github.com/Sirupsen/logrus"
	"github.com/dghubble/go-twitter/twitter"
	"github.com/dghubble/oauth1"
	"github.com/jirwin/quadlek/quadlek"
)

func load(consumerKey, consumerSecret, accessToken, accessSecret string, filter map[string]string) func(bot *quadlek.Bot, store *quadlek.Store) error {

	return func(bot *quadlek.Bot, store *quadlek.Store) error {
		go func() {
			config := oauth1.NewConfig(consumerKey, consumerSecret)
			token := oauth1.NewToken(accessToken, accessSecret)
			httpClient := config.Client(oauth1.NoContext, token)
			client := twitter.NewClient(httpClient)

			followFilters := []string{}
			for follow, _ := range filter {
				followFilters = append(followFilters, follow)
			}

			filterParams := &twitter.StreamFilterParams{
				Follow:        followFilters,
				StallWarnings: twitter.Bool(true),
			}

			stream, err := client.Streams.Filter(filterParams)
			if err != nil {
				log.WithField("err", err).Error("Error streaming tweets.")
				return
			}

			for {
				select {
				case msg := <-stream.Messages:
					switch m := msg.(type) {
					case *twitter.Tweet:
						if channel, ok := filter[m.User.IDStr]; ok {
							//if m.RetweetedStatus != nil {
							//	log.WithField("tweet", m).Info("Got a tweet containing a retweet")
							//	if replyChannel, ok := filter[m.RetweetedStatus.User.IDStr]; ok && channel == replyChannel {
							//		log.WithField("tweet", m).Info("Tweet contains retweet from already monitored account, cancelling message")
							//		continue
							//	}
							//}
							twitterUrl := fmt.Sprintf("https://twitter.com/%s/status/%s", m.User.ScreenName, m.IDStr)
							chanId, err := bot.GetChannelId(channel)
							if err != nil {
								log.WithField("err", err).Error("unable to find channel.")
								continue
							}
							bot.Say(chanId, twitterUrl)
						}
					}
				}
			}
		}()

		return nil
	}
}

func Register(consumerKey, consumerSecret, accessToken, accessSecret string, filter map[string]string) quadlek.Plugin {
	return quadlek.MakePlugin(
		"quadlek-twitter",
		nil,
		nil,
		nil,
		nil,
		load(consumerKey, consumerSecret, accessToken, accessSecret, filter),
	)
}
<commit_msg>Re-enable retweet block<commit_after>package twitter

import (
	"fmt"

	log "github.com/Sirupsen/logrus"
	"github.com/dghubble/go-twitter/twitter"
	"github.com/dghubble/oauth1"
	"github.com/jirwin/quadlek/quadlek"
)

func load(consumerKey, consumerSecret, accessToken, accessSecret string, filter map[string]string) func(bot *quadlek.Bot, store *quadlek.Store) error {

	return func(bot *quadlek.Bot, store *quadlek.Store) error {
		go func() {
			config := oauth1.NewConfig(consumerKey, consumerSecret)
			token := oauth1.NewToken(accessToken, accessSecret)
			httpClient := config.Client(oauth1.NoContext, token)
			client := twitter.NewClient(httpClient)

			followFilters := []string{}
			for follow, _ := range filter {
				followFilters = append(followFilters, follow)
			}

			filterParams := &twitter.StreamFilterParams{
				Follow:        followFilters,
				StallWarnings: twitter.Bool(true),
			}

			stream, err := client.Streams.Filter(filterParams)
			if err != nil {
				log.WithField("err", err).Error("Error streaming tweets.")
				return
			}

			for {
				select {
				case msg := <-stream.Messages:
					switch m := msg.(type) {
					case *twitter.Tweet:
						if channel, ok := filter[m.User.IDStr]; ok {
							if m.RetweetedStatus != nil {
								log.WithField("tweet", m).Info("Got a tweet containing a retweet")
								if replyChannel, ok := filter[m.RetweetedStatus.User.IDStr]; ok && channel == replyChannel {
									log.WithField("tweet", m).Info("Tweet contains retweet from already monitored account, cancelling message")
									continue
								}
							}
							twitterUrl := fmt.Sprintf("https://twitter.com/%s/status/%s", m.User.ScreenName, m.IDStr)
							chanId, err := bot.GetChannelId(channel)
							if err != nil {
								log.WithField("err", err).Error("unable to find channel.")
								continue
							}
							bot.Say(chanId, twitterUrl)
						}
					}
				}
			}
		}()

		return nil
	}
}

func Register(consumerKey, consumerSecret, accessToken, accessSecret string, filter map[string]string) quadlek.Plugin {
	return quadlek.MakePlugin(
		"quadlek-twitter",
		nil,
		nil,
		nil,
		nil,
		load(consumerKey, consumerSecret, accessToken, accessSecret, filter),
	)
}
<|endoftext|>