<commit_before>package main

import (
	"database/sql"
	"fmt"
	"log"
	"os"
	"sort"
	"strconv"
	"strings"

	// #TODO(kishorevaishnav): need to write comment why use "_"
	_ "github.com/lib/pq"
)

//PostgresStruct #TODO(kishorevaishnav): need to write some comment & need to write different name instead of PostgresStruct
type PostgresStruct struct {
	bTQ string
}

//PostgreSQLSupportedDataTypes #TODO(kishorevaishnav): need to write some comment
var PostgreSQLSupportedDataTypes = map[string]string{
	"BIGINT":        "BIGINT",
	"BIGSERIAL":     "BIGSERIAL",
	"BIT":           "BIT",
	"BOOLEAN":       "BOOLEAN",
	"BOX":           "BOX",
	"BYTEA":         "BYTEA",
	"CHARACTER":     "CHARACTER",
	"CIDR":          "CIDR",
	"CIRCLE":        "CIRCLE",
	"DATE":          "DATE",
	"INET":          "INET",
	"INTEGER":       "INTEGER",
	"JSON":          "JSON",
	"LINE":          "LINE",
	"LSEG":          "LSEG",
	"MACADDR":       "MACADDR",
	"MONEY":         "MONEY",
	"NUMERIC":       "NUMERIC",
	"PATH":          "PATH",
	"POINT":         "POINT",
	"POLYGON":       "POLYGON",
	"REAL":          "REAL",
	"SMALLINT":      "SMALLINT",
	"SMALLSERIAL":   "SMALLSERIAL",
	"SERIAL":        "SERIAL",
	"TEXT":          "TEXT",
	"TSQUERY":       "TSQUERY",
	"TSVECTOR":      "TSVECTOR",
	"TXID_SNAPSHOT": "TXID_SNAPSHOT",
	"UUID":          "UUID",
	"XML":           "XML",
	"VARBIT":        "VARBIT",
	"BOOL":          "BOOL",
	"CHAR":          "CHAR",
	"VARCHAR":       "VARCHAR",
	"INT":           "INT",
	"INT8":          "INT8",
	"DECIMAL":       "DECIMAL",
	"TIMETZ":        "TIMETZ",
	"TIMESTAMPTZ":   "TIMESTAMPTZ",
}

func init() {
	ListSuppDataTypes["PostgreSQL"] = PostgreSQLSupportedDataTypes
	// ListSuppDataTypes["Postgres"] = PostgreSQLSupportedDataTypes
}

// // ListOfSupportedDataTypes return the supported List of DataTypes.
// func (s PostgresStruct) ListOfSupportedDataTypes() (sdt map[string]string) {
// 	return PostgreSQLSupportedDataTypes
// }

// Init is called to initiate the connection to check and do some activities
func (s PostgresStruct) Init(c Config) {
	// This can be useful to check for version and any other dependencies etc.,
	// fmt.Println("postgres init() it runs before other functions")
	if c.DbPort == "" {
		c.DbPort = "5432"
	}
	Db, err = sql.Open("postgres", "postgres://"+c.DbUsername+":"+c.DbPassword+"@"+c.DbHostname+"/"+c.DbName+"?sslmode=disable")
	if err != nil {
		log.Fatal(err)
	}
	migrationTableName = c.MigrationTableName

	localConfig = c
	s.bTQ = "\"" // s.bTQ = backTickQuote
}

// GetLastMigrationNo to get what is the last migration it has executed.
func (s PostgresStruct) GetLastMigrationNo() string {
	maxVersion := ""
	query := "SELECT max(" + s.bTQ + "version" + s.bTQ + ") FROM " + s.bTQ + migrationTableName + s.bTQ
	q, err := Db.Query(query)
	defer q.Close()
	if err != nil {
		log.Println(migrationTableName + " table doesn't exists")
		log.Fatal(err)
	} else {
		q.Next()
		q.Scan(&maxVersion)
	}
	return maxVersion
}

// CreateMigrationTable used to create the schema_migration if it doesn't exists.
func (s PostgresStruct) CreateMigrationTable() {
	query := "CREATE TABLE " + s.bTQ + migrationTableName + s.bTQ + " (" + s.bTQ + "version" + s.bTQ + " VARCHAR(15))"
	q, err := Db.Query(query)
	defer q.Close()
	if err != nil {
		log.Fatal(err)
	} else {
		log.Println("Table Created Successfully.")
	}
}

// ProcessNow is used to run the actual migraition whether it is UP or DOWN.
func (s PostgresStruct) ProcessNow(lm Migration, mig UpDown, updown string, force bool) {
	if updown == "up" {
		if force == false && lm.ID <= s.GetLastMigrationNo() {
			return
		}
		if force == true && s.checkMigrationExecutedForID(lm.ID) {
			fmt.Println(lm.ID + " -> Its already executed.")
			return
		}
	}

	localUpDown = updown
	workingVersion = lm.ID

	if nid, _ := strconv.Atoi(lm.ID); nid != 0 {
		fmt.Println("Executing ID : ", lm.ID)
		s.execQuery(s.ReturnQuery(mig))
		if mig.Sql != "" {
			s.directSQL(mig.Sql)
		}
		s.updateMigrationTable()
	}
}

// ReturnQuery will return direct SQL query
func (s PostgresStruct) ReturnQuery(mig UpDown) string {
	for _, v := range mig.AddColumn {
		for _, vv := range v.Columns {
			// #TODO(kishorevaishnav): need to remove the return out of the for loop
			return s.addColumn(s.bTQ+v.TableName+s.bTQ, s.bTQ+vv.FieldName+s.bTQ+" ", s.dataTypeConversion(vv.DataType))
		}
	}
	for _, v := range mig.AddIndex {
		var fieldNameArray []string
		for _, vv := range v.Columns {
			fieldNameArray = append(fieldNameArray, s.bTQ+vv.FieldName+s.bTQ+" ")
		}
		return s.addIndex(s.bTQ+v.TableName+s.bTQ, v.IndexType, fieldNameArray)
	}
	for _, v := range mig.CreateTable {
		var valuesArray []string
		for _, vv := range v.Columns {
			valuesArray = append(valuesArray, s.bTQ+vv.FieldName+s.bTQ+" "+s.dataTypeConversion(vv.DataType))
		}
		return s.createTable(s.bTQ+v.TableName+s.bTQ, valuesArray)
	}
	for _, v := range mig.DropColumn {
		for _, vv := range v.Columns {
			// #TODO(kishorevaishnav): need to remove the return out of the for loop
			return s.dropColumn(s.bTQ+v.TableName+s.bTQ, s.bTQ+vv.FieldName+s.bTQ+" ")
		}
	}
	for _, v := range mig.DropIndex {
		var fieldNameArray []string
		for _, vv := range v.Columns {
			fieldNameArray = append(fieldNameArray, s.bTQ+vv.FieldName+s.bTQ+" ")
		}
		return s.dropIndex(s.bTQ+v.TableName+s.bTQ, v.IndexType, fieldNameArray)
	}
	for _, v := range mig.DropTable {
		// #TODO(kishorevaishnav): need to remove the return out of the for loop
		return s.dropTable(s.bTQ + v.TableName + s.bTQ)
	}
	for _, v := range mig.RenameTable {
		// #TODO(kishorevaishnav): need to remove the return out of the for loop
		return s.renameTable(s.bTQ+v.OldTableName+s.bTQ, s.bTQ+v.NewTableName+s.bTQ)
	}
	return ""
}

func (s PostgresStruct) updateMigrationTable() {
	var query string
	if localUpDown == "up" {
		query = "INSERT INTO " + s.bTQ + migrationTableName + s.bTQ + "(" + s.bTQ + "version" + s.bTQ + ") VALUES ('" + workingVersion + "')"
	} else {
		query = "DELETE FROM " + s.bTQ + migrationTableName + s.bTQ + " WHERE " + s.bTQ + "version" + s.bTQ + "='" + workingVersion + "'"
	}
	q, err := Db.Query(query)
	defer q.Close()
	if err != nil {
		log.Println("not able to add version to the existing migration table")
		log.Fatal(err)
	}
}

func (s PostgresStruct) checkMigrationExecutedForID(id string) bool {
	var version = ""
	query := "SELECT " + s.bTQ + "version" + s.bTQ + " FROM " + s.bTQ + migrationTableName + s.bTQ + " WHERE " + s.bTQ + "version" + s.bTQ + "='" + id + "'"
	q, err := Db.Query(query)
	defer q.Close()
	if err != nil {
		log.Println("couldn't able to execute the check version query...")
		log.Fatal(err)
	} else {
		q.Next()
		q.Scan(&version)
	}
	if version == "" {
		return false
	}
	return true
}

func (s PostgresStruct) dataTypeConversion(dt string) string {
	if PostgreSQLSupportedDataTypes[strings.ToUpper(dt)] == "" {
		fmt.Println("UnSupported DataType")
		os.Exit(1)
	}
	return PostgreSQLSupportedDataTypes[strings.ToUpper(dt)]
}

func (s PostgresStruct) directSQL(query string) {
	s.execQuery(query)
	return
}

func (s PostgresStruct) execQuery(query string) {
	fmt.Println("Postgres---" + query)
	q, err := Db.Query(query)
	if err != nil {
		log.Fatal(err)
	}
	defer q.Close()
}

func (s PostgresStruct) createTable(tableName string, fieldDataType []string) string {
	return "CREATE TABLE " + tableName + " (" + strings.Join(fieldDataType, ",") + ")"
}

func (s PostgresStruct) dropTable(tableName string) string {
	return "DROP TABLE " + tableName
}

func (s PostgresStruct) addColumn(tableName string, columnName string, dataType string) string {
	return "ALTER TABLE " + tableName + " ADD " + columnName + " " + dataType
}

func (s PostgresStruct) dropColumn(tableName string, columnName string) string {
	return "ALTER TABLE " + tableName + " DROP " + columnName
}

func (s PostgresStruct) addIndex(tableName string, indexType string, field []string) string {
	// #TODO(kishorevaishnav): currently indexType is always empty as we don't have a proper way.

	sort.Strings(field)
	tmpIndexName := localConfig.IndexPrefix + "_" + strings.Join(field, "_") + "_" + localConfig.IndexSuffix
	tmpIndexName = strings.Trim(strings.Replace(strings.Replace(strings.ToLower(tmpIndexName), s.bTQ+"", "", -1), " ", "", -1), "_")
	return "CREATE " + strings.ToUpper(indexType) + " INDEX " + tmpIndexName + " ON " + tableName + "( " + strings.Join(field, ",") + " )"
}

func (s PostgresStruct) dropIndex(tableName string, indexType string, field []string) string {
	// #TODO(kishorevaishnav): currently indexType is always empty as we don't have a proper way.

	sort.Strings(field)
	tmpIndexName := localConfig.IndexPrefix + "_" + strings.Join(field, "_") + "_" + localConfig.IndexSuffix
	tmpIndexName = strings.Trim(strings.Replace(strings.Replace(strings.ToLower(tmpIndexName), s.bTQ+"", "", -1), " ", "", -1), "_")
	if indexType != "" {
		return "ALTER TABLE " + tableName + " DROP " + strings.ToUpper(indexType)
	}
	return "ALTER TABLE " + tableName + " DROP INDEX " + tmpIndexName
}

func (s PostgresStruct) renameTable(oldTableName string, newTableName string) string {
	return "ALTER TABLE " + oldTableName + " RENAME " + newTableName
}
<commit_msg>Added common datatypes for postgres<commit_after>package main

import (
	"database/sql"
	"fmt"
	"log"
	"os"
	"sort"
	"strconv"
	"strings"

	// #TODO(kishorevaishnav): need to write comment why use "_"
	_ "github.com/lib/pq"
)

//PostgresStruct #TODO(kishorevaishnav): need to write some comment & need to write different name instead of PostgresStruct
type PostgresStruct struct {
	bTQ string
}

//PostgreSQLSupportedDataTypes #TODO(kishorevaishnav): need to write some comment
var PostgreSQLSupportedDataTypes = map[string]string{
	"BIGINT":        "BIGINT",
	"BIGSERIAL":     "BIGSERIAL",
	"BIT":           "BIT",
	"BOOLEAN":       "BOOLEAN",
	"BOX":           "BOX",
	"BYTEA":         "BYTEA",
	"CHARACTER":     "CHARACTER",
	"CIDR":          "CIDR",
	"CIRCLE":        "CIRCLE",
	"DATE":          "DATE",
	"INET":          "INET",
	"INTEGER":       "INTEGER",
	"JSON":          "JSON",
	"LINE":          "LINE",
	"LSEG":          "LSEG",
	"MACADDR":       "MACADDR",
	"MONEY":         "MONEY",
	"NUMERIC":       "NUMERIC",
	"PATH":          "PATH",
	"POINT":         "POINT",
	"POLYGON":       "POLYGON",
	"REAL":          "REAL",
	"SMALLINT":      "SMALLINT",
	"SMALLSERIAL":   "SMALLSERIAL",
	"SERIAL":        "SERIAL",
	"TEXT":          "TEXT",
	"TSQUERY":       "TSQUERY",
	"TSVECTOR":      "TSVECTOR",
	"TXID_SNAPSHOT": "TXID_SNAPSHOT",
	"UUID":          "UUID",
	"XML":           "XML",
	"VARBIT":        "VARBIT",
	"BOOL":          "BOOL",
	"CHAR":          "CHAR",
	"VARCHAR":       "VARCHAR",
	"INT":           "INT",
	"INT8":          "INT8",
	"DECIMAL":       "DECIMAL",
	"TIMETZ":        "TIMETZ",
	"TIMESTAMPTZ":   "TIMESTAMPTZ",
	"INT":           "INTEGER",      // Alias of INTEGER
	"DEC":           "DECIMAL",      // Alias of DECIMAL
	"NUMERIC":       "DECIMAL",      // Alias of DECIMAL
	"FIXED":         "DECIMAL",      // Alias of DECIMAL
	"BOOL":          "BOOLEAN",      // Alias of BOOLEAN
	"STRING":        "VARCHAR(255)", // Alias of VARCHAR
}

func init() {
	ListSuppDataTypes["PostgreSQL"] = PostgreSQLSupportedDataTypes
	// ListSuppDataTypes["Postgres"] = PostgreSQLSupportedDataTypes
}

// // ListOfSupportedDataTypes return the supported List of DataTypes.
// func (s PostgresStruct) ListOfSupportedDataTypes() (sdt map[string]string) {
// 	return PostgreSQLSupportedDataTypes
// }

