<commit_before>// +build windows

package open

import (
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

var (
	cmd      = "url.dll,FileProtocolHandler"
	runDll32 = filepath.Join(os.Getenv("SYSTEMROOT"), "System32", "rundll32.exe")
)

func cleaninput(input string) string {
	r := strings.NewReplacer("&", "^&")
	return r.Replace(input)
}

func open(input string) *exec.Cmd {
	return exec.Command(runDll32, cmd, cleaninput(input))
}

func openWith(input string, appName string) *exec.Cmd {
	return exec.Command("cmd", "/C", "start", "", appName, cleaninput(input))
}
<commit_msg>Windows URL quick-fix.<commit_after>// +build windows

package open

import (
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

var (
	cmd      = "url.dll,FileProtocolHandler"
	runDll32 = filepath.Join(os.Getenv("SYSTEMROOT"), "System32", "rundll32.exe")
)

func open(input string) *exec.Cmd {
	return exec.Command(runDll32, cmd, input)
}

func openWith(input string, appName string) *exec.Cmd {
	return exec.Command("cmd", "/C", "start", "", appName, input)
}
<|endoftext|>


<commit_before>package rel

type MultiStatementManager struct {
	Engine Engine
	Ast    Visitable
}

func (mgr *MultiStatementManager) ToSql() string {
	return mgr.Engine.Visitor().Accept(mgr.Ast)
}

func NewMultiStatementManager(e Engine) *MultiStatementManager {
	return &MultiStatementManager{Engine: e}
}

func (mgr *MultiStatementManager) Intersect(stmt1 Visitable, stmt2 Visitable) *MultiStatementManager {
	mgr.Ast = IntersectNode{
		Left:  stmt1,
		Right: stmt2,
	}
	return mgr
}

func (mgr *MultiStatementManager) Union(stmt1 Visitable, stmt2 Visitable) *MultiStatementManager {
	mgr.Ast = UnionNode{
		Left:  stmt1,
		Right: stmt2,
	}
	return mgr
}

func (mgr *MultiStatementManager) UnionAll(stmt1 Visitable, stmt2 Visitable) *MultiStatementManager {
	mgr.Ast = UnionAllNode{
		Left:  stmt1,
		Right: stmt2,
	}
	return mgr
}
<commit_msg>Created MultiStatementManager#Except<commit_after>package rel

type MultiStatementManager struct {
	Engine Engine
	Ast    Visitable
}

func (mgr *MultiStatementManager) ToSql() string {
	return mgr.Engine.Visitor().Accept(mgr.Ast)
}

func NewMultiStatementManager(e Engine) *MultiStatementManager {
	return &MultiStatementManager{Engine: e}
}

func (mgr *MultiStatementManager) Intersect(stmt1 Visitable, stmt2 Visitable) *MultiStatementManager {
	mgr.Ast = IntersectNode{
		Left:  stmt1,
		Right: stmt2,
	}
	return mgr
}

func (mgr *MultiStatementManager) Union(stmt1 Visitable, stmt2 Visitable) *MultiStatementManager {
	mgr.Ast = UnionNode{
		Left:  stmt1,
		Right: stmt2,
	}
	return mgr
}

func (mgr *MultiStatementManager) UnionAll(stmt1 Visitable, stmt2 Visitable) *MultiStatementManager {
	mgr.Ast = UnionAllNode{
		Left:  stmt1,
		Right: stmt2,
	}
	return mgr
}

func (mgr *MultiStatementManager) Except(stmt1 Visitable, stmt2 Visitable) *MultiStatementManager {
	mgr.Ast = ExceptNode{
		Left:  stmt1,
		Right: stmt2,
	}
	return mgr
}
<|endoftext|>


<commit_before>// Binary stfortune is a simple client of Veyron Store.  See
// http://go/veyron:codelab-store for a thorough explanation.
package main

import (
	"crypto/md5"
	"encoding/hex"
	"flag"
	"fmt"
	"log"
	"math/rand"
	"strings"
	"time"

	"veyron/examples/stfortune/schema"

	"veyron2/context"
	"veyron2/naming"
	"veyron2/rt"
	istore "veyron2/services/store"
	iwatch "veyron2/services/watch"
	"veyron2/storage"
	"veyron2/storage/vstore"
	"veyron2/storage/vstore/primitives"
	"veyron2/vom"
)

func fortunePath(name string) string {
	return naming.Join(naming.Join(appPath, "fortunes"), name)
}

func userPath(name string) string {
	return naming.Join(naming.Join(appPath, "usernames"), name)
}

// Hashes a string.
func getMD5Hash(text string) string {
	hasher := md5.New()
	hasher.Write([]byte(text))
	return hex.EncodeToString(hasher.Sum(nil))
}

// waitForStore waits for the local store to be ready by checking if
// the schema information is synchronized.
func waitForStore(store storage.Store) {
	ctx := rt.R().NewContext()

	// Register *store.Entry for WatchGlob.
	// TODO(tilaks): store.Entry is declared in vdl, vom should register the
	// pointer automatically.
	vom.Register(&istore.Entry{})

	fmt.Printf("Waiting for Store to be initialized with fortune schema...\n")
	// List of paths to check in store.
	paths := []string{appPath, fortunePath(""), userPath("")}
	for _, path := range paths {
		req := iwatch.GlobRequest{Pattern: ""}
		stream, err := store.Bind(path).WatchGlob(ctx, req)
		if err != nil {
			log.Fatalf("WatchGlob %s failed: %v", path, err)
		}
		if _, err := stream.Recv(); err != nil {
			log.Fatalf("Recv failed: %v", err)
		}
		stream.Cancel()
	}

	fmt.Printf("Store is ready\n")
	return
}

// pickFortune finds all available fortunes under the input path and
// chooses one randomly.
func pickFortune(store storage.Store, ctx context.T, path string) (string, error) {
	tr := primitives.NewTransaction(ctx)
	defer tr.Abort(ctx)

	results, err := store.Bind(path).GlobT(ctx, tr, "*")
	if err != nil {
		return "", err
	}
	var names []string
	for {
		name, err := results.Recv()
		if err != nil {
			break
		}
		names = append(names, name)
	}
	results.Finish()
	if names == nil || len(names) < 1 {
		return "", nil
	}

	// Get a random fortune using the glob results.
	random := rand.New(rand.NewSource(time.Now().UTC().UnixNano()))
	p := fortunePath(names[random.Intn(len(names))])
	f, err := store.Bind(p).Get(ctx, tr)
	if err != nil {
		return "", err
	}
	fortune, ok := f.Value.(schema.FortuneData)
	if !ok {
		return "", fmt.Errorf("found type %T, expected schema.FortuneData", f.Value)
	}
	return fortune.Fortune, nil
}

// getFortune returns a random fortune corresponding to a UserName if
// specified. If not, it picks a random fortune.
func getFortune(store storage.Store, userName string) (string, error) {
	ctx := rt.R().NewContext()

	var p string
	if userName != "" {
		// Look for a random fortune belonging to UserName.
		p = userPath(userName)
	} else {
		// Look for a random fortune.
		p = fortunePath("")
	}

	return pickFortune(store, ctx, p)
}

// addFortune adds a new fortune to the store and links it to the specified
// UserName. In this process, if the UserName doesn't exist, a new
// user is created.
func addFortune(store storage.Store, fortune string, userName string) error {
	ctx := rt.R().NewContext()
	tr := primitives.NewTransaction(ctx)
	committed := false
	defer func() {
		if !committed {
			tr.Abort(ctx)
		}
	}()

	// Check if the UserName exists. If yes, get its OID. If not, create a new user.
	p := userPath(userName)
	o := store.Bind(p)
	exists, err := o.Exists(ctx, tr)
	if err != nil {
		return err
	}
	var userid storage.ID
	if !exists {
		u := schema.User{Name: userName}
		stat, err := o.Put(ctx, tr, u)
		if err != nil {
			return err
		}
		userid = stat.ID
	} else {
		u, err := o.Get(ctx, tr)
		if err != nil {
			return err
		}
		userid = u.Stat.ID
	}

	// Create a new fortune entry.
	f := schema.FortuneData{Fortune: fortune, UserName: userid}
	hash := getMD5Hash(naming.Join(fortune, userName))
	p = fortunePath(hash)
	s, err := store.Bind(p).Put(ctx, tr, f)
	if err != nil {
		return err
	}

	// Link the new fortune to UserName.
	p = userPath(naming.Join(userName, hash))
	if _, err = store.Bind(p).Put(ctx, tr, s.ID); err != nil {
		return err
	}

	// Commit all changes.
	//
	// NOTE: A commit can sometimes fail due to store's optimistic
	// locking. When the error for this scenario is
	// exposed via the Commit API, one could retry the
	// transaction.
	if err := tr.Commit(ctx); err != nil {
		return err
	}
	committed = true
	return nil
}

var (
	appPath      = "/apps/stfortune"
	storeAddress = flag.String("store", "", "the address/endpoint of the Veyron Store")
	newFortune   = flag.String("new_fortune", "", "an optional, new fortune to add to the server's set")
	user         = flag.String("user_name", "", "an optional username of the fortune creator to get/add to the server's set")
)

func main() {
	rt.Init()
	if *storeAddress == "" {
		log.Fatal("--store needs to be specified")
	}

	// Create a handle to the backend store.
	store, err := vstore.New(*storeAddress)
	if err != nil {
		log.Fatalf("Can't connect to store: %s: %v", *storeAddress, err)
	}

	// Wait for the store to be ready before proceeding.
	waitForStore(store)

	// Get a fortune from the store.
	fortune, err := getFortune(store, *user)
	if err != nil {
		log.Fatal("error getting fortune: ", err)
	}
	fmt.Println("Fortune: ", fortune)

	// If the user specified --new_fortune, add it to the store’s set of fortunes.
	if *newFortune != "" {
		if *user == "" {
			*user = "anonymous"
		}
		*user = strings.ToLower(*user)
		if err := addFortune(store, *newFortune, *user); err != nil {
			log.Fatal("error adding fortune: ", err)
		}
	}
}
<commit_msg>veyron/examples/stfortune: Bug fix to handle same fortune being put repeatedly.<commit_after>// Binary stfortune is a simple client of Veyron Store.  See
// http://go/veyron:codelab-store for a thorough explanation.
package main

import (
	"crypto/md5"
	"encoding/hex"
	"flag"
	"fmt"
	"log"
	"math/rand"
	"strings"
	"time"

	"veyron/examples/stfortune/schema"

	"veyron2/context"
	"veyron2/naming"
	"veyron2/rt"
	istore "veyron2/services/store"
	iwatch "veyron2/services/watch"
	"veyron2/storage"
	"veyron2/storage/vstore"
	"veyron2/storage/vstore/primitives"
	"veyron2/vom"
)

func fortunePath(name string) string {
	return naming.Join(naming.Join(appPath, "fortunes"), name)
}

func userPath(name string) string {
	return naming.Join(naming.Join(appPath, "usernames"), name)
}

// Hashes a string.
func getMD5Hash(text string) string {
	hasher := md5.New()
	hasher.Write([]byte(text))
	return hex.EncodeToString(hasher.Sum(nil))
}

// waitForStore waits for the local store to be ready by checking if
// the schema information is synchronized.
func waitForStore(store storage.Store) {
	ctx := rt.R().NewContext()

	// Register *store.Entry for WatchGlob.
	// TODO(tilaks): store.Entry is declared in vdl, vom should register the
	// pointer automatically.
	vom.Register(&istore.Entry{})

	fmt.Printf("Waiting for Store to be initialized with fortune schema...\n")
	// List of paths to check in store.
	paths := []string{appPath, fortunePath(""), userPath("")}
	for _, path := range paths {
		req := iwatch.GlobRequest{Pattern: ""}
		stream, err := store.Bind(path).WatchGlob(ctx, req)
		if err != nil {
			log.Fatalf("WatchGlob %s failed: %v", path, err)
		}
		if _, err := stream.Recv(); err != nil {
			log.Fatalf("Recv failed: %v", err)
		}
		stream.Cancel()
	}

	fmt.Printf("Store is ready\n")
	return
}

// pickFortune finds all available fortunes under the input path and
// chooses one randomly.
func pickFortune(store storage.Store, ctx context.T, path string) (string, error) {
	tr := primitives.NewTransaction(ctx)
	defer tr.Abort(ctx)

	results, err := store.Bind(path).GlobT(ctx, tr, "*")
	if err != nil {
		return "", err
	}
	var names []string
	for {
		name, err := results.Recv()
		if err != nil {
			break
		}
		names = append(names, name)
	}
	results.Finish()
	if names == nil || len(names) < 1 {
		return "", nil
	}

	// Get a random fortune using the glob results.
	random := rand.New(rand.NewSource(time.Now().UTC().UnixNano()))
	p := fortunePath(names[random.Intn(len(names))])
	f, err := store.Bind(p).Get(ctx, tr)
	if err != nil {
		return "", err
	}
	fortune, ok := f.Value.(schema.FortuneData)
	if !ok {
		return "", fmt.Errorf("found type %T, expected schema.FortuneData", f.Value)
	}
	return fortune.Fortune, nil
}

// getFortune returns a random fortune corresponding to a UserName if
// specified. If not, it picks a random fortune.
func getFortune(store storage.Store, userName string) (string, error) {
	ctx := rt.R().NewContext()

	var p string
	if userName != "" {
		// Look for a random fortune belonging to UserName.
		p = userPath(userName)
	} else {
		// Look for a random fortune.
		p = fortunePath("")
	}

	return pickFortune(store, ctx, p)
}

// addFortune adds a new fortune to the store and links it to the specified
// UserName. In this process, if the UserName doesn't exist, a new
// user is created.
func addFortune(store storage.Store, fortune string, userName string) error {
	ctx := rt.R().NewContext()
	tr := primitives.NewTransaction(ctx)
	committed := false
	defer func() {
		if !committed {
			tr.Abort(ctx)
		}
	}()

	// Check if this fortune already exists. If yes, return.
	hash := getMD5Hash(naming.Join(fortune, userName))
	exists, err := store.Bind(fortunePath(hash)).Exists(ctx, tr)
	if err != nil {
		return err
	}
	if exists {
		return nil
	}

	// Check if the UserName exists. If yes, get its OID. If not, create a new user.
	o := store.Bind(userPath(userName))
	exists, err = o.Exists(ctx, tr)
	if err != nil {
		return err
	}
	var userid storage.ID
	if !exists {
		u := schema.User{Name: userName}
		stat, err := o.Put(ctx, tr, u)
		if err != nil {
			return err
		}
		userid = stat.ID
	} else {
		u, err := o.Get(ctx, tr)
		if err != nil {
			return err
		}
		userid = u.Stat.ID
	}

	// Create a new fortune entry.
	f := schema.FortuneData{Fortune: fortune, UserName: userid}
	s, err := store.Bind(fortunePath(hash)).Put(ctx, tr, f)
	if err != nil {
		return err
	}

	// Link the new fortune to UserName.
	p := userPath(naming.Join(userName, hash))
	if _, err = store.Bind(p).Put(ctx, tr, s.ID); err != nil {
		return err
	}

	// Commit all changes.
	//
	// NOTE: A commit can sometimes fail due to store's optimistic
	// locking. When the error for this scenario is
	// exposed via the Commit API, one could retry the
	// transaction.
	if err := tr.Commit(ctx); err != nil {
		return err
	}
	committed = true
	return nil
}

var (
	appPath      = "/apps/stfortune"
	storeAddress = flag.String("store", "", "the address/endpoint of the Veyron Store")
	newFortune   = flag.String("new_fortune", "", "an optional, new fortune to add to the server's set")
	user         = flag.String("user_name", "", "an optional username of the fortune creator to get/add to the server's set")
)

func main() {
	rt.Init()
	if *storeAddress == "" {
		log.Fatal("--store needs to be specified")
	}

	// Create a handle to the backend store.
	store, err := vstore.New(*storeAddress)
	if err != nil {
		log.Fatalf("Can't connect to store: %s: %v", *storeAddress, err)
	}

	// Wait for the store to be ready before proceeding.
	waitForStore(store)

	// Get a fortune from the store.
	fortune, err := getFortune(store, *user)
	if err != nil {
		log.Fatal("error getting fortune: ", err)
	}
	fmt.Println("Fortune: ", fortune)

	// If the user specified --new_fortune, add it to the store’s set of fortunes.
	if *newFortune != "" {
		if *user == "" {
			*user = "anonymous"
		}
		*user = strings.ToLower(*user)
		if err := addFortune(store, *newFortune, *user); err != nil {
			log.Fatal("error adding fortune: ", err)
		}
	}
}
<|endoftext|>


<commit_before>package middleware

import (
	"log"
	"runtime"

	"github.com/neptulon/neptulon"
)

// Error is an error/panic handler middleware.
// Any error/panic is recovered and logged and the error response is returned to the user (auto-generated if none was set).
func Error(ctx *neptulon.ReqCtx) error {
	errored := false

	if err := ctx.Next(); err != nil {
		errored = true
		log.Printf("mw: error: error handling response: %v", err)
	}

	if err := recover(); err != nil {
		errored = true
		const size = 64 << 10
		buf := make([]byte, size)
		buf = buf[:runtime.Stack(buf, false)]
		log.Printf("mw: error: panic handling response: %v\nstack trace: %s", err, buf)
	}

	if errored && ctx.Err == nil {
		ctx.Err = &neptulon.ResError{
			Code:    500,
			Message: "Internal server error.",
		}
	}

	return ctx.Next()
}
<commit_msg>mw: error: call ctx.Next() upon handling error<commit_after>package middleware

import (
	"log"
	"runtime"

	"github.com/neptulon/neptulon"
)

// Error is an error/panic handler middleware.
// Any error/panic is recovered and logged and the error response is returned to the user (auto-generated if none was set).
func Error(ctx *neptulon.ReqCtx) error {
	errored := false

	if err := ctx.Next(); err != nil {
		errored = true
		log.Printf("mw: error: error handling response: %v", err)
	}

	if err := recover(); err != nil {
		errored = true
		const size = 64 << 10
		buf := make([]byte, size)
		buf = buf[:runtime.Stack(buf, false)]
		log.Printf("mw: error: panic handling response: %v\nstack trace: %s", err, buf)
	}

	if errored {
		if ctx.Err == nil {
			ctx.Err = &neptulon.ResError{
				Code:    500,
				Message: "Internal server error.",
			}
		}

		return ctx.Next()
	}

	return nil
}
<|endoftext|>


<commit_before>package middleware

import (
	"fmt"
	"io"
	"math/rand"
	"net"
	"net/http"
	"net/http/httputil"
	"net/url"
	"strings"
	"sync"
	"sync/atomic"
	"time"

	"github.com/webx-top/echo"
)

// TODO: Handle TLS proxy

type (
	// ProxyConfig defines the config for Proxy middleware.
	ProxyConfig struct {
		// Skipper defines a function to skip middleware.
		Skipper echo.Skipper `json:"-"`

		// Balancer defines a load balancing technique.
		// Required.
		Balancer ProxyBalancer `json:"-"`

		Handler ProxyHandler `json:"-"`
		Rewrite RewriteConfig

		// Context key to store selected ProxyTarget into context.
		// Optional. Default value "target".
		ContextKey string
	}

	// ProxyTarget defines the upstream target.
	ProxyTarget struct {
		Name          string
		URL           *url.URL
		FlushInterval time.Duration
		Meta          echo.Store
	}

	// ProxyBalancer defines an interface to implement a load balancing technique.
	ProxyBalancer interface {
		AddTarget(*ProxyTarget) bool
		RemoveTarget(string) bool
		Next(echo.Context) *ProxyTarget
	}

	// ProxyHandler defines an interface to implement a proxy handler.
	ProxyHandler func(t *ProxyTarget, c echo.Context) error

	commonBalancer struct {
		targets []*ProxyTarget
		mutex   sync.RWMutex
	}

	// RandomBalancer implements a random load balancing technique.
	randomBalancer struct {
		*commonBalancer
		random *rand.Rand
	}

	// RoundRobinBalancer implements a round-robin load balancing technique.
	roundRobinBalancer struct {
		*commonBalancer
		i uint32
	}
)

var (
	// DefaultProxyConfig is the default Proxy middleware config.
	DefaultProxyConfig = ProxyConfig{
		Skipper:    echo.DefaultSkipper,
		Handler:    DefaultProxyHandler,
		Rewrite:    DefaultRewriteConfig,
		ContextKey: "target",
	}
	// DefaultProxyHandler Proxy Handler
	DefaultProxyHandler ProxyHandler = func(t *ProxyTarget, c echo.Context) error {
		var key string
		switch {
		case c.IsWebsocket():
			key = `raw`
		case c.Header(echo.HeaderAccept) == echo.MIMEEventStream:
			key = `sse`
		default:
			key = `default`
		}
		if h, ok := DefaultProxyHandlers[key]; ok {
			resp := c.Response().StdResponseWriter()
			req := c.Request().StdRequest()
			h(t, c).ServeHTTP(resp, req)
		}
		return nil
	}

	// DefaultProxyHandlers default preset handlers
	DefaultProxyHandlers = map[string]func(*ProxyTarget, echo.Context) http.Handler{
		`raw`: func(t *ProxyTarget, c echo.Context) http.Handler {
			return proxyRaw(t, c)
		},
		`sse`: func(t *ProxyTarget, c echo.Context) http.Handler {
			return proxyHTTPWithFlushInterval(t)
		},
		`default`: func(t *ProxyTarget, c echo.Context) http.Handler {
			return proxyHTTP(t, c)
		},
	}
)

// Server-Sent Events
func proxyHTTPWithFlushInterval(t *ProxyTarget) http.Handler {
	proxy := httputil.NewSingleHostReverseProxy(t.URL)
	proxy.FlushInterval = t.FlushInterval
	return proxy
}

// http
func proxyHTTP(t *ProxyTarget, _ echo.Context) http.Handler {
	return httputil.NewSingleHostReverseProxy(t.URL)
}

// ProxyHTTPCustomHandler 自定义处理(支持传递body)
func ProxyHTTPCustomHandler(t *ProxyTarget, c echo.Context) http.Handler {
	return newSingleHostReverseProxy(t.URL, c)
}

func newSingleHostReverseProxy(target *url.URL, c echo.Context) *httputil.ReverseProxy {
	director := DefaultProxyHTTPDirector(target.RawQuery)
	return &httputil.ReverseProxy{Director: director}
}

func DefaultProxyHTTPDirector = func(targetQuery string) func(req *http.Request) {
	return func(req *http.Request) {
		if req.Body != nil {
			defer req.Body.Close()
		}
		req.Body = c.Request().Body()
		req.URL.Scheme = target.Scheme
		req.URL.Host = target.Host
		req.URL.Path, req.URL.RawPath = joinURLPath(target, req.URL)
		if targetQuery == "" || req.URL.RawQuery == "" {
			req.URL.RawQuery = targetQuery + req.URL.RawQuery
		} else {
			req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery
		}
		if _, ok := req.Header["User-Agent"]; !ok {
			// explicitly disable User-Agent so it's not set to default value
			req.Header.Set("User-Agent", "")
		}
	}
}

// from net/http/httputil/reverseproxy.go
func singleJoiningSlash(a, b string) string {
	aslash := strings.HasSuffix(a, "/")
	bslash := strings.HasPrefix(b, "/")
	switch {
	case aslash && bslash:
		return a + b[1:]
	case !aslash && !bslash:
		return a + "/" + b
	}
	return a + b
}

// from net/http/httputil/reverseproxy.go
func joinURLPath(a, b *url.URL) (path, rawpath string) {
	if a.RawPath == "" && b.RawPath == "" {
		return singleJoiningSlash(a.Path, b.Path), ""
	}
	// Same as singleJoiningSlash, but uses EscapedPath to determine
	// whether a slash should be added
	apath := a.EscapedPath()
	bpath := b.EscapedPath()

	aslash := strings.HasSuffix(apath, "/")
	bslash := strings.HasPrefix(bpath, "/")

	switch {
	case aslash && bslash:
		return a.Path + b.Path[1:], apath + bpath[1:]
	case !aslash && !bslash:
		return a.Path + "/" + b.Path, apath + "/" + bpath
	}
	return a.Path + b.Path, apath + bpath
}

// websocket
func proxyRaw(t *ProxyTarget, c echo.Context) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		in, _, err := w.(http.Hijacker).Hijack()
		if err != nil {
			c.Error(fmt.Errorf("proxy raw, hijack error=%v, url=%s", t.URL, err))
			return
		}
		defer in.Close()

		out, err := net.Dial("tcp", t.URL.Host)
		if err != nil {
			he := echo.NewHTTPError(http.StatusBadGateway, fmt.Sprintf("proxy raw, dial error=%v, url=%s", t.URL, err)).SetRaw(err)
			c.Error(he)
			return
		}
		defer out.Close()

		// Write header
		err = r.Write(out)
		if err != nil {
			he := echo.NewHTTPError(http.StatusBadGateway, fmt.Sprintf("proxy raw, request header copy error=%v, url=%s", t.URL, err)).SetRaw(err)
			c.Error(he)
			return
		}

		errCh := make(chan error, 2)
		cp := func(dst io.Writer, src io.Reader) {
			_, err = io.Copy(dst, src)
			errCh <- err
		}

		go cp(out, in)
		go cp(in, out)
		err = <-errCh
		if err != nil && err != io.EOF {
			c.Logger().Errorf("proxy raw, copy body error=%v, url=%s", t.URL, err)
		}
	})
}

