<commit_before>/*
    check.go
    ------

    This file is part of the Go reference implementation of NORX.

    :copyright: (c) 2014 Philipp Jovanovic <philipp@jovanovic.io>
    :license: BSD (3-Clause), see LICENSE
*/

package check

import norx "github.com/daeinar/norx-go/aead"

import "fmt"

func Genkat() {

    wlen := uint64(256)
    hlen := uint64(256)
    tlen := uint64(0)
    klen := uint64(32)
    nlen := uint64(16)

    w := make([]uint8, wlen)
    h := make([]uint8, hlen)
    t := make([]uint8, tlen)
    k := make([]uint8, klen)
    n := make([]uint8, nlen)

    for i := uint64(0); i < wlen; i++ { w[i] = uint8(255 & (i*197 + 123)) }
    for i := uint64(0); i < hlen; i++ { h[i] = uint8(255 & (i*193 + 123)) }
    for i := uint64(0); i < klen; i++ { k[i] = uint8(255 & (i*191 + 123)) }
    for i := uint64(0); i < nlen; i++ { n[i] = uint8(255 & (i*181 + 123)) }

    fmt.Println("package check")
    fmt.Println("func getkat(i uint64, j uint64) []uint8 {")
    fmt.Println("kat := []uint8{")
    for i := uint64(0); i < wlen; i++ {

        m := make([]uint8, 256)
        c := make([]uint8, 256 + 32)
        copy(m,w[:i+1])

        clen := uint64(0)
        mlen := uint64(i)
        hlen := uint64(i)

        norx.AEAD_encrypt(c, &clen, h, hlen, m, mlen, t, tlen, n, k)

        norx.Print_bytes(c, clen)
        if i == wlen - 1 {
            fmt.Println("}")
        } else {
            fmt.Println()
        }
    }
    fmt.Println("return kat[i:j]\n}")
}

func Check() int {

    wlen := uint64(256)
    hlen := uint64(256)
    tlen := uint64(0)
    klen := uint64(32)
    nlen := uint64(16)

    w := make([]uint8, wlen)
    h := make([]uint8, hlen)
    t := make([]uint8, tlen)
    k := make([]uint8, klen)
    n := make([]uint8, nlen)

    for i := uint64(0); i < wlen; i++ { w[i] = uint8(255 & (i*197 + 123)) }
    for i := uint64(0); i < hlen; i++ { h[i] = uint8(255 & (i*193 + 123)) }
    for i := uint64(0); i < klen; i++ { k[i] = uint8(255 & (i*191 + 123)) }
    for i := uint64(0); i < nlen; i++ { n[i] = uint8(255 & (i*181 + 123)) }

    kat := uint64(0)

    for i := uint64(0); i < wlen; i++ {

        m := make([]uint8, 256)
        c := make([]uint8, 256 + 32)
        copy(m,w[:i+1])

        clen := uint64(0)
        mlen := uint64(i)
        hlen := uint64(i)

        norx.AEAD_encrypt(c, &clen, h, hlen, m, mlen, t, tlen, n, k)
        if 0 != cmp(getkat(kat,kat+clen),c,clen) {
            fmt.Printf("fail at encrypt check: %d\n", i)
            return -1
        }

        m = make([]uint8, 256)
        mlen = uint64(0)

        if 0 != norx.AEAD_decrypt(m, &mlen, h, hlen, c, clen, t, tlen, n, k) {
            fmt.Printf("fail at decrypt check: %d\n", i)
            return -1
        }

        if 0 != cmp(w,m,mlen) {
            fmt.Printf("fail at msg check: %d\n", i)
            return -1
        }

        kat += clen
    }
    fmt.Println("ok")
    return 0
}

func cmp(a []uint8, b []uint8, len uint64) int {

    for i := uint64(0); i < len; i++ {
        if a[i] != b[i] {
          return -1
        }
    }
    return 0
}
<commit_msg>code cleanup<commit_after>/*
    check.go
    ------

    This file is part of the Go reference implementation of NORX.

    :copyright: (c) 2014 Philipp Jovanovic <philipp@jovanovic.io>
    :license: BSD (3-Clause), see LICENSE
*/

package check

import norx "github.com/daeinar/norx-go/aead"

import "fmt"

func Genkat() {

    var wlen uint64 = 256
    var hlen uint64 = 256
    var tlen uint64 = 0
    var klen uint64 = 32
    var nlen uint64 = 16

    w := make([]uint8, wlen)
    h := make([]uint8, hlen)
    t := make([]uint8, tlen)
    k := make([]uint8, klen)
    n := make([]uint8, nlen)

    for i := uint64(0); i < wlen; i++ { w[i] = uint8(255 & (i*197 + 123)) }
    for i := uint64(0); i < hlen; i++ { h[i] = uint8(255 & (i*193 + 123)) }
    for i := uint64(0); i < klen; i++ { k[i] = uint8(255 & (i*191 + 123)) }
    for i := uint64(0); i < nlen; i++ { n[i] = uint8(255 & (i*181 + 123)) }

    fmt.Println("package check")
    fmt.Println("func getkat(i uint64, j uint64) []uint8 {")
    fmt.Println("kat := []uint8{")
    for i := uint64(0); i < wlen; i++ {

        m := make([]uint8, 256)
        c := make([]uint8, 256 + 32)
        copy(m,w[:i+1])

        clen := uint64(0)
        mlen := uint64(i)
        hlen := uint64(i)

        norx.AEAD_encrypt(c, &clen, h, hlen, m, mlen, t, tlen, n, k)

        norx.Print_bytes(c, clen)
        if i == wlen - 1 {
            fmt.Println("}")
        } else {
            fmt.Println()
        }
    }
    fmt.Println("return kat[i:j]\n}")
}

func Check() int {

    wlen := uint64(256)
    hlen := uint64(256)
    tlen := uint64(0)
    klen := uint64(32)
    nlen := uint64(16)

    w := make([]uint8, wlen)
    h := make([]uint8, hlen)
    t := make([]uint8, tlen)
    k := make([]uint8, klen)
    n := make([]uint8, nlen)

    for i := uint64(0); i < wlen; i++ { w[i] = uint8(255 & (i*197 + 123)) }
    for i := uint64(0); i < hlen; i++ { h[i] = uint8(255 & (i*193 + 123)) }
    for i := uint64(0); i < klen; i++ { k[i] = uint8(255 & (i*191 + 123)) }
    for i := uint64(0); i < nlen; i++ { n[i] = uint8(255 & (i*181 + 123)) }

    kat := uint64(0)

    for i := uint64(0); i < wlen; i++ {

        m := make([]uint8, 256)
        c := make([]uint8, 256 + 32)
        copy(m,w[:i+1])

        clen := uint64(0)
        mlen := uint64(i)
        hlen := uint64(i)

        norx.AEAD_encrypt(c, &clen, h, hlen, m, mlen, t, tlen, n, k)
        if 0 != cmp(getkat(kat,kat+clen),c,clen) {
            fmt.Printf("fail at encrypt check: %d\n", i)
            return -1
        }

        m = make([]uint8, 256)
        mlen = uint64(0)

        if 0 != norx.AEAD_decrypt(m, &mlen, h, hlen, c, clen, t, tlen, n, k) {
            fmt.Printf("fail at decrypt check: %d\n", i)
            return -1
        }

        if 0 != cmp(w,m,mlen) {
            fmt.Printf("fail at msg check: %d\n", i)
            return -1
        }

        kat += clen
    }
    fmt.Println("ok")
    return 0
}

func cmp(a []uint8, b []uint8, len uint64) int {

    for i := uint64(0); i < len; i++ {
        if a[i] != b[i] {
          return -1
        }
    }
    return 0
}
<|endoftext|>


<commit_before>package bot

import (
	"fmt"
	"strings"

	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/jriddick/geoffrey/irc"
	"github.com/jriddick/geoffrey/msg"
)

// MessageHandler is the function type for
// message handlers
type MessageHandler func(*Bot, string)

// Bot is the structure for an IRC bot
type Bot struct {
	client       *irc.IRC
	writer       chan<- string
	reader       <-chan *msg.Message
	stop         chan struct{}
	config       Config
	disconnected chan struct{}
	handlers     map[string]Handler
}

// NewBot creates a new bot
func NewBot(config Config) *Bot {
	// Create the bot
	bot := &Bot{
		client: irc.NewIRC(irc.Config{
			Hostname:           config.Hostname,
			Port:               config.Port,
			Secure:             config.Secure,
			InsecureSkipVerify: config.InsecureSkipVerify,
			Timeout:            time.Second * time.Duration(config.Timeout),
			TimeoutLimit:       config.TimeoutLimit,
		}),
		config:       config,
		stop:         make(chan struct{}),
		handlers:     make(map[string]Handler),
		disconnected: make(chan struct{}),
	}

	return bot
}

// Connect will connect the bot to the server
func (b *Bot) Connect() error {
	// Connect the client
	if err := b.client.Connect(); err != nil {
		return err
	}

	// Get the reader and writer channels
	b.writer = b.client.Writer()
	b.reader = b.client.Reader()

	return nil
}

// Handler will start processing messages
func (b *Bot) Handler() {
	for {
		select {
		case <-b.stop:
			// Send quit message
			b.writer <- "QUIT :Closed"

			// Disconnect the client
			b.client.Disconnect()
			break
		case msg := <-b.reader:
			// Log all messages
			log.Debugln(msg.String())

			// Run all handlers
			for _, handler := range b.handlers {
				if msg.Command == handler.Event {
					// Mark start time
					start := time.Now()

					// Execute the handler
					if err := handler.Run(b, msg); err != nil {
						log.Errorf("%s: %v", handler.Name, err)
					}

					// Log the execution time
					log.Infof("Handler '%s' completed in %s", handler.Name, time.Since(start))
				}
			}
		}
	}
}

// Send will send the given message to the given receiver
func (b *Bot) Send(recv, msg string) {
	b.writer <- fmt.Sprintf("PRIVMSG %s :%s", recv, msg)
}

// Join will join the given channel
func (b *Bot) Join(channel string) {
	// Make sure we have a hashtag
	if !strings.HasPrefix(channel, "#") {
		channel = "#" + channel
	}

	// Send the join command
	b.writer <- fmt.Sprintf("JOIN %s", channel)
}

// Ping will send ping to the server
func (b *Bot) Ping(message string) {
	b.writer <- "PING :" + message
}

// Pong will send pong to the server
func (b *Bot) Pong(message string) {
	b.writer <- "PONG :" + message
}

// Nick will send the nick command to the server and
// update the stored nick.
func (b *Bot) Nick(nick string) {
	// Set the nick
	b.config.Nick = nick

	// Send the nick
	b.writer <- "NICK " + nick
}

// User will send the user command to the server and
// update the stored name and user
func (b *Bot) User(user, name string) {
	// Set the stored user and name
	b.config.User = user
	b.config.Name = name

	// Send the command
	b.writer <- "USER " + user + " 0 * :" + name
}

// Close will disconnect the bot from the server
func (b *Bot) Close() {
	close(b.stop)
}

// Config returns the configuration
func (b *Bot) Config() Config {
	return b.config
}

// AddHandler adds handler to the bot
func (b *Bot) AddHandler(handler Handler) error {
	// Do not add duplicate handlers
	if _, ok := b.handlers[handler.Name]; ok {
		return ErrHandlerExists
	}

	// Add the handler to the bot
	b.handlers[handler.Name] = handler
	return nil
}
<commit_msg>Use goroutines for each handler<commit_after>package bot

import (
	"fmt"
	"strings"

	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/jriddick/geoffrey/irc"
	"github.com/jriddick/geoffrey/msg"
)

// MessageHandler is the function type for
// message handlers
type MessageHandler func(*Bot, string)

// Bot is the structure for an IRC bot
type Bot struct {
	client       *irc.IRC
	writer       chan<- string
	reader       <-chan *msg.Message
	stop         chan struct{}
	config       Config
	disconnected chan struct{}
	handlers     map[string]Handler
}

// NewBot creates a new bot
func NewBot(config Config) *Bot {
	// Create the bot
	bot := &Bot{
		client: irc.NewIRC(irc.Config{
			Hostname:           config.Hostname,
			Port:               config.Port,
			Secure:             config.Secure,
			InsecureSkipVerify: config.InsecureSkipVerify,
			Timeout:            time.Second * time.Duration(config.Timeout),
			TimeoutLimit:       config.TimeoutLimit,
		}),
		config:       config,
		stop:         make(chan struct{}),
		handlers:     make(map[string]Handler),
		disconnected: make(chan struct{}),
	}

	return bot
}

// Connect will connect the bot to the server
func (b *Bot) Connect() error {
	// Connect the client
	if err := b.client.Connect(); err != nil {
		return err
	}

	// Get the reader and writer channels
	b.writer = b.client.Writer()
	b.reader = b.client.Reader()

	return nil
}

// Handler will start processing messages
func (b *Bot) Handler() {
	for {
		select {
		case <-b.stop:
			// Send quit message
			b.writer <- "QUIT :Closed"

			// Disconnect the client
			b.client.Disconnect()
			break
		case message := <-b.reader:
			// Log all messages
			log.Debugln(message.String())

			// Run all handlers
			for _, handler := range b.handlers {
				if message.Command == handler.Event {
					go func(bot *Bot, msg *msg.Message, handler Handler) {
						// Mark start time
						start := time.Now()

						// Execute the handler
						if err := handler.Run(b, msg); err != nil {
							log.Errorf("[%s] %v", handler.Name, err)
						}

						// Log the execution time
						log.Infof("Handler '%s' completed in %s", handler.Name, time.Since(start))
					}(b, message, handler)
				}
			}
		}
	}
}

// Send will send the given message to the given receiver
func (b *Bot) Send(recv, msg string) {
	b.writer <- fmt.Sprintf("PRIVMSG %s :%s", recv, msg)
}

// Join will join the given channel
func (b *Bot) Join(channel string) {
	// Make sure we have a hashtag
	if !strings.HasPrefix(channel, "#") {
		channel = "#" + channel
	}

	// Send the join command
	b.writer <- fmt.Sprintf("JOIN %s", channel)
}

// Ping will send ping to the server
func (b *Bot) Ping(message string) {
	b.writer <- "PING :" + message
}

// Pong will send pong to the server
func (b *Bot) Pong(message string) {
	b.writer <- "PONG :" + message
}

// Nick will send the nick command to the server and
// update the stored nick.
func (b *Bot) Nick(nick string) {
	// Set the nick
	b.config.Nick = nick

	// Send the nick
	b.writer <- "NICK " + nick
}

// User will send the user command to the server and
// update the stored name and user
func (b *Bot) User(user, name string) {
	// Set the stored user and name
	b.config.User = user
	b.config.Name = name

	// Send the command
	b.writer <- "USER " + user + " 0 * :" + name
}

// Close will disconnect the bot from the server
func (b *Bot) Close() {
	close(b.stop)
}

// Config returns the configuration
func (b *Bot) Config() Config {
	return b.config
}

