<commit_before>package common

import (
	"errors"
	"github.com/couchbase/indexing/secondary/dcp"
	"github.com/couchbase/indexing/secondary/logging"
	"sync"
	"time"
)

const (
	notifyWaitTimeout = time.Second * 5
)

type NotificationType int

const (
	ServiceChangeNotification NotificationType = iota
	PoolChangeNotification
)

var (
	ErrNodeServicesConnect = errors.New("Internal services API connection closed")
	ErrNodeServicesCancel  = errors.New("Cancelled services change notifier")
	ErrNotifierInvalid     = errors.New("Notifier invalidated due to internal error")
)

// Implements nodeServices change notifier system
var singletonServicesContainer struct {
	sync.Mutex
	notifiers map[string]*serviceNotifierInstance
}

type serviceNotifierInstance struct {
	sync.Mutex
	id          string
	clusterUrl  string
	pool        string
	waiterCount int
	client      couchbase.Client
	valid       bool
	waiters     map[int]chan Notification
}

func (instance *serviceNotifierInstance) getNotifyCallback(t NotificationType) func(interface{}) error {
	fn := func(msg interface{}) error {
		instance.Lock()
		defer instance.Unlock()

		if !instance.valid {
			return ErrNotifierInvalid
		}

		notifMsg := Notification{
			Type: t,
			Msg:  msg,
		}

		for _, w := range instance.waiters {
			select {
			case w <- notifMsg:
			case <-time.After(notifyWaitTimeout):
				logging.Warnf("servicesChangeNotifier: Consumer for %v took too long to read notification, making the consumer invalid", instance.clusterUrl)
				close(w)
			}
		}
		return nil
	}

	return fn
}

func (instance *serviceNotifierInstance) RunPoolObserver() {
	poolCallback := instance.getNotifyCallback(PoolChangeNotification)
	err := instance.client.RunObservePool(instance.pool, poolCallback, nil)
	if err != nil {
		logging.Errorf("servicesChangeNotifier: Connection terminated for pool notifier instance of %s, %s (%v)", instance.clusterUrl, instance.pool, err)
	}
	instance.cleanup()
}

func (instance *serviceNotifierInstance) RunServicesObserver() {
	servicesCallback := instance.getNotifyCallback(ServiceChangeNotification)
	err := instance.client.RunObserveNodeServices(instance.pool, servicesCallback, nil)
	if err != nil {
		logging.Errorf("servicesChangeNotifier: Connection terminated for services notifier instance of %s, %s (%v)", instance.clusterUrl, instance.pool, err)
	}
	instance.cleanup()
}

func (instance *serviceNotifierInstance) cleanup() {
	instance.Lock()
	defer instance.Unlock()
	if !instance.valid {
		return
	}

	instance.valid = false
	singletonServicesContainer.Lock()
	for _, w := range instance.waiters {
		close(w)
	}
	delete(singletonServicesContainer.notifiers, instance.id)
	singletonServicesContainer.Unlock()
}

type Notification struct {
	Type NotificationType
	Msg  interface{}
}

type ServicesChangeNotifier struct {
	id       int
	instance *serviceNotifierInstance
	ch       chan Notification
	cancel   chan bool
}

func init() {
	singletonServicesContainer.notifiers = make(map[string]*serviceNotifierInstance)
}

// Initialize change notifier object for a clusterUrl
func NewServicesChangeNotifier(clusterUrl, pool string) (*ServicesChangeNotifier, error) {
	singletonServicesContainer.Lock()
	defer singletonServicesContainer.Unlock()
	id := clusterUrl + "-" + pool

	if _, ok := singletonServicesContainer.notifiers[id]; !ok {
		logging.Infof("servicesChangeNotifier: Creating new notifier instance for %s, %s", clusterUrl, pool)
		client, err := couchbase.Connect(clusterUrl)
		if err != nil {
			return nil, err
		}
		instance := &serviceNotifierInstance{
			id:         id,
			client:     client,
			clusterUrl: clusterUrl,
			pool:       pool,
			valid:      true,
			waiters:    make(map[int]chan Notification),
		}

		singletonServicesContainer.notifiers[id] = instance
		go instance.RunPoolObserver()
		go instance.RunServicesObserver()
	}

	notifier := singletonServicesContainer.notifiers[id]
	notifier.Lock()
	defer notifier.Unlock()
	notifier.waiterCount++
	scn := &ServicesChangeNotifier{
		instance: notifier,
		ch:       make(chan Notification, 1),
		cancel:   make(chan bool),
		id:       notifier.waiterCount,
	}

	notifier.waiters[scn.id] = scn.ch

	return scn, nil
}

// Call Get() method to block wait and obtain next services Config
func (sn *ServicesChangeNotifier) Get() (n Notification, err error) {
	select {
	case <-sn.cancel:
		err = ErrNodeServicesCancel
	case msg, ok := <-sn.ch:
		if !ok {
			err = ErrNodeServicesConnect
		} else {
			n = msg
		}
	}
	return
}

func (sn *ServicesChangeNotifier) GetNotifyCh() chan couchbase.PoolServices {
	return sn.ch
}

// Consumer can cancel and invalidate notifier object by calling Close()
func (sn *ServicesChangeNotifier) Close() {
	sn.instance.Lock()
	defer sn.instance.Unlock()
	close(sn.cancel)
	delete(sn.instance.waiters, sn.id)
}
<commit_msg>Fix service_notifer build error<commit_after>package common

import (
	"errors"
	"github.com/couchbase/indexing/secondary/dcp"
	"github.com/couchbase/indexing/secondary/logging"
	"sync"
	"time"
)

const (
	notifyWaitTimeout = time.Second * 5
)

type NotificationType int

const (
	ServiceChangeNotification NotificationType = iota
	PoolChangeNotification
)

var (
	ErrNodeServicesConnect = errors.New("Internal services API connection closed")
	ErrNodeServicesCancel  = errors.New("Cancelled services change notifier")
	ErrNotifierInvalid     = errors.New("Notifier invalidated due to internal error")
)

// Implements nodeServices change notifier system
var singletonServicesContainer struct {
	sync.Mutex
	notifiers map[string]*serviceNotifierInstance
}

type serviceNotifierInstance struct {
	sync.Mutex
	id          string
	clusterUrl  string
	pool        string
	waiterCount int
	client      couchbase.Client
	valid       bool
	waiters     map[int]chan Notification
}

func (instance *serviceNotifierInstance) getNotifyCallback(t NotificationType) func(interface{}) error {
	fn := func(msg interface{}) error {
		instance.Lock()
		defer instance.Unlock()

		if !instance.valid {
			return ErrNotifierInvalid
		}

		notifMsg := Notification{
			Type: t,
			Msg:  msg,
		}

		for _, w := range instance.waiters {
			select {
			case w <- notifMsg:
			case <-time.After(notifyWaitTimeout):
				logging.Warnf("servicesChangeNotifier: Consumer for %v took too long to read notification, making the consumer invalid", instance.clusterUrl)
				close(w)
			}
		}
		return nil
	}

	return fn
}

func (instance *serviceNotifierInstance) RunPoolObserver() {
	poolCallback := instance.getNotifyCallback(PoolChangeNotification)
	err := instance.client.RunObservePool(instance.pool, poolCallback, nil)
	if err != nil {
		logging.Errorf("servicesChangeNotifier: Connection terminated for pool notifier instance of %s, %s (%v)", instance.clusterUrl, instance.pool, err)
	}
	instance.cleanup()
}

func (instance *serviceNotifierInstance) RunServicesObserver() {
	servicesCallback := instance.getNotifyCallback(ServiceChangeNotification)
	err := instance.client.RunObserveNodeServices(instance.pool, servicesCallback, nil)
	if err != nil {
		logging.Errorf("servicesChangeNotifier: Connection terminated for services notifier instance of %s, %s (%v)", instance.clusterUrl, instance.pool, err)
	}
	instance.cleanup()
}

func (instance *serviceNotifierInstance) cleanup() {
	instance.Lock()
	defer instance.Unlock()
	if !instance.valid {
		return
	}

	instance.valid = false
	singletonServicesContainer.Lock()
	for _, w := range instance.waiters {
		close(w)
	}
	delete(singletonServicesContainer.notifiers, instance.id)
	singletonServicesContainer.Unlock()
}

type Notification struct {
	Type NotificationType
	Msg  interface{}
}

type ServicesChangeNotifier struct {
	id       int
	instance *serviceNotifierInstance
	ch       chan Notification
	cancel   chan bool
}

func init() {
	singletonServicesContainer.notifiers = make(map[string]*serviceNotifierInstance)
}

// Initialize change notifier object for a clusterUrl
func NewServicesChangeNotifier(clusterUrl, pool string) (*ServicesChangeNotifier, error) {
	singletonServicesContainer.Lock()
	defer singletonServicesContainer.Unlock()
	id := clusterUrl + "-" + pool

	if _, ok := singletonServicesContainer.notifiers[id]; !ok {
		logging.Infof("servicesChangeNotifier: Creating new notifier instance for %s, %s", clusterUrl, pool)
		client, err := couchbase.Connect(clusterUrl)
		if err != nil {
			return nil, err
		}
		instance := &serviceNotifierInstance{
			id:         id,
			client:     client,
			clusterUrl: clusterUrl,
			pool:       pool,
			valid:      true,
			waiters:    make(map[int]chan Notification),
		}

		singletonServicesContainer.notifiers[id] = instance
		go instance.RunPoolObserver()
		go instance.RunServicesObserver()
	}

	notifier := singletonServicesContainer.notifiers[id]
	notifier.Lock()
	defer notifier.Unlock()
	notifier.waiterCount++
	scn := &ServicesChangeNotifier{
		instance: notifier,
		ch:       make(chan Notification, 1),
		cancel:   make(chan bool),
		id:       notifier.waiterCount,
	}

	notifier.waiters[scn.id] = scn.ch

	return scn, nil
}

// Call Get() method to block wait and obtain next services Config
func (sn *ServicesChangeNotifier) Get() (n Notification, err error) {
	select {
	case <-sn.cancel:
		err = ErrNodeServicesCancel
	case msg, ok := <-sn.ch:
		if !ok {
			err = ErrNodeServicesConnect
		} else {
			n = msg
		}
	}
	return
}

