<commit_before>package termite

import (
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"rpc"
)

type Master struct {
	cache         *ContentCache
	fileServer    *FsServer
	fileServerRpc *rpc.Server
	secret        []byte

	retryCount   int
	mirrors      *mirrorConnections
	writableRoot string
	srcRoot      string
	pending      *PendingConnections
	taskIds      chan int

	replayChannel chan *replayRequest
}

type replayRequest struct {
	NewFiles map[string]string
	Files  []*FileAttr
	Done   chan int
}

func NewMaster(cache *ContentCache, coordinator string, workers []string, secret []byte, excluded []string, maxJobs int) *Master {
	me := &Master{
		cache:      cache,
		fileServer: NewFsServer("/", cache, excluded),
		secret:     secret,
		retryCount: 3,
		taskIds:    make(chan int, 100),
		replayChannel: make(chan *replayRequest, 1),
	}
	me.mirrors = newMirrorConnections(me, workers, coordinator, maxJobs)
	me.secret = secret
	me.pending = NewPendingConnections()
	me.fileServerRpc = rpc.NewServer()
	me.fileServerRpc.Register(me.fileServer)

	// Generate taskids.
	go func() {
		i := 0
		for {
			me.taskIds <-i
			i++
		}
	}()

	// Make sure we update the filesystem and attributes together.
	go func() {
		for {
			r := <-me.replayChannel
			me.replayFileModifications(r.Files, r.NewFiles)
			r.Done <- 1
		}
	}()

	return me
}

func (me *Master) SetSrcRoot(root string) {
	root, _ = filepath.Abs(root)
	me.srcRoot = filepath.Clean(root)
	log.Println("SrcRoot is", me.srcRoot)
}

func (me *Master) SetKeepAlive(keepalive float64, household float64) {
	if household > 0.0 || keepalive > 0.0 {
		me.mirrors.setKeepAliveNs(1e9*keepalive, 1e9*household)
	}
}

func (me *Master) CheckPrivate() {
	if !me.fileServer.excludePrivate {
		return
	}
	d := me.writableRoot
	for d != "" {
		fi, err := os.Lstat(d)
		if err != nil {
			log.Fatal("CheckPrivate:", err)
		}
		if fi != nil && fi.Mode&0077 == 0 {
			log.Fatalf("Error: dir %q is mode %o.", d, fi.Mode&07777)
		}
		d, _ = SplitPath(d)
	}
}

func (me *Master) Start(sock string) {
	localStart(me, sock)
}

func (me *Master) createMirror(addr string, jobs int) (*mirrorConnection, os.Error) {
	conn, err := DialTypedConnection(addr, RPC_CHANNEL, me.secret)
	if err != nil {
		return nil, err
	}
	defer conn.Close()

	rpcId := ConnectionId()
	rpcConn, err := DialTypedConnection(addr, rpcId, me.secret)
	if err != nil {
		return nil, err
	}

	revId := ConnectionId()
	revConn, err := DialTypedConnection(addr, revId, me.secret)
	if err != nil {
		rpcConn.Close()
		return nil, err
	}

	req := CreateMirrorRequest{
		RpcId:        rpcId,
		RevRpcId:     revId,
		WritableRoot: me.writableRoot,
		MaxJobCount:  jobs,
	}
	rep := CreateMirrorResponse{}
	cl := rpc.NewClient(conn)
	err = cl.Call("WorkerDaemon.CreateMirror", &req, &rep)
	cl.Close()

	if err != nil {
		revConn.Close()
		rpcConn.Close()
		return nil, err
	}

	go me.fileServerRpc.ServeConn(revConn)

	mc := &mirrorConnection{
		master:            me,
		rpcClient:         rpc.NewClient(rpcConn),
		reverseConnection: revConn,
		connection:        rpcConn,
		maxJobs:           rep.GrantedJobCount,
		availableJobs:     rep.GrantedJobCount,
	}
	mc.fileSetWaiter = newFileSetWaiter(func(fset FileSet) os.Error {
		return mc.replay(fset)
	})

	mc.queueFiles(me.fileServer.copyCache())
	return mc, nil
}

func (me *Master) runOnMirror(mirror *mirrorConnection, req *WorkRequest, rep *WorkResponse) os.Error {
	defer me.mirrors.jobDone(mirror)

	// Tunnel stdin.
	if req.StdinId != "" {
		inputConn := me.pending.WaitConnection(req.StdinId)
		destInputConn, err := DialTypedConnection(mirror.connection.RemoteAddr().String(),
			req.StdinId, me.secret)
		if err != nil {
			return err
		}
		go func() {
			HookedCopy(destInputConn, inputConn, PrintStdinSliceLen)
			destInputConn.Close()
			inputConn.Close()
		}()
	}

	log.Println("Running command", req.Argv)
	if req.Debug {
		log.Println("with environment", req.Env)
	}

	mirror.fileSetWaiter.newChannel(req.TaskId)
	err := mirror.rpcClient.Call("Mirror.Run", req, rep)
	if err == nil {
		err = mirror.fileSetWaiter.wait(rep, req.TaskId)
	}
	return err
}

func (me *Master) runOnce(req *WorkRequest, rep *WorkResponse) os.Error {
	mirror, err := me.mirrors.pick()
	if err != nil {
		return err
	}
	err = mirror.sendFiles()
	if err != nil {
		me.mirrors.drop(mirror, err)
		return err
	}

	err = me.runOnMirror(mirror, req, rep)
	if err != nil {
		me.mirrors.drop(mirror, err)
		return err
	}

	if err != nil {
		return err
	}
	rep.FileSet = nil
	return err
}

func (me *Master) run(req *WorkRequest, rep *WorkResponse) (err os.Error) {
	me.mirrors.stats.MarkReceive()
	req.TaskId = <-me.taskIds
	if me.MaybeRunInMaster(req, rep) {
		log.Println("Ran in master:", req)
		return nil
	}

	err = me.runOnce(req, rep)
	for i := 0; i < me.retryCount && err != nil; i++ {
		log.Println("Retrying; last error:", err)
		err = me.runOnce(req, rep)
	}

	me.mirrors.stats.MarkReturn(rep)
	return err
}

func (me *Master) replayFileModifications(infos []*FileAttr, newFiles map[string]string) {
	for _, info := range infos {
		logStr := ""
		name := "/" + info.Path
		var err os.Error
		if info.FileInfo != nil && info.FileInfo.IsDirectory() {
			err := os.Mkdir(name, info.FileInfo.Mode&07777)
			if err != nil {
				// some other process may have created
				// the dir.
				if fi, _ := os.Lstat(name); fi != nil && fi.IsDirectory() {
					err = nil
				}
			}
		}
		if info.Hash != "" {
			src := newFiles[info.Path]
			err = os.Rename(src, name)
		}
		if info.Link != "" {
			// Ignore errors.
			os.Remove(name)
			err = os.Symlink(info.Link, name)
			logStr += "Symlink,"
		}
		if info.Deletion() {
			if err := os.Remove(name); err != nil {
				log.Println("delete replay: ", err)
			}
		}

		if info.Hash == "" && info.FileInfo != nil && !info.FileInfo.IsSymlink() {
			if err == nil {
				err = os.Chtimes(name, info.FileInfo.Atime_ns, info.FileInfo.Mtime_ns)
				logStr += "Chtimes,"
			}
			if err == nil {
				err = os.Chmod(name, info.FileInfo.Mode&07777)
				logStr += "Chmod,"
			}
		}

		if err != nil {
			log.Fatal("Replay error ", info.Path, " ", err, infos, logStr)
		}
	}

	me.fileServer.updateFiles(infos)
}

func (me *Master) replay(fset FileSet) {
	req := replayRequest{
		make(map[string]string),
		fset.Files,
		make(chan int),
	}

	// We prepare the files before we call
	// replayFileModifications(), to limit contention.
	for _, info := range fset.Files {
		if info.Hash == "" {
			continue
		}

		log.Printf("Prepare %x: %s", info.Hash, info.Path)
		f, err := ioutil.TempFile(me.writableRoot, ".tmp-termite")
		if err != nil {
			log.Fatal("TempFile", err)
		}

		req.NewFiles[info.Path] = f.Name()

		content := me.cache.ContentsIfLoaded(info.Hash)

		if content == nil {
			var src *os.File
			src, err = os.Open(me.cache.Path(info.Hash))
			if err != nil {
				log.Panicf("cache path missing %x", info.Hash)
			}
			err = CopyFds(f, src)
		} else {
			_, err = f.Write(content)
		}
		if err != nil {
			log.Fatal("f.Write", err)
		}

		err = f.Chmod(info.FileInfo.Mode&07777)
		if err != nil {
			log.Fatal("f.Chmod", err)
		}
		err = f.Close()
		if err != nil {
			log.Fatal("f.Close", err)
		}
		err = os.Chtimes(f.Name(), info.FileInfo.Atime_ns, info.FileInfo.Mtime_ns)
		if err != nil {
			log.Fatal("Chtimes", err)
		}
	}

	me.replayChannel <- &req
	<-req.Done
}

func (me *Master) refreshAttributeCache() {
	for _, r := range []string{me.writableRoot, me.srcRoot} {
		updated := me.fileServer.refreshAttributeCache(r[1:])
		me.mirrors.queueFiles(nil, updated)
	}
}
<commit_msg>Only print summary of command ran in master.<commit_after>package termite

import (
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"rpc"
)

type Master struct {
	cache         *ContentCache
	fileServer    *FsServer
	fileServerRpc *rpc.Server
	secret        []byte

	retryCount   int
	mirrors      *mirrorConnections
	writableRoot string
	srcRoot      string
	pending      *PendingConnections
	taskIds      chan int

	replayChannel chan *replayRequest
}

type replayRequest struct {
	NewFiles map[string]string
	Files  []*FileAttr
	Done   chan int
}

func NewMaster(cache *ContentCache, coordinator string, workers []string, secret []byte, excluded []string, maxJobs int) *Master {
	me := &Master{
		cache:      cache,
		fileServer: NewFsServer("/", cache, excluded),
		secret:     secret,
		retryCount: 3,
		taskIds:    make(chan int, 100),
		replayChannel: make(chan *replayRequest, 1),
	}
	me.mirrors = newMirrorConnections(me, workers, coordinator, maxJobs)
	me.secret = secret
	me.pending = NewPendingConnections()
	me.fileServerRpc = rpc.NewServer()
	me.fileServerRpc.Register(me.fileServer)

	// Generate taskids.
	go func() {
		i := 0
		for {
			me.taskIds <-i
			i++
		}
	}()

	// Make sure we update the filesystem and attributes together.
	go func() {
		for {
			r := <-me.replayChannel
			me.replayFileModifications(r.Files, r.NewFiles)
			r.Done <- 1
		}
	}()

	return me
}

func (me *Master) SetSrcRoot(root string) {
	root, _ = filepath.Abs(root)
	me.srcRoot = filepath.Clean(root)
	log.Println("SrcRoot is", me.srcRoot)
}

func (me *Master) SetKeepAlive(keepalive float64, household float64) {
	if household > 0.0 || keepalive > 0.0 {
		me.mirrors.setKeepAliveNs(1e9*keepalive, 1e9*household)
	}
}

func (me *Master) CheckPrivate() {
	if !me.fileServer.excludePrivate {
		return
	}
	d := me.writableRoot
	for d != "" {
		fi, err := os.Lstat(d)
		if err != nil {
			log.Fatal("CheckPrivate:", err)
		}
		if fi != nil && fi.Mode&0077 == 0 {
			log.Fatalf("Error: dir %q is mode %o.", d, fi.Mode&07777)
		}
		d, _ = SplitPath(d)
	}
}

func (me *Master) Start(sock string) {
	localStart(me, sock)
}

func (me *Master) createMirror(addr string, jobs int) (*mirrorConnection, os.Error) {
	conn, err := DialTypedConnection(addr, RPC_CHANNEL, me.secret)
	if err != nil {
		return nil, err
	}
	defer conn.Close()

	rpcId := ConnectionId()
	rpcConn, err := DialTypedConnection(addr, rpcId, me.secret)
	if err != nil {
		return nil, err
	}

	revId := ConnectionId()
	revConn, err := DialTypedConnection(addr, revId, me.secret)
	if err != nil {
		rpcConn.Close()
		return nil, err
	}

	req := CreateMirrorRequest{
		RpcId:        rpcId,
		RevRpcId:     revId,
		WritableRoot: me.writableRoot,
		MaxJobCount:  jobs,
	}
	rep := CreateMirrorResponse{}
	cl := rpc.NewClient(conn)
	err = cl.Call("WorkerDaemon.CreateMirror", &req, &rep)
	cl.Close()

	if err != nil {
		revConn.Close()
		rpcConn.Close()
		return nil, err
	}

	go me.fileServerRpc.ServeConn(revConn)

	mc := &mirrorConnection{
		master:            me,
		rpcClient:         rpc.NewClient(rpcConn),
		reverseConnection: revConn,
		connection:        rpcConn,
		maxJobs:           rep.GrantedJobCount,
		availableJobs:     rep.GrantedJobCount,
	}
	mc.fileSetWaiter = newFileSetWaiter(func(fset FileSet) os.Error {
		return mc.replay(fset)
	})

	mc.queueFiles(me.fileServer.copyCache())
	return mc, nil
}