// AddHandler adds handler to the bot
func (b *Bot) AddHandler(handler Handler) error {
	// Do not add duplicate handlers
	if _, ok := b.handlers[handler.Name]; ok {
		return ErrHandlerExists
	}

	// Add the handler to the bot
	b.handlers[handler.Name] = handler
	return nil
}
<|endoftext|>


<commit_before>package model551
import (
	"reflect"
	"errors"
	"github.com/go51/string551"
	"strconv"
)

type Model struct {
	models map[string]*ModelInformation
}

type ModelInformation struct {
	NewFunc          NewModelFunc
	ModelType        reflect.Type
	ModelName        string
	TableInformation *TableInformation
	SqlInformation   *SqlCache
}

type TableInformation struct {
	TableName      string
	PrimaryKey     string
	Fields         []string
	DeleteTable    bool
	DeletedAtField string
}

type SqlCache struct {
	Insert        string
	Select        string
	Update        string
	Delete        string
	LogicalDelete string
}

var modelInstance *Model

type NewModelFunc func() interface{}

func Load() *Model {
	if modelInstance != nil {
		return modelInstance
	}

	modelInstance = &Model{
		models:map[string]*ModelInformation{},
	}

	return modelInstance
}

func (m *Model) Add(newFunc NewModelFunc) {
	model := newFunc()

	mType := reflect.TypeOf(model)
	mName := mType.Name()

	if m.models[mName] != nil {
		panic(errors.New("追加されたモデルは既に登録されています。"))
	}

	mInfo := &ModelInformation{
		NewFunc:newFunc,
		ModelType:mType,
		ModelName:mName,
	}

	mInfo.TableInformation = loadTableSetting(mType)

	mInfo.SqlInformation = cacheSql(mInfo.TableInformation)

	m.models[mName] = mInfo
}

func (m *Model) Get(modelName string) *ModelInformation {
	return m.models[modelName]
}

func loadTableSetting(mType reflect.Type) *TableInformation {
	tInfo := &TableInformation{
		TableName:string551.SnakeCase(mType.Name()),
		PrimaryKey:"id",
		Fields:[]string{},
		DeleteTable:false,
		DeletedAtField:"",
	}

	if name := loadTableName(mType); name != "" {
		tInfo.TableName = name
	}

	if primaryKey := loadPrimaryKey(mType); primaryKey != "" {
		tInfo.PrimaryKey = primaryKey
	}

	if del, name := loadDeleteAt(mType); del {
		tInfo.DeleteTable = true
		tInfo.DeletedAtField = name
	}

	tInfo.Fields = loadFields(mType)

	return tInfo
}

func loadTableName(mType reflect.Type) string {
	for i := 0; i < mType.NumField(); i++ {
		sField := mType.Field(i)
		if name := sField.Tag.Get("db_table"); name != "" {
			return name
		}
	}

	return ""
}

func loadPrimaryKey(mType reflect.Type) string {
	for i := 0; i < mType.NumField(); i++ {
		sField := mType.Field(i)
		pk, err := strconv.ParseBool(sField.Tag.Get("db_pk"))
		if err == nil && pk {
			db := sField.Tag.Get("db")
			if db == "" {
				return string551.SnakeCase(sField.Name)
			} else {
				return string551.SnakeCase(db)
			}
		}
	}

	return ""

}

func loadDeleteAt(mType reflect.Type) (bool, string) {

	for i := 0; i < mType.NumField(); i++ {
		sField := mType.Field(i)
		del, err := strconv.ParseBool(sField.Tag.Get("db_delete"))
		if err == nil && del {
			return true, string551.SnakeCase(sField.Name)
		}
	}

	return false, ""
}

func loadFields(mType reflect.Type) []string {
	fields := make([]string, 0)

	for i := 0; i < mType.NumField(); i++ {
		sField := mType.Field(i)
		db := sField.Tag.Get("db")
		del, err := strconv.ParseBool(sField.Tag.Get("db_delete"))
		if err != nil || ! del {
			if db == "" {
				fields = append(fields, string551.SnakeCase(sField.Name))
			} else if db != "-" {
				fields = append(fields, string551.SnakeCase(db))
			}
		}
	}

	return fields

}

func cacheSql(tInfo *TableInformation) *SqlCache {
	sqlCache := &SqlCache{
		Insert:cacheSqlInsert(tInfo),
		Select:cacheSqlSelect(tInfo),
		Update:cacheSqlUpdate(tInfo),
		Delete:cacheSqlDelete(tInfo),
		LogicalDelete:cacheSqlLogicalDelete(tInfo),
	}

	return sqlCache
}

func cacheSqlInsert(tInfo *TableInformation) string {
	sql := ""
	var append int = 0

	sql = string551.Join(sql, "INSERT INTO `" + tInfo.TableName + "` ")
	sql = string551.Join(sql, "(")
	for i := 0; i < len(tInfo.Fields); i++ {
		if tInfo.Fields[i] == tInfo.PrimaryKey {
			continue
		}
		if append == 0 {
			sql = string551.Join(sql, "`" + tInfo.Fields[i] + "`")
		} else {
			sql = string551.Join(sql, ", `" + tInfo.Fields[i] + "`")
		}
		append++
	}

	append = 0
	sql = string551.Join(sql, ") VALUES (")
	for i := 0; i < len(tInfo.Fields); i++ {
		if tInfo.Fields[i] == tInfo.PrimaryKey {
			continue
		}
		if append == 0 {
			sql = string551.Join(sql, "?")
		} else {
			sql = string551.Join(sql, ", ?")
		}
		append++
	}
	sql = string551.Join(sql, ")")

	return sql
}

func cacheSqlSelect(tInfo *TableInformation) string {
	sql := ""

	sql = string551.Join(sql, "SELECT ")
	for i := 0; i < len(tInfo.Fields); i++ {
		if i == 0 {
			sql = string551.Join(sql, "`" + tInfo.Fields[i] + "`")
		} else {
			sql = string551.Join(sql, ", `" + tInfo.Fields[i] + "`")
		}
	}
	sql = string551.Join(sql, " FROM `" + tInfo.TableName + "` WHERE 1 = 1")

	return sql
}

func cacheSqlUpdate(tInfo *TableInformation) string {
	sql := ""
	var append int = 0

	sql = string551.Join(sql, "UPDATE `" + tInfo.TableName + "` SET ")
	for i := 0; i < len(tInfo.Fields); i++ {
		if tInfo.Fields[i] == tInfo.PrimaryKey {
			continue
		}
		if append == 0 {
			sql = string551.Join(sql, "`" + tInfo.Fields[i] + "` = ?")
		} else {
			sql = string551.Join(sql, ", `" + tInfo.Fields[i] + "` = ?")
		}
		append++
	}
	sql = string551.Join(sql, " WHERE `" + tInfo.PrimaryKey + "` = ?")

	return sql
}

func cacheSqlDelete(tInfo *TableInformation) string {
	sql := ""

	sql = string551.Join(sql, "DELETE FROM `" + tInfo.TableName + "` WHERE `" + tInfo.PrimaryKey + "` = ?")

	return sql
}

func cacheSqlLogicalDelete(tInfo *TableInformation) string {
	sql := ""

	if tInfo.DeleteTable == false {
		return sql
	}

	sql = string551.Join(sql, "INSERT INTO `" + tInfo.TableName + "_delete` ")
	sql = string551.Join(sql, "(")
	for i := 0; i < len(tInfo.Fields); i++ {
		if i == 0 {
			sql = string551.Join(sql, "`" + tInfo.Fields[i] + "`")
		} else {
			sql = string551.Join(sql, ", `" + tInfo.Fields[i] + "`")
		}
	}
	sql = string551.Join(sql, ", `" + tInfo.DeletedAtField + "`) VALUES (")
	for i := 0; i < len(tInfo.Fields); i++ {
		if i == 0 {
			sql = string551.Join(sql, "?")
		} else {
			sql = string551.Join(sql, ", ?")
		}
	}
	sql = string551.Join(sql, ", ?)")

	return sql
}<commit_msg>refs #9 プライマリーキー用の SetId, Id メソッドのインターフェースを実装する<commit_after>package model551
import (
	"reflect"
	"errors"
	"github.com/go51/string551"
	"strconv"
)

type Model struct {
	models map[string]*ModelInformation
}

type ModelInformation struct {
	NewFunc          NewModelFunc
	ModelType        reflect.Type
	ModelName        string
	TableInformation *TableInformation
	SqlInformation   *SqlCache
}

type TableInformation struct {
	TableName      string
	PrimaryKey     string
	Fields         []string
	DeleteTable    bool
	DeletedAtField string
}

type SqlCache struct {
	Insert        string
	Select        string
	Update        string
	Delete        string
	LogicalDelete string
}

var modelInstance *Model

type NewModelFunc func() interface{}

type PrimaryInterface interface {
	SetId(int64)
	Id() int64
}

func Load() *Model {
	if modelInstance != nil {
		return modelInstance
	}

	modelInstance = &Model{
		models:map[string]*ModelInformation{},
	}

	return modelInstance
}

func (m *Model) Add(newFunc NewModelFunc) {
	model := newFunc()

	mType := reflect.TypeOf(model)
	mName := mType.Name()

	if m.models[mName] != nil {
		panic(errors.New("追加されたモデルは既に登録されています。"))
	}

	mInfo := &ModelInformation{
		NewFunc:newFunc,
		ModelType:mType,
		ModelName:mName,
	}

	mInfo.TableInformation = loadTableSetting(mType)

	mInfo.SqlInformation = cacheSql(mInfo.TableInformation)

	m.models[mName] = mInfo
}

func (m *Model) Get(modelName string) *ModelInformation {
	return m.models[modelName]
}

func loadTableSetting(mType reflect.Type) *TableInformation {
	tInfo := &TableInformation{
		TableName:string551.SnakeCase(mType.Name()),
		PrimaryKey:"id",
		Fields:[]string{},
		DeleteTable:false,
		DeletedAtField:"",
	}

	if name := loadTableName(mType); name != "" {
		tInfo.TableName = name
	}

	if primaryKey := loadPrimaryKey(mType); primaryKey != "" {
		tInfo.PrimaryKey = primaryKey
	}

	if del, name := loadDeleteAt(mType); del {
		tInfo.DeleteTable = true
		tInfo.DeletedAtField = name
	}

	tInfo.Fields = loadFields(mType)

	return tInfo
}

func loadTableName(mType reflect.Type) string {
	for i := 0; i < mType.NumField(); i++ {
		sField := mType.Field(i)
		if name := sField.Tag.Get("db_table"); name != "" {
			return name
		}
	}

	return ""
}

func loadPrimaryKey(mType reflect.Type) string {
	for i := 0; i < mType.NumField(); i++ {
		sField := mType.Field(i)
		pk, err := strconv.ParseBool(sField.Tag.Get("db_pk"))
		if err == nil && pk {
			db := sField.Tag.Get("db")
			if db == "" {
				return string551.SnakeCase(sField.Name)
			} else {
				return string551.SnakeCase(db)
			}
		}
	}

	return ""

}

func loadDeleteAt(mType reflect.Type) (bool, string) {

	for i := 0; i < mType.NumField(); i++ {
		sField := mType.Field(i)
		del, err := strconv.ParseBool(sField.Tag.Get("db_delete"))
		if err == nil && del {
			return true, string551.SnakeCase(sField.Name)
		}
	}

	return false, ""
}

func loadFields(mType reflect.Type) []string {
	fields := make([]string, 0)

	for i := 0; i < mType.NumField(); i++ {
		sField := mType.Field(i)
		db := sField.Tag.Get("db")
		del, err := strconv.ParseBool(sField.Tag.Get("db_delete"))
		if err != nil || ! del {
			if db == "" {
				fields = append(fields, string551.SnakeCase(sField.Name))
			} else if db != "-" {
				fields = append(fields, string551.SnakeCase(db))
			}
		}
	}

	return fields

}

func cacheSql(tInfo *TableInformation) *SqlCache {
	sqlCache := &SqlCache{
		Insert:cacheSqlInsert(tInfo),
		Select:cacheSqlSelect(tInfo),
		Update:cacheSqlUpdate(tInfo),
		Delete:cacheSqlDelete(tInfo),
		LogicalDelete:cacheSqlLogicalDelete(tInfo),
	}

	return sqlCache
}

func cacheSqlInsert(tInfo *TableInformation) string {
	sql := ""
	var append int = 0

	sql = string551.Join(sql, "INSERT INTO `" + tInfo.TableName + "` ")
	sql = string551.Join(sql, "(")
	for i := 0; i < len(tInfo.Fields); i++ {
		if tInfo.Fields[i] == tInfo.PrimaryKey {
			continue
		}
		if append == 0 {
			sql = string551.Join(sql, "`" + tInfo.Fields[i] + "`")
		} else {
			sql = string551.Join(sql, ", `" + tInfo.Fields[i] + "`")
		}
		append++
	}

	append = 0
	sql = string551.Join(sql, ") VALUES (")
	for i := 0; i < len(tInfo.Fields); i++ {
		if tInfo.Fields[i] == tInfo.PrimaryKey {
			continue
		}
		if append == 0 {
			sql = string551.Join(sql, "?")
		} else {
			sql = string551.Join(sql, ", ?")
		}
		append++
	}
	sql = string551.Join(sql, ")")

	return sql
}

func cacheSqlSelect(tInfo *TableInformation) string {
	sql := ""

	sql = string551.Join(sql, "SELECT ")
	for i := 0; i < len(tInfo.Fields); i++ {
		if i == 0 {
			sql = string551.Join(sql, "`" + tInfo.Fields[i] + "`")
		} else {
			sql = string551.Join(sql, ", `" + tInfo.Fields[i] + "`")
		}
	}
	sql = string551.Join(sql, " FROM `" + tInfo.TableName + "` WHERE 1 = 1")

	return sql
}

func cacheSqlUpdate(tInfo *TableInformation) string {
	sql := ""
	var append int = 0

	sql = string551.Join(sql, "UPDATE `" + tInfo.TableName + "` SET ")
	for i := 0; i < len(tInfo.Fields); i++ {
		if tInfo.Fields[i] == tInfo.PrimaryKey {
			continue
		}
		if append == 0 {
			sql = string551.Join(sql, "`" + tInfo.Fields[i] + "` = ?")
		} else {
			sql = string551.Join(sql, ", `" + tInfo.Fields[i] + "` = ?")
		}
		append++
	}
	sql = string551.Join(sql, " WHERE `" + tInfo.PrimaryKey + "` = ?")

	return sql
}

func cacheSqlDelete(tInfo *TableInformation) string {
	sql := ""

	sql = string551.Join(sql, "DELETE FROM `" + tInfo.TableName + "` WHERE `" + tInfo.PrimaryKey + "` = ?")

	return sql
}