func (sn *ServicesChangeNotifier) GetNotifyCh() chan Notification {
	return sn.ch
}

// Consumer can cancel and invalidate notifier object by calling Close()
func (sn *ServicesChangeNotifier) Close() {
	sn.instance.Lock()
	defer sn.instance.Unlock()
	close(sn.cancel)
	delete(sn.instance.waiters, sn.id)
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"database/sql"
	"flag"
	"fmt"
	"log"
	"os"
	"regexp"
	"sort"
	"strings"
	"time"

	// "database/sql"

	_ "github.com/lib/pq"

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

var (
	localHost     = flag.String("l", ":5432", "puerto local para escuchar")
	dbHostname    = flag.String("h", "localhost", "hostname del servidor PostgreSQL")
	dbPort        = flag.String("r", "5432", "puerto del servidor PostgreSQL")
	dbName        = flag.String("d", "dbname", "nombre de la base de datos")
	dbUsername    = flag.String("u", "username", "usuario para acceder al servidor PostgreSQL")
	dbPassword    = flag.String("p", "password", "password para acceder al servidor PostgreSQL")
	remoteService = flag.String("s", "", "http://localhost:8080/query")
	// messages      = []string{}
)

type msgStruct struct {
	Type    string
	Content string
}

var (
	db *sql.DB
)

func main() {
	flag.Parse()
	// dbinfo := fmt.Sprintf("user=%s password=%s dbname=%s sslmode=disable",
	// 	*dbUsername, *dbPassword, *dbName)
	// db, err := sql.Open("postgres", dbinfo)

	msgs := make(chan string)
	msgCh := make(chan proxy.Pkg)
	msgOut := make(chan msgStruct)
	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())
				msgOut <- msgStruct{Type: "C", Content: 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("/reports/report.md", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0777)
		// c := 0
		spaces := regexp.MustCompile("[\t]+")
		// pdo_stmt_ := regexp.MustCompile("pdo_stmt_[0-9a-fA-F]{8}")
		multipleSpaces := regexp.MustCompile("    ")
		for {
			// select {
			// case msg1 := <-msgOut:
			msg := <-msgOut
			if msg.Type == "C" {
				// c = 0
				f.Close()
				f, err = os.OpenFile(fmt.Sprintf("/reports/report-%s.md", msg.Content), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0777)
				// c = 0
				if err != nil {
					panic(err)
				}
				_, err := f.WriteString(fmt.Sprintf("# %s\n", msg.Content))
				if err != nil {
					log.Fatalf("log failed: %v", err)
				}
			} else {
				// case msg2 := <-msgOut:
				// c = c + 1
				m := spaces.ReplaceAll([]byte(msg.Content), []byte{' '})
				m = multipleSpaces.ReplaceAll(m, []byte{' '})
				_, err := f.WriteString(fmt.Sprintf("\n```sql\n%s\n```\n", string(m)))
				if err != nil {
					log.Fatalf("log failed: %v", err)
				}
			}
		}
	}()

	go func() {
		temp := ""
		for msg := range msgCh {
			msgs <- fmt.Sprintf("received ---->%#v\n", msg)
			if msg.Type == byte('P') {
				if strings.Contains(string(msg.Content), "$1") {
					msgs <- fmt.Sprintf("1 received ---->%#v\n", msg)
					var newMsg proxy.ReadBuf
					newMsg = msg.Content
					_ = newMsg.Int32()

					// The name of the destination portal (an empty string selects the unnamed portal).
					p := bytes.Index(newMsg, []byte{112, 100, 111, 95, 115, 116, 109, 116, 95})
					// remove first string
					msgs <- fmt.Sprintf("msg ---->%#v\n", newMsg)
					msgs <- fmt.Sprintf("msg ---->%s\n", string(newMsg))
					msgs <- fmt.Sprintf("first string ---->%#v\n", newMsg[:p+16])
					msgs <- fmt.Sprintf("first string ---->%s\n", string(newMsg[:p+16]))
					newMsg = newMsg[p+16:]
					fmt.Printf("0 newMsg   ----->%#v\n", newMsg)

					// // The name of the source prepared statement (an empty string selects the unnamed prepared statement).
					// p = bytes.Index(newMsg, []byte{0})
					// // remove second string
					// msgs <- fmt.Sprintf("second string: message ---->%#v\n", newMsg[:p])
					// temp = string(newMsg[:p])
					// msgs <- fmt.Sprintf("second string: message temp ---->%s\n", temp)

					msgs <- fmt.Sprintf("1 temp ---->%#v\n", temp)
				} else {
					msgs <- fmt.Sprintf("2 received ---->%#v\n", msg)
					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")))
					msgOut <- msgStruct{Type: "M", Content: string(bytes.Trim(msg.Content[selectIdx:sepIdx], "\x00"))}
				}
			} else {
				msgs <- fmt.Sprintf("3 received ---->%#v\n", msg)
				if msg.Type == byte('B') && temp != "" && len(msg.Content) > 28 {
					msgs <- fmt.Sprintf("4 received ---->%#v\n", msg)
					var newMsg proxy.ReadBuf
					newMsg = msg.Content

					msgs <- fmt.Sprintf("5 received ---->%#v\n", msg)
					// The name of the destination portal (an empty string selects the unnamed portal).
					p := bytes.Index(newMsg, []byte{0})
					// remove first string
					msgs <- fmt.Sprintf("msg ---->%#v\n", newMsg)
					msgs <- fmt.Sprintf("first string ---->%#v\n", newMsg[:p+1])
					newMsg = newMsg[p+1:]
					msgs <- fmt.Sprintf("0 newMsg   ----->%#v\n", newMsg)

					if newMsg[0] == 0 {
						p := bytes.Index(newMsg, []byte{0})
						// remove first string
						msgs <- fmt.Sprintf("msg ---->%#v\n", newMsg)
						msgs <- fmt.Sprintf("1.1 first string ---->%#v\n", newMsg[:p+1])
						newMsg = newMsg[p:]
						msgs <- fmt.Sprintf("0.1 newMsg   ----->%#v\n", newMsg)
					}
					// The name of the source prepared statement (an empty string selects the unnamed prepared statement).
					p = bytes.Index(newMsg, []byte{0})
					// remove second string
					msgs <- fmt.Sprintf("second string ---->%#v\n", newMsg[:p+1])
					newMsg = newMsg[p+1:]
					msgs <- fmt.Sprintf("1 newMsg   ----->%#v\n", newMsg)

					t := newMsg.Int16()
					msgs <- fmt.Sprintf("vars types numbers ---->%#v\n", t)
					for t1 := 0; t1 == t; t1 = newMsg.Int16() {
						msgs <- fmt.Sprintf("22 newMsg   ----->%#v\n", newMsg)
					}

					msgs <- fmt.Sprintf("23 newMsg   ----->%#v\n", newMsg)
					totalVar := t
					// newMsg.Int16()
					vars := make(map[int]string)
					var varsIdx []int
					if (totalVar == 0 && len(newMsg) > 4) || totalVar > len(newMsg) {
						msgs <- fmt.Sprintf("23.1 newMsg   ----->%#v\n", newMsg)
						msgs <- fmt.Sprintf("0 totalVar  ----->%d\n", totalVar)
						for totalVar := 0; totalVar != 0 && totalVar < len(newMsg); totalVar = newMsg.Int16() {
							msgs <- fmt.Sprintf("24 newMsg   ----->%#v\n", newMsg)
							msgs <- fmt.Sprintf("1 totalVar  ----->%d\n", totalVar)
						}
					}
					//
					// if totalVar == 0 && len(newMsg) > 4 {
					// 	totalVar = newMsg.Int16()
					// }
					// if totalVar == 0 && len(newMsg) > 4 {
					// 	totalVar = newMsg.Int32()
					// }
					msgs <- fmt.Sprintf("totalVar   ----->%d\n", totalVar)
					for i := 0; i < totalVar; i++ {
						msgs <- fmt.Sprintf("2 newMsg   ----->%#v\n", newMsg)
						varLen := newMsg.Int32()
						// var1 := newMsg.Next(4)
						// // fmt.Printf("aa   -----> %#v\n", aa)
						// // fmt.Printf("aa bits ----->%8b\n", aa[len(aa)-1])
						// varLen := int(binary.BigEndian.Uint32(var1))
						// if varLen > len(newMsg) {
						// 	varLen = int(binary.BigEndian.Uint16(var1[:2]))
						// }
						msgs <- fmt.Sprintf("varLen ----->%v\n", varLen)
						msgs <- fmt.Sprintf("newMsg   ----->%#v\n", newMsg)
						if varLen > len(newMsg) {
							varLen = len(newMsg) - 4
							msgs <- fmt.Sprintf("1 varLen ----->%v\n", varLen)
							msgs <- fmt.Sprintf("1 newMsg   ----->%#v\n", newMsg)
						}
						vars[i] = string(newMsg.Next(varLen))
						msgs <- fmt.Sprintf("vars   ----->%#v\n", vars)
						varsIdx = append(varsIdx, i)
						msgs <- fmt.Sprintf("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))
						temp = strings.Replace(temp, fmt.Sprintf("$%d", k+1), fmt.Sprintf("'%s'", string(vars[k])), -1)
						msgs <- fmt.Sprintf("message subst k ----->%v\n", k)
						msgs <- fmt.Sprintf("message subst newMsg ----->%#v\n", newMsg)
						msgs <- fmt.Sprintf("message subst msg ----->%v\n", vars[k+1])
						msgs <- fmt.Sprintf("message subst temp ----->%v\n", temp)
						msgs <- fmt.Sprintf("message subst param %s ----->%v\n", fmt.Sprintf("$%d", k+1), fmt.Sprintf("'%s'", vars[k]))
					}
					msgs <- fmt.Sprintf("end message  ----->%v\n", temp)
					// msgOut <- msgStruct{Type: "M", Content: temp}
					// } else {
				}
				msgOut <- msgStruct{Type: "M", Content: temp}
				temp = ""
			}
		}
	}()

	proxy.Start(localHost, dbHostname, dbPort, 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"
	"database/sql"
	"flag"
	"fmt"
	"log"
	"os"
	"regexp"
	"sort"
	"strings"
	"time"

	// "database/sql"

	_ "github.com/lib/pq"

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

var (
	localHost     = flag.String("l", ":5432", "puerto local para escuchar")
	dbHostname    = flag.String("h", "localhost", "hostname del servidor PostgreSQL")
	dbPort        = flag.String("r", "5432", "puerto del servidor PostgreSQL")
	dbName        = flag.String("d", "dbname", "nombre de la base de datos")
	dbUsername    = flag.String("u", "username", "usuario para acceder al servidor PostgreSQL")
	dbPassword    = flag.String("p", "password", "password para acceder al servidor PostgreSQL")
	remoteService = flag.String("s", "", "http://localhost:8080/query")
	// messages      = []string{}
)

type msgStruct struct {
	Type    string
	Content string
}

var (
	db *sql.DB
)

func main() {
	flag.Parse()
	// dbinfo := fmt.Sprintf("user=%s password=%s dbname=%s sslmode=disable",
	// 	*dbUsername, *dbPassword, *dbName)
	// db, err := sql.Open("postgres", dbinfo)

	msgs := make(chan string)
	msgCh := make(chan proxy.Pkg)
	msgOut := make(chan msgStruct)
	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())
				msgOut <- msgStruct{Type: "C", Content: 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("/reports/report.md", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0777)
		// c := 0
		spaces := regexp.MustCompile("[\t]+")
		// pdo_stmt_ := regexp.MustCompile("pdo_stmt_[0-9a-fA-F]{8}")
		multipleSpaces := regexp.MustCompile("    ")
		for {
			// select {
			// case msg1 := <-msgOut:
			msg := <-msgOut
			if msg.Type == "C" {
				// c = 0
				f.Close()
				f, err = os.OpenFile(fmt.Sprintf("/reports/report-%s.md", msg.Content), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0777)
				// c = 0
				if err != nil {
					panic(err)
				}
				_, err := f.WriteString(fmt.Sprintf("# %s\n", msg.Content))
				if err != nil {
					log.Fatalf("log failed: %v", err)
				}
			} else {
				// case msg2 := <-msgOut:
				// c = c + 1
				m := spaces.ReplaceAll([]byte(msg.Content), []byte{' '})
				m = multipleSpaces.ReplaceAll(m, []byte{' '})
				_, err := f.WriteString(fmt.Sprintf("\n```sql\n%s\n```\n", string(m)))
				if err != nil {
					log.Fatalf("log failed: %v", err)
				}
			}
		}
	}()

	go func() {
		temp := ""
		for msg := range msgCh {
			msgs <- fmt.Sprintf("received ---->%#v\n", msg)
			if msg.Type == byte('P') {
				if strings.Contains(string(msg.Content), "$1") {
					msgs <- fmt.Sprintf("1 received ---->%#v\n", msg)
					var newMsg proxy.ReadBuf
					newMsg = msg.Content
					_ = newMsg.Int32()

					// The name of the destination portal (an empty string selects the unnamed portal).
					p := bytes.Index(newMsg, []byte{112, 100, 111, 95, 115, 116, 109, 116, 95})
					// remove first string
					msgs <- fmt.Sprintf("msg ---->%#v\n", newMsg)
					msgs <- fmt.Sprintf("msg ---->%s\n", string(newMsg))
					msgs <- fmt.Sprintf("first string ---->%#v\n", newMsg[:p+16])
					msgs <- fmt.Sprintf("first string ---->%s\n", string(newMsg[:p+16]))
					newMsg = newMsg[p+16:]
					fmt.Printf("0 newMsg   ----->%#v\n", newMsg)

					// // The name of the source prepared statement (an empty string selects the unnamed prepared statement).
					// p = bytes.Index(newMsg, []byte{0})
					// // remove second string
					// msgs <- fmt.Sprintf("second string: message ---->%#v\n", newMsg[:p])
					// temp = string(newMsg[:p])
					// msgs <- fmt.Sprintf("second string: message temp ---->%s\n", temp)

					msgs <- fmt.Sprintf("1 temp ---->%#v\n", temp)
				} else {
					msgs <- fmt.Sprintf("2 received ---->%#v\n", msg)
					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")))
					msgOut <- msgStruct{Type: "M", Content: string(bytes.Trim(msg.Content[selectIdx:sepIdx], "\x00"))}
				}
			} else {
				msgs <- fmt.Sprintf("3 received ---->%#v\n", msg)
				if msg.Type == byte('B') && temp != "" && len(msg.Content) > 23 {
					msgs <- fmt.Sprintf("4 received ---->%#v\n", msg)
					var newMsg proxy.ReadBuf
					newMsg = msg.Content

					msgs <- fmt.Sprintf("5 received ---->%#v\n", msg)
					// The name of the destination portal (an empty string selects the unnamed portal).
					p := bytes.Index(newMsg, []byte{0})
					// remove first string
					msgs <- fmt.Sprintf("msg ---->%#v\n", newMsg)
					msgs <- fmt.Sprintf("first string ---->%#v\n", newMsg[:p+1])
					newMsg = newMsg[p+1:]
					msgs <- fmt.Sprintf("0 newMsg   ----->%#v\n", newMsg)

					if newMsg[0] == 0 {
						p := bytes.Index(newMsg, []byte{0})
						// remove first string
						msgs <- fmt.Sprintf("msg ---->%#v\n", newMsg)
						msgs <- fmt.Sprintf("1.1 first string ---->%#v\n", newMsg[:p+1])
						newMsg = newMsg[p:]
						msgs <- fmt.Sprintf("0.1 newMsg   ----->%#v\n", newMsg)
					}
					// The name of the source prepared statement (an empty string selects the unnamed prepared statement).
					p = bytes.Index(newMsg, []byte{0})
					// remove second string
					msgs <- fmt.Sprintf("second string ---->%#v\n", newMsg[:p+1])
					newMsg = newMsg[p+1:]
					msgs <- fmt.Sprintf("1 newMsg   ----->%#v\n", newMsg)

					t := newMsg.Int16()
					msgs <- fmt.Sprintf("vars types numbers ---->%#v\n", t)
					for t1 := 0; t1 == t; t1 = newMsg.Int16() {
						msgs <- fmt.Sprintf("22 newMsg   ----->%#v\n", newMsg)
					}

					msgs <- fmt.Sprintf("23 newMsg   ----->%#v\n", newMsg)
					totalVar := t
					// newMsg.Int16()
					vars := make(map[int]string)
					var varsIdx []int
					if (totalVar == 0 && len(newMsg) > 4) || totalVar > len(newMsg) {
						msgs <- fmt.Sprintf("23.1 newMsg   ----->%#v\n", newMsg)
						msgs <- fmt.Sprintf("0 totalVar  ----->%d\n", totalVar)
						for totalVar := 0; totalVar != 0 && totalVar < len(newMsg); totalVar = newMsg.Int16() {
							msgs <- fmt.Sprintf("24 newMsg   ----->%#v\n", newMsg)
							msgs <- fmt.Sprintf("1 totalVar  ----->%d\n", totalVar)
						}
					}
					//
					// if totalVar == 0 && len(newMsg) > 4 {
					// 	totalVar = newMsg.Int16()
					// }
					// if totalVar == 0 && len(newMsg) > 4 {
					// 	totalVar = newMsg.Int32()
					// }
					msgs <- fmt.Sprintf("totalVar   ----->%d\n", totalVar)
					for i := 0; i < totalVar; i++ {
						msgs <- fmt.Sprintf("2 newMsg   ----->%#v\n", newMsg)
						varLen := newMsg.Int32()
						// var1 := newMsg.Next(4)
						// // fmt.Printf("aa   -----> %#v\n", aa)
						// // fmt.Printf("aa bits ----->%8b\n", aa[len(aa)-1])
						// varLen := int(binary.BigEndian.Uint32(var1))
						// if varLen > len(newMsg) {
						// 	varLen = int(binary.BigEndian.Uint16(var1[:2]))
						// }
						msgs <- fmt.Sprintf("varLen ----->%v\n", varLen)
						msgs <- fmt.Sprintf("newMsg   ----->%#v\n", newMsg)
						if varLen > len(newMsg) {
							varLen = len(newMsg) - 4
							msgs <- fmt.Sprintf("1 varLen ----->%v\n", varLen)
							msgs <- fmt.Sprintf("1 newMsg   ----->%#v\n", newMsg)
						}
						vars[i] = string(newMsg.Next(varLen))
						msgs <- fmt.Sprintf("vars   ----->%#v\n", vars)
						varsIdx = append(varsIdx, i)
						msgs <- fmt.Sprintf("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))
						temp = strings.Replace(temp, fmt.Sprintf("$%d", k+1), fmt.Sprintf("'%s'", string(vars[k])), -1)
						msgs <- fmt.Sprintf("message subst k ----->%v\n", k)
						msgs <- fmt.Sprintf("message subst newMsg ----->%#v\n", newMsg)
						msgs <- fmt.Sprintf("message subst msg ----->%v\n", vars[k+1])
						msgs <- fmt.Sprintf("message subst temp ----->%v\n", temp)
						msgs <- fmt.Sprintf("message subst param %s ----->%v\n", fmt.Sprintf("$%d", k+1), fmt.Sprintf("'%s'", vars[k]))
					}
					msgs <- fmt.Sprintf("end message  ----->%v\n", temp)
					// msgOut <- msgStruct{Type: "M", Content: temp}
					// } else {
				}
				msgOut <- msgStruct{Type: "M", Content: temp}
				temp = ""
			}
		}
	}()

	proxy.Start(localHost, dbHostname, dbPort, 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><commit_msg>report test<commit_after><|endoftext|>


<commit_before>package musicplayer

import (
	"time"

	"github.com/Necroforger/Fantasia/system"
	"github.com/Necroforger/Fantasia/widgets"
	"github.com/Necroforger/dream"
)

// CmdTutorial sends a tutorial with instructions on how to use the musicplayer
func (m *Module) CmdTutorial(ctx *system.Context) {
	paginator := widgets.NewPaginator(ctx.Ses, ctx.Msg.ChannelID)

	QuickGuide := dream.NewEmbed().
		SetTitle("Quick guide").
		SetDescription("Get started quickly\n" +
			"`>m queue https://www.youtube.com/watch?v=dm2YwytOyH0`\n" +
			"`>m play`").
		SetImage("http://i.imgur.com/7MLMNmM.gif").
		SetColor(system.StatusNotify).
		MessageEmbed

	QueueHelp := dream.NewEmbed().
		SetTitle("Queueing videos").
		SetImage("http://i.imgur.com/Bs6drYI.gif").
		SetDescription("`queue [ URL | playlist URL | search query | song index]`\n"+
			"If no arguments are provided, list the playlist").
		AddField("URL",
			"Use youtube-dl to queue the requested url. can be a link to soundcloud, youtube, facebook, or any other site supported by youtube-dl").
		AddField("Playlist URL",
			"If you provide a playlist URL, it will add every video in the playlist to the queue").
		AddField("Search Query", "If the argument is not a URL it will be treated as a youtube search query.\n"+
			"The bot will search youtube with the query and queue the first result found").
		AddField("Song Index", "If the argument is a song index integer it will list the songs around the given song index.").
		SetColor(system.StatusNotify).
		InlineAllFields().
		MessageEmbed

	Navigating := dream.NewEmbed().
		SetTitle("Navigating the queue").
		SetDescription("Navigate the queue using the `next`, `previous`, and multipurpose `go` command" +
			"Any command that accepts a song index as an argument (except the queue command) can use one of the following strings " +
			"in its place\n\n" +
			"`start, beginning : select index 0`\n" +
			"`end, last : select the last index`\n" +
			"`middle, center: select the middle index`\n" +
			"`random, rand : select a random index`").
		SetImage("http://i.imgur.com/KaaRGBb.gif").
		SetColor(system.StatusNotify).
		MessageEmbed

	SaveAndLoad := dream.NewEmbed().
		SetTitle("Save and load playlists").
		SetDescription("Use the save and load commands to save and load playlists").
		SetImage("http://i.imgur.com/CJ3tQvj.gif").
		SetColor(system.StatusNotify).
		MessageEmbed

	// Change the colour to yellow when the tutorial is no longer listening
	paginator.Events = widgets.EventChangeColourWhenDone
	paginator.Add(QuickGuide, QueueHelp, Navigating, SaveAndLoad)
	paginator.SetPageFooters()
	paginator.NavigationTimeout = time.Minute * 5
	paginator.Spawn()
}
<commit_msg>Use ctx.Ses.DG instead of ctx.Ses<commit_after>package musicplayer

import (
	"time"

	"github.com/Necroforger/Fantasia/system"
	"github.com/Necroforger/Fantasia/widgets"
	"github.com/Necroforger/dream"
)

// CmdTutorial sends a tutorial with instructions on how to use the musicplayer
func (m *Module) CmdTutorial(ctx *system.Context) {
	paginator := widgets.NewPaginator(ctx.Ses.DG, ctx.Msg.ChannelID)

	QuickGuide := dream.NewEmbed().
		SetTitle("Quick guide").
		SetDescription("Get started quickly\n" +
			"`>m queue https://www.youtube.com/watch?v=dm2YwytOyH0`\n" +
			"`>m play`").
		SetImage("http://i.imgur.com/7MLMNmM.gif").
		SetColor(system.StatusNotify).
		MessageEmbed

	QueueHelp := dream.NewEmbed().
		SetTitle("Queueing videos").
		SetImage("http://i.imgur.com/Bs6drYI.gif").
		SetDescription("`queue [ URL | playlist URL | search query | song index]`\n"+
			"If no arguments are provided, list the playlist").
		AddField("URL",
			"Use youtube-dl to queue the requested url. can be a link to soundcloud, youtube, facebook, or any other site supported by youtube-dl").
		AddField("Playlist URL",
			"If you provide a playlist URL, it will add every video in the playlist to the queue").
		AddField("Search Query", "If the argument is not a URL it will be treated as a youtube search query.\n"+
			"The bot will search youtube with the query and queue the first result found").
		AddField("Song Index", "If the argument is a song index integer it will list the songs around the given song index.").
		SetColor(system.StatusNotify).
		InlineAllFields().
		MessageEmbed

	Navigating := dream.NewEmbed().
		SetTitle("Navigating the queue").
		SetDescription("Navigate the queue using the `next`, `previous`, and multipurpose `go` command" +
			"Any command that accepts a song index as an argument (except the queue command) can use one of the following strings " +
			"in its place\n\n" +
			"`start, beginning : select index 0`\n" +
			"`end, last : select the last index`\n" +
			"`middle, center: select the middle index`\n" +
			"`random, rand : select a random index`").
		SetImage("http://i.imgur.com/KaaRGBb.gif").
		SetColor(system.StatusNotify).
		MessageEmbed

	SaveAndLoad := dream.NewEmbed().
		SetTitle("Save and load playlists").
		SetDescription("Use the save and load commands to save and load playlists").
		SetImage("http://i.imgur.com/CJ3tQvj.gif").
		SetColor(system.StatusNotify).
		MessageEmbed

	// Change the colour to yellow when the tutorial is no longer listening
	paginator.Events = widgets.EventChangeColourWhenDone
	paginator.Add(QuickGuide, QueueHelp, Navigating, SaveAndLoad)
	paginator.SetPageFooters()
	paginator.NavigationTimeout = time.Minute * 5
	paginator.Spawn()
}
<|endoftext|>


<commit_before>package mpb

import (
	"bytes"
	"container/heap"
	"context"
	"fmt"
	"io"
	"math"
	"os"
	"sync"
	"time"

	"github.com/vbauerster/mpb/v8/cwriter"
)

const (
	prr = 150 * time.Millisecond // default RefreshRate
)

// DoneError represents an error when `*mpb.Progress` is done but its functionality is requested.
var DoneError = fmt.Errorf("%T instance can't be reused after it's done!", (*Progress)(nil))

// Progress represents a container that renders one or more progress bars.
type Progress struct {
	ctx          context.Context
	uwg          *sync.WaitGroup
	cwg          *sync.WaitGroup
	bwg          *sync.WaitGroup
	operateState chan func(*pState)
	interceptIo  chan func(io.Writer)
	done         chan struct{}
	refreshCh    chan time.Time
	once         sync.Once
}

// pState holds bars in its priorityQueue, it gets passed to (*Progress).serve monitor goroutine.
type pState struct {
	bHeap       priorityQueue
	heapUpdated bool
	pMatrix     map[int][]chan int
	aMatrix     map[int][]chan int

	// for reuse purposes
	rows []io.Reader
	pool []*Bar

	// following are provided/overrided by user
	idCount          int
	reqWidth         int
	popPriority      int
	popCompleted     bool
	outputDiscarded  bool
	rr               time.Duration
	uwg              *sync.WaitGroup
	externalRefresh  <-chan interface{}
	renderDelay      <-chan struct{}
	shutdownNotifier chan struct{}
	queueBars        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{},
		rows:        make([]io.Reader, 0, 64),
		pool:        make([]*Bar, 0, 64),
		rr:          prr,
		queueBars:   make(map[*Bar]*Bar),
		output:      os.Stdout,
		popPriority: math.MinInt32,
	}

	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)),
		interceptIo:  make(chan func(io.Writer)),
		done:         make(chan struct{}),
	}

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

// AddBar creates a bar with default bar filler.
func (p *Progress) AddBar(total int64, options ...BarOption) *Bar {
	return p.New(total, BarStyle(), options...)
}

// AddSpinner creates a bar with default spinner filler.
func (p *Progress) AddSpinner(total int64, options ...BarOption) *Bar {
	return p.New(total, SpinnerStyle(), options...)
}

// New creates a bar with provided BarFillerBuilder.
func (p *Progress) New(total int64, builder BarFillerBuilder, options ...BarOption) *Bar {
	return p.Add(total, builder.Build(), options...)
}

// Add creates a bar which renders itself by provided filler.
// If `total <= 0` triggering complete event by increment methods is disabled.
// Panics if *Progress instance is done, i.e. called after (*Progress).Wait().
func (p *Progress) Add(total int64, filler BarFiller, options ...BarOption) *Bar {
	if filler == nil {
		filler = NopStyle().Build()
	}
	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.wait.bar != nil {
			ps.queueBars[bs.wait.bar] = bar
		} else {
			heap.Push(&ps.bHeap, bar)
			ps.heapUpdated = true
		}
		ps.idCount++
		result <- bar
	}:
		bar := <-result
		return bar
	case <-p.done:
		p.bwg.Done()
		panic(DoneError)
	}
}

