<commit_before>package api

import (
	"errors"

	"github.com/DataDog/datadog-go/statsd"
	"github.com/MEDIGO/go-healthz"
	"github.com/MEDIGO/laika/notifier"
	"github.com/MEDIGO/laika/store"
	"github.com/labstack/echo"
	"github.com/labstack/echo/middleware"
)

// ServerConfig is used to parametrize a Server.
type ServerConfig struct {
	RootUsername string
	RootPassword string
	Store        store.Store
	Stats        *statsd.Client
	Notifier     notifier.Notifier
}

// NewServer creates a new server.
func NewServer(conf ServerConfig) (*echo.Echo, error) {
	if conf.RootPassword == "" {
		return nil, errors.New("missing root username")
	}

	if conf.RootPassword == "" {
		return nil, errors.New("missing root password")
	}

	if conf.Store == nil {
		return nil, errors.New("missing store")
	}

	if conf.Notifier == nil {
		conf.Notifier = notifier.NewNOOPNotifier()
	}

	e := echo.New()

	basicAuthMiddleware := AuthMiddleware(conf.RootUsername, conf.RootPassword, conf.Store)

	e.Use(TraceMiddleware())
	e.Use(LogMiddleware())
	e.Use(InstrumentMiddleware(conf.Stats))
	e.Use(middleware.Recover())

	events := NewEventResource(conf.Store, conf.Stats, conf.Notifier)

	e.GET("/api/health", echo.WrapHandler(healthz.Handler()))

	e.Use(StateMiddleware(conf.Store))

	publicApi := e.Group("")
	privateApi := e.Group("/api", basicAuthMiddleware)

	// Public routes go here
	publicApi.GET("/api/features/:name/status/:env", GetFeatureStatus)

	// Private(behind auth) routes go here
	privateApi.POST("/events/:type", events.Create)
	privateApi.GET("/features/:name", GetFeature)
	privateApi.GET("/features", ListFeatures)
	privateApi.GET("/environments", ListEnvironments)
	privateApi.GET("/*", func(c echo.Context) error { return NotFound(c) })

	e.Static("/assets", "dashboard/public/assets")
	e.File("/*", "dashboard/public/index.html")

	return e, nil
}
<commit_msg>*tp5712 CORS enabled on server for public api<commit_after>package api

import (
	"errors"

	"github.com/DataDog/datadog-go/statsd"
	"github.com/MEDIGO/go-healthz"
	"github.com/MEDIGO/laika/notifier"
	"github.com/MEDIGO/laika/store"
	"github.com/labstack/echo"
	"github.com/labstack/echo/middleware"
)

// ServerConfig is used to parametrize a Server.
type ServerConfig struct {
	RootUsername string
	RootPassword string
	Store        store.Store
	Stats        *statsd.Client
	Notifier     notifier.Notifier
}

// NewServer creates a new server.
func NewServer(conf ServerConfig) (*echo.Echo, error) {
	if conf.RootPassword == "" {
		return nil, errors.New("missing root username")
	}

	if conf.RootPassword == "" {
		return nil, errors.New("missing root password")
	}

	if conf.Store == nil {
		return nil, errors.New("missing store")
	}

	if conf.Notifier == nil {
		conf.Notifier = notifier.NewNOOPNotifier()
	}

	e := echo.New()

	basicAuthMiddleware := AuthMiddleware(conf.RootUsername, conf.RootPassword, conf.Store)

	e.Use(TraceMiddleware())
	e.Use(LogMiddleware())
	e.Use(InstrumentMiddleware(conf.Stats))
	e.Use(middleware.Recover())

	events := NewEventResource(conf.Store, conf.Stats, conf.Notifier)

	e.GET("/api/health", echo.WrapHandler(healthz.Handler()))

	e.Use(StateMiddleware(conf.Store))

	publicApi := e.Group("")
	publicApi.Use(CORSWithConfig(CORSConfig{
		AllowMethods: []string{http.MethodGet},
	}))

	privateApi := e.Group("/api", basicAuthMiddleware)

	// Public routes go here
	publicApi.GET("/api/features/:name/status/:env", GetFeatureStatus)

	// Private(behind auth) routes go here
	privateApi.POST("/events/:type", events.Create)
	privateApi.GET("/features/:name", GetFeature)
	privateApi.GET("/features", ListFeatures)
	privateApi.GET("/environments", ListEnvironments)
	privateApi.GET("/*", func(c echo.Context) error { return NotFound(c) })

	e.Static("/assets", "dashboard/public/assets")
	e.File("/*", "dashboard/public/index.html")

	return e, nil
}
<|endoftext|>


<commit_before>package nl

const (
	DEFAULT_CHANGE = 0xFFFFFFFF
)

const (
	IFLA_INFO_UNSPEC = iota
	IFLA_INFO_KIND   = iota
	IFLA_INFO_DATA   = iota
	IFLA_INFO_XSTATS = iota
	IFLA_INFO_MAX    = IFLA_INFO_XSTATS
)

const (
	IFLA_VLAN_UNSPEC      = iota
	IFLA_VLAN_ID          = iota
	IFLA_VLAN_FLAGS       = iota
	IFLA_VLAN_EGRESS_QOS  = iota
	IFLA_VLAN_INGRESS_QOS = iota
	IFLA_VLAN_PROTOCOL    = iota
	IFLA_VLAN_MAX         = IFLA_VLAN_PROTOCOL
)

const (
	VETH_INFO_UNSPEC = iota
	VETH_INFO_PEER   = iota
	VETH_INFO_MAX    = VETH_INFO_PEER
)

const (
	IFLA_VXLAN_UNSPEC     = iota
	IFLA_VXLAN_ID         = iota
	IFLA_VXLAN_GROUP      = iota
	IFLA_VXLAN_LINK       = iota
	IFLA_VXLAN_LOCAL      = iota
	IFLA_VXLAN_TTL        = iota
	IFLA_VXLAN_TOS        = iota
	IFLA_VXLAN_LEARNING   = iota
	IFLA_VXLAN_AGEING     = iota
	IFLA_VXLAN_LIMIT      = iota
	IFLA_VXLAN_PORT_RANGE = iota
	IFLA_VXLAN_PROXY      = iota
	IFLA_VXLAN_RSC        = iota
	IFLA_VXLAN_L2MISS     = iota
	IFLA_VXLAN_L3MISS     = iota
	IFLA_VXLAN_PORT       = iota
	IFLA_VXLAN_GROUP6     = iota
	IFLA_VXLAN_LOCAL6     = iota
	IFLA_VXLAN_MAX        = IFLA_VXLAN_LOCAL6
)

const (
	// not defined in syscall
	IFLA_NET_NS_FD = 28
)
<commit_msg>Add constansts for bridge configuration<commit_after>package nl

const (
	DEFAULT_CHANGE = 0xFFFFFFFF
)

const (
	IFLA_INFO_UNSPEC = iota
	IFLA_INFO_KIND   = iota
	IFLA_INFO_DATA   = iota
	IFLA_INFO_XSTATS = iota
	IFLA_INFO_MAX    = IFLA_INFO_XSTATS
)

const (
	IFLA_VLAN_UNSPEC      = iota
	IFLA_VLAN_ID          = iota
	IFLA_VLAN_FLAGS       = iota
	IFLA_VLAN_EGRESS_QOS  = iota
	IFLA_VLAN_INGRESS_QOS = iota
	IFLA_VLAN_PROTOCOL    = iota
	IFLA_VLAN_MAX         = IFLA_VLAN_PROTOCOL
)

const (
	VETH_INFO_UNSPEC = iota
	VETH_INFO_PEER   = iota
	VETH_INFO_MAX    = VETH_INFO_PEER
)

const (
	IFLA_VXLAN_UNSPEC     = iota
	IFLA_VXLAN_ID         = iota
	IFLA_VXLAN_GROUP      = iota
	IFLA_VXLAN_LINK       = iota
	IFLA_VXLAN_LOCAL      = iota
	IFLA_VXLAN_TTL        = iota
	IFLA_VXLAN_TOS        = iota
	IFLA_VXLAN_LEARNING   = iota
	IFLA_VXLAN_AGEING     = iota
	IFLA_VXLAN_LIMIT      = iota
	IFLA_VXLAN_PORT_RANGE = iota
	IFLA_VXLAN_PROXY      = iota
	IFLA_VXLAN_RSC        = iota
	IFLA_VXLAN_L2MISS     = iota
	IFLA_VXLAN_L3MISS     = iota
	IFLA_VXLAN_PORT       = iota
	IFLA_VXLAN_GROUP6     = iota
	IFLA_VXLAN_LOCAL6     = iota
	IFLA_VXLAN_MAX        = IFLA_VXLAN_LOCAL6
)

const (
	BRIDGE_MODE_UNSPEC  = iota
	BRIDGE_MODE_HAIRPIN = iota
)

const (
	IFLA_BRPORT_UNSPEC        = iota
	IFLA_BRPORT_STATE         = iota
	IFLA_BRPORT_PRIORITY      = iota
	IFLA_BRPORT_COST          = iota
	IFLA_BRPORT_MODE          = iota
	IFLA_BRPORT_GUARD         = iota
	IFLA_BRPORT_PROTECT       = iota
	IFLA_BRPORT_FAST_LEAVE    = iota
	IFLA_BRPORT_LEARNING      = iota
	IFLA_BRPORT_UNICAST_FLOOD = iota
	IFLA_BRPORT_MAX           = IFLA_BRPORT_UNICAST_FLOOD
)

const (
	// not defined in syscall
	IFLA_NET_NS_FD = 28
)
<|endoftext|>


<commit_before>package api

import (
	"context"
	"errors"
	"net"
	"net/http"
	"os"
	"os/signal"
	"time"

	emiddleware "github.com/labstack/echo/middleware"

	"github.com/STNS/STNS/middleware"
	"github.com/STNS/STNS/model"
	"github.com/STNS/STNS/stns"
	"github.com/facebookgo/pidfile"
	"github.com/labstack/echo"

	"github.com/sirupsen/logrus"
	"github.com/urfave/cli"

	// PostgreSQL driver
	_ "github.com/jinzhu/gorm/dialects/postgres"
	"github.com/lestrrat/go-server-starter/listener"
)

type server struct {
	config *stns.Config
}

func newServer(confPath string) (*server, error) {
	logrus.Warn(confPath)
	conf, err := stns.NewConfig(confPath)
	if err != nil {
		return nil, err
	}

	s := &server{config: &conf}
	return s, nil
}
func status(c echo.Context) error {
	return c.String(http.StatusOK, "OK")
}

// Run サーバの起動
func (s *server) Run() error {
	e := echo.New()
	e.GET("/status", status)

	if err := pidfile.Write(); err != nil {
		return err
	}
	defer removePidFile()

	b := model.NewBackendTomlFile(s.config.Users, s.config.Groups)
	e.Use(middleware.Backend(b))
	e.Use(middleware.AddHeader(b))
	e.Use(emiddleware.Recover())

	if s.config.UseServerStarter {
		listeners, err := listener.ListenAll()
		if listeners == nil || err != nil {
			return err
		}
		e.Listener = listeners[0]
	} else {
		l, err := net.Listen("tcp", ":8050")
		if err != nil {
			return err
		}
		e.Listener = l
	}
	go func() {
		customServer := &http.Server{
			WriteTimeout: 1 * time.Minute,
		}
		if err := e.StartServer(customServer); err != nil {
			logrus.Info("shutting down the server")
		}
	}()

	v1 := e.Group("/v1")
	UserEndpoints(v1)
	GroupEndpoints(v1)

	e.GET("/", func(c echo.Context) error {
		return c.String(http.StatusOK, "Hello! STNS!!1")
	})

	quit := make(chan os.Signal)
	signal.Notify(quit, os.Interrupt)
	<-quit
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	if err := e.Shutdown(ctx); err != nil {
		return err
	}
	return nil
}

func removePidFile() {
	if err := os.Remove(pidfile.GetPidfilePath()); err != nil {
		logrus.Fatalf("Error removing %s: %s", pidfile.GetPidfilePath(), err)
	}
}

