<commit_before>package main

import (
    "fmt"
    "bytes"
    "net/http"
    "io/ioutil"
    "github.com/andlabs/ui"
)

func main() {
    err := ui.Main(func() {
        vBox := ui.NewVerticalBox()
        // hBox := ui.NewHorizontalBox()

        urlEntry := ui.NewEntry()
        jsonLabel := ui.NewLabel("Input json:")
        jsonEntry := ui.NewEntry()
        goButton := ui.NewButton("Go")
        resLabel := ui.NewLabel("")
        selectCombobox := ui.NewCombobox()

        vBox.Append(ui.NewLabel("Input url:"), false)
        vBox.Append(urlEntry, false)
        vBox.Append(jsonLabel, false)
        vBox.Append(jsonEntry, false)
        vBox.Append(selectCombobox, false)
        vBox.Append(goButton, false)
        vBox.Append(resLabel, false)

        jsonLabel.Hide()
        jsonEntry.Hide()

        selectCombobox.Append("Get")
        selectCombobox.Append("Post")

        selectCombobox.SetSelected(0)

        window := ui.NewWindow("doreq - Do Request", 800, 600, false)
        window.SetChild(vBox)

        selectCombobox.OnSelected(func(*ui.Combobox) {
            selectedIndex := selectCombobox.Selected()
            fmt.Println("selectedIndex:>", selectedIndex)
            switch selectedIndex {
                case 1:
                    jsonLabel.Show()
                    jsonEntry.Show()
                default:
                    jsonLabel.Hide()
                    jsonEntry.Hide()
            }
        })

        goButton.OnClicked(func(*ui.Button) {
            fmt.Printf("goButton pressed\n")
            selectedIndex := selectCombobox.Selected()
            switch selectedIndex {
                case 0:
                    resp, err := http.Get(urlEntry.Text())
                    if err != nil {
                        resLabel.SetText(err.Error())
                        return
                    }
                    if resp.StatusCode == 200 {
                        bodyBytes, err := ioutil.ReadAll(resp.Body)
                        if err != nil {
                            return
                        }
                        bodyString := string(bodyBytes)
                        fmt.Printf(bodyString)
                        resLabel.SetText(bodyString)
                    }
                case 1:
                    url := urlEntry.Text()
                    fmt.Println("URL:>", url)
                    jsonStr := jsonEntry.Text()

                    var jsonBytes = []byte(jsonStr)
                    req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonBytes))
                    req.Header.Set("Content-Type", "application/json")

                    client := &http.Client{}
                    resp, err := client.Do(req)
                    if err != nil {
                        panic(err)
                    }
                    defer resp.Body.Close()

                    fmt.Println("response Status:", resp.Status)
                    fmt.Println("response Headers:", resp.Header)
                    body, _ := ioutil.ReadAll(resp.Body)
                    resLabel.SetText(string(body))
                    fmt.Println("response Body:", string(body))
                default:
                    fmt.Printf("no selected")
            }

        })
        window.OnClosing(func(*ui.Window) bool {
            ui.Quit()
            return true
        })
        window.Show()
    })
    if err != nil {
        panic(err)
    }
}<commit_msg>set padded and margined<commit_after>package main

import (
    "fmt"
    "bytes"
    "net/http"
    "io/ioutil"
    "github.com/andlabs/ui"
)

func main() {
    err := ui.Main(func() {
        vBox := ui.NewVerticalBox()
        hBox := ui.NewHorizontalBox()

        urlEntry := ui.NewEntry()
        jsonLabel := ui.NewLabel("Input json:")
        jsonEntry := ui.NewEntry()
        goButton := ui.NewButton("Go")
        resLabel := ui.NewLabel("")
        selectCombobox := ui.NewCombobox()

        vBox.Append(ui.NewLabel("Input url:"), false)

        hBox.Append(selectCombobox, false)
        hBox.Append(urlEntry, true)
        hBox.Append(goButton, false)
        hBox.SetPadded(true)

        vBox.Append(hBox, false)

        vBox.Append(jsonLabel, false)
        vBox.Append(jsonEntry, false)
        vBox.Append(resLabel, false)

        vBox.SetPadded(true)

        jsonLabel.Hide()
        jsonEntry.Hide()

        selectCombobox.Append("Get")
        selectCombobox.Append("Post")

        selectCombobox.SetSelected(0)

        window := ui.NewWindow("doreq - Do Request", 800, 600, false)
        window.SetChild(vBox)
        window.SetMargined(true)

        selectCombobox.OnSelected(func(*ui.Combobox) {
            selectedIndex := selectCombobox.Selected()
            fmt.Println("selectedIndex:>", selectedIndex)
            switch selectedIndex {
                case 1:
                    jsonLabel.Show()
                    jsonEntry.Show()
                default:
                    jsonLabel.Hide()
                    jsonEntry.Hide()
            }
        })

        goButton.OnClicked(func(*ui.Button) {
            fmt.Printf("goButton pressed\n")
            selectedIndex := selectCombobox.Selected()
            switch selectedIndex {
                case 0:
                    resp, err := http.Get(urlEntry.Text())
                    if err != nil {
                        resLabel.SetText(err.Error())
                        return
                    }
                    if resp.StatusCode == 200 {
                        bodyBytes, err := ioutil.ReadAll(resp.Body)
                        if err != nil {
                            return
                        }
                        bodyString := string(bodyBytes)
                        fmt.Printf(bodyString)
                        resLabel.SetText(bodyString)
                    }
                case 1:
                    url := urlEntry.Text()
                    fmt.Println("URL:>", url)
                    jsonStr := jsonEntry.Text()

                    var jsonBytes = []byte(jsonStr)
                    req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonBytes))
                    req.Header.Set("Content-Type", "application/json")

                    client := &http.Client{}
                    resp, err := client.Do(req)
                    if err != nil {
                        panic(err)
                    }
                    defer resp.Body.Close()

                    fmt.Println("response Status:", resp.Status)
                    fmt.Println("response Headers:", resp.Header)
                    body, _ := ioutil.ReadAll(resp.Body)
                    resLabel.SetText(string(body))
                    fmt.Println("response Body:", string(body))
                default:
                    fmt.Printf("no selected")
            }

        })
        window.OnClosing(func(*ui.Window) bool {
            ui.Quit()
            return true
        })
        window.Show()
    })
    if err != nil {
        panic(err)
    }
}<|endoftext|>


<commit_before>package models

import (
	"errors"
	"fmt"
	"time"

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

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

	// Name of the channel
	Name string `json:"name"`

	// Creator of the channel
	CreatorId int64 `json:"creatorId"`

	// Name of the group which channel is belong to
	Group string `json:"group"`

	// 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:"secretKey"`

	// Type of the channel
	Type string `json:"type"`

	// Privacy constant of the channel
	Privacy string `json:"privacy"`

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

	// Modification date of the channel
	UpdatedAt time.Time `json:"updatedAt"`
}

// 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"
	// Privacy
	Channel_TYPE_PUBLIC  = "public"
	Channel_TYPE_PRIVATE = "private"
	// Koding Group Name
	Channel_KODING_NAME = "koding-main"
)

func NewChannel() *Channel {
	return &Channel{
		Name:      "koding-main",
		CreatorId: 123,
		Group:     Channel_KODING_NAME,
		Purpose:   "string",
		SecretKey: "string",
		Type:      Channel_TYPE_GROUP,
		Privacy:   Channel_TYPE_PRIVATE,
	}
}

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

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

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

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

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

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.Group == "" {
		return errors.New(fmt.Sprintf("Validation failed %s - %s", c.Name, c.Group))
	}

	return bongo.B.Update(c)
}

func (c *Channel) Create() error {
	if c.Name == "" || c.Group == "" || c.Type == "" {
		return errors.New(fmt.Sprintf("Validation failed %s - %s", c.Name, c.Group, c.Group))
	}

	return bongo.B.Create(c)
}

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

func (c *Channel) One(selector map[string]interface{}) error {
	return bongo.B.One(c, c, selector)
}

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.Status == ChannelParticipant_STATUS_ACTIVE {
			return nil, errors.New(fmt.Sprintf("Account %s is already a participant of channel %s", cp.AccountId, cp.ChannelId))
		}
		cp.Status = ChannelParticipant_STATUS_ACTIVE
		if err := cp.Update(); err != nil {
			return nil, err
		}
		return cp, nil
	}

	cp.Status = 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.Status == ChannelParticipant_STATUS_LEFT {
		return nil
	}

	cp.Status = 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")
	}

	selector := map[string]interface{}{
		"channel_id": c.Id,
		"status":     ChannelParticipant_STATUS_ACTIVE,
	}

	pluck := map[string]interface{}{
		"account_id": true,
	}

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

	return participantIds, nil
}

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

	cml := NewChannelMessageList()
	cml.ChannelId = c.Id
	cml.MessageId = messageId

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

	return cml, nil
}
<commit_msg>Social: change channel Group to GroupName<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"`

	// Name of the channel
	Name string `json:"name"`

	// Creator of the channel
	CreatorId int64 `json:"creatorId"`

	// Name of the group which channel is belong to
	GroupName string `json:"groupName"`

	// 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:"secretKey"`

	// Type of the channel
	Type string `json:"type"`

	// Privacy constant of the channel
	Privacy string `json:"privacy"`

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

	// Modification date of the channel
	UpdatedAt time.Time `json:"updatedAt"`
}

// 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"
	// Privacy
	Channel_TYPE_PUBLIC  = "public"
	Channel_TYPE_PRIVATE = "private"
	// Koding Group Name
	Channel_KODING_NAME = "koding"
)

func NewChannel() *Channel {
	return &Channel{
		Name:      "koding",
		CreatorId: 123,
		GroupName: Channel_KODING_NAME,
		Purpose:   "string",
		SecretKey: "string",
		Type:      Channel_TYPE_GROUP,
		Privacy:   Channel_TYPE_PRIVATE,
	}
}

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

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

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

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

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

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.Type == "" {
		return fmt.Errorf("Validation failed %s - %s", c.Name, c.GroupName)
	}
	}

	return bongo.B.Create(c)
}

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

func (c *Channel) One(selector map[string]interface{}) error {
	return bongo.B.One(c, c, selector)
}

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.Status == ChannelParticipant_STATUS_ACTIVE {
			return nil, errors.New(fmt.Sprintf("Account %s is already a participant of channel %s", cp.AccountId, cp.ChannelId))
		}
		cp.Status = ChannelParticipant_STATUS_ACTIVE
		if err := cp.Update(); err != nil {
			return nil, err
		}
		return cp, nil
	}

	cp.Status = 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.Status == ChannelParticipant_STATUS_LEFT {
		return nil
	}

	cp.Status = 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")
	}

	selector := map[string]interface{}{
		"channel_id": c.Id,
		"status":     ChannelParticipant_STATUS_ACTIVE,
	}

	pluck := map[string]interface{}{
		"account_id": true,
	}

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

	return participantIds, nil
}

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

	cml := NewChannelMessageList()
	cml.ChannelId = c.Id
	cml.MessageId = messageId

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

	return cml, nil
}
<|endoftext|>


<commit_before>package cmds

import (
	"bufio"
	"bytes"
	"encoding/base64"
	"fmt"
	"net/url"
	"os"
	"strconv"
	"time"

	"github.com/pachyderm/pachyderm/src/client/version"
	"github.com/pachyderm/pachyderm/src/server/pkg/cmdutil"
	"github.com/pachyderm/pachyderm/src/server/pkg/deploy"
	"github.com/pachyderm/pachyderm/src/server/pkg/deploy/assets"
	_metrics "github.com/pachyderm/pachyderm/src/server/pkg/metrics"

	"github.com/spf13/cobra"
	"go.pedge.io/pkg/cobra"
)

func maybeKcCreate(dryRun bool, manifest *bytes.Buffer) error {
	if dryRun {
		_, err := os.Stdout.Write(manifest.Bytes())
		return err
	}
	return cmdutil.RunIO(
		cmdutil.IO{
			Stdin:  manifest,
			Stdout: os.Stdout,
			Stderr: os.Stderr,
		}, "kubectl", "create", "-f", "-")
}