func (p *Progress) traverseBars(cb func(b *Bar) bool) {
	sync := make(chan struct{})
	select {
	case p.operateState <- func(s *pState) {
		for i := 0; i < s.bHeap.Len(); i++ {
			bar := s.bHeap[i]
			if !cb(bar) {
				break
			}
		}
		close(sync)
	}:
		<-sync
	case <-p.done:
	}
}

// UpdateBarPriority same as *Bar.SetPriority(int).
func (p *Progress) UpdateBarPriority(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:
	}
}

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

// Write is implementation of io.Writer.
// Writing to `*mpb.Progress` will print lines above a running bar.
// Writes aren't flushed immediatly, but at next refresh cycle.
// If Write is called after `*mpb.Progress` is done, `mpb.DoneError`
// is returned.
func (p *Progress) Write(b []byte) (int, error) {
	type result struct {
		n   int
		err error
	}
	ch := make(chan *result)
	select {
	case p.interceptIo <- func(w io.Writer) {
		n, err := w.Write(b)
		ch <- &result{n, err}
	}:
		res := <-ch
		return res.n, res.err
	case <-p.done:
		return 0, DoneError
	}
}

// Wait waits for 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() {
	// wait for user wg, if any
	if p.uwg != nil {
		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()

	render := func(debugOut io.Writer) {
		err := s.render(cw)
		for err != nil {
			if debugOut != nil {
				_, err = fmt.Fprintln(debugOut, err)
			} else {
				panic(err)
			}
			debugOut = nil
		}
	}

	p.refreshCh = s.newTicker(p.done)

	for {
		select {
		case op := <-p.operateState:
			op(s)
		case fn := <-p.interceptIo:
			fn(cw)
		case <-p.refreshCh:
			render(s.debugOut)
		case <-s.shutdownNotifier:
			for s.heapUpdated {
				render(s.debugOut)
			}
			return
		}
	}
}

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

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

	return s.flush(cw, height)
}