func (me *Master) runOnMirror(mirror *mirrorConnection, req *WorkRequest, rep *WorkResponse) os.Error {
	defer me.mirrors.jobDone(mirror)

	// Tunnel stdin.
	if req.StdinId != "" {
		inputConn := me.pending.WaitConnection(req.StdinId)
		destInputConn, err := DialTypedConnection(mirror.connection.RemoteAddr().String(),
			req.StdinId, me.secret)
		if err != nil {
			return err
		}
		go func() {
			HookedCopy(destInputConn, inputConn, PrintStdinSliceLen)
			destInputConn.Close()
			inputConn.Close()
		}()
	}

	log.Println("Running command", req.Argv)
	if req.Debug {
		log.Println("with environment", req.Env)
	}

	mirror.fileSetWaiter.newChannel(req.TaskId)
	err := mirror.rpcClient.Call("Mirror.Run", req, rep)
	if err == nil {
		err = mirror.fileSetWaiter.wait(rep, req.TaskId)
	}
	return err
}

func (me *Master) runOnce(req *WorkRequest, rep *WorkResponse) os.Error {
	mirror, err := me.mirrors.pick()
	if err != nil {
		return err
	}
	err = mirror.sendFiles()
	if err != nil {
		me.mirrors.drop(mirror, err)
		return err
	}

	err = me.runOnMirror(mirror, req, rep)
	if err != nil {
		me.mirrors.drop(mirror, err)
		return err
	}

	if err != nil {
		return err
	}
	rep.FileSet = nil
	return err
}

func (me *Master) run(req *WorkRequest, rep *WorkResponse) (err os.Error) {
	me.mirrors.stats.MarkReceive()
	req.TaskId = <-me.taskIds
	if me.MaybeRunInMaster(req, rep) {
		log.Println("Ran in master:", req.Summary())
		return nil
	}

	err = me.runOnce(req, rep)
	for i := 0; i < me.retryCount && err != nil; i++ {
		log.Println("Retrying; last error:", err)
		err = me.runOnce(req, rep)
	}

	me.mirrors.stats.MarkReturn(rep)
	return err
}

func (me *Master) replayFileModifications(infos []*FileAttr, newFiles map[string]string) {
	for _, info := range infos {
		logStr := ""
		name := "/" + info.Path
		var err os.Error
		if info.FileInfo != nil && info.FileInfo.IsDirectory() {
			err := os.Mkdir(name, info.FileInfo.Mode&07777)
			if err != nil {
				// some other process may have created
				// the dir.
				if fi, _ := os.Lstat(name); fi != nil && fi.IsDirectory() {
					err = nil
				}
			}
		}
		if info.Hash != "" {
			src := newFiles[info.Path]
			err = os.Rename(src, name)
		}
		if info.Link != "" {
			// Ignore errors.
			os.Remove(name)
			err = os.Symlink(info.Link, name)
			logStr += "Symlink,"
		}
		if info.Deletion() {
			if err := os.Remove(name); err != nil {
				log.Println("delete replay: ", err)
			}
		}

		if info.Hash == "" && info.FileInfo != nil && !info.FileInfo.IsSymlink() {
			if err == nil {
				err = os.Chtimes(name, info.FileInfo.Atime_ns, info.FileInfo.Mtime_ns)
				logStr += "Chtimes,"
			}
			if err == nil {
				err = os.Chmod(name, info.FileInfo.Mode&07777)
				logStr += "Chmod,"
			}
		}

		if err != nil {
			log.Fatal("Replay error ", info.Path, " ", err, infos, logStr)
		}
	}

	me.fileServer.updateFiles(infos)
}

func (me *Master) replay(fset FileSet) {
	req := replayRequest{
		make(map[string]string),
		fset.Files,
		make(chan int),
	}

	// We prepare the files before we call
	// replayFileModifications(), to limit contention.
	for _, info := range fset.Files {
		if info.Hash == "" {
			continue
		}

		log.Printf("Prepare %x: %s", info.Hash, info.Path)
		f, err := ioutil.TempFile(me.writableRoot, ".tmp-termite")
		if err != nil {
			log.Fatal("TempFile", err)
		}

		req.NewFiles[info.Path] = f.Name()

		content := me.cache.ContentsIfLoaded(info.Hash)

		if content == nil {
			var src *os.File
			src, err = os.Open(me.cache.Path(info.Hash))
			if err != nil {
				log.Panicf("cache path missing %x", info.Hash)
			}
			err = CopyFds(f, src)
		} else {
			_, err = f.Write(content)
		}
		if err != nil {
			log.Fatal("f.Write", err)
		}

		err = f.Chmod(info.FileInfo.Mode&07777)
		if err != nil {
			log.Fatal("f.Chmod", err)
		}
		err = f.Close()
		if err != nil {
			log.Fatal("f.Close", err)
		}
		err = os.Chtimes(f.Name(), info.FileInfo.Atime_ns, info.FileInfo.Mtime_ns)
		if err != nil {
			log.Fatal("Chtimes", err)
		}
	}

	me.replayChannel <- &req
	<-req.Done
}

func (me *Master) refreshAttributeCache() {
	for _, r := range []string{me.writableRoot, me.srcRoot} {
		updated := me.fileServer.refreshAttributeCache(r[1:])
		me.mirrors.queueFiles(nil, updated)
	}
}
<|endoftext|>


<commit_before>package upgrade

import (
	"os"

	log "github.com/Sirupsen/logrus"
	"github.com/codegangsta/cli"
	"github.com/flexiant/kdeploy/template"
	"github.com/flexiant/kdeploy/upgrade/strategies"
	"github.com/flexiant/kdeploy/utils"
	"github.com/flexiant/kdeploy/webservice"
)

// CmdUpgrade implements 'upgrade' command
func CmdUpgrade(c *cli.Context) {
	localKubePath, err := webservice.FetchKubeFromURL(os.Getenv("KDEPLOY_KUBEWARE"))
	utils.CheckError(err)

	log.Debugf("Going to parse kubeware in %s", localKubePath)

	md := template.ParseMetadata(localKubePath)
	utils.CheckError(err)

	kubernetes, err := webservice.NewKubeClient()
	utils.CheckError(err)

	namespace := os.Getenv("KDEPLOY_NAMESPACE")
	// labelSelector := fmt.Sprintf("kubeware=%s,kubeware-version=%s", md.Name, md.Version)

	// Check if kubeware already installed, error if it's not
	version, err := kubernetes.FindDeployedKubewareVersion(namespace, md.Name)
	utils.CheckError(err)
	log.Infof("Found version %s of %s.%s", version, namespace, md.Name)

	// TODO: Check if version equal or newer one already exists, error if so

	// build attributes merging "role list" to defaults
	log.Debugf("Building attributes")
	defaults, err := md.AttributeDefaults()
	utils.CheckError(err)
	attributes := template.BuildAttributes(c.String("attribute"), defaults)

	// get services and parse each one
	log.Debugf("Parsing services")
	servicesSpecs, err := md.ParseServices(attributes)
	utils.CheckError(err)

	// get replica controllers and parse each one
	log.Debugf("Parsing controllers")
	controllersSpecs, err := md.ParseControllers(attributes)
	utils.CheckError(err)

	upgStrategy := upgradeStrategies.RecreateAllStrategy(kubernetes)
	upgStrategy.Upgrade(namespace, servicesSpecs, controllersSpecs)
}
<commit_msg>Check if newer version already deployed before upgrading<commit_after>package upgrade

import (
	"os"

	log "github.com/Sirupsen/logrus"
	"github.com/codegangsta/cli"
	"github.com/flexiant/kdeploy/template"
	"github.com/flexiant/kdeploy/upgrade/strategies"
	"github.com/flexiant/kdeploy/utils"
	"github.com/flexiant/kdeploy/webservice"
	"github.com/hashicorp/go-version"
)

// CmdUpgrade implements 'upgrade' command
func CmdUpgrade(c *cli.Context) {
	localKubePath, err := webservice.FetchKubeFromURL(os.Getenv("KDEPLOY_KUBEWARE"))
	utils.CheckError(err)

	log.Debugf("Going to parse kubeware in %s", localKubePath)

	md := template.ParseMetadata(localKubePath)
	utils.CheckError(err)

	kubernetes, err := webservice.NewKubeClient()
	utils.CheckError(err)

	namespace := os.Getenv("KDEPLOY_NAMESPACE")
	// labelSelector := fmt.Sprintf("kubeware=%s,kubeware-version=%s", md.Name, md.Version)

	// Check if kubeware already installed, error if it's not
	v, err := kubernetes.FindDeployedKubewareVersion(namespace, md.Name)
	utils.CheckError(err)
	log.Infof("Found version %s of %s.%s", v, namespace, md.Name)

	// Check if equal or newer version already exists, error if so
	deployedVersion, err := version.NewVersion(v)
	utils.CheckError(err)
	upgradeVersion, err := version.NewVersion(md.Version)
	utils.CheckError(err)
	if upgradeVersion.LessThan(deployedVersion) {
		log.Fatalf("Can not upgrade to version '%s' since version '%s' is already deployed", md.Version, v)
	}

	// build attributes merging "role list" to defaults
	log.Debugf("Building attributes")
	defaults, err := md.AttributeDefaults()
	utils.CheckError(err)
	attributes := template.BuildAttributes(c.String("attribute"), defaults)

	// get services and parse each one
	log.Debugf("Parsing services")
	servicesSpecs, err := md.ParseServices(attributes)
	utils.CheckError(err)

	// get replica controllers and parse each one
	log.Debugf("Parsing controllers")
	controllersSpecs, err := md.ParseControllers(attributes)
	utils.CheckError(err)

	upgStrategy := upgradeStrategies.RecreateAllStrategy(kubernetes)
	upgStrategy.Upgrade(namespace, servicesSpecs, controllersSpecs)
}
<|endoftext|>


<commit_before>package handler

import (
	"fmt"
	"github.com/vladpereskokov/Technopark_HighLoad-nginx/src/constants"
	modelServer "github.com/vladpereskokov/Technopark_HighLoad-nginx/src/models/server"
	"github.com/vladpereskokov/Technopark_HighLoad-nginx/src/utils"
	"log"
	"net"
	"strings"
)

const HTTP_CONSTANTS_CONFIG = "configs/http.json"

type Handler struct {
	Connection net.Conn
	Request    *modelServer.Request
	Response   *modelServer.Response
	Constants  *modelServer.Constants
	Dir        string
}

type HandlerFunc func(chan net.Conn)

func CreateHandler(dir string) (handlerFunc HandlerFunc) {
	httpConstantsConfig := new(modelServer.Constants)

	err := utils.FromFile(HTTP_CONSTANTS_CONFIG, &httpConstantsConfig)
	if err != nil {
		log.Panicf("can not init http config: %v", err)
	}

	return func(channel chan net.Conn) {
		handler := Handler{}
		handler.create(httpConstantsConfig, dir)

		go handler.start(channel)
	}
}

func (handler *Handler) create(config *modelServer.Constants, dir string) {
	handler.Request = modelServer.InitRequest()
	handler.Response = modelServer.InitResponse()

	handler.Response.Status.Message = "ok"
	handler.Response.Status.Code = 200

	handler.Constants = config
	handler.Dir = dir
}

func (handler *Handler) start(channel chan net.Conn) {
	for {
		handler.Connection = <-channel
		handler.handle()
	}
}

func (handler *Handler) handle() {
	handler.readRequest()
	handler.writeResponse()
	handler.closeConn()
}

func (handler *Handler) readRequest() {
	buffer := make([]byte, 1024)

	_, err := handler.Connection.Read(buffer)
	if err != nil {
		fmt.Println("Error reading:", err.Error())

		return
	}

	handler.parseRequest(string(buffer))
}

func (handler *Handler) parseRequest(query string) {
	splitedQuery := strings.Split(query, "\r\n")[0]
	queryParts := strings.Split(splitedQuery, " ")

	for _, value := range queryParts {
		handler.Connection.Write([]byte(value))
		handler.Connection.Write([]byte("\r\n"))
	}

	if len(queryParts) != 3 {
		handler.Response.SetStatus(400, handler.Constants.Statuses)

		return
	}
}

func (handler *Handler) writeResponse() {
	handler.write(constants.HTTP_VERSION + " " + handler.Response.Status.Message)
}

func (handler *Handler) write(content string) {
	handler.Connection.Write([]byte(content + "\r\n"))
}

func (handler *Handler) closeConn() {
	handler.Connection.Close()
}
<commit_msg>add headers common write<commit_after>package handler

import (
	"fmt"
	"github.com/vladpereskokov/Technopark_HighLoad-nginx/src/constants"
	modelServer "github.com/vladpereskokov/Technopark_HighLoad-nginx/src/models/server"
	"github.com/vladpereskokov/Technopark_HighLoad-nginx/src/utils"
	"log"
	"net"
	"strings"
	"time"
)