func cacheSqlLogicalDelete(tInfo *TableInformation) string {
	sql := ""

	if tInfo.DeleteTable == false {
		return sql
	}

	sql = string551.Join(sql, "INSERT INTO `" + tInfo.TableName + "_delete` ")
	sql = string551.Join(sql, "(")
	for i := 0; i < len(tInfo.Fields); i++ {
		if i == 0 {
			sql = string551.Join(sql, "`" + tInfo.Fields[i] + "`")
		} else {
			sql = string551.Join(sql, ", `" + tInfo.Fields[i] + "`")
		}
	}
	sql = string551.Join(sql, ", `" + tInfo.DeletedAtField + "`) VALUES (")
	for i := 0; i < len(tInfo.Fields); i++ {
		if i == 0 {
			sql = string551.Join(sql, "?")
		} else {
			sql = string551.Join(sql, ", ?")
		}
	}
	sql = string551.Join(sql, ", ?)")

	return sql
}<|endoftext|>


<commit_before>/*Package gorandpacket is a go library for randomly generating ethernet packets
It's main purpose is for testing networking software/hardware
*/
package gorandpacket

import (
	"code.google.com/p/gopacket"
	"code.google.com/p/gopacket/layers"
	//"fmt"
	"math/rand"
	"net"
	"time"
)

//Struct RandPacket holds the gorandpacket object
type RandPacketT struct {
	MACLen int
	Seed   int64
	Rand   *rand.Rand
}

//NewGorandPacket Factory method for gorandpacket
func NewGorandPacket() RandPacketT {

	rp := RandPacketT{}
	rp.MACLen = 6
	rp.Seed = int64(time.Now().Nanosecond())
	rp.Rand = rand.New(rand.NewSource(rp.Seed))
	return rp

}

//RandIPv4Addr generates a random IPv4 address
func (r *RandPacketT) RandIPv4Addr() net.IP {
	var myIP net.IP
	myIP = make(net.IP, net.IPv4len)

	for i := 0; i < len(myIP); i++ {
		myIP[i] = r.RandByte()
	}
	return myIP
}

//RandIPv6Addr Generate a random IPv6 address
func (r *RandPacketT) RandIPv6Addr() net.IP {
	var myIP net.IP
	myIP = make(net.IP, net.IPv6len)

	for i := 0; i < len(myIP); i++ {
		myIP[i] = r.RandByte()
	}
	return myIP
}

//RandMACAddr Generate a random MAC address
func (r *RandPacketT) RandMACAddr() net.HardwareAddr {

	var myMAC net.HardwareAddr
	myMAC = make(net.HardwareAddr, r.MACLen)
	for i := 0; i < r.MACLen; i++ {
		myMAC[i] = r.RandByte()
	}
	return myMAC

}

//SetSeed Set a seed from an external source
func (r *RandPacketT) SetSeed(s int64) {

	r.Seed = s

}

//RandInt16 generates random uint16
func (r *RandPacketT) RandInt16() uint16 {
	num := r.Rand.Intn(0xFFFF)
	num16 := uint16(num)
	return num16
}

//RandInt32 generates random uint32
func (r *RandPacketT) RandInt32() uint32 {

	num := r.Rand.Intn(0xFFFFFFFF)
	num32 := uint32(num)
	return num32
}

//RandByte Generate a random byte
func (r *RandPacketT) RandByte() byte {

	num := r.Rand.Intn(255)
	mByte := uint8(num)

	return mByte
}

//RandInt generates a random int
func (r *RandPacketT) RandInt(n int) int {
	return r.Rand.Intn(n)
}

//RandPayload generates a Random Payload
func (r *RandPacketT) RandPayload() []byte {

	pSize := r.RandInt(1000)

	var myPayload []byte
	myPayload = make([]byte, pSize)

	for i := 5; i < int(pSize); i++ {
		myPayload[i] = r.RandByte()
		//println(myPayload[i])

	}
	return myPayload

}

//RandIPv4Layer generates a random IPv4 layer
func (r *RandPacketT) RandIPv4Layer() *layers.IPv4 {
	const (
		l3tcp = iota // c0 == 0
		l3udp = iota // c1 == 1
	)
	var l3protocol uint8
	//Randomly choose the l3 protocol to be used
	switch r.Rand.Intn(2) {
	case l3tcp:
		l3protocol = uint8(layers.IPProtocolTCP)
	case l3udp:
		l3protocol = uint8(layers.IPProtocolUDP)
	}

	ipv4 := layers.IPv4{
		Version:    uint8(4),
		IHL:        uint8(5),
		TOS:        uint8(0x1),
		Length:     uint16(40),
		Id:         uint16(r.RandInt16()),
		Flags:      layers.IPv4Flag(0),
		FragOffset: uint16(0),
		TTL:        uint8(0x1),
		Protocol:   layers.IPProtocol(l3protocol),
		Checksum:   uint16(0),
		SrcIP:      r.RandIPv4Addr(),
		DstIP:      r.RandIPv4Addr(),
	}
	return &ipv4
}

//RandIPUDP generates a random UDP layer
func (r *RandPacketT) RandIPUDPLayer() *layers.UDP {

	udp := layers.UDP{
		SrcPort:  layers.UDPPort(r.RandInt16()),
		DstPort:  layers.UDPPort(r.RandInt16()),
		Length:   8,
		Checksum: 0,
	}
	return &udp
}

//RandIPv4TCPLayer generates a random TCP layer
func (r *RandPacketT) RandIPTCPLayer() *layers.TCP {

	ipv4Tcp := layers.TCP{
		SrcPort:    layers.TCPPort(r.RandInt16()), //uint16
		DstPort:    layers.TCPPort(r.RandInt16()), //uint16
		Seq:        0xFFFFFFFF,                    //uint32
		Ack:        0x2,                           //uint32
		DataOffset: uint8(5),                      //must be 5                             //uint8, higer 4 bits are 0.
		FIN:        false,
		SYN:        false,
		RST:        false,
		PSH:        false,
		ACK:        false,
		URG:        false,
		ECE:        false,
		CWR:        false,
		NS:         false,
		Window:     0xff,
		Checksum:   uint16(0),
		Urgent:     0xFF, //uint16
	}
	return &ipv4Tcp

}

//RandEthernetLayer generates a random Ethernet layer
func (r *RandPacketT) RandEthernetLayer() *layers.Ethernet {
	eth := layers.Ethernet{}
	eth.EthernetType = layers.EthernetTypeIPv4
	eth.SrcMAC = r.RandMACAddr()
	eth.DstMAC = r.RandMACAddr()
	return &eth

}

//RandL3Layer generates a random L3 layer:  currently supports TCP & UDP only.
func (r *RandPacketT) RandL3Layer(l3type layers.IPProtocol) gopacket.SerializableLayer {

	var l3 gopacket.SerializableLayer

	/*********************
	Create a Random L3 layer
	**********************/
	switch l3type {
	case layers.IPProtocolTCP:
		// Generate a random TCP layer
		l3 = r.RandIPTCPLayer()
	case layers.IPProtocolUDP:
		//Generate a random UDP layer
		l3 = r.RandIPUDPLayer()
	default:
		panic("Bad l3 packet type")
	}
	return l3
}

/*RandEthernetPacket generates a random ethernet packet.
For now it only generates IPv4/TCP packets
TODO:  Generate more types/protocols
*/
func (r *RandPacketT) RandEthernetPacket() gopacket.SerializeBuffer {

	buf := gopacket.NewSerializeBuffer()

	// See gopacket SerializeOptions for more details.
	opts := gopacket.SerializeOptions{}

	// Generate a random ethernet layer
	eth := r.RandEthernetLayer()

	// Generate a random IPV4 Layer
	//TODO: randomize ip version
	l3 := r.RandIPv4Layer()

	//Generate a random IP L4 layer.
	l4 := r.RandL3Layer(l3.Protocol)

	/*****************************
	Check IP layer size
	******************************/
	l3Buf := gopacket.NewSerializeBuffer()
	l4Buf := gopacket.NewSerializeBuffer()
	err := l3.SerializeTo(l3Buf, opts)
	err = l4.SerializeTo(l4Buf, opts)

	l3.Length = uint16(len(l3Buf.Bytes())) + uint16(len(l4Buf.Bytes()))
	/*****************************
	Generate the final ethernet frame
	by serializing all generated layers
	*****************************/
	err = gopacket.SerializeLayers(buf, opts, eth, l3, l4)
	//fmt.Println(buf)
	if err != nil {
		panic(err)
	}
	return buf
}
<commit_msg>Gopacket moved to github.... changing package path. Sorry, this will break your code.  This is still in beta.<commit_after>/*Package gorandpacket is a go library for randomly generating ethernet packets
It's main purpose is for testing networking software/hardware
*/
package gorandpacket

import (
	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
	"math/rand"
	"net"
	"time"
)

//Struct RandPacket holds the gorandpacket object
type RandPacketT struct {
	MACLen int
	Seed   int64
	Rand   *rand.Rand
}

//NewGorandPacket Factory method for gorandpacket
func NewGorandPacket() RandPacketT {

	rp := RandPacketT{}
	rp.MACLen = 6
	rp.Seed = int64(time.Now().Nanosecond())
	rp.Rand = rand.New(rand.NewSource(rp.Seed))
	return rp

}

//RandIPv4Addr generates a random IPv4 address
func (r *RandPacketT) RandIPv4Addr() net.IP {
	var myIP net.IP
	myIP = make(net.IP, net.IPv4len)

	for i := 0; i < len(myIP); i++ {
		myIP[i] = r.RandByte()
	}
	return myIP
}

//RandIPv6Addr Generate a random IPv6 address
func (r *RandPacketT) RandIPv6Addr() net.IP {
	var myIP net.IP
	myIP = make(net.IP, net.IPv6len)

	for i := 0; i < len(myIP); i++ {
		myIP[i] = r.RandByte()
	}
	return myIP
}

//RandMACAddr Generate a random MAC address
func (r *RandPacketT) RandMACAddr() net.HardwareAddr {

	var myMAC net.HardwareAddr
	myMAC = make(net.HardwareAddr, r.MACLen)
	for i := 0; i < r.MACLen; i++ {
		myMAC[i] = r.RandByte()
	}
	return myMAC

}

//SetSeed Set a seed from an external source
func (r *RandPacketT) SetSeed(s int64) {

	r.Seed = s

}

//RandInt16 generates random uint16
func (r *RandPacketT) RandInt16() uint16 {
	num := r.Rand.Intn(0xFFFF)
	num16 := uint16(num)
	return num16
}

//RandInt32 generates random uint32
func (r *RandPacketT) RandInt32() uint32 {

	num := r.Rand.Intn(0xFFFFFFFF)
	num32 := uint32(num)
	return num32
}

//RandByte Generate a random byte
func (r *RandPacketT) RandByte() byte {

	num := r.Rand.Intn(255)
	mByte := uint8(num)

	return mByte
}

//RandInt generates a random int
func (r *RandPacketT) RandInt(n int) int {
	return r.Rand.Intn(n)
}

//RandPayload generates a Random Payload
func (r *RandPacketT) RandPayload() []byte {

	pSize := r.RandInt(1000)

	var myPayload []byte
	myPayload = make([]byte, pSize)

	for i := 5; i < int(pSize); i++ {
		myPayload[i] = r.RandByte()
		//println(myPayload[i])

	}
	return myPayload

}

//RandIPv4Layer generates a random IPv4 layer
func (r *RandPacketT) RandIPv4Layer() *layers.IPv4 {
	const (
		l3tcp = iota // c0 == 0
		l3udp = iota // c1 == 1
	)
	var l3protocol uint8
	//Randomly choose the l3 protocol to be used
	switch r.Rand.Intn(2) {
	case l3tcp:
		l3protocol = uint8(layers.IPProtocolTCP)
	case l3udp:
		l3protocol = uint8(layers.IPProtocolUDP)
	}

	ipv4 := layers.IPv4{
		Version:    uint8(4),
		IHL:        uint8(5),
		TOS:        uint8(0x1),
		Length:     uint16(40),
		Id:         uint16(r.RandInt16()),
		Flags:      layers.IPv4Flag(0),
		FragOffset: uint16(0),
		TTL:        uint8(0x1),
		Protocol:   layers.IPProtocol(l3protocol),
		Checksum:   uint16(0),
		SrcIP:      r.RandIPv4Addr(),
		DstIP:      r.RandIPv4Addr(),
	}
	return &ipv4
}

//RandIPUDP generates a random UDP layer
func (r *RandPacketT) RandIPUDPLayer() *layers.UDP {

	udp := layers.UDP{
		SrcPort:  layers.UDPPort(r.RandInt16()),
		DstPort:  layers.UDPPort(r.RandInt16()),
		Length:   8,
		Checksum: 0,
	}
	return &udp
}

//RandIPv4TCPLayer generates a random TCP layer
func (r *RandPacketT) RandIPTCPLayer() *layers.TCP {

	ipv4Tcp := layers.TCP{
		SrcPort:    layers.TCPPort(r.RandInt16()), //uint16
		DstPort:    layers.TCPPort(r.RandInt16()), //uint16
		Seq:        0xFFFFFFFF,                    //uint32
		Ack:        0x2,                           //uint32
		DataOffset: uint8(5),                      //must be 5                             //uint8, higer 4 bits are 0.
		FIN:        false,
		SYN:        false,
		RST:        false,
		PSH:        false,
		ACK:        false,
		URG:        false,
		ECE:        false,
		CWR:        false,
		NS:         false,
		Window:     0xff,
		Checksum:   uint16(0),
		Urgent:     0xFF, //uint16
	}
	return &ipv4Tcp

}

//RandEthernetLayer generates a random Ethernet layer
func (r *RandPacketT) RandEthernetLayer() *layers.Ethernet {
	eth := layers.Ethernet{}
	eth.EthernetType = layers.EthernetTypeIPv4
	eth.SrcMAC = r.RandMACAddr()
	eth.DstMAC = r.RandMACAddr()
	return &eth

}

//RandL3Layer generates a random L3 layer:  currently supports TCP & UDP only.
func (r *RandPacketT) RandL3Layer(l3type layers.IPProtocol) gopacket.SerializableLayer {

	var l3 gopacket.SerializableLayer

	/*********************
	Create a Random L3 layer
	**********************/
	switch l3type {
	case layers.IPProtocolTCP:
		// Generate a random TCP layer
		l3 = r.RandIPTCPLayer()
	case layers.IPProtocolUDP:
		//Generate a random UDP layer
		l3 = r.RandIPUDPLayer()
	default:
		panic("Bad l3 packet type")
	}
	return l3
}