func LaunchServer(c *cli.Context) error {
	logrus.SetLevel(logrus.WarnLevel)
	if os.Getenv("STNS_LOG") != "" {
		f, err := os.OpenFile(os.Getenv("STNS_LOG"), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
		if err != nil {
			return errors.New("error opening file :" + err.Error())
		}
		logrus.SetOutput(f)
	}

	pidfile.SetPidfilePath(os.Getenv("STNS_PID"))
	serv, err := newServer(os.Getenv("STNS_CONFIG"))
	if err != nil {
		return errors.New("server init:" + err.Error())
	}
	return serv.Run()
}
<commit_msg>add logger<commit_after>package api

import (
	"context"
	"errors"
	"net"
	"net/http"
	"os"
	"os/signal"
	"time"

	emiddleware "github.com/labstack/echo/middleware"

	"github.com/STNS/STNS/middleware"
	"github.com/STNS/STNS/model"
	"github.com/STNS/STNS/stns"
	"github.com/facebookgo/pidfile"
	"github.com/labstack/echo"

	"github.com/sirupsen/logrus"
	"github.com/urfave/cli"

	// PostgreSQL driver
	_ "github.com/jinzhu/gorm/dialects/postgres"
	"github.com/lestrrat/go-server-starter/listener"
)

type server struct {
	config *stns.Config
}

func newServer(confPath string) (*server, error) {
	logrus.Warn(confPath)
	conf, err := stns.NewConfig(confPath)
	if err != nil {
		return nil, err
	}

	s := &server{config: &conf}
	return s, nil
}
func status(c echo.Context) error {
	return c.String(http.StatusOK, "OK")
}

// Run サーバの起動
func (s *server) Run() error {
	e := echo.New()
	e.GET("/status", status)

	if err := pidfile.Write(); err != nil {
		return err
	}
	defer removePidFile()

	b := model.NewBackendTomlFile(s.config.Users, s.config.Groups)
	e.Use(middleware.Backend(b))
	e.Use(middleware.AddHeader(b))
	e.Use(emiddleware.Recover())
	e.Use(emiddleware.LoggerWithConfig(emiddleware.LoggerConfig{
		Format: `{"time":"${time_rfc3339_nano}","remote_ip":"${remote_ip}","host":"${host}",` +
			`"method":"${method}","uri":"${uri}","status":${status}` + "\n",
	}))

	if s.config.UseServerStarter {
		listeners, err := listener.ListenAll()
		if listeners == nil || err != nil {
			return err
		}
		e.Listener = listeners[0]
	} else {
		l, err := net.Listen("tcp", ":8050")
		if err != nil {
			return err
		}
		e.Listener = l
	}
	go func() {
		customServer := &http.Server{
			WriteTimeout: 1 * time.Minute,
		}
		if err := e.StartServer(customServer); err != nil {
			logrus.Info("shutting down the server")
		}
	}()

	v1 := e.Group("/v1")
	UserEndpoints(v1)
	GroupEndpoints(v1)

	e.GET("/", func(c echo.Context) error {
		return c.String(http.StatusOK, "Hello! STNS!!1")
	})

	quit := make(chan os.Signal)
	signal.Notify(quit, os.Interrupt)
	<-quit
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	if err := e.Shutdown(ctx); err != nil {
		return err
	}
	return nil
}

func removePidFile() {
	if err := os.Remove(pidfile.GetPidfilePath()); err != nil {
		logrus.Fatalf("Error removing %s: %s", pidfile.GetPidfilePath(), err)
	}
}

func LaunchServer(c *cli.Context) error {
	logrus.SetLevel(logrus.WarnLevel)
	if os.Getenv("STNS_LOG") != "" {
		f, err := os.OpenFile(os.Getenv("STNS_LOG"), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
		if err != nil {
			return errors.New("error opening file :" + err.Error())
		}
		logrus.SetOutput(f)
	}

	pidfile.SetPidfilePath(os.Getenv("STNS_PID"))
	serv, err := newServer(os.Getenv("STNS_CONFIG"))
	if err != nil {
		return errors.New("server init:" + err.Error())
	}
	return serv.Run()
}
<|endoftext|>


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

package api

import (
	"fmt"
	"github.com/bmizerany/pat"
	"github.com/globocom/config"
	"github.com/globocom/tsuru/app"
	"github.com/globocom/tsuru/log"
	"github.com/globocom/tsuru/provision"
	"net"
	"net/http"
)

func fatal(err error) {
	log.Fatal(err)
}

// RunServer starts Tsuru API server. The dry parameter indicates whether the
// server should run in dry mode, not starting the HTTP listener (for testing
// purposes).
func RunServer(dry bool) {
	log.Init()
	connString, err := config.GetString("database:url")
	if err != nil {
		fatal(err)
	}
	dbName, err := config.GetString("database:name")
	if err != nil {
		fatal(err)
	}
	fmt.Printf("Using the database %q from the server %q.\n\n", dbName, connString)

	m := pat.New()

	m.Get("/schema/app", authorizationRequiredHandler(appSchema))
	m.Get("/schema/service", authorizationRequiredHandler(serviceSchema))
	m.Get("/schema/services", authorizationRequiredHandler(servicesSchema))

	m.Get("/quota/:owner", authorizationRequiredHandler(quotaByOwner))

	m.Get("/services/instances", authorizationRequiredHandler(serviceInstances))
	m.Get("/services/instances/:name", authorizationRequiredHandler(serviceInstance))
	m.Del("/services/instances/:name", authorizationRequiredHandler(removeServiceInstance))
	m.Post("/services/instances", authorizationRequiredHandler(createServiceInstance))
	m.Put("/services/instances/:instance/:app", authorizationRequiredHandler(bindServiceInstance))
	m.Del("/services/instances/:instance/:app", authorizationRequiredHandler(unbindServiceInstance))
	m.Get("/services/instances/:instance/status", authorizationRequiredHandler(serviceInstanceStatus))

	m.Get("/services", authorizationRequiredHandler(serviceList))
	m.Post("/services", authorizationRequiredHandler(serviceCreate))
	m.Put("/services", authorizationRequiredHandler(serviceUpdate))
	m.Del("/services/:name", authorizationRequiredHandler(serviceDelete))
	m.Get("/services/:name", authorizationRequiredHandler(serviceInfo))
	m.Get("/services/:name/doc", authorizationRequiredHandler(serviceDoc))
	m.Put("/services/:name/doc", authorizationRequiredHandler(serviceAddDoc))
	m.Put("/services/:service/:team", authorizationRequiredHandler(grantServiceAccess))
	m.Del("/services/:service/:team", authorizationRequiredHandler(revokeServiceAccess))

	m.Del("/apps/:app", authorizationRequiredHandler(appDelete))
	m.Get("/apps/:app", authorizationRequiredHandler(appInfo))
	m.Post("/apps/:app/cname", authorizationRequiredHandler(setCName))
	m.Del("/apps/:app/cname", authorizationRequiredHandler(unsetCName))
	m.Post("/apps/:app/run", authorizationRequiredHandler(runCommand))
	m.Get("/apps/:app/restart", authorizationRequiredHandler(restart))
	m.Get("/apps/:app/env", authorizationRequiredHandler(getEnv))
	m.Post("/apps/:app/env", authorizationRequiredHandler(setEnv))
	m.Del("/apps/:app/env", authorizationRequiredHandler(unsetEnv))
	m.Get("/apps", authorizationRequiredHandler(appList))
	m.Post("/apps", authorizationRequiredHandler(createApp))
	m.Put("/apps/:app/units", authorizationRequiredHandler(addUnits))
	m.Del("/apps/:app/units", authorizationRequiredHandler(removeUnits))
	m.Put("/apps/:app/:team", authorizationRequiredHandler(grantAppAccess))
	m.Del("/apps/:app/:team", authorizationRequiredHandler(revokeAppAccess))
	m.Get("/apps/:app/log", authorizationRequiredHandler(appLog))
	m.Post("/apps/:app/log", authorizationRequiredHandler(addLog))

	m.Get("/platforms", authorizationRequiredHandler(platformList))

	// These handlers don't use :app on purpose. Using :app means that only
	// the token generate for the given app is valid, but these handlers
	// use a token generated for Gandalf.
	m.Get("/apps/:appname/available", authorizationRequiredHandler(appIsAvailable))
	m.Post("/apps/:appname/repository/clone", authorizationRequiredHandler(cloneRepository))

	if registrationEnabled, _ := config.GetBool("auth:user-registration"); registrationEnabled {
		m.Post("/users", handler(createUser))
	}

	m.Post("/users/:email/password", handler(resetPassword))
	m.Post("/users/:email/tokens", handler(login))
	m.Del("/users/tokens", authorizationRequiredHandler(logout))
	m.Put("/users/password", authorizationRequiredHandler(changePassword))
	m.Del("/users", authorizationRequiredHandler(removeUser))
	m.Get("/users/:email/keys", authorizationRequiredHandler(listKeys))
	m.Post("/users/keys", authorizationRequiredHandler(addKeyToUser))
	m.Del("/users/keys", authorizationRequiredHandler(removeKeyFromUser))

	m.Post("/tokens", adminRequiredHandler(generateAppToken))

	m.Del("/logs", adminRequiredHandler(logRemove))

	m.Get("/teams", authorizationRequiredHandler(teamList))
	m.Post("/teams", authorizationRequiredHandler(createTeam))
	m.Get("/teams/:name", authorizationRequiredHandler(getTeam))
	m.Del("/teams/:name", authorizationRequiredHandler(removeTeam))
	m.Put("/teams/:team/:user", authorizationRequiredHandler(addUserToTeam))
	m.Del("/teams/:team/:user", authorizationRequiredHandler(removeUserFromTeam))

	m.Get("/healers", authorizationRequiredHandler(healers))
	m.Get("/healers/:healer", authorizationRequiredHandler(healer))

	m.Put("/swap", authorizationRequiredHandler(swap))

	if !dry {
		provisioner, err := getProvisioner()
		if err != nil {
			fmt.Printf("Warning: configuration didn't declare a provisioner, using default provisioner.\n")
		}
		app.Provisioner, err = provision.Get(provisioner)
		if err != nil {
			fatal(err)
		}
		fmt.Printf("Using %q provisioner.\n\n", provisioner)

		listen, err := config.GetString("listen")
		if err != nil {
			fatal(err)
		}
		tls, _ := config.GetBool("use-tls")
		if tls {
			certFile, err := config.GetString("tls:cert-file")
			if err != nil {
				fatal(err)
			}
			keyFile, err := config.GetString("tls:key-file")
			if err != nil {
				fatal(err)
			}
			fmt.Printf("tsuru HTTP/TLS server listening at %s...\n", listen)
			fatal(http.ListenAndServeTLS(listen, certFile, keyFile, m))
		} else {
			listener, err := net.Listen("tcp", listen)
			if err != nil {
				fatal(err)
			}
			fmt.Printf("tsuru HTTP server listening at %s...\n", listen)
			http.Handle("/", m)
			fatal(http.Serve(listener, nil))
		}
	}
}
<commit_msg>api: added route for healthcheck.<commit_after>// Copyright 2013 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package api

import (
	"fmt"
	"github.com/bmizerany/pat"
	"github.com/globocom/config"
	"github.com/globocom/tsuru/app"
	"github.com/globocom/tsuru/log"
	"github.com/globocom/tsuru/provision"
	"net"
	"net/http"
)

func fatal(err error) {
	log.Fatal(err)
}

// RunServer starts Tsuru API server. The dry parameter indicates whether the
// server should run in dry mode, not starting the HTTP listener (for testing
// purposes).
func RunServer(dry bool) {
	log.Init()
	connString, err := config.GetString("database:url")
	if err != nil {
		fatal(err)
	}
	dbName, err := config.GetString("database:name")
	if err != nil {
		fatal(err)
	}
	fmt.Printf("Using the database %q from the server %q.\n\n", dbName, connString)

	m := pat.New()

	m.Get("/schema/app", authorizationRequiredHandler(appSchema))
	m.Get("/schema/service", authorizationRequiredHandler(serviceSchema))
	m.Get("/schema/services", authorizationRequiredHandler(servicesSchema))

	m.Get("/quota/:owner", authorizationRequiredHandler(quotaByOwner))

	m.Get("/services/instances", authorizationRequiredHandler(serviceInstances))
	m.Get("/services/instances/:name", authorizationRequiredHandler(serviceInstance))
	m.Del("/services/instances/:name", authorizationRequiredHandler(removeServiceInstance))
	m.Post("/services/instances", authorizationRequiredHandler(createServiceInstance))
	m.Put("/services/instances/:instance/:app", authorizationRequiredHandler(bindServiceInstance))
	m.Del("/services/instances/:instance/:app", authorizationRequiredHandler(unbindServiceInstance))
	m.Get("/services/instances/:instance/status", authorizationRequiredHandler(serviceInstanceStatus))

	m.Get("/services", authorizationRequiredHandler(serviceList))
	m.Post("/services", authorizationRequiredHandler(serviceCreate))
	m.Put("/services", authorizationRequiredHandler(serviceUpdate))
	m.Del("/services/:name", authorizationRequiredHandler(serviceDelete))
	m.Get("/services/:name", authorizationRequiredHandler(serviceInfo))
	m.Get("/services/:name/doc", authorizationRequiredHandler(serviceDoc))
	m.Put("/services/:name/doc", authorizationRequiredHandler(serviceAddDoc))
	m.Put("/services/:service/:team", authorizationRequiredHandler(grantServiceAccess))
	m.Del("/services/:service/:team", authorizationRequiredHandler(revokeServiceAccess))

	m.Del("/apps/:app", authorizationRequiredHandler(appDelete))
	m.Get("/apps/:app", authorizationRequiredHandler(appInfo))
	m.Post("/apps/:app/cname", authorizationRequiredHandler(setCName))
	m.Del("/apps/:app/cname", authorizationRequiredHandler(unsetCName))
	m.Post("/apps/:app/run", authorizationRequiredHandler(runCommand))
	m.Get("/apps/:app/restart", authorizationRequiredHandler(restart))
	m.Get("/apps/:app/env", authorizationRequiredHandler(getEnv))
	m.Post("/apps/:app/env", authorizationRequiredHandler(setEnv))
	m.Del("/apps/:app/env", authorizationRequiredHandler(unsetEnv))
	m.Get("/apps", authorizationRequiredHandler(appList))
	m.Post("/apps", authorizationRequiredHandler(createApp))
	m.Put("/apps/:app/units", authorizationRequiredHandler(addUnits))
	m.Del("/apps/:app/units", authorizationRequiredHandler(removeUnits))
	m.Put("/apps/:app/:team", authorizationRequiredHandler(grantAppAccess))
	m.Del("/apps/:app/:team", authorizationRequiredHandler(revokeAppAccess))
	m.Get("/apps/:app/log", authorizationRequiredHandler(appLog))
	m.Post("/apps/:app/log", authorizationRequiredHandler(addLog))

	m.Get("/platforms", authorizationRequiredHandler(platformList))

	// These handlers don't use :app on purpose. Using :app means that only
	// the token generate for the given app is valid, but these handlers
	// use a token generated for Gandalf.
	m.Get("/apps/:appname/available", authorizationRequiredHandler(appIsAvailable))
	m.Post("/apps/:appname/repository/clone", authorizationRequiredHandler(cloneRepository))

	if registrationEnabled, _ := config.GetBool("auth:user-registration"); registrationEnabled {
		m.Post("/users", handler(createUser))
	}

	m.Post("/users/:email/password", handler(resetPassword))
	m.Post("/users/:email/tokens", handler(login))
	m.Del("/users/tokens", authorizationRequiredHandler(logout))
	m.Put("/users/password", authorizationRequiredHandler(changePassword))
	m.Del("/users", authorizationRequiredHandler(removeUser))
	m.Get("/users/:email/keys", authorizationRequiredHandler(listKeys))
	m.Post("/users/keys", authorizationRequiredHandler(addKeyToUser))
	m.Del("/users/keys", authorizationRequiredHandler(removeKeyFromUser))

	m.Post("/tokens", adminRequiredHandler(generateAppToken))

	m.Del("/logs", adminRequiredHandler(logRemove))

	m.Get("/teams", authorizationRequiredHandler(teamList))
	m.Post("/teams", authorizationRequiredHandler(createTeam))
	m.Get("/teams/:name", authorizationRequiredHandler(getTeam))
	m.Del("/teams/:name", authorizationRequiredHandler(removeTeam))
	m.Put("/teams/:team/:user", authorizationRequiredHandler(addUserToTeam))
	m.Del("/teams/:team/:user", authorizationRequiredHandler(removeUserFromTeam))

	m.Get("/healers", authorizationRequiredHandler(healers))
	m.Get("/healers/:healer", authorizationRequiredHandler(healer))

	m.Put("/swap", authorizationRequiredHandler(swap))

	m.Get("/healthcheck/", http.HandlerFunc(healthcheck))

	if !dry {
		provisioner, err := getProvisioner()
		if err != nil {
			fmt.Printf("Warning: configuration didn't declare a provisioner, using default provisioner.\n")
		}
		app.Provisioner, err = provision.Get(provisioner)
		if err != nil {
			fatal(err)
		}
		fmt.Printf("Using %q provisioner.\n\n", provisioner)

		listen, err := config.GetString("listen")
		if err != nil {
			fatal(err)
		}
		tls, _ := config.GetBool("use-tls")
		if tls {
			certFile, err := config.GetString("tls:cert-file")
			if err != nil {
				fatal(err)
			}
			keyFile, err := config.GetString("tls:key-file")
			if err != nil {
				fatal(err)
			}
			fmt.Printf("tsuru HTTP/TLS server listening at %s...\n", listen)
			fatal(http.ListenAndServeTLS(listen, certFile, keyFile, m))
		} else {
			listener, err := net.Listen("tcp", listen)
			if err != nil {
				fatal(err)
			}
			fmt.Printf("tsuru HTTP server listening at %s...\n", listen)
			http.Handle("/", m)
			fatal(http.Serve(listener, nil))
		}
	}
}
<|endoftext|>


<commit_before>package whois

import (
	"io"
	"mime"
	"net/http"
	"strconv"
	"strings"
	"time"

	"code.google.com/p/go.net/html/charset"
	"github.com/saintfish/chardet"
)

// Response represents a whois response from a server.
type Response struct {
	Query     string
	Host      string
	FetchedAt time.Time
	MediaType string
	Charset   string
	Body      []byte
}

// NewResponse initializes a new whois response.
func NewResponse(query, host string) *Response {
	return &Response{
		Query:     query,
		Host:      host,
		FetchedAt: time.Now(),
	}
}

// String returns the response body.
func (res *Response) String() string {
	return string(res.Body)
}

// DetectContentType detects and sets the response content type and charset.
func (res *Response) DetectContentType(ct string) {
	// Sensible defaults
	res.MediaType = "text/plain"
	res.Charset = ""

	// Autodetect if not passed a Content-Type header
	if ct == "" {
		ct = http.DetectContentType(res.Body)
	}

	// Content type (e.g. text/plan or text/html)
	mt, params, err := mime.ParseMediaType(ct)
	if err != nil {
		return
	}
	res.MediaType = mt

	// Character set (e.g. utf-8)
	cs, ok := params["charset"]
	if ok {
		res.Charset = cs
	}
	res.DetectCharset()
}

// DetectCharset returns best guess for the reesponse body character set.
func (res *Response) DetectCharset() {
	// Detect via BOM / HTML meta tag
	_, cs1, ok1 := charset.DetermineEncoding(res.Body, res.MediaType)

	// Detect via ICU
	cs2, ok2, html := "", false, false
	var det *chardet.Detector
	if strings.Contains(res.MediaType, "html") || true {
		det = chardet.NewHtmlDetector()
		html = true
	} else {
		det = chardet.NewTextDetector()
	}
	r, err := det.DetectAll(res.Body)
	if err == nil && len(r) > 0 {
		cs2 = strings.ToLower(r[0].Charset)
		ok2 = r[0].Confidence > 50
	}

	// Prefer charset if HTML, otherwise ICU
	if !ok2 && (ok1 || html) {
		res.Charset = cs1
	} else {
		res.Charset = cs2
	}

	// fmt.Printf("Detected charset via go.net/html/charset: %s (%t)\n", cs1, ok1)
	// fmt.Printf("Detected charset via saintfish/chardet:   %s (%d)\n", cs2, r[0].Confidence)
}

// Header returns a stringproto header representing the response.
func (res *Response) Header() http.Header {
	h := make(http.Header)
	h.Set("Query", res.Query)
	h.Set("Host", res.Host)
	h.Set("Fetched-At", res.FetchedAt.Format(time.RFC3339))
	h.Set("Content-Type", res.ContentType())
	h.Set("Content-Length", strconv.Itoa(len(res.Body)))
	return h
}

// ContentType returns an RFC 2045 compatible internet media type string.
func (res *Response) ContentType() string {
	return mime.FormatMediaType(res.MediaType, map[string]string{"charset": res.Charset})
}

// WriteMIME writes a MIME-formatted representation of the response to an io.Writer.
func (res *Response) WriteMIME(w io.Writer) error {
	io.WriteString(w, "MIME-Version: 1.0\r\n")
	err := res.Header().Write(w)
	if err != nil {
		return err
	}
	_, err = io.WriteString(w, "\r\n")
	if err != nil {
		return err
	}
	_, err = w.Write(res.Body)
	if err != nil {
		return err
	}
	return nil
}
<commit_msg>Checksum Response.Body here, rather than whois-fixtures.<commit_after>package whois

import (
	"encoding/hex"
	"io"
	"mime"
	"net/http"
	"strconv"
	"strings"
	"time"

	"crypto/sha1"

	"code.google.com/p/go.net/html/charset"
	"github.com/saintfish/chardet"
)

// Response represents a whois response from a server.
type Response struct {
	Query     string
	Host      string
	FetchedAt time.Time
	MediaType string
	Charset   string
	Body      []byte
}

// NewResponse initializes a new whois response.
func NewResponse(query, host string) *Response {
	return &Response{
		Query:     query,
		Host:      host,
		FetchedAt: time.Now(),
	}
}

// String returns the response body.
func (res *Response) String() string {
	return string(res.Body)
}

// DetectContentType detects and sets the response content type and charset.
func (res *Response) DetectContentType(ct string) {
	// Sensible defaults
	res.MediaType = "text/plain"
	res.Charset = ""

	// Autodetect if not passed a Content-Type header
	if ct == "" {
		ct = http.DetectContentType(res.Body)
	}

	// Content type (e.g. text/plan or text/html)
	mt, params, err := mime.ParseMediaType(ct)
	if err != nil {
		return
	}
	res.MediaType = mt

	// Character set (e.g. utf-8)
	cs, ok := params["charset"]
	if ok {
		res.Charset = cs
	}
	res.DetectCharset()
}

// DetectCharset returns best guess for the reesponse body character set.
func (res *Response) DetectCharset() {
	// Detect via BOM / HTML meta tag
	_, cs1, ok1 := charset.DetermineEncoding(res.Body, res.MediaType)

	// Detect via ICU
	cs2, ok2, html := "", false, false
	var det *chardet.Detector
	if strings.Contains(res.MediaType, "html") || true {
		det = chardet.NewHtmlDetector()
		html = true
	} else {
		det = chardet.NewTextDetector()
	}
	r, err := det.DetectAll(res.Body)
	if err == nil && len(r) > 0 {
		cs2 = strings.ToLower(r[0].Charset)
		ok2 = r[0].Confidence > 50
	}

	// Prefer charset if HTML, otherwise ICU
	if !ok2 && (ok1 || html) {
		res.Charset = cs1
	} else {
		res.Charset = cs2
	}

	// fmt.Printf("Detected charset via go.net/html/charset: %s (%t)\n", cs1, ok1)
	// fmt.Printf("Detected charset via saintfish/chardet:   %s (%d)\n", cs2, r[0].Confidence)
}

// Checksum returns a hex-encoded SHA-1 checksum of the response Body.
func (res *Response) Checksum() string {
	h := sha1.New()
	h.Write(res.Body)
	return strings.ToLower(hex.EncodeToString(h.Sum(nil)))
}

// Header returns a stringproto header representing the response.
func (res *Response) Header() http.Header {
	h := make(http.Header)
	h.Set("Query", res.Query)
	h.Set("Host", res.Host)
	h.Set("Fetched-At", res.FetchedAt.Format(time.RFC3339))
	h.Set("Content-Type", res.ContentType())
	h.Set("Content-Length", strconv.Itoa(len(res.Body)))
	h.Set("Content-Checksum", res.Checksum())
	return h
}

// ContentType returns an RFC 2045 compatible internet media type string.
func (res *Response) ContentType() string {
	return mime.FormatMediaType(res.MediaType, map[string]string{"charset": res.Charset})
}

// WriteMIME writes a MIME-formatted representation of the response to an io.Writer.
func (res *Response) WriteMIME(w io.Writer) error {
	io.WriteString(w, "MIME-Version: 1.0\r\n")
	err := res.Header().Write(w)
	if err != nil {
		return err
	}
	_, err = io.WriteString(w, "\r\n")
	if err != nil {
		return err
	}
	_, err = w.Write(res.Body)
	if err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>package node

import (
	"fmt"
	"log"

	"github.com/streadway/amqp"
)

// Consumer provides a container for `Consumer` configuration and run time values
type Consumer struct {
	channel *amqp.Channel
	conn    *amqp.Connection
	done    chan error
	exch    string
	key     string
	queue   string
	tag     string
	uri     string
}

// NewConsumer will, given the URI of a rabbitMQ instance and a key with which to consume from,
// generate a Consumer for a node to receive messages germane to their operation
func NewConsumer(uri, key string) *Consumer {
	exchangeName := "workflow.exchange"

	c := &Consumer{
		channel: nil,
		conn:    nil,
		done:    make(chan error),
		exch:    exchangeName,
		key:     key,
		queue:   key,
		tag:     key,
		uri:     uri,
	}

	return c
}

// Shutdown ...
// Close AMPQ connections
func (c *Consumer) Shutdown() error {
	// will close() the deliveries channel
	if err := c.channel.Cancel(c.tag, true); err != nil {
		return fmt.Errorf("Consumer cancel failed: %s", err)
	}

	if err := c.conn.Close(); err != nil {
		return fmt.Errorf("AMQP connection close error: %s", err)
	}

	defer log.Printf("AMQP shutdown OK")

	// wait for handle() to exit
	return <-c.done
}
<commit_msg>Remove dead/ unused code<commit_after>package node

import (
	"github.com/streadway/amqp"
)

// Consumer provides a container for `Consumer` configuration and run time values
type Consumer struct {
	channel *amqp.Channel
	conn    *amqp.Connection
	done    chan error
	exch    string
	key     string
	queue   string
	tag     string
	uri     string
}

// NewConsumer will, given the URI of a rabbitMQ instance and a key with which to consume from,
// generate a Consumer for a node to receive messages germane to their operation
func NewConsumer(uri, key string) *Consumer {
	exchangeName := "workflow.exchange"

	c := &Consumer{
		channel: nil,
		conn:    nil,
		done:    make(chan error),
		exch:    exchangeName,
		key:     key,
		queue:   key,
		tag:     key,
		uri:     uri,
	}

	return c
}
<|endoftext|>


<commit_before>package couchbase

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"math/rand"
	"net/http"
	"net/url"
	"time"
)

// ViewRow represents a single result from a view.
//
// Doc is present only if include_docs was set on the request.
type ViewRow struct {
	ID    string
	Key   interface{}
	Value interface{}
	Doc   *interface{}
}

// A ViewError is a node-specific error indicating a partial failure
// within a view result.
type ViewError struct {
	From   string
	Reason string
}

func (ve ViewError) Error() string {
	return "Node: " + ve.From + ", reason: " + ve.Reason
}

// ViewResult holds the entire result set from a view request,
// including the rows and the errors.
type ViewResult struct {
	TotalRows int `json:"total_rows"`
	Rows      []ViewRow
	Errors    []ViewError
}

func (b *Bucket) randomBaseURL() (*url.URL, error) {
	nodes := []Node{}
	for _, n := range b.Nodes() {
		if n.Status == "healthy" && n.CouchAPIBase != "" {
			nodes = append(nodes, n)
		}
	}
	if len(nodes) == 0 {
		return nil, errors.New("no available couch rest URLs")
	}
	nodeNo := rand.Intn(len(nodes))
	node := nodes[nodeNo]
	u, err := ParseURL(node.CouchAPIBase)
	if err != nil {
		return nil, fmt.Errorf("config error: Bucket %q node #%d CouchAPIBase=%q: %v",
			b.Name, nodeNo, node.CouchAPIBase, err)
	} else if b.pool != nil {
		u.User = b.pool.client.BaseURL.User
	}
	return u, err
}

// DocID is the document ID type for the startkey_docid parameter in
// views.
type DocID string

func qParam(k, v string) string {
	format := `"%s"`
	switch k {
	case "startkey_docid","endkey_docid","stale":
		format = "%s"
	}
	return fmt.Sprintf(format, v)
}

// ViewURL constructs a URL for a view with the given ddoc, view name,
// and parameters.
func (b *Bucket) ViewURL(ddoc, name string,
	params map[string]interface{}) (string, error) {
	u, err := b.randomBaseURL()
	if err != nil {
		return "", err
	}

	values := url.Values{}
	for k, v := range params {
		switch t := v.(type) {
		case DocID:
			values[k] = []string{string(t)}
		case string:
			values[k] = []string{qParam(k, t)}
		case int:
			values[k] = []string{fmt.Sprintf(`%d`, t)}
		case bool:
			values[k] = []string{fmt.Sprintf(`%v`, t)}
		default:
			b, err := json.Marshal(v)
			if err != nil {
				return "", fmt.Errorf("unsupported value-type %T in Query, "+
					"json encoder said %v", t, err)
			}
			values[k] = []string{fmt.Sprintf(`%v`, string(b))}
		}
	}

	if ddoc == "" && name == "_all_docs" {
		u.Path = fmt.Sprintf("/%s/_all_docs", b.Name)
	} else {
		u.Path = fmt.Sprintf("/%s/_design/%s/_view/%s", b.Name, ddoc, name)
	}
	u.RawQuery = values.Encode()

	return u.String(), nil
}

// ViewCallback is called for each view invocation.
var ViewCallback func(ddoc, name string, start time.Time, err error)

// ViewCustom performs a view request that can map row values to a
// custom type.
//
// See the source to View for an example usage.
func (b *Bucket) ViewCustom(ddoc, name string, params map[string]interface{},
	vres interface{}) (err error) {
	if SlowServerCallWarningThreshold > 0 {
		defer slowLog(time.Now(), "call to ViewCustom(%q, %q)", ddoc, name)
	}

	if ViewCallback != nil {
		defer func(t time.Time) { ViewCallback(ddoc, name, t, err) }(time.Now())
	}

	u, err := b.ViewURL(ddoc, name, params)
	if err != nil {
		return err
	}

	req, err := http.NewRequest("GET", u, nil)
	if err != nil {
		return err
	}
	maybeAddAuth(req, b.authHandler())

	res, err := HTTPClient.Do(req)
	if err != nil {
		return fmt.Errorf("error starting view req at %v: %v", u, err)
	}
	defer res.Body.Close()

	if res.StatusCode != 200 {
		bod := make([]byte, 512)
		l, _ := res.Body.Read(bod)
		return fmt.Errorf("error executing view req at %v: %v - %s",
			u, res.Status, bod[:l])
	}

	body, err := ioutil.ReadAll(res.Body)
	if err := json.Unmarshal(body, vres); err != nil {
		return nil
	}

	return nil
}

// View executes a view.
//
// The ddoc parameter is just the bare name of your design doc without
// the "_design/" prefix.
//
// Parameters are string keys with values that correspond to couchbase
// view parameters.  Primitive should work fairly naturally (booleans,
// ints, strings, etc...) and other values will attempt to be JSON
// marshaled (useful for array indexing on on view keys, for example).
//
// Example:
//
//   res, err := couchbase.View("myddoc", "myview", map[string]interface{}{
//       "group_level": 2,
//       "startkey_docid":    []interface{}{"thing"},
//       "endkey_docid":      []interface{}{"thing", map[string]string{}},
//       "stale": false,
//       })
func (b *Bucket) View(ddoc, name string, params map[string]interface{}) (ViewResult, error) {
	vres := ViewResult{}

	if err := b.ViewCustom(ddoc, name, params, &vres); err != nil {
		//error in accessing views. Retry once after a bucket refresh
		b.Refresh()
		return vres, b.ViewCustom(ddoc, name, params, &vres)
	} else {
		return vres, nil
	}
}
<commit_msg>Running go fmt<commit_after>package couchbase

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"math/rand"
	"net/http"
	"net/url"
	"time"
)

// ViewRow represents a single result from a view.
//
// Doc is present only if include_docs was set on the request.
type ViewRow struct {
	ID    string
	Key   interface{}
	Value interface{}
	Doc   *interface{}
}

// A ViewError is a node-specific error indicating a partial failure
// within a view result.
type ViewError struct {
	From   string
	Reason string
}

func (ve ViewError) Error() string {
	return "Node: " + ve.From + ", reason: " + ve.Reason
}

// ViewResult holds the entire result set from a view request,
// including the rows and the errors.
type ViewResult struct {
	TotalRows int `json:"total_rows"`
	Rows      []ViewRow
	Errors    []ViewError
}

func (b *Bucket) randomBaseURL() (*url.URL, error) {
	nodes := []Node{}
	for _, n := range b.Nodes() {
		if n.Status == "healthy" && n.CouchAPIBase != "" {
			nodes = append(nodes, n)
		}
	}
	if len(nodes) == 0 {
		return nil, errors.New("no available couch rest URLs")
	}
	nodeNo := rand.Intn(len(nodes))
	node := nodes[nodeNo]
	u, err := ParseURL(node.CouchAPIBase)
	if err != nil {
		return nil, fmt.Errorf("config error: Bucket %q node #%d CouchAPIBase=%q: %v",
			b.Name, nodeNo, node.CouchAPIBase, err)
	} else if b.pool != nil {
		u.User = b.pool.client.BaseURL.User
	}
	return u, err
}

// DocID is the document ID type for the startkey_docid parameter in
// views.
type DocID string

func qParam(k, v string) string {
	format := `"%s"`
	switch k {
	case "startkey_docid", "endkey_docid", "stale":
		format = "%s"
	}
	return fmt.Sprintf(format, v)
}

// ViewURL constructs a URL for a view with the given ddoc, view name,
// and parameters.
func (b *Bucket) ViewURL(ddoc, name string,
	params map[string]interface{}) (string, error) {
	u, err := b.randomBaseURL()
	if err != nil {
		return "", err
	}

	values := url.Values{}
	for k, v := range params {
		switch t := v.(type) {
		case DocID:
			values[k] = []string{string(t)}
		case string:
			values[k] = []string{qParam(k, t)}
		case int:
			values[k] = []string{fmt.Sprintf(`%d`, t)}
		case bool:
			values[k] = []string{fmt.Sprintf(`%v`, t)}
		default:
			b, err := json.Marshal(v)
			if err != nil {
				return "", fmt.Errorf("unsupported value-type %T in Query, "+
					"json encoder said %v", t, err)
			}
			values[k] = []string{fmt.Sprintf(`%v`, string(b))}
		}
	}

	if ddoc == "" && name == "_all_docs" {
		u.Path = fmt.Sprintf("/%s/_all_docs", b.Name)
	} else {
		u.Path = fmt.Sprintf("/%s/_design/%s/_view/%s", b.Name, ddoc, name)
	}
	u.RawQuery = values.Encode()

	return u.String(), nil
}

// ViewCallback is called for each view invocation.
var ViewCallback func(ddoc, name string, start time.Time, err error)

// ViewCustom performs a view request that can map row values to a
// custom type.
//
// See the source to View for an example usage.
func (b *Bucket) ViewCustom(ddoc, name string, params map[string]interface{},
	vres interface{}) (err error) {
	if SlowServerCallWarningThreshold > 0 {
		defer slowLog(time.Now(), "call to ViewCustom(%q, %q)", ddoc, name)
	}

	if ViewCallback != nil {
		defer func(t time.Time) { ViewCallback(ddoc, name, t, err) }(time.Now())
	}

	u, err := b.ViewURL(ddoc, name, params)
	if err != nil {
		return err
	}

	req, err := http.NewRequest("GET", u, nil)
	if err != nil {
		return err
	}
	maybeAddAuth(req, b.authHandler())

	res, err := HTTPClient.Do(req)
	if err != nil {
		return fmt.Errorf("error starting view req at %v: %v", u, err)
	}
	defer res.Body.Close()

	if res.StatusCode != 200 {
		bod := make([]byte, 512)
		l, _ := res.Body.Read(bod)
		return fmt.Errorf("error executing view req at %v: %v - %s",
			u, res.Status, bod[:l])
	}

	body, err := ioutil.ReadAll(res.Body)
	if err := json.Unmarshal(body, vres); err != nil {
		return nil
	}

	return nil
}

// View executes a view.
//
// The ddoc parameter is just the bare name of your design doc without
// the "_design/" prefix.
//
// Parameters are string keys with values that correspond to couchbase
// view parameters.  Primitive should work fairly naturally (booleans,
// ints, strings, etc...) and other values will attempt to be JSON
// marshaled (useful for array indexing on on view keys, for example).
//
// Example:
//
//   res, err := couchbase.View("myddoc", "myview", map[string]interface{}{
//       "group_level": 2,
//       "startkey_docid":    []interface{}{"thing"},
//       "endkey_docid":      []interface{}{"thing", map[string]string{}},
//       "stale": false,
//       })
func (b *Bucket) View(ddoc, name string, params map[string]interface{}) (ViewResult, error) {
	vres := ViewResult{}

	if err := b.ViewCustom(ddoc, name, params, &vres); err != nil {
		//error in accessing views. Retry once after a bucket refresh
		b.Refresh()
		return vres, b.ViewCustom(ddoc, name, params, &vres)
	} else {
		return vres, nil
	}
}
<|endoftext|>


<commit_before>package blockchain

import (
	"context"
	"fmt"
	"net/http"
	"reflect"
	"time"

	log "github.com/sirupsen/logrus"
	cmn "github.com/tendermint/tmlibs/common"

	"github.com/bytom/blockchain/accesstoken"
	"github.com/bytom/blockchain/account"
	"github.com/bytom/blockchain/asset"
	"github.com/bytom/blockchain/pseudohsm"
	"github.com/bytom/blockchain/txfeed"
	"github.com/bytom/blockchain/wallet"
	"github.com/bytom/encoding/json"
	"github.com/bytom/errors"
	"github.com/bytom/mining/cpuminer"
	"github.com/bytom/mining/miningpool"
	"github.com/bytom/p2p"
	"github.com/bytom/p2p/trust"
	"github.com/bytom/protocol"
	protocolTypes "github.com/bytom/protocol/bc/types"
	"github.com/bytom/types"
)

const (
	// BlockchainChannel is a channel for blocks and status updates
	BlockchainChannel = byte(0x40)

	defaultChannelCapacity      = 100
	trySyncIntervalMS           = 100
	statusUpdateIntervalSeconds = 10
	maxBlockchainResponseSize   = 22020096 + 2
	crosscoreRPCPrefix          = "/rpc/"
)

const (
	// SUCCESS indicates the rpc calling is successful.
	SUCCESS = "success"
	// FAIL indicated the rpc calling is failed.
	FAIL = "fail"
)

// Response describes the response standard.
type Response struct {
	Status string      `json:"status,omitempty"`
	Msg    string      `json:"msg,omitempty"`
	Data   interface{} `json:"data,omitempty"`
}

//NewSuccessResponse success response
func NewSuccessResponse(data interface{}) Response {
	return Response{Status: SUCCESS, Data: data}
}

//NewErrorResponse error response
func NewErrorResponse(err error) Response {
	return Response{Status: FAIL, Msg: err.Error()}
}

//BlockchainReactor handles long-term catchup syncing.
type BlockchainReactor struct {
	p2p.BaseReactor

	chain         *protocol.Chain
	wallet        *wallet.Wallet
	accounts      *account.Manager
	assets        *asset.Registry
	accessTokens  *accesstoken.CredentialStore
	txFeedTracker *txfeed.Tracker
	blockKeeper   *blockKeeper
	txPool        *protocol.TxPool
	hsm           *pseudohsm.HSM
	mining        *cpuminer.CPUMiner
	miningPool    *miningpool.MiningPool
	mux           *http.ServeMux
	sw            *p2p.Switch
	handler       http.Handler
	evsw          types.EventSwitch
	miningEnable  bool
}

func batchRecover(ctx context.Context, v *interface{}) {
	if r := recover(); r != nil {
		var err error
		if recoveredErr, ok := r.(error); ok {
			err = recoveredErr
		} else {
			err = fmt.Errorf("panic with %T", r)
		}
		err = errors.Wrap(err)
		*v = err
	}

	if *v == nil {
		return
	}
	// Convert errors into error responses (including errors
	// from recovered panics above).
	if err, ok := (*v).(error); ok {
		*v = errorFormatter.Format(err)
	}
}

func (bcr *BlockchainReactor) info(ctx context.Context) (map[string]interface{}, error) {
	return map[string]interface{}{
		"is_configured": false,
		"version":       "0.001",
		"build_commit":  "----",
		"build_date":    "------",
		"build_config":  "---------",
	}, nil
}

func maxBytes(h http.Handler) http.Handler {
	const maxReqSize = 1e7 // 10MB
	return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		// A block can easily be bigger than maxReqSize, but everything
		// else should be pretty small.
		if req.URL.Path != crosscoreRPCPrefix+"signer/sign-block" {
			req.Body = http.MaxBytesReader(w, req.Body, maxReqSize)
		}
		h.ServeHTTP(w, req)
	})
}