const HTTP_CONSTANTS_CONFIG = "configs/http.json"

type Handler struct {
	Connection net.Conn
	Request    *modelServer.Request
	Response   *modelServer.Response
	Constants  *modelServer.Constants
	Dir        string
}

type HandlerFunc func(chan net.Conn)

func CreateHandler(dir string) (handlerFunc HandlerFunc) {
	httpConstantsConfig := new(modelServer.Constants)

	err := utils.FromFile(HTTP_CONSTANTS_CONFIG, &httpConstantsConfig)
	if err != nil {
		log.Panicf("can not init http config: %v", err)
	}

	return func(channel chan net.Conn) {
		handler := Handler{}
		handler.create(httpConstantsConfig, dir)

		go handler.start(channel)
	}
}

func (handler *Handler) create(config *modelServer.Constants, dir string) {
	handler.Request = modelServer.InitRequest()
	handler.Response = modelServer.InitResponse()

	handler.Response.Status.Message = "ok"
	handler.Response.Status.Code = 200

	handler.Constants = config
	handler.Dir = dir
}

func (handler *Handler) start(channel chan net.Conn) {
	for {
		handler.Connection = <-channel
		handler.handle()
	}
}

func (handler *Handler) handle() {
	handler.readRequest()
	handler.writeResponse()
	handler.closeConn()
}

func (handler *Handler) readRequest() {
	buffer := make([]byte, 1024)

	_, err := handler.Connection.Read(buffer)
	if err != nil {
		fmt.Println("Error reading:", err.Error())

		return
	}

	handler.parseRequest(string(buffer))
}

func (handler *Handler) parseRequest(query string) {
	splitedQuery := strings.Split(query, "\r\n")[0]
	queryParts := strings.Split(splitedQuery, " ")

	for _, value := range queryParts {
		handler.Connection.Write([]byte(value))
		handler.Connection.Write([]byte("\r\n"))
	}

	if len(queryParts) != 3 {
		handler.Response.SetStatus(400, handler.Constants.Statuses)

		return
	}
}

func (handler *Handler) writeResponse() {
	handler.write(constants.HTTP_VERSION + " " + handler.Response.Status.Message)
}

func (handler *Handler) writeHeader(content string) {
	handler.writeCommonHeaders()
}

func (handler *Handler) writeCommonHeaders() {
	handler.write("Date: " + time.Now().String())
	handler.write("Server: " + constants.SERVER)
	handler.write("Connection: close")
}

func (handler *Handler) write(content string) {
	handler.Connection.Write([]byte(content + "\r\n"))
}

func (handler *Handler) closeConn() {
	handler.Connection.Close()
}
<|endoftext|>


<commit_before>package parser

import (
	"fmt"
	"time"

	"github.com/feedbooks/epub"
	"github.com/feedbooks/webpub-streamer/models"
)

func init() {
	parserList = append(parserList, List{fileExt: "epub", parser: EpubParser})
}

// EpubParser TODO add doc
func EpubParser(filePath string, selfURL string) models.Publication {
	var manifestStruct models.Publication
	var metaStruct models.Metadata

	timeNow := time.Now()
	metaStruct.Modified = &timeNow
	manifestStruct.Links = make([]models.Link, 1)
	manifestStruct.Resources = make([]models.Link, 0)
	manifestStruct.Resources = make([]models.Link, 0)
	if selfURL != "" {
		self := models.Link{
			Rel:      []string{"self"},
			Href:     selfURL,
			TypeLink: "application/json",
		}
		manifestStruct.Links[0] = self
	}

	book, err := epub.Open(filePath)
	if err != nil {
		fmt.Println(err)
		return models.Publication{}
	}
	manifestStruct.Internal = append(manifestStruct.Internal, models.Internal{Name: "epub", Value: book.ZipReader()})
	manifestStruct.Internal = append(manifestStruct.Internal, models.Internal{Name: "rootfile", Value: book.Container.Rootfile.Path})

	metaStruct.Title = book.Opf.Metadata.Title[0]

	metaStruct.Language = book.Opf.Metadata.Language
	metaStruct.Identifier = book.Opf.Metadata.Identifier[0].Data
	if len(book.Opf.Metadata.Contributor) > 0 {
		aut := models.Contributor{}
		aut.Name = book.Opf.Metadata.Contributor[0].Data
		metaStruct.Author = append(metaStruct.Author, aut)
	}
	if len(book.Opf.Metadata.Creator) > 0 {
		aut := models.Contributor{}
		aut.Name = book.Opf.Metadata.Creator[0].Data
		metaStruct.Author = append(metaStruct.Author, aut)
	}

	for _, item := range book.Opf.Manifest {
		linkItem := models.Link{}
		linkItem.TypeLink = item.MediaType
		linkItem.Href = item.Href
		if linkItem.TypeLink == "application/xhtml+xml" {
			manifestStruct.Spine = append(manifestStruct.Spine, linkItem)
		} else {
			manifestStruct.Resources = append(manifestStruct.Resources, linkItem)
		}
	}

	manifestStruct.Metadata = metaStruct
	return manifestStruct
}
<commit_msg>begin better epub parser<commit_after>package parser

import (
	"fmt"
	"time"

	"github.com/feedbooks/epub"
	"github.com/feedbooks/webpub-streamer/models"
)

func init() {
	parserList = append(parserList, List{fileExt: "epub", parser: EpubParser})
}

// EpubParser TODO add doc
func EpubParser(filePath string, selfURL string) models.Publication {
	var manifestStruct models.Publication
	var metaStruct models.Metadata

	timeNow := time.Now()
	metaStruct.Modified = &timeNow
	manifestStruct.Links = make([]models.Link, 1)
	manifestStruct.Resources = make([]models.Link, 0)
	manifestStruct.Resources = make([]models.Link, 0)
	if selfURL != "" {
		self := models.Link{
			Rel:      []string{"self"},
			Href:     selfURL,
			TypeLink: "application/json",
		}
		manifestStruct.Links[0] = self
	}

	book, err := epub.Open(filePath)
	if err != nil {
		fmt.Println(err)
		return models.Publication{}
	}
	manifestStruct.Internal = append(manifestStruct.Internal, models.Internal{Name: "epub", Value: book.ZipReader()})
	manifestStruct.Internal = append(manifestStruct.Internal, models.Internal{Name: "rootfile", Value: book.Container.Rootfile.Path})

	metaStruct.Title = book.Opf.Metadata.Title[0]

	metaStruct.Language = book.Opf.Metadata.Language
	metaStruct.Identifier = book.Opf.Metadata.Identifier[0].Data
	if len(book.Opf.Metadata.Contributor) > 0 {
		for _, cont := range book.Opf.Metadata.Contributor {
			addContributor(&metaStruct, cont)
		}
	}
	if len(book.Opf.Metadata.Creator) > 0 {
		for _, cont := range book.Opf.Metadata.Creator {
			addContributor(&metaStruct, cont)
		}
	}

	for _, item := range book.Opf.Manifest {
		linkItem := models.Link{}
		linkItem.TypeLink = item.MediaType
		linkItem.Href = item.Href
		if linkItem.TypeLink == "application/xhtml+xml" {
			manifestStruct.Spine = append(manifestStruct.Spine, linkItem)
		} else {
			manifestStruct.Resources = append(manifestStruct.Resources, linkItem)
		}
	}

	manifestStruct.Metadata = metaStruct
	return manifestStruct
}

func addContributor(metadata *models.Metadata, cont epub.Author) {
	var aut models.Contributor

	aut.Name = cont.Data
	aut.Role = cont.Role
	metadata.Author = append(metadata.Author, aut)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"testing"
	"time"
)

var (
	timeout  = make(chan bool, 1)
	gcChan   = make(chan *gctrace, 1)
	scvgChan = make(chan *scvgtrace, 1)
)

func timeoutAfter(d time.Duration, t *testing.T) {
	time.Sleep(d)
	timeout <- true
}

func runParserWith(line string) {
	reader := bytes.NewReader([]byte(line))

	parser := Parser{
		reader:   reader,
		gcChan:   gcChan,
		scvgChan: scvgChan,
	}

	parser.Run()
}

func TestParserWithMatchingInput(t *testing.T) {
	go timeoutAfter(100*time.Millisecond, t)

	line := "gc76(1): 2+1+1390+1 us, 1 -> 3 MB, 16397 (1015746-999349) objects, 1436/1/0 sweeps, 0(0) handoff, 0(0) steal, 0/0/0 yields\n"
	ended := make(chan bool, 1)

	go func() {
		runParserWith(line)
		ended <- true
	}()

	expectedHeapSize := 3

	select {
	case gctrace := <-gcChan:
		if gctrace.Heap1 != expectedHeapSize {
			t.Errorf("Expected gctrace.Heap1 to equal %d. Got %d instead.", expectedHeapSize, gctrace.Heap1)
		}
	case <-ended:
		t.Errorf("Parser ran but our line didn't match.")
	case <-timeout:
		t.Fatalf("Execution timed out.")
	}
}

func TestParserGoRoutinesInput(t *testing.T) {
	t.Skip()
	go timeoutAfter(100*time.Millisecond, t)

	line := "gc76(1): 2+1+1390+1 us, 1 -> 3 MB, 16397 (1015746-999349) objects, 12 goroutines, 1436/1/0 sweeps, 0(0) handoff, 0(0) steal, 0/0/0 yields\n"
	ended := make(chan bool, 1)

	go func() {
		runParserWith(line)
		ended <- true
	}()

	expectedHeapSize := 3

	select {
	case gctrace := <-gcChan:
		if gctrace.Heap1 != expectedHeapSize {
			t.Errorf("Expected gctrace.Heap1 to equal %d. Got %d instead.", expectedHeapSize, gctrace.Heap1)
		}
	case <-ended:
		t.Errorf("Parser ran but our line didn't match.")
	case <-timeout:
		t.Fatalf("Execution timed out.")
	}
}

func TestParserNonMatchingInput(t *testing.T) {
	go timeoutAfter(100*time.Millisecond, t)

	line := "INFO: test"
	ended := make(chan bool, 1)

	go func() {
		runParserWith(line)
		ended <- true
	}()

	select {
	case <-gcChan:
		t.Fatalf("Unexpected trace result. This input should not trigger gcChan.")
	case <-scvgChan:
		t.Fatalf("Unexpected trace result. This input should not trigger scvgChan.")
	case <-ended:
		return
	case <-timeout:
		t.Fatalf("Execution timed out.")
	}
}
<commit_msg>Fix tests race issue<commit_after>package main

import (
	"bytes"
	"testing"
	"time"
)

var (
	timeout  = make(chan bool, 1)
	gcChan   = make(chan *gctrace, 1)
	scvgChan = make(chan *scvgtrace, 1)
)

func timeoutAfter(d time.Duration, t *testing.T) {
	time.Sleep(d)
	timeout <- true
}

func runParserWith(line string) {
	reader := bytes.NewReader([]byte(line))

	parser := Parser{
		reader:   reader,
		gcChan:   gcChan,
		scvgChan: scvgChan,
	}

	parser.Run()
}

func TestParserWithMatchingInput(t *testing.T) {
	go timeoutAfter(100*time.Millisecond, t)

	line := "gc76(1): 2+1+1390+1 us, 1 -> 3 MB, 16397 (1015746-999349) objects, 1436/1/0 sweeps, 0(0) handoff, 0(0) steal, 0/0/0 yields\n"

	go runParserWith(line)

	expectedHeapSize := 3

	select {
	case gctrace := <-gcChan:
		if gctrace.Heap1 != expectedHeapSize {
			t.Errorf("Expected gctrace.Heap1 to equal %d. Got %d instead.", expectedHeapSize, gctrace.Heap1)
		}
	case <-timeout:
		t.Fatalf("Execution timed out.")
	}
}

func TestParserGoRoutinesInput(t *testing.T) {
	t.Skip()
	go timeoutAfter(100*time.Millisecond, t)

	line := "gc76(1): 2+1+1390+1 us, 1 -> 3 MB, 16397 (1015746-999349) objects, 12 goroutines, 1436/1/0 sweeps, 0(0) handoff, 0(0) steal, 0/0/0 yields\n"

	go runParserWith(line)

	expectedHeapSize := 3

	select {
	case gctrace := <-gcChan:
		if gctrace.Heap1 != expectedHeapSize {
			t.Errorf("Expected gctrace.Heap1 to equal %d. Got %d instead.", expectedHeapSize, gctrace.Heap1)
		}
	case <-timeout:
		t.Fatalf("Execution timed out.")
	}
}

func TestParserNonMatchingInput(t *testing.T) {
	go timeoutAfter(100*time.Millisecond, t)

	line := "INFO: test"
	ended := make(chan bool, 1)

	go func() {
		runParserWith(line)
		ended <- true
	}()

	select {
	case <-gcChan:
		t.Fatalf("Unexpected trace result. This input should not trigger gcChan.")
	case <-scvgChan:
		t.Fatalf("Unexpected trace result. This input should not trigger scvgChan.")
	case <-ended:
		return
	case <-timeout:
		t.Fatalf("Execution timed out.")
	}
}
<|endoftext|>