// Init is called to initiate the connection to check and do some activities
func (s PostgresStruct) Init(c Config) {
	// This can be useful to check for version and any other dependencies etc.,
	// fmt.Println("postgres init() it runs before other functions")
	if c.DbPort == "" {
		c.DbPort = "5432"
	}
	Db, err = sql.Open("postgres", "postgres://"+c.DbUsername+":"+c.DbPassword+"@"+c.DbHostname+"/"+c.DbName+"?sslmode=disable")
	if err != nil {
		log.Fatal(err)
	}
	migrationTableName = c.MigrationTableName

	localConfig = c
	s.bTQ = "\"" // s.bTQ = backTickQuote
}

// GetLastMigrationNo to get what is the last migration it has executed.
func (s PostgresStruct) GetLastMigrationNo() string {
	maxVersion := ""
	query := "SELECT max(" + s.bTQ + "version" + s.bTQ + ") FROM " + s.bTQ + migrationTableName + s.bTQ
	q, err := Db.Query(query)
	defer q.Close()
	if err != nil {
		log.Println(migrationTableName + " table doesn't exists")
		log.Fatal(err)
	} else {
		q.Next()
		q.Scan(&maxVersion)
	}
	return maxVersion
}

// CreateMigrationTable used to create the schema_migration if it doesn't exists.
func (s PostgresStruct) CreateMigrationTable() {
	query := "CREATE TABLE " + s.bTQ + migrationTableName + s.bTQ + " (" + s.bTQ + "version" + s.bTQ + " VARCHAR(15))"
	q, err := Db.Query(query)
	defer q.Close()
	if err != nil {
		log.Fatal(err)
	} else {
		log.Println("Table Created Successfully.")
	}
}

// ProcessNow is used to run the actual migraition whether it is UP or DOWN.
func (s PostgresStruct) ProcessNow(lm Migration, mig UpDown, updown string, force bool) {
	if updown == "up" {
		if force == false && lm.ID <= s.GetLastMigrationNo() {
			return
		}
		if force == true && s.checkMigrationExecutedForID(lm.ID) {
			fmt.Println(lm.ID + " -> Its already executed.")
			return
		}
	}

	localUpDown = updown
	workingVersion = lm.ID

	if nid, _ := strconv.Atoi(lm.ID); nid != 0 {
		fmt.Println("Executing ID : ", lm.ID)
		s.execQuery(s.ReturnQuery(mig))
		if mig.Sql != "" {
			s.directSQL(mig.Sql)
		}
		s.updateMigrationTable()
	}
}

// ReturnQuery will return direct SQL query
func (s PostgresStruct) ReturnQuery(mig UpDown) string {
	for _, v := range mig.AddColumn {
		for _, vv := range v.Columns {
			// #TODO(kishorevaishnav): need to remove the return out of the for loop
			return s.addColumn(s.bTQ+v.TableName+s.bTQ, s.bTQ+vv.FieldName+s.bTQ+" ", s.dataTypeConversion(vv.DataType))
		}
	}
	for _, v := range mig.AddIndex {
		var fieldNameArray []string
		for _, vv := range v.Columns {
			fieldNameArray = append(fieldNameArray, s.bTQ+vv.FieldName+s.bTQ+" ")
		}
		return s.addIndex(s.bTQ+v.TableName+s.bTQ, v.IndexType, fieldNameArray)
	}
	for _, v := range mig.CreateTable {
		var valuesArray []string
		for _, vv := range v.Columns {
			valuesArray = append(valuesArray, s.bTQ+vv.FieldName+s.bTQ+" "+s.dataTypeConversion(vv.DataType))
		}
		return s.createTable(s.bTQ+v.TableName+s.bTQ, valuesArray)
	}
	for _, v := range mig.DropColumn {
		for _, vv := range v.Columns {
			// #TODO(kishorevaishnav): need to remove the return out of the for loop
			return s.dropColumn(s.bTQ+v.TableName+s.bTQ, s.bTQ+vv.FieldName+s.bTQ+" ")
		}
	}
	for _, v := range mig.DropIndex {
		var fieldNameArray []string
		for _, vv := range v.Columns {
			fieldNameArray = append(fieldNameArray, s.bTQ+vv.FieldName+s.bTQ+" ")
		}
		return s.dropIndex(s.bTQ+v.TableName+s.bTQ, v.IndexType, fieldNameArray)
	}
	for _, v := range mig.DropTable {
		// #TODO(kishorevaishnav): need to remove the return out of the for loop
		return s.dropTable(s.bTQ + v.TableName + s.bTQ)
	}
	for _, v := range mig.RenameTable {
		// #TODO(kishorevaishnav): need to remove the return out of the for loop
		return s.renameTable(s.bTQ+v.OldTableName+s.bTQ, s.bTQ+v.NewTableName+s.bTQ)
	}
	return ""
}

func (s PostgresStruct) updateMigrationTable() {
	var query string
	if localUpDown == "up" {
		query = "INSERT INTO " + s.bTQ + migrationTableName + s.bTQ + "(" + s.bTQ + "version" + s.bTQ + ") VALUES ('" + workingVersion + "')"
	} else {
		query = "DELETE FROM " + s.bTQ + migrationTableName + s.bTQ + " WHERE " + s.bTQ + "version" + s.bTQ + "='" + workingVersion + "'"
	}
	q, err := Db.Query(query)
	defer q.Close()
	if err != nil {
		log.Println("not able to add version to the existing migration table")
		log.Fatal(err)
	}
}

func (s PostgresStruct) checkMigrationExecutedForID(id string) bool {
	var version = ""
	query := "SELECT " + s.bTQ + "version" + s.bTQ + " FROM " + s.bTQ + migrationTableName + s.bTQ + " WHERE " + s.bTQ + "version" + s.bTQ + "='" + id + "'"
	q, err := Db.Query(query)
	defer q.Close()
	if err != nil {
		log.Println("couldn't able to execute the check version query...")
		log.Fatal(err)
	} else {
		q.Next()
		q.Scan(&version)
	}
	if version == "" {
		return false
	}
	return true
}

func (s PostgresStruct) dataTypeConversion(dt string) string {
	if PostgreSQLSupportedDataTypes[strings.ToUpper(dt)] == "" {
		fmt.Println("UnSupported DataType")
		os.Exit(1)
	}
	return PostgreSQLSupportedDataTypes[strings.ToUpper(dt)]
}

func (s PostgresStruct) directSQL(query string) {
	s.execQuery(query)
	return
}

func (s PostgresStruct) execQuery(query string) {
	fmt.Println("Postgres---" + query)
	q, err := Db.Query(query)
	if err != nil {
		log.Fatal(err)
	}
	defer q.Close()
}

func (s PostgresStruct) createTable(tableName string, fieldDataType []string) string {
	return "CREATE TABLE " + tableName + " (" + strings.Join(fieldDataType, ",") + ")"
}

func (s PostgresStruct) dropTable(tableName string) string {
	return "DROP TABLE " + tableName
}

func (s PostgresStruct) addColumn(tableName string, columnName string, dataType string) string {
	return "ALTER TABLE " + tableName + " ADD " + columnName + " " + dataType
}

func (s PostgresStruct) dropColumn(tableName string, columnName string) string {
	return "ALTER TABLE " + tableName + " DROP " + columnName
}

func (s PostgresStruct) addIndex(tableName string, indexType string, field []string) string {
	// #TODO(kishorevaishnav): currently indexType is always empty as we don't have a proper way.

	sort.Strings(field)
	tmpIndexName := localConfig.IndexPrefix + "_" + strings.Join(field, "_") + "_" + localConfig.IndexSuffix
	tmpIndexName = strings.Trim(strings.Replace(strings.Replace(strings.ToLower(tmpIndexName), s.bTQ+"", "", -1), " ", "", -1), "_")
	return "CREATE " + strings.ToUpper(indexType) + " INDEX " + tmpIndexName + " ON " + tableName + "( " + strings.Join(field, ",") + " )"
}

func (s PostgresStruct) dropIndex(tableName string, indexType string, field []string) string {
	// #TODO(kishorevaishnav): currently indexType is always empty as we don't have a proper way.

	sort.Strings(field)
	tmpIndexName := localConfig.IndexPrefix + "_" + strings.Join(field, "_") + "_" + localConfig.IndexSuffix
	tmpIndexName = strings.Trim(strings.Replace(strings.Replace(strings.ToLower(tmpIndexName), s.bTQ+"", "", -1), " ", "", -1), "_")
	if indexType != "" {
		return "ALTER TABLE " + tableName + " DROP " + strings.ToUpper(indexType)
	}
	return "ALTER TABLE " + tableName + " DROP INDEX " + tmpIndexName
}

func (s PostgresStruct) renameTable(oldTableName string, newTableName string) string {
	return "ALTER TABLE " + oldTableName + " RENAME " + newTableName
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"encoding/binary"
	"flag"
	"fmt"
	"log"
	"os"
	"strings"
	"time"

	"github.com/DimShadoWWW/power-pg/proxy"
	"github.com/parnurzeal/gorequest"
)

var (
	localHost     = flag.String("l", ":9876", "Endereço e porta do listener local")
	remoteHost    = flag.String("r", "localhost:5432", "Endereço e porta do servidor PostgreSQL")
	remoteService = flag.String("s", "", "http://localhost:8080/query")
	messages      = []string{}
)

func main() {
	flag.Parse()
	msgs := make(chan string)
	msgCh := make(chan proxy.Pkg)
	msgOut := make(chan string)
	if *remoteService != "" {
		go func() {
			time.Sleep(time.Second * 3)
			inFile, _ := os.Open("canales_list.txt")
			defer inFile.Close()
			scanner := bufio.NewScanner(inFile)
			scanner.Split(bufio.ScanLines)

			for scanner.Scan() {
				time.Sleep(time.Second * 1)
				messages = []string{}
				fmt.Println(scanner.Text())
				msgOut <- fmt.Sprintf("# %s\n", scanner.Text())
				_, _, errs := gorequest.New().Get(fmt.Sprintf("%s%s", *remoteService, scanner.Text())).End()
				if errs != nil {
					log.Fatalf("log failed: %v", errs)
				}
			}
			log.Println("done")
			os.Exit(0)
		}()
	}

	go func() {
		f, err := os.OpenFile("/all.txt", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0777)
		if err != nil {
			panic(err)
		}
		defer f.Close()
		for msg := range msgs {
			// fmt.Println(msg)
			_, err := f.WriteString(fmt.Sprintf("%s\n", msg))
			if err != nil {
				log.Fatalf("log failed: %v", err)
			}
		}
	}()

	go func() {
		f, err := os.OpenFile("/report.md", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0777)
		if err != nil {
			panic(err)
		}
		defer f.Close()
		for msg := range msgOut {
			fmt.Println(msg)
			_, err := f.WriteString(fmt.Sprintf("%s\n", msg))
			if err != nil {
				log.Fatalf("log failed: %v", err)
			}
		}
	}()

	go func() {
		temp := ""
		for msg := range msgCh {
			if msg.Type == 'P' {
				if strings.Contains(string(msg.Content), "$1") {
					selectIdx := strings.Index(string(msg.Content), string([]byte{83, 69, 76, 69, 67, 84, 32}))
					if selectIdx == -1 {
						selectIdx = 0
					}
					sepIdx := strings.Index(string(msg.Content), string([]byte{0, 1, 0, 0}))
					if sepIdx == -1 {
						sepIdx = len(msg.Content) - 4
					}

					temp = string(bytes.Trim(msg.Content[selectIdx:sepIdx], "\x00"))
					fmt.Printf("SEP index ----->%v\n", sepIdx)
					fmt.Printf("SEP len   ----->%v\n", len(msg.Content))
					fmt.Printf("SEP CONT  ----->%v\n", msg.Content)
				} else {
					temp = ""
					selectIdx := strings.Index(string(msg.Content), string([]byte{83, 69, 76, 69, 67, 84, 32}))
					if selectIdx == -1 {
						selectIdx = 0
					}
					sepIdx := strings.Index(string(msg.Content), string([]byte{0, 0, 1, 0, 0}))
					if sepIdx == -1 || sepIdx+5 > len(msg.Content) {
						sepIdx := strings.Index(string(msg.Content), string([]byte{0, 1, 0, 0}))
						if sepIdx == -1 || sepIdx+4 > len(msg.Content) {
							sepIdx = len(msg.Content) - 4
						} else {
							sepIdx = len(msg.Content) - 1
						}
					}
					if sepIdx == -1 {
						sepIdx = len(msg.Content)
					}
					if selectIdx == -1 {
						selectIdx = 0
					}

					fmt.Printf("SEP index ----->%v\n", sepIdx)
					fmt.Printf("SEP len   ----->%v\n", len(msg.Content))
					fmt.Printf("SEP CONT  ----->%v\n", msg.Content)
					messages = append(messages, string(bytes.Trim(msg.Content[selectIdx:sepIdx], "\x00")))
				}
			} else {
				if msg.Type == 'B' && len(msg.Content) > 28 && temp != "" {
					var newMsg proxy.ReadBuf
					newMsg = msg.Content

					// The name of the destination portal (an empty string selects the unnamed portal).
					p := bytes.Index(newMsg, []byte{0})
					// remove first string
					newMsg = newMsg[p+1:]

					// The name of the source prepared statement (an empty string selects the unnamed prepared statement).
					p = bytes.Index(newMsg, []byte{0})
					// remove second string
					newMsg = newMsg[p+1:]

					t := newMsg.Int16()
					for i := 0; i < t; i++ {
						t = newMsg.Int16()
					}

					totalVar := newMsg.Int16()
					vars := make(map[int]string)
					var varsIdx []int
					for i := 0; i < totalVar; i++ {
						fmt.Printf("2 newMsg   ----->%#v\n", newMsg)
						// varLen := newMsg.Int32()
						aa := newMsg.Next(4)
						fmt.Printf("aa   -----> %#v\n", aa)
						fmt.Printf("aa bits ----->%8b\n", aa[len(aa)-1])
						varLen := int(binary.BigEndian.Uint32(aa))
						fmt.Printf("varLen ----->%v\n", varLen)
						fmt.Printf("newMsg   ----->%#v\n", newMsg)
						vars[i] = string(newMsg.Next(varLen))
						fmt.Printf("vars   ----->%#v\n", vars)
						varsIdx = append(varsIdx, i)
						fmt.Printf("varIdx  ----->%#v\n", varsIdx)
					}
					// fmt.Printf("2 newMsg   ----->%#v\n", newMsg)

					// idxPdo := strings.Index(string(msg.Content), "pdo_stmt_")
					//
					// if idxPdo != -1 {
					// 	var newMsg proxy.ReadBuf
					// 	// B type allways ends with 0100
					// 	fmt.Printf("msg.Content   ----->%#v\n", msg.Content)
					// 	newMsg = msg.Content[idxPdo+22 : len(msg.Content)-4]
					// 	fmt.Printf("1 newMsg   ----->%#v\n", newMsg)
					// 	totalVar := newMsg.Int16()
					//
					// 	vars := make(map[int]string)
					// 	var varsIdx []int
					// 	for i := 0; i < totalVar; i++ {
					// 		fmt.Printf("2 newMsg   ----->%#v\n", newMsg)
					// 		// varLen := newMsg.Int32()
					// 		aa := newMsg.Next(4)
					// 		fmt.Printf("aa   -----> %#v\n", aa)
					// 		fmt.Printf("aa bits ----->%8b\n", aa[len(aa)-1])
					// 		varLen := int(binary.BigEndian.Uint32(aa))
					// 		fmt.Printf("varLen ----->%v\n", varLen)
					// 		fmt.Printf("newMsg   ----->%#v\n", newMsg)
					// 		vars[i] = string(newMsg.Next(varLen))
					// 		fmt.Printf("vars   ----->%#v\n", vars)
					// 		varsIdx = append(varsIdx, i)
					// 		fmt.Printf("varIdx  ----->%#v\n", varsIdx)
					// 	}
					// 	sort.Sort(sort.Reverse(sort.IntSlice(varsIdx)))
					// 	for _, k := range varsIdx {
					// 		messages = append(messages, strings.Replace(temp, fmt.Sprintf("$%d", k+1), fmt.Sprintf("'%s'", string(newMsg[k+1])), -1))
					// 	}
					// } else {
					// 	messages = append(messages, string(msg.Content[29:len(msg.Content)-4]))
					// }

				}
				temp = ""
			}
			fmt.Printf("---------->%v\n", messages)
			fmt.Printf("---------->%#v\n", messages)
			for k, v := range messages {
				msgOut <- fmt.Sprintf("%d. %s\n", k+1, v)
			}
		}
	}()

	proxy.Start(localHost, remoteHost, getQueryModificada, msgs, msgCh)
}