// Used as a request object for api queries
type requestQuery struct {
	Filter       string        `json:"filter,omitempty"`
	FilterParams []interface{} `json:"filter_params,omitempty"`
	SumBy        []string      `json:"sum_by,omitempty"`
	PageSize     int           `json:"page_size"`

	// AscLongPoll and Timeout are used by /list-transactions
	// to facilitate notifications.
	AscLongPoll bool          `json:"ascending_with_long_poll,omitempty"`
	Timeout     json.Duration `json:"timeout"`

	// After is a completely opaque cursor, indicating that only
	// items in the result set after the one identified by `After`
	// should be included. It has no relationship to time.
	After string `json:"after"`

	// These two are used for time-range queries like /list-transactions
	StartTimeMS uint64 `json:"start_time,omitempty"`
	EndTimeMS   uint64 `json:"end_time,omitempty"`

	// This is used for point-in-time queries like /list-balances
	// TODO(bobg): Different request structs for endpoints with different needs
	TimestampMS uint64 `json:"timestamp,omitempty"`

	// This is used for filtering results from /list-access-tokens
	// Value must be "client" or "network"
	Type string `json:"type"`

	// Aliases is used to filter results from /mockshm/list-keys
	Aliases []string `json:"aliases,omitempty"`
}

// Used as a response object for api queries
type page struct {
	Items    interface{}  `json:"items"`
	Next     requestQuery `json:"next"`
	LastPage bool         `json:"last_page"`
	After    string       `json:"after"`
}