// DeployCmd returns a cobra.Command to deploy pachyderm.
func DeployCmd(noMetrics *bool) *cobra.Command {
	metrics := !*noMetrics
	var pachdShards int
	var hostPath string
	var dev bool
	var dryRun bool
	var secure bool
	var etcdNodes int
	var etcdVolume string
	var blockCacheSize string
	var logLevel string
	var persistentDiskBackend string
	var objectStoreBackend string
	var opts *assets.AssetOpts

	deployLocal := &cobra.Command{
		Use:   "local",
		Short: "Deploy a single-node Pachyderm cluster with local metadata storage.",
		Long:  "Deploy a single-node Pachyderm cluster with local metadata storage.",
		Run: cmdutil.RunFixedArgs(0, func(args []string) (retErr error) {
			if metrics && !dev {
				metricsFn := _metrics.ReportAndFlushUserAction("Deploy")
				defer func(start time.Time) { metricsFn(start, retErr) }(time.Now())
			}
			manifest := &bytes.Buffer{}
			if dev {
				opts.Version = deploy.DevVersionTag
			}
			if err := assets.WriteLocalAssets(manifest, opts, hostPath); err != nil {
				return err
			}
			return maybeKcCreate(dryRun, manifest)
		}),
	}
	deployLocal.Flags().StringVar(&hostPath, "host-path", "/var/pachyderm", "Location on the host machine where PFS metadata will be stored.")
	deployLocal.Flags().BoolVarP(&dev, "dev", "d", false, "Don't use a specific version of pachyderm/pachd.")

	deployGoogle := &cobra.Command{
		Use:   "google <GCS bucket> <size of disk(s) (in GB)>",
		Short: "Deploy a Pachyderm cluster running on GCP.",
		Long: "Deploy a Pachyderm cluster running on GCP.\n" +
			"Arguments are:\n" +
			"  <GCS bucket>: A GCS bucket where Pachyderm will store PFS data.\n" +
			"  <GCE persistent disks>: A comma-separated list of GCE persistent disks, one per etcd node (see --etcd-nodes).\n" +
			"  <size of disks>: Size of GCE persistent disks in GB (assumed to all be the same).\n",
		Run: cmdutil.RunFixedArgs(2, func(args []string) (retErr error) {
			if metrics && !dev {
				metricsFn := _metrics.ReportAndFlushUserAction("Deploy")
				defer func(start time.Time) { metricsFn(start, retErr) }(time.Now())
			}
			volumeSize, err := strconv.Atoi(args[1])
			if err != nil {
				return fmt.Errorf("volume size needs to be an integer; instead got %v", args[1])
			}
			manifest := &bytes.Buffer{}
			opts.BlockCacheSize = 0 // GCS is fast so we want to disable the block cache. See issue #1650
			if err = assets.WriteGoogleAssets(manifest, opts, args[0], volumeSize); err != nil {
				return err
			}
			return maybeKcCreate(dryRun, manifest)
		}),
	}

	deployCustom := &cobra.Command{
		Use:   "custom --persistent-disk <persistent disk backend> --object-store <object store backend> <persistent disk args> <object store args>",
		Short: "(in progress) Deploy a custom Pachyderm cluster configuration",
		Long: "(in progress) Deploy a custom Pachyderm cluster configuration.\n" +
			"If <object store backend> is \"s3\", then the arguments are:\n" +
			"    <volumes> <size of volumes (in GB)> <bucket> <id> <secret> <endpoint>\n",
		Run: pkgcobra.RunBoundedArgs(pkgcobra.Bounds{Min: 4, Max: 7}, func(args []string) (retErr error) {
			if metrics && !dev {
				metricsFn := _metrics.ReportAndFlushUserAction("Deploy")
				defer func(start time.Time) { metricsFn(start, retErr) }(time.Now())
			}
			manifest := &bytes.Buffer{}
			err := assets.WriteCustomAssets(manifest, opts, args, objectStoreBackend, persistentDiskBackend, secure)
			if err != nil {
				return err
			}
			return maybeKcCreate(dryRun, manifest)
		}),
	}
	deployCustom.Flags().BoolVarP(&secure, "secure", "s", false, "Enable secure access to a Minio server.")
	deployCustom.Flags().StringVar(&persistentDiskBackend, "persistent-disk", "aws",
		"(required) Backend providing persistent local volumes to stateful pods. "+
			"One of: aws, google, or azure.")
	deployCustom.Flags().StringVar(&objectStoreBackend, "object-store", "s3",
		"(required) Backend providing an object-storage API to pachyderm. One of: "+
			"s3, gcs, or azure-blob.")

	deployAmazon := &cobra.Command{
		Use:   "amazon <S3 bucket> <id> <secret> <token> <region> <size of volumes (in GB)>",
		Short: "Deploy a Pachyderm cluster running on AWS.",
		Long: "Deploy a Pachyderm cluster running on AWS. Arguments are:\n" +
			"  <S3 bucket>: An S3 bucket where Pachyderm will store PFS data.\n" +
			"  <id>, <secret>, <token>: Session token details, used for authorization. You can get these by running 'aws sts get-session-token'\n" +
			"  <region>: The aws region where pachyderm is being deployed (e.g. us-west-1)\n" +
			"  <size of volumes>: Size of EBS volumes, in GB (assumed to all be the same).\n",
		Run: cmdutil.RunFixedArgs(6, func(args []string) (retErr error) {
			if metrics && !dev {
				metricsFn := _metrics.ReportAndFlushUserAction("Deploy")
				defer func(start time.Time) { metricsFn(start, retErr) }(time.Now())
			}
			volumeSize, err := strconv.Atoi(args[5])
			if err != nil {
				return fmt.Errorf("volume size needs to be an integer; instead got %v", args[5])
			}
			manifest := &bytes.Buffer{}
			if err = assets.WriteAmazonAssets(manifest, opts, args[0], args[1], args[2], args[3], args[4], volumeSize); err != nil {
				return err
			}
			return maybeKcCreate(dryRun, manifest)
		}),
	}

	deployMicrosoft := &cobra.Command{
		Use:   "microsoft <container> <storage account name> <storage account key> <size of volumes (in GB)>",
		Short: "Deploy a Pachyderm cluster running on Microsoft Azure.",
		Long: "Deploy a Pachyderm cluster running on Microsoft Azure. Arguments are:\n" +
			"  <container>: An Azure container where Pachyderm will store PFS data.\n" +
			"  <size of volumes>: Size of persistent volumes, in GB (assumed to all be the same).\n",
		Run: cmdutil.RunFixedArgs(4, func(args []string) (retErr error) {
			if metrics && !dev {
				metricsFn := _metrics.ReportAndFlushUserAction("Deploy")
				defer func(start time.Time) { metricsFn(start, retErr) }(time.Now())
			}
			if _, err := base64.StdEncoding.DecodeString(args[2]); err != nil {
				return fmt.Errorf("storage-account-key needs to be base64 encoded; instead got '%v'", args[2])
			}
			if opts.EtcdVolume != "" {
				tempURI, err := url.ParseRequestURI(opts.EtcdVolume)
				if err != nil {
					return fmt.Errorf("Volume URI needs to be a well-formed URI; instead got '%v'", opts.EtcdVolume)
				}
				opts.EtcdVolume = tempURI.String()
			}
			volumeSize, err := strconv.Atoi(args[3])
			if err != nil {
				return fmt.Errorf("volume size needs to be an integer; instead got %v", args[3])
			}
			manifest := &bytes.Buffer{}
			if err = assets.WriteMicrosoftAssets(manifest, opts, args[0], args[1], args[2], volumeSize); err != nil {
				return err
			}
			return maybeKcCreate(dryRun, manifest)
		}),
	}

	deploy := &cobra.Command{
		Use:   "deploy amazon|google|microsoft|local|custom",
		Short: "Deploy a Pachyderm cluster.",
		Long:  "Deploy a Pachyderm cluster.",
		PersistentPreRun: cmdutil.Run(func([]string) error {
			opts = &assets.AssetOpts{
				PachdShards:    uint64(pachdShards),
				Version:        version.PrettyPrintVersion(version.Version),
				LogLevel:       logLevel,
				Metrics:        metrics,
				BlockCacheSize: blockCacheSize,
				EtcdNodes:      etcdNodes,
				EtcdVolume:     etcdVolume,
			}
			return nil
		}),
	}
	deploy.PersistentFlags().IntVar(&pachdShards, "shards", 16, "Number of Pachd nodes (stateless Pachyderm API servers).")
	deploy.PersistentFlags().IntVar(&etcdNodes, "dynamic-etcd-nodes", 0, "Deploy etcd as a StatefulSet with the given number of pods.  The persistent volumes used by these pods are provisioned dynamically.  Note that StatefulSet is currently a beta kubernetes feature, which might be unavailable in older versions of kubernetes.")
	deploy.PersistentFlags().StringVar(&etcdVolume, "static-etcd-volume", "", "Deploy etcd as a ReplicationController with one pod.  The pod uses the given persistent volume.")
	deploy.PersistentFlags().BoolVar(&dryRun, "dry-run", false, "Don't actually deploy pachyderm to Kubernetes, instead just print the manifest.")
	deploy.PersistentFlags().StringVar(&logLevel, "log-level", "info", "The level of log messages to print options are, from least to most verbose: \"error\", \"info\", \"debug\".")
	deploy.PersistentFlags().StringVar(&blockCacheSize, "block-cache-size", "5G", "Size of in-memory cache to use for blocks. "+
		"Size is specified in bytes, with allowed SI suffixes (M, K, G, Mi, Ki, Gi, etc).")
	deploy.AddCommand(deployLocal)
	deploy.AddCommand(deployAmazon)
	deploy.AddCommand(deployGoogle)
	deploy.AddCommand(deployMicrosoft)
	deploy.AddCommand(deployCustom)
	return deploy
}

// Cmds returns a cobra commands for deploying Pachyderm clusters.
func Cmds(noMetrics *bool) []*cobra.Command {
	deploy := DeployCmd(noMetrics)
	var all bool
	undeploy := &cobra.Command{
		Use:   "undeploy",
		Short: "Tear down a deployed Pachyderm cluster.",
		Long:  "Tear down a deployed Pachyderm cluster.",
		Run: cmdutil.RunFixedArgs(0, func(args []string) error {
			if all {
				fmt.Printf(`
By using the --all flag, you are going to delete everything, including the
persistent volumes where metadata is stored.  If your persistent volumes
were dynamically provisioned (i.e. if you used the "--dynamic-etcd-nodes"
flag), the underlying volumes will be removed, making metadata such repos,
commits, pipelines, and jobs unrecoverable. If your persistent volume was
manually provisioned (i.e. if you used the "--static-etcd-volume" flag), the
underlying volume will not be removed.

Are you sure you want to proceed? yN
`)
				r := bufio.NewReader(os.Stdin)
				bytes, err := r.ReadBytes('\n')
				if err != nil {
					return err
				}
				if !(bytes[0] == 'y' || bytes[0] == 'Y') {
					return nil
				}
			}
			io := cmdutil.IO{
				Stdout: os.Stdout,
				Stderr: os.Stderr,
			}
			if err := cmdutil.RunIO(io, "kubectl", "delete", "job", "-l", "suite=pachyderm"); err != nil {
				return err
			}
			if err := cmdutil.RunIO(io, "kubectl", "delete", "all", "-l", "suite=pachyderm"); err != nil {
				return err
			}
			if err := cmdutil.RunIO(io, "kubectl", "delete", "sa", "-l", "suite=pachyderm"); err != nil {
				return err
			}
			if err := cmdutil.RunIO(io, "kubectl", "delete", "secret", "-l", "suite=pachyderm"); err != nil {
				return err
			}
			if all {
				if err := cmdutil.RunIO(io, "kubectl", "delete", "storageclass", "-l", "suite=pachyderm"); err != nil {
					return err
				}
				if err := cmdutil.RunIO(io, "kubectl", "delete", "pvc", "-l", "suite=pachyderm"); err != nil {
					return err
				}
				if err := cmdutil.RunIO(io, "kubectl", "delete", "pv", "-l", "suite=pachyderm"); err != nil {
					return err
				}
			}
			return nil
		}),
	}
	undeploy.Flags().BoolVarP(&all, "all", "a", false, `
Delete everything, including the persistent volumes where metadata
is stored.  If your persistent volumes were dynamically provisioned (i.e. if
you used the "--dynamic-etcd-nodes" flag), the underlying volumes will be
removed, making metadata such repos, commits, pipelines, and jobs
unrecoverable. If your persistent volume was manually provisioned (i.e. if
you used the "--static-etcd-volume" flag), the underlying volume will not be
removed.`)
	return []*cobra.Command{deploy, undeploy}
}
<commit_msg>Set blockCacheSize default properly<commit_after>package cmds