// NewRandomBalancer returns a random proxy balancer.
func NewRandomBalancer(targets []*ProxyTarget) ProxyBalancer {
	b := &randomBalancer{commonBalancer: new(commonBalancer)}
	b.targets = targets
	return b
}

// NewRoundRobinBalancer returns a round-robin proxy balancer.
func NewRoundRobinBalancer(targets []*ProxyTarget) ProxyBalancer {
	b := &roundRobinBalancer{commonBalancer: new(commonBalancer)}
	b.targets = targets
	return b
}

// AddTarget adds an upstream target to the list.
func (b *commonBalancer) AddTarget(target *ProxyTarget) bool {
	for _, t := range b.targets {
		if t.Name == target.Name {
			return false
		}
	}
	b.mutex.Lock()
	defer b.mutex.Unlock()

	if target.FlushInterval <= 0 {
		target.FlushInterval = 100 * time.Millisecond
	}

	b.targets = append(b.targets, target)
	return true
}

// RemoveTarget removes an upstream target from the list.
func (b *commonBalancer) RemoveTarget(name string) bool {
	b.mutex.Lock()
	defer b.mutex.Unlock()
	for i, t := range b.targets {
		if t.Name == name {
			b.targets = append(b.targets[:i], b.targets[i+1:]...)
			return true
		}
	}
	return false
}