// NewBlockchainReactor returns the reactor of whole blockchain.
func NewBlockchainReactor(chain *protocol.Chain, txPool *protocol.TxPool, accounts *account.Manager, assets *asset.Registry, sw *p2p.Switch, hsm *pseudohsm.HSM, wallet *wallet.Wallet, txfeeds *txfeed.Tracker, accessTokens *accesstoken.CredentialStore, miningEnable bool) *BlockchainReactor {
	bcr := &BlockchainReactor{
		chain:         chain,
		wallet:        wallet,
		accounts:      accounts,
		assets:        assets,
		blockKeeper:   newBlockKeeper(chain, sw),
		txPool:        txPool,
		mining:        cpuminer.NewCPUMiner(chain, accounts, txPool),
		miningPool:    miningpool.NewMiningPool(chain, accounts, txPool),
		mux:           http.NewServeMux(),
		sw:            sw,
		hsm:           hsm,
		txFeedTracker: txfeeds,
		accessTokens:  accessTokens,
		miningEnable:  miningEnable,
	}
	bcr.BaseReactor = *p2p.NewBaseReactor("BlockchainReactor", bcr)
	return bcr
}

// OnStart implements BaseService
func (bcr *BlockchainReactor) OnStart() error {
	bcr.BaseReactor.OnStart()
	bcr.BuildHandler()

	if bcr.miningEnable {
		bcr.mining.Start()
	}
	go bcr.syncRoutine()
	return nil
}