func getQueryModificada(queryOriginal string) string {
	// log.Println("aa")
	// if queryOriginal[:5] != "power" {
	// 	return queryOriginal
	// }

	// log.Println(queryOriginal)
	fmt.Println(queryOriginal)
	return queryOriginal
}
<commit_msg>Update<commit_after>package main

import (
	"bufio"
	"bytes"
	"flag"
	"fmt"
	"log"
	"os"
	"strings"
	"time"

	"github.com/DimShadoWWW/power-pg/proxy"
	"github.com/parnurzeal/gorequest"
)

var (
	localHost     = flag.String("l", ":9876", "Endereço e porta do listener local")
	remoteHost    = flag.String("r", "localhost:5432", "Endereço e porta do servidor PostgreSQL")
	remoteService = flag.String("s", "", "http://localhost:8080/query")
	messages      = []string{}
)

func main() {
	flag.Parse()
	msgs := make(chan string)
	msgCh := make(chan proxy.Pkg)
	msgOut := make(chan string)
	if *remoteService != "" {
		go func() {
			time.Sleep(time.Second * 3)
			inFile, _ := os.Open("canales_list.txt")
			defer inFile.Close()
			scanner := bufio.NewScanner(inFile)
			scanner.Split(bufio.ScanLines)

			for scanner.Scan() {
				time.Sleep(time.Second * 1)
				messages = []string{}
				fmt.Println(scanner.Text())
				msgOut <- fmt.Sprintf("# %s\n", scanner.Text())
				_, _, errs := gorequest.New().Get(fmt.Sprintf("%s%s", *remoteService, scanner.Text())).End()
				if errs != nil {
					log.Fatalf("log failed: %v", errs)
				}
			}
			log.Println("done")
			os.Exit(0)
		}()
	}

	go func() {
		f, err := os.OpenFile("/all.txt", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0777)
		if err != nil {
			panic(err)
		}
		defer f.Close()
		for msg := range msgs {
			// fmt.Println(msg)
			_, err := f.WriteString(fmt.Sprintf("%s\n", msg))
			if err != nil {
				log.Fatalf("log failed: %v", err)
			}
		}
	}()

	go func() {
		f, err := os.OpenFile("/report.md", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0777)
		if err != nil {
			panic(err)
		}
		defer f.Close()
		for msg := range msgOut {
			fmt.Println(msg)
			_, err := f.WriteString(fmt.Sprintf("%s\n", msg))
			if err != nil {
				log.Fatalf("log failed: %v", err)
			}
		}
	}()

	go func() {
		temp := ""
		for msg := range msgCh {
			if msg.Type == 'P' {
				if strings.Contains(string(msg.Content), "$1") {
					selectIdx := strings.Index(string(msg.Content), string([]byte{83, 69, 76, 69, 67, 84, 32}))
					if selectIdx == -1 {
						selectIdx = 0
					}
					sepIdx := strings.Index(string(msg.Content), string([]byte{0, 1, 0, 0}))
					if sepIdx == -1 {
						sepIdx = len(msg.Content) - 4
					}

					temp = string(bytes.Trim(msg.Content[selectIdx:sepIdx], "\x00"))
					fmt.Printf("SEP index ----->%v\n", sepIdx)
					fmt.Printf("SEP len   ----->%v\n", len(msg.Content))
					fmt.Printf("SEP CONT  ----->%v\n", msg.Content)
				} else {
					temp = ""
					selectIdx := strings.Index(string(msg.Content), string([]byte{83, 69, 76, 69, 67, 84, 32}))
					if selectIdx == -1 {
						selectIdx = 0
					}
					sepIdx := strings.Index(string(msg.Content), string([]byte{0, 0, 1, 0, 0}))
					if sepIdx == -1 || sepIdx+5 > len(msg.Content) {
						sepIdx := strings.Index(string(msg.Content), string([]byte{0, 1, 0, 0}))
						if sepIdx == -1 || sepIdx+4 > len(msg.Content) {
							sepIdx = len(msg.Content) - 4
						} else {
							sepIdx = len(msg.Content) - 1
						}
					}
					if sepIdx == -1 {
						sepIdx = len(msg.Content)
					}
					if selectIdx == -1 {
						selectIdx = 0
					}

					fmt.Printf("SEP index ----->%v\n", sepIdx)
					fmt.Printf("SEP len   ----->%v\n", len(msg.Content))
					fmt.Printf("SEP CONT  ----->%v\n", msg.Content)
					messages = append(messages, string(bytes.Trim(msg.Content[selectIdx:sepIdx], "\x00")))
				}
			} else {
				if msg.Type == 'B' && len(msg.Content) > 28 && temp != "" {
					var newMsg proxy.ReadBuf
					newMsg = msg.Content

					// The name of the destination portal (an empty string selects the unnamed portal).
					p := bytes.Index(newMsg, []byte{0})
					// remove first string
					newMsg = newMsg[p+1:]

					// The name of the source prepared statement (an empty string selects the unnamed prepared statement).
					p = bytes.Index(newMsg, []byte{0})
					// remove second string
					newMsg = newMsg[p+1:]

					t := newMsg.Int16()
					for i := 0; i < t; i++ {
						t = newMsg.Int16()
					}

					totalVar := newMsg.Int16()
					vars := make(map[int]string)
					var varsIdx []int
					for i := 0; i < totalVar; i++ {
						fmt.Printf("2 newMsg   ----->%#v\n", newMsg)
						varLen := newMsg.Int32()
						// aa := newMsg.Next(4)
						// fmt.Printf("aa   -----> %#v\n", aa)
						// fmt.Printf("aa bits ----->%8b\n", aa[len(aa)-1])
						// varLen := int(binary.BigEndian.Uint32(aa))
						fmt.Printf("varLen ----->%v\n", varLen)
						fmt.Printf("newMsg   ----->%#v\n", newMsg)
						vars[i] = string(newMsg.Next(varLen))
						fmt.Printf("vars   ----->%#v\n", vars)
						varsIdx = append(varsIdx, i)
						fmt.Printf("varIdx  ----->%#v\n", varsIdx)
					}
					// fmt.Printf("2 newMsg   ----->%#v\n", newMsg)

					// idxPdo := strings.Index(string(msg.Content), "pdo_stmt_")
					//
					// if idxPdo != -1 {
					// 	var newMsg proxy.ReadBuf
					// 	// B type allways ends with 0100
					// 	fmt.Printf("msg.Content   ----->%#v\n", msg.Content)
					// 	newMsg = msg.Content[idxPdo+22 : len(msg.Content)-4]
					// 	fmt.Printf("1 newMsg   ----->%#v\n", newMsg)
					// 	totalVar := newMsg.Int16()
					//
					// 	vars := make(map[int]string)
					// 	var varsIdx []int
					// 	for i := 0; i < totalVar; i++ {
					// 		fmt.Printf("2 newMsg   ----->%#v\n", newMsg)
					// 		// varLen := newMsg.Int32()
					// 		aa := newMsg.Next(4)
					// 		fmt.Printf("aa   -----> %#v\n", aa)
					// 		fmt.Printf("aa bits ----->%8b\n", aa[len(aa)-1])
					// 		varLen := int(binary.BigEndian.Uint32(aa))
					// 		fmt.Printf("varLen ----->%v\n", varLen)
					// 		fmt.Printf("newMsg   ----->%#v\n", newMsg)
					// 		vars[i] = string(newMsg.Next(varLen))
					// 		fmt.Printf("vars   ----->%#v\n", vars)
					// 		varsIdx = append(varsIdx, i)
					// 		fmt.Printf("varIdx  ----->%#v\n", varsIdx)
					// 	}
					// 	sort.Sort(sort.Reverse(sort.IntSlice(varsIdx)))
					// 	for _, k := range varsIdx {
					// 		messages = append(messages, strings.Replace(temp, fmt.Sprintf("$%d", k+1), fmt.Sprintf("'%s'", string(newMsg[k+1])), -1))
					// 	}
					// } else {
					// 	messages = append(messages, string(msg.Content[29:len(msg.Content)-4]))
					// }

				}
				temp = ""
			}
			fmt.Printf("---------->%v\n", messages)
			fmt.Printf("---------->%#v\n", messages)
			for k, v := range messages {
				msgOut <- fmt.Sprintf("%d. %s\n", k+1, v)
			}
		}
	}()

	proxy.Start(localHost, remoteHost, getQueryModificada, msgs, msgCh)
}

func getQueryModificada(queryOriginal string) string {
	// log.Println("aa")
	// if queryOriginal[:5] != "power" {
	// 	return queryOriginal
	// }

	// log.Println(queryOriginal)
	fmt.Println(queryOriginal)
	return queryOriginal
}
<|endoftext|>


<commit_before>package dockerhub

import (
	"fmt"

	"github.com/saulshanabrook/pypi-dockerhub/release"
)

func (c *Client) AddRelease(rel *release.Release) (err error) {
	rel.Log().Debug("Dockerhub: checking if repo exists")
	repoExists, err := c.checkRepoExists(rel)
	if err != nil {
		return wrapError(err, "checking repo exists")
	}
	if !repoExists {
		rel.Log().Debug("Dockerhub: Doesn't exist; creating repo and build")
		if err = c.createRepoAndBuild(rel); err != nil {
			return wrapError(err, "creating repo and build")
		}
	} else {
		rel.Log().Debug("Dockerhub: Exists; checking if build exists")
		buildExists, err := c.checkBuildExists(rel)
		if err != nil {
			return wrapError(err, "checking build exists")
		}
		if !buildExists {
			rel.Log().Debug("Dockerhub: creating build")
			if err = c.createBuild(rel); err != nil {
				return wrapError(err, "creating build")
			}
		} else {
			rel.Log().Debug("Dockerhub: build already exists")
		}
	}
	rel.Log().Debug("Dockerhub: triggering build")
	if err = c.triggerBuild(rel); err != nil {
		return wrapError(err, "triggering build")
	}

	rel.Log().Debug("Dockerhub: setting full description")
	err = c.setFullDescription(rel)
	return wrapError(err, "setting full description")
}

func (c *Client) checkRepoExists(rel *release.Release) (bool, error) {
	res, err := c.callRepo(rel, "autobuild/", "GET", nil, 0, nil)
	if err != nil {
		return false, err
	}
	if res.StatusCode == 404 {
		return false, nil
	}
	if res.StatusCode == 200 {
		return true, nil
	}
	return false, wrongResponseError(res, "autobuild should have either been a 404 or a 200")
}

type buildTag struct {
	Name               string `json:"name"`
	SourceType         string `json:"source_type"`
	SourceName         string `json:"source_name"`
	DockerfileLocation string `json:"dockerfile_location"`
}

func (c *Client) createRepoAndBuild(rel *release.Release) error {
	body := struct {
		Active            bool       `json:"active"`
		BuildTags         []buildTag `json:"build_tags"`
		Description       string     `json:"description"`
		DockerhubRepoName string     `json:"dockerhub_repo_name"`
		IsPrivate         bool       `json:"is_private"`
		Name              string     `json:"name"`
		Namespace         string     `json:"namespace"`
		Provider          string     `json:"provider"`
		VCSRepoName       string     `json:"vcs_repo_name"`
	}{
		Active: false,
		BuildTags: []buildTag{{
			Name:               "latest",
			SourceType:         "Branch",
			SourceName:         "master",
			DockerfileLocation: rel.DockerfilePath(),
		}, {
			Name:               rel.DockerhubTag(),
			SourceType:         "Tag",
			SourceName:         rel.GithubTagName(),
			DockerfileLocation: rel.DockerfilePath(),
		}},
		Description:       rel.DockerhubRepoShortDescription(),
		DockerhubRepoName: fmt.Sprintf("%v/%v", c.dockerhubOwner, rel.DockerhubName()),
		IsPrivate:         false,
		Name:              rel.DockerhubName(),
		Namespace:         c.dockerhubOwner,
		Provider:          "github",
		VCSRepoName:       fmt.Sprintf("%v/%v", c.githubOwner, c.githubRepo),
	}
	res, err := c.callRepo(rel, "autobuild/", "POST", body, 201, nil)
	if err != nil {
		return err
	}
	if err = res.Body.Close(); err != nil {
		return wrapError(err, "closing body on autobuild/")
	}

	var resJSON struct{ Active bool }
	res, err = c.callRepo(rel, "autobuild/", "PATCH", struct {
		Active bool `json:"active"`
	}{false}, 200, &resJSON)
	if err != nil {
		return wrapError(err, "turning off autobuild")
	}
	if resJSON.Active != false {
		return fmt.Errorf("Couldnt turn off autobuilding")
	}
	err = res.Body.Close()
	return wrapError(err, "closing body on PATCH autobuild/")
}