func (s *pState) flush(cw *cwriter.Writer, height int) error {
	var wg sync.WaitGroup
	var popCount int

	for s.bHeap.Len() > 0 {
		var usedRows int
		b := heap.Pop(&s.bHeap).(*Bar)
		frame := <-b.frameCh
		if frame.recovered {
			s.heapUpdated = true
			continue
		}
		for i := len(frame.rows) - 1; i >= 0; i-- {
			if row := frame.rows[i]; len(s.rows) < height {
				s.rows = append(s.rows, row)
				usedRows++
			} else {
				wg.Add(1)
				go func() {
					_, _ = io.Copy(io.Discard, row)
					wg.Done()
				}()
			}
		}
		if frame.shutdown != 0 {
			b.Wait() // waiting for b.done, so it's safe to read b.bs
			drop := b.bs.dropOnComplete
			if qb, ok := s.queueBars[b]; ok {
				delete(s.queueBars, b)
				qb.priority = b.priority
				s.pool = append(s.pool, qb)
				drop = true
			} else if s.popCompleted && !b.bs.noPop {
				if frame.shutdown > 1 {
					popCount += usedRows
					drop = true
				} else {
					s.popPriority++
					b.priority = s.popPriority
				}
			}
			if drop {
				s.heapUpdated = true
				continue
			}
		}
		s.pool = append(s.pool, b)
	}

	wg.Add(1)
	go func() {
		for _, b := range s.pool {
			heap.Push(&s.bHeap, b)
		}
		wg.Done()
	}()

	readRows := len(s.rows)
	for i := readRows - 1; i >= 0; i-- {
		_, err := cw.ReadFrom(s.rows[i])
		if err != nil {
			readRows--
		}
	}

	err := cw.Flush(readRows - popCount)
	wg.Wait()
	s.rows = s.rows[:0]
	s.pool = s.pool[:0]
	return err
}