// OnStop implements BaseService
func (bcr *BlockchainReactor) OnStop() {
	bcr.BaseReactor.OnStop()
	if bcr.miningEnable {
		bcr.mining.Stop()
	}
	bcr.blockKeeper.Stop()
}

// GetChannels implements Reactor
func (bcr *BlockchainReactor) GetChannels() []*p2p.ChannelDescriptor {
	return []*p2p.ChannelDescriptor{
		&p2p.ChannelDescriptor{
			ID:                BlockchainChannel,
			Priority:          5,
			SendQueueCapacity: 100,
		},
	}
}

// AddPeer implements Reactor by sending our state to peer.
func (bcr *BlockchainReactor) AddPeer(peer *p2p.Peer) {
	peer.Send(BlockchainChannel, struct{ BlockchainMessage }{&StatusRequestMessage{}})
}

// RemovePeer implements Reactor by removing peer from the pool.
func (bcr *BlockchainReactor) RemovePeer(peer *p2p.Peer, reason interface{}) {
	bcr.blockKeeper.RemovePeer(peer.Key)
}

// Receive implements Reactor by handling 4 types of messages (look below).
func (bcr *BlockchainReactor) Receive(chID byte, src *p2p.Peer, msgBytes []byte) {
	var tm *trust.TrustMetric
	key := src.Connection().RemoteAddress.IP.String()
	if tm = bcr.sw.TrustMetricStore.GetPeerTrustMetric(key); tm == nil {
		log.Errorf("Can't get peer trust metric")
		return
	}

	_, msg, err := DecodeMessage(msgBytes)
	if err != nil {
		log.Errorf("Error decoding messagek %v", err)
		return
	}
	log.WithFields(log.Fields{"peerID": src.Key, "msg": msg}).Info("Receive request")

	switch msg := msg.(type) {
	case *BlockRequestMessage:
		var block *protocolTypes.Block
		var err error
		if msg.Height != 0 {
			block, err = bcr.chain.GetBlockByHeight(msg.Height)
		} else {
			block, err = bcr.chain.GetBlockByHash(msg.GetHash())
		}
		if err != nil {
			log.Errorf("Fail on BlockRequestMessage get block: %v", err)
			return
		}
		response, err := NewBlockResponseMessage(block)
		if err != nil {
			log.Errorf("Fail on BlockRequestMessage create resoinse: %v", err)
			return
		}
		src.TrySend(BlockchainChannel, struct{ BlockchainMessage }{response})

	case *BlockResponseMessage:
		bcr.blockKeeper.AddBlock(msg.GetBlock(), src)

	case *StatusRequestMessage:
		block := bcr.chain.BestBlock()
		src.TrySend(BlockchainChannel, struct{ BlockchainMessage }{NewStatusResponseMessage(block)})

	case *StatusResponseMessage:
		bcr.blockKeeper.SetPeerHeight(src.Key, msg.Height, msg.GetHash())

	case *TransactionNotifyMessage:
		tx := msg.GetTransaction()
		if err := bcr.chain.ValidateTx(tx); err != nil {
			bcr.sw.AddScamPeer(src)
		}

	default:
		log.Error(cmn.Fmt("Unknown message type %v", reflect.TypeOf(msg)))
	}
}