type autobuildReponse struct {
	BuildTags []buildTag `json:"builds_tags"`
}

func (c *Client) checkBuildExists(rel *release.Release) (bool, error) {
	var resJSON autobuildReponse
	if _, err := c.callRepo(rel, "autobuild/", "GET", "", 200, &resJSON); err != nil {
		return false, err
	}
	for _, bt := range resJSON.BuildTags {
		if bt.Name == rel.DockerhubTag() {
			return true, nil
		}
	}
	return false, nil
}

type completeBuildTag struct {
	buildTag
	IsNew     bool   `json:"is_new"`
	Namespace string `json:"namespace"`
	RepoName  string `json:"repo_name"`
}

func (c *Client) createBuild(rel *release.Release) error {
	body := completeBuildTag{
		buildTag: buildTag{
			Name:               rel.DockerhubTag(),
			SourceType:         "Tag",
			SourceName:         rel.GithubTagName(),
			DockerfileLocation: rel.DockerfilePath(),
		},
		IsNew:     true,
		Namespace: c.dockerhubOwner,
		RepoName:  rel.DockerhubName(),
	}
	res, err := c.callRepo(rel, "autobuild/tags/", "POST", body, 201, nil)
	if err != nil {
		return wrapError(err, "adding build")
	}
	return wrapError(res.Body.Close(), "closing body on autobuild/tags")
}

func (c *Client) triggerBuild(rel *release.Release) (err error) {
	_, err = c.callRepo(rel, "autobuild/trigger-build/", "POST", "", 201, nil)
	return
}

type fullDescriptionBody struct {
	FullDescription string `json:"full_description"`
}

func (c *Client) setFullDescription(rel *release.Release) (err error) {
	_, err = c.callRepo(rel, "", "PATCH", fullDescriptionBody{rel.DockerhubRepoFullDescription()}, 200, nil)
	return
}
<commit_msg>fix checking build exists<commit_after>package dockerhub

import (
	"fmt"

	"github.com/saulshanabrook/pypi-dockerhub/release"
)

func (c *Client) AddRelease(rel *release.Release) (err error) {
	rel.Log().Debug("Dockerhub: checking if repo exists")
	repoExists, err := c.checkRepoExists(rel)
	if err != nil {
		return wrapError(err, "checking repo exists")
	}
	if !repoExists {
		rel.Log().Debug("Dockerhub: Doesn't exist; creating repo and build")
		if err = c.createRepoAndBuild(rel); err != nil {
			return wrapError(err, "creating repo and build")
		}
	} else {
		rel.Log().Debug("Dockerhub: Exists; checking if build exists")
		buildExists, err := c.checkBuildExists(rel)
		if err != nil {
			return wrapError(err, "checking build exists")
		}
		if !buildExists {
			rel.Log().Debug("Dockerhub: creating build")
			if err = c.createBuild(rel); err != nil {
				return wrapError(err, "creating build")
			}
		} else {
			rel.Log().Debug("Dockerhub: build already exists")
		}
	}
	rel.Log().Debug("Dockerhub: triggering build")
	if err = c.triggerBuild(rel); err != nil {
		return wrapError(err, "triggering build")
	}

	rel.Log().Debug("Dockerhub: setting full description")
	err = c.setFullDescription(rel)
	return wrapError(err, "setting full description")
}

func (c *Client) checkRepoExists(rel *release.Release) (bool, error) {
	res, err := c.callRepo(rel, "autobuild/", "GET", nil, 0, nil)
	if err != nil {
		return false, err
	}
	if res.StatusCode == 404 {
		return false, nil
	}
	if res.StatusCode == 200 {
		return true, nil
	}
	return false, wrongResponseError(res, "autobuild should have either been a 404 or a 200")
}

type buildTag struct {
	Name               string `json:"name"`
	SourceType         string `json:"source_type"`
	SourceName         string `json:"source_name"`
	DockerfileLocation string `json:"dockerfile_location"`
}

func (c *Client) createRepoAndBuild(rel *release.Release) error {
	body := struct {
		Active            bool       `json:"active"`
		BuildTags         []buildTag `json:"build_tags"`
		Description       string     `json:"description"`
		DockerhubRepoName string     `json:"dockerhub_repo_name"`
		IsPrivate         bool       `json:"is_private"`
		Name              string     `json:"name"`
		Namespace         string     `json:"namespace"`
		Provider          string     `json:"provider"`
		VCSRepoName       string     `json:"vcs_repo_name"`
	}{
		Active: false,
		BuildTags: []buildTag{{
			Name:               "latest",
			SourceType:         "Branch",
			SourceName:         "master",
			DockerfileLocation: rel.DockerfilePath(),
		}, {
			Name:               rel.DockerhubTag(),
			SourceType:         "Tag",
			SourceName:         rel.GithubTagName(),
			DockerfileLocation: rel.DockerfilePath(),
		}},
		Description:       rel.DockerhubRepoShortDescription(),
		DockerhubRepoName: fmt.Sprintf("%v/%v", c.dockerhubOwner, rel.DockerhubName()),
		IsPrivate:         false,
		Name:              rel.DockerhubName(),
		Namespace:         c.dockerhubOwner,
		Provider:          "github",
		VCSRepoName:       fmt.Sprintf("%v/%v", c.githubOwner, c.githubRepo),
	}
	res, err := c.callRepo(rel, "autobuild/", "POST", body, 201, nil)
	if err != nil {
		return err
	}
	if err = res.Body.Close(); err != nil {
		return wrapError(err, "closing body on autobuild/")
	}

	var resJSON struct{ Active bool }
	res, err = c.callRepo(rel, "autobuild/", "PATCH", struct {
		Active bool `json:"active"`
	}{false}, 200, &resJSON)
	if err != nil {
		return wrapError(err, "turning off autobuild")
	}
	if resJSON.Active != false {
		return fmt.Errorf("Couldnt turn off autobuilding")
	}
	err = res.Body.Close()
	return wrapError(err, "closing body on PATCH autobuild/")
}

type autobuildReponse struct {
	BuildTags []buildTag `json:"build_tags"`
}

func (c *Client) checkBuildExists(rel *release.Release) (bool, error) {
	var resJSON autobuildReponse
	if _, err := c.callRepo(rel, "autobuild/", "GET", "", 200, &resJSON); err != nil {
		return false, err
	}
	for _, bt := range resJSON.BuildTags {
		if bt.Name == rel.DockerhubTag() {
			return true, nil
		}
	}
	return false, nil
}

type completeBuildTag struct {
	buildTag
	IsNew     bool   `json:"is_new"`
	Namespace string `json:"namespace"`
	RepoName  string `json:"repo_name"`
}

func (c *Client) createBuild(rel *release.Release) error {
	body := completeBuildTag{
		buildTag: buildTag{
			Name:               rel.DockerhubTag(),
			SourceType:         "Tag",
			SourceName:         rel.GithubTagName(),
			DockerfileLocation: rel.DockerfilePath(),
		},
		IsNew:     true,
		Namespace: c.dockerhubOwner,
		RepoName:  rel.DockerhubName(),
	}
	res, err := c.callRepo(rel, "autobuild/tags/", "POST", body, 201, nil)
	if err != nil {
		return wrapError(err, "adding build")
	}
	return wrapError(res.Body.Close(), "closing body on autobuild/tags")
}

func (c *Client) triggerBuild(rel *release.Release) (err error) {
	_, err = c.callRepo(rel, "autobuild/trigger-build/", "POST", "", 201, nil)
	return
}

type fullDescriptionBody struct {
	FullDescription string `json:"full_description"`
}

func (c *Client) setFullDescription(rel *release.Release) (err error) {
	_, err = c.callRepo(rel, "", "PATCH", fullDescriptionBody{rel.DockerhubRepoFullDescription()}, 200, nil)
	return
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"encoding/json"

	"time"

	"fmt"

	"strconv"

	"github.com/google/go-github/github"
)

type MirroredPR struct {
	DownstreamID int
	UpstreamID   int
}

type PRMirror struct {
	GitHubClient  *github.Client
	Context       *context.Context
	Configuration *Config
	Database      *Database
}

func (p PRMirror) HandlePREvent(prEvent *github.PullRequestEvent) {

	prAction := prEvent.GetAction()

	log.Debugf("%s\n", prEvent.PullRequest.GetURL())

	if prAction == "closed" {
		if prEvent.PullRequest.GetMerged() == true {
			prID, err := p.MirrorPR(prEvent.PullRequest)
			if err != nil {
				log.Errorf("Error while creating a new PR: %s\n", err.Error())
			} else {
				p.AddLabels(prID, []string{"Upstream PR Merged"})
				p.Database.StoreMirror(prID, prEvent.PullRequest.GetNumber())
			}
		}
	}
}

func (p PRMirror) isRatelimit(err error) bool {
	if _, ok := err.(*github.RateLimitError); ok {
		// TODO: Maybe add some context here
		log.Error("The github.com rate limit has been hit")
		return true
	}
	return false
}

func (p PRMirror) GetRepoEvents() ([]*github.Event, int64, error) {
	var allEvents []*github.Event
	var pollInterval = int64(0)

	opt := &github.ListOptions{
		PerPage: 100,
	}

	for {
		log.Debugf("Getting RepoEvents Page %d\n", opt.Page)

		events, resp, err := p.GitHubClient.Activity.ListRepositoryEvents(*p.Context, p.Configuration.UpstreamOwner, p.Configuration.UpstreamRepo, opt)
		if err != nil {
			log.Errorf("Error while listing repository events. %s", err.Error())
			return nil, 60, err
		}

		allEvents = append(allEvents, events...)
		if resp.NextPage == 0 {
			pollInterval, err = strconv.ParseInt(resp.Response.Header.Get("X-Poll-Interval"), 10, 64)
			if err != nil {
				panic(err)
			}
			break
		}
		opt.Page = resp.NextPage
	}

	return allEvents, pollInterval, nil
}

func (p PRMirror) GetOpenPRs() ([]*github.PullRequest, error) {
	var allPrs []*github.PullRequest

	opt := &github.PullRequestListOptions{
		ListOptions: github.ListOptions{PerPage: 100},
	}

	for {
		log.Debugf("Getting OpenPRs Page %d\n", opt.ListOptions.Page)

		prs, resp, err := p.GitHubClient.PullRequests.List(*p.Context, p.Configuration.UpstreamOwner, p.Configuration.UpstreamRepo, opt)
		if p.isRatelimit(err) {
			return nil, err
		}

		allPrs = append(allPrs, prs...)
		if resp.NextPage == 0 {
			break
		}
		opt.ListOptions.Page = resp.NextPage
	}

	return allPrs, nil
}

func (p PRMirror) InitialImport() {
	prs, err := p.GetOpenPRs()
	if p.isRatelimit(err) {
		return
	}

	for _, pr := range prs {
		prNum, err := p.Database.GetDownstreamID(pr.GetNumber())
		if err != nil {
			panic(err)
		}

		if prNum != 0 {
			log.Infof("DUP: [%d] - %s\n", pr.GetNumber(), pr.GetTitle())
		} else {
			log.Infof("NEW: [%d] - %s\n", pr.GetNumber(), pr.GetTitle())
			prID, err := p.MirrorPR(pr)
			if err != nil {
				log.Errorf("Error while creating a new PR: %s\n", err.Error())
			} else {
				p.Database.StoreMirror(prID, pr.GetNumber())
				p.AddLabels(prID, []string{"Upstream PR Open"})
			}
			time.Sleep(2 * time.Second)
		}
	}
}

func (p PRMirror) Run() {
	for {
		events, pollInterval, err := p.GetRepoEvents()
		if err == nil {
			for _, event := range events {
				seenEvent, _ := p.Database.SeenEvent(event.GetID())

				if !seenEvent {
					eventType := event.GetType()

					if eventType == "PullRequestEvent" {
						prEvent := github.PullRequestEvent{}
						err = json.Unmarshal(event.GetRawPayload(), &prEvent)
						if err != nil {
							panic(err)
						}

						p.HandlePREvent(&prEvent)
						p.Database.AddEvent(event.GetID())
					}
				}
			}
		}

		log.Debugf("Sleeping for %d as specified by GitHub\n", pollInterval)
		time.Sleep(time.Duration(pollInterval) * time.Second)
	}
}

func (p PRMirror) MirrorPR(pr *github.PullRequest) (int, error) {
	log.Infof("Mirroring PR [%d]: %s from %s\n", pr.GetNumber(), pr.GetTitle(), pr.User.GetLogin())

	base := "master"
	maintainerCanModify := false
	title := fmt.Sprintf("[MIRROR] %s", pr.GetTitle())
	body := fmt.Sprintf("Original PR: %s\n--------------------\n%s", pr.GetHTMLURL(), strings.Replace(pr.GetBody(), "@", "@ ", -1))

	newPR := github.NewPullRequest{}
	newPR.Title = &title
	newPR.Body = &body
	newPR.Base = &base
	newPR.Head = pr.Head.Label
	newPR.MaintainerCanModify = &maintainerCanModify

	pr, _, err := p.GitHubClient.PullRequests.Create(*p.Context, p.Configuration.DownstreamOwner, p.Configuration.DownstreamRepo, &newPR)
	if err != nil {
		return 0, err
	}

	return pr.GetNumber(), nil
}

func (p PRMirror) CreateLabel(labelText string, labelColour string) bool {
	label := github.Label{
		Name:  &labelText,
		Color: &labelColour,
	}

	_, _, err := p.GitHubClient.Issues.CreateLabel(*p.Context, p.Configuration.DownstreamOwner, p.Configuration.DownstreamRepo, &label)
	if err != nil {
		log.Errorf("Error while creating a label - %s", err.Error())
		return false
	}

	return true
}

func (p PRMirror) AddLabels(id int, labels []string) bool {
	_, _, err := p.GitHubClient.Issues.AddLabelsToIssue(*p.Context, p.Configuration.DownstreamOwner, p.Configuration.DownstreamRepo, id, labels)
	if err != nil {
		log.Errorf("Error while adding a label on issue#:%d - %s", id, err.Error())
		return false
	}

	return true
}

