<commit_before>package models

import (
	"errors"
	"fmt"
	"time"

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

// todo Scope function for this struct
// in order not to fetch passive accounts
type ChannelParticipant struct {
	// unique identifier of the channel
	Id int64 `json:"id"`

	// Id of the channel
	ChannelId int64 `json:"channelId"              sql:"NOT NULL"`

	// Id of the account
	AccountId int64 `json:"accountId"              sql:"NOT NULL"`

	// Status of the participant in the channel
	StatusConstant string `json:"statusConstant"   sql:"NOT NULL;TYPE:VARCHAR(100);"`

	// date of the user's last access to regarding channel
	LastSeenAt time.Time `json:"lastSeenAt"        sql:"NOT NULL"`

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

	// Modification date of the channel participant's status
	UpdatedAt time.Time `json:"updatedAt"          sql:"NOT NULL"`
}

// here is why i did this not-so-good constants
// https://code.google.com/p/go/issues/detail?id=359
const (
	ChannelParticipant_STATUS_ACTIVE          = "active"
	ChannelParticipant_STATUS_LEFT            = "left"
	ChannelParticipant_STATUS_REQUEST_PENDING = "requestPending"
)

func NewChannelParticipant() *ChannelParticipant {
	return &ChannelParticipant{}
}

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

func (c ChannelParticipant) TableName() string {
	return "api.channel_participant"
}

func (c *ChannelParticipant) BeforeSave() {
	c.LastSeenAt = time.Now().UTC()
}

func (c *ChannelParticipant) BeforeUpdate() {
	c.LastSeenAt = time.Now().UTC()
}

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

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

func (c *ChannelParticipant) AfterDelete() {
	bongo.B.AfterDelete(c)
}

func (c *ChannelParticipant) Create() error {
	if c.ChannelId == 0 {
		return fmt.Errorf("Channel Id is not set %d", c.ChannelId)
	}

	if c.AccountId == 0 {
		return fmt.Errorf("AccountId is not set %d", c.AccountId)
	}

	selector := map[string]interface{}{
		"channel_id": c.ChannelId,
		"account_id": c.AccountId,
	}

	// if err is nil
	// it means we already have that channel
	err := c.One(bongo.NewQS(selector))
	if err == nil {
		c.StatusConstant = ChannelParticipant_STATUS_ACTIVE
		if err := c.Update(); err != nil {
			return err
		}
		return nil
	}

	if err != gorm.RecordNotFound {
		return err
	}

	return bongo.B.Create(c)
}

func (c *ChannelParticipant) Update() error {
	return bongo.B.Update(c)
}

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

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

func (c *ChannelParticipant) Count(where ...interface{}) (int, error) {
	return bongo.B.Count(c, where...)
}

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

func (c *ChannelParticipant) FetchParticipant() error {
	if c.ChannelId == 0 {
		return errors.New("ChannelId is not set")
	}

	if c.AccountId == 0 {
		return errors.New("AccountId is not set")
	}

	selector := map[string]interface{}{
		"channel_id": c.ChannelId,
		"account_id": c.AccountId,
		// "status_constant":     ChannelParticipant_STATUS_ACTIVE,
	}

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

	return nil
}

func (c *ChannelParticipant) FetchUnreadCount() (int, error) {
	cml := NewChannelMessageList()
	return cml.UnreadCount(c)
}

func (c *ChannelParticipant) Delete() error {
	selector := bongo.Partial{
		"account_id": c.AccountId,
		"channel_id": c.ChannelId,
	}

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

	return bongo.B.UpdatePartial(c,
		bongo.Partial{
			"status_constant": ChannelParticipant_STATUS_LEFT,
		},
	)
}

func (c *ChannelParticipant) List() ([]ChannelParticipant, error) {
	var participants []ChannelParticipant

	if c.ChannelId == 0 {
		return participants, errors.New("ChannelId is not set")
	}
	query := &bongo.Query{
		Selector: map[string]interface{}{
			"channel_id":      c.ChannelId,
			"status_constant": ChannelParticipant_STATUS_ACTIVE,
		},
	}

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

	return participants, nil
}

func (c *ChannelParticipant) ListAccountIds(limit int) ([]int64, error) {
	var participants []int64

	if c.ChannelId == 0 {
		return participants, errors.New("ChannelId is not set")
	}

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

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

	return participants, nil
}

func (c *ChannelParticipant) FetchParticipatedChannelIds(a *Account, q *Query) ([]int64, error) {
	if a.Id == 0 {
		return nil, errors.New("Account.Id is not set")
	}

	channelIds := make([]int64, 0)

	// var results []ChannelParticipant
	rows, err := bongo.B.DB.Table(c.TableName()).
		Select("api.channel_participant.channel_id").
		Joins("left join api.channel on api.channel_participant.channel_id = api.channel.id").
		Where("api.channel_participant.account_id = ? and api.channel.type_constant = ? and  api.channel_participant.status_constant = ?", a.Id, q.Type, ChannelParticipant_STATUS_ACTIVE).
		Limit(q.Limit).
		Offset(q.Skip).
		Rows()
	defer rows.Close()
	if err != nil {
		return channelIds, err
	}

	var channelId int64
	for rows.Next() {
		rows.Scan(&channelId)
		channelIds = append(channelIds, channelId)
	}

	return channelIds, nil
}

func (c *ChannelParticipant) FetchParticipantCount() (int, error) {
	if c.ChannelId == 0 {
		return 0, errors.New("Channel.Id is not set")
	}

	return c.Count("channel_id = ?", c.ChannelId)
}

func (c *ChannelParticipant) IsParticipant(accountId int64) (bool, error) {
	if c.ChannelId == 0 {
		return false, errors.New("Channel.Id is not set")
	}

	selector := map[string]interface{}{
		"channel_id":      c.ChannelId,
		"account_id":      accountId,
		"status_constant": ChannelParticipant_STATUS_ACTIVE,
	}

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

	if err == gorm.RecordNotFound {
		return false, nil
	}

	return false, err
}
<commit_msg>Social: lowercase request pending status constant<commit_after>package models

import (
	"errors"
	"fmt"
	"time"

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

// todo Scope function for this struct
// in order not to fetch passive accounts
type ChannelParticipant struct {
	// unique identifier of the channel
	Id int64 `json:"id"`

	// Id of the channel
	ChannelId int64 `json:"channelId"              sql:"NOT NULL"`

	// Id of the account
	AccountId int64 `json:"accountId"              sql:"NOT NULL"`

	// Status of the participant in the channel
	StatusConstant string `json:"statusConstant"   sql:"NOT NULL;TYPE:VARCHAR(100);"`

	// date of the user's last access to regarding channel
	LastSeenAt time.Time `json:"lastSeenAt"        sql:"NOT NULL"`

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

	// Modification date of the channel participant's status
	UpdatedAt time.Time `json:"updatedAt"          sql:"NOT NULL"`
}

// here is why i did this not-so-good constants
// https://code.google.com/p/go/issues/detail?id=359
const (
	ChannelParticipant_STATUS_ACTIVE          = "active"
	ChannelParticipant_STATUS_LEFT            = "left"
	ChannelParticipant_STATUS_REQUEST_PENDING = "requestpending"
)

func NewChannelParticipant() *ChannelParticipant {
	return &ChannelParticipant{}
}

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

func (c ChannelParticipant) TableName() string {
	return "api.channel_participant"
}

func (c *ChannelParticipant) BeforeSave() {
	c.LastSeenAt = time.Now().UTC()
}

func (c *ChannelParticipant) BeforeUpdate() {
	c.LastSeenAt = time.Now().UTC()
}

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

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

func (c *ChannelParticipant) AfterDelete() {
	bongo.B.AfterDelete(c)
}

func (c *ChannelParticipant) Create() error {
	if c.ChannelId == 0 {
		return fmt.Errorf("Channel Id is not set %d", c.ChannelId)
	}

	if c.AccountId == 0 {
		return fmt.Errorf("AccountId is not set %d", c.AccountId)
	}

	selector := map[string]interface{}{
		"channel_id": c.ChannelId,
		"account_id": c.AccountId,
	}

	// if err is nil
	// it means we already have that channel
	err := c.One(bongo.NewQS(selector))
	if err == nil {
		c.StatusConstant = ChannelParticipant_STATUS_ACTIVE
		if err := c.Update(); err != nil {
			return err
		}
		return nil
	}

	if err != gorm.RecordNotFound {
		return err
	}

	return bongo.B.Create(c)
}

func (c *ChannelParticipant) Update() error {
	return bongo.B.Update(c)
}

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

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

func (c *ChannelParticipant) Count(where ...interface{}) (int, error) {
	return bongo.B.Count(c, where...)
}

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

func (c *ChannelParticipant) FetchParticipant() error {
	if c.ChannelId == 0 {
		return errors.New("ChannelId is not set")
	}

	if c.AccountId == 0 {
		return errors.New("AccountId is not set")
	}

	selector := map[string]interface{}{
		"channel_id": c.ChannelId,
		"account_id": c.AccountId,
		// "status_constant":     ChannelParticipant_STATUS_ACTIVE,
	}

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

	return nil
}

func (c *ChannelParticipant) FetchUnreadCount() (int, error) {
	cml := NewChannelMessageList()
	return cml.UnreadCount(c)
}

func (c *ChannelParticipant) Delete() error {
	selector := bongo.Partial{
		"account_id": c.AccountId,
		"channel_id": c.ChannelId,
	}

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

	return bongo.B.UpdatePartial(c,
		bongo.Partial{
			"status_constant": ChannelParticipant_STATUS_LEFT,
		},
	)
}

func (c *ChannelParticipant) List() ([]ChannelParticipant, error) {
	var participants []ChannelParticipant

	if c.ChannelId == 0 {
		return participants, errors.New("ChannelId is not set")
	}
	query := &bongo.Query{
		Selector: map[string]interface{}{
			"channel_id":      c.ChannelId,
			"status_constant": ChannelParticipant_STATUS_ACTIVE,
		},
	}

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

	return participants, nil
}

func (c *ChannelParticipant) ListAccountIds(limit int) ([]int64, error) {
	var participants []int64

	if c.ChannelId == 0 {
		return participants, errors.New("ChannelId is not set")
	}

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

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

	return participants, nil
}

func (c *ChannelParticipant) FetchParticipatedChannelIds(a *Account, q *Query) ([]int64, error) {
	if a.Id == 0 {
		return nil, errors.New("Account.Id is not set")
	}

	channelIds := make([]int64, 0)

	// var results []ChannelParticipant
	rows, err := bongo.B.DB.Table(c.TableName()).
		Select("api.channel_participant.channel_id").
		Joins("left join api.channel on api.channel_participant.channel_id = api.channel.id").
		Where("api.channel_participant.account_id = ? and api.channel.type_constant = ? and  api.channel_participant.status_constant = ?", a.Id, q.Type, ChannelParticipant_STATUS_ACTIVE).
		Limit(q.Limit).
		Offset(q.Skip).
		Rows()
	defer rows.Close()
	if err != nil {
		return channelIds, err
	}

	var channelId int64
	for rows.Next() {
		rows.Scan(&channelId)
		channelIds = append(channelIds, channelId)
	}

	return channelIds, nil
}

func (c *ChannelParticipant) FetchParticipantCount() (int, error) {
	if c.ChannelId == 0 {
		return 0, errors.New("Channel.Id is not set")
	}

	return c.Count("channel_id = ?", c.ChannelId)
}

func (c *ChannelParticipant) IsParticipant(accountId int64) (bool, error) {
	if c.ChannelId == 0 {
		return false, errors.New("Channel.Id is not set")
	}

	selector := map[string]interface{}{
		"channel_id":      c.ChannelId,
		"account_id":      accountId,
		"status_constant": ChannelParticipant_STATUS_ACTIVE,
	}

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

	if err == gorm.RecordNotFound {
		return false, nil
	}

	return false, err
}
<|endoftext|>


<commit_before>package moby

import (
	"context"
	"io"

	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/container"
	"github.com/docker/docker/client"

	"github.com/docker/api/backend"
	"github.com/docker/api/compose"
	"github.com/docker/api/containers"
)

type mobyService struct {
	apiClient *client.Client
}

func init() {
	backend.Register("moby", "moby", func(ctx context.Context) (backend.Service, error) {
		return New()
	})
}

// New returns a moby backend implementation
func New() (backend.Service, error) {
	apiClient, err := client.NewClientWithOpts(client.FromEnv)
	if err != nil {
		return nil, err
	}

	return &mobyService{
		apiClient,
	}, nil
}

func (ms *mobyService) ContainerService() containers.Service {
	return ms
}

func (ms *mobyService) ComposeService() compose.Service {
	return nil
}

func (ms *mobyService) List(ctx context.Context) ([]containers.Container, error) {
	css, err := ms.apiClient.ContainerList(ctx, types.ContainerListOptions{
		All: false,
	})
	if err != nil {
		return []containers.Container{}, err
	}

	var result []containers.Container
	for _, container := range css {
		result = append(result, containers.Container{
			ID:      container.ID,
			Image:   container.Image,
			Status:  container.Status,
			Command: container.Command,
		})
	}

	return result, nil
}

func (ms *mobyService) Run(ctx context.Context, r containers.ContainerConfig) error {
	create, err := ms.apiClient.ContainerCreate(ctx, &container.Config{
		Image: r.Image,
	}, nil, nil, r.ID)
	if err != nil {
		return err
	}

	return ms.apiClient.ContainerStart(ctx, create.ID, types.ContainerStartOptions{})
}

func (ms *mobyService) Exec(ctx context.Context, name string, command string, reader io.Reader, writer io.Writer) error {
	cec, err := ms.apiClient.ContainerExecCreate(ctx, name, types.ExecConfig{
		Cmd:          []string{command},
		Tty:          true,
		AttachStderr: true,
		AttachStdin:  true,
		AttachStdout: true,
	})
	if err != nil {
		return err
	}
	resp, err := ms.apiClient.ContainerExecAttach(ctx, cec.ID, types.ExecStartCheck{})
	if err != nil {
		return err
	}
	defer resp.Close()
	readChannel := make(chan error, 10)
	writeChannel := make(chan error, 10)

	go func() {
		_, err := io.Copy(writer, resp.Reader)
		readChannel <- err
	}()

	go func() {
		_, err := io.Copy(resp.Conn, reader)
		writeChannel <- err
	}()

	for {
		select {
		case err := <-readChannel:
			return err
		case err := <-writeChannel:
			return err
		}
	}
}

func (ms *mobyService) Logs(ctx context.Context, containerName string, request containers.LogsRequest) error {
	r, err := ms.apiClient.ContainerLogs(ctx, containerName, types.ContainerLogsOptions{
		ShowStdout: true,
		ShowStderr: true,
	})
	if err != nil {
		return err
	}
	_, err = io.Copy(request.Writer, r)
	return err
}
<commit_msg>Implement `Delete` for moby<commit_after>package moby

import (
	"context"
	"io"

	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/container"
	"github.com/docker/docker/client"

	"github.com/docker/api/backend"
	"github.com/docker/api/compose"
	"github.com/docker/api/containers"
)

type mobyService struct {
	apiClient *client.Client
}

func init() {
	backend.Register("moby", "moby", func(ctx context.Context) (backend.Service, error) {
		return New()
	})
}

// New returns a moby backend implementation
func New() (backend.Service, error) {
	apiClient, err := client.NewClientWithOpts(client.FromEnv)
	if err != nil {
		return nil, err
	}

	return &mobyService{
		apiClient,
	}, nil
}

func (ms *mobyService) ContainerService() containers.Service {
	return ms
}

func (ms *mobyService) ComposeService() compose.Service {
	return nil
}

func (ms *mobyService) List(ctx context.Context) ([]containers.Container, error) {
	css, err := ms.apiClient.ContainerList(ctx, types.ContainerListOptions{
		All: false,
	})
	if err != nil {
		return []containers.Container{}, err
	}

	var result []containers.Container
	for _, container := range css {
		result = append(result, containers.Container{
			ID:      container.ID,
			Image:   container.Image,
			Status:  container.Status,
			Command: container.Command,
		})
	}

	return result, nil
}

func (ms *mobyService) Run(ctx context.Context, r containers.ContainerConfig) error {
	create, err := ms.apiClient.ContainerCreate(ctx, &container.Config{
		Image: r.Image,
	}, nil, nil, r.ID)
	if err != nil {
		return err
	}

	return ms.apiClient.ContainerStart(ctx, create.ID, types.ContainerStartOptions{})
}

func (ms *mobyService) Exec(ctx context.Context, name string, command string, reader io.Reader, writer io.Writer) error {
	cec, err := ms.apiClient.ContainerExecCreate(ctx, name, types.ExecConfig{
		Cmd:          []string{command},
		Tty:          true,
		AttachStderr: true,
		AttachStdin:  true,
		AttachStdout: true,
	})
	if err != nil {
		return err
	}
	resp, err := ms.apiClient.ContainerExecAttach(ctx, cec.ID, types.ExecStartCheck{})
	if err != nil {
		return err
	}
	defer resp.Close()
	readChannel := make(chan error, 10)
	writeChannel := make(chan error, 10)

	go func() {
		_, err := io.Copy(writer, resp.Reader)
		readChannel <- err
	}()

	go func() {
		_, err := io.Copy(resp.Conn, reader)
		writeChannel <- err
	}()

	for {
		select {
		case err := <-readChannel:
			return err
		case err := <-writeChannel:
			return err
		}
	}
}

func (ms *mobyService) Logs(ctx context.Context, containerName string, request containers.LogsRequest) error {
	r, err := ms.apiClient.ContainerLogs(ctx, containerName, types.ContainerLogsOptions{
		ShowStdout: true,
		ShowStderr: true,
	})
	if err != nil {
		return err
	}
	_, err = io.Copy(request.Writer, r)
	return err
}

func (ms *mobyService) Delete(ctx context.Context, containerID string, force bool) error {
	return ms.apiClient.ContainerRemove(ctx, containerID, types.ContainerRemoveOptions{
		Force: force,
	})
}
<|endoftext|>


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

package bzip2

import (
	"io"

	"github.com/dsnet/compress/internal/prefix"
)

type writer struct {
	codes2D [maxNumTrees][maxNumSyms]prefix.PrefixCode
	codes1D [maxNumTrees]prefix.PrefixCodes
	trees1D [maxNumTrees]prefix.Encoder
}

func newWriter(w *io.Writer) *writer {
	bw := new(writer)
	bw.Reset(w)
	return bw
}

func (bw *writer) Write(buf []byte) (int, error) {
	return 0, nil
}

func (bw *writer) Close(buf []byte) error {
	return nil
}

func (bw *writer) Reset(w *io.Writer) {
	return
}
<commit_msg>bzip2: initial Writer implementation<commit_after>// Copyright 2015, Joe Tsai. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE.md file.

package bzip2

import (
	"io"

	"github.com/dsnet/compress/internal"
	"github.com/dsnet/compress/internal/prefix"
)

type Writer struct {
	InputOffset  int64 // Total number of bytes issued to Write
	OutputOffset int64 // Total number of bytes written to underlying io.Writer

	wr     prefixWriter
	err    error
	level  int
	wrHdr  bool
	blkCRC uint32
	endCRC uint32

	rle runLengthEncoding
	bwt burrowsWheelerTransform
	mtf moveToFront

	buf []byte
}

func NewWriter(w io.Writer) *Writer {
	zw, _ := NewWriterLevel(w, DefaultCompression)
	return zw
}

func NewWriterLevel(w io.Writer, lvl int) (*Writer, error) {
	if lvl == DefaultCompression {
		lvl = 6
	}
	if lvl < BestSpeed || lvl > BestCompression {
		return nil, Error{"invalid compression level"}
	}
	zw := new(Writer)
	zw.level = lvl
	zw.Reset(w)
	return zw, nil
}

func (zw *Writer) Write(buf []byte) (int, error) {
	if zw.err != nil {
		return 0, zw.err
	}

	cnt := len(buf)
	for len(buf) > 0 {
		wrCnt, err := zw.rle.Write(buf)
		zw.blkCRC = updateCRC(zw.blkCRC, buf[:wrCnt])
		buf = buf[wrCnt:]
		if err != rleDone {
			continue
		}
		if zw.err = zw.flush(); zw.err != nil {
			return 0, zw.err
		}
	}
	zw.InputOffset += int64(cnt)
	return cnt, nil
}

func (zw *Writer) flush() error {
	vals := zw.rle.Bytes()
	if len(vals) == 0 {
		return nil
	}
	zw.wr.Offset = zw.OutputOffset
	func() {
		defer errRecover(&zw.err)
		if !zw.wrHdr {
			// Write stream header.
			zw.wr.WriteBitsBE64(hdrMagic, 16)
			zw.wr.WriteBitsBE64('h', 8)
			zw.wr.WriteBitsBE64(uint64('0'+zw.level), 8)
			zw.wrHdr = true
		}
		zw.compressBlock(vals)
	}()
	if zw.OutputOffset, zw.err = zw.wr.Flush(); zw.err != nil {
		return zw.err
	}
	zw.endCRC = (zw.endCRC<<1 | zw.endCRC>>31) ^ zw.blkCRC
	zw.blkCRC = 0
	zw.rle.Init(zw.buf)
	return nil
}

func (zw *Writer) Close() error {
	if zw.err == ErrClosed {
		return nil
	}

	// Flush RLE buffer if there is left-over data.
	if zw.err = zw.flush(); zw.err != nil {
		return zw.err
	}

	// Write stream footer.
	zw.wr.Offset = zw.OutputOffset
	func() {
		defer errRecover(&zw.err)
		zw.wr.WriteBitsBE64(endMagic, 48)
		zw.wr.WriteBitsBE64(uint64(zw.endCRC), 32)
		zw.wr.WritePads(0)
	}()
	if zw.OutputOffset, zw.err = zw.wr.Flush(); zw.err != nil {
		return zw.err
	}

	if zw.err == nil {
		zw.err = ErrClosed
		return nil
	}
	return zw.err
}

func (zw *Writer) Reset(w io.Writer) {
	*zw = Writer{
		wr:    zw.wr,
		level: zw.level,
		rle:   zw.rle,
		bwt:   zw.bwt,
		mtf:   zw.mtf,
		buf:   zw.buf,
	}
	zw.wr.Init(w)
	blkSize := zw.level * blockSize
	if cap(zw.buf) >= blkSize {
		zw.buf = zw.buf[:blkSize]
	} else {
		zw.buf = make([]byte, blkSize)
	}
	zw.rle.Init(zw.buf)
	return
}

func (zw *Writer) compressBlock(buf []byte) {
	zw.wr.WriteBitsBE64(blkMagic, 48)
	zw.wr.WriteBitsBE64(uint64(zw.blkCRC), 32)
	zw.wr.WriteBitsBE64(0, 1)

	// Step 1: Burrows-Wheeler transformation.
	ptr := zw.bwt.Encode(buf)
	zw.wr.WriteBitsBE64(uint64(ptr), 24)

	// Step 2: Move-to-front transform and run-length encoding.
	var dictMap [256]bool
	for _, c := range buf {
		dictMap[c] = true
	}

	var dictArr [256]uint8
	var symMaps [16]uint16
	var symMap uint16
	dict := dictArr[:0]
	for i, b := range dictMap {
		if b {
			c := uint8(i)
			dict = append(dict, c)
			symMap |= 1 << (c >> 4)
			symMaps[c>>4] |= 1 << (c & 0xf)
		}
	}

	zw.wr.WriteBits(uint(symMap), 16)
	for _, m := range symMaps {
		if m > 0 {
			zw.wr.WriteBits(uint(m), 16)
		}
	}

	zw.mtf.Init(dict, len(buf))
	syms := zw.mtf.Encode(buf)

	// Step 3: Prefix encoding.
	zw.encodePrefix(syms, len(dict))
}

func (zw *Writer) encodePrefix(syms []uint16, numSyms int) {
	numSyms += 2                           // Remove 0 symbol, add RUNA, RUNB, and EOF symbols
	syms = append(syms, uint16(numSyms-1)) // EOF marker

	// Compute number of prefix trees needed.
	numTrees := maxNumTrees
	for i, lim := range []int{200, 600, 1200, 2400} {
		if len(syms) < lim {
			numTrees = minNumTrees + i
			break
		}
	}

	// Compute number of block selectors.
	numSels := (len(syms) + numBlockSyms - 1) / numBlockSyms
	treeSels := make([]uint8, numSels)
	for i := range treeSels {
		treeSels[i] = uint8(i % numTrees)
	}

	// Initialize prefix codes.
	var codes2D [maxNumTrees][maxNumSyms]prefix.PrefixCode
	var codes1D [maxNumTrees]prefix.PrefixCodes
	var trees1D [maxNumTrees]prefix.Encoder
	for i := range codes2D[:numTrees] {
		pc := codes2D[i][:numSyms]
		for j := range pc {
			pc[j].Sym = uint32(j)
		}
		codes1D[i] = pc
	}

	// First cut at assigning prefix trees to each group.
	var codes prefix.PrefixCodes
	var blkLen, treeIdx int
	for _, sym := range syms {
		if blkLen == 0 {
			blkLen = numBlockSyms
			codes = codes2D[treeSels[treeIdx]][:numSyms]
			treeIdx++
		}
		blkLen--
		codes[sym].Cnt++
	}

	// TODO(dsnet): Use K-means to cluster groups to each prefix tree.

	// Generate lengths and prefixes based on symbol frequencies.
	for i := range trees1D[:numTrees] {
		pc := prefix.PrefixCodes(codes2D[i][:numSyms])
		pc.SortByCount()
		if err := prefix.GenerateLengths(pc, maxPrefixBits); err != nil {
			panic(err)
		}
		pc.SortBySymbol()
		if err := prefix.GeneratePrefixes(pc); err != nil {
			panic(err)
		}
		trees1D[i].Init(pc)
	}

	// Write out information about the trees and tree selectors.
	var mtf internal.MoveToFront
	zw.wr.WriteBitsBE64(uint64(numTrees), 3)
	zw.wr.WriteBitsBE64(uint64(numSels), 15)
	treeSelsMTF := make([]uint8, numSels)
	copy(treeSelsMTF, treeSels)
	mtf.Encode(treeSelsMTF)
	for _, sym := range treeSelsMTF {
		zw.wr.WriteSymbol(uint(sym), &encSel)
	}
	zw.wr.WritePrefixCodes(codes1D[:numTrees])

	// Write out prefix encoded symbols of compressed data.
	var tree *prefix.Encoder
	blkLen, treeIdx = 0, 0
	for _, sym := range syms {
		if blkLen == 0 {
			blkLen = numBlockSyms
			tree = &trees1D[treeSels[treeIdx]]
			treeIdx++
		}
		blkLen--
		ok := zw.wr.TryWriteSymbol(uint(sym), tree)
		if !ok {
			zw.wr.WriteSymbol(uint(sym), tree)
		}
	}
}
<|endoftext|>


<commit_before>package i18n

import (
	"regexp"

	"github.com/volatile/core"
)

// Locale contains translations and special i18n values associated to unique keys.
type Locale map[string]string

// Locales contains locales associated to their names.
type Locales map[string]Locale

const (
	// TransNPlaceholder is the placeholder replaced by n in a translation, when using the TransN function.
	TransNPlaceholder = "{{.n}}"

	contextDataKey = "i18nLocale"
)

var (
	useCookie  bool       // Defines if the matched locale must be saved in a cookie after matching.
	cookieName = "locale" // The name of the cookie used to save the client matched locale.

	defaultLocale   string
	locales         *Locales // The map of available locales. It is ensured to not be empty.
	localeKeyRegexp = regexp.MustCompile("^[a-z]{2}$")
)

// ViewsFuncs provides i18n functions that can be set for templates.
var ViewsFuncs = map[string]interface{}{
	"locale":           ClientLocale,
	"num":              Num,
	"sortedLocaleKeys": SortedLocaleKeys,
	"trans":            Trans,
	"transn":           TransN,
}

// Use registers locales l.
// On request, if none match to the client accepted languages, the locale def will be used.
// And if useCookie is true, a cookie will be used to save the most appropriate and available locale key for the client.
func Use(l *Locales, def string, cookie bool) {
	if len(*locales) == 0 {
		panic("i18n: locales map can't be empty")
	}

	for i := range *l {
		if !localeKeyRegexp.MatchString(i) {
			panic(`i18n: locale key must be an ISO 639-1 code (2 letters lowercase), so "` + i + `" is invalid`)
		}
	}
	locales = l

	if !localeExists(def) {
		panic("i18n: default locale " + def + " doesn't exist")
	}
	defaultLocale = def

	useCookie = cookie

	// Trigger ClientLocale to match and set locale at least one time.
	core.Use(func(c *core.Context) {
		ClientLocale(c)
		c.Next()
	})
}
<commit_msg>Fix nil locales panic on Use<commit_after>package i18n

import (
	"regexp"

	"github.com/volatile/core"
)

// Locale contains translations and special i18n values associated to unique keys.
type Locale map[string]string

// Locales contains locales associated to their names.
type Locales map[string]Locale

const (
	// TransNPlaceholder is the placeholder replaced by n in a translation, when using the TransN function.
	TransNPlaceholder = "{{.n}}"

	contextDataKey = "i18nLocale"
)

var (
	useCookie  bool       // Defines if the matched locale must be saved in a cookie after matching.
	cookieName = "locale" // The name of the cookie used to save the client matched locale.

	defaultLocale   string
	locales         *Locales // The map of available locales. It is ensured to not be empty.
	localeKeyRegexp = regexp.MustCompile("^[a-z]{2}$")
)

// ViewsFuncs provides i18n functions that can be set for templates.
var ViewsFuncs = map[string]interface{}{
	"locale":           ClientLocale,
	"num":              Num,
	"sortedLocaleKeys": SortedLocaleKeys,
	"trans":            Trans,
	"transn":           TransN,
}

// Use registers locales l.
// On request, if none match to the client accepted languages, the locale def will be used.
// And if useCookie is true, a cookie will be used to save the most appropriate and available locale key for the client.
func Use(l *Locales, def string, cookie bool) {
	if l == nil {
		panic("i18n: locales map can't be empty")
	}

	for i := range *l {
		if !localeKeyRegexp.MatchString(i) {
			panic(`i18n: locale key must be an ISO 639-1 code (2 letters lowercase), so "` + i + `" is invalid`)
		}
	}
	locales = l

	if !localeExists(def) {
		panic("i18n: default locale " + def + " doesn't exist")
	}
	defaultLocale = def

	useCookie = cookie

	// Trigger ClientLocale to match and set locale at least one time.
	core.Use(func(c *core.Context) {
		ClientLocale(c)
		c.Next()
	})
}
<|endoftext|>


<commit_before>package response

import (
	"encoding/json"
	"errors"
	"html/template"
	"net/http"
	"os"
	"path/filepath"

	"github.com/volatile/core"
	"github.com/volatile/core/log"
)

const viewsDir = "views"

var views *template.Template

func init() {
	if _, err := os.Stat(viewsDir); err != nil {
		return
	}

	views = template.New("views")

	// Built-in views funcs
	views.Funcs(template.FuncMap{
		"html":  viewsFuncHTML,
		"nl2br": viewsFuncNL2BR,
	})

	core.BeforeRun(func() {
		if err := filepath.Walk(viewsDir, viewsWalk); err != nil {
			panic("response: " + err.Error())
		}
	})
}

// walk is the path/filepath.WalkFunc used to walk viewsDir in order to initialize views.
// It will try to parse all files it encounters and recurse into subdirectories.
func viewsWalk(path string, f os.FileInfo, err error) error {
	if err != nil {
		return err
	}

	if f.IsDir() {
		return nil
	}

	_, err = views.ParseFiles(path)

	return err
}

// FuncMap is the type of the map defining the mapping from names to functions.
// Each function must have either a single return value, or two return values of which the second has type error.
// In that case, if the second (error) argument evaluates to non-nil during execution, execution terminates and Execute returns that error.
// FuncMap has the same base type as FuncMap in "text/template", copied here so clients need not import "text/template".
type FuncMap map[string]interface{}

// ViewsFuncs adds a function that will be available to all templates.
func ViewsFuncs(funcMap FuncMap) {
	if views == nil {
		panic(`response: views can't be used without a "views" directory`)
	}
	views.Funcs(template.FuncMap(funcMap))
}

// Status responds with the given status code.
func Status(c *core.Context, v int) {
	http.Error(c.ResponseWriter, http.StatusText(v), v)
}

// String responds with the given string.
func String(c *core.Context, s string) {
	c.ResponseWriter.Write([]byte(s))
}

// Bytes responds with the given slice of byte.
func Bytes(c *core.Context, b []byte) {
	c.ResponseWriter.Write(b)
}

// JSON set the correct header and responds with the marshalled content.
func JSON(c *core.Context, v interface{}) {
	c.ResponseWriter.Header().Set("Content-Type", "application/json")
	if err := json.NewEncoder(c.ResponseWriter).Encode(v); err != nil {
		log.Stack(err)
		http.Error(c.ResponseWriter, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
	}
}

// View pass the data to the template associated to name, and responds with it.
func View(c *core.Context, name string, data map[string]interface{}) {
	if views == nil {
		log.Stack(errors.New(`views can't be used without a "views" directory`))
		http.Error(c.ResponseWriter, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	}

	if data == nil {
		data = make(map[string]interface{})
	}
	data["c"] = c

	c.ResponseWriter.Header().Set("Content-Type", "text/html; charset=utf-8")
	if err := views.ExecuteTemplate(c.ResponseWriter, name, data); err != nil {
		log.Stack(err)
		http.Error(c.ResponseWriter, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
	}
}
<commit_msg>Add funcs for status codes<commit_after>package response

import (
	"encoding/json"
	"errors"
	"html/template"
	"net/http"
	"os"
	"path/filepath"

	"github.com/volatile/core"
	"github.com/volatile/core/httputil"
	"github.com/volatile/core/log"
)

const viewsDir = "views"

var views *template.Template

func init() {
	if _, err := os.Stat(viewsDir); err != nil {
		return
	}

	views = template.New("views")

	// Built-in views funcs
	views.Funcs(template.FuncMap{
		"html":  viewsFuncHTML,
		"nl2br": viewsFuncNL2BR,
	})

	core.BeforeRun(func() {
		if err := filepath.Walk(viewsDir, viewsWalk); err != nil {
			panic("response: " + err.Error())
		}
	})
}

// walk is the path/filepath.WalkFunc used to walk viewsDir in order to initialize views.
// It will try to parse all files it encounters and recurse into subdirectories.
func viewsWalk(path string, f os.FileInfo, err error) error {
	if err != nil {
		return err
	}

	if f.IsDir() {
		return nil
	}

	_, err = views.ParseFiles(path)

	return err
}

// FuncMap is the type of the map defining the mapping from names to functions.
// Each function must have either a single return value, or two return values of which the second has type error.
// In that case, if the second (error) argument evaluates to non-nil during execution, execution terminates and Execute returns that error.
// FuncMap has the same base type as FuncMap in "text/template", copied here so clients need not import "text/template".
type FuncMap map[string]interface{}

// ViewsFuncs adds a function that will be available to all templates.
func ViewsFuncs(funcMap FuncMap) {
	if views == nil {
		panic(`response: views can't be used without a "views" directory`)
	}
	views.Funcs(template.FuncMap(funcMap))
}

// Status responds with the given status code.
func Status(c *core.Context, v int) {
	http.Error(c.ResponseWriter, http.StatusText(v), v)
}

// String responds with the given string.
func String(c *core.Context, s string) {
	StringStatus(c, s, http.StatusOK)
}

// StringStatus responds with the given string and status code.
func StringStatus(c *core.Context, s string, code int) {
	httputil.SetDetectedContentType(c.ResponseWriter, []byte(s))
	c.ResponseWriter.WriteHeader(code)
	c.ResponseWriter.Write([]byte(s))
}

// Bytes responds with the given slice of byte.
func Bytes(c *core.Context, b []byte) {
	BytesStatus(c, b, http.StatusOK)
}

// BytesStatus responds with the given slice of byte and status code.
func BytesStatus(c *core.Context, b []byte, code int) {
	httputil.SetDetectedContentType(c.ResponseWriter, b)
	c.ResponseWriter.WriteHeader(code)
	c.ResponseWriter.Write(b)
}

// JSON set the correct header and responds with the marshalled content.
func JSON(c *core.Context, v interface{}) {
	JSONStatus(c, v, http.StatusOK)
}

// JSONStatus set the correct header and responds with the marshalled content and status code.
func JSONStatus(c *core.Context, v interface{}, code int) {
	b, err := json.Marshal(v)
	if err != nil {
		log.Stack(err)
		http.Error(c.ResponseWriter, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
	}

	c.ResponseWriter.Header().Set("Content-Type", "application/json")
	c.ResponseWriter.WriteHeader(code)
	c.ResponseWriter.Write(b)
}

// View pass the data to the template associated to name, and responds with it.
func View(c *core.Context, name string, data map[string]interface{}) {
	if views == nil {
		log.Stack(errors.New(`views can't be used without a "views" directory`))
		http.Error(c.ResponseWriter, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	}

	if data == nil {
		data = make(map[string]interface{})
	}
	data["c"] = c

	c.ResponseWriter.Header().Set("Content-Type", "text/html; charset=utf-8")
	if err := views.ExecuteTemplate(c.ResponseWriter, name, data); err != nil {
		log.Stack(err)
		http.Error(c.ResponseWriter, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
	}
}
<|endoftext|>


<commit_before>package builder

import (
	"strings"
)

type Query struct {
	TypeQuery     string
	Columns       []interface{}
	TableName     string
	WhereCond     []WhereStruct
	GroupByStruct []interface{}
}

type WhereStruct struct {
	Expression string
	Value      interface{}
	Delimiter  string
}

func Select(columns ...interface{}) *Query {

	return &Query{
		Columns:   columns,
		TypeQuery: "Select",
	}
}

func (query *Query) From(table string) *Query {
	query.TableName = strings.Replace(table, " ", "", -1)
	return query
}

func (query *Query) FromSubquery(table string) *Query {
	query.TableName = "(" + table + ")"
	return query
}

func (query *Query) Where(query_str string, value interface{}) *Query {
	query.WhereCond = append(query.WhereCond, WhereStruct{Expression: query_str, Value: value})
	return query
}

func (query *Query) And(query_str string, value interface{}) *Query {
	query.WhereCond = append(query.WhereCond, WhereStruct{Expression: query_str, Value: value, Delimiter: " And "})
	return query
}

func (query *Query) Or(query_str string, value interface{}) *Query {
	query.WhereCond = append(query.WhereCond, WhereStruct{Expression: query_str, Value: value, Delimiter: " Or "})
	return query
}

func (query *Query) GroupBy(values interface{}) *Query {
	query.GroupByStruct = values
	return query
}
<commit_msg>GroupBy - replace ...interface to interface<commit_after>package builder

import (
	"strings"
)

type Query struct {
	TypeQuery     string
	Columns       []interface{}
	TableName     string
	WhereCond     []WhereStruct
	GroupByStruct []interface{}
}

type WhereStruct struct {
	Expression string
	Value      interface{}
	Delimiter  string
}

func Select(columns ...interface{}) *Query {

	return &Query{
		Columns:   columns,
		TypeQuery: "Select",
	}
}

func (query *Query) From(table string) *Query {
	query.TableName = strings.Replace(table, " ", "", -1)
	return query
}

func (query *Query) FromSubquery(table string) *Query {
	query.TableName = "(" + table + ")"
	return query
}

func (query *Query) Where(query_str string, value interface{}) *Query {
	query.WhereCond = append(query.WhereCond, WhereStruct{Expression: query_str, Value: value})
	return query
}

func (query *Query) And(query_str string, value interface{}) *Query {
	query.WhereCond = append(query.WhereCond, WhereStruct{Expression: query_str, Value: value, Delimiter: " And "})
	return query
}

func (query *Query) Or(query_str string, value interface{}) *Query {
	query.WhereCond = append(query.WhereCond, WhereStruct{Expression: query_str, Value: value, Delimiter: " Or "})
	return query
}

func (query *Query) GroupBy(values []interface{}) *Query {
	query.GroupByStruct = values
	return query
}
<|endoftext|>


<commit_before>package cat

import "net"
import "fmt"

var Tchan chan Transaction = make(chan Transaction, 256)

//sender_run is internally used and only called by Cat_init_if.
//sender_run receive Transaction from a specific channel,
//encode Transaction and start new goroutines to send Transaction to backend.
//Basically, only 1 goroutine keeps the function.
func sender_run() {
	for {
		t := <-Tchan
		fmt.Println(t.GetName())
		fmt.Println(t.GetType())
	}
}

//sender_send is internally used and only called by sender_run
func sender_send(conn net.Conn, data []byte) {
}
<commit_msg>add simple sender<commit_after>package cat

import "fmt"
import "time"
import "bytes"
import "net"
import "strconv"
import "encoding/binary"
import "strings"

var Mchan chan Message = make(chan Message, 1<<20)
var MaxBatchSize int = 1 << 8

//sender_run is internally used and only called by Cat_init_if.
//sender_run call sender_collect repeatedly.
//Basically, only 1 goroutine keeps this function.
func sender_run() {
	for {
		if sender_collect() {
			time.Sleep(5*time.Microsecond)
		}
	}
}

func sender_collect() bool{
	messages := make(chan Message, MaxBatchSize)
	var count = 0
collect:
	for count < MaxBatchSize {
		select {
		case message := <-Mchan:
			messages <- message
			count++
		default:
			break collect
		}
	}
	close(messages)
	if count > 0 {
		sender_encode(messages, count)
		return false
	} else {
		return true
	}
}

func sender_encode(messages <-chan Message, count int) {
	datas := make(chan []byte, count)
	for message := range messages {
		buf := bytes.NewBuffer([]byte{0, 0, 0, 0})
		encode_header(buf)
		message.Encode(buf)
		load := int32tobytes(int32(buf.Len() - 4))
		data := buf.Bytes()
		data[0] = load[0]
		data[1] = load[1]
		data[2] = load[2]
		data[3] = load[3]
		datas <- data
	}
	close(datas)
	sender_send(datas)
}

func sender_send(datas <-chan []byte) {
	conn, err := net.Dial("tcp", "10.2.6.99:2280")
	if err != nil {
		fmt.Println(err)
	}
	for data := range datas {
		conn.Write(data)
	}
	conn.Close()
}

const m_domain string = "555554"
const m_hostname string = "DST51752"
const m_ipAddress string = "192.168.141.131"

var sender_index int = 0
var sender_l chan int = make(chan int, 1)

func message_id() []byte {
	var timestamp = time.Now().Unix() / 3600
	var index int
	sender_l <- 0
	index = sender_index
	sender_index++
	<-sender_l
	b := new(bytes.Buffer)
	b.WriteString(m_domain)
	b.WriteString("-")
	b.WriteString(iptohex(m_ipAddress))
	b.WriteString("-")
	b.WriteString(strconv.FormatInt(timestamp, 10))
	b.WriteString("-")
	b.WriteString(strconv.Itoa(index))
	return b.Bytes()
}

func encode_header(buf *bytes.Buffer) {
	buf.WriteString("PT1")
	buf.WriteString(TAB)
	buf.WriteString(m_domain)
	buf.WriteString(TAB)
	buf.WriteString(m_hostname)
	buf.WriteString(TAB)
	buf.WriteString(m_ipAddress)
	buf.WriteString(TAB)
	buf.WriteString("main")
	buf.WriteString(TAB)
	buf.WriteString("1")
	buf.WriteString(TAB)
	buf.WriteString("main")
	buf.WriteString(TAB)
	buf.Write(message_id())
	buf.WriteString(TAB)
	buf.WriteString("null")
	buf.WriteString(TAB)
	buf.WriteString("null")
	buf.WriteString(TAB)
	buf.WriteString("null")
	buf.WriteString(TAB)
	buf.WriteString(LF)
}

func int32tobytes(i int32) []byte {
	buf := bytes.NewBuffer([]byte{})
	binary.Write(buf, binary.BigEndian, i)
	return buf.Bytes()
}

func iptohex(ip string) string {
	var strs []string = strings.Split(ip, ".")
	for i := 0; i < 4; i++ {
		digit, _ := strconv.Atoi(strs[i])
		strs[i] = fmt.Sprintf("%x", digit)
	}
	return strings.Join(strs, "")
}
<|endoftext|>


<commit_before>// Copyright 2015 Igor Dolzhikov. All rights reserved.
// Use of this source code is governed by a license
// that can be found in the LICENSE file.

package spawn

import (
	"bufio"
	"bytes"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/http/httputil"
	"os"
	"regexp"
	"sort"
	"time"

	"github.com/takama/router"
)

const (

	// VERSION - current version of the service
	VERSION = "0.1.9"

	// DATE - revision date of the service
	DATE = "2015-04-03T01:46:17Z"

	// MaxSignals - maximum count of update signals
	MaxSignals = 1000

	// MaxJobs - maximum count of update jobs for every bundle
	MaxJobs = 100000

	// DefaultTimeout is a timeout for the worker's response
	DefaultTimeout time.Duration = 10

	// HTTP methods, which should be queued
	protocolHTTP = "http"
	methodGET    = "GET"
	methodPOST   = "POST"
	methodPUT    = "PUT"
	methodDELETE = "DELETE"

	// Job signals
	responseSignal = iota
	nodeJobSignal
)

// simplest logger, which initialized during starts of the application
var (
	stdlog = log.New(os.Stdout, "", log.Ldate|log.Ltime)
	errlog = log.New(os.Stderr, "", log.Ldate|log.Ltime|log.Lshortfile)
)

// Server Record
type Server struct {

	// Server name/description
	Name string

	// Node Bundle contains the Node records
	Nodes *NodeBundle
	// contains filtered or unexported fields

	// Embeded router
	*router.Router

	// Response signal channel
	response chan struct{}

	// responseTimeout is a timeout for worker's response
	responseTimeout time.Duration

	// job signal channel
	job chan int

	// quit signal channel
	quit chan struct{}

	// round robin mode
	roundRobin bool

	// nodes will queried according to priority
	byPriority bool

	// nodes health check
	check HealthCheck

	// Queue Bundle contains the queue records
	queues *queueBundle

	// Node connection transport
	transport http.RoundTripper
}

// HealthCheck contains parameters which used for checking node
type HealthCheck struct {

	// health check time of the node in seconds
	Seconds time.Duration `json:"seconds"`

	// url which will be checked
	URL string `json:"url"`

	// regexp pattern for extended check analyze
	Pattern string `json:"regexp"`
}

// NewServer creates a new server which contains the nodes/queues
func NewServer(name string) (*Server, error) {

	// Init the router
	r := router.New()
	r.PanicHandler = panicHandler
	r.NotFound = notFound
	r.Logger = logger
	r.CustomHandler = baseHandler

	// Init the Server
	server := &Server{
		Name:            name,
		Router:          r,
		responseTimeout: DefaultTimeout,
		response:        make(chan struct{}),
		job:             make(chan int, MaxSignals),
		quit:            make(chan struct{}),
		transport:       http.DefaultTransport,
	}

	// Create and init nodes bundle
	server.Nodes = &NodeBundle{
		Server:  server,
		records: make(map[string]map[uint64]Node),
	}

	// Create and init queues bundle
	server.queues = &queueBundle{records: make(map[string]*queue)}

	return server, nil
}

// Run the server, init the handlers, init the specified modes
// If handler RequestHandler is not defined used default handler
// with standard handling of the requests/responses
func (server *Server) Run(
	hostPort, apiHostPort string,
	handler RequestHandler,
	nodes []Node,
	roundRobin, byPriority bool,
	check HealthCheck,
) (status string, err error) {

	// if used round-robin mode
	if roundRobin {
		stdlog.Println(server.Name, "will used 'round-robin' mode")
		server.roundRobin = roundRobin
	}

	// if used by-priority mode
	if byPriority {
		stdlog.Println("Nodes will queried according to priority")
		server.byPriority = byPriority
	}

	// Init the Nodes update channel
	server.Nodes.update = make(chan nodeJob, MaxJobs)

	// Starts the worker which manage server's jobs
	go server.manage()

	// Init the Nodes settings
	if !server.Nodes.SetAll(nodes) {
		status = server.Name + " is not loaded"
		err = errors.New("The nodes settings in config have incorrect values")
		return
	}

	// Init a health check settings
	server.check = check

	// The info handler returns a system status of the application
	server.GET("/info", infoHandler)

	// Lists methods, which display how to use API
	server.GET("/list", displayAllMethods)
	server.GET("/list/nodes", displayAllNodeMethods)
	server.GET("/list/nodes/get", displayGetNodeMethods)
	server.GET("/list/nodes/set", displaySetNodeMethods)
	server.GET("/list/nodes/delete", displayDeleteNodeMethods)

	// Init API methods for the Nodes
	server.GET("/nodes/:host/:port", server.Nodes.getRecord)
	server.GET("/nodes/:host", server.Nodes.getAllRecordsByHost)
	server.GET("/nodes", server.Nodes.getAllRecords)
	server.PUT("/nodes/:host/:port", server.Nodes.putRecord)
	server.PUT("/nodes", server.Nodes.putAllRecords)
	server.DELETE("/nodes/:host/:port", server.Nodes.deleteRecord)
	server.DELETE("/nodes/:host", server.Nodes.deleteAllRecordsByHost)
	server.DELETE("/nodes", server.Nodes.deleteAllRecords)

	go server.Listen(apiHostPort)
	go func() {
		p := new(proxy)
		if handler != nil {
			p.handler = handler
		} else {
			p.handler = server.proxyHandler
		}
		if err := http.ListenAndServe(hostPort, p); err != nil {
			errlog.Fatal(err)
		}
	}()

	status = server.Name + " loaded successfully"

	return
}

// Shutdown closes the server graceful
func (server *Server) Shutdown() (status string, err error) {

	// Set timer to wait one minute
	timeout := time.NewTimer(time.Second * 30)

	// a unwanted response sweeps if exist
	for {
		select {
		case <-server.response:
			continue
		default:
		}
		break
	}

	// sends a 'quit' signal
	server.quit <- struct{}{}

	status = server.Name + " connections closed"
	select {

	// Exit by timeout if jobs did not done
	case <-timeout.C:
		err = errors.New("timeout")
		return
	// Exit after all jobs done
	case <-server.response:
		return
	}
}

// Manage routine which manage all jobs
func (server *Server) manage() {
	defer func() {
		if recovery := recover(); recovery != nil {
			errlog.Println("Recovered in Manage routine", recovery)
			// Recover routine
			go server.manage()
		} else {
			stdlog.Println("Manage routine stoped")
			server.response <- struct{}{}
		}
	}()
	for {
		select {
		case job := <-server.job:
			server.doJob(job)
			continue
		default:
		}
		select {
		case job := <-server.job:
			server.doJob(job)
			continue
		case <-server.quit:
			return
		}
	}
}

// Do updates depended by the signal
func (server *Server) doJob(signal int) {
	defer func() {
		if recovery := recover(); recovery != nil {
			errlog.Println("Recovered in do job routine", recovery)
		}
	}()
	switch signal {
	case responseSignal:
		server.response <- struct{}{}
	case nodeJobSignal:
		server.Nodes.updateRecords()
		server.Nodes.InitRing()
	}
}

// proxyHandler manages all requests/responses
func (server *Server) proxyHandler(request *http.Request) *http.Response {

	// Add "X-Forwarded-For" to repost remote host IP
	if request.Header.Get("X-Forwarded-For") == "" {
		request.Header.Add("X-Forwarded-For", request.RemoteAddr)
	}

	// Use HTTP scheme
	request.URL.Scheme = protocolHTTP

	// If requests should not be queued, get result immediately
	if request.Method != methodPOST &&
		request.Method != methodPUT &&
		request.Method != methodDELETE {

		return server.processReceive(request)
	}

	return server.processUpdate(request)
}

// call 'GET' and others requests to the node using defined mode
func (server *Server) processReceive(request *http.Request) *http.Response {
	if server.roundRobin {

		// Use round robin to get data from the host
		for count := 0; count < server.Nodes.ring.Len(); count++ {
			if node, ok := server.Nodes.CurrentFromRing(); ok &&
				node.Active && !node.Maintenance {

				// The host is active and is not in maintenance
				request.URL.Host = fmt.Sprintf("%s:%d", node.Host, node.Port)

				// Prepare next host
				server.Nodes.TwistRing()

				if server.checkNode(request.URL.Host) {
					response, err := server.transport.RoundTrip(request)
					if err == nil {
						// If response is sucess, return
						return response
					}
					errlog.Println(err)
				}
			} else {

				// Use next host if not active or maintenance mode
				server.Nodes.TwistRing()
			}
		}
	} else {

		// If is not round robin mode, use first registered host
		if nodes, total := server.Nodes.GetAll(); total > 0 {
			if server.byPriority {
				sort.Sort(byPriority(nodes))
			}
			for _, node := range nodes {
				if node.Active && !node.Maintenance {

					// The host is active and is not in maintenance
					request.URL.Host = fmt.Sprintf("%s:%d", node.Host, node.Port)
					if server.checkNode(request.URL.Host) {
						response, err := http.DefaultTransport.RoundTrip(request)
						if err == nil {
							// If response is sucess, return
							return response
						}
						errlog.Println(err)
					}
				}
			}
		}
	}

	stdlog.Println("Warning: no one of the nodes is active")

	return nil
}

// call 'PUT', 'POST', 'DELETE' request to the node
func (server *Server) processUpdate(request *http.Request) *http.Response {
	// grab update request
	proxyRequestData, err := httputil.DumpRequest(request, true)
	if err != nil {

		// if unsuccessful, return nil response
		errlog.Println(err)
		return nil
	}
	var host string
	var response *http.Response
	if nodes, total := server.Nodes.GetAll(); total > 0 {
		answer := make(chan *http.Response, total)
		done := make(chan struct{}, total)
		for _, node := range nodes {
			if node.Active {

				host = fmt.Sprintf("%s:%d", node.Host, node.Port)

				// create new queue job
				job := &queueJob{
					done:   done,
					query:  make(chan []byte, 1),
					answer: answer,
				}
				job.query <- proxyRequestData

				queue, _ := server.queues.check(host)
				queue.jobs <- job
				queue.task <- doJobTask
			}
		}
		timeout := time.NewTimer(time.Second * server.responseTimeout)
		for {
			select {
			case response = <-answer:
				return response
			case <-timeout.C:
				return response
			}
		}
	}
	return response
}

// worker receive a data from the queue and send it to the node
func (server *Server) worker(q *queue) {
	defer func() {
		if recovery := recover(); recovery != nil {
			errlog.Println("Recovered in worker routine", recovery)
			// the worker recovers again
			go server.worker(q)
		} else {
			q.response <- struct{}{}
			stdlog.Println("Worker closed for", q.id)
		}
	}()
	stdlog.Println("Worker started for", q.id)
	for {
		select {
		case task := <-q.task:
			switch task {
			case doJobTask:
				server.doUpdate(q)
			}
			continue
		default:
		}
		select {
		case task := <-q.task:
			switch task {
			case doJobTask:
				server.doUpdate(q)
			}
			continue
		case <-q.quit:
			return
		case <-q.ask:
			q.response <- struct{}{}
		}
	}
}

func (server *Server) doUpdate(q *queue) {
	// check the node
	for {
		if server.checkNode(q.id) {
			break
		}
		stdlog.Println("Node", q.id, "does not ready for updates")
		stdlog.Println("try again in", server.check.Seconds, "seconds")
		timeout := time.NewTimer(time.Second * server.check.Seconds)
		select {
		//  Repeat by timeout
		case <-timeout.C:
			continue
		case <-q.quit:
			q.task <- doJobTask
			return
		case <-q.ask:
			q.response <- struct{}{}
		}
	}
	// if the node is alive, post data
	job := <-q.jobs
	data := <-job.query
	if response, err := server.dispatchRequest(q.id, data); err != nil {

		// Job does not done
		errlog.Println(err)

	} else {

		// job done
		if len(job.done) == 0 {
			// send first response and done signal
			job.done <- struct{}{}
			job.answer <- response
		} else {
			// just close connection
			response.Body.Close()
		}
	}
}

// check the node
func (server *Server) checkNode(host string) bool {
	response, err := http.Get(protocolHTTP + "://" + host + server.check.URL)
	if err != nil {
		return false
	}

	defer response.Body.Close()
	// if pattern does not exist, should be true
	if server.check.Pattern == "" {
		return true
	}

	data, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return false
	}
	// check of regexp pattern
	valid := regexp.MustCompile(server.check.Pattern)
	return valid.MatchString(string(data))
}

// Reproduce request to specified node and capture response
func (server *Server) dispatchRequest(host string, data []byte) (*http.Response, error) {
	reader := bufio.NewReader(bytes.NewBuffer(data))
	request, err := http.ReadRequest(reader)
	if err != nil {
		return nil, err
	}
	request.Body = ioutil.NopCloser(reader)
	request.URL.Scheme = protocolHTTP
	request.URL.Host = host

	response, err := server.transport.RoundTrip(request)
	if err != nil {
		return nil, err
	}
	return response, nil
}
<commit_msg>Bumped version number to 0.1.10<commit_after>// Copyright 2015 Igor Dolzhikov. All rights reserved.
// Use of this source code is governed by a license
// that can be found in the LICENSE file.

package spawn

import (
	"bufio"
	"bytes"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/http/httputil"
	"os"
	"regexp"
	"sort"
	"time"

	"github.com/takama/router"
)

const (

	// VERSION - current version of the service
	VERSION = "0.1.10"

	// DATE - revision date of the service
	DATE = "2015-04-03T17:40:17Z"

	// MaxSignals - maximum count of update signals
	MaxSignals = 1000

	// MaxJobs - maximum count of update jobs for every bundle
	MaxJobs = 100000

	// DefaultTimeout is a timeout for the worker's response
	DefaultTimeout time.Duration = 10

	// HTTP methods, which should be queued
	protocolHTTP = "http"
	methodGET    = "GET"
	methodPOST   = "POST"
	methodPUT    = "PUT"
	methodDELETE = "DELETE"

	// Job signals
	responseSignal = iota
	nodeJobSignal
)

// simplest logger, which initialized during starts of the application
var (
	stdlog = log.New(os.Stdout, "", log.Ldate|log.Ltime)
	errlog = log.New(os.Stderr, "", log.Ldate|log.Ltime|log.Lshortfile)
)

// Server Record
type Server struct {

	// Server name/description
	Name string

	// Node Bundle contains the Node records
	Nodes *NodeBundle
	// contains filtered or unexported fields

	// Embeded router
	*router.Router

	// Response signal channel
	response chan struct{}

	// responseTimeout is a timeout for worker's response
	responseTimeout time.Duration

	// job signal channel
	job chan int

	// quit signal channel
	quit chan struct{}

	// round robin mode
	roundRobin bool

	// nodes will queried according to priority
	byPriority bool

	// nodes health check
	check HealthCheck

	// Queue Bundle contains the queue records
	queues *queueBundle

	// Node connection transport
	transport http.RoundTripper
}

// HealthCheck contains parameters which used for checking node
type HealthCheck struct {

	// health check time of the node in seconds
	Seconds time.Duration `json:"seconds"`

	// url which will be checked
	URL string `json:"url"`

	// regexp pattern for extended check analyze
	Pattern string `json:"regexp"`
}

// NewServer creates a new server which contains the nodes/queues
func NewServer(name string) (*Server, error) {

	// Init the router
	r := router.New()
	r.PanicHandler = panicHandler
	r.NotFound = notFound
	r.Logger = logger
	r.CustomHandler = baseHandler

	// Init the Server
	server := &Server{
		Name:            name,
		Router:          r,
		responseTimeout: DefaultTimeout,
		response:        make(chan struct{}),
		job:             make(chan int, MaxSignals),
		quit:            make(chan struct{}),
		transport:       http.DefaultTransport,
	}

	// Create and init nodes bundle
	server.Nodes = &NodeBundle{
		Server:  server,
		records: make(map[string]map[uint64]Node),
	}

	// Create and init queues bundle
	server.queues = &queueBundle{records: make(map[string]*queue)}

	return server, nil
}

// Run the server, init the handlers, init the specified modes
// If handler RequestHandler is not defined used default handler
// with standard handling of the requests/responses
func (server *Server) Run(
	hostPort, apiHostPort string,
	handler RequestHandler,
	nodes []Node,
	roundRobin, byPriority bool,
	check HealthCheck,
) (status string, err error) {

	// if used round-robin mode
	if roundRobin {
		stdlog.Println(server.Name, "will used 'round-robin' mode")
		server.roundRobin = roundRobin
	}

	// if used by-priority mode
	if byPriority {
		stdlog.Println("Nodes will queried according to priority")
		server.byPriority = byPriority
	}

	// Init the Nodes update channel
	server.Nodes.update = make(chan nodeJob, MaxJobs)

	// Starts the worker which manage server's jobs
	go server.manage()

	// Init the Nodes settings
	if !server.Nodes.SetAll(nodes) {
		status = server.Name + " is not loaded"
		err = errors.New("The nodes settings in config have incorrect values")
		return
	}

	// Init a health check settings
	server.check = check

	// The info handler returns a system status of the application
	server.GET("/info", infoHandler)

	// Lists methods, which display how to use API
	server.GET("/list", displayAllMethods)
	server.GET("/list/nodes", displayAllNodeMethods)
	server.GET("/list/nodes/get", displayGetNodeMethods)
	server.GET("/list/nodes/set", displaySetNodeMethods)
	server.GET("/list/nodes/delete", displayDeleteNodeMethods)

	// Init API methods for the Nodes
	server.GET("/nodes/:host/:port", server.Nodes.getRecord)
	server.GET("/nodes/:host", server.Nodes.getAllRecordsByHost)
	server.GET("/nodes", server.Nodes.getAllRecords)
	server.PUT("/nodes/:host/:port", server.Nodes.putRecord)
	server.PUT("/nodes", server.Nodes.putAllRecords)
	server.DELETE("/nodes/:host/:port", server.Nodes.deleteRecord)
	server.DELETE("/nodes/:host", server.Nodes.deleteAllRecordsByHost)
	server.DELETE("/nodes", server.Nodes.deleteAllRecords)

	go server.Listen(apiHostPort)
	go func() {
		p := new(proxy)
		if handler != nil {
			p.handler = handler
		} else {
			p.handler = server.proxyHandler
		}
		if err := http.ListenAndServe(hostPort, p); err != nil {
			errlog.Fatal(err)
		}
	}()

	status = server.Name + " loaded successfully"

	return
}

// Shutdown closes the server graceful
func (server *Server) Shutdown() (status string, err error) {

	// Set timer to wait one minute
	timeout := time.NewTimer(time.Second * 30)

	// a unwanted response sweeps if exist
	for {
		select {
		case <-server.response:
			continue
		default:
		}
		break
	}

	// sends a 'quit' signal
	server.quit <- struct{}{}

	status = server.Name + " connections closed"
	select {

	// Exit by timeout if jobs did not done
	case <-timeout.C:
		err = errors.New("timeout")
		return
	// Exit after all jobs done
	case <-server.response:
		return
	}
}

// Manage routine which manage all jobs
func (server *Server) manage() {
	defer func() {
		if recovery := recover(); recovery != nil {
			errlog.Println("Recovered in Manage routine", recovery)
			// Recover routine
			go server.manage()
		} else {
			stdlog.Println("Manage routine stoped")
			server.response <- struct{}{}
		}
	}()
	for {
		select {
		case job := <-server.job:
			server.doJob(job)
			continue
		default:
		}
		select {
		case job := <-server.job:
			server.doJob(job)
			continue
		case <-server.quit:
			return
		}
	}
}

// Do updates depended by the signal
func (server *Server) doJob(signal int) {
	defer func() {
		if recovery := recover(); recovery != nil {
			errlog.Println("Recovered in do job routine", recovery)
		}
	}()
	switch signal {
	case responseSignal:
		server.response <- struct{}{}
	case nodeJobSignal:
		server.Nodes.updateRecords()
		server.Nodes.InitRing()
	}
}

// proxyHandler manages all requests/responses
func (server *Server) proxyHandler(request *http.Request) *http.Response {

	// Add "X-Forwarded-For" to repost remote host IP
	if request.Header.Get("X-Forwarded-For") == "" {
		request.Header.Add("X-Forwarded-For", request.RemoteAddr)
	}

	// Use HTTP scheme
	request.URL.Scheme = protocolHTTP

	// If requests should not be queued, get result immediately
	if request.Method != methodPOST &&
		request.Method != methodPUT &&
		request.Method != methodDELETE {

		return server.processReceive(request)
	}

	return server.processUpdate(request)
}

// call 'GET' and others requests to the node using defined mode
func (server *Server) processReceive(request *http.Request) *http.Response {
	if server.roundRobin {

		// Use round robin to get data from the host
		for count := 0; count < server.Nodes.ring.Len(); count++ {
			if node, ok := server.Nodes.CurrentFromRing(); ok &&
				node.Active && !node.Maintenance {

				// The host is active and is not in maintenance
				request.URL.Host = fmt.Sprintf("%s:%d", node.Host, node.Port)

				// Prepare next host
				server.Nodes.TwistRing()

				if server.checkNode(request.URL.Host) {
					response, err := server.transport.RoundTrip(request)
					if err == nil {
						// If response is sucess, return
						return response
					}
					errlog.Println(err)
				}
			} else {

				// Use next host if not active or maintenance mode
				server.Nodes.TwistRing()
			}
		}
	} else {

		// If is not round robin mode, use first registered host
		if nodes, total := server.Nodes.GetAll(); total > 0 {
			if server.byPriority {
				sort.Sort(byPriority(nodes))
			}
			for _, node := range nodes {
				if node.Active && !node.Maintenance {

					// The host is active and is not in maintenance
					request.URL.Host = fmt.Sprintf("%s:%d", node.Host, node.Port)
					if server.checkNode(request.URL.Host) {
						response, err := http.DefaultTransport.RoundTrip(request)
						if err == nil {
							// If response is sucess, return
							return response
						}
						errlog.Println(err)
					}
				}
			}
		}
	}

	stdlog.Println("Warning: no one of the nodes is active")

	return nil
}

// call 'PUT', 'POST', 'DELETE' request to the node
func (server *Server) processUpdate(request *http.Request) *http.Response {
	// grab update request
	proxyRequestData, err := httputil.DumpRequest(request, true)
	if err != nil {

		// if unsuccessful, return nil response
		errlog.Println(err)
		return nil
	}
	var host string
	var response *http.Response
	if nodes, total := server.Nodes.GetAll(); total > 0 {
		answer := make(chan *http.Response, total)
		done := make(chan struct{}, total)
		for _, node := range nodes {
			if node.Active {

				host = fmt.Sprintf("%s:%d", node.Host, node.Port)

				// create new queue job
				job := &queueJob{
					done:   done,
					query:  make(chan []byte, 1),
					answer: answer,
				}
				job.query <- proxyRequestData

				queue, _ := server.queues.check(host)
				queue.jobs <- job
				queue.task <- doJobTask
			}
		}
		timeout := time.NewTimer(time.Second * server.responseTimeout)
		for {
			select {
			case response = <-answer:
				return response
			case <-timeout.C:
				return response
			}
		}
	}
	return response
}

// worker receive a data from the queue and send it to the node
func (server *Server) worker(q *queue) {
	defer func() {
		if recovery := recover(); recovery != nil {
			errlog.Println("Recovered in worker routine", recovery)
			// the worker recovers again
			go server.worker(q)
		} else {
			q.response <- struct{}{}
			stdlog.Println("Worker closed for", q.id)
		}
	}()
	stdlog.Println("Worker started for", q.id)
	for {
		select {
		case task := <-q.task:
			switch task {
			case doJobTask:
				server.doUpdate(q)
			}
			continue
		default:
		}
		select {
		case task := <-q.task:
			switch task {
			case doJobTask:
				server.doUpdate(q)
			}
			continue
		case <-q.quit:
			return
		case <-q.ask:
			q.response <- struct{}{}
		}
	}
}

func (server *Server) doUpdate(q *queue) {
	// check the node
	for {
		if server.checkNode(q.id) {
			break
		}
		stdlog.Println("Node", q.id, "does not ready for updates")
		stdlog.Println("try again in", server.check.Seconds, "seconds")
		timeout := time.NewTimer(time.Second * server.check.Seconds)
		select {
		//  Repeat by timeout
		case <-timeout.C:
			continue
		case <-q.quit:
			q.task <- doJobTask
			return
		case <-q.ask:
			q.response <- struct{}{}
		}
	}
	// if the node is alive, post data
	job := <-q.jobs
	data := <-job.query
	if response, err := server.dispatchRequest(q.id, data); err != nil {

		// Job does not done
		errlog.Println(err)

	} else {

		// job done
		if len(job.done) == 0 {
			// send first response and done signal
			job.done <- struct{}{}
			job.answer <- response
		} else {
			// just close connection
			response.Body.Close()
		}
	}
}

// check the node
func (server *Server) checkNode(host string) bool {
	response, err := http.Get(protocolHTTP + "://" + host + server.check.URL)
	if err != nil {
		return false
	}

	defer response.Body.Close()
	// if pattern does not exist, should be true
	if server.check.Pattern == "" {
		return true
	}

	data, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return false
	}
	// check of regexp pattern
	valid := regexp.MustCompile(server.check.Pattern)
	return valid.MatchString(string(data))
}

// Reproduce request to specified node and capture response
func (server *Server) dispatchRequest(host string, data []byte) (*http.Response, error) {
	reader := bufio.NewReader(bytes.NewBuffer(data))
	request, err := http.ReadRequest(reader)
	if err != nil {
		return nil, err
	}
	request.Body = ioutil.NopCloser(reader)
	request.URL.Scheme = protocolHTTP
	request.URL.Host = host

	response, err := server.transport.RoundTrip(request)
	if err != nil {
		return nil, err
	}
	return response, nil
}
<|endoftext|>


<commit_before>// Copyright 2015 The httpserver Authors. All rights reserved.  Use of this
// source code is governed by a MIT-style license that can be found in the
// LICENSE file.
package httpserver

import (
	"fmt"
	"net/http"
	"text/template"

	"github.com/gorilla/mux"
)

type Route struct {
	path       string
	handleFunc http.HandlerFunc
}

func NewRoute(p string, hf http.HandlerFunc) *Route {

	r := &Route{path: p, handleFunc: hf}
	return r

}

type ServerError struct {
	Msg string
}

func NewError(msg string) *ServerError {
	s := &ServerError{Msg: msg}
	return s
}

type HttpServer struct {
	port             string
	address          string
	errTemplate      *template.Template
	notFoundTemplate *template.Template
	router           *mux.Router
}

func NewHttpServer(a string, p string) *HttpServer {
	r := mux.NewRouter()
	s := &HttpServer{router: r, address: a, port: p}
	return s
}

type RouteHandler interface {
	GetRoutes() []*Route
}

type ErrHandler func(http.HandlerFunc) http.HandlerFunc

func (s *HttpServer) SetErrTemplate(t *template.Template) {
	s.errTemplate = t
}

func (s *HttpServer) SetNotFoundTemplate(t *template.Template) {
	s.notFoundTemplate = t
}

func (s *HttpServer) errorHandler(fn http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		defer func() {
			if recoverErr := recover(); recoverErr != nil {
				error := NewError(fmt.Sprintf("\"%v\"", recoverErr))
				w.WriteHeader(500)
				if s.errTemplate != nil {
					s.errTemplate.Execute(w, error)
				} else {
					fmt.Fprintf(w, fmt.Sprintf("\"%v\"", recoverErr))
				}
			}
		}()
		fmt.Println("error handler func...")
		fn(w, r)
	}
}
func (s *HttpServer) NotFound(w http.ResponseWriter, r *http.Request) {

	w.WriteHeader(404)
	if s.notFoundTemplate != nil {
		s.notFoundTemplate.Execute(w, nil)
	} else {
		fmt.Fprintf(w, "Not found")
	}

}

func (s *HttpServer) DeployAtBase(h RouteHandler) {
	s.Deploy("", h)
}

func (s *HttpServer) Deploy(context string, h RouteHandler) {
	routes := h.GetRoutes()
	for _, r := range routes {
		s.router.HandleFunc(fmt.Sprintf("%s/%s", context, r.path), s.errorHandler(r.handleFunc))
	}
	http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./static"))))
	http.Handle("/", s.router)
	s.router.NotFoundHandler = http.HandlerFunc(s.NotFound)
}

func (s *HttpServer) Start() error {
	return http.ListenAndServe(fmt.Sprintf("%s:%s", s.address, s.port), nil)
}
<commit_msg>http method check added<commit_after>// Copyright 2015 The httpserver Authors. All rights reserved.  Use of this
// source code is governed by a MIT-style license that can be found in the
// LICENSE file.
package httpserver

import (
	"fmt"
	"net/http"
	"text/template"

	"github.com/gorilla/mux"
)

type Route struct {
	Path       string
	Method     string
	HandleFunc http.HandlerFunc
}

func NewRoute(p string, m string, hf http.HandlerFunc) *Route {
	r := &Route{Path: p, Method: m, HandleFunc: hf}
	return r
}

func (r *Route) HasIncorrectHttpMethod(method string) bool {

	if len(r.Method) != 0 && method != r.Method {
		return true
	}
	return false

}

type ServerError struct {
	Msg string
}

func NewError(msg string) *ServerError {
	s := &ServerError{Msg: msg}
	return s
}

type HttpServer struct {
	port             string
	address          string
	errTemplate      *template.Template
	notFoundTemplate *template.Template
	router           *mux.Router
}

func NewHttpServer(a string, p string) *HttpServer {
	r := mux.NewRouter()
	s := &HttpServer{router: r, address: a, port: p}
	return s
}

type RouteHandler interface {
	GetRoutes() []*Route
}

func (s *HttpServer) SetErrTemplate(t *template.Template) {
	s.errTemplate = t
}

func (s *HttpServer) SetNotFoundTemplate(t *template.Template) {
	s.notFoundTemplate = t
}

func (s *HttpServer) errorHandler(route *Route) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		defer func() {
			if recoverErr := recover(); recoverErr != nil {
				error := NewError(fmt.Sprintf("\"%v\"", recoverErr))
				w.WriteHeader(500)
				if s.errTemplate != nil {
					s.errTemplate.Execute(w, error)
				} else {
					fmt.Fprintf(w, fmt.Sprintf("\"%v\"", recoverErr))
				}
			}
		}()
		if route.HasIncorrectHttpMethod(r.Method) {
			http.Error(w, "Method not allowed", 405)
			return
		}
		route.HandleFunc(w, r)
	}
}
func (s *HttpServer) NotFound(w http.ResponseWriter, r *http.Request) {

	w.WriteHeader(404)
	if s.notFoundTemplate != nil {
		s.notFoundTemplate.Execute(w, nil)
	} else {
		fmt.Fprintf(w, "Not found")
	}

}

func (s *HttpServer) DeployAtBase(h RouteHandler) {
	s.Deploy("", h)
}

func (s *HttpServer) Deploy(context string, h RouteHandler) {
	routes := h.GetRoutes()
	for _, r := range routes {
		s.router.HandleFunc(fmt.Sprintf("%s/%s", context, r.Path), s.errorHandler(r))
	}
	http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./static"))))
	http.Handle("/", s.router)
	s.router.NotFoundHandler = http.HandlerFunc(s.NotFound)
}

func (s *HttpServer) Start() error {
	return http.ListenAndServe(fmt.Sprintf("%s:%s", s.address, s.port), nil)
}
<|endoftext|>


<commit_before>// Title：统一的数据库服务
//
// Description:
//
// Author:black
//
// Createtime:2013-08-06 17:13
//
// Version:1.0
//
// 修改历史:版本号 修改日期 修改人 修改说明
//
// 1.0 2013-08-06 17:13 black 创建文档
package lessgo

import (
	"fmt"
	"github.com/hjqhezgh/commonlib"
	"math"
	"strings"
)

//构建查询的sql语句
func bulidSelectSql(entity Entity, colmuns []column) (string, string) {

	dataSql := "select " + entity.Id + "." + entity.Pk + ","

	if len(colmuns) > 0 {
		for _, column := range colmuns {
			if strings.Contains(column.Field, ".") {
				dataSql += column.Field + ","
			} else {
				dataSql += entity.Id + "." + column.Field + ","
			}
		}
	} else {
		for _, field := range entity.Fields {
			dataSql += entity.Id + "." + field.Name + ","
		}

		for _, ref := range entity.Refs {

			for _, field := range ref.Fields {
				if ref.Alias != ""{
					dataSql += ref.Alias + "." + field.Name + ","
				}else{
					dataSql += ref.Entity + "." + field.Name + ","
				}

			}

		}
	}

	dataSql = commonlib.Substr(dataSql, 0, len(dataSql)-1)

	dataSql += " from " + entity.Id + " " + entity.Id

	for _, ref := range entity.Refs {
		if ref.Alias != ""{
			dataSql += fmt.Sprintf(" left join %v %v on %v.%v=%v.%v", ref.Entity, ref.Alias, entity.Id, ref.Field, ref.Alias, ref.RefEntityField)
		}else{
			dataSql += fmt.Sprintf(" left join %v %v on %v.%v=%v.%v", ref.Entity, ref.Entity, entity.Id, ref.Field, ref.Entity, ref.RefEntityField)
		}
	}

	countSql := "select count(1) from " + entity.Id

	return countSql, dataSql
}

//构建查询
func bulidWhereSql(entity Entity, countSql, dataSql string, searchParam []search) (string, string, []interface{}) {

	params := []interface{}{}

	if len(searchParam) > 0 {
		countSql += " where 1=1 "
		dataSql += " where 1=1 "

		for _, search := range searchParam {
			if search.Value != "" {

				opera := ""

				switch search.SearchType {
				case "like":
					opera = "like"
				case "eq":
					opera = "="
				case "ge":
					opera = ">="
				case "le":
					opera = "<="
				case "gt":
					opera = ">"
				case "lt":
					opera = "<"
				}

				countSql += " and " + entity.Id + "." + search.Field + " " + opera + " ? "
				dataSql += " and " + entity.Id + "." + search.Field + " " + opera + " ? "

				if search.SearchType == "like" {
					params = append(params, "%"+search.Value+"%")
				} else {
					params = append(params, search.Value)
				}
			}
		}

		return countSql, dataSql, params
	} else {
		return countSql, dataSql, []interface{}{}
	}

	return countSql, dataSql, []interface{}{}
}

//查找分页数据
func findTraditionPage(entity Entity, currPageNo, pageSize int, searchParam []search, colmuns []column) (*commonlib.TraditionPage, error) {

	countSql, dataSql := bulidSelectSql(entity, colmuns)

	countSql, dataSql, params := bulidWhereSql(entity, countSql, dataSql, searchParam)

	Log.Debug(countSql)

	db := GetMySQL()
	defer db.Close()

	rows, err := db.Query(countSql, params...)

	if err != nil {
		Log.Error(err.Error())
		return nil, err
	}

	totalNum := 0

	if rows.Next() {
		err := rows.Scan(&totalNum)

		if err != nil {
			Log.Error(err.Error())
			return nil, err
		}
	}

	dataSql += " order by " + entity.Pk + " desc "
	dataSql += " limit ?,?"

	totalPage := int(math.Ceil(float64(totalNum) / float64(pageSize)))

	if currPageNo > totalPage {
		currPageNo = totalPage
	}

	params = append(params, (currPageNo-1)*pageSize, pageSize)
	Log.Debug(dataSql)

	rows, err = db.Query(dataSql, params...)

	if err != nil {
		Log.Error(err.Error())
		return nil, err
	}

	objects := []interface{}{}

	for rows.Next() {

		model := new(Model)
		model.Entity = entity
		model.Id = 0
		model.Props = []*Prop{}

		fillObjects := []interface{}{}

		fillObjects = append(fillObjects, &model.Id)

		for _, column := range colmuns {
			prop := new(Prop)
			prop.Name = column.Field
			prop.Value = ""
			fillObjects = append(fillObjects, &prop.Value)
			model.Props = append(model.Props, prop)
		}

		err = commonlib.PutRecord(rows, fillObjects...)

		if err != nil {
			Log.Error(err.Error())
			return nil, err
		}

		objects = append(objects, model)
	}

	return commonlib.BulidTraditionPage(currPageNo, pageSize, totalNum, objects), nil
}

//查找分页数据
func findAllData(entity Entity) ([]*Model, error) {

	_, dataSql := bulidSelectSql(entity, []column{})

	Log.Debug(dataSql)

	db := GetMySQL()
	defer db.Close()

	dataSql += " order by " + entity.Pk + " desc "

	Log.Debug(dataSql)

	objects := []*Model{}

	rows, err := db.Query(dataSql)

	if err != nil {
		Log.Error(err.Error())
		return objects, err
	}

	for rows.Next() {

		dataModel := new(Model)
		dataModel.Entity = entity
		dataModel.Id = 0
		dataModel.Props = []*Prop{}

		fillObjects := []interface{}{}

		fillObjects = append(fillObjects, &dataModel.Id)

		for _, field := range entity.Fields {
			prop := new(Prop)
			prop.Name = field.Name
			prop.Value = ""
			fillObjects = append(fillObjects, &prop.Value)
			dataModel.Props = append(dataModel.Props, prop)
		}

		for _, ref := range entity.Refs {
			for _, field := range ref.Fields {
				prop := new(Prop)
				prop.Name = ref.Entity + "." + field.Name
				prop.Value = ""
				fillObjects = append(fillObjects, &prop.Value)
				dataModel.Props = append(dataModel.Props, prop)
			}
		}

		err = commonlib.PutRecord(rows, fillObjects...)

		if err != nil {
			Log.Error(err.Error())
			return []*Model{}, err
		}

		objects = append(objects, dataModel)
	}

	return objects, nil
}

//添加数据
func insert(entity Entity, model *Model, elements []element) (id int, err error) {

	sql := "insert into " + entity.Id + "("
	valueSql := " values ("

	params := []interface{}{}

	for index, element := range elements {
		sql += element.Field

		valueSql += "?"

		if index < len(elements)-1 {
			sql += ","
			valueSql += ","
		}

		params = append(params, getPropValue(model, element.Field))
	}
	fmt.Println(params)
	sql += ")"
	valueSql += ")"
	sql += valueSql

	Log.Debug(sql)

	db := GetMySQL()
	defer db.Close()

	stmt, err := db.Prepare(sql)

	if err != nil {
		Log.Warn(err.Error())
		return 0, err
	}

	res, err := stmt.Exec(params...)

	if err != nil {
		Log.Warn(err.Error())
		return 0, err
	}

	id64, err := res.LastInsertId()

	if err != nil {
		Log.Warn(err.Error())

		return 0, err
	}

	return int(id64), nil
}

//根据id查找对象
func findById(entity Entity, id string) (*Model, error) {

	dataSql := "select " + entity.Pk + ","

	for index, field := range entity.Fields {
		dataSql += field.Name
		if index < len(entity.Fields)-1 {
			dataSql += ","
		}
	}

	dataSql += " from " + entity.Id + " where " + entity.Pk + "=?"

	Log.Debug(dataSql)

	db := GetMySQL()
	defer db.Close()

	rows, err := db.Query(dataSql, id)

	if err != nil {
		Log.Warn(err.Error())
		return nil, err
	}

	model := new(Model)
	model.Entity = entity
	model.Id = 0
	model.Props = []*Prop{}

	if rows.Next() {

		fillObjects := []interface{}{}

		fillObjects = append(fillObjects, &model.Id)

		for _, field := range entity.Fields {
			prop := new(Prop)
			prop.Name = field.Name
			prop.Value = ""
			fillObjects = append(fillObjects, &prop.Value)
			model.Props = append(model.Props, prop)
		}

		err = commonlib.PutRecord(rows, fillObjects...)

		if err != nil {
			return nil, err
		}
	}

	return model, nil
}

//修改
func modify(entity Entity, model *Model, elements []element) error {
	sql := "update " + entity.Id + " set "

	params := []interface{}{}

	for index, element := range elements {
		sql += element.Field + "=?"

		if index < len(elements)-1 {
			sql += ","
		}

		params = append(params, getPropValue(model, element.Field))
	}

	sql += " where " + entity.Pk + "=?"
	params = append(params, model.Id)

	Log.Debug(sql)

	db := GetMySQL()
	defer db.Close()

	stmt, err := db.Prepare(sql)
	if err != nil {
		Log.Warn(err.Error())
		return err
	}

	_, err = stmt.Exec(params...)

	if err != nil {
		Log.Warn(err.Error())
		return err
	}

	return nil
}

//删除
func delete(entity Entity, id string) error {
	sql := "delete from " + entity.Id + " where " + entity.Pk + "=?"

	Log.Debug(sql)

	db := GetMySQL()
	defer db.Close()

	stmt, err := db.Prepare(sql)
	if err != nil {
		Log.Warn(err.Error())
		return err
	}

	_, err = stmt.Exec(id)

	if err != nil {
		Log.Warn(err.Error())
		return err
	}

	return nil
}
<commit_msg>自表连接的bug<commit_after>// Title：统一的数据库服务
//
// Description:
//
// Author:black
//
// Createtime:2013-08-06 17:13
//
// Version:1.0
//
// 修改历史:版本号 修改日期 修改人 修改说明
//
// 1.0 2013-08-06 17:13 black 创建文档
package lessgo

import (
	"fmt"
	"github.com/hjqhezgh/commonlib"
	"math"
	"strings"
)

//构建查询的sql语句
func bulidSelectSql(entity Entity, colmuns []column) (string, string) {

	dataSql := "select " + entity.Id + "." + entity.Pk + ","

	if len(colmuns) > 0 {
		for _, column := range colmuns {
			if strings.Contains(column.Field, ".") {
				dataSql += column.Field + ","
			} else {
				dataSql += entity.Id + "." + column.Field + ","
			}
		}
	} else {
		for _, field := range entity.Fields {
			dataSql += entity.Id + "." + field.Name + ","
		}

		for _, ref := range entity.Refs {

			for _, field := range ref.Fields {
				if ref.Alias != "" {
					dataSql += ref.Alias + "." + field.Name + ","
				} else {
					dataSql += ref.Entity + "." + field.Name + ","
				}

			}

		}
	}

	dataSql = commonlib.Substr(dataSql, 0, len(dataSql)-1)

	dataSql += " from " + entity.Id + " " + entity.Id

	for _, ref := range entity.Refs {
		if ref.Alias != "" {
			dataSql += fmt.Sprintf(" left join %v %v on %v.%v=%v.%v", ref.Entity, ref.Alias, entity.Id, ref.Field, ref.Alias, ref.RefEntityField)
		} else {
			dataSql += fmt.Sprintf(" left join %v %v on %v.%v=%v.%v", ref.Entity, ref.Entity, entity.Id, ref.Field, ref.Entity, ref.RefEntityField)
		}
	}

	countSql := "select count(1) from " + entity.Id

	return countSql, dataSql
}

//构建查询
func bulidWhereSql(entity Entity, countSql, dataSql string, searchParam []search) (string, string, []interface{}) {

	params := []interface{}{}

	if len(searchParam) > 0 {
		countSql += " where 1=1 "
		dataSql += " where 1=1 "

		for _, search := range searchParam {
			if search.Value != "" {

				opera := ""

				switch search.SearchType {
				case "like":
					opera = "like"
				case "eq":
					opera = "="
				case "ge":
					opera = ">="
				case "le":
					opera = "<="
				case "gt":
					opera = ">"
				case "lt":
					opera = "<"
				}

				countSql += " and " + entity.Id + "." + search.Field + " " + opera + " ? "
				dataSql += " and " + entity.Id + "." + search.Field + " " + opera + " ? "

				if search.SearchType == "like" {
					params = append(params, "%"+search.Value+"%")
				} else {
					params = append(params, search.Value)
				}
			}
		}

		return countSql, dataSql, params
	} else {
		return countSql, dataSql, []interface{}{}
	}

	return countSql, dataSql, []interface{}{}
}

//查找分页数据
func findTraditionPage(entity Entity, currPageNo, pageSize int, searchParam []search, colmuns []column) (*commonlib.TraditionPage, error) {

	countSql, dataSql := bulidSelectSql(entity, colmuns)

	countSql, dataSql, params := bulidWhereSql(entity, countSql, dataSql, searchParam)

	Log.Debug(countSql)

	db := GetMySQL()
	defer db.Close()

	rows, err := db.Query(countSql, params...)

	if err != nil {
		Log.Error(err.Error())
		return nil, err
	}

	totalNum := 0

	if rows.Next() {
		err := rows.Scan(&totalNum)

		if err != nil {
			Log.Error(err.Error())
			return nil, err
		}
	}

	dataSql += " order by " + entity.Pk + " desc "
	dataSql += " limit ?,?"

	totalPage := int(math.Ceil(float64(totalNum) / float64(pageSize)))

	if currPageNo > totalPage {
		currPageNo = totalPage
	}

	params = append(params, (currPageNo-1)*pageSize, pageSize)
	Log.Debug(dataSql)

	rows, err = db.Query(dataSql, params...)

	if err != nil {
		Log.Error(err.Error())
		return nil, err
	}

	objects := []interface{}{}

	for rows.Next() {

		model := new(Model)
		model.Entity = entity
		model.Id = 0
		model.Props = []*Prop{}

		fillObjects := []interface{}{}

		fillObjects = append(fillObjects, &model.Id)

		for _, column := range colmuns {
			prop := new(Prop)
			prop.Name = column.Field
			prop.Value = ""
			fillObjects = append(fillObjects, &prop.Value)
			model.Props = append(model.Props, prop)
		}

		err = commonlib.PutRecord(rows, fillObjects...)

		if err != nil {
			Log.Error(err.Error())
			return nil, err
		}

		objects = append(objects, model)
	}

	return commonlib.BulidTraditionPage(currPageNo, pageSize, totalNum, objects), nil
}

//查找分页数据
func findAllData(entity Entity) ([]*Model, error) {

	_, dataSql := bulidSelectSql(entity, []column{})

	Log.Debug(dataSql)

	db := GetMySQL()
	defer db.Close()

	dataSql += " order by " + entity.Pk + " desc "

	Log.Debug(dataSql)

	objects := []*Model{}

	rows, err := db.Query(dataSql)

	if err != nil {
		Log.Error(err.Error())
		return objects, err
	}

	for rows.Next() {

		dataModel := new(Model)
		dataModel.Entity = entity
		dataModel.Id = 0
		dataModel.Props = []*Prop{}

		fillObjects := []interface{}{}

		fillObjects = append(fillObjects, &dataModel.Id)

		for _, field := range entity.Fields {
			prop := new(Prop)
			prop.Name = field.Name
			prop.Value = ""
			fillObjects = append(fillObjects, &prop.Value)
			dataModel.Props = append(dataModel.Props, prop)
		}

		for _, ref := range entity.Refs {
			for _, field := range ref.Fields {
				prop := new(Prop)
				prop.Name = ref.Entity + "." + field.Name
				prop.Value = ""
				fillObjects = append(fillObjects, &prop.Value)
				dataModel.Props = append(dataModel.Props, prop)
			}
		}

		err = commonlib.PutRecord(rows, fillObjects...)

		if err != nil {
			Log.Error(err.Error())
			return []*Model{}, err
		}

		objects = append(objects, dataModel)
	}

	return objects, nil
}

//添加数据
func insert(entity Entity, model *Model, elements []element) (id int, err error) {

	sql := "insert into " + entity.Id + "("
	valueSql := " values ("

	params := []interface{}{}

	for index, element := range elements {
		sql += element.Field

		valueSql += "?"

		if index < len(elements)-1 {
			sql += ","
			valueSql += ","
		}

		params = append(params, getPropValue(model, element.Field))
	}
	fmt.Println(params)
	sql += ")"
	valueSql += ")"
	sql += valueSql

	Log.Debug(sql)

	db := GetMySQL()
	defer db.Close()

	stmt, err := db.Prepare(sql)

	if err != nil {
		Log.Warn(err.Error())
		return 0, err
	}

	res, err := stmt.Exec(params...)

	if err != nil {
		Log.Warn(err.Error())
		return 0, err
	}

	id64, err := res.LastInsertId()

	if err != nil {
		Log.Warn(err.Error())

		return 0, err
	}

	return int(id64), nil
}

//根据id查找对象
func findById(entity Entity, id string) (*Model, error) {

	dataSql := "select " + entity.Pk + ","

	for index, field := range entity.Fields {
		dataSql += field.Name
		if index < len(entity.Fields)-1 {
			dataSql += ","
		}
	}

	dataSql += " from " + entity.Id + " where " + entity.Pk + "=?"

	Log.Debug(dataSql)

	db := GetMySQL()
	defer db.Close()

	rows, err := db.Query(dataSql, id)

	if err != nil {
		Log.Warn(err.Error())
		return nil, err
	}

	model := new(Model)
	model.Entity = entity
	model.Id = 0
	model.Props = []*Prop{}

	if rows.Next() {

		fillObjects := []interface{}{}

		fillObjects = append(fillObjects, &model.Id)

		for _, field := range entity.Fields {
			prop := new(Prop)
			prop.Name = field.Name
			prop.Value = ""
			fillObjects = append(fillObjects, &prop.Value)
			model.Props = append(model.Props, prop)
		}

		err = commonlib.PutRecord(rows, fillObjects...)

		if err != nil {
			return nil, err
		}
	}

	return model, nil
}

//修改
func modify(entity Entity, model *Model, elements []element) error {
	sql := "update " + entity.Id + " set "

	params := []interface{}{}

	for index, element := range elements {
		sql += element.Field + "=?"

		if index < len(elements)-1 {
			sql += ","
		}

		params = append(params, getPropValue(model, element.Field))
	}

	sql += " where " + entity.Pk + "=?"
	params = append(params, model.Id)

	Log.Debug(sql)

	db := GetMySQL()
	defer db.Close()

	stmt, err := db.Prepare(sql)
	if err != nil {
		Log.Warn(err.Error())
		return err
	}

	_, err = stmt.Exec(params...)

	if err != nil {
		Log.Warn(err.Error())
		return err
	}

	return nil
}

//删除
func delete(entity Entity, id string) error {
	sql := "delete from " + entity.Id + " where " + entity.Pk + "=?"

	Log.Debug(sql)

	db := GetMySQL()
	defer db.Close()

	stmt, err := db.Prepare(sql)
	if err != nil {
		Log.Warn(err.Error())
		return err
	}

	_, err = stmt.Exec(id)

	if err != nil {
		Log.Warn(err.Error())
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"strconv"

	"github.com/HewlettPackard/oneview-golang/ov"
)

func main() {
	var (
		ClientOV *ov.OVClient
	)
	apiversion, _ := strconv.Atoi(os.Getenv("ONEVIEW_APIVERSION"))
	ovc := ClientOV.NewOVClient(
		os.Getenv("ONEVIEW_OV_USER"),
		os.Getenv("ONEVIEW_OV_PASSWORD"),
		os.Getenv("ONEVIEW_OV_DOMAIN"),
		os.Getenv("ONEVIEW_OV_ENDPOINT"),
		false,
		apiversion,
		"*")

	snmpv3User := ov.SNMPv3User{
		UserName:                 "user47",
		SecurityLevel:            "Authentication and privacy",
		AuthenticationProtocol:   "SHA1",
		AuthenticationPassphrase: "authPass",
		PrivacyProtocol:          "AES-128",
		PrivacyPassphrase:        "1234567812345678",
	}

	//Creating an SNMPv3 User
	_, err := ovc.CreateSNMPv3Users(snmpv3User)
	if err != nil {
		panic(err)
	} else {
		fmt.Println("#-----Created SNMPv3 User-----#")
	}

	//Get all the SNMPv3 User
	allsnmpv3user, err1 := ovc.GetSNMPv3Users("", "", "", "")
	if err1 != nil {
		panic(err1)
	} else {
		fmt.Println("#-----Got All SNMPv1 Trap Destinations-----#")
		for i := range allsnmpv3user.Members {
			fmt.Println(allsnmpv3user.Members[i])
		}
	}

	//Get SNMPv3 User by ID
	id := "49a96a2a-a200-44df-b600-3a4c3d9f267c"
	snmpv3User, err2 := ovc.GetSNMPv3UserById(id)
	if err2 != nil {
		panic(err2)
	} else {
		fmt.Printf("\n#-----Got SNMPv3 User of ID %v", id)
		fmt.Println(snmpv3User)
	}

	//Get SNMPv3 User by username
	username := "user47"
	snmpv3User, err3 := ovc.GetSNMPv3UserByUserName(username)
	if err3 != nil {
		panic(err3)
	} else {
		fmt.Printf("\n#-----Got SNMPv3 User of UserName %v", username)
		fmt.Println(snmpv3User)
	}

	//updating SNMPv3 User

	updated_snmpv3user := ov.SNMPv3User{
		Type:                     "Users",
		URI:                      "/rest/appliance/snmpv3-trap-forwarding/users/1e706f76-c585-4fc5-8a2b-86af678e4be1",
		Category:                 "SnmpV3User",
		ETAG:                     "2021-06-14T16:49:41.137Z",
		Id:                       "1e706f76-c585-4fc5-8a2b-86af678e4be1",
		UserName:                 "user2",
		SecurityLevel:            "Authentication and privacy",
		AuthenticationProtocol:   "SHA1",
		AuthenticationPassphrase: "dsfdsfdsfdfdsfds",
		PrivacyProtocol:          "AES-128",
		PrivacyPassphrase:        "dsfdsfdsf545454",
	}
	response, err4 := ovc.UpdateSNMPv3User(updated_snmpv3user, id)
	if err4 != nil {
		panic(err4)
	} else {
		fmt.Printf("\n#-----Updated SNMPv1 Trap Destinations port and community string: %v\n", response.URI)
	}

	// //Delete SNMPv3 User by ID
	err5 := ovc.DeleteSNMPv3UserById(id)
	if err5 != nil {
		panic(err5)
	} else {
		fmt.Printf("\n#-----Deleted SNMPv3 User of ID %v\n", id)
	}
	//Delete SNMPv3 User by UserName
	username1 := "user3"

	err6 := ovc.DeleteSNMPv3UserByName(username1)
	if err5 != nil {
		panic(err6)
	} else {
		fmt.Printf("\n#-----Deleted SNMPv3 User of Username %v\n", username1)
	}
}
<commit_msg>added snmp v3 user example<commit_after>package main

import (
	"fmt"
	"os"
	"strconv"

	"github.com/HewlettPackard/oneview-golang/ov"
)

func main() {
	var (
		ClientOV *ov.OVClient
	)
	apiversion, _ := strconv.Atoi(os.Getenv("ONEVIEW_APIVERSION"))
	ovc := ClientOV.NewOVClient(
		os.Getenv("ONEVIEW_OV_USER"),
		os.Getenv("ONEVIEW_OV_PASSWORD"),
		os.Getenv("ONEVIEW_OV_DOMAIN"),
		os.Getenv("ONEVIEW_OV_ENDPOINT"),
		false,
		apiversion,
		"*")

	snmpv3User := ov.SNMPv3User{
		UserName:                 "user0",
		SecurityLevel:            "Authentication and privacy",
		AuthenticationProtocol:   "SHA1",
		AuthenticationPassphrase: "authPass",
		PrivacyProtocol:          "AES-128",
		PrivacyPassphrase:        "1234567812345678",
	}

	snmpv3User1 := ov.SNMPv3User{
		UserName:                 "user1",
		SecurityLevel:            "Authentication and privacy",
		AuthenticationProtocol:   "SHA1",
		AuthenticationPassphrase: "authPass",
		PrivacyProtocol:          "AES-128",
		PrivacyPassphrase:        "1234567812345678",
	}

	//Creating an SNMPv3 User
	_, err := ovc.CreateSNMPv3Users(snmpv3User)
	if err != nil {
		panic(err)
	} else {
		fmt.Println("#-----Created SNMPv3 User-----#")
	}

	//Creating second SNMP User
	_, err0 := ovc.CreateSNMPv3Users(snmpv3User1)
	if err0 != nil {
		panic(err0)
	} else {
		fmt.Println("#-----Created SNMPv3 User-----#")
	}

	//Get all the SNMPv3 User
	allsnmpv3user, err1 := ovc.GetSNMPv3Users("", "", "", "")
	if err1 != nil {
		panic(err1)
	} else {
		fmt.Println("#-----Got All SNMPv3 Users-----#")
		for i := range allsnmpv3user.Members {
			fmt.Println(allsnmpv3user.Members[i])
		}
	}

	//Get SNMPv3 User by username
	snmpv3UserUserName, err3 := ovc.GetSNMPv3UserByUserName(snmpv3User.UserName)
	if err3 != nil {
		panic(err3)
	} else {
		fmt.Printf("\n#-----Got SNMPv3 User of UserName %v", snmpv3User.UserName)
		fmt.Println(snmpv3UserUserName)
	}

	//Get SNMPv3 User by ID

	snmpv3UserID, err2 := ovc.GetSNMPv3UserById(snmpv3UserUserName.Id)
	if err2 != nil {
		panic(err2)
	} else {
		fmt.Printf("\n#-----Got SNMPv3 User of ID %v", snmpv3UserUserName.Id)
		fmt.Println(snmpv3UserID)
	}

	//updating SNMPv3 User

	snmpv3UserID.PrivacyPassphrase = "55555555"
	snmpv3UserID.AuthenticationPassphrase = "aaaaaaaaa"

	response, err4 := ovc.UpdateSNMPv3User(snmpv3UserID, snmpv3UserUserName.Id)
	if err4 != nil {
		panic(err4)
	} else {
		fmt.Printf("\n#-----Updated SNMPv3 User Privacy passphrase and authenction passphrase : %v\n", response.URI)
	}

	// //Delete SNMPv3 User by ID
	err5 := ovc.DeleteSNMPv3UserById(response.Id)
	if err5 != nil {
		panic(err5)
	} else {
		fmt.Printf("\n#-----Deleted SNMPv3 User of ID %v\n", response.Id)
	}
	//Delete SNMPv3 User by UserName

	err6 := ovc.DeleteSNMPv3UserByName(snmpv3User1.UserName)
	if err5 != nil {
		panic(err6)
	} else {
		fmt.Printf("\n#-----Deleted SNMPv3 User of Username %v\n", snmpv3User1.UserName)
	}
}
<|endoftext|>