// Handle messages from the poolReactor telling the reactor what to do.
// NOTE: Don't sleep in the FOR_LOOP or otherwise slow it down!
// (Except for the SYNC_LOOP, which is the primary purpose and must be synchronous.)
func (bcr *BlockchainReactor) syncRoutine() {
	statusUpdateTicker := time.NewTicker(statusUpdateIntervalSeconds * time.Second)
	newTxCh := bcr.txPool.GetNewTxCh()

	for {
		select {
		case newTx := <-newTxCh:
			bcr.txFeedTracker.TxFilter(newTx)
			go bcr.BroadcastTransaction(newTx)
		case _ = <-statusUpdateTicker.C:
			go bcr.BroadcastStatusResponse()

			if bcr.miningEnable {
				// mining if and only if block sync is finished
				if bcr.blockKeeper.IsCaughtUp() {
					bcr.mining.Start()
				} else {
					bcr.mining.Stop()
				}
			}
		case <-bcr.Quit:
			return
		}
	}
}

// BroadcastStatusResponse broadcasts `BlockStore` height.
func (bcr *BlockchainReactor) BroadcastStatusResponse() {
	block := bcr.chain.BestBlock()
	bcr.Switch.Broadcast(BlockchainChannel, struct{ BlockchainMessage }{NewStatusResponseMessage(block)})
}

// BroadcastTransaction broadcats `BlockStore` transaction.
func (bcr *BlockchainReactor) BroadcastTransaction(tx *protocolTypes.Tx) error {
	msg, err := NewTransactionNotifyMessage(tx)
	if err != nil {
		return err
	}
	bcr.Switch.Broadcast(BlockchainChannel, struct{ BlockchainMessage }{msg})
	return nil
}
<commit_msg>remove useless code in blockchain/reactor.go (#441)<commit_after>package blockchain

import (
	"context"
	"net/http"
	"reflect"
	"time"

	log "github.com/sirupsen/logrus"
	cmn "github.com/tendermint/tmlibs/common"

	"github.com/bytom/blockchain/accesstoken"
	"github.com/bytom/blockchain/account"
	"github.com/bytom/blockchain/asset"
	"github.com/bytom/blockchain/pseudohsm"
	"github.com/bytom/blockchain/txfeed"
	"github.com/bytom/blockchain/wallet"
	"github.com/bytom/mining/cpuminer"
	"github.com/bytom/mining/miningpool"
	"github.com/bytom/p2p"
	"github.com/bytom/p2p/trust"
	"github.com/bytom/protocol"
	protocolTypes "github.com/bytom/protocol/bc/types"
	"github.com/bytom/types"
)

const (
	// BlockchainChannel is a channel for blocks and status updates
	BlockchainChannel = byte(0x40)

	statusUpdateIntervalSeconds = 10
	maxBlockchainResponseSize   = 22020096 + 2
	crosscoreRPCPrefix          = "/rpc/"
)

const (
	// SUCCESS indicates the rpc calling is successful.
	SUCCESS = "success"
	// FAIL indicated the rpc calling is failed.
	FAIL = "fail"
)

// Response describes the response standard.
type Response struct {
	Status string      `json:"status,omitempty"`
	Msg    string      `json:"msg,omitempty"`
	Data   interface{} `json:"data,omitempty"`
}

//NewSuccessResponse success response
func NewSuccessResponse(data interface{}) Response {
	return Response{Status: SUCCESS, Data: data}
}

//NewErrorResponse error response
func NewErrorResponse(err error) Response {
	return Response{Status: FAIL, Msg: err.Error()}
}

//BlockchainReactor handles long-term catchup syncing.
type BlockchainReactor struct {
	p2p.BaseReactor

	chain         *protocol.Chain
	wallet        *wallet.Wallet
	accounts      *account.Manager
	assets        *asset.Registry
	accessTokens  *accesstoken.CredentialStore
	txFeedTracker *txfeed.Tracker
	blockKeeper   *blockKeeper
	txPool        *protocol.TxPool
	hsm           *pseudohsm.HSM
	mining        *cpuminer.CPUMiner
	miningPool    *miningpool.MiningPool
	mux           *http.ServeMux
	sw            *p2p.Switch
	handler       http.Handler
	evsw          types.EventSwitch
	miningEnable  bool
}

func (bcr *BlockchainReactor) info(ctx context.Context) (map[string]interface{}, error) {
	return map[string]interface{}{
		"is_configured": false,
		"version":       "0.001",
		"build_commit":  "----",
		"build_date":    "------",
		"build_config":  "---------",
	}, nil
}

func maxBytes(h http.Handler) http.Handler {
	const maxReqSize = 1e7 // 10MB
	return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		// A block can easily be bigger than maxReqSize, but everything
		// else should be pretty small.
		if req.URL.Path != crosscoreRPCPrefix+"signer/sign-block" {
			req.Body = http.MaxBytesReader(w, req.Body, maxReqSize)
		}
		h.ServeHTTP(w, req)
	})
}

// NewBlockchainReactor returns the reactor of whole blockchain.
func NewBlockchainReactor(chain *protocol.Chain, txPool *protocol.TxPool, accounts *account.Manager, assets *asset.Registry, sw *p2p.Switch, hsm *pseudohsm.HSM, wallet *wallet.Wallet, txfeeds *txfeed.Tracker, accessTokens *accesstoken.CredentialStore, miningEnable bool) *BlockchainReactor {
	bcr := &BlockchainReactor{
		chain:         chain,
		wallet:        wallet,
		accounts:      accounts,
		assets:        assets,
		blockKeeper:   newBlockKeeper(chain, sw),
		txPool:        txPool,
		mining:        cpuminer.NewCPUMiner(chain, accounts, txPool),
		miningPool:    miningpool.NewMiningPool(chain, accounts, txPool),
		mux:           http.NewServeMux(),
		sw:            sw,
		hsm:           hsm,
		txFeedTracker: txfeeds,
		accessTokens:  accessTokens,
		miningEnable:  miningEnable,
	}
	bcr.BaseReactor = *p2p.NewBaseReactor("BlockchainReactor", bcr)
	return bcr
}

// OnStart implements BaseService
func (bcr *BlockchainReactor) OnStart() error {
	bcr.BaseReactor.OnStart()
	bcr.BuildHandler()

	if bcr.miningEnable {
		bcr.mining.Start()
	}
	go bcr.syncRoutine()
	return nil
}

// OnStop implements BaseService
func (bcr *BlockchainReactor) OnStop() {
	bcr.BaseReactor.OnStop()
	if bcr.miningEnable {
		bcr.mining.Stop()
	}
	bcr.blockKeeper.Stop()
}

// GetChannels implements Reactor
func (bcr *BlockchainReactor) GetChannels() []*p2p.ChannelDescriptor {
	return []*p2p.ChannelDescriptor{
		{
			ID:                BlockchainChannel,
			Priority:          5,
			SendQueueCapacity: 100,
		},
	}
}

// AddPeer implements Reactor by sending our state to peer.
func (bcr *BlockchainReactor) AddPeer(peer *p2p.Peer) {
	peer.Send(BlockchainChannel, struct{ BlockchainMessage }{&StatusRequestMessage{}})
}

// RemovePeer implements Reactor by removing peer from the pool.
func (bcr *BlockchainReactor) RemovePeer(peer *p2p.Peer, reason interface{}) {
	bcr.blockKeeper.RemovePeer(peer.Key)
}

// Receive implements Reactor by handling 4 types of messages (look below).
func (bcr *BlockchainReactor) Receive(chID byte, src *p2p.Peer, msgBytes []byte) {
	var tm *trust.TrustMetric
	key := src.Connection().RemoteAddress.IP.String()
	if tm = bcr.sw.TrustMetricStore.GetPeerTrustMetric(key); tm == nil {
		log.Errorf("Can't get peer trust metric")
		return
	}

	_, msg, err := DecodeMessage(msgBytes)
	if err != nil {
		log.Errorf("Error decoding messagek %v", err)
		return
	}
	log.WithFields(log.Fields{"peerID": src.Key, "msg": msg}).Info("Receive request")

	switch msg := msg.(type) {
	case *BlockRequestMessage:
		var block *protocolTypes.Block
		var err error
		if msg.Height != 0 {
			block, err = bcr.chain.GetBlockByHeight(msg.Height)
		} else {
			block, err = bcr.chain.GetBlockByHash(msg.GetHash())
		}
		if err != nil {
			log.Errorf("Fail on BlockRequestMessage get block: %v", err)
			return
		}
		response, err := NewBlockResponseMessage(block)
		if err != nil {
			log.Errorf("Fail on BlockRequestMessage create resoinse: %v", err)
			return
		}
		src.TrySend(BlockchainChannel, struct{ BlockchainMessage }{response})

	case *BlockResponseMessage:
		bcr.blockKeeper.AddBlock(msg.GetBlock(), src)

	case *StatusRequestMessage:
		block := bcr.chain.BestBlock()
		src.TrySend(BlockchainChannel, struct{ BlockchainMessage }{NewStatusResponseMessage(block)})

	case *StatusResponseMessage:
		bcr.blockKeeper.SetPeerHeight(src.Key, msg.Height, msg.GetHash())

	case *TransactionNotifyMessage:
		tx := msg.GetTransaction()
		if err := bcr.chain.ValidateTx(tx); err != nil {
			bcr.sw.AddScamPeer(src)
		}

	default:
		log.Error(cmn.Fmt("Unknown message type %v", reflect.TypeOf(msg)))
	}
}

// Handle messages from the poolReactor telling the reactor what to do.
// NOTE: Don't sleep in the FOR_LOOP or otherwise slow it down!
// (Except for the SYNC_LOOP, which is the primary purpose and must be synchronous.)
func (bcr *BlockchainReactor) syncRoutine() {
	statusUpdateTicker := time.NewTicker(statusUpdateIntervalSeconds * time.Second)
	newTxCh := bcr.txPool.GetNewTxCh()

	for {
		select {
		case newTx := <-newTxCh:
			bcr.txFeedTracker.TxFilter(newTx)
			go bcr.BroadcastTransaction(newTx)
		case _ = <-statusUpdateTicker.C:
			go bcr.BroadcastStatusResponse()

			if bcr.miningEnable {
				// mining if and only if block sync is finished
				if bcr.blockKeeper.IsCaughtUp() {
					bcr.mining.Start()
				} else {
					bcr.mining.Stop()
				}
			}
		case <-bcr.Quit:
			return
		}
	}
}

// BroadcastStatusResponse broadcasts `BlockStore` height.
func (bcr *BlockchainReactor) BroadcastStatusResponse() {
	block := bcr.chain.BestBlock()
	bcr.Switch.Broadcast(BlockchainChannel, struct{ BlockchainMessage }{NewStatusResponseMessage(block)})
}

// BroadcastTransaction broadcats `BlockStore` transaction.
func (bcr *BlockchainReactor) BroadcastTransaction(tx *protocolTypes.Tx) error {
	msg, err := NewTransactionNotifyMessage(tx)
	if err != nil {
		return err
	}
	bcr.Switch.Broadcast(BlockchainChannel, struct{ BlockchainMessage }{msg})
	return nil
}
<|endoftext|>


<commit_before>// +build windows

package uilive

import (
	"fmt"
	"github.com/mattn/go-isatty"
	"os"
	"syscall"
	"unsafe"
)

var kernel32 = syscall.NewLazyDLL("kernel32.dll")

var (
	procGetStdHandle               = kernel32.NewProc("GetStdHandle")
	procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo")
	procGetConsoleCursorInfo       = kernel32.NewProc("GetConsoleCursorInfo")
	procSetConsoleCursorPosition   = kernel32.NewProc("SetConsoleCursorPosition")
	procFillConsoleOutputCharacter = kernel32.NewProc("FillConsoleOutputCharacterW")
	procFillConsoleOutputAttribute = kernel32.NewProc("FillConsoleOutputAttribute")
	procSetConsoleTextAttribute    = kernel32.NewProc("SetConsoleTextAttribute")
	procScrollConsoleScreenBuffer  = kernel32.NewProc("ScrollConsoleScreenBufferW")
)