/*RandEthernetPacket generates a random ethernet packet.
For now it only generates IPv4/TCP packets
TODO:  Generate more types/protocols
*/
func (r *RandPacketT) RandEthernetPacket() gopacket.SerializeBuffer {

	buf := gopacket.NewSerializeBuffer()

	// See gopacket SerializeOptions for more details.
	opts := gopacket.SerializeOptions{}

	// Generate a random ethernet layer
	eth := r.RandEthernetLayer()

	// Generate a random IPV4 Layer
	//TODO: randomize ip version
	l3 := r.RandIPv4Layer()

	//Generate a random IP L4 layer.
	l4 := r.RandL3Layer(l3.Protocol)

	/*****************************
	Check IP layer size
	******************************/
	l3Buf := gopacket.NewSerializeBuffer()
	l4Buf := gopacket.NewSerializeBuffer()
	err := l3.SerializeTo(l3Buf, opts)
	err = l4.SerializeTo(l4Buf, opts)

	l3.Length = uint16(len(l3Buf.Bytes())) + uint16(len(l4Buf.Bytes()))
	/*****************************
	Generate the final ethernet frame
	by serializing all generated layers
	*****************************/
	err = gopacket.SerializeLayers(buf, opts, eth, l3, l4)
	//fmt.Println(buf)
	if err != nil {
		panic(err)
	}
	return buf
}
<|endoftext|>


<commit_before>package shell

import (
	"context"
	"errors"
	"fmt"
	"io"
	"os"
	"os/exec"
	"reflect"
	"strings"
	"sync"
	"syscall"

	"github.com/zetamatta/go-findfile"

	"../dos"
	. "../ifdbg"
)

const FLAG_AMP2NEWCONSOLE = false

var WildCardExpansionAlways = false

type CommandNotFound struct {
	Name string
	Err  error
}

// from "TDM-GCC-64/x86_64-w64-mingw32/include/winbase.h"
const (
	CREATE_NEW_CONSOLE       = 0x10
	CREATE_NEW_PROCESS_GROUP = 0x200
)

func (this CommandNotFound) Stringer() string {
	return fmt.Sprintf("'%s' is not recognized as an internal or external command,\noperable program or batch file", this.Name)
}

func (this CommandNotFound) Error() string {
	return this.Stringer()
}

type Cmd struct {
	exec.Cmd
	Stdio        [3]*os.File
	HookCount    int
	Tag          interface{}
	PipeSeq      [2]uint
	IsBackGround bool
	RawArgs      []string

	OnFork  func(*Cmd) error
	OffFork func(*Cmd) error
	Closers []io.Closer
}

func (this *Cmd) GetRawArgs() []string {
	return this.RawArgs
}

func (this *Cmd) Close() {
	if this.Closers != nil {
		for _, c := range this.Closers {
			c.Close()
		}
		this.Closers = nil
	}
}

func New() *Cmd {
	this := Cmd{
		Stdio: [3]*os.File{os.Stdin, os.Stdout, os.Stderr},
	}
	this.Stdin = os.Stdin
	this.Stdout = os.Stdout
	this.Stderr = os.Stderr
	this.PipeSeq[0] = pipeSeq
	this.PipeSeq[1] = 0
	return &this
}

func (this *Cmd) SetStdin(f *os.File) {
	this.Stdio[0] = f
	this.Stdin = f
}
func (this *Cmd) SetStdout(f *os.File) {
	this.Stdio[1] = f
	this.Stdout = f
}
func (this *Cmd) SetStderr(f *os.File) {
	this.Stdio[2] = f
	this.Stderr = f
}

func (this *Cmd) Clone() (*Cmd, error) {
	rv := new(Cmd)
	rv.Args = this.Args
	rv.RawArgs = this.RawArgs
	rv.Stdio[0] = this.Stdio[0]
	rv.Stdio[1] = this.Stdio[1]
	rv.Stdio[2] = this.Stdio[2]
	rv.Stdin = this.Stdin
	rv.Stdout = this.Stdout
	rv.Stderr = this.Stderr
	rv.HookCount = this.HookCount
	rv.Tag = this.Tag
	rv.PipeSeq = this.PipeSeq
	rv.Closers = nil
	rv.OnFork = this.OnFork
	rv.OffFork = this.OffFork
	return rv, nil
}

type ArgsHookT func(it *Cmd, args []string) ([]string, error)

var argsHook = func(it *Cmd, args []string) ([]string, error) {
	return args, nil
}

func SetArgsHook(argsHook_ ArgsHookT) (rv ArgsHookT) {
	rv, argsHook = argsHook, argsHook_
	return
}

type HookT func(context.Context, *Cmd) (int, bool, error)

var hook = func(context.Context, *Cmd) (int, bool, error) {
	return 0, false, nil
}

func SetHook(hook_ HookT) (rv HookT) {
	rv, hook = hook, hook_
	return
}

var OnCommandNotFound = func(this *Cmd, err error) error {
	err = &CommandNotFound{this.Args[0], err}
	return err
}

var LastErrorLevel int

func nvl(a *os.File, b *os.File) *os.File {
	if a != nil {
		return a
	} else {
		return b
	}
}

func makeCmdline(args, rawargs []string) string {
	buffer := make([]byte, 0, 1024)
	for i, s := range args {
		if i > 0 {
			buffer = append(buffer, ' ')
		}
		if (len(rawargs) > i && len(rawargs[i]) > 0 && rawargs[i][0] == '"') || strings.ContainsAny(s, " &|<>\t\"") {
			buffer = append(buffer, '"')
			qs := strings.Replace(s, `"`, `\"`, -1)
			buffer = append(buffer, qs...)
			buffer = append(buffer, '"')
		} else {
			buffer = append(buffer, s...)
		}
	}
	return string(buffer)
}

func (this *Cmd) spawnvp_noerrmsg(ctx context.Context) (int, error) {
	// command is empty.
	if len(this.Args) <= 0 {
		return 0, nil
	}
	if DBG {
		print("spawnvp_noerrmsg('", this.Args[0], "')\n")
	}

	// aliases and lua-commands
	if errorlevel, done, err := hook(ctx, this); done || err != nil {
		return errorlevel, err
	}

	// command not found hook
	var err error
	this.Path = dos.LookPath(this.Args[0], "NYAGOSPATH")
	if this.Path == "" {
		return 255, OnCommandNotFound(this, os.ErrNotExist)
	}
	this.Args[0] = this.Path
	if DBG {
		print("exec.LookPath(", this.Args[0], ")==", this.Path, "\n")
	}

	if WildCardExpansionAlways {
		this.Args = findfile.Globs(this.Args)
	}

	// executable-file
	if FLAG_AMP2NEWCONSOLE {
		if this.SysProcAttr != nil && (this.SysProcAttr.CreationFlags&CREATE_NEW_CONSOLE) != 0 {
			err = this.Start()
			return 0, err
		}
	}

	if this.SysProcAttr == nil {
		this.SysProcAttr = new(syscall.SysProcAttr)
	}
	cmdline := makeCmdline(this.Args, this.RawArgs)
	if DBG {
		println(cmdline)
	}
	this.SysProcAttr.CmdLine = cmdline
	err = this.Run()

	errorlevel, errorlevelOk := dos.GetErrorLevel(&this.Cmd)
	if errorlevelOk {
		return errorlevel, err
	} else {
		return 255, err
	}
}

type AlreadyReportedError struct {
	Err error
}

func (this AlreadyReportedError) Error() string {
	return ""
}

func IsAlreadyReported(err error) bool {
	_, ok := err.(AlreadyReportedError)
	return ok
}

func (this *Cmd) Spawnvp() (int, error) {
	return this.SpawnvpContext(context.Background())
}

func (this *Cmd) SpawnvpContext(ctx context.Context) (int, error) {
	errorlevel, err := this.spawnvp_noerrmsg(ctx)
	if err != nil && err != io.EOF && !IsAlreadyReported(err) {
		if DBG {
			val := reflect.ValueOf(err)
			fmt.Fprintf(this.Stderr, "error-type=%s\n", val.Type())
		}
		fmt.Fprintln(this.Stderr, err.Error())
		err = AlreadyReportedError{err}
	}
	return errorlevel, err
}

var pipeSeq uint = 0

func (this *Cmd) Interpret(text string) (int, error) {
	return this.InterpretContext(context.Background(), text)
}

type gotoEol struct{}

var GotoEol = gotoEol{}

func (this *Cmd) InterpretContext(ctx_ context.Context, text string) (errorlevel int, err error) {
	if DBG {
		print("Interpret('", text, "')\n")
	}
	if this == nil {
		return 255, errors.New("Fatal Error: Interpret: instance is nil")
	}
	errorlevel = 0
	err = nil

	statements, statementsErr := Parse(text)
	if statementsErr != nil {
		if DBG {
			print("Parse Error:", statementsErr.Error(), "\n")
		}
		return 0, statementsErr
	}
	if argsHook != nil {
		if DBG {
			print("call argsHook\n")
		}
		for _, pipeline := range statements {
			for _, state := range pipeline {
				state.Args, err = argsHook(this, state.Args)
				if err != nil {
					return 255, err
				}
			}
		}
		if DBG {
			print("done argsHook\n")
		}
	}
	for _, pipeline := range statements {
		for i, state := range pipeline {
			if state.Term == "|" && (i+1 >= len(pipeline) || len(pipeline[i+1].Args) <= 0) {
				return 255, errors.New("The syntax of the command is incorrect.")
			}
		}
	}

	for _, pipeline := range statements {

		var pipeIn *os.File = nil
		pipeSeq++
		isBackGround := this.IsBackGround
		for _, state := range pipeline {
			if state.Term == "&" {
				isBackGround = true
				break
			}
		}
		var wg sync.WaitGroup
		shutdown_immediately := false
		for i, state := range pipeline {
			if DBG {
				print(i, ": pipeline loop(", state.Args[0], ")\n")
			}
			cmd, err := this.Clone()
			if err != nil {
				return 255, err
			}
			cmd.PipeSeq[0] = pipeSeq
			cmd.PipeSeq[1] = uint(1 + i)
			cmd.IsBackGround = isBackGround

			ctx := context.WithValue(ctx_, GotoEol, func() {
				shutdown_immediately = true
				gotoeol, ok := ctx_.Value(GotoEol).(func())
				if ok {
					gotoeol()
				}
			})

			if pipeIn != nil {
				cmd.SetStdin(pipeIn)
				cmd.Closers = append(cmd.Closers, pipeIn)
				pipeIn = nil
			}

			if state.Term[0] == '|' {
				var pipeOut *os.File
				pipeIn, pipeOut, err = os.Pipe()
				cmd.SetStdout(pipeOut)
				if state.Term == "|&" {
					cmd.SetStderr(pipeOut)
				}
				cmd.Closers = append(cmd.Closers, pipeOut)
			}

			for _, red := range state.Redirect {
				var fd *os.File
				fd, err = red.OpenOn(cmd)
				if err != nil {
					return 0, err
				}
				defer fd.Close()
			}

			cmd.Args = state.Args
			cmd.RawArgs = state.RawArgs
			if i > 0 {
				cmd.IsBackGround = true
			}
			if i == len(pipeline)-1 && state.Term != "&" {
				// foreground execution.
				errorlevel, err = cmd.SpawnvpContext(ctx)
				LastErrorLevel = errorlevel
				cmd.Close()
			} else {
				// background
				if !isBackGround {
					wg.Add(1)
				}
				if cmd.OnFork != nil {
					if err := cmd.OnFork(cmd); err != nil {
						fmt.Fprintln(cmd.Stderr, err.Error())
						return -1, err
					}
				}
				go func(cmd1 *Cmd) {
					if isBackGround {
						if FLAG_AMP2NEWCONSOLE {
							if len(pipeline) == 1 {
								cmd1.SysProcAttr = &syscall.SysProcAttr{
									CreationFlags: CREATE_NEW_CONSOLE |
										CREATE_NEW_PROCESS_GROUP,
								}
							}
						}
					} else {
						defer wg.Done()
					}
					cmd1.SpawnvpContext(ctx)
					if cmd1.OffFork != nil {
						if err := cmd1.OffFork(cmd1); err != nil {
							fmt.Fprintln(cmd1.Stderr, err.Error())
							goto exit
						}
					}
				exit:
					cmd1.Close()
				}(cmd)
			}
		}
		if !isBackGround {
			wg.Wait()
			if shutdown_immediately {
				return errorlevel, nil
			}
			if len(pipeline) > 0 {
				switch pipeline[len(pipeline)-1].Term {
				case "&&":
					if errorlevel != 0 {
						return errorlevel, nil
					}
				case "||":
					if errorlevel == 0 {
						return errorlevel, nil
					}
				}
			}
		}
	}
	return
}
<commit_msg>Fix: `exit` could not shutdown nyagos.<commit_after>package shell

import (
	"context"
	"errors"
	"fmt"
	"io"
	"os"
	"os/exec"
	"reflect"
	"strings"
	"sync"
	"syscall"

	"github.com/zetamatta/go-findfile"

	"../dos"
	. "../ifdbg"
)

const FLAG_AMP2NEWCONSOLE = false

var WildCardExpansionAlways = false

type CommandNotFound struct {
	Name string
	Err  error
}

// from "TDM-GCC-64/x86_64-w64-mingw32/include/winbase.h"
const (
	CREATE_NEW_CONSOLE       = 0x10
	CREATE_NEW_PROCESS_GROUP = 0x200
)

func (this CommandNotFound) Stringer() string {
	return fmt.Sprintf("'%s' is not recognized as an internal or external command,\noperable program or batch file", this.Name)
}

func (this CommandNotFound) Error() string {
	return this.Stringer()
}

type Cmd struct {
	exec.Cmd
	Stdio        [3]*os.File
	HookCount    int
	Tag          interface{}
	PipeSeq      [2]uint
	IsBackGround bool
	RawArgs      []string

	OnFork  func(*Cmd) error
	OffFork func(*Cmd) error
	Closers []io.Closer
}

func (this *Cmd) GetRawArgs() []string {
	return this.RawArgs
}

func (this *Cmd) Close() {
	if this.Closers != nil {
		for _, c := range this.Closers {
			c.Close()
		}
		this.Closers = nil
	}
}

func New() *Cmd {
	this := Cmd{
		Stdio: [3]*os.File{os.Stdin, os.Stdout, os.Stderr},
	}
	this.Stdin = os.Stdin
	this.Stdout = os.Stdout
	this.Stderr = os.Stderr
	this.PipeSeq[0] = pipeSeq
	this.PipeSeq[1] = 0
	return &this
}

func (this *Cmd) SetStdin(f *os.File) {
	this.Stdio[0] = f
	this.Stdin = f
}
func (this *Cmd) SetStdout(f *os.File) {
	this.Stdio[1] = f
	this.Stdout = f
}
func (this *Cmd) SetStderr(f *os.File) {
	this.Stdio[2] = f
	this.Stderr = f
}

func (this *Cmd) Clone() (*Cmd, error) {
	rv := new(Cmd)
	rv.Args = this.Args
	rv.RawArgs = this.RawArgs
	rv.Stdio[0] = this.Stdio[0]
	rv.Stdio[1] = this.Stdio[1]
	rv.Stdio[2] = this.Stdio[2]
	rv.Stdin = this.Stdin
	rv.Stdout = this.Stdout
	rv.Stderr = this.Stderr
	rv.HookCount = this.HookCount
	rv.Tag = this.Tag
	rv.PipeSeq = this.PipeSeq
	rv.Closers = nil
	rv.OnFork = this.OnFork
	rv.OffFork = this.OffFork
	return rv, nil
}