<commit_before>package ini

import (
	"strings"
	"testing"
)

func assertIsSection(sectionName string, t *testing.T) {
	if !isSection(sectionName) {
		t.Errorf("%q is not a valid section name", sectionName)
	}
}

func assertIsNotSection(sectionName string, t *testing.T) {
	if isSection(sectionName) {
		t.Errorf("%q is a valid section name", sectionName)
	}
}

func expectLine(expectedLine, actualLine string, t *testing.T) {
	if actualLine != expectedLine {
		t.Errorf("expected line %q, got %q", actualLine, expectedLine)
	}
}

func expectProperty(expectedProperty, actualProperty string, t *testing.T) {
	if actualProperty != expectedProperty {
		errmsg := "expected property %q, got %q"
		t.Errorf(errmsg, expectedProperty, actualProperty)
	}
}

func expectValue(expectedValue, actualValue string, t *testing.T) {
	if actualValue != expectedValue {
		errmsg := "expected value %q, got %q"
		t.Errorf(errmsg, expectedValue, actualValue)
	}
}

func TestReadlineEmpty(t *testing.T) {
	linereader := newLineReader(strings.NewReader(""))
	line, err := linereader.ReadLine()
	assertErrorIsNil(err, t)
	expectLine("", line, t)
}

func TestReadlineNoNewline(t *testing.T) {
	linereader := newLineReader(strings.NewReader("line without nl"))
	line, err := linereader.ReadLine()
	assertErrorIsNil(err, t)
	expectLine("line without nl", line, t)
}

func TestReadline(t *testing.T) {
	reader := strings.NewReader("first line\nsecond line")
	linereader := newLineReader(reader)
	line, err := linereader.ReadLine()
	assertErrorIsNil(err, t)
	expectLine("first line\n", line, t)
}

func TestIsSectionEmptyString(t *testing.T) {
	assertIsNotSection("", t)
}

func TestIsSectionEmptySection(t *testing.T) {
	assertIsNotSection("[]", t)
}

func TestIsSectionOneLetterName(t *testing.T) {
	assertIsSection("[a]", t)
}

func TestIsSectionValid(t *testing.T) {
	assertIsSection("[validsection]", t)
}

func TestParseItemEmptyString(t *testing.T) {
	line := ""
	_, err := parseItem(line)
	assertErrorIsNotNil(err, t)
	if err != MissingEqualSignError {
		t.Errorf("expected MissingEqualSignError, got %v", err)
	}
}

func TestParseItemSimpleValid(t *testing.T) {
	line := "foo=bar"
	item, err := parseItem(line)
	assertErrorIsNil(err, t)
	expectProperty("foo", item.Property, t)
	expectValue("bar", item.Value, t)
}

func TestParseItemWithWhitespace(t *testing.T) {
	line := "foo  = 	bar"
	item, err := parseItem(line)
	assertErrorIsNil(err, t)
	expectProperty("foo", item.Property, t)
	expectValue("bar", item.Value, t)
}

func TestParseItemUnescapedEqualSign(t *testing.T) {
	line := "foo = bar = baz"
	_, err := parseItem(line)
	assertErrorIsNotNil(err, t)
	if err != TooManyEqualSignsError {
		t.Errorf("expected TooManyEqualSignsError, got %v", err)
	}
}

func TestParseItemWithEscapedEqualSign(t *testing.T) {
	line := "foo = bar \\= baz"
	item, err := parseItem(line)
	assertErrorIsNil(err, t)
	expectProperty("foo", item.Property, t)
	expectValue("bar \\= baz", item.Value, t)
}

// TODO: test parseItem with quoted values!

func TestParseINIEmpty(t *testing.T) {
	config, err := NewConfigFromString("")
	assertErrorIsNil(err, t)
	expectedConfig := make(Config)
	assertConfigMapsEqual(config, &expectedConfig, t)
}

func TestParseINIOneSection(t *testing.T) {
	config, err := NewConfigFromString("[section]")
	assertErrorIsNil(err, t)
	section := make(map[string]string)
	expectedConfig := &Config{"section": section}
	assertConfigMapsEqual(config, expectedConfig, t)
}

func TestParseINITwoSections(t *testing.T) {
	config, err := NewConfigFromString("[section one]\n[section two]")
	assertErrorIsNil(err, t)
	sectionOne := make(map[string]string)
	sectionTwo := make(map[string]string)
	expectedConfig := &Config{
		"section one": sectionOne,
		"section two": sectionTwo}
	assertConfigMapsEqual(config, expectedConfig, t)
}

func TestParseINISectionWithOneAssignment(t *testing.T) {
	config, err := NewConfigFromString("[section]\nproperty=value")
	assertErrorIsNil(err, t)
	expectedConfig := &Config{"section": {"property": "value"}}
	assertConfigMapsEqual(config, expectedConfig, t)
}

func TestParseINIAssignmentBeforeSection(t *testing.T) {
	_, err := NewConfigFromString("property=value\n[section]")
	assertErrorIsNotNil(err, t)
	if err != AssignmentOutsideSectionError {
		t.Errorf("expected AssignmentOutsideSectionError, got %v", err)
	}
}

func TestParseINIBrokenAssignment(t *testing.T) {
	_, err := NewConfigFromString("[section]\nproperty value")
	assertErrorIsNotNil(err, t)
	if err != MissingEqualSignError {
		t.Errorf("expected MissingEqualSignError, got %v", err)
	}
}

func TestConfigStringEmpty(t *testing.T) {
	stringedConfig := NewConfig().String()
	if expectedStr := ""; stringedConfig != expectedStr {
		t.Errorf("expected %q, got %q", expectedStr, stringedConfig)
	}
}

func TestConfigStringOneSection(t *testing.T) {
	c, err := NewConfigFromString("[section]")
	assertErrorIsNil(err, t)
	stringedConfig := c.String()
	if expectedStr := "[section]"; stringedConfig != expectedStr {
		t.Errorf("expected %q, got %q", expectedStr, stringedConfig)
	}
}

func TestStringSectionWithItem(t *testing.T) {
	c, err := NewConfigFromString("[section]\nfoo	=bar")
	assertErrorIsNil(err, t)
	expectedStr := "[section]\nfoo = bar"
	if stringedConfig := c.String(); stringedConfig != expectedStr {
		t.Errorf("expected %q, got %q", expectedStr, stringedConfig)
	}
}
<commit_msg>added example for documentation on how *Config.String() works<commit_after>package ini

import (
	"fmt"
	"strings"
	"testing"
)

func assertIsSection(sectionName string, t *testing.T) {
	if !isSection(sectionName) {
		t.Errorf("%q is not a valid section name", sectionName)
	}
}

func assertIsNotSection(sectionName string, t *testing.T) {
	if isSection(sectionName) {
		t.Errorf("%q is a valid section name", sectionName)
	}
}

func expectLine(expectedLine, actualLine string, t *testing.T) {
	if actualLine != expectedLine {
		t.Errorf("expected line %q, got %q", actualLine, expectedLine)
	}
}

func expectProperty(expectedProperty, actualProperty string, t *testing.T) {
	if actualProperty != expectedProperty {
		errmsg := "expected property %q, got %q"
		t.Errorf(errmsg, expectedProperty, actualProperty)
	}
}

func expectValue(expectedValue, actualValue string, t *testing.T) {
	if actualValue != expectedValue {
		errmsg := "expected value %q, got %q"
		t.Errorf(errmsg, expectedValue, actualValue)
	}
}

func TestReadlineEmpty(t *testing.T) {
	linereader := newLineReader(strings.NewReader(""))
	line, err := linereader.ReadLine()
	assertErrorIsNil(err, t)
	expectLine("", line, t)
}

func TestReadlineNoNewline(t *testing.T) {
	linereader := newLineReader(strings.NewReader("line without nl"))
	line, err := linereader.ReadLine()
	assertErrorIsNil(err, t)
	expectLine("line without nl", line, t)
}

func TestReadline(t *testing.T) {
	reader := strings.NewReader("first line\nsecond line")
	linereader := newLineReader(reader)
	line, err := linereader.ReadLine()
	assertErrorIsNil(err, t)
	expectLine("first line\n", line, t)
}

func TestIsSectionEmptyString(t *testing.T) {
	assertIsNotSection("", t)
}

func TestIsSectionEmptySection(t *testing.T) {
	assertIsNotSection("[]", t)
}

func TestIsSectionOneLetterName(t *testing.T) {
	assertIsSection("[a]", t)
}

func TestIsSectionValid(t *testing.T) {
	assertIsSection("[validsection]", t)
}

func TestParseItemEmptyString(t *testing.T) {
	line := ""
	_, err := parseItem(line)
	assertErrorIsNotNil(err, t)
	if err != MissingEqualSignError {
		t.Errorf("expected MissingEqualSignError, got %v", err)
	}
}

func TestParseItemSimpleValid(t *testing.T) {
	line := "foo=bar"
	item, err := parseItem(line)
	assertErrorIsNil(err, t)
	expectProperty("foo", item.Property, t)
	expectValue("bar", item.Value, t)
}

func TestParseItemWithWhitespace(t *testing.T) {
	line := "foo  = 	bar"
	item, err := parseItem(line)
	assertErrorIsNil(err, t)
	expectProperty("foo", item.Property, t)
	expectValue("bar", item.Value, t)
}

func TestParseItemUnescapedEqualSign(t *testing.T) {
	line := "foo = bar = baz"
	_, err := parseItem(line)
	assertErrorIsNotNil(err, t)
	if err != TooManyEqualSignsError {
		t.Errorf("expected TooManyEqualSignsError, got %v", err)
	}
}

func TestParseItemWithEscapedEqualSign(t *testing.T) {
	line := "foo = bar \\= baz"
	item, err := parseItem(line)
	assertErrorIsNil(err, t)
	expectProperty("foo", item.Property, t)
	expectValue("bar \\= baz", item.Value, t)
}

// TODO: test parseItem with quoted values!

func TestParseINIEmpty(t *testing.T) {
	config, err := NewConfigFromString("")
	assertErrorIsNil(err, t)
	expectedConfig := make(Config)
	assertConfigMapsEqual(config, &expectedConfig, t)
}

func TestParseINIOneSection(t *testing.T) {
	config, err := NewConfigFromString("[section]")
	assertErrorIsNil(err, t)
	section := make(map[string]string)
	expectedConfig := &Config{"section": section}
	assertConfigMapsEqual(config, expectedConfig, t)
}

func TestParseINITwoSections(t *testing.T) {
	config, err := NewConfigFromString("[section one]\n[section two]")
	assertErrorIsNil(err, t)
	sectionOne := make(map[string]string)
	sectionTwo := make(map[string]string)
	expectedConfig := &Config{
		"section one": sectionOne,
		"section two": sectionTwo}
	assertConfigMapsEqual(config, expectedConfig, t)
}

func TestParseINISectionWithOneAssignment(t *testing.T) {
	config, err := NewConfigFromString("[section]\nproperty=value")
	assertErrorIsNil(err, t)
	expectedConfig := &Config{"section": {"property": "value"}}
	assertConfigMapsEqual(config, expectedConfig, t)
}

func TestParseINIAssignmentBeforeSection(t *testing.T) {
	_, err := NewConfigFromString("property=value\n[section]")
	assertErrorIsNotNil(err, t)
	if err != AssignmentOutsideSectionError {
		t.Errorf("expected AssignmentOutsideSectionError, got %v", err)
	}
}

func TestParseINIBrokenAssignment(t *testing.T) {
	_, err := NewConfigFromString("[section]\nproperty value")
	assertErrorIsNotNil(err, t)
	if err != MissingEqualSignError {
		t.Errorf("expected MissingEqualSignError, got %v", err)
	}
}

func TestConfigStringEmpty(t *testing.T) {
	stringedConfig := NewConfig().String()
	if expectedStr := ""; stringedConfig != expectedStr {
		t.Errorf("expected %q, got %q", expectedStr, stringedConfig)
	}
}

func TestConfigStringOneSection(t *testing.T) {
	c, err := NewConfigFromString("[section]")
	assertErrorIsNil(err, t)
	stringedConfig := c.String()
	if expectedStr := "[section]"; stringedConfig != expectedStr {
		t.Errorf("expected %q, got %q", expectedStr, stringedConfig)
	}
}

func TestStringSectionWithItem(t *testing.T) {
	c, err := NewConfigFromString("[section]\nfoo	=bar")
	assertErrorIsNil(err, t)
	expectedStr := "[section]\nfoo = bar"
	if stringedConfig := c.String(); stringedConfig != expectedStr {
		t.Errorf("expected %q, got %q", expectedStr, stringedConfig)
	}
}

func ExampleConfig_String() {
	conf, _ := NewConfigFromString("[section]\n\tfoo 	\t	= bar  	")
	fmt.Println(conf)
	// Output:
	// [section]
	// foo = bar
}
<|endoftext|>