// Next randomly returns an upstream target.
func (b *randomBalancer) Next(c echo.Context) *ProxyTarget {
	if b.random == nil {
		b.random = rand.New(rand.NewSource(int64(time.Now().Nanosecond())))
	}
	b.mutex.RLock()
	defer b.mutex.RUnlock()
	return b.targets[b.random.Intn(len(b.targets))]
}

// Next returns an upstream target using round-robin technique.
func (b *roundRobinBalancer) Next(c echo.Context) *ProxyTarget {
	b.i = b.i % uint32(len(b.targets))
	t := b.targets[b.i]
	atomic.AddUint32(&b.i, 1)
	return t
}

// Proxy returns a Proxy middleware.
//
// Proxy middleware forwards the request to upstream server using a configured load balancing technique.
func Proxy(balancer ProxyBalancer) echo.MiddlewareFuncd {
	c := DefaultProxyConfig
	c.Balancer = balancer
	return ProxyWithConfig(c)
}

// ProxyWithConfig returns a Proxy middleware with config.
// See: `Proxy()`
func ProxyWithConfig(config ProxyConfig) echo.MiddlewareFuncd {
	// Defaults
	if config.Skipper == nil {
		config.Skipper = DefaultProxyConfig.Skipper
	}
	if config.Handler == nil {
		config.Handler = DefaultProxyConfig.Handler
	}
	if config.Balancer == nil {
		panic("echo: proxy middleware requires balancer")
	}
	config.Rewrite.Init()
	return func(next echo.Handler) echo.HandlerFunc {
		return func(c echo.Context) (err error) {
			if config.Skipper(c) {
				return next.Handle(c)
			}

			req := c.Request()
			tgt := config.Balancer.Next(c)
			if len(config.ContextKey) > 0 {
				c.Set(config.ContextKey, tgt)
			}
			req.URL().SetPath(config.Rewrite.Rewrite(req.URL().Path()))
			// Fix header
			if len(c.Header(echo.HeaderXRealIP)) == 0 {
				req.Header().Set(echo.HeaderXRealIP, c.RealIP())
			}
			if len(c.Header(echo.HeaderXForwardedProto)) == 0 {
				req.Header().Set(echo.HeaderXForwardedProto, c.Scheme())
			}
			if c.IsWebsocket() && len(c.Header(echo.HeaderXForwardedFor)) == 0 { // For HTTP, it is automatically set by Go HTTP reverse proxy.
				req.Header().Set(echo.HeaderXForwardedFor, c.RealIP())
			}

			return config.Handler(tgt, c)
		}
	}
}
<commit_msg>update<commit_after>package middleware

import (
	"fmt"
	"io"
	"math/rand"
	"net"
	"net/http"
	"net/http/httputil"
	"net/url"
	"strings"
	"sync"
	"sync/atomic"
	"time"

	"github.com/webx-top/echo"
)

// TODO: Handle TLS proxy

type (
	// ProxyConfig defines the config for Proxy middleware.
	ProxyConfig struct {
		// Skipper defines a function to skip middleware.
		Skipper echo.Skipper `json:"-"`

		// Balancer defines a load balancing technique.
		// Required.
		Balancer ProxyBalancer `json:"-"`

		Handler ProxyHandler `json:"-"`
		Rewrite RewriteConfig

		// Context key to store selected ProxyTarget into context.
		// Optional. Default value "target".
		ContextKey string
	}

	// ProxyTarget defines the upstream target.
	ProxyTarget struct {
		Name          string
		URL           *url.URL
		FlushInterval time.Duration
		Meta          echo.Store
	}

	// ProxyBalancer defines an interface to implement a load balancing technique.
	ProxyBalancer interface {
		AddTarget(*ProxyTarget) bool
		RemoveTarget(string) bool
		Next(echo.Context) *ProxyTarget
	}

	// ProxyHandler defines an interface to implement a proxy handler.
	ProxyHandler func(t *ProxyTarget, c echo.Context) error

	commonBalancer struct {
		targets []*ProxyTarget
		mutex   sync.RWMutex
	}

	// RandomBalancer implements a random load balancing technique.
	randomBalancer struct {
		*commonBalancer
		random *rand.Rand
	}

	// RoundRobinBalancer implements a round-robin load balancing technique.
	roundRobinBalancer struct {
		*commonBalancer
		i uint32
	}
)

var (
	// DefaultProxyConfig is the default Proxy middleware config.
	DefaultProxyConfig = ProxyConfig{
		Skipper:    echo.DefaultSkipper,
		Handler:    DefaultProxyHandler,
		Rewrite:    DefaultRewriteConfig,
		ContextKey: "target",
	}
	// DefaultProxyHandler Proxy Handler
	DefaultProxyHandler ProxyHandler = func(t *ProxyTarget, c echo.Context) error {
		var key string
		switch {
		case c.IsWebsocket():
			key = `raw`
		case c.Header(echo.HeaderAccept) == echo.MIMEEventStream:
			key = `sse`
		default:
			key = `default`
		}
		if h, ok := DefaultProxyHandlers[key]; ok {
			resp := c.Response().StdResponseWriter()
			req := c.Request().StdRequest()
			h(t, c).ServeHTTP(resp, req)
		}
		return nil
	}

	// DefaultProxyHandlers default preset handlers
	DefaultProxyHandlers = map[string]func(*ProxyTarget, echo.Context) http.Handler{
		`raw`: func(t *ProxyTarget, c echo.Context) http.Handler {
			return proxyRaw(t, c)
		},
		`sse`: func(t *ProxyTarget, c echo.Context) http.Handler {
			return proxyHTTPWithFlushInterval(t)
		},
		`default`: func(t *ProxyTarget, c echo.Context) http.Handler {
			return proxyHTTP(t, c)
		},
	}
)

// Server-Sent Events
func proxyHTTPWithFlushInterval(t *ProxyTarget) http.Handler {
	proxy := httputil.NewSingleHostReverseProxy(t.URL)
	proxy.FlushInterval = t.FlushInterval
	return proxy
}

// http
func proxyHTTP(t *ProxyTarget, _ echo.Context) http.Handler {
	return httputil.NewSingleHostReverseProxy(t.URL)
}

// ProxyHTTPCustomHandler 自定义处理(支持传递body)
func ProxyHTTPCustomHandler(t *ProxyTarget, c echo.Context) http.Handler {
	return newSingleHostReverseProxy(t.URL, c)
}

func newSingleHostReverseProxy(target *url.URL, c echo.Context) *httputil.ReverseProxy {
	director := DefaultProxyHTTPDirector(target, c)
	return &httputil.ReverseProxy{Director: director}
}

// DefaultProxyHTTPDirector default director
var DefaultProxyHTTPDirector = func(target *url.URL, c echo.Context) func(req *http.Request) {
	targetQuery := target.RawQuery
	return func(req *http.Request) {
		if req.Body == nil {
			req.Body = c.Request().Body()
		}
		req.URL.Scheme = target.Scheme
		req.URL.Host = target.Host
		req.URL.Path, req.URL.RawPath = joinURLPath(target, req.URL)
		if targetQuery == "" || req.URL.RawQuery == "" {
			req.URL.RawQuery = targetQuery + req.URL.RawQuery
		} else {
			req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery
		}
		if _, ok := req.Header["User-Agent"]; !ok {
			// explicitly disable User-Agent so it's not set to default value
			req.Header.Set("User-Agent", "")
		}
	}
}

// from net/http/httputil/reverseproxy.go
func singleJoiningSlash(a, b string) string {
	aslash := strings.HasSuffix(a, "/")
	bslash := strings.HasPrefix(b, "/")
	switch {
	case aslash && bslash:
		return a + b[1:]
	case !aslash && !bslash:
		return a + "/" + b
	}
	return a + b
}

// from net/http/httputil/reverseproxy.go
func joinURLPath(a, b *url.URL) (path, rawpath string) {
	if a.RawPath == "" && b.RawPath == "" {
		return singleJoiningSlash(a.Path, b.Path), ""
	}
	// Same as singleJoiningSlash, but uses EscapedPath to determine
	// whether a slash should be added
	apath := a.EscapedPath()
	bpath := b.EscapedPath()

	aslash := strings.HasSuffix(apath, "/")
	bslash := strings.HasPrefix(bpath, "/")

	switch {
	case aslash && bslash:
		return a.Path + b.Path[1:], apath + bpath[1:]
	case !aslash && !bslash:
		return a.Path + "/" + b.Path, apath + "/" + bpath
	}
	return a.Path + b.Path, apath + bpath
}

// websocket
func proxyRaw(t *ProxyTarget, c echo.Context) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		in, _, err := w.(http.Hijacker).Hijack()
		if err != nil {
			c.Error(fmt.Errorf("proxy raw, hijack error=%v, url=%s", t.URL, err))
			return
		}
		defer in.Close()

		out, err := net.Dial("tcp", t.URL.Host)
		if err != nil {
			he := echo.NewHTTPError(http.StatusBadGateway, fmt.Sprintf("proxy raw, dial error=%v, url=%s", t.URL, err)).SetRaw(err)
			c.Error(he)
			return
		}
		defer out.Close()

		// Write header
		err = r.Write(out)
		if err != nil {
			he := echo.NewHTTPError(http.StatusBadGateway, fmt.Sprintf("proxy raw, request header copy error=%v, url=%s", t.URL, err)).SetRaw(err)
			c.Error(he)
			return
		}

		errCh := make(chan error, 2)
		cp := func(dst io.Writer, src io.Reader) {
			_, err = io.Copy(dst, src)
			errCh <- err
		}

		go cp(out, in)
		go cp(in, out)
		err = <-errCh
		if err != nil && err != io.EOF {
			c.Logger().Errorf("proxy raw, copy body error=%v, url=%s", t.URL, err)
		}
	})
}

// NewRandomBalancer returns a random proxy balancer.
func NewRandomBalancer(targets []*ProxyTarget) ProxyBalancer {
	b := &randomBalancer{commonBalancer: new(commonBalancer)}
	b.targets = targets
	return b
}

// NewRoundRobinBalancer returns a round-robin proxy balancer.
func NewRoundRobinBalancer(targets []*ProxyTarget) ProxyBalancer {
	b := &roundRobinBalancer{commonBalancer: new(commonBalancer)}
	b.targets = targets
	return b
}

// AddTarget adds an upstream target to the list.
func (b *commonBalancer) AddTarget(target *ProxyTarget) bool {
	for _, t := range b.targets {
		if t.Name == target.Name {
			return false
		}
	}
	b.mutex.Lock()
	defer b.mutex.Unlock()

	if target.FlushInterval <= 0 {
		target.FlushInterval = 100 * time.Millisecond
	}

	b.targets = append(b.targets, target)
	return true
}

// RemoveTarget removes an upstream target from the list.
func (b *commonBalancer) RemoveTarget(name string) bool {
	b.mutex.Lock()
	defer b.mutex.Unlock()
	for i, t := range b.targets {
		if t.Name == name {
			b.targets = append(b.targets[:i], b.targets[i+1:]...)
			return true
		}
	}
	return false
}

// Next randomly returns an upstream target.
func (b *randomBalancer) Next(c echo.Context) *ProxyTarget {
	if b.random == nil {
		b.random = rand.New(rand.NewSource(int64(time.Now().Nanosecond())))
	}
	b.mutex.RLock()
	defer b.mutex.RUnlock()
	return b.targets[b.random.Intn(len(b.targets))]
}

// Next returns an upstream target using round-robin technique.
func (b *roundRobinBalancer) Next(c echo.Context) *ProxyTarget {
	b.i = b.i % uint32(len(b.targets))
	t := b.targets[b.i]
	atomic.AddUint32(&b.i, 1)
	return t
}

// Proxy returns a Proxy middleware.
//
// Proxy middleware forwards the request to upstream server using a configured load balancing technique.
func Proxy(balancer ProxyBalancer) echo.MiddlewareFuncd {
	c := DefaultProxyConfig
	c.Balancer = balancer
	return ProxyWithConfig(c)
}

// ProxyWithConfig returns a Proxy middleware with config.
// See: `Proxy()`
func ProxyWithConfig(config ProxyConfig) echo.MiddlewareFuncd {
	// Defaults
	if config.Skipper == nil {
		config.Skipper = DefaultProxyConfig.Skipper
	}
	if config.Handler == nil {
		config.Handler = DefaultProxyConfig.Handler
	}
	if config.Balancer == nil {
		panic("echo: proxy middleware requires balancer")
	}
	config.Rewrite.Init()
	return func(next echo.Handler) echo.HandlerFunc {
		return func(c echo.Context) (err error) {
			if config.Skipper(c) {
				return next.Handle(c)
			}

			req := c.Request()
			tgt := config.Balancer.Next(c)
			if len(config.ContextKey) > 0 {
				c.Set(config.ContextKey, tgt)
			}
			req.URL().SetPath(config.Rewrite.Rewrite(req.URL().Path()))
			// Fix header
			if len(c.Header(echo.HeaderXRealIP)) == 0 {
				req.Header().Set(echo.HeaderXRealIP, c.RealIP())
			}
			if len(c.Header(echo.HeaderXForwardedProto)) == 0 {
				req.Header().Set(echo.HeaderXForwardedProto, c.Scheme())
			}
			if c.IsWebsocket() && len(c.Header(echo.HeaderXForwardedFor)) == 0 { // For HTTP, it is automatically set by Go HTTP reverse proxy.
				req.Header().Set(echo.HeaderXForwardedFor, c.RealIP())
			}

			return config.Handler(tgt, c)
		}
	}
}
<|endoftext|>