type ArgsHookT func(it *Cmd, args []string) ([]string, error)

var argsHook = func(it *Cmd, args []string) ([]string, error) {
	return args, nil
}

func SetArgsHook(argsHook_ ArgsHookT) (rv ArgsHookT) {
	rv, argsHook = argsHook, argsHook_
	return
}

type HookT func(context.Context, *Cmd) (int, bool, error)

var hook = func(context.Context, *Cmd) (int, bool, error) {
	return 0, false, nil
}

func SetHook(hook_ HookT) (rv HookT) {
	rv, hook = hook, hook_
	return
}

var OnCommandNotFound = func(this *Cmd, err error) error {
	err = &CommandNotFound{this.Args[0], err}
	return err
}

var LastErrorLevel int

func nvl(a *os.File, b *os.File) *os.File {
	if a != nil {
		return a
	} else {
		return b
	}
}

func makeCmdline(args, rawargs []string) string {
	buffer := make([]byte, 0, 1024)
	for i, s := range args {
		if i > 0 {
			buffer = append(buffer, ' ')
		}
		if (len(rawargs) > i && len(rawargs[i]) > 0 && rawargs[i][0] == '"') || strings.ContainsAny(s, " &|<>\t\"") {
			buffer = append(buffer, '"')
			qs := strings.Replace(s, `"`, `\"`, -1)
			buffer = append(buffer, qs...)
			buffer = append(buffer, '"')
		} else {
			buffer = append(buffer, s...)
		}
	}
	return string(buffer)
}

func (this *Cmd) spawnvp_noerrmsg(ctx context.Context) (int, error) {
	// command is empty.
	if len(this.Args) <= 0 {
		return 0, nil
	}
	if DBG {
		print("spawnvp_noerrmsg('", this.Args[0], "')\n")
	}

	// aliases and lua-commands
	if errorlevel, done, err := hook(ctx, this); done || err != nil {
		return errorlevel, err
	}

	// command not found hook
	var err error
	this.Path = dos.LookPath(this.Args[0], "NYAGOSPATH")
	if this.Path == "" {
		return 255, OnCommandNotFound(this, os.ErrNotExist)
	}
	this.Args[0] = this.Path
	if DBG {
		print("exec.LookPath(", this.Args[0], ")==", this.Path, "\n")
	}

	if WildCardExpansionAlways {
		this.Args = findfile.Globs(this.Args)
	}

	// executable-file
	if FLAG_AMP2NEWCONSOLE {
		if this.SysProcAttr != nil && (this.SysProcAttr.CreationFlags&CREATE_NEW_CONSOLE) != 0 {
			err = this.Start()
			return 0, err
		}
	}

	if this.SysProcAttr == nil {
		this.SysProcAttr = new(syscall.SysProcAttr)
	}
	cmdline := makeCmdline(this.Args, this.RawArgs)
	if DBG {
		println(cmdline)
	}
	this.SysProcAttr.CmdLine = cmdline
	err = this.Run()

	errorlevel, errorlevelOk := dos.GetErrorLevel(&this.Cmd)
	if errorlevelOk {
		return errorlevel, err
	} else {
		return 255, err
	}
}

type AlreadyReportedError struct {
	Err error
}

func (this AlreadyReportedError) Error() string {
	return ""
}

func IsAlreadyReported(err error) bool {
	_, ok := err.(AlreadyReportedError)
	return ok
}

func (this *Cmd) Spawnvp() (int, error) {
	return this.SpawnvpContext(context.Background())
}

func (this *Cmd) SpawnvpContext(ctx context.Context) (int, error) {
	errorlevel, err := this.spawnvp_noerrmsg(ctx)
	if err != nil && err != io.EOF && !IsAlreadyReported(err) {
		if DBG {
			val := reflect.ValueOf(err)
			fmt.Fprintf(this.Stderr, "error-type=%s\n", val.Type())
		}
		fmt.Fprintln(this.Stderr, err.Error())
		err = AlreadyReportedError{err}
	}
	return errorlevel, err
}

var pipeSeq uint = 0

func (this *Cmd) Interpret(text string) (int, error) {
	return this.InterpretContext(context.Background(), text)
}

type gotoEol struct{}

var GotoEol = gotoEol{}

func (this *Cmd) InterpretContext(ctx_ context.Context, text string) (errorlevel int, finalerr error) {
	if DBG {
		print("Interpret('", text, "')\n")
	}
	if this == nil {
		return 255, errors.New("Fatal Error: Interpret: instance is nil")
	}
	errorlevel = 0
	finalerr = nil

	statements, statementsErr := Parse(text)
	if statementsErr != nil {
		if DBG {
			print("Parse Error:", statementsErr.Error(), "\n")
		}
		return 0, statementsErr
	}
	if argsHook != nil {
		if DBG {
			print("call argsHook\n")
		}
		for _, pipeline := range statements {
			for _, state := range pipeline {
				var err error
				state.Args, err = argsHook(this, state.Args)
				if err != nil {
					return 255, err
				}
			}
		}
		if DBG {
			print("done argsHook\n")
		}
	}
	for _, pipeline := range statements {
		for i, state := range pipeline {
			if state.Term == "|" && (i+1 >= len(pipeline) || len(pipeline[i+1].Args) <= 0) {
				return 255, errors.New("The syntax of the command is incorrect.")
			}
		}
	}

	for _, pipeline := range statements {

		var pipeIn *os.File = nil
		pipeSeq++
		isBackGround := this.IsBackGround
		for _, state := range pipeline {
			if state.Term == "&" {
				isBackGround = true
				break
			}
		}
		var wg sync.WaitGroup
		shutdown_immediately := false
		for i, state := range pipeline {
			if DBG {
				print(i, ": pipeline loop(", state.Args[0], ")\n")
			}
			cmd, err := this.Clone()
			if err != nil {
				return 255, err
			}
			cmd.PipeSeq[0] = pipeSeq
			cmd.PipeSeq[1] = uint(1 + i)
			cmd.IsBackGround = isBackGround

			ctx := context.WithValue(ctx_, GotoEol, func() {
				shutdown_immediately = true
				gotoeol, ok := ctx_.Value(GotoEol).(func())
				if ok {
					gotoeol()
				}
			})

			if pipeIn != nil {
				cmd.SetStdin(pipeIn)
				cmd.Closers = append(cmd.Closers, pipeIn)
				pipeIn = nil
			}

			if state.Term[0] == '|' {
				var pipeOut *os.File
				pipeIn, pipeOut, err = os.Pipe()
				cmd.SetStdout(pipeOut)
				if state.Term == "|&" {
					cmd.SetStderr(pipeOut)
				}
				cmd.Closers = append(cmd.Closers, pipeOut)
			}

			for _, red := range state.Redirect {
				var fd *os.File
				fd, err = red.OpenOn(cmd)
				if err != nil {
					return 0, err
				}
				defer fd.Close()
			}

			cmd.Args = state.Args
			cmd.RawArgs = state.RawArgs
			if i > 0 {
				cmd.IsBackGround = true
			}
			if i == len(pipeline)-1 && state.Term != "&" {
				// foreground execution.
				errorlevel, finalerr = cmd.SpawnvpContext(ctx)
				LastErrorLevel = errorlevel
				cmd.Close()
			} else {
				// background
				if !isBackGround {
					wg.Add(1)
				}
				if cmd.OnFork != nil {
					if err := cmd.OnFork(cmd); err != nil {
						fmt.Fprintln(cmd.Stderr, err.Error())
						return -1, err
					}
				}
				go func(cmd1 *Cmd) {
					if isBackGround {
						if FLAG_AMP2NEWCONSOLE {
							if len(pipeline) == 1 {
								cmd1.SysProcAttr = &syscall.SysProcAttr{
									CreationFlags: CREATE_NEW_CONSOLE |
										CREATE_NEW_PROCESS_GROUP,
								}
							}
						}
					} else {
						defer wg.Done()
					}
					cmd1.SpawnvpContext(ctx)
					if cmd1.OffFork != nil {
						if err := cmd1.OffFork(cmd1); err != nil {
							fmt.Fprintln(cmd1.Stderr, err.Error())
							goto exit
						}
					}
				exit:
					cmd1.Close()
				}(cmd)
			}
		}
		if !isBackGround {
			wg.Wait()
			if shutdown_immediately {
				return errorlevel, nil
			}
			if len(pipeline) > 0 {
				switch pipeline[len(pipeline)-1].Term {
				case "&&":
					if errorlevel != 0 {
						return errorlevel, nil
					}
				case "||":
					if errorlevel == 0 {
						return errorlevel, nil
					}
				}
			}
		}
	}
	return
}
<|endoftext|>


<commit_before>package commands

import (
	"fmt"
	"os"
	"os/exec"

	"github.com/leancloud/lean-cli/logo"
	"github.com/leancloud/lean-cli/version"
	"github.com/urfave/cli"
)

// Run the command line
func Run(args []string) {
	// add banner text to help text
	cli.AppHelpTemplate = logo.Logo() + cli.AppHelpTemplate
	cli.SubcommandHelpTemplate = logo.Logo() + cli.SubcommandHelpTemplate

	app := cli.NewApp()
	app.Name = "lean"
	app.Version = version.Version
	app.Usage = "Command line to manage and deploy LeanCloud apps"
	app.EnableBashCompletion = true

	app.CommandNotFound = thirdPartyCommand

	app.Commands = []cli.Command{
		{
			Name:      "login",
			Usage:     "Log in to LeanCloud",
			Action:    wrapAction(loginAction),
			ArgsUsage: "[-u username -p password (--region <CN> | <US> | <TAB>)]",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "username,u",
					Usage: "Username",
				},
				cli.StringFlag{
					Name:  "password,p",
					Usage: "Password",
				},
				cli.StringFlag{
					Name:  "region,r",
					Usage: "The LeanCloud region to log in to (e.g., US, CN)",
				},
			},
		},
		{
			Name:      "metric",
			Usage:     "Obtain LeanStorage performance metrics of current project",
			Action:    wrapAction(statusAction),
			ArgsUsage: "[--from fromTime --to toTime --format default|json]",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "from",
					Usage: "Start date, formatted as YYYY-MM-DD，e.g., 1926-08-17",
				},
				cli.StringFlag{
					Name:  "to",
					Usage: "End date formatted as YYYY-MM-DD，e.g., 1926-08-17",
				},
				cli.StringFlag{
					Name:  "format",
					Usage: "Output format，'default' or 'json'",
				},
			},
		},
		{
			Name:   "info",
			Usage:  "Show information about the current user and app",
			Action: wrapAction(infoAction),
		},
		{
			Name:   "up",
			Usage:  "Start a development instance locally",
			Action: wrapAction(upAction),
			Flags: []cli.Flag{
				cli.IntFlag{
					Name:  "port,p",
					Usage: "Local port to listen on",
					Value: 3000,
				},
				cli.IntFlag{
					Name:  "console-port,c",
					Usage: "Port of the debug console",
				},
				cli.StringFlag{
					Name:  "cmd",
					Usage: "Command to start the project, other arguments except --console-port are ignored",
				},
			},
		},
		{
			Name:      "init",
			Usage:     "Initialize a LeanEngine project",
			Action:    wrapAction(initAction),
			ArgsUsage: "[dest]",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "region",
					Usage: "LeanCloud region for the project",
				},
				cli.StringFlag{
					Name:  "group",
					Usage: "LeanEngine group",
				},
			},
		},
		{
			Name:      "switch",
			Usage:     "Change the associated LeanCloud app",
			Action:    wrapAction(switchAction),
			ArgsUsage: "[appID | appName]",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "region",
					Usage: "LeanCloud region",
				},
				cli.StringFlag{
					Name:  "group",
					Usage: "LeanEngine group",
				},
			},
		},
		{
			Name:   "deploy",
			Usage:  "Deploy the project to LeanEngine",
			Action: wrapAction(deployAction),
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "g",
					Usage: "Deploy from git repo",
				},
				cli.BoolFlag{
					Name:  "war",
					Usage: "Deploy .war file for Java project. The first .war file in target/ is used by default",
				},
				cli.BoolFlag{
					Name:  "no-cache",
					Usage: "Force download dependencies",
				},
				cli.StringFlag{
					Name:  "leanignore",
					Usage: "Rule file for ignored files in deployment",
					Value: ".leanignore",
				},
				cli.StringFlag{
					Name:  "message,m",
					Usage: "Comment for this deployment, only applicable when deploying from local files",
				},
				cli.BoolFlag{
					Name: "keep-deploy-file",
				},
				cli.StringFlag{
					Name:  "revision,r",
					Usage: "Git revision or branch. Only applicable when deploying from Git",
					Value: "master",
				},
				cli.StringFlag{
					Name:  "options",
					Usage: "Send additional deploy options to server, in urlencode format(like `--options build-root=app&atomic=true`)",
				},
				cli.StringFlag{
					Name:  "prod",
					Usage: "Deploy to production(`--prod 1`) or staging(`--prod 0`) environment, default to staging if it exists",
				},
			},
		},
		{
			Name:   "publish",
			Usage:  "Publish code from staging to production",
			Action: wrapAction(publishAction),
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "options",
					Usage: "Send additional deploy options to server, in urlencode format(like `--options build-root=app&atomic=true`)",
				},
			},
		},
		{
			Name:      "upload",
			Usage:     "Upload files to the current application (available in the '_File' class)",
			Action:    uploadAction,
			ArgsUsage: "<file-path> <file-path> ...",
		},
		{
			Name:   "logs",
			Usage:  "Show LeanEngine logs",
			Action: wrapAction(logsAction),
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "f",
					Usage: "Wait for and continuously show most recent logs",
				},
				cli.StringFlag{
					Name:  "env,e",
					Usage: "Environment to view (staging / production)",
					Value: "production",
				},
				cli.IntFlag{
					Name:  "limit,l",
					Usage: "Maximum number of lines to show",
					Value: 30,
				},
				cli.StringFlag{
					Name:  "from",
					Usage: "Start date formatted as YYYY-MM-DD，e.g., 1926-08-17",
				},
				cli.StringFlag{
					Name:  "to",
					Usage: "End date formatted as YYYY-MM-DD，e.g., 1926-08-17",
				},
				cli.StringFlag{
					Name:  "format",
					Usage: "Format to use ('default' or 'json')",
					Value: "default",
				},
			},
		},
		{
			Name:   "debug",
			Usage:  "Start the debug console without running the project",
			Action: wrapAction(debugAction),
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "remote,r",
					Usage: "URL of target app",
					Value: "http://localhost:3000",
				},
				cli.StringFlag{
					Name:  "app-id",
					Usage: "Target AppID, use the AppID of the current project by default",
				},
				cli.IntFlag{
					Name:  "port,p",
					Usage: "Port to listen on",
					Value: 3001,
				},
			},
		},
		{
			Name:   "env",
			Usage:  "Output environment variables used by the current project",
			Action: wrapAction(envAction),
			Flags: []cli.Flag{
				cli.IntFlag{
					Name:  "port,p",
					Usage: "Local port for the app (affects value of LC_APP_PORT)",
					Value: 3000,
				},
				cli.StringFlag{
					Name:  "template",
					Usage: "Template for output, 'export {{name}}={{value}}' by default",
				},
			},
			Subcommands: []cli.Command{
				{
					Name:      "set",
					Usage:     "Set the value of an environment variable",
					Action:    wrapAction(envSetAction),
					ArgsUsage: "[env-name] [env-value]",
				},
				{
					Name:      "unset",
					Usage:     "Delete an environment variable",
					Action:    wrapAction(envUnsetAction),
					ArgsUsage: "[env-name]",
				},
			},
		},
		{
			Name:   "cache",
			Usage:  "LeanCache shell",
			Action: wrapAction(cacheAction),
			Flags: []cli.Flag{
				cli.IntFlag{
					Name:  "db",
					Usage: "Number of LeanCache DB",
					Value: -1,
				},
				cli.StringFlag{
					Name:  "name",
					Usage: "Name of LeanCache instance",
				},
				cli.StringFlag{
					Name:  "eval",
					Usage: "LeanCache command to run",
				},
			},
			Subcommands: []cli.Command{
				{
					Name:   "list",
					Usage:  "Show LeanCache instances of the current project",
					Action: wrapAction(cacheListAction),
				},
			},
		},
		{
			Name:   "cql",
			Usage:  "Start CQL interactive mode",
			Action: wrapAction(cqlAction),
			Flags: []cli.Flag{
				cli.StringFlag{Name: "format,f",
					Usage: "CQL result format",
					Value: "table",
				},
				cli.StringFlag{
					Name:  "eval",
					Usage: "CQL command to run",
				},
			},
		},
		{
			Name:    "help",
			Aliases: []string{"h"},
			Usage:   "Show all commands or help info for one command",
			Action: func(c *cli.Context) error {
				args := c.Args()
				if args.Present() {
					_, err := fmt.Printf("Please use `lean %s -h` for subcommand usage.\n", args.First())
					return err
				}
				return cli.ShowAppHelp(c)
			},
		},
	}

	app.Before = func(c *cli.Context) error {
		args := []string{"--_collect-stats"}
		args = append(args, c.Args()...)
		err := exec.Command(os.Args[0], args...).Start()
		_ = err
		return nil
	}

	app.Run(args)
}
<commit_msg>docs: warn cql is deprecated<commit_after>package commands