func (p PRMirror) RemoveLabel(id int, labels string) bool {
	_, err := p.GitHubClient.Issues.RemoveLabelForIssue(*p.Context, p.Configuration.DownstreamOwner, p.Configuration.DownstreamRepo, id, labels)
	if err != nil {
		log.Errorf("Error while removing a label on issue#:%d - %s", id, err.Error())
		return false
	}

	return true
}

func (p PRMirror) AddComment(id int, comment string) bool {
	issueComment := github.IssueComment{}
	issueComment.Body = &comment

	_, _, err := p.GitHubClient.Issues.CreateComment(*p.Context, p.Configuration.DownstreamOwner, p.Configuration.DownstreamRepo, id, &issueComment)
	if err != nil {
		log.Errorf("Error while adding a comment to issue#:%d - %s", id, err.Error())
		return false
	}

	return true
}
<commit_msg>Oopsie.<commit_after>package main

import (
	"context"
	"encoding/json"
	"fmt"
	"strconv"
	"strings"
	"time"

	"github.com/google/go-github/github"
)

type MirroredPR struct {
	DownstreamID int
	UpstreamID   int
}

type PRMirror struct {
	GitHubClient  *github.Client
	Context       *context.Context
	Configuration *Config
	Database      *Database
}

func (p PRMirror) HandlePREvent(prEvent *github.PullRequestEvent) {

	prAction := prEvent.GetAction()

	log.Debugf("%s\n", prEvent.PullRequest.GetURL())

	if prAction == "closed" {
		if prEvent.PullRequest.GetMerged() == true {
			prID, err := p.MirrorPR(prEvent.PullRequest)
			if err != nil {
				log.Errorf("Error while creating a new PR: %s\n", err.Error())
			} else {
				p.AddLabels(prID, []string{"Upstream PR Merged"})
				p.Database.StoreMirror(prID, prEvent.PullRequest.GetNumber())
			}
		}
	}
}

func (p PRMirror) isRatelimit(err error) bool {
	if _, ok := err.(*github.RateLimitError); ok {
		// TODO: Maybe add some context here
		log.Error("The github.com rate limit has been hit")
		return true
	}
	return false
}

func (p PRMirror) GetRepoEvents() ([]*github.Event, int64, error) {
	var allEvents []*github.Event
	var pollInterval = int64(0)

	opt := &github.ListOptions{
		PerPage: 100,
	}

	for {
		log.Debugf("Getting RepoEvents Page %d\n", opt.Page)

		events, resp, err := p.GitHubClient.Activity.ListRepositoryEvents(*p.Context, p.Configuration.UpstreamOwner, p.Configuration.UpstreamRepo, opt)
		if err != nil {
			log.Errorf("Error while listing repository events. %s", err.Error())
			return nil, 60, err
		}

		allEvents = append(allEvents, events...)
		if resp.NextPage == 0 {
			pollInterval, err = strconv.ParseInt(resp.Response.Header.Get("X-Poll-Interval"), 10, 64)
			if err != nil {
				panic(err)
			}
			break
		}
		opt.Page = resp.NextPage
	}

	return allEvents, pollInterval, nil
}

func (p PRMirror) GetOpenPRs() ([]*github.PullRequest, error) {
	var allPrs []*github.PullRequest

	opt := &github.PullRequestListOptions{
		ListOptions: github.ListOptions{PerPage: 100},
	}

	for {
		log.Debugf("Getting OpenPRs Page %d\n", opt.ListOptions.Page)

		prs, resp, err := p.GitHubClient.PullRequests.List(*p.Context, p.Configuration.UpstreamOwner, p.Configuration.UpstreamRepo, opt)
		if p.isRatelimit(err) {
			return nil, err
		}

		allPrs = append(allPrs, prs...)
		if resp.NextPage == 0 {
			break
		}
		opt.ListOptions.Page = resp.NextPage
	}

	return allPrs, nil
}

func (p PRMirror) InitialImport() {
	prs, err := p.GetOpenPRs()
	if p.isRatelimit(err) {
		return
	}

	for _, pr := range prs {
		prNum, err := p.Database.GetDownstreamID(pr.GetNumber())
		if err != nil {
			panic(err)
		}

		if prNum != 0 {
			log.Infof("DUP: [%d] - %s\n", pr.GetNumber(), pr.GetTitle())
		} else {
			log.Infof("NEW: [%d] - %s\n", pr.GetNumber(), pr.GetTitle())
			prID, err := p.MirrorPR(pr)
			if err != nil {
				log.Errorf("Error while creating a new PR: %s\n", err.Error())
			} else {
				p.Database.StoreMirror(prID, pr.GetNumber())
				p.AddLabels(prID, []string{"Upstream PR Open"})
			}
			time.Sleep(2 * time.Second)
		}
	}
}

func (p PRMirror) Run() {
	for {
		events, pollInterval, err := p.GetRepoEvents()
		if err == nil {
			for _, event := range events {
				seenEvent, _ := p.Database.SeenEvent(event.GetID())

				if !seenEvent {
					eventType := event.GetType()

					if eventType == "PullRequestEvent" {
						prEvent := github.PullRequestEvent{}
						err = json.Unmarshal(event.GetRawPayload(), &prEvent)
						if err != nil {
							panic(err)
						}

						p.HandlePREvent(&prEvent)
						p.Database.AddEvent(event.GetID())
					}
				}
			}
		}

		log.Debugf("Sleeping for %d as specified by GitHub\n", pollInterval)
		time.Sleep(time.Duration(pollInterval) * time.Second)
	}
}

func (p PRMirror) MirrorPR(pr *github.PullRequest) (int, error) {
	log.Infof("Mirroring PR [%d]: %s from %s\n", pr.GetNumber(), pr.GetTitle(), pr.User.GetLogin())

	base := "master"
	maintainerCanModify := false
	title := fmt.Sprintf("[MIRROR] %s", pr.GetTitle())
	body := fmt.Sprintf("Original PR: %s\n--------------------\n%s", pr.GetHTMLURL(), strings.Replace(pr.GetBody(), "@", "@ ", -1))

	newPR := github.NewPullRequest{}
	newPR.Title = &title
	newPR.Body = &body
	newPR.Base = &base
	newPR.Head = pr.Head.Label
	newPR.MaintainerCanModify = &maintainerCanModify

	pr, _, err := p.GitHubClient.PullRequests.Create(*p.Context, p.Configuration.DownstreamOwner, p.Configuration.DownstreamRepo, &newPR)
	if err != nil {
		return 0, err
	}

	return pr.GetNumber(), nil
}

func (p PRMirror) CreateLabel(labelText string, labelColour string) bool {
	label := github.Label{
		Name:  &labelText,
		Color: &labelColour,
	}

	_, _, err := p.GitHubClient.Issues.CreateLabel(*p.Context, p.Configuration.DownstreamOwner, p.Configuration.DownstreamRepo, &label)
	if err != nil {
		log.Errorf("Error while creating a label - %s", err.Error())
		return false
	}

	return true
}

func (p PRMirror) AddLabels(id int, labels []string) bool {
	_, _, err := p.GitHubClient.Issues.AddLabelsToIssue(*p.Context, p.Configuration.DownstreamOwner, p.Configuration.DownstreamRepo, id, labels)
	if err != nil {
		log.Errorf("Error while adding a label on issue#:%d - %s", id, err.Error())
		return false
	}

	return true
}

func (p PRMirror) RemoveLabel(id int, labels string) bool {
	_, err := p.GitHubClient.Issues.RemoveLabelForIssue(*p.Context, p.Configuration.DownstreamOwner, p.Configuration.DownstreamRepo, id, labels)
	if err != nil {
		log.Errorf("Error while removing a label on issue#:%d - %s", id, err.Error())
		return false
	}

	return true
}

func (p PRMirror) AddComment(id int, comment string) bool {
	issueComment := github.IssueComment{}
	issueComment.Body = &comment

	_, _, err := p.GitHubClient.Issues.CreateComment(*p.Context, p.Configuration.DownstreamOwner, p.Configuration.DownstreamRepo, id, &issueComment)
	if err != nil {
		log.Errorf("Error while adding a comment to issue#:%d - %s", id, err.Error())
		return false
	}

	return true
}
<|endoftext|>


<commit_before>package mpb

import (
	"bytes"
	"container/heap"
	"context"
	"io"
	"io/ioutil"
	"log"
	"os"
	"sync"
	"time"

	"github.com/vbauerster/mpb/v4/cwriter"
	"github.com/vbauerster/mpb/v4/decor"
)

const (
	// default RefreshRate
	prr = 120 * time.Millisecond
	// default width
	pwidth = 80
)

// Progress represents the container that renders Progress bars
type Progress struct {
	ctx          context.Context
	uwg          *sync.WaitGroup
	cwg          *sync.WaitGroup
	bwg          *sync.WaitGroup
	operateState chan func(*pState)
	done         chan struct{}
	forceRefresh chan time.Time
	once         sync.Once
	dlogger      *log.Logger
}

type pState struct {
	bHeap            priorityQueue
	heapUpdated      bool
	pMatrix          map[int][]chan int
	aMatrix          map[int][]chan int
	barShutdownQueue []*Bar
	barPopQueue      []*Bar

	// following are provided/overrided by user
	idCount          int
	width            int
	popCompleted     bool
	rr               time.Duration
	uwg              *sync.WaitGroup
	manualRefreshCh  <-chan time.Time
	shutdownNotifier chan struct{}
	parkedBars       map[*Bar]*Bar
	output           io.Writer
	debugOut         io.Writer
}

// New creates new Progress container instance. It's not possible to
// reuse instance after *Progress.Wait() method has been called.
func New(options ...ContainerOption) *Progress {
	return NewWithContext(context.Background(), options...)
}

// NewWithContext creates new Progress container instance with provided
// context. It's not possible to reuse instance after *Progress.Wait()
// method has been called.
func NewWithContext(ctx context.Context, options ...ContainerOption) *Progress {
	s := &pState{
		bHeap:      priorityQueue{},
		width:      pwidth,
		rr:         prr,
		parkedBars: make(map[*Bar]*Bar),
		output:     os.Stdout,
		debugOut:   ioutil.Discard,
	}

	for _, opt := range options {
		if opt != nil {
			opt(s)
		}
	}

	p := &Progress{
		ctx:          ctx,
		uwg:          s.uwg,
		cwg:          new(sync.WaitGroup),
		bwg:          new(sync.WaitGroup),
		operateState: make(chan func(*pState)),
		forceRefresh: make(chan time.Time),
		done:         make(chan struct{}),
		dlogger:      log.New(s.debugOut, "[mpb] ", log.Lshortfile),
	}

	p.cwg.Add(1)
	go p.serve(s, cwriter.New(s.output))
	return p
}

// AddBar creates a new progress bar and adds to the container.
func (p *Progress) AddBar(total int64, options ...BarOption) *Bar {
	return p.Add(total, NewBarFiller(), options...)
}

// AddSpinner creates a new spinner bar and adds to the container.
func (p *Progress) AddSpinner(total int64, alignment SpinnerAlignment, options ...BarOption) *Bar {
	return p.Add(total, NewSpinnerFiller(alignment), options...)
}

// Add creates a bar which renders itself by provided filler.
// Set total to 0, if you plan to update it later.
func (p *Progress) Add(total int64, filler Filler, options ...BarOption) *Bar {
	if filler == nil {
		filler = NewBarFiller()
	}
	p.bwg.Add(1)
	result := make(chan *Bar)
	select {
	case p.operateState <- func(ps *pState) {
		bs := ps.makeBarState(total, filler, options...)
		bar := newBar(p, bs)
		if bs.runningBar != nil {
			bs.runningBar.noPop = true
			ps.parkedBars[bs.runningBar] = bar
		} else {
			heap.Push(&ps.bHeap, bar)
			ps.heapUpdated = true
		}
		ps.idCount++
		result <- bar
	}:
		bar := <-result
		bar.subscribeDecorators()
		return bar
	case <-p.done:
		p.bwg.Done()
		return nil
	}
}

func (p *Progress) dropBar(b *Bar) {
	select {
	case p.operateState <- func(s *pState) {
		if b.index < 0 {
			return
		}
		heap.Remove(&s.bHeap, b.index)
		s.heapUpdated = true
	}:
	case <-p.done:
	}
}

func (p *Progress) setBarPriority(b *Bar, priority int) {
	select {
	case p.operateState <- func(s *pState) {
		if b.index < 0 {
			return
		}
		b.priority = priority
		heap.Fix(&s.bHeap, b.index)
	}:
	case <-p.done:
	}
}

// UpdateBarPriority same as *Bar.SetPriority.
func (p *Progress) UpdateBarPriority(b *Bar, priority int) {
	p.setBarPriority(b, priority)
}

// BarCount returns bars count
func (p *Progress) BarCount() int {
	result := make(chan int, 1)
	select {
	case p.operateState <- func(s *pState) { result <- s.bHeap.Len() }:
		return <-result
	case <-p.done:
		return 0
	}
}

// Wait waits far all bars to complete and finally shutdowns container.
// After this method has been called, there is no way to reuse *Progress
// instance.
func (p *Progress) Wait() {
	if p.uwg != nil {
		// wait for user wg
		p.uwg.Wait()
	}

	// wait for bars to quit, if any
	p.bwg.Wait()

	p.once.Do(p.shutdown)

	// wait for container to quit
	p.cwg.Wait()
}

func (p *Progress) shutdown() {
	close(p.done)
}

func (p *Progress) serve(s *pState, cw *cwriter.Writer) {
	defer p.cwg.Done()

	manualOrTickCh, cleanUp := s.manualOrTick()
	defer cleanUp()

	refreshCh := fanInRefreshSrc(p.done, p.forceRefresh, manualOrTickCh)

	for {
		select {
		case op := <-p.operateState:
			op(s)
		case _, ok := <-refreshCh:
			if !ok {
				if s.shutdownNotifier != nil {
					close(s.shutdownNotifier)
				}
				return
			}
			if err := s.render(cw); err != nil {
				p.dlogger.Println(err)
			}
		}
	}
}

func (s *pState) render(cw *cwriter.Writer) error {
	if s.heapUpdated {
		s.updateSyncMatrix()
		s.heapUpdated = false
	}
	syncWidth(s.pMatrix)
	syncWidth(s.aMatrix)

	tw, err := cw.GetWidth()
	if err != nil {
		tw = s.width
	}
	for i := 0; i < s.bHeap.Len(); i++ {
		bar := s.bHeap[i]
		go bar.render(tw)
	}

	return s.flush(cw)
}