<commit_before>// Copyright (c) 2011 CZ.NIC z.s.p.o. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// blame: jnml, labs.nic.cz

package dns

// Pull test dependencies too.
// Enables easy 'go test X' after 'go get X'
import (
	"github.com/cznic/mathutil"
)
<commit_msg>dns: Fix test_deps.go<commit_after>// Copyright (c) 2011 CZ.NIC z.s.p.o. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// blame: jnml, labs.nic.cz

package dns

// Pull test dependencies too.
// Enables easy 'go test X' after 'go get X'
import (
	_ "github.com/cznic/mathutil"
)
<|endoftext|>


<commit_before>package lexer

type Lexer struct {
	input        string
	position     int  // curr pos in input(points to current char)
	readPosition int  // after current char
	ch           byte // char we are working with now
}

func New(input string) *Lexer {
	l := &Lexer{input: input}
	return l
}
<commit_msg>add readchar method to lexer struct<commit_after>package lexer

type Lexer struct {
	input        string
	position     int  // curr pos in input(points to current char)
	readPosition int  // after current char
	ch           byte // char we are working with now
}

func New(input string) *Lexer {
	l := &Lexer{input: input}
	return l
}

func (l *Lexer) readChar() {
	if l.readPosition >= len(l.input) {
		l.ch = 0
	} else {
		l.ch = l.input[l.readPosition]
	}

	l.position = l.readPosition
	l.readPosition += 1
}
<|endoftext|>


<commit_before>// Package tiff implements TIFF decoding as defined in TIFF 6.0 specification.
package tiff

import (
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"math"
	"math/big"
)

var fmtSize = map[uint16]uint32{
	1:  1,
	2:  1,
	3:  2,
	4:  4,
	5:  8,
	6:  1,
	7:  1,
	8:  2,
	9:  4,
	10: 8,
	11: 4,
	12: 8,
}

// ReadAtReader is used when decoding Tiff tags and directories
type ReadAtReader interface {
	io.Reader
	io.ReaderAt
}

// Tiff provides access to decoded tiff data.
type Tiff struct {
	// Dirs is an ordered slice of the tiff's Image File Directories (IFDs).
	// The IFD at index 0 is IFD0.
	Dirs []*Dir
	// The tiff's byte-encoding (i.e. big/little endian).
	Order binary.ByteOrder
}

// Decode parses tiff-encoded data from r and returns a Tiff that reflects the
// structure and content of the tiff data. The first read from r should be the
// first byte of the tiff-encoded data (not necessarily the first byte of an
// os.File object).
func Decode(r io.Reader) (*Tiff, error) {
	data, err := ioutil.ReadAll(r)
	if err != nil {
		return nil, errors.New("tiff: could not read data")
	}
	buf := bytes.NewReader(data)

	t := new(Tiff)

	// read byte order
	bo := make([]byte, 2)
	n, err := buf.Read(bo)
	if n < len(bo) || err != nil {
		return nil, errors.New("tiff: could not read tiff byte order")
	} else {
		if string(bo) == "II" {
			t.Order = binary.LittleEndian
		} else if string(bo) == "MM" {
			t.Order = binary.BigEndian
		} else {
			return nil, errors.New("tiff: could not read tiff byte order")
		}
	}

	// check for special tiff marker
	var sp int16
	err = binary.Read(buf, t.Order, &sp)
	if err != nil || 0x002A != sp {
		return nil, errors.New("tiff: could not find special tiff marker")
	}

	// load offset to first IFD
	var offset int32
	err = binary.Read(buf, t.Order, &offset)
	if err != nil {
		return nil, errors.New("tiff: could not read offset to first IFD")
	}

	// load IFD's
	var d *Dir
	for offset != 0 {
		// seek to offset
		_, err := buf.Seek(int64(offset), 0)
		if err != nil {
			return nil, errors.New("tiff: seek to IFD failed")
		}

		if buf.Len() == 0 {
			return nil, errors.New("tiff: seek offset after EOF")
		}

		// load the dir
		d, offset, err = DecodeDir(buf, t.Order)
		if err != nil {
			return nil, err
		}
		t.Dirs = append(t.Dirs, d)
	}

	return t, nil
}

func (tf *Tiff) String() string {
	s := "Tiff{"
	for _, d := range tf.Dirs {
		s += d.String() + ", "
	}
	return s + "}"
}

// Dir reflects the parsed content of a tiff Image File Directory (IFD).
type Dir struct {
	Tags []*Tag
}

// DecodeDir parses a tiff-encoded IFD from r and returns a Dir object.  offset
// is the offset to the next IFD.  The first read from r should be at the first
// byte of the IFD. ReadAt offsets should be relative to the beginning of the
// tiff structure (not relative to the beginning of the IFD).
func DecodeDir(r ReadAtReader, order binary.ByteOrder) (d *Dir, offset int32, err error) {
	d = new(Dir)

	// get num of tags in ifd
	var nTags int16
	err = binary.Read(r, order, &nTags)
	if err != nil {
		return nil, 0, errors.New("tiff: falied to read IFD tag count: " + err.Error())
	}

	// load tags
	for n := 0; n < int(nTags); n++ {
		t, err := DecodeTag(r, order)
		if err != nil {
			return nil, 0, err
		}
		d.Tags = append(d.Tags, t)
	}

	// get offset to next ifd
	err = binary.Read(r, order, &offset)
	if err != nil {
		return nil, 0, errors.New("tiff: falied to read offset to next IFD: " + err.Error())
	}

	return d, offset, nil
}

func (d *Dir) String() string {
	s := "Dir{"
	for _, t := range d.Tags {
		s += t.String() + ", "
	}
	return s + "}"
}

// Tag reflects the parsed content of a tiff IFD tag.
type Tag struct {
	// Id is the 2-byte tiff tag identifier
	Id uint16
	// Fmt is an integer (1 through 12) indicating the tag value's format.
	Fmt uint16
	// Ncomp is the number of type Fmt stored in the tag's value (i.e. the tag's
	// value is an array of type Fmt and length Ncomp).
	Ncomp uint32
	// Val holds the bytes that represent the tag's value.
	Val []byte
}

// DecodeTag parses a tiff-encoded IFD tag from r and returns Tag object. The
// first read from r should be the first byte of the tag. ReadAt offsets should
// be relative to the beginning of the tiff structure (not relative to the
// beginning of the tag).
func DecodeTag(r ReadAtReader, order binary.ByteOrder) (*Tag, error) {
	t := new(Tag)

	err := binary.Read(r, order, &t.Id)
	if err != nil {
		return nil, errors.New("tiff: tag id read failed: " + err.Error())
	}

	err = binary.Read(r, order, &t.Fmt)
	if err != nil {
		return nil, errors.New("tiff: tag format read failed: " + err.Error())
	}

	err = binary.Read(r, order, &t.Ncomp)
	if err != nil {
		return nil, errors.New("tiff: tag component count read failed: " + err.Error())
	}

	var offset uint32
	err = binary.Read(r, order, &offset)
	if err != nil {
		return nil, errors.New("tiff: tag offset read failed: " + err.Error())
	}

	valLen := fmtSize[t.Fmt] * t.Ncomp
	if valLen > 4 {
		t.Val = make([]byte, valLen)
		n, err := r.ReadAt(t.Val, int64(offset))
		if n != int(valLen) || err != nil {
			return nil, errors.New("tiff: tag value read failed: " + err.Error())
		}
	} else {
		t.Val = make([]byte, 8)
		binary.PutUvarint(t.Val, uint64(offset))
	}

	return t, nil
}

// Rat returns the tag's i'th value as a rational number. It panics if the tag format
// is not rational, if the denominator is zero, or if the tag has no i'th
// component. If a denominator is zero, use Rat2.
func (t *Tag) Rat(i int) *big.Rat {
	n, d := t.Rat2(i)
	return big.NewRat(n, d)
}

// Rat2 returns the tag's i'th value as a rational number represented by a
// numerator-denominator pair. It panics if the tag format is not rational
// or if the tag value has no i'th component.
func (t *Tag) Rat2(i int) (int64, int64) {
	start := i * int(fmtSize[t.Fmt])
	middle := start + 4
	end := middle + 4
	if t.Fmt == 10 {
		num, _ := binary.Varint(t.Val[start:middle])
		den, _ := binary.Varint(t.Val[middle:end])
		return num, den
	} else if t.Fmt == 5 {
		num, _ := binary.Uvarint(t.Val[start:middle])
		den, _ := binary.Uvarint(t.Val[middle:end])
		return int64(num), int64(den)
	} else {
		panic("Tag format is not 'rational'")
	}
	return 0, 0
}

// Int returns the tag's i'th value as an integer. It panics if the tag format is not
// an integer or if the tag value has no i'th component.
func (t *Tag) Int(i int) int64 {
	start := i * int(fmtSize[t.Fmt])
	var u int64
	switch t.Fmt {
	case 1:
		v, _ := binary.Uvarint(t.Val[start : start+1])
		u = int64(v)
	case 3:
		v, _ := binary.Uvarint(t.Val[start : start+2])
		u = int64(v)
	case 4:
		v, _ := binary.Uvarint(t.Val[start : start+4])
		u = int64(v)
	case 6:
		u, _ = binary.Varint(t.Val[start : start+1])
	case 8:
		u, _ = binary.Varint(t.Val[start : start+2])
	case 9:
		u, _ = binary.Varint(t.Val[start : start+4])
	default:
		panic("Tag format is not 'int'")
	}
	return u
}

// Float returns the tag's i'th value as a float. It panics if the tag format is not
// a float or if the tag value has no i'th component.
func (t *Tag) Float(i int) float64 {
	start := i * int(fmtSize[t.Fmt])
	if t.Fmt != 11 && t.Fmt != 12 {
		panic("Tag format is not 'float'")
	}
	uintVal, _ := binary.Uvarint(t.Val[start : start+4])
	return math.Float64frombits(uintVal)
}

// StringVal returns the tag's value as a string. It panics if the tag format is not
// an ascii string.
func (t *Tag) StringVal() string {
	if t.Fmt != 2 {
		panic("Tag format is not 'ascii string'")
	}
	return string(t.Val)
}

// String returns a nicely formatted version of the tag.
func (t *Tag) String() string {
	msg := fmt.Sprintf("Tag{Id=%X, Val=[", t.Id)
	switch t.Fmt {
	case 2:
		msg += string(t.Val)
	case 1, 3, 4, 6, 8, 9:
		for i := 0; i < int(t.Ncomp); i++ {
			msg += fmt.Sprint(t.Int(i), ", ")
		}
	case 5, 10:
		for i := 0; i < int(t.Ncomp); i++ {
			n, d := t.Rat2(i)
			msg += fmt.Sprintf("%v/%v, ", n, d)
		}
	case 7:
		msg += string(t.Val)
	case 11, 12:
		for i := 0; i < int(t.Ncomp); i++ {
			msg += fmt.Sprint(t.Float(i), ", ")
		}
	}
	return msg + "]}"
}
<commit_msg>fixes #1 - thanks imarko<commit_after>// Package tiff implements TIFF decoding as defined in TIFF 6.0 specification.
package tiff

import (
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"math"
	"math/big"
)

var fmtSize = map[uint16]uint32{
	1:  1,
	2:  1,
	3:  2,
	4:  4,
	5:  8,
	6:  1,
	7:  1,
	8:  2,
	9:  4,
	10: 8,
	11: 4,
	12: 8,
}

// ReadAtReader is used when decoding Tiff tags and directories
type ReadAtReader interface {
	io.Reader
	io.ReaderAt
}

// Tiff provides access to decoded tiff data.
type Tiff struct {
	// Dirs is an ordered slice of the tiff's Image File Directories (IFDs).
	// The IFD at index 0 is IFD0.
	Dirs []*Dir
	// The tiff's byte-encoding (i.e. big/little endian).
	Order binary.ByteOrder
}

// Decode parses tiff-encoded data from r and returns a Tiff that reflects the
// structure and content of the tiff data. The first read from r should be the
// first byte of the tiff-encoded data (not necessarily the first byte of an
// os.File object).
func Decode(r io.Reader) (*Tiff, error) {
	data, err := ioutil.ReadAll(r)
	if err != nil {
		return nil, errors.New("tiff: could not read data")
	}
	buf := bytes.NewReader(data)

	t := new(Tiff)

	// read byte order
	bo := make([]byte, 2)
	n, err := buf.Read(bo)
	if n < len(bo) || err != nil {
		return nil, errors.New("tiff: could not read tiff byte order")
	} else {
		if string(bo) == "II" {
			t.Order = binary.LittleEndian
		} else if string(bo) == "MM" {
			t.Order = binary.BigEndian
		} else {
			return nil, errors.New("tiff: could not read tiff byte order")
		}
	}

	// check for special tiff marker
	var sp int16
	err = binary.Read(buf, t.Order, &sp)
	if err != nil || 0x002A != sp {
		return nil, errors.New("tiff: could not find special tiff marker")
	}

	// load offset to first IFD
	var offset int32
	err = binary.Read(buf, t.Order, &offset)
	if err != nil {
		return nil, errors.New("tiff: could not read offset to first IFD")
	}

	// load IFD's
	var d *Dir
	for offset != 0 {
		// seek to offset
		_, err := buf.Seek(int64(offset), 0)
		if err != nil {
			return nil, errors.New("tiff: seek to IFD failed")
		}

		if buf.Len() == 0 {
			return nil, errors.New("tiff: seek offset after EOF")
		}

		// load the dir
		d, offset, err = DecodeDir(buf, t.Order)
		if err != nil {
			return nil, err
		}
		t.Dirs = append(t.Dirs, d)
	}

	return t, nil
}