import (
	"fmt"
	"os"
	"os/exec"

	"github.com/leancloud/lean-cli/logo"
	"github.com/leancloud/lean-cli/version"
	"github.com/urfave/cli"
)

// Run the command line
func Run(args []string) {
	// add banner text to help text
	cli.AppHelpTemplate = logo.Logo() + cli.AppHelpTemplate
	cli.SubcommandHelpTemplate = logo.Logo() + cli.SubcommandHelpTemplate

	app := cli.NewApp()
	app.Name = "lean"
	app.Version = version.Version
	app.Usage = "Command line to manage and deploy LeanCloud apps"
	app.EnableBashCompletion = true

	app.CommandNotFound = thirdPartyCommand

	app.Commands = []cli.Command{
		{
			Name:      "login",
			Usage:     "Log in to LeanCloud",
			Action:    wrapAction(loginAction),
			ArgsUsage: "[-u username -p password (--region <CN> | <US> | <TAB>)]",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "username,u",
					Usage: "Username",
				},
				cli.StringFlag{
					Name:  "password,p",
					Usage: "Password",
				},
				cli.StringFlag{
					Name:  "region,r",
					Usage: "The LeanCloud region to log in to (e.g., US, CN)",
				},
			},
		},
		{
			Name:      "metric",
			Usage:     "Obtain LeanStorage performance metrics of current project",
			Action:    wrapAction(statusAction),
			ArgsUsage: "[--from fromTime --to toTime --format default|json]",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "from",
					Usage: "Start date, formatted as YYYY-MM-DD，e.g., 1926-08-17",
				},
				cli.StringFlag{
					Name:  "to",
					Usage: "End date formatted as YYYY-MM-DD，e.g., 1926-08-17",
				},
				cli.StringFlag{
					Name:  "format",
					Usage: "Output format，'default' or 'json'",
				},
			},
		},
		{
			Name:   "info",
			Usage:  "Show information about the current user and app",
			Action: wrapAction(infoAction),
		},
		{
			Name:   "up",
			Usage:  "Start a development instance locally",
			Action: wrapAction(upAction),
			Flags: []cli.Flag{
				cli.IntFlag{
					Name:  "port,p",
					Usage: "Local port to listen on",
					Value: 3000,
				},
				cli.IntFlag{
					Name:  "console-port,c",
					Usage: "Port of the debug console",
				},
				cli.StringFlag{
					Name:  "cmd",
					Usage: "Command to start the project, other arguments except --console-port are ignored",
				},
			},
		},
		{
			Name:      "init",
			Usage:     "Initialize a LeanEngine project",
			Action:    wrapAction(initAction),
			ArgsUsage: "[dest]",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "region",
					Usage: "LeanCloud region for the project",
				},
				cli.StringFlag{
					Name:  "group",
					Usage: "LeanEngine group",
				},
			},
		},
		{
			Name:      "switch",
			Usage:     "Change the associated LeanCloud app",
			Action:    wrapAction(switchAction),
			ArgsUsage: "[appID | appName]",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "region",
					Usage: "LeanCloud region",
				},
				cli.StringFlag{
					Name:  "group",
					Usage: "LeanEngine group",
				},
			},
		},
		{
			Name:   "deploy",
			Usage:  "Deploy the project to LeanEngine",
			Action: wrapAction(deployAction),
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "g",
					Usage: "Deploy from git repo",
				},
				cli.BoolFlag{
					Name:  "war",
					Usage: "Deploy .war file for Java project. The first .war file in target/ is used by default",
				},
				cli.BoolFlag{
					Name:  "no-cache",
					Usage: "Force download dependencies",
				},
				cli.StringFlag{
					Name:  "leanignore",
					Usage: "Rule file for ignored files in deployment",
					Value: ".leanignore",
				},
				cli.StringFlag{
					Name:  "message,m",
					Usage: "Comment for this deployment, only applicable when deploying from local files",
				},
				cli.BoolFlag{
					Name: "keep-deploy-file",
				},
				cli.StringFlag{
					Name:  "revision,r",
					Usage: "Git revision or branch. Only applicable when deploying from Git",
					Value: "master",
				},
				cli.StringFlag{
					Name:  "options",
					Usage: "Send additional deploy options to server, in urlencode format(like `--options build-root=app&atomic=true`)",
				},
				cli.StringFlag{
					Name:  "prod",
					Usage: "Deploy to production(`--prod 1`) or staging(`--prod 0`) environment, default to staging if it exists",
				},
			},
		},
		{
			Name:   "publish",
			Usage:  "Publish code from staging to production",
			Action: wrapAction(publishAction),
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "options",
					Usage: "Send additional deploy options to server, in urlencode format(like `--options build-root=app&atomic=true`)",
				},
			},
		},
		{
			Name:      "upload",
			Usage:     "Upload files to the current application (available in the '_File' class)",
			Action:    uploadAction,
			ArgsUsage: "<file-path> <file-path> ...",
		},
		{
			Name:   "logs",
			Usage:  "Show LeanEngine logs",
			Action: wrapAction(logsAction),
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "f",
					Usage: "Wait for and continuously show most recent logs",
				},
				cli.StringFlag{
					Name:  "env,e",
					Usage: "Environment to view (staging / production)",
					Value: "production",
				},
				cli.IntFlag{
					Name:  "limit,l",
					Usage: "Maximum number of lines to show",
					Value: 30,
				},
				cli.StringFlag{
					Name:  "from",
					Usage: "Start date formatted as YYYY-MM-DD，e.g., 1926-08-17",
				},
				cli.StringFlag{
					Name:  "to",
					Usage: "End date formatted as YYYY-MM-DD，e.g., 1926-08-17",
				},
				cli.StringFlag{
					Name:  "format",
					Usage: "Format to use ('default' or 'json')",
					Value: "default",
				},
			},
		},
		{
			Name:   "debug",
			Usage:  "Start the debug console without running the project",
			Action: wrapAction(debugAction),
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "remote,r",
					Usage: "URL of target app",
					Value: "http://localhost:3000",
				},
				cli.StringFlag{
					Name:  "app-id",
					Usage: "Target AppID, use the AppID of the current project by default",
				},
				cli.IntFlag{
					Name:  "port,p",
					Usage: "Port to listen on",
					Value: 3001,
				},
			},
		},
		{
			Name:   "env",
			Usage:  "Output environment variables used by the current project",
			Action: wrapAction(envAction),
			Flags: []cli.Flag{
				cli.IntFlag{
					Name:  "port,p",
					Usage: "Local port for the app (affects value of LC_APP_PORT)",
					Value: 3000,
				},
				cli.StringFlag{
					Name:  "template",
					Usage: "Template for output, 'export {{name}}={{value}}' by default",
				},
			},
			Subcommands: []cli.Command{
				{
					Name:      "set",
					Usage:     "Set the value of an environment variable",
					Action:    wrapAction(envSetAction),
					ArgsUsage: "[env-name] [env-value]",
				},
				{
					Name:      "unset",
					Usage:     "Delete an environment variable",
					Action:    wrapAction(envUnsetAction),
					ArgsUsage: "[env-name]",
				},
			},
		},
		{
			Name:   "cache",
			Usage:  "LeanCache shell",
			Action: wrapAction(cacheAction),
			Flags: []cli.Flag{
				cli.IntFlag{
					Name:  "db",
					Usage: "Number of LeanCache DB",
					Value: -1,
				},
				cli.StringFlag{
					Name:  "name",
					Usage: "Name of LeanCache instance",
				},
				cli.StringFlag{
					Name:  "eval",
					Usage: "LeanCache command to run",
				},
			},
			Subcommands: []cli.Command{
				{
					Name:   "list",
					Usage:  "Show LeanCache instances of the current project",
					Action: wrapAction(cacheListAction),
				},
			},
		},
		{
			Name:   "cql",
			Usage:  "Start CQL interactive mode (warn: CQL is deprecated)",
			Action: wrapAction(cqlAction),
			Flags: []cli.Flag{
				cli.StringFlag{Name: "format,f",
					Usage: "CQL result format",
					Value: "table",
				},
				cli.StringFlag{
					Name:  "eval",
					Usage: "CQL command to run",
				},
			},
		},
		{
			Name:    "help",
			Aliases: []string{"h"},
			Usage:   "Show all commands or help info for one command",
			Action: func(c *cli.Context) error {
				args := c.Args()
				if args.Present() {
					_, err := fmt.Printf("Please use `lean %s -h` for subcommand usage.\n", args.First())
					return err
				}
				return cli.ShowAppHelp(c)
			},
		},
	}

	app.Before = func(c *cli.Context) error {
		args := []string{"--_collect-stats"}
		args = append(args, c.Args()...)
		err := exec.Command(os.Args[0], args...).Start()
		_ = err
		return nil
	}

	app.Run(args)
}
<|endoftext|>


<commit_before>package ringbuffer

import (
	"fmt"
	"sync"
	"sync/atomic"
)

type RingBuffer struct {
	readIndex  int64      //读序号
	writeIndex int64      //写序号
	buf        []*[]byte  //环形buffer指针数组
	bufSize    int64      //初始化环形buffer指针数组大小
	mask       int64      //初始化环形buffer指针数组大小
	pcond      *sync.Cond //生产者
	ccond      *sync.Cond //消费者
}

func powerOfTwo64(n int64) bool {
	return n != 0 && (n&(n-1)) == 0
}

/**
初始化ringbuffer
参数bufferSize：初始化环形buffer指针数组大小
*/
func NewRingBuffer(size int64) (*RingBuffer, error) {
	if !powerOfTwo64(size) {
		return nil, fmt.Errorf("This size is not able to used")
	}
	buffer := RingBuffer{
		readIndex:  int64(0),
		writeIndex: int64(0),
		buf:        make([]*[]byte, size),
		bufSize:    size,
		mask:       size - int64(1),
		pcond:      sync.NewCond(new(sync.Mutex)),
		ccond:      sync.NewCond(new(sync.Mutex)),
	}
	for i := int64(0); i < size; i++ {
		buffer.buf[i] = nil
	}
	return &buffer, nil
}

/**
获取当前读序号
*/
func (this *RingBuffer) GetCurrentReadIndex() int64 {
	return atomic.LoadInt64(&this.readIndex)
}

/**
获取当前写序号
*/
func (this *RingBuffer) GetCurrentWriteIndex() int64 {
	return atomic.LoadInt64(&this.writeIndex)
}

/**
读取ringbuffer指定的buffer指针，返回该指针并清空ringbuffer该位置存在的指针内容，以及将读序号加1
*/
func (this *RingBuffer) ReadBuffer() (p *[]byte, ok bool) {
	this.ccond.L.Lock()
	defer func() {
		this.pcond.Broadcast()
		this.ccond.L.Unlock()
	}()
	ok = false
	p = nil
	readIndex := this.GetCurrentReadIndex()
	writeIndex := this.GetCurrentWriteIndex()
	for readIndex >= writeIndex {
		writeIndex = this.GetCurrentWriteIndex()
		this.ccond.Wait()
		continue
	}
	index := readIndex & this.mask //替代求模
	p = this.buf[index]
	this.buf[index] = nil
	atomic.AddInt64(&this.readIndex, int64(1))
	if p != nil {
		ok = true
	}
	return p, ok
}

/**
写入ringbuffer指针，以及将写序号加1
*/
func (this *RingBuffer) WriteBuffer(in *[]byte) (ok bool) {
	this.pcond.L.Lock()
	defer func() {
		this.ccond.Broadcast()
		this.pcond.L.Unlock()
	}()
	ok = false
	readIndex := this.GetCurrentReadIndex()
	writeIndex := this.GetCurrentWriteIndex()
	for writeIndex-readIndex > this.bufSize {
		readIndex = this.GetCurrentReadIndex()
		this.pcond.Wait()
		continue
	}
	index := writeIndex & this.mask //替代求模
	this.buf[index] = in
	atomic.AddInt64(&this.writeIndex, int64(1))
	ok = true
	return ok
}
<commit_msg>修改bug<commit_after>package ringbuffer

import (
	"fmt"
	"sync"
	"sync/atomic"
)

type RingBuffer struct {
	readIndex  int64      //读序号
	writeIndex int64      //写序号
	buf        []*[]byte  //环形buffer指针数组
	bufSize    int64      //初始化环形buffer指针数组大小
	mask       int64      //初始化环形buffer指针数组大小
	pcond      *sync.Cond //生产者
	ccond      *sync.Cond //消费者
}

func powerOfTwo64(n int64) bool {
	return n != 0 && (n&(n-1)) == 0
}