func (s *pState) flush(cw *cwriter.Writer) error {
	var lineCount int
	bm := make(map[*Bar]struct{}, s.bHeap.Len())
	for s.bHeap.Len() > 0 {
		b := heap.Pop(&s.bHeap).(*Bar)
		cw.ReadFrom(<-b.frameCh)
		if b.toShutdown {
			// shutdown at next flush
			// this ensures no bar ends up with less than 100% rendered
			defer func() {
				s.barShutdownQueue = append(s.barShutdownQueue, b)
				if !b.noPop && s.popCompleted {
					b.priority = -1
				}
			}()
		}
		lineCount += b.extendedLines + 1
		bm[b] = struct{}{}
	}

	for _, b := range s.barShutdownQueue {
		if parkedBar := s.parkedBars[b]; parkedBar != nil {
			parkedBar.priority = b.priority
			heap.Push(&s.bHeap, parkedBar)
			delete(s.parkedBars, b)
			b.toDrop = true
		}
		if b.toDrop {
			delete(bm, b)
			s.heapUpdated = true
		} else if s.popCompleted {
			if b := b; !b.noPop {
				defer func() {
					s.barPopQueue = append(s.barPopQueue, b)
				}()
			}
		}
		b.cancel()
	}
	s.barShutdownQueue = s.barShutdownQueue[0:0]

	for _, b := range s.barPopQueue {
		delete(bm, b)
		s.heapUpdated = true
		lineCount -= b.extendedLines + 1
	}
	s.barPopQueue = s.barPopQueue[0:0]

	for b := range bm {
		heap.Push(&s.bHeap, b)
	}

	return cw.Flush(lineCount)
}

func (s *pState) manualOrTick() (<-chan time.Time, func()) {
	if s.manualRefreshCh != nil {
		return s.manualRefreshCh, func() {}
	}
	ticker := time.NewTicker(s.rr)
	return ticker.C, ticker.Stop
}

func (s *pState) updateSyncMatrix() {
	s.pMatrix = make(map[int][]chan int)
	s.aMatrix = make(map[int][]chan int)
	for i := 0; i < s.bHeap.Len(); i++ {
		bar := s.bHeap[i]
		table := bar.wSyncTable()
		pRow, aRow := table[0], table[1]

		for i, ch := range pRow {
			s.pMatrix[i] = append(s.pMatrix[i], ch)
		}

		for i, ch := range aRow {
			s.aMatrix[i] = append(s.aMatrix[i], ch)
		}
	}
}

func (s *pState) makeBarState(total int64, filler Filler, options ...BarOption) *bState {
	bs := &bState{
		total:    total,
		filler:   filler,
		priority: s.idCount,
		id:       s.idCount,
		width:    s.width,
		debugOut: s.debugOut,
		extender: func(r io.Reader, tw int, st *decor.Statistics) (io.Reader, int) {
			return r, 0
		},
	}

	for _, opt := range options {
		if opt != nil {
			opt(bs)
		}
	}

	bs.bufP = bytes.NewBuffer(make([]byte, 0, bs.width))
	bs.bufB = bytes.NewBuffer(make([]byte, 0, bs.width))
	bs.bufA = bytes.NewBuffer(make([]byte, 0, bs.width))

	return bs
}

func syncWidth(matrix map[int][]chan int) {
	for _, column := range matrix {
		column := column
		go func() {
			var maxWidth int
			for _, ch := range column {
				if w := <-ch; w > maxWidth {
					maxWidth = w
				}
			}
			for _, ch := range column {
				ch <- maxWidth
			}
		}()
	}
}

func fanInRefreshSrc(done <-chan struct{}, channels ...<-chan time.Time) <-chan time.Time {
	var wg sync.WaitGroup
	multiplexedStream := make(chan time.Time)

	multiplex := func(c <-chan time.Time) {
		defer wg.Done()
		// source channels are never closed (time.Ticker never closes associated
		// channel), so we cannot simply range over a c, instead we use select
		// inside infinite loop
		for {
			select {
			case v := <-c:
				select {
				case multiplexedStream <- v:
				case <-done:
					return
				}
			case <-done:
				return
			}
		}
	}

	wg.Add(len(channels))
	for _, c := range channels {
		go multiplex(c)
	}

	go func() {
		wg.Wait()
		close(multiplexedStream)
	}()

	return multiplexedStream
}
<commit_msg>_ unused<commit_after>package mpb

import (
	"bytes"
	"container/heap"
	"context"
	"io"
	"io/ioutil"
	"log"
	"os"
	"sync"
	"time"

	"github.com/vbauerster/mpb/v4/cwriter"
	"github.com/vbauerster/mpb/v4/decor"
)

const (
	// default RefreshRate
	prr = 120 * time.Millisecond
	// default width
	pwidth = 80
)

// Progress represents the container that renders Progress bars
type Progress struct {
	ctx          context.Context
	uwg          *sync.WaitGroup
	cwg          *sync.WaitGroup
	bwg          *sync.WaitGroup
	operateState chan func(*pState)
	done         chan struct{}
	forceRefresh chan time.Time
	once         sync.Once
	dlogger      *log.Logger
}

type pState struct {
	bHeap            priorityQueue
	heapUpdated      bool
	pMatrix          map[int][]chan int
	aMatrix          map[int][]chan int
	barShutdownQueue []*Bar
	barPopQueue      []*Bar

	// following are provided/overrided by user
	idCount          int
	width            int
	popCompleted     bool
	rr               time.Duration
	uwg              *sync.WaitGroup
	manualRefreshCh  <-chan time.Time
	shutdownNotifier chan struct{}
	parkedBars       map[*Bar]*Bar
	output           io.Writer
	debugOut         io.Writer
}

// New creates new Progress container instance. It's not possible to
// reuse instance after *Progress.Wait() method has been called.
func New(options ...ContainerOption) *Progress {
	return NewWithContext(context.Background(), options...)
}

// NewWithContext creates new Progress container instance with provided
// context. It's not possible to reuse instance after *Progress.Wait()
// method has been called.
func NewWithContext(ctx context.Context, options ...ContainerOption) *Progress {
	s := &pState{
		bHeap:      priorityQueue{},
		width:      pwidth,
		rr:         prr,
		parkedBars: make(map[*Bar]*Bar),
		output:     os.Stdout,
		debugOut:   ioutil.Discard,
	}

	for _, opt := range options {
		if opt != nil {
			opt(s)
		}
	}

	p := &Progress{
		ctx:          ctx,
		uwg:          s.uwg,
		cwg:          new(sync.WaitGroup),
		bwg:          new(sync.WaitGroup),
		operateState: make(chan func(*pState)),
		forceRefresh: make(chan time.Time),
		done:         make(chan struct{}),
		dlogger:      log.New(s.debugOut, "[mpb] ", log.Lshortfile),
	}

	p.cwg.Add(1)
	go p.serve(s, cwriter.New(s.output))
	return p
}

// AddBar creates a new progress bar and adds to the container.
func (p *Progress) AddBar(total int64, options ...BarOption) *Bar {
	return p.Add(total, NewBarFiller(), options...)
}

// AddSpinner creates a new spinner bar and adds to the container.
func (p *Progress) AddSpinner(total int64, alignment SpinnerAlignment, options ...BarOption) *Bar {
	return p.Add(total, NewSpinnerFiller(alignment), options...)
}

// Add creates a bar which renders itself by provided filler.
// Set total to 0, if you plan to update it later.
func (p *Progress) Add(total int64, filler Filler, options ...BarOption) *Bar {
	if filler == nil {
		filler = NewBarFiller()
	}
	p.bwg.Add(1)
	result := make(chan *Bar)
	select {
	case p.operateState <- func(ps *pState) {
		bs := ps.makeBarState(total, filler, options...)
		bar := newBar(p, bs)
		if bs.runningBar != nil {
			bs.runningBar.noPop = true
			ps.parkedBars[bs.runningBar] = bar
		} else {
			heap.Push(&ps.bHeap, bar)
			ps.heapUpdated = true
		}
		ps.idCount++
		result <- bar
	}:
		bar := <-result
		bar.subscribeDecorators()
		return bar
	case <-p.done:
		p.bwg.Done()
		return nil
	}
}

func (p *Progress) dropBar(b *Bar) {
	select {
	case p.operateState <- func(s *pState) {
		if b.index < 0 {
			return
		}
		heap.Remove(&s.bHeap, b.index)
		s.heapUpdated = true
	}:
	case <-p.done:
	}
}

func (p *Progress) setBarPriority(b *Bar, priority int) {
	select {
	case p.operateState <- func(s *pState) {
		if b.index < 0 {
			return
		}
		b.priority = priority
		heap.Fix(&s.bHeap, b.index)
	}:
	case <-p.done:
	}
}

// UpdateBarPriority same as *Bar.SetPriority.
func (p *Progress) UpdateBarPriority(b *Bar, priority int) {
	p.setBarPriority(b, priority)
}

// BarCount returns bars count
func (p *Progress) BarCount() int {
	result := make(chan int, 1)
	select {
	case p.operateState <- func(s *pState) { result <- s.bHeap.Len() }:
		return <-result
	case <-p.done:
		return 0
	}
}

// Wait waits far all bars to complete and finally shutdowns container.
// After this method has been called, there is no way to reuse *Progress
// instance.
func (p *Progress) Wait() {
	if p.uwg != nil {
		// wait for user wg
		p.uwg.Wait()
	}

	// wait for bars to quit, if any
	p.bwg.Wait()

	p.once.Do(p.shutdown)

	// wait for container to quit
	p.cwg.Wait()
}

func (p *Progress) shutdown() {
	close(p.done)
}

func (p *Progress) serve(s *pState, cw *cwriter.Writer) {
	defer p.cwg.Done()

	manualOrTickCh, cleanUp := s.manualOrTick()
	defer cleanUp()

	refreshCh := fanInRefreshSrc(p.done, p.forceRefresh, manualOrTickCh)

	for {
		select {
		case op := <-p.operateState:
			op(s)
		case _, ok := <-refreshCh:
			if !ok {
				if s.shutdownNotifier != nil {
					close(s.shutdownNotifier)
				}
				return
			}
			if err := s.render(cw); err != nil {
				p.dlogger.Println(err)
			}
		}
	}
}

func (s *pState) render(cw *cwriter.Writer) error {
	if s.heapUpdated {
		s.updateSyncMatrix()
		s.heapUpdated = false
	}
	syncWidth(s.pMatrix)
	syncWidth(s.aMatrix)

	tw, err := cw.GetWidth()
	if err != nil {
		tw = s.width
	}
	for i := 0; i < s.bHeap.Len(); i++ {
		bar := s.bHeap[i]
		go bar.render(tw)
	}

	return s.flush(cw)
}

func (s *pState) flush(cw *cwriter.Writer) error {
	var lineCount int
	bm := make(map[*Bar]struct{}, s.bHeap.Len())
	for s.bHeap.Len() > 0 {
		b := heap.Pop(&s.bHeap).(*Bar)
		cw.ReadFrom(<-b.frameCh)
		if b.toShutdown {
			// shutdown at next flush
			// this ensures no bar ends up with less than 100% rendered
			defer func() {
				s.barShutdownQueue = append(s.barShutdownQueue, b)
				if !b.noPop && s.popCompleted {
					b.priority = -1
				}
			}()
		}
		lineCount += b.extendedLines + 1
		bm[b] = struct{}{}
	}

	for _, b := range s.barShutdownQueue {
		if parkedBar := s.parkedBars[b]; parkedBar != nil {
			parkedBar.priority = b.priority
			heap.Push(&s.bHeap, parkedBar)
			delete(s.parkedBars, b)
			b.toDrop = true
		}
		if b.toDrop {
			delete(bm, b)
			s.heapUpdated = true
		} else if s.popCompleted {
			if b := b; !b.noPop {
				defer func() {
					s.barPopQueue = append(s.barPopQueue, b)
				}()
			}
		}
		b.cancel()
	}
	s.barShutdownQueue = s.barShutdownQueue[0:0]

	for _, b := range s.barPopQueue {
		delete(bm, b)
		s.heapUpdated = true
		lineCount -= b.extendedLines + 1
	}
	s.barPopQueue = s.barPopQueue[0:0]

	for b := range bm {
		heap.Push(&s.bHeap, b)
	}

	return cw.Flush(lineCount)
}

func (s *pState) manualOrTick() (<-chan time.Time, func()) {
	if s.manualRefreshCh != nil {
		return s.manualRefreshCh, func() {}
	}
	ticker := time.NewTicker(s.rr)
	return ticker.C, ticker.Stop
}

func (s *pState) updateSyncMatrix() {
	s.pMatrix = make(map[int][]chan int)
	s.aMatrix = make(map[int][]chan int)
	for i := 0; i < s.bHeap.Len(); i++ {
		bar := s.bHeap[i]
		table := bar.wSyncTable()
		pRow, aRow := table[0], table[1]

		for i, ch := range pRow {
			s.pMatrix[i] = append(s.pMatrix[i], ch)
		}

		for i, ch := range aRow {
			s.aMatrix[i] = append(s.aMatrix[i], ch)
		}
	}
}

func (s *pState) makeBarState(total int64, filler Filler, options ...BarOption) *bState {
	bs := &bState{
		total:    total,
		filler:   filler,
		priority: s.idCount,
		id:       s.idCount,
		width:    s.width,
		debugOut: s.debugOut,
		extender: func(r io.Reader, _ int, _ *decor.Statistics) (io.Reader, int) {
			return r, 0
		},
	}

	for _, opt := range options {
		if opt != nil {
			opt(bs)
		}
	}

	bs.bufP = bytes.NewBuffer(make([]byte, 0, bs.width))
	bs.bufB = bytes.NewBuffer(make([]byte, 0, bs.width))
	bs.bufA = bytes.NewBuffer(make([]byte, 0, bs.width))

	return bs
}

func syncWidth(matrix map[int][]chan int) {
	for _, column := range matrix {
		column := column
		go func() {
			var maxWidth int
			for _, ch := range column {
				if w := <-ch; w > maxWidth {
					maxWidth = w
				}
			}
			for _, ch := range column {
				ch <- maxWidth
			}
		}()
	}
}