func (tf *Tiff) String() string {
	s := "Tiff{"
	for _, d := range tf.Dirs {
		s += d.String() + ", "
	}
	return s + "}"
}

// Dir reflects the parsed content of a tiff Image File Directory (IFD).
type Dir struct {
	Tags []*Tag
}

// DecodeDir parses a tiff-encoded IFD from r and returns a Dir object.  offset
// is the offset to the next IFD.  The first read from r should be at the first
// byte of the IFD. ReadAt offsets should be relative to the beginning of the
// tiff structure (not relative to the beginning of the IFD).
func DecodeDir(r ReadAtReader, order binary.ByteOrder) (d *Dir, offset int32, err error) {
	d = new(Dir)

	// get num of tags in ifd
	var nTags int16
	err = binary.Read(r, order, &nTags)
	if err != nil {
		return nil, 0, errors.New("tiff: falied to read IFD tag count: " + err.Error())
	}

	// load tags
	for n := 0; n < int(nTags); n++ {
		t, err := DecodeTag(r, order)
		if err != nil {
			return nil, 0, err
		}
		d.Tags = append(d.Tags, t)
	}

	// get offset to next ifd
	err = binary.Read(r, order, &offset)
	if err != nil {
		return nil, 0, errors.New("tiff: falied to read offset to next IFD: " + err.Error())
	}

	return d, offset, nil
}

func (d *Dir) String() string {
	s := "Dir{"
	for _, t := range d.Tags {
		s += t.String() + ", "
	}
	return s + "}"
}

// Tag reflects the parsed content of a tiff IFD tag.
type Tag struct {
	// Id is the 2-byte tiff tag identifier
	Id uint16
	// Fmt is an integer (1 through 12) indicating the tag value's format.
	Fmt uint16
	// Ncomp is the number of type Fmt stored in the tag's value (i.e. the tag's
	// value is an array of type Fmt and length Ncomp).
	Ncomp uint32
	// Val holds the bytes that represent the tag's value.
	Val []byte

  order binary.ByteOrder
}

// DecodeTag parses a tiff-encoded IFD tag from r and returns Tag object. The
// first read from r should be the first byte of the tag. ReadAt offsets should
// be relative to the beginning of the tiff structure (not relative to the
// beginning of the tag).
func DecodeTag(r ReadAtReader, order binary.ByteOrder) (*Tag, error) {
	t := new(Tag)
  t.order = order

	err := binary.Read(r, order, &t.Id)
	if err != nil {
		return nil, errors.New("tiff: tag id read failed: " + err.Error())
	}

	err = binary.Read(r, order, &t.Fmt)
	if err != nil {
		return nil, errors.New("tiff: tag format read failed: " + err.Error())
	}

	err = binary.Read(r, order, &t.Ncomp)
	if err != nil {
		return nil, errors.New("tiff: tag component count read failed: " + err.Error())
	}

	var offset uint32
	err = binary.Read(r, order, &offset)
	if err != nil {
		return nil, errors.New("tiff: tag offset read failed: " + err.Error())
	}

	valLen := fmtSize[t.Fmt] * t.Ncomp
	if valLen > 4 {
		t.Val = make([]byte, valLen)
		n, err := r.ReadAt(t.Val, int64(offset))
		if n != int(valLen) || err != nil {
			return nil, errors.New("tiff: tag value read failed: " + err.Error())
		}
	} else {
		t.Val = make([]byte, 8)
		binary.PutUvarint(t.Val, uint64(offset))
	}

	return t, nil
}

// Rat returns the tag's i'th value as a rational number. It panics if the tag format
// is not rational, if the denominator is zero, or if the tag has no i'th
// component. If a denominator is zero, use Rat2.
func (t *Tag) Rat(i int) *big.Rat {
	n, d := t.Rat2(i)
	return big.NewRat(n, d)
}

// Rat2 returns the tag's i'th value as a rational number represented by a
// numerator-denominator pair. It panics if the tag format is not rational
// or if the tag value has no i'th component.
func (t *Tag) Rat2(i int) (num, den int64) {
	start := i * int(fmtSize[t.Fmt])
	end := start + 8

  r := bytes.NewReader(t.Val[start:end])

	if t.Fmt == 10 {
    var n, d int32
    err := binary.Read(r, t.order, &n)
    if err != nil {
      panic(err.Error())
    }
    err = binary.Read(r, t.order, &d)
    if err != nil {
      panic(err.Error())
    }
    return int64(n), int64(d)
	} else if t.Fmt == 5 {
    var n, d uint32
    err := binary.Read(r, t.order, &n)
    if err != nil {
      panic(err.Error())
    }
    err = binary.Read(r, t.order, &d)
    if err != nil {
      panic(err.Error())
    }
    return int64(n), int64(d)
	} else {
		panic("Tag format is not 'rational'")
	}
	return 0, 0
}

// Int returns the tag's i'th value as an integer. It panics if the tag format is not
// an integer or if the tag value has no i'th component.
func (t *Tag) Int(i int) int64 {
	start := i * int(fmtSize[t.Fmt])
	var u int64
	switch t.Fmt {
	case 1:
		v, _ := binary.Uvarint(t.Val[start : start+1])
		u = int64(v)
	case 3:
		v, _ := binary.Uvarint(t.Val[start : start+2])
		u = int64(v)
	case 4:
		v, _ := binary.Uvarint(t.Val[start : start+4])
		u = int64(v)
	case 6:
		u, _ = binary.Varint(t.Val[start : start+1])
	case 8:
		u, _ = binary.Varint(t.Val[start : start+2])
	case 9:
		u, _ = binary.Varint(t.Val[start : start+4])
	default:
		panic("Tag format is not 'int'")
	}
	return u
}

// Float returns the tag's i'th value as a float. It panics if the tag format is not
// a float or if the tag value has no i'th component.
func (t *Tag) Float(i int) float64 {
	start := i * int(fmtSize[t.Fmt])
	if t.Fmt != 11 && t.Fmt != 12 {
		panic("Tag format is not 'float'")
	}
	uintVal, _ := binary.Uvarint(t.Val[start : start+4])
	return math.Float64frombits(uintVal)
}

// StringVal returns the tag's value as a string. It panics if the tag format is not
// an ascii string.
func (t *Tag) StringVal() string {
	if t.Fmt != 2 {
		panic("Tag format is not 'ascii string'")
	}
	return string(t.Val)
}

// String returns a nicely formatted version of the tag.
func (t *Tag) String() string {
	msg := fmt.Sprintf("Tag{Id=%X, Val=[", t.Id)
	switch t.Fmt {
	case 2:
		msg += string(t.Val)
	case 1, 3, 4, 6, 8, 9:
		for i := 0; i < int(t.Ncomp); i++ {
			msg += fmt.Sprint(t.Int(i), ", ")
		}
	case 5, 10:
		for i := 0; i < int(t.Ncomp); i++ {
			n, d := t.Rat2(i)
			msg += fmt.Sprintf("%v/%v, ", n, d)
		}
	case 7:
		msg += string(t.Val)
	case 11, 12:
		for i := 0; i < int(t.Ncomp); i++ {
			msg += fmt.Sprint(t.Float(i), ", ")
		}
	}
	return msg + "]}"
}
<|endoftext|>


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

package client

import (
	"strings"
	"sync"

	"v.io/v23/context"
	"v.io/v23/syncbase"
	"v.io/x/ref/services/syncbase/longevity_tests/model"
)

// Noop is a client that creates any databases, collections, and syncgroups in
// the model, and then does nothing.
type Noop struct {
	// Map of databases and their respective collections.
	dbColMap map[syncbase.Database][]syncbase.Collection

	err error
	wg  sync.WaitGroup
}

var _ Client = (*Noop)(nil)

func (noop *Noop) String() string {
	dbNames := []string{}
	for db := range noop.dbColMap {
		dbNames = append(dbNames, db.Id().Name)
	}
	return strings.Join(append([]string{"Noop"}, dbNames...), "-")
}

func (noop *Noop) Start(ctx *context.T, sbName string, dbModels model.DatabaseSet) {
	noop.wg.Add(1)
	go func() {
		defer noop.wg.Done()
		var err error
		noop.dbColMap, _, err = CreateDbsAndCollections(ctx, sbName, dbModels)
		noop.setError(err)
	}()
}

func (noop *Noop) Stop() error {
	noop.wg.Wait()
	return noop.err
}

func (noop *Noop) setError(err error) {
	if err != nil && noop.err == nil {
		noop.err = err
	}
}
<commit_msg>longevity tests: Small cleanup from v.io/c/21879l<commit_after>// Copyright 2016 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package client

import (
	"strings"
	"sync"

	"v.io/v23/context"
	"v.io/v23/syncbase"
	"v.io/x/ref/services/syncbase/longevity_tests/model"
)

// Noop is a client that creates any databases, collections, and syncgroups in
// the model, and then does nothing.
type Noop struct {
	// Map of databases and their respective collections.
	dbColMap map[syncbase.Database][]syncbase.Collection

	err error
	wg  sync.WaitGroup
}

var _ Client = (*Noop)(nil)

func (noop *Noop) String() string {
	dbNames := []string{}
	for db := range noop.dbColMap {
		dbNames = append(dbNames, db.Id().Name)
	}
	return strings.Join(append([]string{"Noop"}, dbNames...), "-")
}

func (noop *Noop) Start(ctx *context.T, sbName string, dbModels model.DatabaseSet) {
	noop.wg.Add(1)
	go func() {
		defer noop.wg.Done()
		noop.dbColMap, _, noop.err = CreateDbsAndCollections(ctx, sbName, dbModels)
	}()
}

func (noop *Noop) Stop() error {
	noop.wg.Wait()
	return noop.err
}
<|endoftext|>


<commit_before>// See LICENSE.txt for licensing information.

package perlin

import (
	"fmt"
	"testing"
)

var (
	g = NewGenerator(2, 2, 1, 100)
)

func TestNoise1D(t *testing.T) {
	noise := g.Noise1D(0.2)
	if noise < -1 || noise > 1 {
		t.Errorf("Unexpected noise")
	}
}

func TestNoise2D(t *testing.T) {
	noise := g.Noise2D(0.2, 0.2)
	if noise < -1 || noise > 1 {
		t.Errorf("Unexpected noise")
	}
}

func TestNoise3D(t *testing.T) {
	noise := g.Noise3D(0.2, 0.2, 0.2)
	if noise < -1 || noise > 1 {
		t.Errorf("Unexpected noise")
	}
}

func TestTwoGenerators(t *testing.T) {
	g2 := NewGenerator(2, 2, 1, 41)
	val := g.Noise1D(0.2)
	val2 := g2.Noise1D(0.2)
	if val == val2 {
		t.Errorf("Same value for Noise1D")
	}
	val = g.Noise2D(0.12, 0.48)
	val2 = g2.Noise2D(0.12, 0.48)
	if val == val2 {
		t.Errorf("Same value for Noise2D")
	}
	val = g.Noise3D(0.19, 9.32, 0.1233)
	val2 = g2.Noise3D(0.19, 0.32, 0.1233)
	if val == val2 {
		t.Errorf("Same value for Noise3D")
	}
}

func TestDeterministicOutput(t *testing.T) {
	val := g.Noise2D(0.412, 0.931)
	val2 := g.Noise2D(0.412, 0.931)
	if val != val2 {
		t.Errorf("Non-deterministic output: %v != %v", val, val2)
	}
}

func TestLowZNoise3D(t *testing.T) {
	val := g.Noise3D(0.23, 0.23, 0.0000012)
	val2 := g.Noise2D(0.23, 0.23)
	if val != val2 {
		t.Errorf("Noise3D mismatches Noise2D at near-zero Z: %v != %v", val, val2)
	}
}

func ExampleGenerator_Noise1D() {
	g1 := NewGenerator(2, 2, 1, 41)
	g2 := NewGenerator(2, 2, 1, 4231)
	fmt.Printf("g1 noise at 0.1, 0.2 = %f\n", g1.Noise2D(0.1, 0.2))
	fmt.Printf("g2 noise at 0.1, 0.2 = %f\n", g2.Noise2D(0.1, 0.2))
	// Output:
	// g1 noise at 0.1, 0.2 = -0.125053
	// g2 noise at 0.1, 0.2 = 0.182675
}

func BenchmarkNoise1D(b *testing.B) {
	step := 1.0 / float64(b.N)
	for i := float64(0); i < 1.0; i += step {
		g.Noise1D(i)
	}
}