import (
	"bufio"
	"bytes"
	"encoding/base64"
	"fmt"
	"net/url"
	"os"
	"strconv"
	"time"

	"github.com/pachyderm/pachyderm/src/client/version"
	"github.com/pachyderm/pachyderm/src/server/pkg/cmdutil"
	"github.com/pachyderm/pachyderm/src/server/pkg/deploy"
	"github.com/pachyderm/pachyderm/src/server/pkg/deploy/assets"
	_metrics "github.com/pachyderm/pachyderm/src/server/pkg/metrics"

	"github.com/spf13/cobra"
	"go.pedge.io/pkg/cobra"
)

func maybeKcCreate(dryRun bool, manifest *bytes.Buffer) error {
	if dryRun {
		_, err := os.Stdout.Write(manifest.Bytes())
		return err
	}
	return cmdutil.RunIO(
		cmdutil.IO{
			Stdin:  manifest,
			Stdout: os.Stdout,
			Stderr: os.Stderr,
		}, "kubectl", "create", "-f", "-")
}

// DeployCmd returns a cobra.Command to deploy pachyderm.
func DeployCmd(noMetrics *bool) *cobra.Command {
	metrics := !*noMetrics
	var pachdShards int
	var hostPath string
	var dev bool
	var dryRun bool
	var secure bool
	var etcdNodes int
	var etcdVolume string
	var blockCacheSize string
	var logLevel string
	var persistentDiskBackend string
	var objectStoreBackend string
	var opts *assets.AssetOpts

	deployLocal := &cobra.Command{
		Use:   "local",
		Short: "Deploy a single-node Pachyderm cluster with local metadata storage.",
		Long:  "Deploy a single-node Pachyderm cluster with local metadata storage.",
		Run: cmdutil.RunFixedArgs(0, func(args []string) (retErr error) {
			if metrics && !dev {
				metricsFn := _metrics.ReportAndFlushUserAction("Deploy")
				defer func(start time.Time) { metricsFn(start, retErr) }(time.Now())
			}
			manifest := &bytes.Buffer{}
			if dev {
				opts.Version = deploy.DevVersionTag
			}
			if err := assets.WriteLocalAssets(manifest, opts, hostPath); err != nil {
				return err
			}
			return maybeKcCreate(dryRun, manifest)
		}),
	}
	deployLocal.Flags().StringVar(&hostPath, "host-path", "/var/pachyderm", "Location on the host machine where PFS metadata will be stored.")
	deployLocal.Flags().BoolVarP(&dev, "dev", "d", false, "Don't use a specific version of pachyderm/pachd.")

	deployGoogle := &cobra.Command{
		Use:   "google <GCS bucket> <size of disk(s) (in GB)>",
		Short: "Deploy a Pachyderm cluster running on GCP.",
		Long: "Deploy a Pachyderm cluster running on GCP.\n" +
			"Arguments are:\n" +
			"  <GCS bucket>: A GCS bucket where Pachyderm will store PFS data.\n" +
			"  <GCE persistent disks>: A comma-separated list of GCE persistent disks, one per etcd node (see --etcd-nodes).\n" +
			"  <size of disks>: Size of GCE persistent disks in GB (assumed to all be the same).\n",
		Run: cmdutil.RunFixedArgs(2, func(args []string) (retErr error) {
			if metrics && !dev {
				metricsFn := _metrics.ReportAndFlushUserAction("Deploy")
				defer func(start time.Time) { metricsFn(start, retErr) }(time.Now())
			}
			volumeSize, err := strconv.Atoi(args[1])
			if err != nil {
				return fmt.Errorf("volume size needs to be an integer; instead got %v", args[1])
			}
			manifest := &bytes.Buffer{}
			opts.BlockCacheSize = "0G" // GCS is fast so we want to disable the block cache. See issue #1650
			if err = assets.WriteGoogleAssets(manifest, opts, args[0], volumeSize); err != nil {
				return err
			}
			return maybeKcCreate(dryRun, manifest)
		}),
	}

	deployCustom := &cobra.Command{
		Use:   "custom --persistent-disk <persistent disk backend> --object-store <object store backend> <persistent disk args> <object store args>",
		Short: "(in progress) Deploy a custom Pachyderm cluster configuration",
		Long: "(in progress) Deploy a custom Pachyderm cluster configuration.\n" +
			"If <object store backend> is \"s3\", then the arguments are:\n" +
			"    <volumes> <size of volumes (in GB)> <bucket> <id> <secret> <endpoint>\n",
		Run: pkgcobra.RunBoundedArgs(pkgcobra.Bounds{Min: 4, Max: 7}, func(args []string) (retErr error) {
			if metrics && !dev {
				metricsFn := _metrics.ReportAndFlushUserAction("Deploy")
				defer func(start time.Time) { metricsFn(start, retErr) }(time.Now())
			}
			manifest := &bytes.Buffer{}
			err := assets.WriteCustomAssets(manifest, opts, args, objectStoreBackend, persistentDiskBackend, secure)
			if err != nil {
				return err
			}
			return maybeKcCreate(dryRun, manifest)
		}),
	}
	deployCustom.Flags().BoolVarP(&secure, "secure", "s", false, "Enable secure access to a Minio server.")
	deployCustom.Flags().StringVar(&persistentDiskBackend, "persistent-disk", "aws",
		"(required) Backend providing persistent local volumes to stateful pods. "+
			"One of: aws, google, or azure.")
	deployCustom.Flags().StringVar(&objectStoreBackend, "object-store", "s3",
		"(required) Backend providing an object-storage API to pachyderm. One of: "+
			"s3, gcs, or azure-blob.")

	deployAmazon := &cobra.Command{
		Use:   "amazon <S3 bucket> <id> <secret> <token> <region> <size of volumes (in GB)>",
		Short: "Deploy a Pachyderm cluster running on AWS.",
		Long: "Deploy a Pachyderm cluster running on AWS. Arguments are:\n" +
			"  <S3 bucket>: An S3 bucket where Pachyderm will store PFS data.\n" +
			"  <id>, <secret>, <token>: Session token details, used for authorization. You can get these by running 'aws sts get-session-token'\n" +
			"  <region>: The aws region where pachyderm is being deployed (e.g. us-west-1)\n" +
			"  <size of volumes>: Size of EBS volumes, in GB (assumed to all be the same).\n",
		Run: cmdutil.RunFixedArgs(6, func(args []string) (retErr error) {
			if metrics && !dev {
				metricsFn := _metrics.ReportAndFlushUserAction("Deploy")
				defer func(start time.Time) { metricsFn(start, retErr) }(time.Now())
			}
			volumeSize, err := strconv.Atoi(args[5])
			if err != nil {
				return fmt.Errorf("volume size needs to be an integer; instead got %v", args[5])
			}
			manifest := &bytes.Buffer{}
			if err = assets.WriteAmazonAssets(manifest, opts, args[0], args[1], args[2], args[3], args[4], volumeSize); err != nil {
				return err
			}
			return maybeKcCreate(dryRun, manifest)
		}),
	}

	deployMicrosoft := &cobra.Command{
		Use:   "microsoft <container> <storage account name> <storage account key> <size of volumes (in GB)>",
		Short: "Deploy a Pachyderm cluster running on Microsoft Azure.",
		Long: "Deploy a Pachyderm cluster running on Microsoft Azure. Arguments are:\n" +
			"  <container>: An Azure container where Pachyderm will store PFS data.\n" +
			"  <size of volumes>: Size of persistent volumes, in GB (assumed to all be the same).\n",
		Run: cmdutil.RunFixedArgs(4, func(args []string) (retErr error) {
			if metrics && !dev {
				metricsFn := _metrics.ReportAndFlushUserAction("Deploy")
				defer func(start time.Time) { metricsFn(start, retErr) }(time.Now())
			}
			if _, err := base64.StdEncoding.DecodeString(args[2]); err != nil {
				return fmt.Errorf("storage-account-key needs to be base64 encoded; instead got '%v'", args[2])
			}
			if opts.EtcdVolume != "" {
				tempURI, err := url.ParseRequestURI(opts.EtcdVolume)
				if err != nil {
					return fmt.Errorf("Volume URI needs to be a well-formed URI; instead got '%v'", opts.EtcdVolume)
				}
				opts.EtcdVolume = tempURI.String()
			}
			volumeSize, err := strconv.Atoi(args[3])
			if err != nil {
				return fmt.Errorf("volume size needs to be an integer; instead got %v", args[3])
			}
			manifest := &bytes.Buffer{}
			if err = assets.WriteMicrosoftAssets(manifest, opts, args[0], args[1], args[2], volumeSize); err != nil {
				return err
			}
			return maybeKcCreate(dryRun, manifest)
		}),
	}

	deploy := &cobra.Command{
		Use:   "deploy amazon|google|microsoft|local|custom",
		Short: "Deploy a Pachyderm cluster.",
		Long:  "Deploy a Pachyderm cluster.",
		PersistentPreRun: cmdutil.Run(func([]string) error {
			opts = &assets.AssetOpts{
				PachdShards:    uint64(pachdShards),
				Version:        version.PrettyPrintVersion(version.Version),
				LogLevel:       logLevel,
				Metrics:        metrics,
				BlockCacheSize: blockCacheSize,
				EtcdNodes:      etcdNodes,
				EtcdVolume:     etcdVolume,
			}
			return nil
		}),
	}
	deploy.PersistentFlags().IntVar(&pachdShards, "shards", 16, "Number of Pachd nodes (stateless Pachyderm API servers).")
	deploy.PersistentFlags().IntVar(&etcdNodes, "dynamic-etcd-nodes", 0, "Deploy etcd as a StatefulSet with the given number of pods.  The persistent volumes used by these pods are provisioned dynamically.  Note that StatefulSet is currently a beta kubernetes feature, which might be unavailable in older versions of kubernetes.")
	deploy.PersistentFlags().StringVar(&etcdVolume, "static-etcd-volume", "", "Deploy etcd as a ReplicationController with one pod.  The pod uses the given persistent volume.")
	deploy.PersistentFlags().BoolVar(&dryRun, "dry-run", false, "Don't actually deploy pachyderm to Kubernetes, instead just print the manifest.")
	deploy.PersistentFlags().StringVar(&logLevel, "log-level", "info", "The level of log messages to print options are, from least to most verbose: \"error\", \"info\", \"debug\".")
	deploy.PersistentFlags().StringVar(&blockCacheSize, "block-cache-size", "5G", "Size of in-memory cache to use for blocks. "+
		"Size is specified in bytes, with allowed SI suffixes (M, K, G, Mi, Ki, Gi, etc).")
	deploy.AddCommand(deployLocal)
	deploy.AddCommand(deployAmazon)
	deploy.AddCommand(deployGoogle)
	deploy.AddCommand(deployMicrosoft)
	deploy.AddCommand(deployCustom)
	return deploy
}

