Code

Convert the code to the new client.Client interface.
authorSebastian Harl <sh@tokkee.org>
Tue, 12 May 2015 20:43:16 +0000 (22:43 +0200)
committerSebastian Harl <sh@tokkee.org>
Tue, 12 May 2015 20:43:16 +0000 (22:43 +0200)
Drop the custom query abstraction in favor of client.Query().

main.go
server/graph.go
server/query.go
server/server.go

diff --git a/main.go b/main.go
index 0b2bfae0e9b4aaf1b1aa9089a62736951d630726..5ded81417cedb53920b393cbaacd471d64ee9e9b 100644 (file)
--- a/main.go
+++ b/main.go
@@ -34,7 +34,6 @@ import (
        "os"
        "os/user"
 
-       "github.com/sysdb/go/client"
        "github.com/sysdb/webui/server"
 )
 
@@ -63,22 +62,7 @@ func main() {
        flag.Parse()
 
        log.Printf("Connecting to SysDB at %s.", *addr)
-       var conns []*client.Conn
-       for i := 0; i < 10; i++ {
-               conn, err := client.Connect(*addr, *username)
-               if err != nil {
-                       fatalf("Failed to connect to SysDB at %q: %v", *addr, err)
-               }
-               conns = append(conns, conn)
-       }
-       major, minor, patch, extra, err := conns[0].ServerVersion()
-       if err != nil {
-               fatalf("Failed to query server version: %v", err)
-       }
-       log.Printf("Connected to SysDB %d.%d.%d%s.", major, minor, patch, extra)
-
-       srv, err := server.New(server.Config{
-               Conns:        conns,
+       srv, err := server.New(*addr, *username, server.Config{
                TemplatePath: *tmpl,
                StaticPath:   *static,
        })
index 11254d6081526e60db2482dea11a1282982a566d..ed5c7fd8338cedb694944674e0cdfe1c440cdca0 100644 (file)
@@ -39,6 +39,7 @@ import (
        "github.com/gonum/plot/plotter"
        "github.com/gonum/plot/plotutil"
        "github.com/gonum/plot/vg"
+       "github.com/sysdb/go/client"
        "github.com/sysdb/go/sysdb"
 )
 
@@ -70,13 +71,18 @@ func (s *Server) graph(w http.ResponseWriter, req request) {
                return
        }
 
-       res, err := s.query("TIMESERIES %s.%s START %s END %s", req.args[0], req.args[1], start, end)
+       q, err := client.QueryString("TIMESERIES %s.%s START %s END %s", req.args[0], req.args[1], start, end)
+       if err != nil {
+               s.internal(w, fmt.Errorf("Failed to retrieve graph data: %v", err))
+               return
+       }
+       res, err := s.c.Query(q)
        if err != nil {
                s.internal(w, fmt.Errorf("Failed to retrieve graph data: %v", err))
                return
        }
 
-       ts, ok := res.(sysdb.Timeseries)
+       ts, ok := res.(*sysdb.Timeseries)
        if !ok {
                s.internal(w, errors.New("TIMESERIES did not return a time-series"))
                return
index cb74f22f479dcd4bbec5dcd787b82f0fdb992c5c..6d8fddf252d8159e7c3facbf5b7e24b43d5120f5 100644 (file)
@@ -30,13 +30,12 @@ package server
 import (
        "errors"
        "fmt"
-       "log"
        "strings"
        "time"
        "unicode"
 
+       "github.com/sysdb/go/client"
        "github.com/sysdb/go/proto"
-       "github.com/sysdb/go/sysdb"
 )
 
 func listAll(req request, s *Server) (*page, error) {
@@ -44,7 +43,11 @@ func listAll(req request, s *Server) (*page, error) {
                return nil, fmt.Errorf("%s not found", strings.Title(req.cmd))
        }
 
-       res, err := s.query("LIST %s", identifier(req.cmd))
+       q, err := client.QueryString("LIST %s", client.Identifier(req.cmd))
+       if err != nil {
+               return nil, err
+       }
+       res, err := s.c.Query(q)
        if err != nil {
                return nil, err
        }
@@ -94,7 +97,11 @@ func lookup(req request, s *Server) (*page, error) {
                }
        }
 
-       res, err := s.query("LOOKUP %s MATCHING"+args, identifier(typ))
+       q, err := client.QueryString("LOOKUP %s MATCHING"+args, client.Identifier(typ))
+       if err != nil {
+               return nil, err
+       }
+       res, err := s.c.Query(q)
        if err != nil {
                return nil, err
        }
@@ -109,28 +116,33 @@ func fetch(req request, s *Server) (*page, error) {
                return nil, fmt.Errorf("%s not found", strings.Title(req.cmd))
        }
 
-       var res interface{}
+       var q string
        var err error
        switch req.cmd {
        case "host":
                if len(req.args) != 1 {
                        return nil, fmt.Errorf("%s not found", strings.Title(req.cmd))
                }
-               res, err = s.query("FETCH host %s", req.args[0])
+               q, err = client.QueryString("FETCH host %s", req.args[0])
        case "service", "metric":
                if len(req.args) != 2 {
                        return nil, fmt.Errorf("%s not found", strings.Title(req.cmd))
                }
-               res, err = s.query("FETCH %s %s.%s", identifier(req.cmd), req.args[0], req.args[1])
-               if err == nil && req.cmd == "metric" {
-                       return metric(req, res, s)
-               }
+               q, err = client.QueryString("FETCH %s %s.%s", client.Identifier(req.cmd), req.args[0], req.args[1])
        default:
                panic("Unknown request: fetch(" + req.cmd + ")")
        }
        if err != nil {
                return nil, err
        }
+
+       res, err := s.c.Query(q)
+       if err != nil {
+               return nil, err
+       }
+       if req.cmd == "metric" {
+               return metric(req, res, s)
+       }
        return tmpl(s.results[req.cmd], res)
 }
 
@@ -267,73 +279,4 @@ func (s *scanner) inField(r rune) bool {
        return !unicode.IsSpace(r)
 }
 
-type identifier string
-
-func (s *Server) query(cmd string, args ...interface{}) (interface{}, error) {
-       c := <-s.conns
-       defer func() { s.conns <- c }()
-
-       for i, arg := range args {
-               switch v := arg.(type) {
-               case identifier:
-                       // Nothing to do.
-               case string:
-                       args[i] = proto.EscapeString(v)
-               case time.Time:
-                       args[i] = v.Format(datetime)
-               default:
-                       panic(fmt.Sprintf("query: invalid type %T", arg))
-               }
-       }
-
-       cmd = fmt.Sprintf(cmd, args...)
-       m := &proto.Message{
-               Type: proto.ConnectionQuery,
-               Raw:  []byte(cmd),
-       }
-       if err := c.Send(m); err != nil {
-               return nil, fmt.Errorf("Query %q: %v", cmd, err)
-       }
-
-       for {
-               m, err := c.Receive()
-               if err != nil {
-                       return nil, fmt.Errorf("Failed to receive server response: %v", err)
-               }
-               if m.Type == proto.ConnectionLog {
-                       log.Println(string(m.Raw[4:]))
-                       continue
-               } else if m.Type == proto.ConnectionError {
-                       return nil, errors.New(string(m.Raw))
-               }
-
-               t, err := m.DataType()
-               if err != nil {
-                       return nil, fmt.Errorf("Failed to unmarshal response: %v", err)
-               }
-
-               var res interface{}
-               switch t {
-               case proto.HostList:
-                       var hosts []sysdb.Host
-                       err = proto.Unmarshal(m, &hosts)
-                       res = hosts
-               case proto.Host:
-                       var host sysdb.Host
-                       err = proto.Unmarshal(m, &host)
-                       res = host
-               case proto.Timeseries:
-                       var ts sysdb.Timeseries
-                       err = proto.Unmarshal(m, &ts)
-                       res = ts
-               default:
-                       return nil, fmt.Errorf("Unsupported data type %d", t)
-               }
-               if err != nil {
-                       return nil, fmt.Errorf("Failed to unmarshal response: %v", err)
-               }
-               return res, nil
-       }
-}
-
 // vim: set tw=78 sw=4 sw=4 noexpandtab :
index 093c683bb598eabc77e5e8ba76f80955cb39b459..8d0d72dc191770f6810896306ea3f0f3beca64b5 100644 (file)
@@ -28,10 +28,10 @@ package server
 
 import (
        "bytes"
-       "errors"
        "fmt"
        "html/template"
        "io"
+       "log"
        "net/http"
        "net/url"
        "path/filepath"
@@ -42,12 +42,6 @@ import (
 
 // A Config specifies configuration values for a SysDB web server.
 type Config struct {
-       // Conns is a slice of connections to a SysDB server instance. The number of
-       // elements specifies the maximum number of parallel queries to the backend.
-       // Note that a client connection is not thread-safe but multiple idle
-       // connections don't impose any load on the server.
-       Conns []*client.Conn
-
        // TemplatePath specifies the relative or absolute location of template files.
        TemplatePath string
 
@@ -57,7 +51,7 @@ type Config struct {
 
 // A Server implements an http.Handler that serves the SysDB user interface.
 type Server struct {
-       conns chan *client.Conn
+       c *client.Client
 
        // Request multiplexer
        mux map[string]handler
@@ -71,25 +65,20 @@ type Server struct {
 }
 
 // New constructs a new SysDB web server using the specified configuration.
-func New(cfg Config) (*Server, error) {
-       if len(cfg.Conns) == 0 {
-               return nil, errors.New("need at least one client connection")
-       }
+func New(addr, user string, cfg Config) (*Server, error) {
+       s := &Server{results: make(map[string]*template.Template)}
 
-       s := &Server{
-               conns:   make(chan *client.Conn, len(cfg.Conns)),
-               results: make(map[string]*template.Template),
+       var err error
+       if s.c, err = client.Connect(addr, user); err != nil {
+               return nil, err
        }
-       for _, c := range cfg.Conns {
-               s.conns <- c
+       if major, minor, patch, extra, err := s.c.ServerVersion(); err == nil {
+               log.Printf("Connected to SysDB %d.%d.%d%s.", major, minor, patch, extra)
        }
 
-       var err error
-       s.main, err = cfg.parse("main.tmpl")
-       if err != nil {
+       if s.main, err = cfg.parse("main.tmpl"); err != nil {
                return nil, err
        }
-
        types := []string{"host", "hosts", "service", "services", "metric", "metrics"}
        for _, t := range types {
                s.results[t], err = cfg.parse(t + ".tmpl")
@@ -216,10 +205,7 @@ func (s *Server) static(w http.ResponseWriter, req request) {
 }
 
 func index(_ request, s *Server) (*page, error) {
-       c := <-s.conns
-       defer func() { s.conns <- c }()
-
-       major, minor, patch, extra, err := c.ServerVersion()
+       major, minor, patch, extra, err := s.c.ServerVersion()
        if err != nil {
                return nil, err
        }