type wchar uint16
type short int16
type dword uint32
type word uint16

type coord struct {
	x short
	y short
}

type smallRect struct {
	left   short
	top    short
	right  short
	bottom short
}

type consoleScreenBufferInfo struct {
	size              coord
	cursorPosition    coord
	attributes        word
	window            smallRect
	maximumWindowSize coord
}

type consoleCursorInfo struct {
	size    dword
	visible int32
}

func (w *Writer) clearLines() {
	f, ok := w.Out.(*os.File)
	if ok && !isatty.IsTerminal(f.Fd()) {
		ok = false
	}
	if !ok {
		for i := 0; i < w.lineCount; i++ {
			fmt.Fprintf(w.Out, "%c[%dA", ESC, 0) // move the cursor up
			fmt.Fprintf(w.Out, "%c[2K\r", ESC)   // clear the line
		}
		return
	}
	fd := f.Fd()
	var csbi consoleScreenBufferInfo
	procGetConsoleScreenBufferInfo.Call(fd, uintptr(unsafe.Pointer(&csbi)))

	for i := 0; i < w.lineCount; i++ {
		// move the cursor up
		csbi.cursorPosition.y--
		procSetConsoleCursorPosition.Call(fd, uintptr(*(*int32)(unsafe.Pointer(&csbi.cursorPosition))))
		// clear the line
		cursor := coord{
			x: csbi.window.left,
			y: csbi.window.top + csbi.cursorPosition.y,
		}
		var count, w dword
		count = dword(csbi.size.x)
		procFillConsoleOutputCharacter.Call(fd, uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&w)))
		procFillConsoleOutputAttribute.Call(fd, uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&w)))

	}
}
<commit_msg>Remove needless types<commit_after>// +build windows

package uilive

import (
	"fmt"
	"github.com/mattn/go-isatty"
	"os"
	"syscall"
	"unsafe"
)

var kernel32 = syscall.NewLazyDLL("kernel32.dll")

var (
	procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo")
	procSetConsoleCursorPosition   = kernel32.NewProc("SetConsoleCursorPosition")
	procFillConsoleOutputCharacter = kernel32.NewProc("FillConsoleOutputCharacterW")
	procFillConsoleOutputAttribute = kernel32.NewProc("FillConsoleOutputAttribute")
)

type short int16
type dword uint32
type word uint16

type coord struct {
	x short
	y short
}

type smallRect struct {
	left   short
	top    short
	right  short
	bottom short
}

type consoleScreenBufferInfo struct {
	size              coord
	cursorPosition    coord
	attributes        word
	window            smallRect
	maximumWindowSize coord
}

func (w *Writer) clearLines() {
	f, ok := w.Out.(*os.File)
	if ok && !isatty.IsTerminal(f.Fd()) {
		ok = false
	}
	if !ok {
		for i := 0; i < w.lineCount; i++ {
			fmt.Fprintf(w.Out, "%c[%dA", ESC, 0) // move the cursor up
			fmt.Fprintf(w.Out, "%c[2K\r", ESC)   // clear the line
		}
		return
	}
	fd := f.Fd()
	var csbi consoleScreenBufferInfo
	procGetConsoleScreenBufferInfo.Call(fd, uintptr(unsafe.Pointer(&csbi)))

	for i := 0; i < w.lineCount; i++ {
		// move the cursor up
		csbi.cursorPosition.y--
		procSetConsoleCursorPosition.Call(fd, uintptr(*(*int32)(unsafe.Pointer(&csbi.cursorPosition))))
		// clear the line
		cursor := coord{
			x: csbi.window.left,
			y: csbi.window.top + csbi.cursorPosition.y,
		}
		var count, w dword
		count = dword(csbi.size.x)
		procFillConsoleOutputCharacter.Call(fd, uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&w)))
		procFillConsoleOutputAttribute.Call(fd, uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&w)))

	}
}
<|endoftext|>


<commit_before>package main

import (
    "log"
    "net"
    "time"
    "sync"
    "strings"
    "container/list"
    "huabot-sched/db"
)

type Sched struct {
    TotalWorkerCount int
    timer            *time.Timer
    grabQueue        *list.List
    jobQueue         *list.List
    entryPoint       string
    JobLocker        *sync.Mutex
    Funcs            map[string]*FuncStat
}

type FuncStat struct {
    TotalWorker uint `json:"worker_count"`
    TotalJob    uint `json:"job_count"`
    ProcJob     uint `json:"processing"`
}

func (stat *FuncStat) IncrWorker() uint {
    stat.TotalWorker += 1
    return stat.TotalWorker
}

func (stat *FuncStat) DecrWorker() uint {
    stat.TotalWorker -= 1
    return stat.TotalWorker
}

func (stat *FuncStat) IncrJob() uint {
    stat.TotalJob += 1
    return stat.TotalJob
}

func (stat *FuncStat) DecrJob() uint {
    stat.TotalJob -= 1
    return stat.TotalJob
}

func (stat *FuncStat) IncrDoing() uint {
    stat.ProcJob += 1
    return stat.ProcJob
}

func (stat *FuncStat) DecrDoing() uint {
    stat.ProcJob -= 1
    return stat.ProcJob
}

func NewSched(entryPoint string) *Sched {
    sched = new(Sched)
    sched.TotalWorkerCount = 0
    sched.timer = time.NewTimer(1 * time.Hour)
    sched.grabQueue = list.New()
    sched.jobQueue = list.New()
    sched.entryPoint = entryPoint
    sched.JobLocker = new(sync.Mutex)
    sched.Funcs = make(map[string]*FuncStat)
    return sched
}

func (sched *Sched) Serve() {
    parts := strings.SplitN(sched.entryPoint, "://", 2)
    if parts[0] == "unix" {
        sockCheck(parts[1])
    }
    sched.checkJobQueue()
    go sched.handle()
    listen, err := net.Listen(parts[0], parts[1])
    if err != nil {
        log.Fatal(err)
    }
    defer listen.Close()
    log.Printf("huabot-sched started on %s\n", sched.entryPoint)
    for {
        conn, err := listen.Accept()
        if err != nil {
            log.Fatal(err)
        }
        sched.HandleConnection(conn)
    }
}

func (sched *Sched) Notify() {
    sched.timer.Reset(time.Millisecond)
}

func (sched *Sched) DieWorker(worker *Worker) {
    defer sched.Notify()
    sched.TotalWorkerCount -= 1
    log.Printf("Total worker: %d\n", sched.TotalWorkerCount)
    sched.removeGrabQueue(worker)
    worker.Close()
}

func (sched *Sched) HandleConnection(conn net.Conn) {
    worker := NewWorker(sched, Conn{Conn: conn})
    sched.TotalWorkerCount += 1
    log.Printf("Total worker: %d\n", sched.TotalWorkerCount)
    go worker.Handle()
}

func (sched *Sched) Done(jobId int64) {
    defer sched.Notify()
    defer sched.JobLocker.Unlock()
    sched.JobLocker.Lock()
    removeListJob(sched.jobQueue, jobId)
    job, err := db.GetJob(jobId)
    if err == nil {
        job.Delete()
        sched.DecrStatJob(job)
        sched.DecrStatProc(job)
    }
    return
}

func (sched *Sched) isDoJob(job db.Job) bool {
    now := time.Now()
    current := int64(now.Unix())
    ret := false
    for e := sched.jobQueue.Front(); e != nil; e = e.Next() {
        chk := e.Value.(db.Job)
        runAt := chk.RunAt
        if runAt < chk.SchedAt {
            runAt = chk.SchedAt
        }
        if chk.Timeout > 0 && runAt + chk.Timeout < current {
            newJob, _ := db.GetJob(chk.Id)
            if newJob.Status == "doing" {
                newJob.Status = "ready"
                newJob.Save()
                sched.DecrStatProc(newJob)
            }
            sched.jobQueue.Remove(e)
            continue
        }
        if chk.Id == job.Id {
            old := e.Value.(db.Job)
            runAt := old.RunAt
            if runAt < old.SchedAt {
                runAt = old.SchedAt
            }
            if old.Timeout > 0 && runAt + old.Timeout < current {
                ret = false
            } else {
                ret = true
            }
        }
    }
    return ret
}

func (sched *Sched) SubmitJob(worker *Worker, job db.Job) {
    defer sched.JobLocker.Unlock()
    sched.JobLocker.Lock()
    if job.Name == "" {
        job.Delete()
        return
    }
    if sched.isDoJob(job) {
        return
    }
    if !worker.alive {
        return
    }
    if err := worker.HandleDo(job); err != nil {
        worker.alive = false
        sched.DieWorker(worker)
        return
    }
    now := time.Now()
    current := int64(now.Unix())
    job.Status = "doing"
    job.RunAt = current
    job.Save()
    sched.IncrStatProc(job)
    sched.jobQueue.PushBack(job)
    sched.removeGrabQueue(worker)
}

func (sched *Sched) handle() {
    var current time.Time
    var timestamp int64
    var schedJob db.Job
    var isFirst bool
    for {
        if sched.grabQueue.Len() == 0 {
            sched.timer.Reset(time.Minute)
            current =<-sched.timer.C
            continue
        }

        isFirst = true
        for Func, stat := range sched.Funcs {
            if stat.TotalWorker == 0 || (stat.TotalJob > 0 && stat.ProcJob == stat.TotalJob) {
                continue
            }
            jobs, err := db.RangeSchedJob(Func, "ready", 0, 0)
            if err != nil || len(jobs) == 0 {
                stat.TotalJob = stat.ProcJob
                continue
            }

            if isFirst {
                schedJob = jobs[0]
                isFirst = false
                continue
            }

            if schedJob.SchedAt > jobs[0].SchedAt {
                schedJob = jobs[0]
            }
        }
        if isFirst {
            sched.timer.Reset(time.Minute)
            current =<-sched.timer.C
            continue
        }

        timestamp = int64(time.Now().Unix())

        if schedJob.SchedAt > timestamp {
            sched.timer.Reset(time.Second * time.Duration(schedJob.SchedAt - timestamp))
            current =<-sched.timer.C
            timestamp = int64(current.Unix())
            if schedJob.SchedAt > timestamp {
                continue
            }
        }

        isSubmited := false
        for e := sched.grabQueue.Front(); e != nil; e = e.Next() {
            worker := e.Value.(*Worker)
            for _, Func := range worker.Funcs {
                if schedJob.Func == Func {
                    sched.SubmitJob(worker, schedJob)
                    isSubmited = true
                    break
                }
            }
            if isSubmited {
                break
            }
        }

        if !isSubmited {
            sched.DecrStatFunc(schedJob.Func)
        }
    }
}

func (sched *Sched) Fail(jobId int64) {
    defer sched.Notify()
    defer sched.JobLocker.Unlock()
    sched.JobLocker.Lock()
    removeListJob(sched.jobQueue, jobId)
    job, _ := db.GetJob(jobId)
    job.Status = "ready"
    job.Save()
    sched.DecrStatProc(job)
    return
}

func (sched *Sched) IncrStatFunc(Func string) {
    stat, ok := sched.Funcs[Func]
    if !ok {
        stat = new(FuncStat)
        sched.Funcs[Func] = stat
    }
    stat.IncrWorker()
}

func (sched *Sched) DecrStatFunc(Func string) {
    stat, ok := sched.Funcs[Func]
    if ok {
        stat.DecrWorker()
    }
}

func (sched *Sched) IncrStatJob(job db.Job) {
    stat, ok := sched.Funcs[job.Func]
    if !ok {
        stat = new(FuncStat)
        sched.Funcs[job.Func] = stat
    }
    stat.IncrJob()
}

func (sched *Sched) DecrStatJob(job db.Job) {
    stat, ok := sched.Funcs[job.Func]
    if ok {
        stat.DecrJob()
    }
}

func (sched *Sched) IncrStatProc(job db.Job) {
    stat, ok := sched.Funcs[job.Func]
    if !ok {
        stat = new(FuncStat)
        sched.Funcs[job.Func] = stat
    }
    stat.IncrDoing()
}