// Cmds returns a cobra commands for deploying Pachyderm clusters.
func Cmds(noMetrics *bool) []*cobra.Command {
	deploy := DeployCmd(noMetrics)
	var all bool
	undeploy := &cobra.Command{
		Use:   "undeploy",
		Short: "Tear down a deployed Pachyderm cluster.",
		Long:  "Tear down a deployed Pachyderm cluster.",
		Run: cmdutil.RunFixedArgs(0, func(args []string) error {
			if all {
				fmt.Printf(`
By using the --all flag, you are going to delete everything, including the
persistent volumes where metadata is stored.  If your persistent volumes
were dynamically provisioned (i.e. if you used the "--dynamic-etcd-nodes"
flag), the underlying volumes will be removed, making metadata such repos,
commits, pipelines, and jobs unrecoverable. If your persistent volume was
manually provisioned (i.e. if you used the "--static-etcd-volume" flag), the
underlying volume will not be removed.

Are you sure you want to proceed? yN
`)
				r := bufio.NewReader(os.Stdin)
				bytes, err := r.ReadBytes('\n')
				if err != nil {
					return err
				}
				if !(bytes[0] == 'y' || bytes[0] == 'Y') {
					return nil
				}
			}
			io := cmdutil.IO{
				Stdout: os.Stdout,
				Stderr: os.Stderr,
			}
			if err := cmdutil.RunIO(io, "kubectl", "delete", "job", "-l", "suite=pachyderm"); err != nil {
				return err
			}
			if err := cmdutil.RunIO(io, "kubectl", "delete", "all", "-l", "suite=pachyderm"); err != nil {
				return err
			}
			if err := cmdutil.RunIO(io, "kubectl", "delete", "sa", "-l", "suite=pachyderm"); err != nil {
				return err
			}
			if err := cmdutil.RunIO(io, "kubectl", "delete", "secret", "-l", "suite=pachyderm"); err != nil {
				return err
			}
			if all {
				if err := cmdutil.RunIO(io, "kubectl", "delete", "storageclass", "-l", "suite=pachyderm"); err != nil {
					return err
				}
				if err := cmdutil.RunIO(io, "kubectl", "delete", "pvc", "-l", "suite=pachyderm"); err != nil {
					return err
				}
				if err := cmdutil.RunIO(io, "kubectl", "delete", "pv", "-l", "suite=pachyderm"); err != nil {
					return err
				}
			}
			return nil
		}),
	}
	undeploy.Flags().BoolVarP(&all, "all", "a", false, `
Delete everything, including the persistent volumes where metadata
is stored.  If your persistent volumes were dynamically provisioned (i.e. if
you used the "--dynamic-etcd-nodes" flag), the underlying volumes will be
removed, making metadata such repos, commits, pipelines, and jobs
unrecoverable. If your persistent volume was manually provisioned (i.e. if
you used the "--static-etcd-volume" flag), the underlying volume will not be
removed.`)
	return []*cobra.Command{deploy, undeploy}
}
<|endoftext|>


<commit_before>package models

import (
	"errors"
	"fmt"
	"time"

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

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

	// Name of the channel
	Name string `json:"name"`

	// Creator of the channel
	CreatorId int64 `json:"creatorId"`

	// Name of the group which channel is belong to
	Group string `json:"group"`

	// 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:"secretKey"`

	// Type of the channel
	Type string `json:"type"`

	// Privacy constant of the channel
	Privacy string `json:"privacy"`

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

	// Modification date of the channel
	UpdatedAt time.Time `json:"updatedAt"`
}

// 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"
	// Privacy
	Channel_TYPE_PUBLIC  = "public"
	Channel_TYPE_PRIVATE = "private"
	// Koding Group Name
	Channel_KODING_NAME = "koding-main"
)

func NewChannel() *Channel {
	return &Channel{
		Name:      "koding-main",
		CreatorId: 123,
		Group:     Channel_KODING_NAME,
		Purpose:   "string",
		SecretKey: "string",
		Type:      Channel_TYPE_GROUP,
		Privacy:   Channel_TYPE_PRIVATE,
	}
}

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

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

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

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

func (c *Channel) Self() bongo.Modellable {
	return c
}

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

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

	return bongo.B.Update(c)
}

func (c *Channel) Create() error {
	if c.Name == "" || c.Group == "" || c.Type == "" {
		return errors.New(fmt.Sprintf("Validation failed %s - %s", c.Name, c.Group, c.Group))
	}

	return bongo.B.Create(c)
}

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

func (c *Channel) One(selector map[string]interface{}) error {
	return bongo.B.One(c, c, selector)
}

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.Status == ChannelParticipant_STATUS_ACTIVE {
			return nil, errors.New(fmt.Sprintf("Account %s is already a participant of channel %s", cp.AccountId, cp.ChannelId))
		}
		cp.Status = ChannelParticipant_STATUS_ACTIVE
		if err := cp.Update(); err != nil {
			return nil, err
		}
		return cp, nil
	}

	cp.Status = 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.Status == ChannelParticipant_STATUS_LEFT {
		return nil
	}

	cp.Status = 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")
	}

	selector := map[string]interface{}{
		"channel_id": c.Id,
		"status":     ChannelParticipant_STATUS_ACTIVE,
	}

	pluck := map[string]interface{}{
		"account_id": true,
	}

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

	return participantIds, nil
}

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

	cml := NewChannelMessageList()
	cml.ChannelId = c.Id
	cml.MessageId = messageId

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

	return cml, nil
}
<commit_msg>Social: add plugins<commit_after>package models

import (
	"errors"
	"fmt"
	"time"

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

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

	// Name of the channel
	Name string `json:"name"`

	// Creator of the channel
	CreatorId int64 `json:"creatorId"`

	// Name of the group which channel is belong to
	Group string `json:"group"`

	// 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:"secretKey"`

	// Type of the channel
	Type string `json:"type"`

	// Privacy constant of the channel
	Privacy string `json:"privacy"`

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

	// Modification date of the channel
	UpdatedAt time.Time `json:"updatedAt"`
}

// 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"
	// Privacy
	Channel_TYPE_PUBLIC  = "public"
	Channel_TYPE_PRIVATE = "private"
	// Koding Group Name
	Channel_KODING_NAME = "koding-main"
)

func NewChannel() *Channel {
	return &Channel{
		Name:      "koding-main",
		CreatorId: 123,
		Group:     Channel_KODING_NAME,
		Purpose:   "string",
		SecretKey: "string",
		Type:      Channel_TYPE_GROUP,
		Privacy:   Channel_TYPE_PRIVATE,
	}
}

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

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

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

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

func (c *Channel) Self() bongo.Modellable {
	return c
}

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

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.Group == "" {
		return errors.New(fmt.Sprintf("Validation failed %s - %s", c.Name, c.Group))
	}

	return bongo.B.Update(c)
}

func (c *Channel) Create() error {
	if c.Name == "" || c.Group == "" || c.Type == "" {
		return errors.New(fmt.Sprintf("Validation failed %s - %s", c.Name, c.Group, c.Group))
	}

	return bongo.B.Create(c)
}

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

func (c *Channel) One(selector map[string]interface{}) error {
	return bongo.B.One(c, c, selector)
}

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.Status == ChannelParticipant_STATUS_ACTIVE {
			return nil, errors.New(fmt.Sprintf("Account %s is already a participant of channel %s", cp.AccountId, cp.ChannelId))
		}
		cp.Status = ChannelParticipant_STATUS_ACTIVE
		if err := cp.Update(); err != nil {
			return nil, err
		}
		return cp, nil
	}

	cp.Status = 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.Status == ChannelParticipant_STATUS_LEFT {
		return nil
	}

	cp.Status = 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")
	}

	selector := map[string]interface{}{
		"channel_id": c.Id,
		"status":     ChannelParticipant_STATUS_ACTIVE,
	}

	pluck := map[string]interface{}{
		"account_id": true,
	}

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

	return participantIds, nil
}

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

	cml := NewChannelMessageList()
	cml.ChannelId = c.Id
	cml.MessageId = messageId

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

	return cml, nil
}
<|endoftext|>


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

package tabletmanager

// This file handles the health check. It is enabled by passing a
// target_tablet_type command line parameter. The tablet will then go
// to the target tablet type if healthy, and to 'spare' if not.

import (
	"flag"
	"fmt"
	"reflect"
	"time"

	log "github.com/golang/glog"
	"github.com/youtube/vitess/go/timer"
	"github.com/youtube/vitess/go/vt/health"
	"github.com/youtube/vitess/go/vt/servenv"
	"github.com/youtube/vitess/go/vt/tabletmanager/actionnode"
	"github.com/youtube/vitess/go/vt/tabletserver"
	"github.com/youtube/vitess/go/vt/topo"
	"github.com/youtube/vitess/go/vt/topotools"
)

var (
	healthCheckInterval = flag.Duration("health_check_interval", 20*time.Second, "Interval between health checks")
	targetTabletType    = flag.String("target_tablet_type", "", "The tablet type we are thriving to be when healthy. When not healthy, we'll go to spare.")
	lockTimeout         = flag.Duration("lock_timeout", actionnode.DefaultLockTimeout, "lock time for wrangler/topo operations")
)

// HealthRecord records one run of the health checker
type HealthRecord struct {
	Error  error
	Result map[string]string
	Time   time.Time
}

// This returns a readable one word version of the health
func (r *HealthRecord) Class() string {
	switch {
	case r.Error != nil:
		return "unhealthy"
	case len(r.Result) > 0:
		return "unhappy"
	default:
		return "healthy"
	}
}

// IsDuplicate implements history.Deduplicable
func (r *HealthRecord) IsDuplicate(other interface{}) bool {
	rother, ok := other.(HealthRecord)
	if !ok {
		return false
	}
	return reflect.DeepEqual(r.Error, rother.Error) && reflect.DeepEqual(r.Result, rother.Result)
}

func (agent *ActionAgent) initHeathCheck() {
	if *targetTabletType == "" {
		log.Infof("No target_tablet_type specified, disabling any health check")
		return
	}

	log.Infof("Starting periodic health check every %v with target_tablet_type=%v", *healthCheckInterval, *targetTabletType)
	t := timer.NewTimer(*healthCheckInterval)
	servenv.OnTerm(func() {
		// When we enter lameduck mode, we want to not call
		// the health check any more. After this returns, we
		// are guaranteed to not call it.
		log.Info("Stopping periodic health check timer")
		t.Stop()

		// Now we can finish up and force ourselves to not healthy.
		agent.terminateHealthChecks(topo.TabletType(*targetTabletType), *lockTimeout)
	})
	t.Start(func() {
		agent.runHealthCheck(topo.TabletType(*targetTabletType), *lockTimeout)
	})
}