func (s *pState) newTicker(done <-chan struct{}) chan time.Time {
	ch := make(chan time.Time)
	if s.shutdownNotifier == nil {
		s.shutdownNotifier = make(chan struct{})
	}
	go func() {
		if s.renderDelay != nil {
			<-s.renderDelay
		}
		var internalRefresh <-chan time.Time
		if !s.outputDiscarded {
			if s.externalRefresh == nil {
				ticker := time.NewTicker(s.rr)
				defer ticker.Stop()
				internalRefresh = ticker.C
			}
		} else {
			s.externalRefresh = nil
		}
		for {
			select {
			case t := <-internalRefresh:
				ch <- t
			case x := <-s.externalRefresh:
				if t, ok := x.(time.Time); ok {
					ch <- t
				} else {
					ch <- time.Now()
				}
			case <-done:
				close(s.shutdownNotifier)
				return
			}
		}
	}()
	return ch
}

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 BarFiller, options ...BarOption) *bState {
	bs := &bState{
		id:       s.idCount,
		priority: s.idCount,
		reqWidth: s.reqWidth,
		total:    total,
		filler:   filler,
		debugOut: s.debugOut,
	}

	if total > 0 {
		bs.triggerComplete = true
	}

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

	if bs.middleware != nil {
		bs.filler = bs.middleware(filler)
		bs.middleware = nil
	}

	for i := 0; i < len(bs.buffers); i++ {
		bs.buffers[i] = bytes.NewBuffer(make([]byte, 0, 512))
	}

	bs.subscribeDecorators()

	return bs
}

func syncWidth(matrix map[int][]chan int) {
	for _, column := range matrix {
		go maxWidthDistributor(column)
	}
}

func maxWidthDistributor(column []chan int) {
	var maxWidth int
	for _, ch := range column {
		if w := <-ch; w > maxWidth {
			maxWidth = w
		}
	}
	for _, ch := range column {
		ch <- maxWidth
	}
}
<commit_msg>debug error if any<commit_after>package mpb

import (
	"bytes"
	"container/heap"
	"context"
	"fmt"
	"io"
	"math"
	"os"
	"sync"
	"time"

	"github.com/vbauerster/mpb/v8/cwriter"
)

const (
	prr = 150 * time.Millisecond // default RefreshRate
)

// DoneError represents an error when `*mpb.Progress` is done but its functionality is requested.
var DoneError = fmt.Errorf("%T instance can't be reused after it's done!", (*Progress)(nil))

// Progress represents a container that renders one or more progress bars.
type Progress struct {
	ctx          context.Context
	uwg          *sync.WaitGroup
	cwg          *sync.WaitGroup
	bwg          *sync.WaitGroup
	operateState chan func(*pState)
	interceptIo  chan func(io.Writer)
	done         chan struct{}
	refreshCh    chan time.Time
	once         sync.Once
}

// pState holds bars in its priorityQueue, it gets passed to (*Progress).serve monitor goroutine.
type pState struct {
	bHeap       priorityQueue
	heapUpdated bool
	pMatrix     map[int][]chan int
	aMatrix     map[int][]chan int

	// for reuse purposes
	rows []io.Reader
	pool []*Bar

	// following are provided/overrided by user
	idCount          int
	reqWidth         int
	popPriority      int
	popCompleted     bool
	outputDiscarded  bool
	rr               time.Duration
	uwg              *sync.WaitGroup
	externalRefresh  <-chan interface{}
	renderDelay      <-chan struct{}
	shutdownNotifier chan struct{}
	queueBars        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{},
		rows:        make([]io.Reader, 0, 64),
		pool:        make([]*Bar, 0, 64),
		rr:          prr,
		queueBars:   make(map[*Bar]*Bar),
		output:      os.Stdout,
		popPriority: math.MinInt32,
	}

	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)),
		interceptIo:  make(chan func(io.Writer)),
		done:         make(chan struct{}),
	}

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

// AddBar creates a bar with default bar filler.
func (p *Progress) AddBar(total int64, options ...BarOption) *Bar {
	return p.New(total, BarStyle(), options...)
}

// AddSpinner creates a bar with default spinner filler.
func (p *Progress) AddSpinner(total int64, options ...BarOption) *Bar {
	return p.New(total, SpinnerStyle(), options...)
}

// New creates a bar with provided BarFillerBuilder.
func (p *Progress) New(total int64, builder BarFillerBuilder, options ...BarOption) *Bar {
	return p.Add(total, builder.Build(), options...)
}

// Add creates a bar which renders itself by provided filler.
// If `total <= 0` triggering complete event by increment methods is disabled.
// Panics if *Progress instance is done, i.e. called after (*Progress).Wait().
func (p *Progress) Add(total int64, filler BarFiller, options ...BarOption) *Bar {
	if filler == nil {
		filler = NopStyle().Build()
	}
	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.wait.bar != nil {
			ps.queueBars[bs.wait.bar] = bar
		} else {
			heap.Push(&ps.bHeap, bar)
			ps.heapUpdated = true
		}
		ps.idCount++
		result <- bar
	}:
		bar := <-result
		return bar
	case <-p.done:
		p.bwg.Done()
		panic(DoneError)
	}
}

func (p *Progress) traverseBars(cb func(b *Bar) bool) {
	sync := make(chan struct{})
	select {
	case p.operateState <- func(s *pState) {
		for i := 0; i < s.bHeap.Len(); i++ {
			bar := s.bHeap[i]
			if !cb(bar) {
				break
			}
		}
		close(sync)
	}:
		<-sync
	case <-p.done:
	}
}

// UpdateBarPriority same as *Bar.SetPriority(int).
func (p *Progress) UpdateBarPriority(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:
	}
}

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

// Write is implementation of io.Writer.
// Writing to `*mpb.Progress` will print lines above a running bar.
// Writes aren't flushed immediatly, but at next refresh cycle.
// If Write is called after `*mpb.Progress` is done, `mpb.DoneError`
// is returned.
func (p *Progress) Write(b []byte) (int, error) {
	type result struct {
		n   int
		err error
	}
	ch := make(chan *result)
	select {
	case p.interceptIo <- func(w io.Writer) {
		n, err := w.Write(b)
		ch <- &result{n, err}
	}:
		res := <-ch
		return res.n, res.err
	case <-p.done:
		return 0, DoneError
	}
}

// Wait waits for 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() {
	// wait for user wg, if any
	if p.uwg != nil {
		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()

	render := func(debugOut io.Writer) {
		err := s.render(cw)
		for err != nil {
			if debugOut != nil {
				_, err = fmt.Fprintln(debugOut, err)
			} else {
				panic(err)
			}
			debugOut = nil
		}
	}

	p.refreshCh = s.newTicker(p.done)

	for {
		select {
		case op := <-p.operateState:
			op(s)
		case fn := <-p.interceptIo:
			fn(cw)
		case <-p.refreshCh:
			render(s.debugOut)
		case <-s.shutdownNotifier:
			for s.heapUpdated {
				render(s.debugOut)
			}
			return
		}
	}
}

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

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

	return s.flush(cw, height)
}