func fanInRefreshSrc(done <-chan struct{}, channels ...<-chan time.Time) <-chan time.Time {
	var wg sync.WaitGroup
	multiplexedStream := make(chan time.Time)

	multiplex := func(c <-chan time.Time) {
		defer wg.Done()
		// source channels are never closed (time.Ticker never closes associated
		// channel), so we cannot simply range over a c, instead we use select
		// inside infinite loop
		for {
			select {
			case v := <-c:
				select {
				case multiplexedStream <- v:
				case <-done:
					return
				}
			case <-done:
				return
			}
		}
	}

	wg.Add(len(channels))
	for _, c := range channels {
		go multiplex(c)
	}

	go func() {
		wg.Wait()
		close(multiplexedStream)
	}()

	return multiplexedStream
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/HearthSim/stove/bnet"
	"github.com/HearthSim/stove/pegasus"
	"github.com/jinzhu/gorm"
	_ "github.com/mattn/go-sqlite3"
	"os"
	"strings"
)

const (
	CONN_DEFAULT_HOST = "localhost"
	CONN_DEFAULT_PORT = 1119
)

func migrate() {
	conn, err := gorm.Open("sqlite3", "db/pegasus.db")
	if err != nil {
		panic(err)
	}

	conn.LogMode(true)
	conn.SingularTable(true)
	conn.AutoMigrate(
		&pegasus.Account{},
		&pegasus.AccountLicense{},
		&pegasus.Achieve{},
		&pegasus.Booster{},
		&pegasus.BoosterCard{},
		&pegasus.FavoriteHero{},
		&pegasus.Deck{},
		&pegasus.DeckCard{},
		&pegasus.License{},
		&pegasus.SeasonProgress{},
		&pegasus.Bundle{},
		&pegasus.ProductGoldCost{},
		&pegasus.Product{},
	)

	conn.Close()
}

func main() {
	addr := fmt.Sprintf("%s:%d", CONN_DEFAULT_HOST, CONN_DEFAULT_PORT)
	flag.StringVar(&addr, "bind", addr, "The address to run on")
	runMigrate := flag.Bool("migrate", false, "Perform a database migration and exit")
	flag.Parse()

	if !strings.Contains(addr, ":") {
		addr = fmt.Sprintf("%s:%d", addr, CONN_DEFAULT_PORT)
	}

	if *runMigrate {
		fmt.Printf("Performing database migration\n")
		migrate()
		os.Exit(0)
	}

	serv := bnet.NewServer()
	serv.RegisterGameServer("WTCG", pegasus.NewServer(serv))

	fmt.Printf("Listening on %s ...\n", addr)
	err := serv.ListenAndServe(addr)
	if err != nil {
		fmt.Println(err)
	}
}
<commit_msg>Panic if errors happened during automigration<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/HearthSim/stove/bnet"
	"github.com/HearthSim/stove/pegasus"
	"github.com/jinzhu/gorm"
	_ "github.com/mattn/go-sqlite3"
	"os"
	"strings"
)

const (
	CONN_DEFAULT_HOST = "localhost"
	CONN_DEFAULT_PORT = 1119
)

func migrate() {
	conn, err := gorm.Open("sqlite3", "db/pegasus.db")
	if err != nil {
		panic(err)
	}

	conn.LogMode(true)
	conn.SingularTable(true)
	err = conn.AutoMigrate(
		&pegasus.Account{},
		&pegasus.AccountLicense{},
		&pegasus.Achieve{},
		&pegasus.Booster{},
		&pegasus.BoosterCard{},
		&pegasus.FavoriteHero{},
		&pegasus.Deck{},
		&pegasus.DeckCard{},
		&pegasus.License{},
		&pegasus.SeasonProgress{},
		&pegasus.Bundle{},
		&pegasus.ProductGoldCost{},
		&pegasus.Product{},
	).Error

	conn.Close()

	if err != nil {
		panic(err)
	}
}

func main() {
	addr := fmt.Sprintf("%s:%d", CONN_DEFAULT_HOST, CONN_DEFAULT_PORT)
	flag.StringVar(&addr, "bind", addr, "The address to run on")
	runMigrate := flag.Bool("migrate", false, "Perform a database migration and exit")
	flag.Parse()

	if !strings.Contains(addr, ":") {
		addr = fmt.Sprintf("%s:%d", addr, CONN_DEFAULT_PORT)
	}

	if *runMigrate {
		fmt.Printf("Performing database migration\n")
		migrate()
		os.Exit(0)
	}

	serv := bnet.NewServer()
	serv.RegisterGameServer("WTCG", pegasus.NewServer(serv))

	fmt.Printf("Listening on %s ...\n", addr)
	err := serv.ListenAndServe(addr)
	if err != nil {
		fmt.Println(err)
	}
}
<|endoftext|>


<commit_before>// svctl
// Copyright (C) 2015 Karol 'Kenji Takahashi' Woźniak
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

// svctl is an interactive runit controller.
package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"os"
	"path"
	"path/filepath"
	"sort"
	"strings"
	"sync"
	"time"

	"github.com/adrg/xdg"
	"github.com/peterh/liner"
)

// status Represents current status of a single process.
// Note that it gathers all information during construction,
// so it is generally meant to be short lived.
type status struct {
	name string
	err  error

	Offsets []int

	sv       []byte
	svStatus string
	svPid    uint
	svTime   uint64
}

// newStatus Creates new status representation for given directory and name.
func newStatus(dir, name string) *status {
	s := &status{Offsets: make([]int, 2), name: name}
	s.Offsets[0] = len(s.name)

	status, err := s.status(dir)
	if err != nil {
		s.err = err

		s.Offsets[1] = len("ERROR")
	} else {
		s.svPid = svPid(status)
		s.svStatus = svStatus(status, s.svPid)
		s.svTime = svTime(status)

		s.Offsets[1] = len(s.svStatus)
		if s.svStatus == "RUNNING" {
			s.Offsets[1] += len(fmt.Sprintf(" (pid %d)", s.svPid))
		}
	}
	s.sv = status

	return s
}

// status Reads current status from specified dir.
func (s *status) status(dir string) ([]byte, error) {
	if _, err := os.OpenFile(path.Join(dir, "supervise/ok"), os.O_WRONLY, 0600); err != nil {
		return nil, fmt.Errorf("unable to open supervise/ok")
	}

	fstatus, err := os.Open(path.Join(dir, "supervise/status"))
	if err != nil {
		return nil, fmt.Errorf("unable to open supervise/status")
	}

	b := make([]byte, 20)
	_, err = io.ReadFull(fstatus, b)
	fstatus.Close()
	if err != nil {
		if err == io.ErrUnexpectedEOF {
			return nil, fmt.Errorf("unable to read supervise/status: wrong format")
		}
		return nil, fmt.Errorf("unable to read supervise/status")
	}
	return b, nil
}

// Check Performs svCheck on status, if retrieved successfully.
func (s *status) Check(action []byte, start uint64) bool {
	if s.err != nil {
		return true
	}
	return svCheck(action, s.sv, start)
}

// CheckControl Performs svCheckControl on status.
func (s *status) CheckControl(action []byte) bool {
	return svCheckControl(action, s.sv)
}

// String Returns nicely stringified version of the status.
//
// s.Offsets can be set from the outside to make indentation uniform
// among multiple statuses.
func (s *status) String() string {
	var status bytes.Buffer
	fmt.Fprintf(&status, "%-[1]*s", s.Offsets[0]+3, s.name)
	if s.err != nil {
		fmt.Fprintf(&status, "%-[1]*s%s", s.Offsets[1]+3, "ERROR", s.err)
		return status.String()
	}
	fmt.Fprintf(&status, s.svStatus)
	if s.svStatus == "RUNNING" {
		fmt.Fprintf(&status, " (pid %d)", s.svPid)
	}
	fmt.Fprintf(
		&status, "%-[1]*s%ds",
		s.Offsets[1]+3-status.Len()+s.Offsets[0]+3, "", svNow()-s.svTime,
	)
	return status.String()
}

// Errored Returns whether status retrieval ended with error or not.
func (s *status) Errored() bool {
	return s.err != nil
}

// ctl Represents main svctl entry point.
type ctl struct {
	line    *liner.State
	basedir string
	stdout  io.Writer
}

// newCtl Creates new ctl instance.
// Initializes input prompt, reads history, reads $SVDIR.
func newCtl(stdout io.Writer) *ctl {
	c := &ctl{line: liner.NewLiner(), stdout: stdout}

	fn, _ := xdg.DataFile("svctl/hist")
	if f, err := os.Open(fn); err == nil {
		c.line.ReadHistory(f)
		f.Close()
	}
	c.basedir = os.Getenv("SVDIR")
	if c.basedir == "" {
		c.basedir = "/service"
	}

	c.line.SetTabCompletionStyle(liner.TabPrints)
	c.line.SetWordCompleter(c.completer)

	return c
}

// Close Closes input prompt, saves history to file.
func (c *ctl) Close() {
	fn, _ := xdg.DataFile("svctl/hist")
	f, err := os.Create(fn)
	if err != nil {
		log.Printf("error opening history file: %s\n", err)
		return
	}
	if n, err := c.line.WriteHistory(f); err != nil {
		log.Printf("error writing history file: %s, lines written: %d\n", err, n)
	}
	c.line.Close()
}

func (c *ctl) completer(line string, pos int) (h string, compl []string, t string) {
	s := strings.Split(line, " ")
	if len(s) == 1 {
		return "", cmdMatchName(line), ""
	}
	i := strings.Count(line[:pos], " ")

	if s[0] == "?" || s[0] == "help" {
		compl = cmdMatchName(s[i])
	} else {
		services := c.Services(fmt.Sprintf("%s*", s[i]), true)

		compl = make([]string, len(services))
		for i, service := range services {
			compl[i] = fmt.Sprintf("%s ", c.serviceName(service))
		}
	}
	h = fmt.Sprintf("%s ", strings.Join(s[:i], " "))
	t = strings.Join(s[i+1:], " ")
	if t != "" {
		t = fmt.Sprintf(" %s", t)
	}
	return
}

func (c *ctl) printf(format string, a ...interface{}) {
	fmt.Fprintf(c.stdout, format, a...)
}

func (c *ctl) println(a ...interface{}) {
	fmt.Fprintln(c.stdout, a...)
}

// serviceName Returns name of the service, i.e. directory chain relative to current base.
func (c *ctl) serviceName(dir string) string {
	if name, err := filepath.Rel(c.basedir, dir); err == nil {
		return name
	}
	return dir
}

// Services Returns paths to all services matching pattern.
func (c *ctl) Services(pattern string, toLog bool) []string {
	if len(pattern) < len(c.basedir) || pattern[:len(c.basedir)] != c.basedir {
		pattern = path.Join(c.basedir, pattern)
	}
	files, err := filepath.Glob(pattern)
	if err != nil {
		log.Printf("error getting services list: %s\n", err)
	}
	if toLog {
		logs, err := filepath.Glob(path.Join(pattern, "log"))
		if err != nil {
			log.Printf("error getting logs list: %s\n", err)
		} else {
			files = append(files, logs...)
			sort.Strings(files)
		}
	}

	dirs := []string{}
	for _, file := range files {
		if fi, err := os.Stat(file); err == nil && fi.IsDir() {
			dirs = append(dirs, file)
		}
	}
	return dirs
}

// Status Prints all statuses matching id and optionally their log process statuses.
func (c *ctl) Status(id string, toLog bool) {
	// TODO: normally (up|down) and stuff?
	services := c.Services(id, toLog)
	statuses := make([]*status, len(services))
	for i, dir := range services {
		status := newStatus(dir, c.serviceName(dir))
		statuses[i] = status

		for i, offset := range status.Offsets {
			if statuses[0].Offsets[i] < offset {
				statuses[0].Offsets[i] = offset
			}
		}
	}
	for _, status := range statuses {
		status.Offsets = statuses[0].Offsets
		c.println(status)
	}
}

// control Sends action byte to service.
func (c *ctl) control(action []byte, service string) error {
	f, err := os.OpenFile(
		path.Join(service, "supervise/control"), os.O_WRONLY, 0600,
	)
	if err != nil {
		return fmt.Errorf("%s: unable to open supervise/control", path.Base(service))
	}
	defer f.Close()
	if _, err := f.Write(action); err != nil {
		return fmt.Errorf("%s: unable to write to supervise/control", path.Base(service))
	}
	return nil
}

// ctl Delegates a single action for single service.
func (c *ctl) ctl(action []byte, service string, start uint64, wg *sync.WaitGroup) {
	defer wg.Done()

	status := newStatus(service, c.serviceName(service))
	if status.Errored() {
		c.println(status)
		return
	}
	if status.CheckControl(action) {
		if err := c.control(action, service); err != nil {
			c.println(err)
			return
		}
	}

	timeout := time.After(7 * time.Second)
	tick := time.Tick(100 * time.Millisecond)
	for {
		select {
		case <-timeout:
			c.printf("TIMEOUT: ")
			c.Status(service, false)
			return
		case <-tick:
			status := newStatus(service, c.serviceName(service))
			if status.Check(action, start) {
				c.println(status)
				return
			}
		}
	}
}

// Ctl Handles command supplied by user.
//
// Depending on the command, it might just exit, print help or propagate
// command to cmds to delegate action to runsv.
//
// If more than one service was specified with the command,
// actions are delegated asynchronically.
func (c *ctl) Ctl(cmdStr string) bool {
	c.line.AppendHistory(cmdStr)
	start := svNow()
	params := strings.Split(strings.TrimSpace(cmdStr), " ")

	cmd := cmdMatch(params[0])
	if ctlCmd, ok := cmd.(ctlCmd); ok {
		return ctlCmd.Run(c, params)
	}
	if cmd == nil {
		c.printf("%s: unable to find action\n", params[0])
		return false
	}
	action := cmd.Action()

	if len(params) == 1 {
		params = append(params, "*")
	}
	var wg sync.WaitGroup
	for _, param := range params[1:] {
		if param == "" {
			continue
		}
		services := c.Services(param, false)
		if len(services) == 0 {
			c.printf("%s: unable to find service\n", param)
			continue
		}
		wg.Add(len(services))
		for _, service := range services {
			go c.ctl(action, service, start, &wg)
		}
	}
	wg.Wait()

	return false
}

// Run Performs one tick of a input prompt event loop.
// If this function returns true, the outside loop should terminate.
func (c *ctl) Run() bool {
	cmd, err := c.line.Prompt("svctl> ")
	if err == io.EOF {
		c.println()
		return true
	} else if err != nil {
		log.Printf("error reading prompt contents: %s\n", err)
		return false
	}
	return c.Ctl(cmd)
}

// main Creates svctl entry point, prints all processes statuses and launches event loop.
func main() {
	ctl := newCtl(os.Stdout)
	defer ctl.Close()
	ctl.Status("*", true)
	for !ctl.Run() {
	}
}
<commit_msg>close history file after writing<commit_after>// svctl
// Copyright (C) 2015 Karol 'Kenji Takahashi' Woźniak
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