// runHealthCheck takes the action mutex, runs the health check,
// and if we need to change our state, do it.
// If we are the master, we don't change our type, healthy or not.
// If we are not the master, we change to spare if not healthy,
// or to the passed in targetTabletType if healthy.
//
// Note we only update the topo record if we need to, that is if our type or
// health details changed.
func (agent *ActionAgent) runHealthCheck(targetTabletType topo.TabletType, lockTimeout time.Duration) {
	agent.actionMutex.Lock()
	defer agent.actionMutex.Unlock()

	// read the current tablet record
	agent.mutex.Lock()
	tablet := agent._tablet
	agent.mutex.Unlock()

	// run the health check
	typeForHealthCheck := targetTabletType
	if tablet.Type == topo.TYPE_MASTER {
		typeForHealthCheck = topo.TYPE_MASTER
	}
	health, err := health.Run(typeForHealthCheck)

	// get the state of the query service
	isQueryServiceRunning := tabletserver.SqlQueryRpcService.GetState() == "SERVING"

	// Figure out if we should be running QueryService. If we should,
	// and we aren't, and we're otherwise healthy, try to start it
	if err == nil && topo.IsRunningQueryService(targetTabletType) && !isQueryServiceRunning {
		err = agent.allowQueries(tablet.Tablet)
	}

	// save the health record
	record := HealthRecord{
		Error:  err,
		Result: health,
		Time:   time.Now(),
	}
	agent.History.Add(record)

	// Update our topo.Server state, start with no change
	newTabletType := tablet.Type
	if err != nil {
		// The tablet is not healthy, let's see what we need to do
		if tablet.Type != targetTabletType {
			log.Infof("Tablet not healthy and in state %v, not changing it: %v", tablet.Type, err)
			return
		}

		// Note that if the query service is running, we may
		// need to stop it. The post-action callback will do
		// it, and it will be done after we change our state,
		// so it's the right order, let it do it.
		log.Infof("Tablet not healthy, converting it from %v to spare: %v", targetTabletType, err)
		newTabletType = topo.TYPE_SPARE
	} else {
		// We are healthy, maybe with health, see if we need
		// to update the record. We only change from spare to
		// our target type.
		if tablet.Type == topo.TYPE_SPARE {
			newTabletType = targetTabletType
		}
		if tablet.Type == newTabletType && tablet.IsHealthEqual(health) {
			// no change in health, not logging anything,
			// and we're done
			return
		}

		// we need to update our state
		log.Infof("Updating tablet record as healthy type %v -> %v with health details %v -> %v", tablet.Type, newTabletType, tablet.Health, health)
	}

	// Change the Type, update the health. Note we pass in a map
	// that's not nil, meaning if it's empty, we will clear it.
	if err := topotools.ChangeType(agent.TopoServer, tablet.Alias, newTabletType, health, true /*runHooks*/); err != nil {
		log.Infof("Error updating tablet record: %v", err)
		return
	}

	// Rebuild the serving graph in our cell, only if we're dealing with
	// a serving type
	if err := agent.rebuildShardIfNeeded(tablet, targetTabletType, lockTimeout); err != nil {
		log.Warningf("rebuildShardIfNeeded failed, not running post action callbacks: %v", err)
		return
	}

	// run the post action callbacks
	agent.afterAction("healthcheck", false /* reloadSchema */)
}

// terminateHealthChecks is called when we enter lame duck mode.
// We will clean up our state, and shut down query service.
// We only do something if we are in targetTabletType state, and then
// we just go to spare.
func (agent *ActionAgent) terminateHealthChecks(targetTabletType topo.TabletType, lockTimeout time.Duration) {
	agent.actionMutex.Lock()
	defer agent.actionMutex.Unlock()
	log.Info("agent.terminateHealthChecks is starting")

	// read the current tablet record
	agent.mutex.Lock()
	tablet := agent._tablet
	agent.mutex.Unlock()

	if tablet.Type != targetTabletType {
		log.Infof("Tablet in state %v, not changing it", tablet.Type)
		return
	}

	// Change the Type to spare, update the health. Note we pass in a map
	// that's not nil, meaning we will clear it.
	if err := topotools.ChangeType(agent.TopoServer, tablet.Alias, topo.TYPE_SPARE, make(map[string]string), true /*runHooks*/); err != nil {
		log.Infof("Error updating tablet record: %v", err)
		return
	}

	// Rebuild the serving graph in our cell, only if we're dealing with
	// a serving type
	if err := agent.rebuildShardIfNeeded(tablet, targetTabletType, lockTimeout); err != nil {
		log.Warningf("rebuildShardIfNeeded failed, not running post action callbacks: %v", err)
		return
	}

	// Run the post action callbacks (let them shutdown the query service)
	agent.afterAction("terminatehealthcheck", false /* reloadSchema */)
}

// rebuildShardIfNeeded will rebuild the serving graph if we need to
func (agent *ActionAgent) rebuildShardIfNeeded(tablet *topo.TabletInfo, targetTabletType topo.TabletType, lockTimeout time.Duration) error {
	if topo.IsInServingGraph(targetTabletType) {
		// TODO: interrupted may need to be a global one closed when we exit
		interrupted := make(chan struct{})

		if *topotools.UseSrvShardLocks {
			// no need to take the shard lock in this case
			if err := topotools.RebuildShard(agent.TopoServer, tablet.Keyspace, tablet.Shard, topotools.RebuildShardOptions{Cells: []string{tablet.Alias.Cell}, IgnorePartialResult: true}, lockTimeout, interrupted); err != nil {
				return fmt.Errorf("topotools.RebuildShard returned an error: %v", err)
			}
		} else {
			actionNode := actionnode.RebuildShard()
			lockPath, err := actionNode.LockShard(agent.TopoServer, tablet.Keyspace, tablet.Shard, lockTimeout, interrupted)
			if err != nil {
				return fmt.Errorf("cannot lock shard for rebuild: %v", err)
			}
			err = topotools.RebuildShard(agent.TopoServer, tablet.Keyspace, tablet.Shard, topotools.RebuildShardOptions{Cells: []string{tablet.Alias.Cell}, IgnorePartialResult: true}, lockTimeout, interrupted)
			err = actionNode.UnlockShard(agent.TopoServer, tablet.Keyspace, tablet.Shard, lockPath, err)
			if err != nil {
				return fmt.Errorf("UnlockShard returned an error: %v", err)
			}
		}
	}
	return nil
}
<commit_msg>Adding an external function IsrunningHealthCheck.<commit_after>// Copyright 2014, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package tabletmanager

// This file handles the health check. It is enabled by passing a
// target_tablet_type command line parameter. The tablet will then go
// to the target tablet type if healthy, and to 'spare' if not.

import (
	"flag"
	"fmt"
	"reflect"
	"time"

	log "github.com/golang/glog"
	"github.com/youtube/vitess/go/timer"
	"github.com/youtube/vitess/go/vt/health"
	"github.com/youtube/vitess/go/vt/servenv"
	"github.com/youtube/vitess/go/vt/tabletmanager/actionnode"
	"github.com/youtube/vitess/go/vt/tabletserver"
	"github.com/youtube/vitess/go/vt/topo"
	"github.com/youtube/vitess/go/vt/topotools"
)

var (
	healthCheckInterval = flag.Duration("health_check_interval", 20*time.Second, "Interval between health checks")
	targetTabletType    = flag.String("target_tablet_type", "", "The tablet type we are thriving to be when healthy. When not healthy, we'll go to spare.")
	lockTimeout         = flag.Duration("lock_timeout", actionnode.DefaultLockTimeout, "lock time for wrangler/topo operations")
)

// HealthRecord records one run of the health checker
type HealthRecord struct {
	Error  error
	Result map[string]string
	Time   time.Time
}

// This returns a readable one word version of the health
func (r *HealthRecord) Class() string {
	switch {
	case r.Error != nil:
		return "unhealthy"
	case len(r.Result) > 0:
		return "unhappy"
	default:
		return "healthy"
	}
}

// IsDuplicate implements history.Deduplicable
func (r *HealthRecord) IsDuplicate(other interface{}) bool {
	rother, ok := other.(HealthRecord)
	if !ok {
		return false
	}
	return reflect.DeepEqual(r.Error, rother.Error) && reflect.DeepEqual(r.Result, rother.Result)
}

func (agent *ActionAgent) IsRunningHealthCheck() bool {
	return *targetTabletType != ""
}

func (agent *ActionAgent) initHeathCheck() {
	if !agent.IsRunningHealthCheck() {
		log.Infof("No target_tablet_type specified, disabling any health check")
		return
	}

	log.Infof("Starting periodic health check every %v with target_tablet_type=%v", *healthCheckInterval, *targetTabletType)
	t := timer.NewTimer(*healthCheckInterval)
	servenv.OnTerm(func() {
		// When we enter lameduck mode, we want to not call
		// the health check any more. After this returns, we
		// are guaranteed to not call it.
		log.Info("Stopping periodic health check timer")
		t.Stop()

		// Now we can finish up and force ourselves to not healthy.
		agent.terminateHealthChecks(topo.TabletType(*targetTabletType), *lockTimeout)
	})
	t.Start(func() {
		agent.runHealthCheck(topo.TabletType(*targetTabletType), *lockTimeout)
	})
}

// runHealthCheck takes the action mutex, runs the health check,
// and if we need to change our state, do it.
// If we are the master, we don't change our type, healthy or not.
// If we are not the master, we change to spare if not healthy,
// or to the passed in targetTabletType if healthy.
//
// Note we only update the topo record if we need to, that is if our type or
// health details changed.
func (agent *ActionAgent) runHealthCheck(targetTabletType topo.TabletType, lockTimeout time.Duration) {
	agent.actionMutex.Lock()
	defer agent.actionMutex.Unlock()

	// read the current tablet record
	agent.mutex.Lock()
	tablet := agent._tablet
	agent.mutex.Unlock()

	// run the health check
	typeForHealthCheck := targetTabletType
	if tablet.Type == topo.TYPE_MASTER {
		typeForHealthCheck = topo.TYPE_MASTER
	}
	health, err := health.Run(typeForHealthCheck)

	// get the state of the query service
	isQueryServiceRunning := tabletserver.SqlQueryRpcService.GetState() == "SERVING"

	// Figure out if we should be running QueryService. If we should,
	// and we aren't, and we're otherwise healthy, try to start it
	if err == nil && topo.IsRunningQueryService(targetTabletType) && !isQueryServiceRunning {
		err = agent.allowQueries(tablet.Tablet)
	}

	// save the health record
	record := HealthRecord{
		Error:  err,
		Result: health,
		Time:   time.Now(),
	}
	agent.History.Add(record)

	// Update our topo.Server state, start with no change
	newTabletType := tablet.Type
	if err != nil {
		// The tablet is not healthy, let's see what we need to do
		if tablet.Type != targetTabletType {
			log.Infof("Tablet not healthy and in state %v, not changing it: %v", tablet.Type, err)
			return
		}

		// Note that if the query service is running, we may
		// need to stop it. The post-action callback will do
		// it, and it will be done after we change our state,
		// so it's the right order, let it do it.
		log.Infof("Tablet not healthy, converting it from %v to spare: %v", targetTabletType, err)
		newTabletType = topo.TYPE_SPARE
	} else {
		// We are healthy, maybe with health, see if we need
		// to update the record. We only change from spare to
		// our target type.
		if tablet.Type == topo.TYPE_SPARE {
			newTabletType = targetTabletType
		}
		if tablet.Type == newTabletType && tablet.IsHealthEqual(health) {
			// no change in health, not logging anything,
			// and we're done
			return
		}

		// we need to update our state
		log.Infof("Updating tablet record as healthy type %v -> %v with health details %v -> %v", tablet.Type, newTabletType, tablet.Health, health)
	}

	// Change the Type, update the health. Note we pass in a map
	// that's not nil, meaning if it's empty, we will clear it.
	if err := topotools.ChangeType(agent.TopoServer, tablet.Alias, newTabletType, health, true /*runHooks*/); err != nil {
		log.Infof("Error updating tablet record: %v", err)
		return
	}

	// Rebuild the serving graph in our cell, only if we're dealing with
	// a serving type
	if err := agent.rebuildShardIfNeeded(tablet, targetTabletType, lockTimeout); err != nil {
		log.Warningf("rebuildShardIfNeeded failed, not running post action callbacks: %v", err)
		return
	}

	// run the post action callbacks
	agent.afterAction("healthcheck", false /* reloadSchema */)
}

// terminateHealthChecks is called when we enter lame duck mode.
// We will clean up our state, and shut down query service.
// We only do something if we are in targetTabletType state, and then
// we just go to spare.
func (agent *ActionAgent) terminateHealthChecks(targetTabletType topo.TabletType, lockTimeout time.Duration) {
	agent.actionMutex.Lock()
	defer agent.actionMutex.Unlock()
	log.Info("agent.terminateHealthChecks is starting")

	// read the current tablet record
	agent.mutex.Lock()
	tablet := agent._tablet
	agent.mutex.Unlock()

	if tablet.Type != targetTabletType {
		log.Infof("Tablet in state %v, not changing it", tablet.Type)
		return
	}

	// Change the Type to spare, update the health. Note we pass in a map
	// that's not nil, meaning we will clear it.
	if err := topotools.ChangeType(agent.TopoServer, tablet.Alias, topo.TYPE_SPARE, make(map[string]string), true /*runHooks*/); err != nil {
		log.Infof("Error updating tablet record: %v", err)
		return
	}

	// Rebuild the serving graph in our cell, only if we're dealing with
	// a serving type
	if err := agent.rebuildShardIfNeeded(tablet, targetTabletType, lockTimeout); err != nil {
		log.Warningf("rebuildShardIfNeeded failed, not running post action callbacks: %v", err)
		return
	}

	// Run the post action callbacks (let them shutdown the query service)
	agent.afterAction("terminatehealthcheck", false /* reloadSchema */)
}