func (sched *Sched) DecrStatProc(job db.Job) {
    stat, ok := sched.Funcs[job.Func]
    if ok {
        stat.DecrDoing()
    }
}

func (sched *Sched) SchedLater(jobId int64, delay int64) {
    defer sched.Notify()
    defer sched.JobLocker.Unlock()
    sched.JobLocker.Lock()
    removeListJob(sched.jobQueue, jobId)
    job, _ := db.GetJob(jobId)
    job.Status = "ready"
    var now = time.Now()
    job.SchedAt = int64(now.Unix()) + delay
    job.Save()
    sched.DecrStatProc(job)
    return
}

func (sched *Sched) removeGrabQueue(worker *Worker) {
    for e := sched.grabQueue.Front(); e != nil; e = e.Next() {
        if e.Value.(*Worker) == worker {
            sched.grabQueue.Remove(e)
        }
    }
}

func (sched *Sched) checkJobQueue() {
    start := 0
    limit := 20
    total, _ := db.CountJob()
    updateQueue := make([]db.Job, 0)
    removeQueue := make([]db.Job, 0)
    var now = time.Now()
    current := int64(now.Unix())

    for start = 0; start < int(total); start += limit {
        jobs, _ := db.RangeJob(start, start + limit - 1)
        for _, job := range jobs {
            if job.Name == "" {
                removeQueue = append(removeQueue, job)
                continue
            }
            sched.IncrStatJob(job)
            if job.Status != "doing" {
                continue
            }
            runAt := job.RunAt
            if runAt < job.SchedAt {
                runAt = job.SchedAt
            }
            if runAt + job.Timeout < current {
                updateQueue = append(updateQueue, job)
            } else {
                sched.jobQueue.PushBack(job)
                sched.IncrStatProc(job)
            }
        }
    }

    for _, job := range updateQueue {
        job.Status = "ready"
        job.Save()
    }

    for _, job := range removeQueue {
        job.Delete()
    }
}

func (sched *Sched) Close() {
}
<commit_msg>Fix. cause a dead job lock<commit_after>package main

import (
    "log"
    "net"
    "time"
    "sync"
    "strings"
    "container/list"
    "huabot-sched/db"
)

type Sched struct {
    TotalWorkerCount int
    timer            *time.Timer
    grabQueue        *list.List
    jobQueue         *list.List
    entryPoint       string
    JobLocker        *sync.Mutex
    Funcs            map[string]*FuncStat
}

type FuncStat struct {
    TotalWorker uint `json:"worker_count"`
    TotalJob    uint `json:"job_count"`
    ProcJob     uint `json:"processing"`
}

func (stat *FuncStat) IncrWorker() uint {
    stat.TotalWorker += 1
    return stat.TotalWorker
}

func (stat *FuncStat) DecrWorker() uint {
    stat.TotalWorker -= 1
    return stat.TotalWorker
}

func (stat *FuncStat) IncrJob() uint {
    stat.TotalJob += 1
    return stat.TotalJob
}

func (stat *FuncStat) DecrJob() uint {
    stat.TotalJob -= 1
    return stat.TotalJob
}

func (stat *FuncStat) IncrDoing() uint {
    stat.ProcJob += 1
    return stat.ProcJob
}

func (stat *FuncStat) DecrDoing() uint {
    stat.ProcJob -= 1
    return stat.ProcJob
}

func NewSched(entryPoint string) *Sched {
    sched = new(Sched)
    sched.TotalWorkerCount = 0
    sched.timer = time.NewTimer(1 * time.Hour)
    sched.grabQueue = list.New()
    sched.jobQueue = list.New()
    sched.entryPoint = entryPoint
    sched.JobLocker = new(sync.Mutex)
    sched.Funcs = make(map[string]*FuncStat)
    return sched
}

func (sched *Sched) Serve() {
    parts := strings.SplitN(sched.entryPoint, "://", 2)
    if parts[0] == "unix" {
        sockCheck(parts[1])
    }
    sched.checkJobQueue()
    go sched.handle()
    listen, err := net.Listen(parts[0], parts[1])
    if err != nil {
        log.Fatal(err)
    }
    defer listen.Close()
    log.Printf("huabot-sched started on %s\n", sched.entryPoint)
    for {
        conn, err := listen.Accept()
        if err != nil {
            log.Fatal(err)
        }
        sched.HandleConnection(conn)
    }
}

func (sched *Sched) Notify() {
    sched.timer.Reset(time.Millisecond)
}

func (sched *Sched) DieWorker(worker *Worker) {
    defer sched.Notify()
    sched.TotalWorkerCount -= 1
    log.Printf("Total worker: %d\n", sched.TotalWorkerCount)
    sched.removeGrabQueue(worker)
    worker.Close()
}

func (sched *Sched) HandleConnection(conn net.Conn) {
    worker := NewWorker(sched, Conn{Conn: conn})
    sched.TotalWorkerCount += 1
    log.Printf("Total worker: %d\n", sched.TotalWorkerCount)
    go worker.Handle()
}

func (sched *Sched) Done(jobId int64) {
    defer sched.Notify()
    defer sched.JobLocker.Unlock()
    sched.JobLocker.Lock()
    removeListJob(sched.jobQueue, jobId)
    job, err := db.GetJob(jobId)
    if err == nil {
        job.Delete()
        sched.DecrStatJob(job)
        sched.DecrStatProc(job)
    }
    return
}

func (sched *Sched) isDoJob(job db.Job) bool {
    now := time.Now()
    current := int64(now.Unix())
    ret := false
    for e := sched.jobQueue.Front(); e != nil; e = e.Next() {
        chk := e.Value.(db.Job)
        runAt := chk.RunAt
        if runAt < chk.SchedAt {
            runAt = chk.SchedAt
        }
        if chk.Timeout > 0 && runAt + chk.Timeout < current {
            newJob, _ := db.GetJob(chk.Id)
            if newJob.Status == "doing" {
                newJob.Status = "ready"
                newJob.Save()
                sched.DecrStatProc(newJob)
            }
            sched.jobQueue.Remove(e)
            continue
        }
        if chk.Id == job.Id {
            old := e.Value.(db.Job)
            runAt := old.RunAt
            if runAt < old.SchedAt {
                runAt = old.SchedAt
            }
            if old.Timeout > 0 && runAt + old.Timeout < current {
                ret = false
            } else {
                ret = true
            }
        }
    }
    return ret
}

func (sched *Sched) SubmitJob(worker *Worker, job db.Job) {
    defer sched.JobLocker.Unlock()
    sched.JobLocker.Lock()
    if job.Name == "" {
        job.Delete()
        return
    }
    if sched.isDoJob(job) {
        return
    }
    if !worker.alive {
        return
    }
    if err := worker.HandleDo(job); err != nil {
        worker.alive = false
        go sched.DieWorker(worker)
        return
    }
    now := time.Now()
    current := int64(now.Unix())
    job.Status = "doing"
    job.RunAt = current
    job.Save()
    sched.IncrStatProc(job)
    sched.jobQueue.PushBack(job)
    sched.removeGrabQueue(worker)
}

func (sched *Sched) handle() {
    var current time.Time
    var timestamp int64
    var schedJob db.Job
    var isFirst bool
    for {
        if sched.grabQueue.Len() == 0 {
            sched.timer.Reset(time.Minute)
            current =<-sched.timer.C
            continue
        }

        isFirst = true
        for Func, stat := range sched.Funcs {
            if stat.TotalWorker == 0 || (stat.TotalJob > 0 && stat.ProcJob == stat.TotalJob) {
                continue
            }
            jobs, err := db.RangeSchedJob(Func, "ready", 0, 0)
            if err != nil || len(jobs) == 0 {
                stat.TotalJob = stat.ProcJob
                continue
            }

            if isFirst {
                schedJob = jobs[0]
                isFirst = false
                continue
            }

            if schedJob.SchedAt > jobs[0].SchedAt {
                schedJob = jobs[0]
            }
        }
        if isFirst {
            sched.timer.Reset(time.Minute)
            current =<-sched.timer.C
            continue
        }

        timestamp = int64(time.Now().Unix())

        if schedJob.SchedAt > timestamp {
            sched.timer.Reset(time.Second * time.Duration(schedJob.SchedAt - timestamp))
            current =<-sched.timer.C
            timestamp = int64(current.Unix())
            if schedJob.SchedAt > timestamp {
                continue
            }
        }

        isSubmited := false
        for e := sched.grabQueue.Front(); e != nil; e = e.Next() {
            worker := e.Value.(*Worker)
            for _, Func := range worker.Funcs {
                if schedJob.Func == Func {
                    sched.SubmitJob(worker, schedJob)
                    isSubmited = true
                    break
                }
            }
            if isSubmited {
                break
            }
        }

        if !isSubmited {
            sched.DecrStatFunc(schedJob.Func)
        }
    }
}

func (sched *Sched) Fail(jobId int64) {
    defer sched.Notify()
    defer sched.JobLocker.Unlock()
    sched.JobLocker.Lock()
    removeListJob(sched.jobQueue, jobId)
    job, _ := db.GetJob(jobId)
    job.Status = "ready"
    job.Save()
    sched.DecrStatProc(job)
    return
}

func (sched *Sched) IncrStatFunc(Func string) {
    stat, ok := sched.Funcs[Func]
    if !ok {
        stat = new(FuncStat)
        sched.Funcs[Func] = stat
    }
    stat.IncrWorker()
}

func (sched *Sched) DecrStatFunc(Func string) {
    stat, ok := sched.Funcs[Func]
    if ok {
        stat.DecrWorker()
    }
}

func (sched *Sched) IncrStatJob(job db.Job) {
    stat, ok := sched.Funcs[job.Func]
    if !ok {
        stat = new(FuncStat)
        sched.Funcs[job.Func] = stat
    }
    stat.IncrJob()
}

func (sched *Sched) DecrStatJob(job db.Job) {
    stat, ok := sched.Funcs[job.Func]
    if ok {
        stat.DecrJob()
    }
}

func (sched *Sched) IncrStatProc(job db.Job) {
    stat, ok := sched.Funcs[job.Func]
    if !ok {
        stat = new(FuncStat)
        sched.Funcs[job.Func] = stat
    }
    stat.IncrDoing()
}

func (sched *Sched) DecrStatProc(job db.Job) {
    stat, ok := sched.Funcs[job.Func]
    if ok {
        stat.DecrDoing()
    }
}

func (sched *Sched) SchedLater(jobId int64, delay int64) {
    defer sched.Notify()
    defer sched.JobLocker.Unlock()
    sched.JobLocker.Lock()
    removeListJob(sched.jobQueue, jobId)
    job, _ := db.GetJob(jobId)
    job.Status = "ready"
    var now = time.Now()
    job.SchedAt = int64(now.Unix()) + delay
    job.Save()
    sched.DecrStatProc(job)
    return
}

func (sched *Sched) removeGrabQueue(worker *Worker) {
    for e := sched.grabQueue.Front(); e != nil; e = e.Next() {
        if e.Value.(*Worker) == worker {
            sched.grabQueue.Remove(e)
        }
    }
}

func (sched *Sched) checkJobQueue() {
    start := 0
    limit := 20
    total, _ := db.CountJob()
    updateQueue := make([]db.Job, 0)
    removeQueue := make([]db.Job, 0)
    var now = time.Now()
    current := int64(now.Unix())

    for start = 0; start < int(total); start += limit {
        jobs, _ := db.RangeJob(start, start + limit - 1)
        for _, job := range jobs {
            if job.Name == "" {
                removeQueue = append(removeQueue, job)
                continue
            }
            sched.IncrStatJob(job)
            if job.Status != "doing" {
                continue
            }
            runAt := job.RunAt
            if runAt < job.SchedAt {
                runAt = job.SchedAt
            }
            if runAt + job.Timeout < current {
                updateQueue = append(updateQueue, job)
            } else {
                sched.jobQueue.PushBack(job)
                sched.IncrStatProc(job)
            }
        }
    }

    for _, job := range updateQueue {
        job.Status = "ready"
        job.Save()
    }

    for _, job := range removeQueue {
        job.Delete()
    }
}

func (sched *Sched) Close() {
}
<|endoftext|>