func BenchmarkNoise2D(b *testing.B) {
	step := 1.0 / float64(b.N)
	for i := float64(0); i < 1.0; i += step {
		g.Noise2D(i, i)
	}
}

func BenchmarkNoise3D(b *testing.B) {
	step := 1.0 / float64(b.N)
	for i := float64(0); i < 1.0; i += step {
		g.Noise3D(i, i, i)
	}
}
<commit_msg>Fix example code<commit_after>// See LICENSE.txt for licensing information.

package perlin

import (
	"fmt"
	"testing"
)

var (
	g = NewGenerator(2, 2, 1, 100)
)

func TestNoise1D(t *testing.T) {
	noise := g.Noise1D(0.2)
	if noise < -1 || noise > 1 {
		t.Errorf("Unexpected noise")
	}
}

func TestNoise2D(t *testing.T) {
	noise := g.Noise2D(0.2, 0.2)
	if noise < -1 || noise > 1 {
		t.Errorf("Unexpected noise")
	}
}

func TestNoise3D(t *testing.T) {
	noise := g.Noise3D(0.2, 0.2, 0.2)
	if noise < -1 || noise > 1 {
		t.Errorf("Unexpected noise")
	}
}

func TestTwoGenerators(t *testing.T) {
	g2 := NewGenerator(2, 2, 1, 41)
	val := g.Noise1D(0.2)
	val2 := g2.Noise1D(0.2)
	if val == val2 {
		t.Errorf("Same value for Noise1D")
	}
	val = g.Noise2D(0.12, 0.48)
	val2 = g2.Noise2D(0.12, 0.48)
	if val == val2 {
		t.Errorf("Same value for Noise2D")
	}
	val = g.Noise3D(0.19, 9.32, 0.1233)
	val2 = g2.Noise3D(0.19, 0.32, 0.1233)
	if val == val2 {
		t.Errorf("Same value for Noise3D")
	}
}

func TestDeterministicOutput(t *testing.T) {
	val := g.Noise2D(0.412, 0.931)
	val2 := g.Noise2D(0.412, 0.931)
	if val != val2 {
		t.Errorf("Non-deterministic output: %v != %v", val, val2)
	}
}

func TestLowZNoise3D(t *testing.T) {
	val := g.Noise3D(0.23, 0.23, 0.0000012)
	val2 := g.Noise2D(0.23, 0.23)
	if val != val2 {
		t.Errorf("Noise3D mismatches Noise2D at near-zero Z: %v != %v", val, val2)
	}
}

func ExampleGenerator_Noise2D() {
	g1 := NewGenerator(2, 2, 1, 41)
	g2 := NewGenerator(2, 2, 1, 4231)
	fmt.Printf("g1 noise at 0.1, 0.2 = %f\n", g1.Noise2D(0.1, 0.2))
	fmt.Printf("g2 noise at 0.1, 0.2 = %f\n", g2.Noise2D(0.1, 0.2))
	// Output:
	// g1 noise at 0.1, 0.2 = -0.125053
	// g2 noise at 0.1, 0.2 = 0.182675
}

func BenchmarkNoise1D(b *testing.B) {
	step := 1.0 / float64(b.N)
	for i := float64(0); i < 1.0; i += step {
		g.Noise1D(i)
	}
}

func BenchmarkNoise2D(b *testing.B) {
	step := 1.0 / float64(b.N)
	for i := float64(0); i < 1.0; i += step {
		g.Noise2D(i, i)
	}
}

func BenchmarkNoise3D(b *testing.B) {
	step := 1.0 / float64(b.N)
	for i := float64(0); i < 1.0; i += step {
		g.Noise3D(i, i, i)
	}
}
<|endoftext|>


<commit_before>package p2p

import (
	"bytes"
	"fmt"
	"math/rand"
	"reflect"
	"time"

	wire "github.com/tendermint/go-wire"
)

const (
	// PexChannel is a channel for PEX messages
	PexChannel = byte(0x00)

	// period to ensure peers connected
	defaultEnsurePeersPeriod = 30 * time.Second
	minNumOutboundPeers      = 10
	maxPexMessageSize        = 1048576 // 1MB

	// maximum messages one peer can send to us during `msgCountByPeerFlushInterval`
	defaultMaxMsgCountByPeer    = 1000
	msgCountByPeerFlushInterval = 1 * time.Hour
)

// PEXReactor handles PEX (peer exchange) and ensures that an
// adequate number of peers are connected to the switch.
//
// It uses `AddrBook` (address book) to store `NetAddress`es of the peers.
//
// ## Preventing abuse
//
// For now, it just limits the number of messages from one peer to
// `defaultMaxMsgCountByPeer` messages per `msgCountByPeerFlushInterval` (1000
// msg/hour).
//
// NOTE [2017-01-17]:
//   Limiting is fine for now. Maybe down the road we want to keep track of the
//   quality of peer messages so if peerA keeps telling us about peers we can't
//   connect to then maybe we should care less about peerA. But I don't think
//   that kind of complexity is priority right now.
type PEXReactor struct {
	BaseReactor

	sw                *Switch
	book              *AddrBook
	ensurePeersPeriod time.Duration

	// tracks message count by peer, so we can prevent abuse
	msgCountByPeer    map[string]uint16
	maxMsgCountByPeer uint16
}

// NewPEXReactor creates new PEX reactor.
func NewPEXReactor(b *AddrBook) *PEXReactor {
	r := &PEXReactor{
		book:              b,
		ensurePeersPeriod: defaultEnsurePeersPeriod,
		msgCountByPeer:    make(map[string]uint16),
		maxMsgCountByPeer: defaultMaxMsgCountByPeer,
	}
	r.BaseReactor = *NewBaseReactor(log, "PEXReactor", r)
	return r
}

// OnStart implements BaseService
func (r *PEXReactor) OnStart() error {
	r.BaseReactor.OnStart()
	r.book.Start()
	go r.ensurePeersRoutine()
	go r.flushMsgCountByPeer()
	return nil
}

// OnStop implements BaseService
func (r *PEXReactor) OnStop() {
	r.BaseReactor.OnStop()
	r.book.Stop()
}

// GetChannels implements Reactor
func (r *PEXReactor) GetChannels() []*ChannelDescriptor {
	return []*ChannelDescriptor{
		&ChannelDescriptor{
			ID:                PexChannel,
			Priority:          1,
			SendQueueCapacity: 10,
		},
	}
}

// AddPeer implements Reactor by adding peer to the address book (if inbound)
// or by requesting more addresses (if outbound).
func (r *PEXReactor) AddPeer(p *Peer) {
	if p.IsOutbound() { // For outbound peers, the address is already in the books
		if r.book.NeedMoreAddrs() {
			r.RequestPEX(p)
		}
	} else { // For inbound connections, the peer is its own source
		addr, err := NewNetAddressString(p.ListenAddr)
		if err != nil {
			// this should never happen
			log.Error("Error in AddPeer: invalid peer address", "addr", p.ListenAddr, "error", err)
			return
		}
		r.book.AddAddress(addr, addr)
	}
}

// RemovePeer implements Reactor by removing peer from the address book.
//
// The peer will be proposed to us by other peers (PexAddrsMessage) or himself
// and we will add him again upon successful connection. Note that other peers
// will remove him too. The peer will need to send first requests to others by
// himself (he will have an addrbook or the seeds).
func (r *PEXReactor) RemovePeer(p *Peer, reason interface{}) {
	addr, err := NewNetAddressString(p.ListenAddr)
	if err != nil {
		// this should never happen
		log.Error("Error in AddPeer: invalid peer address", "addr", p.ListenAddr, "error", err)
		return
	}
	r.book.RemoveAddress(addr)
}

// Receive implements Reactor by handling incoming PEX messages.
func (r *PEXReactor) Receive(chID byte, src *Peer, msgBytes []byte) {
	srcAddr := src.Connection().RemoteAddress
	srcAddrStr := srcAddr.String()
	r.msgCountByPeer[srcAddrStr]++
	if r.ReachedMaxMsgCountForPeer(srcAddrStr) {
		log.Warn("Maximum number of messages reached for peer", "peer", srcAddrStr)
		// TODO remove src from peers?
		return
	}

	_, msg, err := DecodeMessage(msgBytes)
	if err != nil {
		log.Warn("Error decoding message", "error", err)
		return
	}
	log.Notice("Received message", "msg", msg)

	switch msg := msg.(type) {
	case *pexRequestMessage:
		// src requested some peers.
		r.SendAddrs(src, r.book.GetSelection())
	case *pexAddrsMessage:
		// We received some peer addresses from src.
		// (We don't want to get spammed with bad peers)
		for _, addr := range msg.Addrs {
			if addr != nil {
				r.book.AddAddress(addr, srcAddr)
			}
		}
	default:
		log.Warn(fmt.Sprintf("Unknown message type %v", reflect.TypeOf(msg)))
	}
}

// RequestPEX asks peer for more addresses.
func (r *PEXReactor) RequestPEX(p *Peer) {
	p.Send(PexChannel, struct{ PexMessage }{&pexRequestMessage{}})
}

// SendAddrs sends addrs to the peer.
func (r *PEXReactor) SendAddrs(p *Peer, addrs []*NetAddress) {
	p.Send(PexChannel, struct{ PexMessage }{&pexAddrsMessage{Addrs: addrs}})
}

// SetEnsurePeersPeriod sets period to ensure peers connected.
func (r *PEXReactor) SetEnsurePeersPeriod(d time.Duration) {
	r.ensurePeersPeriod = d
}

// SetMaxMsgCountByPeer sets maximum messages one peer can send to us during 'msgCountByPeerFlushInterval'.
func (r *PEXReactor) SetMaxMsgCountByPeer(v uint16) {
	r.maxMsgCountByPeer = v
}

// ReachedMaxMsgCountForPeer returns true if we received too many
// messages from peer with address `addr`.
func (r *PEXReactor) ReachedMaxMsgCountForPeer(addr string) bool {
	return r.msgCountByPeer[addr] >= r.maxMsgCountByPeer
}

// Ensures that sufficient peers are connected. (continuous)
func (r *PEXReactor) ensurePeersRoutine() {
	// Randomize when routine starts
	ensurePeersPeriodMs := r.ensurePeersPeriod.Nanoseconds() / 1e6
	time.Sleep(time.Duration(rand.Int63n(ensurePeersPeriodMs)) * time.Millisecond)

	// fire once immediately.
	r.ensurePeers()

	// fire periodically
	ticker := time.NewTicker(r.ensurePeersPeriod)

	for {
		select {
		case <-ticker.C:
			r.ensurePeers()
		case <-r.Quit:
			ticker.Stop()
			return
		}
	}
}

// ensurePeers ensures that sufficient peers are connected. (once)
func (r *PEXReactor) ensurePeers() {
	numOutPeers, _, numDialing := r.Switch.NumPeers()
	numToDial := minNumOutboundPeers - (numOutPeers + numDialing)
	log.Info("Ensure peers", "numOutPeers", numOutPeers, "numDialing", numDialing, "numToDial", numToDial)
	if numToDial <= 0 {
		return
	}

	toDial := make(map[string]*NetAddress)

	// Try to pick numToDial addresses to dial.
	for i := 0; i < numToDial; i++ {
		var picked *NetAddress
		// Try to fetch a new peer 3 times.
		// This caps the maximum number of tries to 3 * numToDial.
		for j := 0; j < 3; j++ {
			// NOTE always picking from the new group because old one stores already
			// connected peers.
			try := r.book.PickAddress(100)
			if try == nil {
				break
			}
			_, alreadySelected := toDial[try.IP.String()]
			alreadyDialing := r.Switch.IsDialing(try)
			if alreadySelected || alreadyDialing {
				// log.Info("Cannot dial address", "addr", try,
				// 	"alreadySelected", alreadySelected,
				// 	"alreadyDialing", alreadyDialing)
				continue
			} else {
				log.Info("Will dial address", "addr", try)
				picked = try
				break
			}
		}
		if picked == nil {
			continue
		}
		toDial[picked.IP.String()] = picked
	}

	// Dial picked addresses
	for _, item := range toDial {
		go func(picked *NetAddress) {
			_, err := r.Switch.DialPeerWithAddress(picked, false)
			if err != nil {
				r.book.MarkAttempt(picked)
			} else {
				// move address to the old group
				r.book.MarkGood(picked)
			}
		}(item)
	}

	// If we need more addresses, pick a random peer and ask for more.
	if r.book.NeedMoreAddrs() {
		if peers := r.Switch.Peers().List(); len(peers) > 0 {
			i := rand.Int() % len(peers)
			peer := peers[i]
			log.Info("No addresses to dial. Sending pexRequest to random peer", "peer", peer)
			r.RequestPEX(peer)
		}
	}
}

func (r *PEXReactor) flushMsgCountByPeer() {
	ticker := time.NewTicker(msgCountByPeerFlushInterval)

	for {
		select {
		case <-ticker.C:
			r.msgCountByPeer = make(map[string]uint16)
		case <-r.Quit:
			ticker.Stop()
			return
		}
	}
}

//-----------------------------------------------------------------------------
// Messages