<commit_before>package main

import ()

func ownerGetByEmail(email string) (owner, error) {
	if email == "" {
		return owner{}, errorMissingField
	}

	statement := `
		SELECT ownerHex, email, name, confirmedEmail, joinDate
		FROM owners
		WHERE email=$1;
	`
	row := db.QueryRow(statement, email)

	var o owner
	if err := row.Scan(&o.OwnerHex, &o.Email, &o.Name, &o.ConfirmedEmail, &o.JoinDate); err != nil {
		// TODO: Make sure this is actually no such email.
		return owner{}, errorNoSuchEmail
	}

	return o, nil
}

func ownerGetByOwnerToken(ownerToken string) (owner, error) {
	if ownerToken == "" {
		return owner{}, errorMissingField
	}

	statement := `
		SELECT ownerHex, email, name, confirmedEmail, joinDate
		FROM owners
		WHERE ownerHex IN (
			SELECT ownerHex FROM ownerSessions
			WHERE ownerToken = $1
		);
	`
	row := db.QueryRow(statement, ownerToken)

	var o owner
	if err := row.Scan(&o.OwnerHex, &o.Email, &o.Name, &o.ConfirmedEmail, &o.JoinDate); err != nil {
		logger.Errorf("cannot scan owner: %v\n", err)
		return owner{}, errorInternal
	}

	return o, nil
}

func ownerGetByOwnerHex(ownerHex string) (owner, error) {
	if ownerHex == "" {
		return owner{}, errorMissingField
	}

	statement := `
		SELECT ownerHex, email, name, confirmedEmail, joinDate
		FROM owners
		WHERE ownerHex = $1;
	`
	row := db.QueryRow(statement, ownerHex)

	var o owner
	if err := row.Scan(&o.OwnerHex, &o.Email, &o.Name, &o.ConfirmedEmail, &o.JoinDate); err != nil {
		logger.Errorf("cannot scan owner: %v\n", err)
		return owner{}, errorInternal
	}

	return o, nil
}
<commit_msg>owner_get.go: clean up SQL<commit_after>package main

import ()

var ownersRowColumns string = `
	owners.ownerHex,
	owners.email,
	owners.name,
	owners.confirmedEmail,
	owners.joinDate
`

func ownersRowScan(s sqlScanner, o *owner) error {
	return s.Scan(
		&o.OwnerHex,
		&o.Email,
		&o.Name,
		&o.ConfirmedEmail,
		&o.JoinDate,
	)
}

func ownerGetByEmail(email string) (owner, error) {
	if email == "" {
		return owner{}, errorMissingField
	}

	statement := `
		SELECT ` + ownersRowColumns + `
		FROM owners
		WHERE email=$1;
	`
	row := db.QueryRow(statement, email)

	var o owner
	if err := ownersRowScan(row, &o); err != nil {
		// TODO: Make sure this is actually no such email.
		return owner{}, errorNoSuchEmail
	}

	return o, nil
}

func ownerGetByOwnerToken(ownerToken string) (owner, error) {
	if ownerToken == "" {
		return owner{}, errorMissingField
	}

	statement := `
		SELECT ` + ownersRowColumns + `
		FROM owners
		WHERE owners.ownerHex IN (
			SELECT ownerSessions.ownerHex FROM ownerSessions
			WHERE ownerSessions.ownerToken = $1
		);
	`
	row := db.QueryRow(statement, ownerToken)

	var o owner
	if err := ownersRowScan(row, &o); err != nil {
		logger.Errorf("cannot scan owner: %v\n", err)
		return owner{}, errorInternal
	}

	return o, nil
}

func ownerGetByOwnerHex(ownerHex string) (owner, error) {
	if ownerHex == "" {
		return owner{}, errorMissingField
	}

	statement := `
		SELECT ` + ownersRowColumns + `
		FROM owners
		WHERE ownerHex = $1;
	`
	row := db.QueryRow(statement, ownerHex)

	var o owner
	if err := ownersRowScan(row, &o); err != nil {
		logger.Errorf("cannot scan owner: %v\n", err)
		return owner{}, errorInternal
	}

	return o, nil
}
<|endoftext|>


<commit_before>// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.

package gdb

import (
	"database/sql"
	"github.com/gogf/gf/errors/gerror"
	"github.com/gogf/gf/text/gstr"
	"github.com/gogf/gf/util/gconv"
	"github.com/gogf/gf/util/gutil"
	"reflect"
)

// ScanList converts `r` to struct slice which contains other complex struct attributes.
// Note that the parameter `listPointer` should be type of *[]struct/*[]*struct.
// Usage example:
//
// type Entity struct {
// 	   User       *EntityUser
// 	   UserDetail *EntityUserDetail
//	   UserScores []*EntityUserScores
// }
// var users []*Entity
// or
// var users []Entity
//
// ScanList(&users, "User")
// ScanList(&users, "UserDetail", "User", "uid:Uid")
// ScanList(&users, "UserScores", "User", "uid:Uid")
//
// The parameters "User/UserDetail/UserScores" in the example codes specify the target attribute struct
// that current result will be bound to.
//
// The "uid" in the example codes is the table field name of the result, and the "Uid" is the relational
// struct attribute name - not the attribute name of the bound to target. In the example codes, it's attribute
// name "Uid" of "User" of entity "Entity". It automatically calculates the HasOne/HasMany relationship with
// given `relation` parameter.
//
// See the example or unit testing cases for clear understanding for this function.
func (r Result) ScanList(listPointer interface{}, bindToAttrName string, relationKV ...string) (err error) {
	if r.IsEmpty() {
		return nil
	}
	// Necessary checks for parameters.
	if bindToAttrName == "" {
		return gerror.New(`bindToAttrName should not be empty`)
	}
	//if len(relation) > 0 {
	//	if len(relation) < 2 {
	//		return gerror.New(`relation name and key should are both necessary`)
	//	}
	//	if relation[0] == "" || relation[1] == "" {
	//		return gerror.New(`relation name and key should not be empty`)
	//	}
	//}

	var (
		reflectValue = reflect.ValueOf(listPointer)
		reflectKind  = reflectValue.Kind()
	)
	if reflectKind == reflect.Interface {
		reflectValue = reflectValue.Elem()
		reflectKind = reflectValue.Kind()
	}
	if reflectKind != reflect.Ptr {
		return gerror.Newf("parameter should be type of *[]struct/*[]*struct, but got: %v", reflectKind)
	}
	reflectValue = reflectValue.Elem()
	reflectKind = reflectValue.Kind()
	if reflectKind != reflect.Slice && reflectKind != reflect.Array {
		return gerror.Newf("parameter should be type of *[]struct/*[]*struct, but got: %v", reflectKind)
	}
	length := len(r)
	if length == 0 {
		// The pointed slice is not empty.
		if reflectValue.Len() > 0 {
			// It here checks if it has struct item, which is already initialized.
			// It then returns error to warn the developer its empty and no conversion.
			if v := reflectValue.Index(0); v.Kind() != reflect.Ptr {
				return sql.ErrNoRows
			}
		}
		// Do nothing for empty struct slice.
		return nil
	}
	var (
		arrayValue    reflect.Value // Like: []*Entity
		arrayItemType reflect.Type  // Like: *Entity
		reflectType   = reflect.TypeOf(listPointer)
	)
	if reflectValue.Len() > 0 {
		arrayValue = reflectValue
	} else {
		arrayValue = reflect.MakeSlice(reflectType.Elem(), length, length)
	}

	// Slice element item.
	arrayItemType = arrayValue.Index(0).Type()

	// Relation variables.
	var (
		relationKVStr             string
		relationDataMap           map[string]Value
		relationFromAttrName      string // Eg: relationKV: User, uid:Uid -> User
		relationResultFieldName   string // Eg: relationKV: uid:Uid       -> uid
		relationBindToSubAttrName string // Eg: relationKV: uid:Uid       -> Uid
	)
	if len(relationKV) > 0 {
		if len(relationKV) == 1 {
			relationKVStr = relationKV[0]
		} else {
			relationFromAttrName = relationKV[0]
			relationKVStr = relationKV[1]
		}
		// The relation key string of table filed name and attribute name
		// can be joined with char '=' or ':'.
		array := gstr.SplitAndTrim(relationKVStr, "=")
		if len(array) == 1 {
			// Compatible with old splitting char ':'.
			array = gstr.SplitAndTrim(relationKVStr, ":")
		}
		if len(array) == 2 {
			// Defined table field to relation attribute name.
			// Like:
			// uid:Uid
			// uid:UserId
			relationResultFieldName = array[0]
			relationBindToSubAttrName = array[1]
			if key, _ := gutil.MapPossibleItemByKey(r[0].Map(), relationResultFieldName); key == "" {
				return gerror.Newf(
					`cannot find possible related table field name "%s" from given relation key "%s"`,
					relationResultFieldName,
					relationKVStr,
				)
			} else {
				relationResultFieldName = key
			}
		} else {
			return gerror.New(`parameter relationKV should be format of "ResultFieldName:BindToAttrName"`)
		}
		if relationResultFieldName != "" {
			relationDataMap = r.MapKeyValue(relationResultFieldName)
		}
		if len(relationDataMap) == 0 {
			return gerror.Newf(`cannot find the relation data map, maybe invalid relation given "%v"`, relationKV)
		}
	}
	// Bind to target attribute.
	var (
		ok              bool
		bindToAttrValue reflect.Value
		bindToAttrKind  reflect.Kind
		bindToAttrType  reflect.Type
		bindToAttrField reflect.StructField
	)
	if arrayItemType.Kind() == reflect.Ptr {
		if bindToAttrField, ok = arrayItemType.Elem().FieldByName(bindToAttrName); !ok {
			return gerror.Newf(`invalid parameter bindToAttrName: cannot find attribute with name "%s" from slice element`, bindToAttrName)
		}
	} else {
		if bindToAttrField, ok = arrayItemType.FieldByName(bindToAttrName); !ok {
			return gerror.Newf(`invalid parameter bindToAttrName: cannot find attribute with name "%s" from slice element`, bindToAttrName)
		}
	}
	bindToAttrType = bindToAttrField.Type
	bindToAttrKind = bindToAttrType.Kind()

	// Bind to relation conditions.
	var (
		relationFromAttrValue            reflect.Value
		relationFromAttrField            reflect.Value
		relationBindToSubAttrNameChecked bool
	)
	for i := 0; i < arrayValue.Len(); i++ {
		arrayElemValue := arrayValue.Index(i)
		// The FieldByName should be called on non-pointer reflect.Value.
		if arrayElemValue.Kind() == reflect.Ptr {
			// Like: []*Entity
			arrayElemValue = arrayElemValue.Elem()
			if !arrayElemValue.IsValid() {
				// The element is nil, then create one and set it to the slice.
				// The "reflect.New(itemType.Elem())" creates a new element and returns the address of it.
				// For example:
				// reflect.New(itemType.Elem())        => *Entity
				// reflect.New(itemType.Elem()).Elem() => Entity
				arrayElemValue = reflect.New(arrayItemType.Elem()).Elem()
				arrayValue.Index(i).Set(arrayElemValue.Addr())
			}
		} else {
			// Like: []Entity
		}
		bindToAttrValue = arrayElemValue.FieldByName(bindToAttrName)
		if relationFromAttrName != "" {
			// Attribute value of current slice element.
			relationFromAttrValue = arrayElemValue.FieldByName(relationFromAttrName)
			if relationFromAttrValue.Kind() == reflect.Ptr {
				relationFromAttrValue = relationFromAttrValue.Elem()
			}
		} else {
			// Current slice element.
			relationFromAttrValue = arrayElemValue
		}
		if len(relationDataMap) > 0 && !relationFromAttrValue.IsValid() {
			return gerror.Newf(`invalid relation specified: "%v"`, relationKV)
		}
		// Check and find possible bind to attribute name.
		if relationKVStr != "" && !relationBindToSubAttrNameChecked {
			relationFromAttrField = relationFromAttrValue.FieldByName(relationBindToSubAttrName)
			if !relationFromAttrField.IsValid() {
				var (
					relationFromAttrType = relationFromAttrValue.Type()
					filedMap             = make(map[string]interface{})
				)
				for i := 0; i < relationFromAttrType.NumField(); i++ {
					filedMap[relationFromAttrType.Field(i).Name] = struct{}{}
				}
				if key, _ := gutil.MapPossibleItemByKey(filedMap, relationBindToSubAttrName); key == "" {
					return gerror.Newf(
						`cannot find possible related attribute name "%s" from given relation key "%s"`,
						relationBindToSubAttrName,
						relationKVStr,
					)
				} else {
					relationBindToSubAttrName = key
				}
			}
			relationBindToSubAttrNameChecked = true
		}
		switch bindToAttrKind {
		case reflect.Array, reflect.Slice:
			if len(relationDataMap) > 0 {
				relationFromAttrField = relationFromAttrValue.FieldByName(relationBindToSubAttrName)
				if relationFromAttrField.IsValid() {
					if err = gconv.Structs(
						relationDataMap[gconv.String(relationFromAttrField.Interface())],
						bindToAttrValue.Addr(),
					); err != nil {
						return err
					}
				} else {
					// May be the attribute does not exist yet.
					return gerror.Newf(`invalid relation specified: "%v"`, relationKV)
				}
			} else {
				return gerror.Newf(`relationKey should not be empty as field "%s" is slice`, bindToAttrName)
			}

		case reflect.Ptr:
			var element reflect.Value
			if bindToAttrValue.IsNil() {
				element = reflect.New(bindToAttrType.Elem()).Elem()
			} else {
				element = bindToAttrValue.Elem()
			}
			if len(relationDataMap) > 0 {
				relationFromAttrField = relationFromAttrValue.FieldByName(relationBindToSubAttrName)
				if relationFromAttrField.IsValid() {
					v := relationDataMap[gconv.String(relationFromAttrField.Interface())]
					if v == nil {
						// There's no relational data.
						continue
					}
					if err = gconv.Struct(v, element); err != nil {
						return err
					}
				} else {
					// May be the attribute does not exist yet.
					return gerror.Newf(`invalid relation specified: "%v"`, relationKV)
				}
			} else {
				v := r[i]
				if v == nil {
					// There's no relational data.
					continue
				}
				if err = gconv.Struct(v, element); err != nil {
					return err
				}
			}
			bindToAttrValue.Set(element.Addr())

		case reflect.Struct:
			if len(relationDataMap) > 0 {
				relationFromAttrField = relationFromAttrValue.FieldByName(relationBindToSubAttrName)
				if relationFromAttrField.IsValid() {
					relationDataItem := relationDataMap[gconv.String(relationFromAttrField.Interface())]
					if relationDataItem == nil {
						// There's no relational data.
						continue
					}
					if err = gconv.Struct(relationDataItem, bindToAttrValue); err != nil {
						return err
					}
				} else {
					// May be the attribute does not exist yet.
					return gerror.Newf(`invalid relation specified: "%v"`, relationKV)
				}
			} else {
				relationDataItem := r[i]
				if relationDataItem == nil {
					// There's no relational data.
					continue
				}
				if err = gconv.Struct(relationDataItem, bindToAttrValue); err != nil {
					return err
				}
			}

		default:
			return gerror.Newf(`unsupported attribute type: %s`, bindToAttrKind.String())
		}
	}
	reflect.ValueOf(listPointer).Elem().Set(arrayValue)
	return nil
}
<commit_msg>fix issue #1187<commit_after>// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.