// rebuildShardIfNeeded will rebuild the serving graph if we need to
func (agent *ActionAgent) rebuildShardIfNeeded(tablet *topo.TabletInfo, targetTabletType topo.TabletType, lockTimeout time.Duration) error {
	if topo.IsInServingGraph(targetTabletType) {
		// TODO: interrupted may need to be a global one closed when we exit
		interrupted := make(chan struct{})

		if *topotools.UseSrvShardLocks {
			// no need to take the shard lock in this case
			if err := topotools.RebuildShard(agent.TopoServer, tablet.Keyspace, tablet.Shard, topotools.RebuildShardOptions{Cells: []string{tablet.Alias.Cell}, IgnorePartialResult: true}, lockTimeout, interrupted); err != nil {
				return fmt.Errorf("topotools.RebuildShard returned an error: %v", err)
			}
		} else {
			actionNode := actionnode.RebuildShard()
			lockPath, err := actionNode.LockShard(agent.TopoServer, tablet.Keyspace, tablet.Shard, lockTimeout, interrupted)
			if err != nil {
				return fmt.Errorf("cannot lock shard for rebuild: %v", err)
			}
			err = topotools.RebuildShard(agent.TopoServer, tablet.Keyspace, tablet.Shard, topotools.RebuildShardOptions{Cells: []string{tablet.Alias.Cell}, IgnorePartialResult: true}, lockTimeout, interrupted)
			err = actionNode.UnlockShard(agent.TopoServer, tablet.Keyspace, tablet.Shard, lockPath, err)
			if err != nil {
				return fmt.Errorf("UnlockShard returned an error: %v", err)
			}
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package ds

import (
	"net/url"
	"strconv"
	"strings"

	"github.com/sselph/scraper/ss"
)

// SS is the source for ScreenScraper
type SS struct {
	HM     *HashMap
	Hasher *Hasher
	Dev    ss.DevInfo
	User   ss.UserInfo
	Lang   []LangType
	Region []RegionType
	Width  int
}

// GetID implements DS
func (s *SS) GetID(p string) (string, error) {
	return s.Hasher.Hash(p)
}

// GetName implements DS
func (s *SS) GetName(p string) string {
	h, err := s.Hasher.Hash(p)
	if err != nil {
		return ""
	}
	name, ok := s.HM.Name(h)
	if !ok {
		return ""
	}
	return name
}

// ssBoxURL gets the URL for BoxArt for the preferred region.
func ssBoxURL(media ss.GameMedia, regions []RegionType, width int) string {
	for _, r := range regions {
		switch r {
		case RegionUS:
			if media.BoxUS != "" {
				return ssImgURL(media.BoxUS, width)
			}
		case RegionEU:
			if media.BoxEU != "" {
				return ssImgURL(media.BoxEU, width)
			}
		case RegionFR:
			if media.BoxFR != "" {
				return ssImgURL(media.BoxFR, width)
			}
		case RegionJP:
			if media.BoxJP != "" {
				return ssImgURL(media.BoxJP, width)
			}
		case RegionXX:
			if media.BoxXX != "" {
				return ssImgURL(media.BoxXX, width)
			}
		}
	}
	return ""
}

// ss3DBoxURL gets the URL for 3D-BoxArt for the preferred region.
func ss3DBoxURL(media ss.GameMedia, regions []RegionType, width int) string {
	for _, r := range regions {
		switch r {
		case RegionUS:
			if media.Box3DUS != "" {
				return ssImgURL(media.Box3DUS, width)
			}
		case RegionEU:
			if media.Box3DEU != "" {
				return ssImgURL(media.Box3DEU, width)
			}
		case RegionFR:
			if media.Box3DFR != "" {
				return ssImgURL(media.Box3DFR, width)
			}
		case RegionJP:
			if media.Box3DJP != "" {
				return ssImgURL(media.Box3DJP, width)
			}
		case RegionXX:
			if media.Box3DXX != "" {
				return ssImgURL(media.Box3DXX, width)
			}
		}
	}
	return ""
}

// ssDate gets the date for the preferred region.
func ssDate(dates ss.GameDates, regions []RegionType) string {
	for _, r := range regions {
		switch r {
		case RegionUS:
			if dates.US != "" {
				return toXMLDate(dates.US)
			}
		case RegionEU:
			if dates.EU != "" {
				return toXMLDate(dates.EU)
			}
		case RegionFR:
			if dates.FR != "" {
				return toXMLDate(dates.FR)
			}
		case RegionJP:
			if dates.JP != "" {
				return toXMLDate(dates.JP)
			}
		case RegionXX:
			if dates.XX != "" {
				return toXMLDate(dates.XX)
			}
		}
	}
	return ""
}

// ssDesc gets the desc for the preferred language.
func ssDesc(desc ss.GameDesc, lang []LangType) string {
	for _, l := range lang {
		switch l {
		case LangEN:
			if desc.EN != "" {
				return desc.EN
			}
		case LangFR:
			if desc.FR != "" {
				return desc.FR
			}
		case LangES:
			if desc.ES != "" {
				return desc.ES
			}
		case LangDE:
			if desc.DE != "" {
				return desc.DE
			}
		case LangPT:
			if desc.PT != "" {
				return desc.PT
			}
		}
	}
	return ""
}

// ssName gets the name for the preferred language, else the original.
func ssName(name ss.GameNames, lang []LangType) string {
	for _, l := range lang {
		switch l {
		case LangEN:
			if name.EN != "" {
				return name.EN
			}
		case LangFR:
			if name.FR != "" {
				return name.FR
			}
		case LangES:
			if name.ES != "" {
				return name.ES
			}
		case LangDE:
			if name.DE != "" {
				return name.DE
			}
		case LangPT:
			if name.PT != "" {
				return name.PT
			}
		}
	}
	return name.Original
}

// ssGenre gets the genre for the preferred language.
func ssGenre(genre ss.GameGenre, lang []LangType) string {
	for _, l := range lang {
		switch l {
		case LangEN:
			if genre.EN != nil {
				return strings.Join(genre.EN, ",")
			}
		case LangFR:
			if genre.FR != nil {
				return strings.Join(genre.FR, ",")
			}
		case LangES:
			if genre.ES != nil {
				return strings.Join(genre.ES, ",")
			}
		case LangDE:
			if genre.DE != nil {
				return strings.Join(genre.DE, ",")
			}
		case LangPT:
			if genre.PT != nil {
				return strings.Join(genre.PT, ",")
			}
		}
	}
	return ""
}

// romRegion extracts the region from the No-Intro name.
func romRegion(n string) RegionType {
	for {
		s := strings.IndexRune(n, '(')
		if s == -1 {
			return RegionUnknown
		}
		e := strings.IndexRune(n[s:], ')')
		if e == -1 {
			return RegionUnknown
		}
		switch n[s : s+e+1] {
		case "(USA)":
			return RegionUS
		case "(Europe)":
			return RegionEU
		case "(Japan)":
			return RegionJP
		case "(France)":
			return RegionFR
		case "(World)":
			return RegionUnknown
		}
		n = n[s+e+1:]
	}
}

// GetGame implements DS
func (s *SS) GetGame(id string) (*Game, error) {
	req := ss.GameInfoReq{SHA1: id}
	resp, err := ss.GameInfo(s.Dev, s.User, req)
	if err != nil {
		if err == ss.ErrNotFound {
			return nil, ErrNotFound
		}
		return nil, err
	}
	game := resp.Game

	region := RegionUnknown
	if name, ok := s.HM.Name(id); ok {
		region = romRegion(name)
	}
	var regions []RegionType
	if region != RegionUnknown {
		regions = append([]RegionType{region}, s.Region...)
	} else {
		regions = s.Region
	}

	ret := NewGame()
	if game.Media.ScreenShot != "" {
		ret.Images[ImgScreen] = ssImgURL(game.Media.ScreenShot, s.Width)
	}
	if imgURL := ssBoxURL(game.Media, regions, s.Width); imgURL != "" {
		ret.Images[ImgBoxart] = imgURL
	}
	if imgURL := ss3DBoxURL(game.Media, regions, s.Width); imgURL != "" {
		ret.Images[ImgBoxart3D] = imgURL
	}
	ret.ID = strconv.Itoa(game.ID)
	ret.Source = "screenscraper.fr"
	ret.GameTitle = game.Names.Original
	ret.Overview = ssDesc(game.Desc, s.Lang)
	ret.Rating = game.Rating / 20.0
	ret.Developer = game.Developer
	ret.Publisher = game.Publisher
	ret.Genre = ssGenre(game.Genre, s.Lang)
	ret.ReleaseDate = ssDate(game.Dates, s.Region)
	if strings.ContainsRune(game.Players, '-') {
		x := strings.Split(game.Players, "-")
		game.Players = x[len(x)-1]
	}
	p, err := strconv.ParseInt(strings.TrimRight(game.Players, "+"), 10, 32)
	if err == nil {
		ret.Players = p
	}
	if ret.Overview == "" && ret.ReleaseDate == "" && ret.Developer == "" && ret.Publisher == "" && ret.Images[ImgBoxart] == "" && ret.Images[ImgScreen] == "" {
		return nil, ErrNotFound
	}
	return ret, nil
}

// ssImgURL parses the URL and adds the maxwidth.
func ssImgURL(img string, width int) string {
	if width <= 0 {
		return img
	}
	u, err := url.Parse(img)
	if err != nil {
		return img
	}
	v := u.Query()
	v.Set("maxwidth", strconv.Itoa(width))
	u.RawQuery = v.Encode()
	return u.String()
}
<commit_msg>Reject Screensaver with empty overview<commit_after>package ds

import (
	"net/url"
	"strconv"
	"strings"

	"github.com/sselph/scraper/ss"
)

// SS is the source for ScreenScraper
type SS struct {
	HM     *HashMap
	Hasher *Hasher
	Dev    ss.DevInfo
	User   ss.UserInfo
	Lang   []LangType
	Region []RegionType
	Width  int
}

// GetID implements DS
func (s *SS) GetID(p string) (string, error) {
	return s.Hasher.Hash(p)
}

// GetName implements DS
func (s *SS) GetName(p string) string {
	h, err := s.Hasher.Hash(p)
	if err != nil {
		return ""
	}
	name, ok := s.HM.Name(h)
	if !ok {
		return ""
	}
	return name
}

// ssBoxURL gets the URL for BoxArt for the preferred region.
func ssBoxURL(media ss.GameMedia, regions []RegionType, width int) string {
	for _, r := range regions {
		switch r {
		case RegionUS:
			if media.BoxUS != "" {
				return ssImgURL(media.BoxUS, width)
			}
		case RegionEU:
			if media.BoxEU != "" {
				return ssImgURL(media.BoxEU, width)
			}
		case RegionFR:
			if media.BoxFR != "" {
				return ssImgURL(media.BoxFR, width)
			}
		case RegionJP:
			if media.BoxJP != "" {
				return ssImgURL(media.BoxJP, width)
			}
		case RegionXX:
			if media.BoxXX != "" {
				return ssImgURL(media.BoxXX, width)
			}
		}
	}
	return ""
}

// ss3DBoxURL gets the URL for 3D-BoxArt for the preferred region.
func ss3DBoxURL(media ss.GameMedia, regions []RegionType, width int) string {
	for _, r := range regions {
		switch r {
		case RegionUS:
			if media.Box3DUS != "" {
				return ssImgURL(media.Box3DUS, width)
			}
		case RegionEU:
			if media.Box3DEU != "" {
				return ssImgURL(media.Box3DEU, width)
			}
		case RegionFR:
			if media.Box3DFR != "" {
				return ssImgURL(media.Box3DFR, width)
			}
		case RegionJP:
			if media.Box3DJP != "" {
				return ssImgURL(media.Box3DJP, width)
			}
		case RegionXX:
			if media.Box3DXX != "" {
				return ssImgURL(media.Box3DXX, width)
			}
		}
	}
	return ""
}

// ssDate gets the date for the preferred region.
func ssDate(dates ss.GameDates, regions []RegionType) string {
	for _, r := range regions {
		switch r {
		case RegionUS:
			if dates.US != "" {
				return toXMLDate(dates.US)
			}
		case RegionEU:
			if dates.EU != "" {
				return toXMLDate(dates.EU)
			}
		case RegionFR:
			if dates.FR != "" {
				return toXMLDate(dates.FR)
			}
		case RegionJP:
			if dates.JP != "" {
				return toXMLDate(dates.JP)
			}
		case RegionXX:
			if dates.XX != "" {
				return toXMLDate(dates.XX)
			}
		}
	}
	return ""
}

// ssDesc gets the desc for the preferred language.
func ssDesc(desc ss.GameDesc, lang []LangType) string {
	for _, l := range lang {
		switch l {
		case LangEN:
			if desc.EN != "" {
				return desc.EN
			}
		case LangFR:
			if desc.FR != "" {
				return desc.FR
			}
		case LangES:
			if desc.ES != "" {
				return desc.ES
			}
		case LangDE:
			if desc.DE != "" {
				return desc.DE
			}
		case LangPT:
			if desc.PT != "" {
				return desc.PT
			}
		}
	}
	return ""
}

// ssName gets the name for the preferred language, else the original.
func ssName(name ss.GameNames, lang []LangType) string {
	for _, l := range lang {
		switch l {
		case LangEN:
			if name.EN != "" {
				return name.EN
			}
		case LangFR:
			if name.FR != "" {
				return name.FR
			}
		case LangES:
			if name.ES != "" {
				return name.ES
			}
		case LangDE:
			if name.DE != "" {
				return name.DE
			}
		case LangPT:
			if name.PT != "" {
				return name.PT
			}
		}
	}
	return name.Original
}

// ssGenre gets the genre for the preferred language.
func ssGenre(genre ss.GameGenre, lang []LangType) string {
	for _, l := range lang {
		switch l {
		case LangEN:
			if genre.EN != nil {
				return strings.Join(genre.EN, ",")
			}
		case LangFR:
			if genre.FR != nil {
				return strings.Join(genre.FR, ",")
			}
		case LangES:
			if genre.ES != nil {
				return strings.Join(genre.ES, ",")
			}
		case LangDE:
			if genre.DE != nil {
				return strings.Join(genre.DE, ",")
			}
		case LangPT:
			if genre.PT != nil {
				return strings.Join(genre.PT, ",")
			}
		}
	}
	return ""
}

// romRegion extracts the region from the No-Intro name.
func romRegion(n string) RegionType {
	for {
		s := strings.IndexRune(n, '(')
		if s == -1 {
			return RegionUnknown
		}
		e := strings.IndexRune(n[s:], ')')
		if e == -1 {
			return RegionUnknown
		}
		switch n[s : s+e+1] {
		case "(USA)":
			return RegionUS
		case "(Europe)":
			return RegionEU
		case "(Japan)":
			return RegionJP
		case "(France)":
			return RegionFR
		case "(World)":
			return RegionUnknown
		}
		n = n[s+e+1:]
	}
}

// GetGame implements DS
func (s *SS) GetGame(id string) (*Game, error) {
	req := ss.GameInfoReq{SHA1: id}
	resp, err := ss.GameInfo(s.Dev, s.User, req)
	if err != nil {
		if err == ss.ErrNotFound {
			return nil, ErrNotFound
		}
		return nil, err
	}
	game := resp.Game

	region := RegionUnknown
	if name, ok := s.HM.Name(id); ok {
		region = romRegion(name)
	}
	var regions []RegionType
	if region != RegionUnknown {
		regions = append([]RegionType{region}, s.Region...)
	} else {
		regions = s.Region
	}

	ret := NewGame()
	if game.Media.ScreenShot != "" {
		ret.Images[ImgScreen] = ssImgURL(game.Media.ScreenShot, s.Width)
	}
	if imgURL := ssBoxURL(game.Media, regions, s.Width); imgURL != "" {
		ret.Images[ImgBoxart] = imgURL
	}
	if imgURL := ss3DBoxURL(game.Media, regions, s.Width); imgURL != "" {
		ret.Images[ImgBoxart3D] = imgURL
	}
	ret.ID = strconv.Itoa(game.ID)
	ret.Source = "screenscraper.fr"
	ret.GameTitle = game.Names.Original
	ret.Overview = ssDesc(game.Desc, s.Lang)
	ret.Rating = game.Rating / 20.0
	ret.Developer = game.Developer
	ret.Publisher = game.Publisher
	ret.Genre = ssGenre(game.Genre, s.Lang)
	ret.ReleaseDate = ssDate(game.Dates, s.Region)
	if strings.ContainsRune(game.Players, '-') {
		x := strings.Split(game.Players, "-")
		game.Players = x[len(x)-1]
	}
	p, err := strconv.ParseInt(strings.TrimRight(game.Players, "+"), 10, 32)
	if err == nil {
		ret.Players = p
	}
	if ret.Overview == "" || ret.ReleaseDate == "" || ret.Developer == "" || ret.Publisher == "" || ret.Images[ImgBoxart] == "" || ret.Images[ImgScreen] == "" {
		return nil, ErrNotFound
	}
	return ret, nil
}

// ssImgURL parses the URL and adds the maxwidth.
func ssImgURL(img string, width int) string {
	if width <= 0 {
		return img
	}
	u, err := url.Parse(img)
	if err != nil {
		return img
	}
	v := u.Query()
	v.Set("maxwidth", strconv.Itoa(width))
	u.RawQuery = v.Encode()
	return u.String()
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
// See License.txt for license information.

package utils

import (
	"os"
	"testing"
)

func TestConfig(t *testing.T) {
	LoadConfig("config.json")
}

func TestEnvOverride(t *testing.T) {
	os.Setenv("MATTERMOST_DOMAIN", "testdomain.com")

	LoadConfig("config_docker.json")
	if Cfg.ServiceSettings.Domain != "testdomain.com" {
		t.Fail()
	}

	LoadConfig("config.json")
	if Cfg.ServiceSettings.Domain == "testdomain.com" {
		t.Fail()
	}
}
<commit_msg>Fixing build<commit_after>// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
// See License.txt for license information.

package utils

import (
	"os"
	"testing"
)

func TestConfig(t *testing.T) {
	LoadConfig("config.json")
}

/*
func TestEnvOverride(t *testing.T) {
	os.Setenv("MATTERMOST_DOMAIN", "testdomain.com")

	LoadConfig("config_docker.json")
	if Cfg.ServiceSettings.Domain != "testdomain.com" {
		t.Fail()
	}

	LoadConfig("config.json")
	if Cfg.ServiceSettings.Domain == "testdomain.com" {
		t.Fail()
	}
}
*/
<|endoftext|>


<commit_before>// Copyright 2014 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package sysfs

import (
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"strconv"
	"strings"
)

const (
	blockDir = "/sys/block"
	cacheDir = "/sys/devices/system/cpu/cpu"
	netDir   = "/sys/class/net"
	dmiDir   = "/sys/class/dmi"
)

type CacheInfo struct {
	// size in bytes
	Size uint64
	// cache type - instruction, data, unified
	Type string
	// distance from cpus in a multi-level hierarchy
	Level int
	// number of cpus that can access this cache.
	Cpus int
}

// Abstracts the lowest level calls to sysfs.
type SysFs interface {
	// Get directory information for available block devices.
	GetBlockDevices() ([]os.FileInfo, error)
	// Get Size of a given block device.
	GetBlockDeviceSize(string) (string, error)
	// Get scheduler type for the block device.
	GetBlockDeviceScheduler(string) (string, error)
	// Get device major:minor number string.
	GetBlockDeviceNumbers(string) (string, error)

	GetNetworkDevices() ([]os.FileInfo, error)
	GetNetworkAddress(string) (string, error)
	GetNetworkMtu(string) (string, error)
	GetNetworkSpeed(string) (string, error)
	GetNetworkStatValue(dev string, stat string) (uint64, error)

	// Get directory information for available caches accessible to given cpu.
	GetCaches(id int) ([]os.FileInfo, error)
	// Get information for a cache accessible from the given cpu.
	GetCacheInfo(cpu int, cache string) (CacheInfo, error)

	GetSystemUUID() (string, error)
}

type realSysFs struct{}

func NewRealSysFs() (SysFs, error) {
	return &realSysFs{}, nil
}

func (self *realSysFs) GetBlockDevices() ([]os.FileInfo, error) {
	return ioutil.ReadDir(blockDir)
}

func (self *realSysFs) GetBlockDeviceNumbers(name string) (string, error) {
	dev, err := ioutil.ReadFile(path.Join(blockDir, name, "/dev"))
	if err != nil {
		return "", err
	}
	return string(dev), nil
}

func (self *realSysFs) GetBlockDeviceScheduler(name string) (string, error) {
	sched, err := ioutil.ReadFile(path.Join(blockDir, name, "/queue/scheduler"))
	if err != nil {
		return "", err
	}
	return string(sched), nil
}

func (self *realSysFs) GetBlockDeviceSize(name string) (string, error) {
	size, err := ioutil.ReadFile(path.Join(blockDir, name, "/size"))
	if err != nil {
		return "", err
	}
	return string(size), nil
}

func (self *realSysFs) GetNetworkDevices() ([]os.FileInfo, error) {
	files, err := ioutil.ReadDir(netDir)
	if err != nil {
		return nil, err
	}

	// Filter out non-directory & non-symlink files
	var dirs []os.FileInfo
	for _, f := range files {
		if f.Mode()|os.ModeSymlink != 0 {
			f, err = os.Stat(path.Join(netDir, f.Name()))
			if err != nil {
				continue
			}
		}
		if f.IsDir() {
			dirs = append(dirs, f)
		}
	}
	return dirs, nil
}

func (self *realSysFs) GetNetworkAddress(name string) (string, error) {
	address, err := ioutil.ReadFile(path.Join(netDir, name, "/address"))
	if err != nil {
		return "", err
	}
	return string(address), nil
}

func (self *realSysFs) GetNetworkMtu(name string) (string, error) {
	mtu, err := ioutil.ReadFile(path.Join(netDir, name, "/mtu"))
	if err != nil {
		return "", err
	}
	return string(mtu), nil
}

func (self *realSysFs) GetNetworkSpeed(name string) (string, error) {
	speed, err := ioutil.ReadFile(path.Join(netDir, name, "/speed"))
	if err != nil {
		return "", err
	}
	return string(speed), nil
}

func (self *realSysFs) GetNetworkStatValue(dev string, stat string) (uint64, error) {
	statPath := path.Join(netDir, dev, "/statistics", stat)
	out, err := ioutil.ReadFile(statPath)
	if err != nil {
		return 0, fmt.Errorf("failed to read stat from %q for device %q", statPath, dev)
	}
	var s uint64
	n, err := fmt.Sscanf(string(out), "%d", &s)
	if err != nil || n != 1 {
		return 0, fmt.Errorf("could not parse value from %q for file %s", string(out), statPath)
	}
	return s, nil
}

func (self *realSysFs) GetCaches(id int) ([]os.FileInfo, error) {
	cpuPath := fmt.Sprintf("%s%d/cache", cacheDir, id)
	return ioutil.ReadDir(cpuPath)
}

func bitCount(i uint64) (count int) {
	for i != 0 {
		if i&1 == 1 {
			count++
		}
		i >>= 1
	}
	return
}

func getCpuCount(cache string) (count int, err error) {
	out, err := ioutil.ReadFile(path.Join(cache, "/shared_cpu_map"))
	if err != nil {
		return 0, err
	}
	masks := strings.Split(string(out), ",")
	for _, mask := range masks {
		// convert hex string to uint64
		m, err := strconv.ParseUint(strings.TrimSpace(mask), 16, 64)
		if err != nil {
			return 0, fmt.Errorf("failed to parse cpu map %q: %v", string(out), err)
		}
		count += bitCount(m)
	}
	return
}

func (self *realSysFs) GetCacheInfo(id int, name string) (CacheInfo, error) {
	cachePath := fmt.Sprintf("%s%d/cache/%s", cacheDir, id, name)
	out, err := ioutil.ReadFile(path.Join(cachePath, "/size"))
	if err != nil {
		return CacheInfo{}, err
	}
	var size uint64
	n, err := fmt.Sscanf(string(out), "%dK", &size)
	if err != nil || n != 1 {
		return CacheInfo{}, err
	}
	// convert to bytes
	size = size * 1024
	out, err = ioutil.ReadFile(path.Join(cachePath, "/level"))
	if err != nil {
		return CacheInfo{}, err
	}
	var level int
	n, err = fmt.Sscanf(string(out), "%d", &level)
	if err != nil || n != 1 {
		return CacheInfo{}, err
	}

	out, err = ioutil.ReadFile(path.Join(cachePath, "/type"))
	if err != nil {
		return CacheInfo{}, err
	}
	cacheType := strings.TrimSpace(string(out))
	cpuCount, err := getCpuCount(cachePath)
	if err != nil {
		return CacheInfo{}, err
	}
	return CacheInfo{
		Size:  size,
		Level: level,
		Type:  cacheType,
		Cpus:  cpuCount,
	}, nil
}

func (self *realSysFs) GetSystemUUID() (string, error) {
	id, err := ioutil.ReadFile(path.Join(dmiDir, "id", "product_uuid"))
	if err != nil {
		return "", err
	}
	return strings.TrimSpace(string(id)), nil
}
<commit_msg>Handle system UUID retrieval for Power(ppc64) Systems<commit_after>// Copyright 2014 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package sysfs

import (
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"strconv"
	"strings"
)

const (
	blockDir   = "/sys/block"
	cacheDir   = "/sys/devices/system/cpu/cpu"
	netDir     = "/sys/class/net"
	dmiDir     = "/sys/class/dmi"
	ppcDevTree = "/proc/device-tree"
)

type CacheInfo struct {
	// size in bytes
	Size uint64
	// cache type - instruction, data, unified
	Type string
	// distance from cpus in a multi-level hierarchy
	Level int
	// number of cpus that can access this cache.
	Cpus int
}

// Abstracts the lowest level calls to sysfs.
type SysFs interface {
	// Get directory information for available block devices.
	GetBlockDevices() ([]os.FileInfo, error)
	// Get Size of a given block device.
	GetBlockDeviceSize(string) (string, error)
	// Get scheduler type for the block device.
	GetBlockDeviceScheduler(string) (string, error)
	// Get device major:minor number string.
	GetBlockDeviceNumbers(string) (string, error)

	GetNetworkDevices() ([]os.FileInfo, error)
	GetNetworkAddress(string) (string, error)
	GetNetworkMtu(string) (string, error)
	GetNetworkSpeed(string) (string, error)
	GetNetworkStatValue(dev string, stat string) (uint64, error)

	// Get directory information for available caches accessible to given cpu.
	GetCaches(id int) ([]os.FileInfo, error)
	// Get information for a cache accessible from the given cpu.
	GetCacheInfo(cpu int, cache string) (CacheInfo, error)

	GetSystemUUID() (string, error)
}

type realSysFs struct{}

func NewRealSysFs() (SysFs, error) {
	return &realSysFs{}, nil
}

func (self *realSysFs) GetBlockDevices() ([]os.FileInfo, error) {
	return ioutil.ReadDir(blockDir)
}

func (self *realSysFs) GetBlockDeviceNumbers(name string) (string, error) {
	dev, err := ioutil.ReadFile(path.Join(blockDir, name, "/dev"))
	if err != nil {
		return "", err
	}
	return string(dev), nil
}

func (self *realSysFs) GetBlockDeviceScheduler(name string) (string, error) {
	sched, err := ioutil.ReadFile(path.Join(blockDir, name, "/queue/scheduler"))
	if err != nil {
		return "", err
	}
	return string(sched), nil
}

func (self *realSysFs) GetBlockDeviceSize(name string) (string, error) {
	size, err := ioutil.ReadFile(path.Join(blockDir, name, "/size"))
	if err != nil {
		return "", err
	}
	return string(size), nil
}

func (self *realSysFs) GetNetworkDevices() ([]os.FileInfo, error) {
	files, err := ioutil.ReadDir(netDir)
	if err != nil {
		return nil, err
	}

	// Filter out non-directory & non-symlink files
	var dirs []os.FileInfo
	for _, f := range files {
		if f.Mode()|os.ModeSymlink != 0 {
			f, err = os.Stat(path.Join(netDir, f.Name()))
			if err != nil {
				continue
			}
		}
		if f.IsDir() {
			dirs = append(dirs, f)
		}
	}
	return dirs, nil
}

func (self *realSysFs) GetNetworkAddress(name string) (string, error) {
	address, err := ioutil.ReadFile(path.Join(netDir, name, "/address"))
	if err != nil {
		return "", err
	}
	return string(address), nil
}

func (self *realSysFs) GetNetworkMtu(name string) (string, error) {
	mtu, err := ioutil.ReadFile(path.Join(netDir, name, "/mtu"))
	if err != nil {
		return "", err
	}
	return string(mtu), nil
}

func (self *realSysFs) GetNetworkSpeed(name string) (string, error) {
	speed, err := ioutil.ReadFile(path.Join(netDir, name, "/speed"))
	if err != nil {
		return "", err
	}
	return string(speed), nil
}

func (self *realSysFs) GetNetworkStatValue(dev string, stat string) (uint64, error) {
	statPath := path.Join(netDir, dev, "/statistics", stat)
	out, err := ioutil.ReadFile(statPath)
	if err != nil {
		return 0, fmt.Errorf("failed to read stat from %q for device %q", statPath, dev)
	}
	var s uint64
	n, err := fmt.Sscanf(string(out), "%d", &s)
	if err != nil || n != 1 {
		return 0, fmt.Errorf("could not parse value from %q for file %s", string(out), statPath)
	}
	return s, nil
}

func (self *realSysFs) GetCaches(id int) ([]os.FileInfo, error) {
	cpuPath := fmt.Sprintf("%s%d/cache", cacheDir, id)
	return ioutil.ReadDir(cpuPath)
}

func bitCount(i uint64) (count int) {
	for i != 0 {
		if i&1 == 1 {
			count++
		}
		i >>= 1
	}
	return
}

func getCpuCount(cache string) (count int, err error) {
	out, err := ioutil.ReadFile(path.Join(cache, "/shared_cpu_map"))
	if err != nil {
		return 0, err
	}
	masks := strings.Split(string(out), ",")
	for _, mask := range masks {
		// convert hex string to uint64
		m, err := strconv.ParseUint(strings.TrimSpace(mask), 16, 64)
		if err != nil {
			return 0, fmt.Errorf("failed to parse cpu map %q: %v", string(out), err)
		}
		count += bitCount(m)
	}
	return
}

func (self *realSysFs) GetCacheInfo(id int, name string) (CacheInfo, error) {
	cachePath := fmt.Sprintf("%s%d/cache/%s", cacheDir, id, name)
	out, err := ioutil.ReadFile(path.Join(cachePath, "/size"))
	if err != nil {
		return CacheInfo{}, err
	}
	var size uint64
	n, err := fmt.Sscanf(string(out), "%dK", &size)
	if err != nil || n != 1 {
		return CacheInfo{}, err
	}
	// convert to bytes
	size = size * 1024
	out, err = ioutil.ReadFile(path.Join(cachePath, "/level"))
	if err != nil {
		return CacheInfo{}, err
	}
	var level int
	n, err = fmt.Sscanf(string(out), "%d", &level)
	if err != nil || n != 1 {
		return CacheInfo{}, err
	}

	out, err = ioutil.ReadFile(path.Join(cachePath, "/type"))
	if err != nil {
		return CacheInfo{}, err
	}
	cacheType := strings.TrimSpace(string(out))
	cpuCount, err := getCpuCount(cachePath)
	if err != nil {
		return CacheInfo{}, err
	}
	return CacheInfo{
		Size:  size,
		Level: level,
		Type:  cacheType,
		Cpus:  cpuCount,
	}, nil
}

func (self *realSysFs) GetSystemUUID() (string, error) {
	id, err := ioutil.ReadFile(path.Join(dmiDir, "id", "product_uuid"))
	if err != nil {
		//If running on baremetal Power then UID is /proc/device-tree/system-id
		id, err = ioutil.ReadFile(path.Join(ppcDevTree, "system-id"))
		if err != nil {
			//If running on a KVM guest on Power then UUID is /proc/device-tree/vm,uuid
			id, err = ioutil.ReadFile(path.Join(ppcDevTree, "vm,uuid"))
			if err != nil {
				return "", err
			}
		}
	}
	return strings.TrimSpace(string(id)), nil
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"os"
)

func FilesCount(d string) int {
	files, _ := ioutil.ReadDir(d)
	return len(files)
}

func SizeOf(d string) int64 {
	files, _ := ioutil.ReadDir(d)
	var sum int64
	for i := 0; i < len(files); i++ {
		//fmt.Println(files[i].Name())
		if IsDir(files[i]) {
			//fmt.Println(d+files[i].Name())
			sum += SizeOf(d+files[i].Name())
			fmt.Println(sum)
		} else {
			sum += files[i].Size()
			fmt.Println(sum)
		}
	}
	return sum
}

func IsDir(fileInfo os.FileInfo) bool {
	return fileInfo.IsDir()
}

func main() {
	flag.Parse();
	dirs := flag.Args()
	fmt.Println(dirs)
	dir_files := 0
	var dir_sizes int64
	for i := 0; i < len(dirs); i++ {
		dir_files += FilesCount(dirs[i])
		dir_sizes += SizeOf(dirs[i])
	}
	fmt.Printf("%d files, %d bytes", dir_files, dir_sizes)
}
<commit_msg>du.go FilesList<commit_after>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"path"
)

func FilesCount(d string) int {
	files, _ := ioutil.ReadDir(d)
	return len(files)
}

func SizeOf(d string) int64 {
	files, _ := ioutil.ReadDir(d)
	var sum int64
	for i := 0; i < len(files); i++ {
		//fmt.Println(files[i].Name())
		if IsDir(files[i]) {
			//fmt.Println(d+files[i].Name())
			sum += SizeOf(d+files[i].Name())
			fmt.Println(sum)
		} else {
			sum += files[i].Size()
			fmt.Println(sum)
		}
	}
	return sum
}

func FilesList(d string) []os.FileInfo {
	dorf, _ := ioutil.ReadDir(d)
	var fileinfos []os.FileInfo
	j := 0
	for i := 0; i < len(dorf); i++ {
		if dorf[i].IsDir() {
			dir := d + "/" + dorf[i].Name()
			infos := FilesList(dir)
			for k := 0; k < len(infos); k++ {
				fileinfos[j] = infos[k]
				j++
			}
		} else {
			fileinfos[j] = dorf[i]
			j++
		}
	}
	return fileinfos
}

func main() {
	flag.Parse();
	dirs := flag.Args()
	fmt.Println(dirs)
	dir_files := 0
	var dir_sizes int64
	for i := 0; i < len(dirs); i++ {
		files, _ := ioutil.ReadDir(dirs[i])
		for j := 0; j < len(files); j++ {
			if files[j].IsDir() {

			}
		}
		dir_files += FilesCount(dirs[i])
		dir_sizes += SizeOf(dirs[i])
	}
	fmt.Printf("%d files, %d bytes", dir_files, dir_sizes)
}
<|endoftext|>