// svctl is an interactive runit controller.
package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"os"
	"path"
	"path/filepath"
	"sort"
	"strings"
	"sync"
	"time"

	"github.com/adrg/xdg"
	"github.com/peterh/liner"
)

// status Represents current status of a single process.
// Note that it gathers all information during construction,
// so it is generally meant to be short lived.
type status struct {
	name string
	err  error

	Offsets []int

	sv       []byte
	svStatus string
	svPid    uint
	svTime   uint64
}

// newStatus Creates new status representation for given directory and name.
func newStatus(dir, name string) *status {
	s := &status{Offsets: make([]int, 2), name: name}
	s.Offsets[0] = len(s.name)

	status, err := s.status(dir)
	if err != nil {
		s.err = err

		s.Offsets[1] = len("ERROR")
	} else {
		s.svPid = svPid(status)
		s.svStatus = svStatus(status, s.svPid)
		s.svTime = svTime(status)

		s.Offsets[1] = len(s.svStatus)
		if s.svStatus == "RUNNING" {
			s.Offsets[1] += len(fmt.Sprintf(" (pid %d)", s.svPid))
		}
	}
	s.sv = status

	return s
}

// status Reads current status from specified dir.
func (s *status) status(dir string) ([]byte, error) {
	if _, err := os.OpenFile(path.Join(dir, "supervise/ok"), os.O_WRONLY, 0600); err != nil {
		return nil, fmt.Errorf("unable to open supervise/ok")
	}

	fstatus, err := os.Open(path.Join(dir, "supervise/status"))
	if err != nil {
		return nil, fmt.Errorf("unable to open supervise/status")
	}

	b := make([]byte, 20)
	_, err = io.ReadFull(fstatus, b)
	fstatus.Close()
	if err != nil {
		if err == io.ErrUnexpectedEOF {
			return nil, fmt.Errorf("unable to read supervise/status: wrong format")
		}
		return nil, fmt.Errorf("unable to read supervise/status")
	}
	return b, nil
}

// Check Performs svCheck on status, if retrieved successfully.
func (s *status) Check(action []byte, start uint64) bool {
	if s.err != nil {
		return true
	}
	return svCheck(action, s.sv, start)
}

// CheckControl Performs svCheckControl on status.
func (s *status) CheckControl(action []byte) bool {
	return svCheckControl(action, s.sv)
}

// String Returns nicely stringified version of the status.
//
// s.Offsets can be set from the outside to make indentation uniform
// among multiple statuses.
func (s *status) String() string {
	var status bytes.Buffer
	fmt.Fprintf(&status, "%-[1]*s", s.Offsets[0]+3, s.name)
	if s.err != nil {
		fmt.Fprintf(&status, "%-[1]*s%s", s.Offsets[1]+3, "ERROR", s.err)
		return status.String()
	}
	fmt.Fprintf(&status, s.svStatus)
	if s.svStatus == "RUNNING" {
		fmt.Fprintf(&status, " (pid %d)", s.svPid)
	}
	fmt.Fprintf(
		&status, "%-[1]*s%ds",
		s.Offsets[1]+3-status.Len()+s.Offsets[0]+3, "", svNow()-s.svTime,
	)
	return status.String()
}

// Errored Returns whether status retrieval ended with error or not.
func (s *status) Errored() bool {
	return s.err != nil
}

// ctl Represents main svctl entry point.
type ctl struct {
	line    *liner.State
	basedir string
	stdout  io.Writer
}

// newCtl Creates new ctl instance.
// Initializes input prompt, reads history, reads $SVDIR.
func newCtl(stdout io.Writer) *ctl {
	c := &ctl{line: liner.NewLiner(), stdout: stdout}

	fn, _ := xdg.DataFile("svctl/hist")
	if f, err := os.Open(fn); err == nil {
		c.line.ReadHistory(f)
		f.Close()
	}
	c.basedir = os.Getenv("SVDIR")
	if c.basedir == "" {
		c.basedir = "/service"
	}

	c.line.SetTabCompletionStyle(liner.TabPrints)
	c.line.SetWordCompleter(c.completer)

	return c
}

// Close Closes input prompt, saves history to file.
func (c *ctl) Close() {
	fn, _ := xdg.DataFile("svctl/hist")
	f, err := os.Create(fn)
	if err != nil {
		log.Printf("error opening history file: %s\n", err)
		return
	}
	if n, err := c.line.WriteHistory(f); err != nil {
		log.Printf("error writing history file: %s, lines written: %d\n", err, n)
	}
	c.line.Close()
	f.Close()
}

func (c *ctl) completer(line string, pos int) (h string, compl []string, t string) {
	s := strings.Split(line, " ")
	if len(s) == 1 {
		return "", cmdMatchName(line), ""
	}
	i := strings.Count(line[:pos], " ")

	if s[0] == "?" || s[0] == "help" {
		compl = cmdMatchName(s[i])
	} else {
		services := c.Services(fmt.Sprintf("%s*", s[i]), true)

		compl = make([]string, len(services))
		for i, service := range services {
			compl[i] = fmt.Sprintf("%s ", c.serviceName(service))
		}
	}
	h = fmt.Sprintf("%s ", strings.Join(s[:i], " "))
	t = strings.Join(s[i+1:], " ")
	if t != "" {
		t = fmt.Sprintf(" %s", t)
	}
	return
}

func (c *ctl) printf(format string, a ...interface{}) {
	fmt.Fprintf(c.stdout, format, a...)
}

func (c *ctl) println(a ...interface{}) {
	fmt.Fprintln(c.stdout, a...)
}

// serviceName Returns name of the service, i.e. directory chain relative to current base.
func (c *ctl) serviceName(dir string) string {
	if name, err := filepath.Rel(c.basedir, dir); err == nil {
		return name
	}
	return dir
}

// Services Returns paths to all services matching pattern.
func (c *ctl) Services(pattern string, toLog bool) []string {
	if len(pattern) < len(c.basedir) || pattern[:len(c.basedir)] != c.basedir {
		pattern = path.Join(c.basedir, pattern)
	}
	files, err := filepath.Glob(pattern)
	if err != nil {
		log.Printf("error getting services list: %s\n", err)
	}
	if toLog {
		logs, err := filepath.Glob(path.Join(pattern, "log"))
		if err != nil {
			log.Printf("error getting logs list: %s\n", err)
		} else {
			files = append(files, logs...)
			sort.Strings(files)
		}
	}

	dirs := []string{}
	for _, file := range files {
		if fi, err := os.Stat(file); err == nil && fi.IsDir() {
			dirs = append(dirs, file)
		}
	}
	return dirs
}

// Status Prints all statuses matching id and optionally their log process statuses.
func (c *ctl) Status(id string, toLog bool) {
	// TODO: normally (up|down) and stuff?
	services := c.Services(id, toLog)
	statuses := make([]*status, len(services))
	for i, dir := range services {
		status := newStatus(dir, c.serviceName(dir))
		statuses[i] = status

		for i, offset := range status.Offsets {
			if statuses[0].Offsets[i] < offset {
				statuses[0].Offsets[i] = offset
			}
		}
	}
	for _, status := range statuses {
		status.Offsets = statuses[0].Offsets
		c.println(status)
	}
}

// control Sends action byte to service.
func (c *ctl) control(action []byte, service string) error {
	f, err := os.OpenFile(
		path.Join(service, "supervise/control"), os.O_WRONLY, 0600,
	)
	if err != nil {
		return fmt.Errorf("%s: unable to open supervise/control", path.Base(service))
	}
	defer f.Close()
	if _, err := f.Write(action); err != nil {
		return fmt.Errorf("%s: unable to write to supervise/control", path.Base(service))
	}
	return nil
}

// ctl Delegates a single action for single service.
func (c *ctl) ctl(action []byte, service string, start uint64, wg *sync.WaitGroup) {
	defer wg.Done()

	status := newStatus(service, c.serviceName(service))
	if status.Errored() {
		c.println(status)
		return
	}
	if status.CheckControl(action) {
		if err := c.control(action, service); err != nil {
			c.println(err)
			return
		}
	}

	timeout := time.After(7 * time.Second)
	tick := time.Tick(100 * time.Millisecond)
	for {
		select {
		case <-timeout:
			c.printf("TIMEOUT: ")
			c.Status(service, false)
			return
		case <-tick:
			status := newStatus(service, c.serviceName(service))
			if status.Check(action, start) {
				c.println(status)
				return
			}
		}
	}
}

// Ctl Handles command supplied by user.
//
// Depending on the command, it might just exit, print help or propagate
// command to cmds to delegate action to runsv.
//
// If more than one service was specified with the command,
// actions are delegated asynchronically.
func (c *ctl) Ctl(cmdStr string) bool {
	c.line.AppendHistory(cmdStr)
	start := svNow()
	params := strings.Split(strings.TrimSpace(cmdStr), " ")

	cmd := cmdMatch(params[0])
	if ctlCmd, ok := cmd.(ctlCmd); ok {
		return ctlCmd.Run(c, params)
	}
	if cmd == nil {
		c.printf("%s: unable to find action\n", params[0])
		return false
	}
	action := cmd.Action()

	if len(params) == 1 {
		params = append(params, "*")
	}
	var wg sync.WaitGroup
	for _, param := range params[1:] {
		if param == "" {
			continue
		}
		services := c.Services(param, false)
		if len(services) == 0 {
			c.printf("%s: unable to find service\n", param)
			continue
		}
		wg.Add(len(services))
		for _, service := range services {
			go c.ctl(action, service, start, &wg)
		}
	}
	wg.Wait()

	return false
}

// Run Performs one tick of a input prompt event loop.
// If this function returns true, the outside loop should terminate.
func (c *ctl) Run() bool {
	cmd, err := c.line.Prompt("svctl> ")
	if err == io.EOF {
		c.println()
		return true
	} else if err != nil {
		log.Printf("error reading prompt contents: %s\n", err)
		return false
	}
	return c.Ctl(cmd)
}

// main Creates svctl entry point, prints all processes statuses and launches event loop.
func main() {
	ctl := newCtl(os.Stdout)
	defer ctl.Close()
	ctl.Status("*", true)
	for !ctl.Run() {
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"math/rand"

	"github.com/chrislusf/seaweedfs/weed/operation"
	"github.com/chrislusf/seaweedfs/weed/security"
	"github.com/chrislusf/seaweedfs/weed/util"
)

var (
	master = flag.String("master", "127.0.0.1:9333", "the master server")
	repeat = flag.Int("n", 5, "repeat how many times")
)

func main() {
	flag.Parse()

	util.LoadConfiguration("security", false)
	grpcDialOption := security.LoadClientTLS(util.GetViper(), "grpc.client")

	for i := 0; i < *repeat; i++ {
		assignResult, err := operation.Assign(*master, grpcDialOption, &operation.VolumeAssignRequest{Count: 1})
		if err != nil {
			log.Fatalf("assign: %v", err)
		}

		data := make([]byte, 1024)
		rand.Read(data)

		targetUrl := fmt.Sprintf("http://%s/%s", assignResult.Url, assignResult.Fid)

		_, err = operation.UploadData(targetUrl, fmt.Sprintf("test%d", i), false, data, false, "bench/test", nil, assignResult.Auth)
		if err != nil {
			log.Fatalf("upload: %v", err)
		}

		util.Delete(targetUrl, string(assignResult.Auth))

		util.Get(fmt.Sprintf("http://%s/vol/vacuum", *master))

	}

}
<commit_msg>vacuum benchmarking<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"math/rand"

	"google.golang.org/grpc"

	"github.com/chrislusf/seaweedfs/weed/operation"
	"github.com/chrislusf/seaweedfs/weed/security"
	"github.com/chrislusf/seaweedfs/weed/util"
)

var (
	master           = flag.String("master", "127.0.0.1:9333", "the master server")
	repeat           = flag.Int("n", 5, "repeat how many times")
	garbageThreshold = flag.Float64("garbageThreshold", 0.3, "garbageThreshold")
)

func main() {
	flag.Parse()

	util.LoadConfiguration("security", false)
	grpcDialOption := security.LoadClientTLS(util.GetViper(), "grpc.client")

	genFile(grpcDialOption, 0)

	for i := 0; i < *repeat; i++ {
		// create 2 files, and delete one of them

		assignResult, targetUrl := genFile(grpcDialOption, i)

		util.Delete(targetUrl, string(assignResult.Auth))

		println("vacuum", i, "threshold", *garbageThreshold)
		util.Get(fmt.Sprintf("http://%s/vol/vacuum?garbageThreshold=%f", *master, *garbageThreshold))

	}

}

func genFile(grpcDialOption grpc.DialOption, i int) (*operation.AssignResult, string) {
	assignResult, err := operation.Assign(*master, grpcDialOption, &operation.VolumeAssignRequest{Count: 1})
	if err != nil {
		log.Fatalf("assign: %v", err)
	}

	data := make([]byte, 1024)
	rand.Read(data)

	targetUrl := fmt.Sprintf("http://%s/%s", assignResult.Url, assignResult.Fid)

	_, err = operation.UploadData(targetUrl, fmt.Sprintf("test%d", i), false, data, false, "bench/test", nil, assignResult.Auth)
	if err != nil {
		log.Fatalf("upload: %v", err)
	}
	return assignResult, targetUrl
}
<|endoftext|>


<commit_before>package tavor

const (
	Version = "0.1"
)

//TODO remove this
var DEBUG = false
<commit_msg>helper function PrettyPrintTree<commit_after>package tavor

import (
	"fmt"
	"io"
	"strings"

	"github.com/zimmski/tavor/token"
	"github.com/zimmski/tavor/token/lists"
)

const (
	Version = "0.1"
)

//TODO remove this
var DEBUG = false

func PrettyPrintTree(w io.Writer, root token.Token) {
	prettyPrintTreeRek(w, root, 0)
}

func prettyPrintTreeRek(w io.Writer, tok token.Token, level int) {
	fmt.Fprintf(w, "%s(%p)%#v\n", strings.Repeat("\t", level), tok, tok)

	switch t := tok.(type) {
	case token.ForwardToken:
		if v := t.Get(); v != nil {
			prettyPrintTreeRek(w, v, level+1)
		}
	case lists.List:
		for i := 0; i < t.Len(); i++ {
			c, _ := t.Get(i)

			prettyPrintTreeRek(w, c, level+1)
		}
	}
}
<|endoftext|>