package gdb

import (
	"database/sql"
	"github.com/gogf/gf/errors/gerror"
	"github.com/gogf/gf/text/gstr"
	"github.com/gogf/gf/util/gconv"
	"github.com/gogf/gf/util/gutil"
	"reflect"
)

// ScanList converts `r` to struct slice which contains other complex struct attributes.
// Note that the parameter `listPointer` should be type of *[]struct/*[]*struct.
// Usage example:
//
// type Entity struct {
// 	   User       *EntityUser
// 	   UserDetail *EntityUserDetail
//	   UserScores []*EntityUserScores
// }
// var users []*Entity
// or
// var users []Entity
//
// ScanList(&users, "User")
// ScanList(&users, "UserDetail", "User", "uid:Uid")
// ScanList(&users, "UserScores", "User", "uid:Uid")
//
// The parameters "User/UserDetail/UserScores" in the example codes specify the target attribute struct
// that current result will be bound to.
//
// The "uid" in the example codes is the table field name of the result, and the "Uid" is the relational
// struct attribute name - not the attribute name of the bound to target. In the example codes, it's attribute
// name "Uid" of "User" of entity "Entity". It automatically calculates the HasOne/HasMany relationship with
// given `relation` parameter.
//
// See the example or unit testing cases for clear understanding for this function.
func (r Result) ScanList(listPointer interface{}, bindToAttrName string, relationKV ...string) (err error) {
	if r.IsEmpty() {
		return nil
	}
	// Necessary checks for parameters.
	if bindToAttrName == "" {
		return gerror.New(`bindToAttrName should not be empty`)
	}
	//if len(relation) > 0 {
	//	if len(relation) < 2 {
	//		return gerror.New(`relation name and key should are both necessary`)
	//	}
	//	if relation[0] == "" || relation[1] == "" {
	//		return gerror.New(`relation name and key should not be empty`)
	//	}
	//}

	var (
		reflectValue = reflect.ValueOf(listPointer)
		reflectKind  = reflectValue.Kind()
	)
	if reflectKind == reflect.Interface {
		reflectValue = reflectValue.Elem()
		reflectKind = reflectValue.Kind()
	}
	if reflectKind != reflect.Ptr {
		return gerror.Newf("parameter should be type of *[]struct/*[]*struct, but got: %v", reflectKind)
	}
	reflectValue = reflectValue.Elem()
	reflectKind = reflectValue.Kind()
	if reflectKind != reflect.Slice && reflectKind != reflect.Array {
		return gerror.Newf("parameter should be type of *[]struct/*[]*struct, but got: %v", reflectKind)
	}
	length := len(r)
	if length == 0 {
		// The pointed slice is not empty.
		if reflectValue.Len() > 0 {
			// It here checks if it has struct item, which is already initialized.
			// It then returns error to warn the developer its empty and no conversion.
			if v := reflectValue.Index(0); v.Kind() != reflect.Ptr {
				return sql.ErrNoRows
			}
		}
		// Do nothing for empty struct slice.
		return nil
	}
	var (
		arrayValue    reflect.Value // Like: []*Entity
		arrayItemType reflect.Type  // Like: *Entity
		reflectType   = reflect.TypeOf(listPointer)
	)
	if reflectValue.Len() > 0 {
		arrayValue = reflectValue
	} else {
		arrayValue = reflect.MakeSlice(reflectType.Elem(), length, length)
	}

	// Slice element item.
	arrayItemType = arrayValue.Index(0).Type()

	// Relation variables.
	var (
		relationKVStr             string
		relationDataMap           map[string]Value
		relationFromAttrName      string // Eg: relationKV: User, uid:Uid -> User
		relationResultFieldName   string // Eg: relationKV: uid:Uid       -> uid
		relationBindToSubAttrName string // Eg: relationKV: uid:Uid       -> Uid
	)
	if len(relationKV) > 0 {
		if len(relationKV) == 1 {
			relationKVStr = relationKV[0]
		} else {
			relationFromAttrName = relationKV[0]
			relationKVStr = relationKV[1]
		}
		// The relation key string of table filed name and attribute name
		// can be joined with char '=' or ':'.
		array := gstr.SplitAndTrim(relationKVStr, "=")
		if len(array) == 1 {
			// Compatible with old splitting char ':'.
			array = gstr.SplitAndTrim(relationKVStr, ":")
		}
		if len(array) == 2 {
			// Defined table field to relation attribute name.
			// Like:
			// uid:Uid
			// uid:UserId
			relationResultFieldName = array[0]
			relationBindToSubAttrName = array[1]
			if key, _ := gutil.MapPossibleItemByKey(r[0].Map(), relationResultFieldName); key == "" {
				return gerror.Newf(
					`cannot find possible related table field name "%s" from given relation key "%s"`,
					relationResultFieldName,
					relationKVStr,
				)
			} else {
				relationResultFieldName = key
			}
		} else {
			return gerror.New(`parameter relationKV should be format of "ResultFieldName:BindToAttrName"`)
		}
		if relationResultFieldName != "" {
			relationDataMap = r.MapKeyValue(relationResultFieldName)
		}
		if len(relationDataMap) == 0 {
			return gerror.Newf(`cannot find the relation data map, maybe invalid relation given "%v"`, relationKV)
		}
	}
	// Bind to target attribute.
	var (
		ok              bool
		bindToAttrValue reflect.Value
		bindToAttrKind  reflect.Kind
		bindToAttrType  reflect.Type
		bindToAttrField reflect.StructField
	)
	if arrayItemType.Kind() == reflect.Ptr {
		if bindToAttrField, ok = arrayItemType.Elem().FieldByName(bindToAttrName); !ok {
			return gerror.Newf(`invalid parameter bindToAttrName: cannot find attribute with name "%s" from slice element`, bindToAttrName)
		}
	} else {
		if bindToAttrField, ok = arrayItemType.FieldByName(bindToAttrName); !ok {
			return gerror.Newf(`invalid parameter bindToAttrName: cannot find attribute with name "%s" from slice element`, bindToAttrName)
		}
	}
	bindToAttrType = bindToAttrField.Type
	bindToAttrKind = bindToAttrType.Kind()

	// Bind to relation conditions.
	var (
		relationFromAttrValue            reflect.Value
		relationFromAttrField            reflect.Value
		relationBindToSubAttrNameChecked bool
	)
	for i := 0; i < arrayValue.Len(); i++ {
		arrayElemValue := arrayValue.Index(i)
		// The FieldByName should be called on non-pointer reflect.Value.
		if arrayElemValue.Kind() == reflect.Ptr {
			// Like: []*Entity
			arrayElemValue = arrayElemValue.Elem()
			if !arrayElemValue.IsValid() {
				// The element is nil, then create one and set it to the slice.
				// The "reflect.New(itemType.Elem())" creates a new element and returns the address of it.
				// For example:
				// reflect.New(itemType.Elem())        => *Entity
				// reflect.New(itemType.Elem()).Elem() => Entity
				arrayElemValue = reflect.New(arrayItemType.Elem()).Elem()
				arrayValue.Index(i).Set(arrayElemValue.Addr())
			}
		} else {
			// Like: []Entity
		}
		bindToAttrValue = arrayElemValue.FieldByName(bindToAttrName)
		if relationFromAttrName != "" {
			// Attribute value of current slice element.
			relationFromAttrValue = arrayElemValue.FieldByName(relationFromAttrName)
			if relationFromAttrValue.Kind() == reflect.Ptr {
				relationFromAttrValue = relationFromAttrValue.Elem()
			}
		} else {
			// Current slice element.
			relationFromAttrValue = arrayElemValue
		}
		if len(relationDataMap) > 0 && !relationFromAttrValue.IsValid() {
			return gerror.Newf(`invalid relation specified: "%v"`, relationKV)
		}
		// Check and find possible bind to attribute name.
		if relationKVStr != "" && !relationBindToSubAttrNameChecked {
			relationFromAttrField = relationFromAttrValue.FieldByName(relationBindToSubAttrName)
			if !relationFromAttrField.IsValid() {
				var (
					relationFromAttrType = relationFromAttrValue.Type()
					filedMap             = make(map[string]interface{})
				)
				for i := 0; i < relationFromAttrType.NumField(); i++ {
					filedMap[relationFromAttrType.Field(i).Name] = struct{}{}
				}
				if key, _ := gutil.MapPossibleItemByKey(filedMap, relationBindToSubAttrName); key == "" {
					return gerror.Newf(
						`cannot find possible related attribute name "%s" from given relation key "%s"`,
						relationBindToSubAttrName,
						relationKVStr,
					)
				} else {
					relationBindToSubAttrName = key
				}
			}
			relationBindToSubAttrNameChecked = true
		}
		switch bindToAttrKind {
		case reflect.Array, reflect.Slice:
			if len(relationDataMap) > 0 {
				relationFromAttrField = relationFromAttrValue.FieldByName(relationBindToSubAttrName)
				if relationFromAttrField.IsValid() {
					if err = gconv.Structs(
						relationDataMap[gconv.String(relationFromAttrField.Interface())],
						bindToAttrValue.Addr(),
					); err != nil {
						return err
					}
				} else {
					// May be the attribute does not exist yet.
					return gerror.Newf(`invalid relation specified: "%v"`, relationKV)
				}
			} else {
				return gerror.Newf(`relationKey should not be empty as field "%s" is slice`, bindToAttrName)
			}

		case reflect.Ptr:
			var element reflect.Value
			if bindToAttrValue.IsNil() {
				element = reflect.New(bindToAttrType.Elem()).Elem()
			} else {
				element = bindToAttrValue.Elem()
			}
			if len(relationDataMap) > 0 {
				relationFromAttrField = relationFromAttrValue.FieldByName(relationBindToSubAttrName)
				if relationFromAttrField.IsValid() {
					v := relationDataMap[gconv.String(relationFromAttrField.Interface())]
					if v == nil {
						// There's no relational data.
						continue
					}
					if err = gconv.Struct(v, element); err != nil {
						return err
					}
				} else {
					// May be the attribute does not exist yet.
					return gerror.Newf(`invalid relation specified: "%v"`, relationKV)
				}
			} else {
				if i >= len(r) {
					// There's no relational data.
					continue
				}
				v := r[i]
				if v == nil {
					// There's no relational data.
					continue
				}
				if err = gconv.Struct(v, element); err != nil {
					return err
				}
			}
			bindToAttrValue.Set(element.Addr())

		case reflect.Struct:
			if len(relationDataMap) > 0 {
				relationFromAttrField = relationFromAttrValue.FieldByName(relationBindToSubAttrName)
				if relationFromAttrField.IsValid() {
					relationDataItem := relationDataMap[gconv.String(relationFromAttrField.Interface())]
					if relationDataItem == nil {
						// There's no relational data.
						continue
					}
					if err = gconv.Struct(relationDataItem, bindToAttrValue); err != nil {
						return err
					}
				} else {
					// May be the attribute does not exist yet.
					return gerror.Newf(`invalid relation specified: "%v"`, relationKV)
				}
			} else {
				if i >= len(r) {
					// There's no relational data.
					continue
				}
				relationDataItem := r[i]
				if relationDataItem == nil {
					// There's no relational data.
					continue
				}
				if err = gconv.Struct(relationDataItem, bindToAttrValue); err != nil {
					return err
				}
			}

		default:
			return gerror.Newf(`unsupported attribute type: %s`, bindToAttrKind.String())
		}
	}
	reflect.ValueOf(listPointer).Elem().Set(arrayValue)
	return nil
}
<|endoftext|>


<commit_before>// Package scanner provides a recursive file scanner that is useful for
// efficiently processing relatively static datasets.
package scanner