const (
	msgTypeRequest = byte(0x01)
	msgTypeAddrs   = byte(0x02)
)

// PexMessage is a primary type for PEX messages. Underneath, it could contain
// either pexRequestMessage, or pexAddrsMessage messages.
type PexMessage interface{}

var _ = wire.RegisterInterface(
	struct{ PexMessage }{},
	wire.ConcreteType{&pexRequestMessage{}, msgTypeRequest},
	wire.ConcreteType{&pexAddrsMessage{}, msgTypeAddrs},
)

// DecodeMessage implements interface registered above.
func DecodeMessage(bz []byte) (msgType byte, msg PexMessage, err error) {
	msgType = bz[0]
	n := new(int)
	r := bytes.NewReader(bz)
	msg = wire.ReadBinary(struct{ PexMessage }{}, r, maxPexMessageSize, n, &err).(struct{ PexMessage }).PexMessage
	return
}

/*
A pexRequestMessage requests additional peer addresses.
*/
type pexRequestMessage struct {
}

func (m *pexRequestMessage) String() string {
	return "[pexRequest]"
}

/*
A message with announced peer addresses.
*/
type pexAddrsMessage struct {
	Addrs []*NetAddress
}

func (m *pexAddrsMessage) String() string {
	return fmt.Sprintf("[pexAddrs %v]", m.Addrs)
}
<commit_msg>revert e448199<commit_after>package p2p

import (
	"bytes"
	"fmt"
	"math/rand"
	"reflect"
	"time"

	cmn "github.com/tendermint/go-common"
	wire "github.com/tendermint/go-wire"
)

const (
	// PexChannel is a channel for PEX messages
	PexChannel = byte(0x00)

	// period to ensure peers connected
	defaultEnsurePeersPeriod = 30 * time.Second
	minNumOutboundPeers      = 10
	maxPexMessageSize        = 1048576 // 1MB

	// maximum messages one peer can send to us during `msgCountByPeerFlushInterval`
	defaultMaxMsgCountByPeer    = 1000
	msgCountByPeerFlushInterval = 1 * time.Hour
)

// PEXReactor handles PEX (peer exchange) and ensures that an
// adequate number of peers are connected to the switch.
//
// It uses `AddrBook` (address book) to store `NetAddress`es of the peers.
//
// ## Preventing abuse
//
// For now, it just limits the number of messages from one peer to
// `defaultMaxMsgCountByPeer` messages per `msgCountByPeerFlushInterval` (1000
// msg/hour).
//
// NOTE [2017-01-17]:
//   Limiting is fine for now. Maybe down the road we want to keep track of the
//   quality of peer messages so if peerA keeps telling us about peers we can't
//   connect to then maybe we should care less about peerA. But I don't think
//   that kind of complexity is priority right now.
type PEXReactor struct {
	BaseReactor

	sw                *Switch
	book              *AddrBook
	ensurePeersPeriod time.Duration

	// tracks message count by peer, so we can prevent abuse
	msgCountByPeer    map[string]uint16
	maxMsgCountByPeer uint16
}

// NewPEXReactor creates new PEX reactor.
func NewPEXReactor(b *AddrBook) *PEXReactor {
	r := &PEXReactor{
		book:              b,
		ensurePeersPeriod: defaultEnsurePeersPeriod,
		msgCountByPeer:    make(map[string]uint16),
		maxMsgCountByPeer: defaultMaxMsgCountByPeer,
	}
	r.BaseReactor = *NewBaseReactor(log, "PEXReactor", r)
	return r
}

// OnStart implements BaseService
func (r *PEXReactor) OnStart() error {
	r.BaseReactor.OnStart()
	r.book.Start()
	go r.ensurePeersRoutine()
	go r.flushMsgCountByPeer()
	return nil
}

// OnStop implements BaseService
func (r *PEXReactor) OnStop() {
	r.BaseReactor.OnStop()
	r.book.Stop()
}

// GetChannels implements Reactor
func (r *PEXReactor) GetChannels() []*ChannelDescriptor {
	return []*ChannelDescriptor{
		&ChannelDescriptor{
			ID:                PexChannel,
			Priority:          1,
			SendQueueCapacity: 10,
		},
	}
}

// AddPeer implements Reactor by adding peer to the address book (if inbound)
// or by requesting more addresses (if outbound).
func (r *PEXReactor) AddPeer(p *Peer) {
	if p.IsOutbound() { // For outbound peers, the address is already in the books
		if r.book.NeedMoreAddrs() {
			r.RequestPEX(p)
		}
	} else { // For inbound connections, the peer is its own source
		addr, err := NewNetAddressString(p.ListenAddr)
		if err != nil {
			// this should never happen
			log.Error("Error in AddPeer: invalid peer address", "addr", p.ListenAddr, "error", err)
			return
		}
		r.book.AddAddress(addr, addr)
	}
}

// RemovePeer implements Reactor by removing peer from the address book.
//
// The peer will be proposed to us by other peers (PexAddrsMessage) or himself
// and we will add him again upon successful connection. Note that other peers
// will remove him too. The peer will need to send first requests to others by
// himself (he will have an addrbook or the seeds).
func (r *PEXReactor) RemovePeer(p *Peer, reason interface{}) {
	addr, err := NewNetAddressString(p.ListenAddr)
	if err != nil {
		// this should never happen
		log.Error("Error in AddPeer: invalid peer address", "addr", p.ListenAddr, "error", err)
		return
	}
	r.book.RemoveAddress(addr)
}

// Receive implements Reactor by handling incoming PEX messages.
func (r *PEXReactor) Receive(chID byte, src *Peer, msgBytes []byte) {
	srcAddr := src.Connection().RemoteAddress
	srcAddrStr := srcAddr.String()
	r.msgCountByPeer[srcAddrStr]++
	if r.ReachedMaxMsgCountForPeer(srcAddrStr) {
		log.Warn("Maximum number of messages reached for peer", "peer", srcAddrStr)
		// TODO remove src from peers?
		return
	}

	_, msg, err := DecodeMessage(msgBytes)
	if err != nil {
		log.Warn("Error decoding message", "error", err)
		return
	}
	log.Notice("Received message", "msg", msg)

	switch msg := msg.(type) {
	case *pexRequestMessage:
		// src requested some peers.
		r.SendAddrs(src, r.book.GetSelection())
	case *pexAddrsMessage:
		// We received some peer addresses from src.
		// (We don't want to get spammed with bad peers)
		for _, addr := range msg.Addrs {
			if addr != nil {
				r.book.AddAddress(addr, srcAddr)
			}
		}
	default:
		log.Warn(fmt.Sprintf("Unknown message type %v", reflect.TypeOf(msg)))
	}
}

// RequestPEX asks peer for more addresses.
func (r *PEXReactor) RequestPEX(p *Peer) {
	p.Send(PexChannel, struct{ PexMessage }{&pexRequestMessage{}})
}

// SendAddrs sends addrs to the peer.
func (r *PEXReactor) SendAddrs(p *Peer, addrs []*NetAddress) {
	p.Send(PexChannel, struct{ PexMessage }{&pexAddrsMessage{Addrs: addrs}})
}

// SetEnsurePeersPeriod sets period to ensure peers connected.
func (r *PEXReactor) SetEnsurePeersPeriod(d time.Duration) {
	r.ensurePeersPeriod = d
}

// SetMaxMsgCountByPeer sets maximum messages one peer can send to us during 'msgCountByPeerFlushInterval'.
func (r *PEXReactor) SetMaxMsgCountByPeer(v uint16) {
	r.maxMsgCountByPeer = v
}

// ReachedMaxMsgCountForPeer returns true if we received too many
// messages from peer with address `addr`.
func (r *PEXReactor) ReachedMaxMsgCountForPeer(addr string) bool {
	return r.msgCountByPeer[addr] >= r.maxMsgCountByPeer
}

// Ensures that sufficient peers are connected. (continuous)
func (r *PEXReactor) ensurePeersRoutine() {
	// Randomize when routine starts
	ensurePeersPeriodMs := r.ensurePeersPeriod.Nanoseconds() / 1e6
	time.Sleep(time.Duration(rand.Int63n(ensurePeersPeriodMs)) * time.Millisecond)

	// fire once immediately.
	r.ensurePeers()

	// fire periodically
	ticker := time.NewTicker(r.ensurePeersPeriod)

	for {
		select {
		case <-ticker.C:
			r.ensurePeers()
		case <-r.Quit:
			ticker.Stop()
			return
		}
	}
}

// ensurePeers ensures that sufficient peers are connected. (once)
//
// Old bucket / New bucket are arbitrary categories to denote whether an
// address is vetted or not, and this needs to be determined over time via a
// heuristic that we haven't perfected yet, or, perhaps is manually edited by
// the node operator. It should not be used to compute what addresses are
// already connected or not.
//
// TODO Basically, we need to work harder on our good-peer/bad-peer marking.
// What we're currently doing in terms of marking good/bad peers is just a
// placeholder. It should not be the case that an address becomes old/vetted
// upon a single successful connection.
func (r *PEXReactor) ensurePeers() {
	numOutPeers, _, numDialing := r.Switch.NumPeers()
	numToDial := minNumOutboundPeers - (numOutPeers + numDialing)
	log.Info("Ensure peers", "numOutPeers", numOutPeers, "numDialing", numDialing, "numToDial", numToDial)
	if numToDial <= 0 {
		return
	}

	toDial := make(map[string]*NetAddress)

	// Try to pick numToDial addresses to dial.
	for i := 0; i < numToDial; i++ {
		// The purpose of newBias is to first prioritize old (more vetted) peers
		// when we have few connections, but to allow for new (less vetted) peers
		// if we already have many connections. This algorithm isn't perfect, but
		// it somewhat ensures that we prioritize connecting to more-vetted
		// peers.
		newBias := cmn.MinInt(numOutPeers, 8)*10 + 10
		var picked *NetAddress
		// Try to fetch a new peer 3 times.
		// This caps the maximum number of tries to 3 * numToDial.
		for j := 0; j < 3; j++ {
			try := r.book.PickAddress(newBias)
			if try == nil {
				break
			}
			_, alreadySelected := toDial[try.IP.String()]
			alreadyDialing := r.Switch.IsDialing(try)
			alreadyConnected := r.Switch.Peers().Has(try.IP.String())
			if alreadySelected || alreadyDialing || alreadyConnected {
				// log.Info("Cannot dial address", "addr", try,
				// 	"alreadySelected", alreadySelected,
				// 	"alreadyDialing", alreadyDialing,
				//  "alreadyConnected", alreadyConnected)
				continue
			} else {
				log.Info("Will dial address", "addr", try)
				picked = try
				break
			}
		}
		if picked == nil {
			continue
		}
		toDial[picked.IP.String()] = picked
	}

	// Dial picked addresses
	for _, item := range toDial {
		go func(picked *NetAddress) {
			_, err := r.Switch.DialPeerWithAddress(picked, false)
			if err != nil {
				r.book.MarkAttempt(picked)
			}
		}(item)
	}

	// If we need more addresses, pick a random peer and ask for more.
	if r.book.NeedMoreAddrs() {
		if peers := r.Switch.Peers().List(); len(peers) > 0 {
			i := rand.Int() % len(peers)
			peer := peers[i]
			log.Info("No addresses to dial. Sending pexRequest to random peer", "peer", peer)
			r.RequestPEX(peer)
		}
	}
}

func (r *PEXReactor) flushMsgCountByPeer() {
	ticker := time.NewTicker(msgCountByPeerFlushInterval)

	for {
		select {
		case <-ticker.C:
			r.msgCountByPeer = make(map[string]uint16)
		case <-r.Quit:
			ticker.Stop()
			return
		}
	}
}

//-----------------------------------------------------------------------------
// Messages

const (
	msgTypeRequest = byte(0x01)
	msgTypeAddrs   = byte(0x02)
)

// PexMessage is a primary type for PEX messages. Underneath, it could contain
// either pexRequestMessage, or pexAddrsMessage messages.
type PexMessage interface{}

var _ = wire.RegisterInterface(
	struct{ PexMessage }{},
	wire.ConcreteType{&pexRequestMessage{}, msgTypeRequest},
	wire.ConcreteType{&pexAddrsMessage{}, msgTypeAddrs},
)

// DecodeMessage implements interface registered above.
func DecodeMessage(bz []byte) (msgType byte, msg PexMessage, err error) {
	msgType = bz[0]
	n := new(int)
	r := bytes.NewReader(bz)
	msg = wire.ReadBinary(struct{ PexMessage }{}, r, maxPexMessageSize, n, &err).(struct{ PexMessage }).PexMessage
	return
}

/*
A pexRequestMessage requests additional peer addresses.
*/
type pexRequestMessage struct {
}

func (m *pexRequestMessage) String() string {
	return "[pexRequest]"
}

/*
A message with announced peer addresses.
*/
type pexAddrsMessage struct {
	Addrs []*NetAddress
}

func (m *pexAddrsMessage) String() string {
	return fmt.Sprintf("[pexAddrs %v]", m.Addrs)
}
<|endoftext|>