/**
初始化ringbuffer
参数bufferSize：初始化环形buffer指针数组大小
*/
func NewRingBuffer(size int64) (*RingBuffer, error) {
	if !powerOfTwo64(size) {
		return nil, fmt.Errorf("This size is not able to used")
	}
	buffer := RingBuffer{
		readIndex:  int64(0),
		writeIndex: int64(0),
		buf:        make([]*[]byte, size),
		bufSize:    size,
		mask:       size - int64(1),
		pcond:      sync.NewCond(new(sync.Mutex)),
		ccond:      sync.NewCond(new(sync.Mutex)),
	}
	for i := int64(0); i < size; i++ {
		buffer.buf[i] = nil
	}
	return &buffer, nil
}

/**
获取当前读序号
*/
func (this *RingBuffer) GetCurrentReadIndex() int64 {
	return atomic.LoadInt64(&this.readIndex)
}

/**
获取当前写序号
*/
func (this *RingBuffer) GetCurrentWriteIndex() int64 {
	return atomic.LoadInt64(&this.writeIndex)
}

/**
读取ringbuffer指定的buffer指针，返回该指针并清空ringbuffer该位置存在的指针内容，以及将读序号加1
*/
func (this *RingBuffer) ReadBuffer() (p *[]byte, ok bool) {
	this.ccond.L.Lock()
	defer func() {
		this.pcond.Broadcast()
		this.ccond.L.Unlock()
	}()
	ok = false
	p = nil
	readIndex := this.GetCurrentReadIndex()
	writeIndex := this.GetCurrentWriteIndex()
	for readIndex > writeIndex {
		writeIndex = this.GetCurrentWriteIndex()
		this.ccond.Wait()
		continue
	}
	index := readIndex & this.mask //替代求模
	p = this.buf[index]
	this.buf[index] = nil
	atomic.AddInt64(&this.readIndex, int64(1))
	if p != nil {
		ok = true
	}
	return p, ok
}

/**
写入ringbuffer指针，以及将写序号加1
*/
func (this *RingBuffer) WriteBuffer(in *[]byte) (ok bool) {
	this.pcond.L.Lock()
	defer func() {
		this.ccond.Broadcast()
		this.pcond.L.Unlock()
	}()
	ok = false
	readIndex := this.GetCurrentReadIndex()
	writeIndex := this.GetCurrentWriteIndex()
	next := writeIndex + int64(1)
	for next-readIndex >= this.bufSize {
		readIndex = this.GetCurrentReadIndex()
		this.pcond.Wait()
		continue
	}
	index := next & this.mask //替代求模
	this.buf[index] = in
	atomic.AddInt64(&this.writeIndex, int64(1))
	ok = true
	return ok
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/MG-RAST/Shock/shock-server/auth"
	"github.com/MG-RAST/Shock/shock-server/conf"
	ncon "github.com/MG-RAST/Shock/shock-server/controller/node"
	acon "github.com/MG-RAST/Shock/shock-server/controller/node/acl"
	icon "github.com/MG-RAST/Shock/shock-server/controller/node/index"
	pcon "github.com/MG-RAST/Shock/shock-server/controller/preauth"
	"github.com/MG-RAST/Shock/shock-server/db"
	"github.com/MG-RAST/Shock/shock-server/logger"
	"github.com/MG-RAST/Shock/shock-server/node"
	"github.com/MG-RAST/Shock/shock-server/preauth"
	"github.com/MG-RAST/Shock/shock-server/responder"
	"github.com/MG-RAST/Shock/shock-server/user"
	"github.com/MG-RAST/Shock/shock-server/util"
	"github.com/MG-RAST/golib/stretchr/goweb"
	"github.com/MG-RAST/golib/stretchr/goweb/context"
	"net"
	"net/http"
	"os"
	"os/signal"
	"runtime"
	"strconv"
	"strings"
	"time"
)

const (
	longDateForm = "2006-01-02T15:04:05-07:00"
)

type anonymous struct {
	Read   bool `json:"read"`
	Write  bool `json:"write"`
	Delete bool `json:"delete"`
}

type resource struct {
	A []string  `json:"attribute_indexes"`
	C string    `json:"contact"`
	D string    `json:"documentation"`
	I string    `json:"id"`
	O []string  `json:"auth"`
	P anonymous `json:"anonymous_permissions"`
	R []string  `json:"resources"`
	S string    `json:"server_time"`
	T string    `json:"type"`
	U string    `json:"url"`
	V string    `json:"version"`
}

func mapRoutes() {
	goweb.MapBefore(func(ctx context.Context) error {
		req := ctx.HttpRequest()
		host, _, _ := net.SplitHostPort(req.RemoteAddr)
		if host == "::1" {
			host = "localhost"
		}
		suffix := ""
		if _, ok := req.Header["Authorization"]; ok {
			suffix += " AUTH"
		}
		if l, has := req.Header["Content-Length"]; has {
			suffix += " Content-Length: " + l[0]
		}
		logger.Info("access", fmt.Sprintf("%s REQ RECEIVED \"%s %s%s\"", host, ctx.MethodString(), req.RequestURI, suffix))
		return nil
	})

	goweb.MapAfter(func(ctx context.Context) error {
		req := ctx.HttpRequest()
		host, _, _ := net.SplitHostPort(req.RemoteAddr)
		if host == "::1" {
			host = "localhost"
		}
		suffix := ""
		if _, ok := req.Header["Authorization"]; ok {
			suffix += " AUTH"
		}
		if l, has := req.Header["Content-Length"]; has {
			suffix += " Content-Length: " + l[0]
		}
		logger.Info("access", fmt.Sprintf("RESPONDED TO %s \"%s %s%s\"", host, ctx.MethodString(), req.RequestURI, suffix))
		return nil
	})

	goweb.Map("/preauth/{id}", func(ctx context.Context) error {
		if ctx.HttpRequest().Method == "OPTIONS" {
			return responder.RespondOK(ctx)
		}
		pcon.PreAuthRequest(ctx)
		return nil
	})

	goweb.Map("/node/{nid}/acl/{type}", func(ctx context.Context) error {
		if ctx.HttpRequest().Method == "OPTIONS" {
			return responder.RespondOK(ctx)
		}
		acon.AclTypedRequest(ctx)
		return nil
	})

	goweb.Map("/node/{nid}/acl/", func(ctx context.Context) error {
		if ctx.HttpRequest().Method == "OPTIONS" {
			return responder.RespondOK(ctx)
		}
		acon.AclRequest(ctx)
		return nil
	})

	goweb.Map("/node/{nid}/index/{idxType}", func(ctx context.Context) error {
		if ctx.HttpRequest().Method == "OPTIONS" {
			return responder.RespondOK(ctx)
		}
		icon.IndexTypedRequest(ctx)
		return nil
	})

	goweb.Map("/", func(ctx context.Context) error {
		host := util.ApiUrl(ctx)

		attrs := strings.Split(conf.MONGODB_ATTRIBUTE_INDEXES, ",")
		for k, v := range attrs {
			attrs[k] = strings.TrimSpace(v)
		}

		anonPerms := new(anonymous)
		anonPerms.Read = conf.ANON_READ
		anonPerms.Write = conf.ANON_WRITE
		anonPerms.Delete = conf.ANON_DELETE

		var auth []string
		if conf.AUTH_GLOBUS_TOKEN_URL != "" && conf.AUTH_GLOBUS_PROFILE_URL != "" {
			auth = append(auth, "globus")
		}
		if conf.AUTH_MGRAST_OAUTH_URL != "" {
			auth = append(auth, "mgrast")
		}

		r := resource{
			A: attrs,
			C: conf.ADMIN_EMAIL,
			D: host + "/wiki/",
			I: "Shock",
			O: auth,
			P: *anonPerms,
			R: []string{"node"},
			S: time.Now().Format(longDateForm),
			T: "Shock",
			U: host + "/",
			V: "[% VERSION %]",
		}
		return responder.WriteResponseObject(ctx, http.StatusOK, r)
	})

	nodeController := new(ncon.NodeController)
	goweb.MapController(nodeController)

	goweb.MapStatic("/wiki", conf.PATH_SITE)

	// Map the favicon
	//goweb.MapStaticFile("/favicon.ico", "static-files/favicon.ico")

	// Catch-all handler for everything that we don't understand
	goweb.Map(func(ctx context.Context) error {
		return responder.RespondWithError(ctx, http.StatusBadRequest, "Parameters do not match a valid Shock request type.")
	})
}

func main() {
	// init(s)
	conf.Initialize()
	logger.Initialize()
	if err := db.Initialize(); err != nil {
		fmt.Fprintf(os.Stderr, "ERROR: %v\n", err)
		logger.Error("ERROR: " + err.Error())
		os.Exit(1)
	}
	user.Initialize()
	node.Initialize()
	preauth.Initialize()
	auth.Initialize()

	// print conf
	printLogo()
	conf.Print()

	// check if necessary directories exist or created
	for _, path := range []string{conf.PATH_SITE, conf.PATH_DATA, conf.PATH_LOGS, conf.PATH_DATA + "/temp"} {
		if _, err := os.Stat(path); err != nil && os.IsNotExist(err) {
			if err := os.Mkdir(path, 0777); err != nil {
				fmt.Fprintf(os.Stderr, "ERROR: %v\n", err)
				logger.Error("ERROR: " + err.Error())
				os.Exit(1)
			}
		}
	}

	// reload
	if conf.RELOAD != "" {
		fmt.Println("####### Reloading #######")
		err := reload(conf.RELOAD)
		if err != nil {
			fmt.Fprintf(os.Stderr, "ERROR: %v\n", err)
			logger.Error("ERROR: " + err.Error())
			os.Exit(1)
		}
		fmt.Println("Done")
	}

	// setting GOMAXPROCS
	var procs int
	avail := runtime.NumCPU()
	if avail <= 2 {
		procs = 1
	} else if avail == 3 {
		procs = 2
	} else {
		procs = avail - 2
	}

	fmt.Println("##### Procs #####")
	fmt.Printf("Number of available CPUs = %d\n", avail)
	if conf.GOMAXPROCS != "" {
		if setting, err := strconv.Atoi(conf.GOMAXPROCS); err != nil {
			err_msg := "ERROR: could not interpret configured GOMAXPROCS value as integer.\n"
			fmt.Fprintf(os.Stderr, err_msg)
			logger.Error("ERROR: " + err_msg)
			os.Exit(1)
		} else {
			procs = setting
		}
	}

	if procs <= avail {
		fmt.Printf("Running Shock server with GOMAXPROCS = %d\n\n", procs)
		runtime.GOMAXPROCS(procs)
	} else {
		fmt.Println("GOMAXPROCS config value is greater than available number of CPUs.")
		fmt.Printf("Running Shock server with GOMAXPROCS = %d\n\n", avail)
		runtime.GOMAXPROCS(avail)
	}

	if conf.PATH_PIDFILE != "" {
		f, err := os.Create(conf.PATH_PIDFILE)
		if err != nil {
			err_msg := "Could not create pid file: " + conf.PATH_PIDFILE + "\n"
			fmt.Fprintf(os.Stderr, err_msg)
			logger.Error("ERROR: " + err_msg)
			os.Exit(1)
		}
		defer f.Close()

		pid := os.Getpid()
		fmt.Fprintln(f, pid)

		fmt.Println("##### pidfile #####")
		fmt.Printf("pid: %d saved to file: %s\n\n", pid, conf.PATH_PIDFILE)
	}

	Address := conf.API_IP + ":" + conf.API_PORT
	mapRoutes()

	s := &http.Server{
		Addr:           ":" + Address,
		Handler:        goweb.DefaultHttpHandler(),
		ReadTimeout:    48 * time.Hour,
		WriteTimeout:   48 * time.Hour,
		MaxHeaderBytes: 1 << 20,
	}

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	listener, listenErr := net.Listen("tcp", Address)

	if listenErr != nil {
		err_msg := "Could not listen - " + listenErr.Error() + "\n"
		fmt.Fprintf(os.Stderr, err_msg)
		logger.Error("ERROR: " + err_msg)
		os.Exit(1)
	}

	go func() {
		for _ = range c {
			// sig is a ^C, handle it

			// stop the HTTP server
			fmt.Fprintln(os.Stderr, "Stopping the server...")
			listener.Close()
		}
	}()

	fmt.Fprintf(os.Stderr, "Error in Serve: %s\n", s.Serve(listener))
}
<commit_msg>Checking versions at startup.<commit_after>package main

import (
	"fmt"
	"github.com/MG-RAST/Shock/shock-server/auth"
	"github.com/MG-RAST/Shock/shock-server/conf"
	ncon "github.com/MG-RAST/Shock/shock-server/controller/node"
	acon "github.com/MG-RAST/Shock/shock-server/controller/node/acl"
	icon "github.com/MG-RAST/Shock/shock-server/controller/node/index"
	pcon "github.com/MG-RAST/Shock/shock-server/controller/preauth"
	"github.com/MG-RAST/Shock/shock-server/db"
	"github.com/MG-RAST/Shock/shock-server/logger"
	"github.com/MG-RAST/Shock/shock-server/node"
	"github.com/MG-RAST/Shock/shock-server/preauth"
	"github.com/MG-RAST/Shock/shock-server/responder"
	"github.com/MG-RAST/Shock/shock-server/user"
	"github.com/MG-RAST/Shock/shock-server/util"
	"github.com/MG-RAST/Shock/shock-server/versions"
	"github.com/MG-RAST/golib/stretchr/goweb"
	"github.com/MG-RAST/golib/stretchr/goweb/context"
	"net"
	"net/http"
	"os"
	"os/signal"
	"runtime"
	"strconv"
	"strings"
	"time"
)

const (
	longDateForm = "2006-01-02T15:04:05-07:00"
)

type anonymous struct {
	Read   bool `json:"read"`
	Write  bool `json:"write"`
	Delete bool `json:"delete"`
}

type resource struct {
	A []string  `json:"attribute_indexes"`
	C string    `json:"contact"`
	D string    `json:"documentation"`
	I string    `json:"id"`
	O []string  `json:"auth"`
	P anonymous `json:"anonymous_permissions"`
	R []string  `json:"resources"`
	S string    `json:"server_time"`
	T string    `json:"type"`
	U string    `json:"url"`
	V string    `json:"version"`
}