import (
	"io/ioutil"
	"os"
	"strings"
	"sync"
)

// Scanner recursively scans a directory for files.
type Scanner struct {

	// Buffer is length of the files channel buffer.
	Buffer int

	// errs is the channel that errors are sent to.
	errs chan error

	// files is the challen that discovered files are sent to.
	files chan string

	// path is the directory being scanned.
	path string

	// separator is the OS's path separator represented as a string. We
	// store this value in a struct so we don;t have to repeatedly convert
	// the rune to a string. This is a micro-optimization, but an
	// optimization none the less.
	separator string
}

// New returns a new Scanner instance.
func New(path string) *Scanner {
	return &Scanner{
		Buffer:    1,
		errs:      make(chan error),
		path:      path,
		separator: string(os.PathSeparator),
	}
}

// Scan recursively scans the directory and sends the files and errors to
// the passed Handler in goroutines.
func (s *Scanner) Scan(h Handler) {
	var wg sync.WaitGroup
	s.files = make(chan string, s.Buffer)

	go func() {
		s.scan(s.path)
		close(s.files)
		close(s.errs)
	}()

	if h == nil {
		return
	}

	wg.Add(2)

	go func() {
		defer wg.Done()
		for err := range s.errs {
			h.HandleError(err)
		}
	}()

	go func() {
		defer wg.Done()
		for f := range s.files {
			h.Handle(f)
		}
	}()

	wg.Wait()
}

// scan recursively scans path and sends the discovered files and errors to
// the built-in channels.
func (s *Scanner) scan(path string) {
	files, err := ioutil.ReadDir(path)
	if err != nil {
		s.errs <- err
		return
	}

	basedir := strings.TrimRight(path, s.separator)
	for _, f := range files {
		file := basedir + s.separator + f.Name()
		if f.IsDir() {
			s.scan(file)
		} else {
			s.files <- file
		}
	}
}

// Handler is an interface for handlers that process scanned files.
type Handler interface {

	// Handle is passed the path to the file that was discovered during the
	// scan operation. Files are passed in a single-threaded manner, so
	// concurrency is the responsibility of the Handler implementation.
	Handle(string)

	// HandleError is passed the errors that occur during scan operations.
	// Like the Handle method, errors are passed in a single-threaded
	// manner.
	HandleError(error)
}

// MemoryHandler returns a new memoryHandler instance, which stores the
// scanned files and errors in the exported Files and Errors fields
// respectively.
func MemoryHandler() *memoryHandler {
	return &memoryHandler{}
}

// memoryHandler implements Handler and stores the scanned files and errors
// in slices.
type memoryHandler struct {
	Files  []string
	Errors []error
}

// Handle implements Handler.Handle and stores file in a struct.
func (h *memoryHandler) Handle(file string) {
	h.Files = append(h.Files, file)
}

// HandleError implements Handler.HandleError stores err in a struct.
func (h *memoryHandler) HandleError(err error) {
	h.Errors = append(h.Errors, err)
}
<commit_msg>Fixed typos in comments<commit_after>// Package scanner provides a recursive file scanner that is useful for
// efficiently processing relatively static datasets.
package scanner

import (
	"io/ioutil"
	"os"
	"strings"
	"sync"
)

// Scanner recursively scans a directory for files.
type Scanner struct {

	// Buffer is length of the files channel buffer.
	Buffer int

	// errs is the channel that errors are sent to.
	errs chan error

	// files is the channel that discovered files are sent to.
	files chan string

	// path is the directory being scanned.
	path string

	// separator is the OS's path separator represented as a string. We
	// store this value in a struct so we don't have to repeatedly convert
	// the rune to a string. This is a micro-optimization, but an
	// optimization none the less.
	separator string
}

// New returns a new Scanner instance.
func New(path string) *Scanner {
	return &Scanner{
		Buffer:    1,
		errs:      make(chan error),
		path:      path,
		separator: string(os.PathSeparator),
	}
}

// Scan recursively scans the directory and sends the files and errors to
// the passed Handler in goroutines.
func (s *Scanner) Scan(h Handler) {
	var wg sync.WaitGroup
	s.files = make(chan string, s.Buffer)

	go func() {
		s.scan(s.path)
		close(s.files)
		close(s.errs)
	}()

	if h == nil {
		return
	}

	wg.Add(2)

	go func() {
		defer wg.Done()
		for err := range s.errs {
			h.HandleError(err)
		}
	}()

	go func() {
		defer wg.Done()
		for f := range s.files {
			h.Handle(f)
		}
	}()

	wg.Wait()
}

// scan recursively scans path and sends the discovered files and errors to
// the built-in channels.
func (s *Scanner) scan(path string) {
	files, err := ioutil.ReadDir(path)
	if err != nil {
		s.errs <- err
		return
	}

	basedir := strings.TrimRight(path, s.separator)
	for _, f := range files {
		file := basedir + s.separator + f.Name()
		if f.IsDir() {
			s.scan(file)
		} else {
			s.files <- file
		}
	}
}

// Handler is an interface for handlers that process scanned files.
type Handler interface {

	// Handle is passed the path to the file that was discovered during the
	// scan operation. Files are passed in a single-threaded manner, so
	// concurrency is the responsibility of the Handler implementation.
	Handle(string)

	// HandleError is passed the errors that occur during scan operations.
	// Like the Handle method, errors are passed in a single-threaded
	// manner.
	HandleError(error)
}

// MemoryHandler returns a new memoryHandler instance, which stores the
// scanned files and errors in the exported Files and Errors fields
// respectively.
func MemoryHandler() *memoryHandler {
	return &memoryHandler{}
}

// memoryHandler implements Handler and stores the scanned files and errors
// in slices.
type memoryHandler struct {
	Files  []string
	Errors []error
}

// Handle implements Handler.Handle and stores file in a struct.
func (h *memoryHandler) Handle(file string) {
	h.Files = append(h.Files, file)
}

// HandleError implements Handler.HandleError stores err in a struct.
func (h *memoryHandler) HandleError(err error) {
	h.Errors = append(h.Errors, err)
}
<|endoftext|>


<commit_before>package css

import (
	"bufio"
	"bytes"
	"io"
	"strconv"
)

// Scanner implements a CSS3 standard compliant scanner.
type Scanner struct {
	// Type is set after parsing an ident-token, function-token,
	// at-keyword-token, hash-token, string-token, and url-token.
	// It is set to either "id" or "unrestricted".
	Type string

	// Value is the literal representation of the last read token.
	Value string

	// These numeric values are set after scanning a number-token,
	// a percentage-token, or a dimension-token.
	IntValue    int
	NumberValue int

	// Start and End are set after each unicode-range token.
	Start int
	End   int

	// Ending represents the ending code point of a string.
	Ending rune

	rd  io.RuneReader
	pos Pos

	buf  [3]rune // circular buffer
	bufi int     // circular buffer index
	bufn int     // number of buffered characters
}

// NewScanner returns a new instance of Scanner.
func NewScanner(r io.Reader) *Scanner {
	// TODO(benbjohnson): Determine fallback encoding (§3.2).
	return &Scanner{
		rd: bufio.NewReader(r),
	}
}

func (s *Scanner) Scan() (pos Pos, tok Token) {
	// Mark the start position for this scan.
	pos = s.pos

	// Initialize fields.
	s.Type = "unrestricted"
	s.Value = ""
	s.IntValue = 0
	s.NumberValue = 0
	s.Start = 0
	s.End = 0
	s.Ending = '\000'

	// Read next code point.
	ch, err := s.read()
	if err == io.EOF {
		tok = EOF
		return
	}

	// Scan all contiguous whitespace.
	if isWhitespace(ch) {
		tok = WHITESPACE
		s.Value = s.scanWhitespace()
		return
	}

	// Scan a string if it starts with a quote.
	if ch == '"' || ch == '\'' {
		tok, s.Value = s.scanString()
		return
	}

	// Scan a hash token.
	if ch == '#' {
		tok, s.Value = s.scanHash()
		return
	}

	// Scan a suffix-match token.
	if ch == '$' {
		if next, err := s.read(); err != nil {
			tok = EOF
		} else if next == '=' {
			tok, s.Value = SUFFIXMATCH, "$="
		} else {
			s.unread()
			tok, s.Value = DELIM, string(ch)
		}
		return
	}

	return
}

// scanWhitespace consumes the current code point and all subsequent whitespace.
func (s *Scanner) scanWhitespace() string {
	var buf bytes.Buffer
	_, _ = buf.WriteRune(s.peek())
	for {
		ch, err := s.read()
		if err == io.EOF {
			break
		} else if !isWhitespace(ch) {
			s.unread()
			break
		}
		_, _ = buf.WriteRune(ch)
	}
	return buf.String()
}

// scanString consumes a quoted string. (§4.3.4)
//
// This assumes that the current token is a single or double quote.
// This function consumes all code points and escaped code points up until
// a matching, unescaped ending quote.
// An EOF closes out a string but does not return an error.
// A newline will close a string and returns a bad-string token.
func (s *Scanner) scanString() (Token, string) {
	var buf bytes.Buffer
	s.Ending = s.peek()
	for {
		ch, err := s.read()
		if err == io.EOF || ch == s.Ending {
			return STRING, buf.String()
		} else if ch == '\n' {
			s.unread()
			return BADSTRING, buf.String()
		} else if ch == '\\' {
			if s.peekEscape() {
				_, _ = buf.WriteRune(s.scanEscape())
				continue
			}
			if next, err := s.read(); err == io.EOF {
				continue
			} else if next == '\n' {
				_, _ = buf.WriteRune(next)
			}
		} else {
			_, _ = buf.WriteRune(ch)
		}
	}
}

// scanHash consumes a hash token.
//
// This assumes the current token is a '#' code point.
// It will return a hash token if the next code points are a name or valid escape.
// It will return a delim token otherwise.
// Hash tokens' type flag is set to "id" if its value is an identifier.
func (s *Scanner) scanHash() (Token, string) {
	// If there is a name following the hash then we have a hash token.
	ch, _ := s.read()
	if isName(ch) || s.peekEscape() {
		// If the name is an identifier then change the type.
		if s.peekIdent() {
			s.Type = "id"
		}
		return HASH, s.scanName()
	}

	// If there is no name following the hash symbol then return delim-token.
	return DELIM, "#"
}

// scanName consumes a name.
func (s *Scanner) scanName() string {
	return "" // TODO(benbjohnson)
}

// scanEscape consumes an escaped code point.
func (s *Scanner) scanEscape() rune {
	var buf bytes.Buffer
	ch, err := s.read()
	if isHexDigit(ch) {
		_, _ = buf.WriteRune(ch)
		for i := 0; i < 5; i++ {
			if next, err := s.read(); err == io.EOF || isWhitespace(next) {
				break
			} else if !isHexDigit(next) {
				s.unread()
				break
			} else {
				_, _ = buf.WriteRune(next)
			}
		}
		v, _ := strconv.ParseInt(buf.String(), 16, 0)
		return rune(v)
	} else if err == io.EOF {
		return '\uFFFD'
	} else {
		return ch
	}
}

// peekEscape checks if the next code points are a valid escape.
func (s *Scanner) peekEscape() bool {
	// If the current code point is not a backslash then this is not an escape.
	if s.peek() != '\\' {
		return false
	}

	// If the next code point is a newline then this is not an escape.
	next, err := s.read()
	if err != io.EOF {
		s.unread()
	}
	return next != '\n'
}

// peekIdent checks if the next code points are a valid identifier.
func (s *Scanner) peekIdent() bool {
	return false // TODO(benbjohnson)
}

// read reads the next rune from the reader.
func (s *Scanner) read() (rune, error) {
	// If we have runes on our internal lookahead buffer then return those.
	if s.bufn > 0 {
		s.bufi = ((s.bufi + 1) % len(s.buf))
		s.bufn--
		if ch := s.buf[s.bufi]; ch != '\000' {
			return ch, nil
		}
		return 0, io.EOF
	}

	// Otherwise read from the reader.
	ch, _, err := s.rd.ReadRune()
	if err != nil {
		return 0, err
	}

	// Preprocess the input stream by replacing FF with LF. (§3.3)
	if ch == '\f' {
		ch = '\n'
	}

	// Preprocess the input stream by replacing CR and CRLF with LF. (§3.3)
	if ch == '\r' {
		if ch, _, err := s.rd.ReadRune(); err == io.EOF {
			// nop
		} else if err != nil {
			return 0, err
		} else if ch != '\n' {
			s.unread()
		}
		ch = '\n'
	}

	// Replace NULL with Unicode replacement character. (§3.3)
	if ch == '\000' {
		ch = '\uFFFD'
	}

	// Track scanner position.
	if ch == '\n' {
		s.pos.Line++
		s.pos.Char = 0
	} else {
		s.pos.Char++
	}

	// Add to circular buffer.
	s.bufi = ((s.bufi + 1) % len(s.buf))
	s.buf[s.bufi] = ch
	return ch, nil
}

// unread puts a run on the internal buffer.
func (s *Scanner) unread() {
	s.bufi = ((s.bufi + len(s.buf) - 1) % len(s.buf))
	s.bufn++
}

// peek reads the current code point.
func (s *Scanner) peek() rune {
	return s.buf[s.bufi]
}

// isWhitespace returns true if the rune is a space, tab, or newline.
func isWhitespace(ch rune) bool {
	return ch == ' ' || ch == '\t' || ch == '\n'
}

// isLetter returns true if the rune is a letter.
func isLetter(ch rune) bool {
	return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')
}