func (s *pState) flush(cw *cwriter.Writer, height int) error {
	var wg sync.WaitGroup
	var popCount int

	for s.bHeap.Len() > 0 {
		var usedRows int
		b := heap.Pop(&s.bHeap).(*Bar)
		frame := <-b.frameCh
		if frame.recovered {
			s.heapUpdated = true
			continue
		}
		for i := len(frame.rows) - 1; i >= 0; i-- {
			if row := frame.rows[i]; len(s.rows) < height {
				s.rows = append(s.rows, row)
				usedRows++
			} else {
				wg.Add(1)
				go func() {
					_, _ = io.Copy(io.Discard, row)
					wg.Done()
				}()
			}
		}
		if frame.shutdown != 0 {
			b.Wait() // waiting for b.done, so it's safe to read b.bs
			drop := b.bs.dropOnComplete
			if qb, ok := s.queueBars[b]; ok {
				delete(s.queueBars, b)
				qb.priority = b.priority
				s.pool = append(s.pool, qb)
				drop = true
			} else if s.popCompleted && !b.bs.noPop {
				if frame.shutdown > 1 {
					popCount += usedRows
					drop = true
				} else {
					s.popPriority++
					b.priority = s.popPriority
				}
			}
			if drop {
				s.heapUpdated = true
				continue
			}
		}
		s.pool = append(s.pool, b)
	}

	wg.Add(1)
	go func() {
		for _, b := range s.pool {
			heap.Push(&s.bHeap, b)
		}
		wg.Done()
	}()

	readRows := len(s.rows)
	for i := readRows - 1; i >= 0; i-- {
		_, err := cw.ReadFrom(s.rows[i])
		if err != nil {
			if s.debugOut != nil {
				fmt.Fprintf(s.debugOut, "cw.ReadFrom: %s\n", err.Error())
			}
			readRows--
		}
	}

	err := cw.Flush(readRows - popCount)
	wg.Wait()
	s.rows = s.rows[:0]
	s.pool = s.pool[:0]
	return err
}

func (s *pState) newTicker(done <-chan struct{}) chan time.Time {
	ch := make(chan time.Time)
	if s.shutdownNotifier == nil {
		s.shutdownNotifier = make(chan struct{})
	}
	go func() {
		if s.renderDelay != nil {
			<-s.renderDelay
		}
		var internalRefresh <-chan time.Time
		if !s.outputDiscarded {
			if s.externalRefresh == nil {
				ticker := time.NewTicker(s.rr)
				defer ticker.Stop()
				internalRefresh = ticker.C
			}
		} else {
			s.externalRefresh = nil
		}
		for {
			select {
			case t := <-internalRefresh:
				ch <- t
			case x := <-s.externalRefresh:
				if t, ok := x.(time.Time); ok {
					ch <- t
				} else {
					ch <- time.Now()
				}
			case <-done:
				close(s.shutdownNotifier)
				return
			}
		}
	}()
	return ch
}

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 BarFiller, options ...BarOption) *bState {
	bs := &bState{
		id:       s.idCount,
		priority: s.idCount,
		reqWidth: s.reqWidth,
		total:    total,
		filler:   filler,
		debugOut: s.debugOut,
	}

	if total > 0 {
		bs.triggerComplete = true
	}

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

	if bs.middleware != nil {
		bs.filler = bs.middleware(filler)
		bs.middleware = nil
	}

	for i := 0; i < len(bs.buffers); i++ {
		bs.buffers[i] = bytes.NewBuffer(make([]byte, 0, 512))
	}

	bs.subscribeDecorators()

	return bs
}

func syncWidth(matrix map[int][]chan int) {
	for _, column := range matrix {
		go maxWidthDistributor(column)
	}
}

func maxWidthDistributor(column []chan int) {
	var maxWidth int
	for _, ch := range column {
		if w := <-ch; w > maxWidth {
			maxWidth = w
		}
	}
	for _, ch := range column {
		ch <- maxWidth
	}
}
<|endoftext|>


<commit_before>package handlers

import (
	"fmt"
	"net/http"
	"strings"

	"github.com/google/go-github/github"
	"github.com/k8s-community/cicd"
	githubWrap "github.com/k8s-community/github-integration/github"
	userManClient "github.com/k8s-community/user-manager/client"
	"github.com/takama/router"
	githubhook "gopkg.in/rjz/githubhook.v0"
	"github.com/AlekSi/pointer"
	"github.com/k8s-community/github-integration/models"
	"gopkg.in/reform.v1"
)

// WebHookHandler is common handler for web hooks (installation, repositories installation, push)
func (h *Handler) WebHookHandler(c *router.Control) {
	secret := []byte(h.Env["GITHUBINT_TOKEN"])

	hook, err := githubhook.Parse(secret, c.Request)
	if err != nil {
		h.Errlog.Printf("cannot parse hook (ID %s): %s", hook.Id, err)
		return
	}

	switch hook.Event {
	case "integration_installation":
		// Triggered when an integration has been installed or uninstalled by user.
		h.Infolog.Printf("initialization web hook (ID %s)", hook.Id)
		err = h.saveInstallation(hook)

	case "integration_installation_repositories":
		// Triggered when a repository is added or removed from an installation.
		h.Infolog.Printf("initialization web hook for user repositories (ID %s)", hook.Id)
		err = h.initialUserManagement(hook)

	case "push":
		// Any Git push to a Repository, including editing tags or branches.
		// Commits via API actions that update references are also counted. This is the default event.
		h.Infolog.Printf("push hook (ID %s)", hook.Id)
		err = h.runCiCdProcess(c, hook)
		if err != nil {
			h.Infolog.Printf("cannot run ci/cd process for hook (ID %s): %s", hook.Id, err)
			c.Code(http.StatusBadRequest).Body(nil)
			return
		}

	default:
		h.Infolog.Printf("not processed hook (ID %s), event = %s", hook.Id, hook.Event)
		c.Code(http.StatusNotFound).Body(nil)
		return
	}

	if err != nil {
		h.Errlog.Printf("cannot process hook (ID %s): %s", hook.Id, err)
		c.Code(http.StatusInternalServerError).Body(nil)
		return
	}

	h.Infolog.Printf("finished to process hook (ID %s)", hook.Id)
	c.Code(http.StatusOK).Body(nil)
}

// initialUserManagement is used for user activation in k8s system
func (h *Handler) initialUserManagement(hook *githubhook.Hook) error {
	evt := github.IntegrationInstallationRepositoriesEvent{}

	err := hook.Extract(&evt)
	if err != nil {
		return err
	}

	userManagerURL := h.Env["USERMAN_BASE_URL"]

	client, err := userManClient.NewClient(nil, userManagerURL)
	if err != nil {
		return err
	}

	h.Infolog.Print("Try to activate (sync) user in k8s system: ", *evt.Sender.Login)

	user := userManClient.NewUser(*evt.Installation.Account.Login)

	code, err := client.User.Sync(user)
	if err != nil {
		return err
	}

	h.Infolog.Printf("Service user-man, method sync, returned code: %d", code)

	return nil
}

// runCiCdProcess is used for start CI/CD process for some repository from push hook
func (h *Handler) runCiCdProcess(c *router.Control, hook *githubhook.Hook) error {
	evt := github.PushEvent{}

	err := hook.Extract(&evt)
	if err != nil {
		return err
	}

	if !strings.HasPrefix(*evt.Ref, "refs/heads/" + h.Env["GITHUBINT_BRANCH"]) {
		return fmt.Errorf("incorrect branch %s for ci/cd process", *evt.Ref)
	}

	ciCdURL := h.Env["CICD_BASE_URL"]

	client := cicd.NewClient(ciCdURL)

	// set Pending sttatus to Github
	build := &githubWrap.BuildCallback{
		Username:   *evt.Repo.Owner.Name,
		Repository: *evt.Repo.Name,
		CommitHash: *evt.HeadCommit.ID,
		State:      "pending",
		BuildURL:   pointer.ToString("https://k8s.community"), // TODO fix it
		Context: pointer.ToString("k8s-community/cicd"), // move to constant!
		Description: pointer.ToString("Waiting for release..."),
	}
	err = h.updateCommitStatus(c, build)
	if err != nil {
		h.Errlog.Printf("cannot update commit status, build: %+v, err: %s", build, err)
	}

	// run CICD process
	req := &cicd.BuildRequest{
		Username:   *evt.Repo.Owner.Name,
		Repository: *evt.Repo.Name,
		CommitHash: *evt.HeadCommit.ID,
	}

	_, err = client.Build(req)
	if err != nil {
		return fmt.Errorf("cannot run ci/cd process for hook (ID %s): %s", hook.Id, err)
	}

	return nil
}

// saveInstallation saves installation in memory
func (h *Handler) saveInstallation(hook *githubhook.Hook) error {
	evt := github.IntegrationInstallationEvent{}

	err := hook.Extract(&evt)
	if err != nil {
		return err
	}

	h.Infolog.Printf("save installation for user %s (installation ID = %d)", *evt.Sender.Login, *evt.Installation.ID)

	// save installation for commit status update
	err = h.setInstallationID(*evt.Installation.Account.Login, *evt.Installation.ID)
	if err != nil {
		h.Errlog.Printf("Couldn't save installation: %+v", err)
	}

	return nil
}

// installationID gets installation from DB
func (h *Handler) installationID(username string) (*int, error) {
	st, err := h.DB.FindOneFrom(models.InstallationTable, "username", username)
	if err != nil {
		return nil, err
	}
	inst := st.(*models.Installation)

	return pointer.ToInt(inst.InstallationID), nil
}

func (h *Handler) setInstallationID(username string, instID int) error {
	var inst *models.Installation

	st, err := h.DB.FindOneFrom(models.InstallationTable, "username", username)
	if err != nil && err != reform.ErrNoRows {
		return err
	}

	if err == nil {
		inst = st.(*models.Installation)
	}

	inst.InstallationID = instID
	inst.Username = username

	err = h.DB.Save(inst)

	return err
}
<commit_msg>Fix problem with missed installation id<commit_after>package handlers

import (
	"fmt"
	"net/http"
	"strings"

	"github.com/google/go-github/github"
	"github.com/k8s-community/cicd"
	githubWrap "github.com/k8s-community/github-integration/github"
	userManClient "github.com/k8s-community/user-manager/client"
	"github.com/takama/router"
	githubhook "gopkg.in/rjz/githubhook.v0"
	"github.com/AlekSi/pointer"
	"github.com/k8s-community/github-integration/models"
	"gopkg.in/reform.v1"
)