func mapRoutes() {
	goweb.MapBefore(func(ctx context.Context) error {
		req := ctx.HttpRequest()
		host, _, _ := net.SplitHostPort(req.RemoteAddr)
		if host == "::1" {
			host = "localhost"
		}
		suffix := ""
		if _, ok := req.Header["Authorization"]; ok {
			suffix += " AUTH"
		}
		if l, has := req.Header["Content-Length"]; has {
			suffix += " Content-Length: " + l[0]
		}
		logger.Info("access", fmt.Sprintf("%s REQ RECEIVED \"%s %s%s\"", host, ctx.MethodString(), req.RequestURI, suffix))
		return nil
	})

	goweb.MapAfter(func(ctx context.Context) error {
		req := ctx.HttpRequest()
		host, _, _ := net.SplitHostPort(req.RemoteAddr)
		if host == "::1" {
			host = "localhost"
		}
		suffix := ""
		if _, ok := req.Header["Authorization"]; ok {
			suffix += " AUTH"
		}
		if l, has := req.Header["Content-Length"]; has {
			suffix += " Content-Length: " + l[0]
		}
		logger.Info("access", fmt.Sprintf("RESPONDED TO %s \"%s %s%s\"", host, ctx.MethodString(), req.RequestURI, suffix))
		return nil
	})

	goweb.Map("/preauth/{id}", func(ctx context.Context) error {
		if ctx.HttpRequest().Method == "OPTIONS" {
			return responder.RespondOK(ctx)
		}
		pcon.PreAuthRequest(ctx)
		return nil
	})

	goweb.Map("/node/{nid}/acl/{type}", func(ctx context.Context) error {
		if ctx.HttpRequest().Method == "OPTIONS" {
			return responder.RespondOK(ctx)
		}
		acon.AclTypedRequest(ctx)
		return nil
	})

	goweb.Map("/node/{nid}/acl/", func(ctx context.Context) error {
		if ctx.HttpRequest().Method == "OPTIONS" {
			return responder.RespondOK(ctx)
		}
		acon.AclRequest(ctx)
		return nil
	})

	goweb.Map("/node/{nid}/index/{idxType}", func(ctx context.Context) error {
		if ctx.HttpRequest().Method == "OPTIONS" {
			return responder.RespondOK(ctx)
		}
		icon.IndexTypedRequest(ctx)
		return nil
	})

	goweb.Map("/", func(ctx context.Context) error {
		host := util.ApiUrl(ctx)

		attrs := strings.Split(conf.MONGODB_ATTRIBUTE_INDEXES, ",")
		for k, v := range attrs {
			attrs[k] = strings.TrimSpace(v)
		}

		anonPerms := new(anonymous)
		anonPerms.Read = conf.ANON_READ
		anonPerms.Write = conf.ANON_WRITE
		anonPerms.Delete = conf.ANON_DELETE

		var auth []string
		if conf.AUTH_GLOBUS_TOKEN_URL != "" && conf.AUTH_GLOBUS_PROFILE_URL != "" {
			auth = append(auth, "globus")
		}
		if conf.AUTH_MGRAST_OAUTH_URL != "" {
			auth = append(auth, "mgrast")
		}

		r := resource{
			A: attrs,
			C: conf.ADMIN_EMAIL,
			D: host + "/wiki/",
			I: "Shock",
			O: auth,
			P: *anonPerms,
			R: []string{"node"},
			S: time.Now().Format(longDateForm),
			T: "Shock",
			U: host + "/",
			V: "[% VERSION %]",
		}
		return responder.WriteResponseObject(ctx, http.StatusOK, r)
	})

	nodeController := new(ncon.NodeController)
	goweb.MapController(nodeController)

	goweb.MapStatic("/wiki", conf.PATH_SITE)

	// Map the favicon
	//goweb.MapStaticFile("/favicon.ico", "static-files/favicon.ico")

	// Catch-all handler for everything that we don't understand
	goweb.Map(func(ctx context.Context) error {
		return responder.RespondWithError(ctx, http.StatusBadRequest, "Parameters do not match a valid Shock request type.")
	})
}

func main() {
	// init(s)
	conf.Initialize()
	logger.Initialize()
	if err := db.Initialize(); err != nil {
		fmt.Fprintf(os.Stderr, "Err@db.Initialize: %v\n", err)
		logger.Error("Err@db.Initialize: " + err.Error())
		os.Exit(1)
	}
	user.Initialize()
	node.Initialize()
	preauth.Initialize()
	auth.Initialize()
	if err := versions.Initialize(); err != nil {
		fmt.Fprintf(os.Stderr, "Err@versions.Initialize: %v\n", err)
		logger.Error("Err@versions.Initialize: " + err.Error())
		os.Exit(1)
	}
	if err := versions.RunVersionUpdates(); err != nil {
		fmt.Fprintf(os.Stderr, "Err@versions.RunVersionUpdates: %v\n", err)
		logger.Error("Err@versions.RunVersionUpdates: " + err.Error())
		os.Exit(1)
	}
	// After version updates have succeeded without error, we can push the configured version numbers into the mongo db
	// Note: configured version numbers are configured in conf.go but are NOT user configurable by design
	if err := versions.PushVersionsToDatabase(); err != nil {
		fmt.Fprintf(os.Stderr, "Err@versions.PushVersionsToDatabase: %v\n", err)
		logger.Error("Err@versions.PushVersionsToDatabase: " + err.Error())
		os.Exit(1)
	}
	printLogo()
	conf.Print()
	if err := versions.Print(); err != nil {
		fmt.Fprintf(os.Stderr, "Err@versions.Print: %v\n", err)
		logger.Error("Err@versions.Print: " + err.Error())
		os.Exit(1)
	}

	// check if necessary directories exist or created
	for _, path := range []string{conf.PATH_SITE, conf.PATH_DATA, conf.PATH_LOGS, conf.PATH_DATA + "/temp"} {
		if _, err := os.Stat(path); err != nil && os.IsNotExist(err) {
			if err := os.Mkdir(path, 0777); err != nil {
				fmt.Fprintf(os.Stderr, "ERROR: %v\n", err)
				logger.Error("ERROR: " + err.Error())
				os.Exit(1)
			}
		}
	}

	// reload
	if conf.RELOAD != "" {
		fmt.Println("####### Reloading #######")
		err := reload(conf.RELOAD)
		if err != nil {
			fmt.Fprintf(os.Stderr, "ERROR: %v\n", err)
			logger.Error("ERROR: " + err.Error())
			os.Exit(1)
		}
		fmt.Println("Done")
	}

	// setting GOMAXPROCS
	var procs int
	avail := runtime.NumCPU()
	if avail <= 2 {
		procs = 1
	} else if avail == 3 {
		procs = 2
	} else {
		procs = avail - 2
	}

	fmt.Println("##### Procs #####")
	fmt.Printf("Number of available CPUs = %d\n", avail)
	if conf.GOMAXPROCS != "" {
		if setting, err := strconv.Atoi(conf.GOMAXPROCS); err != nil {
			err_msg := "ERROR: could not interpret configured GOMAXPROCS value as integer.\n"
			fmt.Fprintf(os.Stderr, err_msg)
			logger.Error("ERROR: " + err_msg)
			os.Exit(1)
		} else {
			procs = setting
		}
	}

	if procs <= avail {
		fmt.Printf("Running Shock server with GOMAXPROCS = %d\n\n", procs)
		runtime.GOMAXPROCS(procs)
	} else {
		fmt.Println("GOMAXPROCS config value is greater than available number of CPUs.")
		fmt.Printf("Running Shock server with GOMAXPROCS = %d\n\n", avail)
		runtime.GOMAXPROCS(avail)
	}

	if conf.PATH_PIDFILE != "" {
		f, err := os.Create(conf.PATH_PIDFILE)
		if err != nil {
			err_msg := "Could not create pid file: " + conf.PATH_PIDFILE + "\n"
			fmt.Fprintf(os.Stderr, err_msg)
			logger.Error("ERROR: " + err_msg)
			os.Exit(1)
		}
		defer f.Close()

		pid := os.Getpid()
		fmt.Fprintln(f, pid)

		fmt.Println("##### pidfile #####")
		fmt.Printf("pid: %d saved to file: %s\n\n", pid, conf.PATH_PIDFILE)
	}

	Address := conf.API_IP + ":" + conf.API_PORT
	mapRoutes()

	s := &http.Server{
		Addr:           ":" + Address,
		Handler:        goweb.DefaultHttpHandler(),
		ReadTimeout:    48 * time.Hour,
		WriteTimeout:   48 * time.Hour,
		MaxHeaderBytes: 1 << 20,
	}

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	listener, listenErr := net.Listen("tcp", Address)

	if listenErr != nil {
		err_msg := "Could not listen - " + listenErr.Error() + "\n"
		fmt.Fprintf(os.Stderr, err_msg)
		logger.Error("ERROR: " + err_msg)
		os.Exit(1)
	}

	go func() {
		for _ = range c {
			// sig is a ^C, handle it

			// stop the HTTP server
			fmt.Fprintln(os.Stderr, "Stopping the server...")
			listener.Close()
		}
	}()

	fmt.Fprintf(os.Stderr, "Error in Serve: %s\n", s.Serve(listener))
}
<|endoftext|>


<commit_before>package repository

import (
	"fmt"
	"github.com/timeredbull/tsuru/api/unit"
	"github.com/timeredbull/tsuru/log"
)

const gitServer = "tsuru.plataformas.glb.com"

func Clone(app string, machine int) ([]byte, error) {
	u := unit.Unit{Name: app, Machine: machine}
	cmd := fmt.Sprintf("git clone %s /home/application/current --depth 1", GetReadOnlyUrl(app))
	output, err := u.Command(cmd)
	log.Printf("Command output: " + string(output))
	if err != nil {
		return output, err
	}
	return output, nil
}

func Pull(app string, machine int) ([]byte, error) {
	u := unit.Unit{Name: app, Machine: machine}
	cmd := fmt.Sprintf("git --git-dir=/home/application/current/.git --work-tree=/home/application/current pull origin master")
	output, err := u.Command(cmd)
	log.Printf("Command output: " + string(output))
	if err != nil {
		return output, err
	}
	return output, u.ExecuteHook("reload-gunicorn")
}

func CloneOrPull(app string, machine int) (string, error) {
	var output []byte
	output, err := Clone(app, machine)
	fmt.Println(string(output))
	if err != nil {
		output, err = Pull(app, machine)
		fmt.Println(string(output))
		if err != nil {
			return string(output), err
		}
	}
	u := unit.Unit{Name: app, Machine: machine}
	err = u.ExecuteHook("dependencies")
	return string(output), err
}

func GetUrl(app string) string {
	return fmt.Sprintf("git@%s:%s.git", gitServer, app)
}

func GetReadOnlyUrl(app string) string {
	return fmt.Sprintf("git://%s/%s.git", gitServer, app)
}
<commit_msg>Removing duplicated hook execution from repository functions<commit_after>package repository

import (
	"fmt"
	"github.com/timeredbull/tsuru/api/unit"
	"github.com/timeredbull/tsuru/log"
)

const gitServer = "tsuru.plataformas.glb.com"

func Clone(app string, machine int) ([]byte, error) {
	u := unit.Unit{Name: app, Machine: machine}
	cmd := fmt.Sprintf("git clone %s /home/application/current --depth 1", GetReadOnlyUrl(app))
	output, err := u.Command(cmd)
	log.Printf(`"git clone" output: ` + string(output))
	if err != nil {
		return output, err
	}
	return output, nil
}

func Pull(app string, machine int) ([]byte, error) {
	u := unit.Unit{Name: app, Machine: machine}
	cmd := fmt.Sprintf("git --git-dir=/home/application/current/.git --work-tree=/home/application/current pull origin master")
	output, err := u.Command(cmd)
	log.Printf(`"git pull" output: ` + string(output))
	if err != nil {
		return output, err
	}
	return output, nil
}

func CloneOrPull(app string, machine int) (string, error) {
	var output []byte
	output, err := Clone(app, machine)
	fmt.Println(string(output))
	if err != nil {
		output, err = Pull(app, machine)
		fmt.Println(string(output))
		if err != nil {
			return string(output), err
		}
	}
	return string(output), nil
}

func GetUrl(app string) string {
	return fmt.Sprintf("git@%s:%s.git", gitServer, app)
}

func GetReadOnlyUrl(app string) string {
	return fmt.Sprintf("git://%s/%s.git", gitServer, app)
}
<|endoftext|>


<commit_before>package routers

import (
	"github.com/pompeu/controllers"
	"github.com/pompeu/helpers"
	"github.com/pompeu/models"
)

func ReHander() *helpers.RegexpHandler {
	person := &models.Person{}
	post := &models.Post{}
	coment := &models.Coment{}
	server := &controllers.Server{}

	h := new(helpers.RegexpHandler)

	h.HandleFunc("/users/$", "POST", person.Save)
	h.HandleFunc("/users/$", "GET", person.GetAll)
	h.HandleFunc("/users/[0-9a-z]+$", "PUT", person.Update)
	h.HandleFunc("/users/[0-9a-z]+$", "DELETE", person.Remove)
	h.HandleFunc("/users/[0-9a-z]+$", "GET", person.GetOne)

	h.HandleFunc("/posts/$", "POST", post.Save)
	h.HandleFunc("/posts/$", "GET", post.GetAll)
	h.HandleFunc("/posts/[0-9a-z]+$", "PUT", post.Update)
	h.HandleFunc("/posts/[0-9a-z]+$", "DELETE", post.Remove)
	h.HandleFunc("/posts/[0-9a-z]+$", "GET", post.GetOne)

	h.HandleFunc("/coments/$", "POST", coment.Save)
	h.HandleFunc("/coments/$", "GET", coment.GetAll)
	h.HandleFunc("/coments/[0-9a-z]+$", "PUT", coment.Update)
	h.HandleFunc("/coments/[0-9a-z]+$", "DELETE", coment.Remove)
	h.HandleFunc("/coments/[0-9a-z]+$", "GET", coment.GetOne)

	h.HandleFunc("/login/", "GET", controllers.Login)
	h.HandleFunc("/login/", "POST", controllers.Login)

	h.HandleFunc("/registrar/", "GET", controllers.Registrar)
	h.HandleFunc("/registrar/", "POST", controllers.Registrar)

	h.HandleFunc(".*.[js|css|png|svg|jpg]", "GET", controllers.Assets)

	h.HandleFunc("/", "GET", server.MainIndex)

	return h
}
<commit_msg>routes not used removed<commit_after>package routers

import (
	"github.com/pompeu/controllers"
	"github.com/pompeu/helpers"
)

func ReHander() *helpers.RegexpHandler {

	h := new(helpers.RegexpHandler)

	h.HandleFunc("/post/$", "GET", controllers.CriarPost)
	h.HandleFunc("/post/edit/[0-9a-z]+$", "GET", controllers.CriarPost)
	h.HandleFunc("/post/show/[0-9a-z]+$", "GET", controllers.ShowPost)
	h.HandleFunc("/post/", "POST", controllers.CriarPost)

	h.HandleFunc("/login/", "GET", controllers.Login)
	h.HandleFunc("/login/", "POST", controllers.Login)
	h.HandleFunc("/logout/", "GET", controllers.Logout)

	h.HandleFunc("/registrar/", "GET", controllers.Registrar)
	h.HandleFunc("/registrar/", "POST", controllers.Registrar)

	h.HandleFunc(".*.[js|css|png|svg|jpg]", "GET", controllers.Assets)

	h.HandleFunc("/", "GET", controllers.MainIndex)

	return h
}
<|endoftext|>