// isDigit returns true if the rune is a digit.
func isDigit(ch rune) bool {
	return (ch >= '0' && ch <= '9')
}

// isHexDigit returns true if the rune is a hex digit.
func isHexDigit(ch rune) bool {
	return (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')
}

// isNonASCII returns true if the rune is greater than U+0080.
func isNonASCII(ch rune) bool {
	return ch >= '\u0080'
}

// isNameStart returns true if the rune can start a name.
func isNameStart(ch rune) bool {
	return isLetter(ch) || isNonASCII(ch) || ch == '_'
}

// isName returns true if the character is a name code point.
func isName(ch rune) bool {
	return isNameStart(ch) || isDigit(ch) || ch == '-'
}
<commit_msg>Change EOF to a rune marker.<commit_after>package css

import (
	"bufio"
	"bytes"
	"io"
	"strconv"
)

// eof represents an EOF file byte.
var eof rune = 0

// Scanner implements a CSS3 standard compliant scanner.
type Scanner struct {
	// Type is set after parsing an ident-token, function-token,
	// at-keyword-token, hash-token, string-token, and url-token.
	// It is set to either "id" or "unrestricted".
	Type string

	// Value is the literal representation of the last read token.
	Value string

	// These numeric values are set after scanning a number-token,
	// a percentage-token, or a dimension-token.
	IntValue    int
	NumberValue int

	// Start and End are set after each unicode-range token.
	Start int
	End   int

	// Ending represents the ending code point of a string.
	Ending rune

	rd  io.RuneReader
	pos Pos

	buf  [3]rune // circular buffer
	bufi int     // circular buffer index
	bufn int     // number of buffered characters
}

// NewScanner returns a new instance of Scanner.
func NewScanner(r io.Reader) *Scanner {
	// TODO(benbjohnson): Determine fallback encoding (§3.2).
	return &Scanner{
		rd: bufio.NewReader(r),
	}
}

func (s *Scanner) Scan() (pos Pos, tok Token) {
	// Mark the start position for this scan.
	pos = s.pos

	// Initialize fields.
	s.Type = "unrestricted"
	s.Value = ""
	s.IntValue = 0
	s.NumberValue = 0
	s.Start = 0
	s.End = 0
	s.Ending = '\000'

	// Read next code point.
	ch := s.read()
	if ch == eof {
		tok = EOF
		return
	}

	// Scan all contiguous whitespace.
	if isWhitespace(ch) {
		tok = WHITESPACE
		s.Value = s.scanWhitespace()
		return
	}

	// Scan a string if it starts with a quote.
	if ch == '"' || ch == '\'' {
		tok, s.Value = s.scanString()
		return
	}

	// Scan a hash token.
	if ch == '#' {
		tok, s.Value = s.scanHash()
		return
	}

	// Scan a suffix-match token.
	if ch == '$' {
		if next := s.read(); next == eof {
			tok = EOF
		} else if next == '=' {
			tok, s.Value = SUFFIXMATCH, "$="
		} else {
			s.unread()
			tok, s.Value = DELIM, string(ch)
		}
		return
	}

	return
}

// scanWhitespace consumes the current code point and all subsequent whitespace.
func (s *Scanner) scanWhitespace() string {
	var buf bytes.Buffer
	_, _ = buf.WriteRune(s.peek())
	for {
		ch := s.read()
		if ch == eof {
			break
		} else if !isWhitespace(ch) {
			s.unread()
			break
		}
		_, _ = buf.WriteRune(ch)
	}
	return buf.String()
}

// scanString consumes a quoted string. (§4.3.4)
//
// This assumes that the current token is a single or double quote.
// This function consumes all code points and escaped code points up until
// a matching, unescaped ending quote.
// An EOF closes out a string but does not return an error.
// A newline will close a string and returns a bad-string token.
func (s *Scanner) scanString() (Token, string) {
	var buf bytes.Buffer
	s.Ending = s.peek()
	for {
		ch := s.read()
		if ch == eof || ch == s.Ending {
			return STRING, buf.String()
		} else if ch == '\n' {
			s.unread()
			return BADSTRING, buf.String()
		} else if ch == '\\' {
			if s.peekEscape() {
				_, _ = buf.WriteRune(s.scanEscape())
				continue
			}
			if next := s.read(); next == eof {
				continue
			} else if next == '\n' {
				_, _ = buf.WriteRune(next)
			}
		} else {
			_, _ = buf.WriteRune(ch)
		}
	}
}

// scanHash consumes a hash token.
//
// This assumes the current token is a '#' code point.
// It will return a hash token if the next code points are a name or valid escape.
// It will return a delim token otherwise.
// Hash tokens' type flag is set to "id" if its value is an identifier.
func (s *Scanner) scanHash() (Token, string) {
	// If there is a name following the hash then we have a hash token.
	ch := s.read()
	if isName(ch) || s.peekEscape() {
		// If the name is an identifier then change the type.
		if s.peekIdent() {
			s.Type = "id"
		}
		return HASH, s.scanName()
	}

	// If there is no name following the hash symbol then return delim-token.
	return DELIM, "#"
}

// scanName consumes a name.
func (s *Scanner) scanName() string {
	return "" // TODO(benbjohnson)
}

// scanEscape consumes an escaped code point.
func (s *Scanner) scanEscape() rune {
	var buf bytes.Buffer
	ch := s.read()
	if isHexDigit(ch) {
		_, _ = buf.WriteRune(ch)
		for i := 0; i < 5; i++ {
			if next := s.read(); next == eof || isWhitespace(next) {
				break
			} else if !isHexDigit(next) {
				s.unread()
				break
			} else {
				_, _ = buf.WriteRune(next)
			}
		}
		v, _ := strconv.ParseInt(buf.String(), 16, 0)
		return rune(v)
	} else if ch == eof {
		return '\uFFFD'
	} else {
		return ch
	}
}

// peekEscape checks if the next code points are a valid escape.
func (s *Scanner) peekEscape() bool {
	// If the current code point is not a backslash then this is not an escape.
	if s.peek() != '\\' {
		return false
	}

	// If the next code point is a newline then this is not an escape.
	next := s.read()
	if next != eof {
		s.unread()
	}
	return next != '\n'
}

// peekIdent checks if the next code points are a valid identifier.
func (s *Scanner) peekIdent() bool {
	return false // TODO(benbjohnson)
}

// read reads the next rune from the reader.
// This function will initially check for any characters that have been pushed
// back onto the lookahead buffer and return those. Otherwise it will read from
// the reader and do preprocessing to convert newline characters and NULL.
// EOF is converted to a zero rune (\000) and returned.
func (s *Scanner) read() rune {
	// If we have runes on our internal lookahead buffer then return those.
	if s.bufn > 0 {
		s.bufi = ((s.bufi + 1) % len(s.buf))
		s.bufn--
		return s.buf[s.bufi]
	}

	// Otherwise read from the reader.
	ch, _, err := s.rd.ReadRune()
	if err != nil {
		return eof
	}

	// Preprocess the input stream by replacing FF with LF. (§3.3)
	if ch == '\f' {
		ch = '\n'
	}

	// Preprocess the input stream by replacing CR and CRLF with LF. (§3.3)
	if ch == '\r' {
		if ch, _, err := s.rd.ReadRune(); err != nil {
			// nop
		} else if ch != '\n' {
			s.unread()
		}
		ch = '\n'
	}

	// Replace NULL with Unicode replacement character. (§3.3)
	if ch == '\000' {
		ch = '\uFFFD'
	}

	// Track scanner position.
	if ch == '\n' {
		s.pos.Line++
		s.pos.Char = 0
	} else {
		s.pos.Char++
	}

	// Add to circular buffer.
	s.bufi = ((s.bufi + 1) % len(s.buf))
	s.buf[s.bufi] = ch
	return ch
}

// unread puts a run on the internal buffer.
func (s *Scanner) unread() {
	s.bufi = ((s.bufi + len(s.buf) - 1) % len(s.buf))
	s.bufn++
}

// peek reads the current code point.
func (s *Scanner) peek() rune {
	return s.buf[s.bufi]
}

// isWhitespace returns true if the rune is a space, tab, or newline.
func isWhitespace(ch rune) bool {
	return ch == ' ' || ch == '\t' || ch == '\n'
}

// isLetter returns true if the rune is a letter.
func isLetter(ch rune) bool {
	return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')
}

// isDigit returns true if the rune is a digit.
func isDigit(ch rune) bool {
	return (ch >= '0' && ch <= '9')
}

// isHexDigit returns true if the rune is a hex digit.
func isHexDigit(ch rune) bool {
	return (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')
}

// isNonASCII returns true if the rune is greater than U+0080.
func isNonASCII(ch rune) bool {
	return ch >= '\u0080'
}

// isNameStart returns true if the rune can start a name.
func isNameStart(ch rune) bool {
	return isLetter(ch) || isNonASCII(ch) || ch == '_'
}

// isName returns true if the character is a name code point.
func isName(ch rune) bool {
	return isNameStart(ch) || isDigit(ch) || ch == '-'
}
<|endoftext|>


<commit_before>/*
Copyright 2018 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
	"flag"
	"net/http"
	"os"
	"time"

	"github.com/golang/glog"
	kube_flag "k8s.io/apiserver/pkg/util/flag"
	"k8s.io/autoscaler/vertical-pod-autoscaler/common"
	"k8s.io/autoscaler/vertical-pod-autoscaler/pkg/admission-controller/logic"
	vpa_clientset "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/client/clientset/versioned"
	vpa_lister "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/client/listers/autoscaling.k8s.io/v1beta1"
	"k8s.io/autoscaler/vertical-pod-autoscaler/pkg/utils/metrics"
	metrics_admission "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/utils/metrics/admission"
	vpa_api_util "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/utils/vpa"
	"k8s.io/client-go/rest"
)

var (
	certsConfiguration = &certsConfig{
		clientCaFile:  flag.String("client-ca-file", "/etc/tls-certs/caCert.pem", "Path to CA PEM file."),
		tlsCertFile:   flag.String("tls-cert-file", "/etc/tls-certs/serverCert.pem", "Path to server certificate PEM file."),
		tlsPrivateKey: flag.String("tls-private-key", "/etc/tls-certs/serverKey.pem", "Path to server certificate key PEM file."),
	}

	address   = flag.String("address", ":8944", "The address to expose Prometheus metrics.")
	namespace = os.Getenv("NAMESPACE")
)

func newReadyVPALister(stopChannel <-chan struct{}) vpa_lister.VerticalPodAutoscalerLister {
	config, err := rest.InClusterConfig()
	if err != nil {
		glog.Fatal(err)
	}
	vpaClient := vpa_clientset.NewForConfigOrDie(config)
	return vpa_api_util.NewAllVpasLister(vpaClient, stopChannel)
}

func main() {
	kube_flag.InitFlags()
	glog.V(1).Infof("Vertical Pod Autoscaler %s Admission Controller", common.VerticalPodAutoscalerVersion)

	healthCheck := metrics.NewHealthCheck(time.Minute, false)
	metrics.Initialize(*address, healthCheck)
	metrics_admission.Register()

	certs := initCerts(*certsConfiguration)
	stopChannel := make(chan struct{})
	vpaLister := newReadyVPALister(stopChannel)
	as := logic.NewAdmissionServer(logic.NewRecommendationProvider(vpaLister, vpa_api_util.NewCappingRecommendationProcessor()), logic.NewDefaultPodPreProcessor())
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		as.Serve(w, r)
		healthCheck.UpdateLastActivity()
	})
	clientset := getClient()
	server := &http.Server{
		Addr:      ":8000",
		TLSConfig: configTLS(clientset, certs.serverCert, certs.serverKey),
	}
	go selfRegistration(clientset, certs.caCert, &namespace)
	server.ListenAndServeTLS("", "")
}
<commit_msg>allow to configure the port the admission-controller listen onto<commit_after>/*
Copyright 2018 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
	"flag"
	"fmt"
	"net/http"
	"os"
	"time"

	"github.com/golang/glog"
	kube_flag "k8s.io/apiserver/pkg/util/flag"
	"k8s.io/autoscaler/vertical-pod-autoscaler/common"
	"k8s.io/autoscaler/vertical-pod-autoscaler/pkg/admission-controller/logic"
	vpa_clientset "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/client/clientset/versioned"
	vpa_lister "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/client/listers/autoscaling.k8s.io/v1beta1"
	"k8s.io/autoscaler/vertical-pod-autoscaler/pkg/utils/metrics"
	metrics_admission "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/utils/metrics/admission"
	vpa_api_util "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/utils/vpa"
	"k8s.io/client-go/rest"
)

var (
	certsConfiguration = &certsConfig{
		clientCaFile:  flag.String("client-ca-file", "/etc/tls-certs/caCert.pem", "Path to CA PEM file."),
		tlsCertFile:   flag.String("tls-cert-file", "/etc/tls-certs/serverCert.pem", "Path to server certificate PEM file."),
		tlsPrivateKey: flag.String("tls-private-key", "/etc/tls-certs/serverKey.pem", "Path to server certificate key PEM file."),
	}

	port      = flag.Int("port", 8000, "The port to listen on.")
	address   = flag.String("address", ":8944", "The address to expose Prometheus metrics.")
	namespace = os.Getenv("NAMESPACE")
)

func newReadyVPALister(stopChannel <-chan struct{}) vpa_lister.VerticalPodAutoscalerLister {
	config, err := rest.InClusterConfig()
	if err != nil {
		glog.Fatal(err)
	}
	vpaClient := vpa_clientset.NewForConfigOrDie(config)
	return vpa_api_util.NewAllVpasLister(vpaClient, stopChannel)
}

func main() {
	kube_flag.InitFlags()
	glog.V(1).Infof("Vertical Pod Autoscaler %s Admission Controller", common.VerticalPodAutoscalerVersion)

	healthCheck := metrics.NewHealthCheck(time.Minute, false)
	metrics.Initialize(*address, healthCheck)
	metrics_admission.Register()

	certs := initCerts(*certsConfiguration)
	stopChannel := make(chan struct{})
	vpaLister := newReadyVPALister(stopChannel)
	as := logic.NewAdmissionServer(logic.NewRecommendationProvider(vpaLister, vpa_api_util.NewCappingRecommendationProcessor()), logic.NewDefaultPodPreProcessor())
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		as.Serve(w, r)
		healthCheck.UpdateLastActivity()
	})
	clientset := getClient()
	server := &http.Server{
		Addr:      fmt.Sprintf(":%d", *port),
		TLSConfig: configTLS(clientset, certs.serverCert, certs.serverKey),
	}
	go selfRegistration(clientset, certs.caCert, &namespace)
	server.ListenAndServeTLS("", "")
}
<|endoftext|>


<commit_before>package etcd

import (
	"strings"
	"time"

	"golang.org/x/net/context"

	log "github.com/Sirupsen/logrus"
	"github.com/coreos/etcd/client"
)

// A Store implements a consistent distributed key value store similar to Etcd.
type Store interface {
	Watch(path string, rateLimit time.Duration) chan struct{}
	Mkdir(dir string) error
	GetTree(dir string) (Tree, error)
	Get(path string) (string, error)
	Delete(path string) error
	Create(path, value string, ttl time.Duration) error
	Update(path, value string, ttl time.Duration) error
	Set(path, value string, ttl time.Duration) error
}

type store struct {
	kapi client.KeysAPI
}

// NewStore creates a new consensus store and returns it.
func NewStore() Store {
	var etcd client.Client
	for {
		var err error
		etcd, err = client.New(client.Config{
			Endpoints: []string{"http://127.0.0.1:2379"},
			Transport: client.DefaultTransport,
		})
		if err != nil {
			log.WithError(err).Warning("Failed to connect to ETCD.")
			time.Sleep(30 * time.Second)
			continue
		}

		break
	}

	return store{client.NewKeysAPI(etcd)}
}

func (s store) Watch(path string, rateLimit time.Duration) chan struct{} {
	c := make(chan struct{})
	go func() {
		watcher := s.kapi.Watcher(path, &client.WatcherOptions{Recursive: true})
		for {
			c <- struct{}{}
			time.Sleep(rateLimit)
			watcher.Next(context.Background())
		}
	}()

	return c
}

func (s store) Mkdir(dir string) error {
	_, err := s.kapi.Set(ctx(), dir, "", &client.SetOptions{
		Dir:       true,
		PrevExist: client.PrevNoExist,
	})
	return err
}

// A Tree is a parsed subtree of the consensus store including each node's key, value
// and all of it's children recursively.
type Tree struct {
	Key      string
	Value    string
	Children map[string]Tree
}

func (s store) GetTree(dir string) (Tree, error) {
	resp, err := s.kapi.Get(ctx(), dir, &client.GetOptions{
		Recursive: true,
		Sort:      false,
		Quorum:    true,
	})
	if err != nil {
		return Tree{}, err
	}

	var rec func(*client.Node) Tree
	rec = func(node *client.Node) Tree {
		keySlice := strings.Split(node.Key, "/")
		tree := Tree{
			Key:      keySlice[len(keySlice)-1],
			Value:    node.Value,
			Children: map[string]Tree{},
		}

		for _, child := range node.Nodes {
			ct := rec(child)
			tree.Children[ct.Key] = ct
		}

		return tree
	}

	return rec(resp.Node), nil
}

func (s store) Get(path string) (string, error) {
	resp, err := s.kapi.Get(ctx(), path, &client.GetOptions{
		Quorum: true,
	})
	if err != nil {
		return "", err
	}

	return resp.Node.Value, nil
}

func (s store) Delete(path string) error {
	_, err := s.kapi.Delete(ctx(), path, &client.DeleteOptions{Recursive: true})
	return err
}

func (s store) Create(path, value string, ttl time.Duration) error {
	_, err := s.kapi.Set(ctx(), path, value,
		&client.SetOptions{PrevExist: client.PrevNoExist, TTL: ttl})
	return err
}

func (s store) Update(path, value string, ttl time.Duration) error {
	_, err := s.kapi.Set(ctx(), path, value, &client.SetOptions{TTL: ttl})
	return err
}

func (s store) Set(path, value string, ttl time.Duration) error {
	_, err := s.kapi.Set(ctx(), path, value, nil)
	return err
}

func ctx() context.Context {
	ctx, _ := context.WithTimeout(context.Background(), 5*time.Second)
	return ctx
}
<commit_msg>minion: Correct Store.Set to respect TTLs<commit_after>package etcd

import (
	"strings"
	"time"

	"golang.org/x/net/context"

	log "github.com/Sirupsen/logrus"
	"github.com/coreos/etcd/client"
)

// A Store implements a consistent distributed key value store similar to Etcd.
type Store interface {
	Watch(path string, rateLimit time.Duration) chan struct{}
	Mkdir(dir string) error
	GetTree(dir string) (Tree, error)
	Get(path string) (string, error)
	Delete(path string) error
	Create(path, value string, ttl time.Duration) error
	Update(path, value string, ttl time.Duration) error
	Set(path, value string, ttl time.Duration) error
}

type store struct {
	kapi client.KeysAPI
}

// NewStore creates a new consensus store and returns it.
func NewStore() Store {
	var etcd client.Client
	for {
		var err error
		etcd, err = client.New(client.Config{
			Endpoints: []string{"http://127.0.0.1:2379"},
			Transport: client.DefaultTransport,
		})
		if err != nil {
			log.WithError(err).Warning("Failed to connect to ETCD.")
			time.Sleep(30 * time.Second)
			continue
		}

		break
	}

	return store{client.NewKeysAPI(etcd)}
}

func (s store) Watch(path string, rateLimit time.Duration) chan struct{} {
	c := make(chan struct{})
	go func() {
		watcher := s.kapi.Watcher(path, &client.WatcherOptions{Recursive: true})
		for {
			c <- struct{}{}
			time.Sleep(rateLimit)
			watcher.Next(context.Background())
		}
	}()

	return c
}

func (s store) Mkdir(dir string) error {
	_, err := s.kapi.Set(ctx(), dir, "", &client.SetOptions{
		Dir:       true,
		PrevExist: client.PrevNoExist,
	})
	return err
}

// A Tree is a parsed subtree of the consensus store including each node's key, value
// and all of it's children recursively.
type Tree struct {
	Key      string
	Value    string
	Children map[string]Tree
}

func (s store) GetTree(dir string) (Tree, error) {
	resp, err := s.kapi.Get(ctx(), dir, &client.GetOptions{
		Recursive: true,
		Sort:      false,
		Quorum:    true,
	})
	if err != nil {
		return Tree{}, err
	}

	var rec func(*client.Node) Tree
	rec = func(node *client.Node) Tree {
		keySlice := strings.Split(node.Key, "/")
		tree := Tree{
			Key:      keySlice[len(keySlice)-1],
			Value:    node.Value,
			Children: map[string]Tree{},
		}

		for _, child := range node.Nodes {
			ct := rec(child)
			tree.Children[ct.Key] = ct
		}

		return tree
	}

	return rec(resp.Node), nil
}

func (s store) Get(path string) (string, error) {
	resp, err := s.kapi.Get(ctx(), path, &client.GetOptions{
		Quorum: true,
	})
	if err != nil {
		return "", err
	}

	return resp.Node.Value, nil
}

func (s store) Delete(path string) error {
	_, err := s.kapi.Delete(ctx(), path, &client.DeleteOptions{Recursive: true})
	return err
}

func (s store) Create(path, value string, ttl time.Duration) error {
	_, err := s.kapi.Set(ctx(), path, value,
		&client.SetOptions{PrevExist: client.PrevNoExist, TTL: ttl})
	return err
}

func (s store) Update(path, value string, ttl time.Duration) error {
	_, err := s.kapi.Set(ctx(), path, value, &client.SetOptions{TTL: ttl})
	return err
}

func (s store) Set(path, value string, ttl time.Duration) error {
	_, err := s.kapi.Set(ctx(), path, value, &client.SetOptions{TTL: ttl})
	return err
}

func ctx() context.Context {
	ctx, _ := context.WithTimeout(context.Background(), 5*time.Second)
	return ctx
}
<|endoftext|>


<commit_before>// Copyright (c) 2015, Peter Mrekaj. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE.txt file.

package strings

// IndexNaive returns an start index of pattern p in the string s.
// It uses sequential search method for matching a pattern p in the string s.
// Let n be len(s) and m be len(p), then the matching time is O((n−m+1)*m)
// without any pre-processing time.
func IndexNaive(s, p string) int {
	m := len(p)
	if m == 0 {
		return 0
	}
	for i := m; i <= len(s); i++ {
		if s[i-m:i] == p {
			return i - m
		}
	}
	return -1
}

// IndexRK returns an start index of pattern p in the string s.
// It uses Rabin-Karp method for matching a pattern p in the string s.
// Let n be len(s) and m be len(p), then the time for pre-processing is Θ(m).
// And the time for matching:
// 	- average: Θ(n+m+1)
// 	- worst: Θ((n−m+1)*m)
//
func IndexRK(s, p string) int {
	const b = 977 // Base (a prime).

	n := len(s)
	m := len(p)

	switch {
	case m == 0:
		return 0
	case m == n:
		if p == s {
			return 0
		}
		return -1
	case m > n:
		return -1
	}

	// We don't manually reduce the computed hash values (and base power) by modulus.
	// Instead we use the fact that overflow of integer multiplication and addition acts as a modulus.
	// For example, overflow of the two unit32 values: a*b == (a*b)%(2**32).
	// The increased number of potential collisions, when modulus isn't a large
	// prime, is outweighed by the fact that we wouldn't need to explicitly use
	// modular reduction for every addition and multiplication. This results in
	// a better performance characteristics.

	// Pre-processing.
	var bp, ph, sh uint32 = 1, 0, 0
	for i := 0; i < m; i++ {
		if i > 0 { // Base power: bp = b**(m-1)%(2**32).
			bp *= b // Implicit modulus 2**32.
		}
		ph = b*ph + uint32(p[i]) // Implicit modulus 2**32.
		sh = b*sh + uint32(s[i]) // Implicit modulus 2**32.
	}

	// Matching.
	for i := m; i <= n; i++ {
		if ph == sh {
			if s[i-m:i] == p {
				return i - m
			}
		}
		if i < n {
			// Slide right the rolling hash window (include implicit modulus 2**32).
			sh -= bp * uint32(s[i-m]) // Remove previous value.
			sh = b*sh + uint32(s[i])  // Add next value.
		}
	}

	return -1
}
<commit_msg>Correct the modulus constant in comments<commit_after>// Copyright (c) 2015, Peter Mrekaj. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE.txt file.

package strings

// IndexNaive returns an start index of pattern p in the string s.
// It uses sequential search method for matching a pattern p in the string s.
// Let n be len(s) and m be len(p), then the matching time is O((n−m+1)*m)
// without any pre-processing time.
func IndexNaive(s, p string) int {
	m := len(p)
	if m == 0 {
		return 0
	}
	for i := m; i <= len(s); i++ {
		if s[i-m:i] == p {
			return i - m
		}
	}
	return -1
}

// IndexRK returns an start index of pattern p in the string s.
// It uses Rabin-Karp method for matching a pattern p in the string s.
// Let n be len(s) and m be len(p), then the time for pre-processing is Θ(m).
// And the time for matching:
// 	- average: Θ(n+m+1)
// 	- worst: Θ((n−m+1)*m)
//
func IndexRK(s, p string) int {
	const b = 977 // We use prime number as a base to reduce number of collisions in hash.

	n := len(s)
	m := len(p)

	switch {
	case m == 0:
		return 0
	case m == n:
		if p == s {
			return 0
		}
		return -1
	case m > n:
		return -1
	}

	// We don't manually reduce the computed hash values (and base power) by modulus.
	// Instead we use the fact that overflow of integer multiplication and addition acts as a modulus.
	// For example, overflow of the two unit32 values: a*b == (a*b)%(2**32-1).
	// The increased number of potential collisions, when modulus isn't a large
	// prime, is outweighed by the fact that we wouldn't need to explicitly use
	// modular reduction for every addition and multiplication. This results in
	// a better performance characteristics.

	// Pre-processing.
	var bp, ph, sh uint32 = 1, 0, 0
	for i := 0; i < m; i++ {
		if i > 0 { // Base power: bp = b**(m-1)%(2**32-1).
			bp *= b // Implicit modulus 2**32-1.
		}
		ph = b*ph + uint32(p[i]) // Implicit modulus 2**32-1.
		sh = b*sh + uint32(s[i]) // Implicit modulus 2**32-1.
	}

	// Matching.
	for i := m; i <= n; i++ {
		if ph == sh {
			if s[i-m:i] == p {
				return i - m
			}
		}
		if i < n {
			// Slide right the rolling hash window (include implicit modulus 2**32-1).
			sh -= bp * uint32(s[i-m]) // Remove previous value.
			sh = b*sh + uint32(s[i])  // Add next value.
		}
	}

	return -1
}
<|endoftext|>