// WebHookHandler is common handler for web hooks (installation, repositories installation, push)
func (h *Handler) WebHookHandler(c *router.Control) {
	secret := []byte(h.Env["GITHUBINT_TOKEN"])

	hook, err := githubhook.Parse(secret, c.Request)
	if err != nil {
		h.Errlog.Printf("cannot parse hook (ID %s): %s", hook.Id, err)
		return
	}

	switch hook.Event {
	case "integration_installation":
		// Triggered when an integration has been installed or uninstalled by user.
		h.Infolog.Printf("initialization web hook (ID %s)", hook.Id)
		err = h.saveInstallation(hook)

	case "integration_installation_repositories":
		// Triggered when a repository is added or removed from an installation.
		h.Infolog.Printf("initialization web hook for user repositories (ID %s)", hook.Id)
		err = h.initialUserManagement(hook)

	case "push":
		// Any Git push to a Repository, including editing tags or branches.
		// Commits via API actions that update references are also counted. This is the default event.
		h.Infolog.Printf("push hook (ID %s)", hook.Id)
		err = h.runCiCdProcess(c, hook)
		if err != nil {
			h.Infolog.Printf("cannot run ci/cd process for hook (ID %s): %s", hook.Id, err)
			c.Code(http.StatusBadRequest).Body(nil)
			return
		}

	default:
		h.Infolog.Printf("not processed hook (ID %s), event = %s", hook.Id, hook.Event)
		c.Code(http.StatusNotFound).Body(nil)
		return
	}

	if err != nil {
		h.Errlog.Printf("cannot process hook (ID %s): %s", hook.Id, err)
		c.Code(http.StatusInternalServerError).Body(nil)
		return
	}

	h.Infolog.Printf("finished to process hook (ID %s)", hook.Id)
	c.Code(http.StatusOK).Body(nil)
}

// initialUserManagement is used for user activation in k8s system
func (h *Handler) initialUserManagement(hook *githubhook.Hook) error {
	evt := github.IntegrationInstallationRepositoriesEvent{}

	err := hook.Extract(&evt)
	if err != nil {
		return err
	}

	userManagerURL := h.Env["USERMAN_BASE_URL"]

	client, err := userManClient.NewClient(nil, userManagerURL)
	if err != nil {
		return err
	}

	h.Infolog.Print("Try to activate (sync) user in k8s system: ", *evt.Sender.Login)

	user := userManClient.NewUser(*evt.Installation.Account.Login)

	code, err := client.User.Sync(user)
	if err != nil {
		return err
	}

	h.Infolog.Printf("Service user-man, method sync, returned code: %d", code)

	return nil
}

// runCiCdProcess is used for start CI/CD process for some repository from push hook
func (h *Handler) runCiCdProcess(c *router.Control, hook *githubhook.Hook) error {
	evt := github.PushEvent{}

	err := hook.Extract(&evt)
	if err != nil {
		return err
	}

	h.setInstallationID(*evt.Repo.Owner.Name, *evt.Installation.ID)

	if !strings.HasPrefix(*evt.Ref, "refs/heads/" + h.Env["GITHUBINT_BRANCH"]) {
		return fmt.Errorf("incorrect branch %s for ci/cd process", *evt.Ref)
	}

	ciCdURL := h.Env["CICD_BASE_URL"]

	client := cicd.NewClient(ciCdURL)

	// set Pending sttatus to Github
	build := &githubWrap.BuildCallback{
		Username:   *evt.Repo.Owner.Name,
		Repository: *evt.Repo.Name,
		CommitHash: *evt.HeadCommit.ID,
		State:      "pending",
		BuildURL:   pointer.ToString("https://k8s.community"), // TODO fix it
		Context: pointer.ToString("k8s-community/cicd"), // move to constant!
		Description: pointer.ToString("Waiting for release..."),
	}
	err = h.updateCommitStatus(c, build)
	if err != nil {
		h.Errlog.Printf("cannot update commit status, build: %+v, err: %s", build, err)
	}

	// run CICD process
	req := &cicd.BuildRequest{
		Username:   *evt.Repo.Owner.Name,
		Repository: *evt.Repo.Name,
		CommitHash: *evt.HeadCommit.ID,
	}

	_, err = client.Build(req)
	if err != nil {
		return fmt.Errorf("cannot run ci/cd process for hook (ID %s): %s", hook.Id, err)
	}

	return nil
}

// saveInstallation saves installation in memory
func (h *Handler) saveInstallation(hook *githubhook.Hook) error {
	evt := github.IntegrationInstallationEvent{}

	err := hook.Extract(&evt)
	if err != nil {
		return err
	}

	h.Infolog.Printf("save installation for user %s (installation ID = %d)", *evt.Sender.Login, *evt.Installation.ID)

	// save installation for commit status update
	err = h.setInstallationID(*evt.Installation.Account.Login, *evt.Installation.ID)
	if err != nil {
		h.Errlog.Printf("Couldn't save installation: %+v", err)
	}

	return nil
}

// installationID gets installation from DB
func (h *Handler) installationID(username string) (*int, error) {
	st, err := h.DB.FindOneFrom(models.InstallationTable, "username", username)
	if err != nil {
		return nil, err
	}
	inst := st.(*models.Installation)

	return pointer.ToInt(inst.InstallationID), nil
}

func (h *Handler) setInstallationID(username string, instID int) error {
	var inst *models.Installation

	st, err := h.DB.FindOneFrom(models.InstallationTable, "username", username)
	if err != nil && err != reform.ErrNoRows {
		return err
	}

	if err == nil {
		inst = st.(*models.Installation)
	}

	inst.InstallationID = instID
	inst.Username = username

	err = h.DB.Save(inst)

	return err
}
<|endoftext|>


<commit_before>package handlers

import (
	"net/http"

	"fmt"

	"github.com/google/go-github/github"
	"github.com/k8s-community/cicd"
	userManClient "github.com/k8s-community/user-manager/client"
	"github.com/takama/router"
	githubhook "gopkg.in/rjz/githubhook.v0"
)

// installations is used for installations storing
// TODO: move this data in persistent key-value storage
var installations map[string]int = make(map[string]int)

// WebHookHandler is common handler for web hooks (installation, repositories installation, push)
func (h *Handler) WebHookHandler(c *router.Control) {
	secret := []byte(h.Env["GITHUBINT_TOKEN"])

	hook, err := githubhook.Parse(secret, c.Request)
	if err != nil {
		h.Errlog.Printf("cannot parse hook (ID %s): %s", hook.Id, err)
		return
	}

	switch hook.Event {
	case "integration_installation":
		// Triggered when an integration has been installed or uninstalled by user.
		h.Infolog.Printf("initialization web hook (ID %s)", hook.Id)
		err = h.saveInstallation(hook)

	case "integration_installation_repositories":
		// Triggered when a repository is added or removed from an installation.
		h.Infolog.Printf("initialization web hook for user repositories (ID %s)", hook.Id)
		err = h.initialUserManagement(hook)

	case "push":
		// Any Git push to a Repository, including editing tags or branches.
		// Commits via API actions that update references are also counted. This is the default event.
		h.Infolog.Printf("push hook (ID %s)", hook.Id)
		err = h.runCiCdProcess(hook)

	default:
		h.Infolog.Printf("not processed hook (ID %s), event = %s", hook.Id, hook.Event)
		c.Code(http.StatusNotFound).Body(nil)
		return
	}

	if err != nil {
		h.Errlog.Printf("cannot process hook (ID %s): %s", hook.Id, err)
		c.Code(http.StatusInternalServerError).Body(nil)
		return
	}

	h.Infolog.Printf("finished to process hook (ID %s)", hook.Id)
	c.Code(http.StatusOK).Body(nil)
}

// initialUserManagement is used for user activation in k8s system
func (h *Handler) initialUserManagement(hook *githubhook.Hook) error {
	evt := github.IntegrationInstallationRepositoriesEvent{}

	err := hook.Extract(&evt)
	if err != nil {
		return err
	}

	userManagerURL := fmt.Sprintf("%s:%s", h.Env["USERMAN_SERVICE_HOST"], h.Env["USERMAN_SERVICE_PORT"])

	client, err := userManClient.NewClient(nil, userManagerURL)
	if err != nil {
		return err
	}

	h.Infolog.Print("Try to activate (sync) user in k8s system: ", *evt.Sender.Login)

	user := userManClient.NewUser(*evt.Sender.Login)

	err = client.User.Sync(*user)
	if err != nil {
		return err
	}

	return nil
}

// runCiCdProcess is used for start CI/CD process for some repository from push hook
func (h *Handler) runCiCdProcess(hook *githubhook.Hook) error {
	evt := github.PushEvent{}

	err := hook.Extract(&evt)
	if err != nil {
		return err
	}

	ciCdURL := fmt.Sprintf("%s:%s", h.Env["CICD_SERVICE_HOST"], h.Env["CICD_SERVICE_PORT"])

	client := cicd.NewClient(ciCdURL)

	req := &cicd.BuildRequest{
		Username:   *evt.Repo.Owner.Name,
		Repository: *evt.Repo.Name,
		CommitHash: *evt.HeadCommit.ID,
	}

	_, err = client.Build(req)
	if err != nil {
		return fmt.Errorf("cannot run ci/cd process for hook (ID %s): %s", hook.Id, err)
	}

	return nil
}

// saveInstallation saves installation in memory
func (h *Handler) saveInstallation(hook *githubhook.Hook) error {
	evt := github.IntegrationInstallationEvent{}

	err := hook.Extract(&evt)
	if err != nil {
		return err
	}

	h.Infolog.Printf("save installation for user %s (installation ID = %d)", *evt.Sender.Login, *evt.Installation.ID)

	// save installation in memory for commit status update
	installations[*evt.Sender.Login] = *evt.Installation.ID

	return nil
}

// getInstallationID gets installation from memory
func (h *Handler) getInstallationID(username string) (int, bool) {
	id, ok := installations[username]

	return id, ok
}
<commit_msg>added template of branch name for CI/CD process<commit_after>package handlers

import (
	"net/http"

	"fmt"
	"strings"

	"github.com/google/go-github/github"
	"github.com/k8s-community/cicd"
	userManClient "github.com/k8s-community/user-manager/client"
	"github.com/takama/router"
	githubhook "gopkg.in/rjz/githubhook.v0"
)

// installations is used for installations storing
// TODO: move this data in persistent key-value storage
var installations map[string]int = make(map[string]int)

// WebHookHandler is common handler for web hooks (installation, repositories installation, push)
func (h *Handler) WebHookHandler(c *router.Control) {
	secret := []byte(h.Env["GITHUBINT_TOKEN"])

	hook, err := githubhook.Parse(secret, c.Request)
	if err != nil {
		h.Errlog.Printf("cannot parse hook (ID %s): %s", hook.Id, err)
		return
	}

	switch hook.Event {
	case "integration_installation":
		// Triggered when an integration has been installed or uninstalled by user.
		h.Infolog.Printf("initialization web hook (ID %s)", hook.Id)
		err = h.saveInstallation(hook)

	case "integration_installation_repositories":
		// Triggered when a repository is added or removed from an installation.
		h.Infolog.Printf("initialization web hook for user repositories (ID %s)", hook.Id)
		err = h.initialUserManagement(hook)

	case "push":
		// Any Git push to a Repository, including editing tags or branches.
		// Commits via API actions that update references are also counted. This is the default event.
		h.Infolog.Printf("push hook (ID %s)", hook.Id)
		err = h.runCiCdProcess(hook)
		if err != nil {
			h.Infolog.Printf("cannot run ci/cd process for hook (ID %s): %s", hook.Id, err)
			c.Code(http.StatusBadRequest).Body(nil)
			return
		}

	default:
		h.Infolog.Printf("not processed hook (ID %s), event = %s", hook.Id, hook.Event)
		c.Code(http.StatusNotFound).Body(nil)
		return
	}

	if err != nil {
		h.Errlog.Printf("cannot process hook (ID %s): %s", hook.Id, err)
		c.Code(http.StatusInternalServerError).Body(nil)
		return
	}

	h.Infolog.Printf("finished to process hook (ID %s)", hook.Id)
	c.Code(http.StatusOK).Body(nil)
}

// initialUserManagement is used for user activation in k8s system
func (h *Handler) initialUserManagement(hook *githubhook.Hook) error {
	evt := github.IntegrationInstallationRepositoriesEvent{}

	err := hook.Extract(&evt)
	if err != nil {
		return err
	}

	userManagerURL := fmt.Sprintf("%s:%s", h.Env["USERMAN_SERVICE_HOST"], h.Env["USERMAN_SERVICE_PORT"])

	client, err := userManClient.NewClient(nil, userManagerURL)
	if err != nil {
		return err
	}

	h.Infolog.Print("Try to activate (sync) user in k8s system: ", *evt.Sender.Login)

	user := userManClient.NewUser(*evt.Sender.Login)

	err = client.User.Sync(*user)
	if err != nil {
		return err
	}

	return nil
}

// runCiCdProcess is used for start CI/CD process for some repository from push hook
func (h *Handler) runCiCdProcess(hook *githubhook.Hook) error {
	evt := github.PushEvent{}

	err := hook.Extract(&evt)
	if err != nil {
		return err
	}

	ciCdURL := fmt.Sprintf("%s:%s", h.Env["CICD_SERVICE_HOST"], h.Env["CICD_SERVICE_PORT"])

	client := cicd.NewClient(ciCdURL)

	req := &cicd.BuildRequest{
		Username:   *evt.Repo.Owner.Name,
		Repository: *evt.Repo.Name,
		CommitHash: *evt.HeadCommit.ID,
	}

	_, err = client.Build(req)
	if err != nil {
		return fmt.Errorf("cannot run ci/cd process for hook (ID %s): %s", hook.Id, err)
	}

	if !strings.HasPrefix(evt.Repo.Name, h.Env["GITHUBINT_BRANCH"]) {
		return fmt.Errorf("incorrect branch %s for ci/cd process", evt.Repo.Name)
	}

	return nil
}

// saveInstallation saves installation in memory
func (h *Handler) saveInstallation(hook *githubhook.Hook) error {
	evt := github.IntegrationInstallationEvent{}

	err := hook.Extract(&evt)
	if err != nil {
		return err
	}

	h.Infolog.Printf("save installation for user %s (installation ID = %d)", *evt.Sender.Login, *evt.Installation.ID)

	// save installation in memory for commit status update
	installations[*evt.Sender.Login] = *evt.Installation.ID

	return nil
}

// getInstallationID gets installation from memory
func (h *Handler) getInstallationID(username string) (int, bool) {
	id, ok := installations[username]

	return id, ok
}
<|endoftext|>


<commit_before>package phlow

import (
	"fmt"
	"strings"

	"github.com/praqma/git-phlow/githandler"
	"github.com/praqma/git-phlow/printers"
)

//WrapUp ...
func WrapUp(verbose bool) {

	printers.PrintVerbose("Addind files to index", verbose)

	//Add all files to index
	if err := githandler.Add(); err != nil {
		fmt.Println("project files could not be added: " + err.Error())
		return
	}

	//Retrieve branch info - current branch
	info, _ := githandler.Branch()
	commitMessage := "close #" + strings.Replace(info.Current, "-", " ", -1)

	if _, err := githandler.Commit(commitMessage); err != nil {
		fmt.Println(err)
		return
	}
	printers.PrintVerbose(commitMessage, verbose)
}
<commit_msg>close #47 rework green tests<commit_after>package phlow

import (
	"fmt"
	"strings"

	"github.com/praqma/git-phlow/githandler"
	"os"
)

//WrapUp ...
func WrapUp(verbose bool) {

	fmt.Fprintln(os.Stdout, "Addind files to index")

	//Add all files to index
	if err := githandler.Add(); err != nil {
		fmt.Println("project files could not be added: " + err.Error())
		return
	}

	//Retrieve branch info - current branch
	info, _ := githandler.Branch()
	commitMessage := "close #" + strings.Replace(info.Current, "-", " ", -1)

	if _, err := githandler.Commit(commitMessage); err != nil {
		fmt.Println(err)
		return
	}
	fmt.Fprintln(os.Stdout, commitMessage)
}
<|endoftext|>


<commit_before>package hashmap

import (
	"fmt"
	"testing"
)

func TestHash(t *testing.T) {
	m := NewMap()
	h1 := m.hash("hello", 1024)
	h2 := m.hash("hello", 1024)
	if h1 != h2 {
		t.Fail()
	}
}

func TestGet(t *testing.T) {
	m := NewMap()

	for i := 0; i < 100; i++ {
		k := fmt.Sprintf("%d", i)
		m.Put(k, k)
	}

	exp := "20"
	got := m.Get(exp)
	if exp != got {
		t.Errorf("expectd: %s got: %v", exp, got)
	}
}

func BenchmarkHash8(b *testing.B) {
	m := NewMap()
	for i := 0; i < b.N; i++ {
		m.hash("12345678", 1024)
	}
}
func BenchmarkHash16(b *testing.B) {
	m := NewMap()
	for i := 0; i < b.N; i++ {
		m.hash("8888888888888888", 1024)
	}
}

func BenchmarkGet(b *testing.B) {
	m := NewMap()
	size := 100
	for i := 0; i < size; i++ {
		k := fmt.Sprintf("%d", i)
		m.Put(k, k)
	}

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		m.Get(fmt.Sprintf("%d", i%size))
	}
}
<commit_msg>updated test<commit_after>package hashmap

import (
	"fmt"
	"testing"
)

func TestHash(t *testing.T) {
	m := NewMap()
	h1 := m.hash("hello", 1024)
	h2 := m.hash("hello", 1024)
	if h1 != h2 {
		t.Fail()
	}
}

func TestGet(t *testing.T) {
	m := NewMap()

	for i := 0; i < 100; i++ {
		k := fmt.Sprintf("%d", i)
		m.Put(k, k)
	}

	for i := 0; i < 100; i++ {
		k := fmt.Sprintf("%d", i)
		if k != m.Get(k) {
			t.Fail()
		}
	}
}

func BenchmarkHash8(b *testing.B) {
	m := NewMap()
	for i := 0; i < b.N; i++ {
		m.hash("12345678", 1024)
	}
}
func BenchmarkHash16(b *testing.B) {
	m := NewMap()
	for i := 0; i < b.N; i++ {
		m.hash("8888888888888888", 1024)
	}
}

func BenchmarkGet(b *testing.B) {
	m := NewMap()
	size := 100
	for i := 0; i < size; i++ {
		k := fmt.Sprintf("%d", i)
		m.Put(k, k)
	}

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		m.Get(fmt.Sprintf("%d", i%size))
	}
}
<|endoftext|>


<commit_before>//////////////////////////////////////////
// archivex_test.go
// Jhonathan Paulo Banczek - 2014
// jpbanczek@gmail.com - jhoonb.com
//////////////////////////////////////////

package archivex

import (
	"testing"
)

func Test_archivex(t *testing.T) {

	// interface
	arcvx := []Archivex{&ZipFile{}, &TarFile{}}

	for _, arc := range arcvx {
		// create file
		err := arc.Create("filetest")
		checkError(t, err)
		// create 50000 files
		err = arc.AddAll("testfolder/", true)
		checkError(t, err)
		arc.Close()
		checkError(t, err)
	}
}

// func for check errors
func checkError(t *testing.T, err error) {
	if err != nil {
		t.Error(err)
		t.Fail()
	}
}
<commit_msg>Update test<commit_after>//////////////////////////////////////////
// archivex_test.go
// Jhonathan Paulo Banczek - 2014
// jpbanczek@gmail.com - jhoonb.com
//////////////////////////////////////////

package archivex

import (
	"testing"
	"os"
)

func Test_archivex(t *testing.T) {

	// interface
	arcvx := []Archivex{&ZipFile{}, &TarFile{}}

	for _, arc := range arcvx {
		// create file
		err := arc.Create("filetest")
		checkError(t, err)
		// create 50000 files
		dir, _ := os.Getwd()
		// absolute path
		err = arc.AddAll(dir+"/testfolder/", true)
		err = arc.AddAll(dir+"/testfolder/", false)
		// relative path
        	err = arc.AddAll("testfolder/", true)
        	err = arc.AddAll("testfolder/", false)
		checkError(t, err)
		arc.Close()
		checkError(t, err)
	}
}

// func for check errors
func checkError(t *testing.T, err error) {
	if err != nil {
		t.Error(err)
		t.Fail()
	}
}
<|endoftext|>


<commit_before><commit_msg>add big transaction condition<commit_after><|endoftext|>


<commit_before><commit_msg>Additional TLD exceptions.<commit_after><|endoftext|>