<commit_before>package server

import (
	"fmt"
	"net/http"

	"github.com/influxdata/chronograf"
)

// AuthRoute are the routes for each type of OAuth2 provider
type AuthRoute struct {
	Name     string `json:"name"`     // Name uniquely identifies the provider
	Label    string `json:"label"`    // Label is a user-facing string to present in the UI
	Login    string `json:"login"`    // Login is the route to the login redirect path
	Logout   string `json:"logout"`   // Logout is the route to the logout redirect path
	Callback string `json:"callback"` // Callback is the route the provider calls to exchange the code/state
}

// AuthRoutes contains all OAuth2 provider routes.
type AuthRoutes []AuthRoute

// Lookup searches all the routes for a specific provider
func (r *AuthRoutes) Lookup(provider string) (AuthRoute, bool) {
	for _, route := range *r {
		if route.Name == provider {
			return route, true
		}
	}
	return AuthRoute{}, false
}

type getRoutesResponse struct {
	Layouts       string                   `json:"layouts"`          // Location of the layouts endpoint
	Mappings      string                   `json:"mappings"`         // Location of the application mappings endpoint
	Sources       string                   `json:"sources"`          // Location of the sources endpoint
	Me            string                   `json:"me"`               // Location of the me endpoint
	Dashboards    string                   `json:"dashboards"`       // Location of the dashboards endpoint
	Auth          []AuthRoute              `json:"auth"`             // Location of all auth routes.
	Logout        *string                  `json:"logout,omitempty"` // Location of the logout route for all auth routes
	ExternalLinks getExternalLinksResponse `json:"external"`         // All external links for the client to use
}

type getExternalLinksResponse struct {
	StatusFeed  *string      `json:"statusFeed,omitempty"` // Location of the a JSON Feed for client's Status page News Feed
	CustomLinks []CustomLink `json:"custom,omitempty"`     // Any custom external links for client's User menu
}

// CustomLink is a handler that returns a custom link to be used in server's routes response, within ExternalLinks
type CustomLink struct {
	Name string `json:"name,omitempty"`
	URL  string `json:"url,omitempty"`
}

// AllRoutes is a handler that returns all links to resources in Chronograf server, as well as
// external links for the client to know about, such as for JSON feeds or custom side nav buttons.
// Optionally, routes for authentication can be returned.
type AllRoutes struct {
	AuthRoutes  []AuthRoute       // Location of all auth routes. If no auth, this can be empty.
	LogoutLink  string            // Location of the logout route for all auth routes. If no auth, this can be empty.
	StatusFeed  string            // External link to the JSON Feed for the News Feed on the client's Status Page
	CustomLinks map[string]string // Any custom external links for client's User menu passed in via CLI/ENV
	Logger      chronograf.Logger
}

// ServeHTTP returns all top level routes and external links within chronograf
func (a *AllRoutes) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	customLinks, err := NewCustomLinks(a.CustomLinks)
	if err != nil {
		msg := fmt.Sprintf("Invalid CustomLinks input: %v", customLinks)
		Error(w, http.StatusUnprocessableEntity, msg, a.Logger)
		return
	}

	routes := getRoutesResponse{
		Sources:    "/chronograf/v1/sources",
		Layouts:    "/chronograf/v1/layouts",
		Me:         "/chronograf/v1/me",
		Mappings:   "/chronograf/v1/mappings",
		Dashboards: "/chronograf/v1/dashboards",
		Auth:       make([]AuthRoute, len(a.AuthRoutes)), // We want to return at least an empty array, rather than null
		ExternalLinks: getExternalLinksResponse{
			StatusFeed:  &a.StatusFeed,
			CustomLinks: customLinks,
		},
	}

	// The JSON response will have no field present for the LogoutLink if there is no logout link.
	if a.LogoutLink != "" {
		routes.Logout = &a.LogoutLink
	}

	for i, route := range a.AuthRoutes {
		routes.Auth[i] = route
	}

	encodeJSON(w, http.StatusOK, routes, a.Logger)
}
<commit_msg>Use appropriate error when NewCustomLinks fails<commit_after>package server

import (
	"fmt"
	"net/http"

	"github.com/influxdata/chronograf"
)

// AuthRoute are the routes for each type of OAuth2 provider
type AuthRoute struct {
	Name     string `json:"name"`     // Name uniquely identifies the provider
	Label    string `json:"label"`    // Label is a user-facing string to present in the UI
	Login    string `json:"login"`    // Login is the route to the login redirect path
	Logout   string `json:"logout"`   // Logout is the route to the logout redirect path
	Callback string `json:"callback"` // Callback is the route the provider calls to exchange the code/state
}

// AuthRoutes contains all OAuth2 provider routes.
type AuthRoutes []AuthRoute

// Lookup searches all the routes for a specific provider
func (r *AuthRoutes) Lookup(provider string) (AuthRoute, bool) {
	for _, route := range *r {
		if route.Name == provider {
			return route, true
		}
	}
	return AuthRoute{}, false
}

type getRoutesResponse struct {
	Layouts       string                   `json:"layouts"`          // Location of the layouts endpoint
	Mappings      string                   `json:"mappings"`         // Location of the application mappings endpoint
	Sources       string                   `json:"sources"`          // Location of the sources endpoint
	Me            string                   `json:"me"`               // Location of the me endpoint
	Dashboards    string                   `json:"dashboards"`       // Location of the dashboards endpoint
	Auth          []AuthRoute              `json:"auth"`             // Location of all auth routes.
	Logout        *string                  `json:"logout,omitempty"` // Location of the logout route for all auth routes
	ExternalLinks getExternalLinksResponse `json:"external"`         // All external links for the client to use
}

type getExternalLinksResponse struct {
	StatusFeed  *string      `json:"statusFeed,omitempty"` // Location of the a JSON Feed for client's Status page News Feed
	CustomLinks []CustomLink `json:"custom,omitempty"`     // Any custom external links for client's User menu
}

// CustomLink is a handler that returns a custom link to be used in server's routes response, within ExternalLinks
type CustomLink struct {
	Name string `json:"name,omitempty"`
	URL  string `json:"url,omitempty"`
}

// AllRoutes is a handler that returns all links to resources in Chronograf server, as well as
// external links for the client to know about, such as for JSON feeds or custom side nav buttons.
// Optionally, routes for authentication can be returned.
type AllRoutes struct {
	AuthRoutes  []AuthRoute       // Location of all auth routes. If no auth, this can be empty.
	LogoutLink  string            // Location of the logout route for all auth routes. If no auth, this can be empty.
	StatusFeed  string            // External link to the JSON Feed for the News Feed on the client's Status Page
	CustomLinks map[string]string // Any custom external links for client's User menu passed in via CLI/ENV
	Logger      chronograf.Logger
}

// ServeHTTP returns all top level routes and external links within chronograf
func (a *AllRoutes) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	customLinks, err := NewCustomLinks(a.CustomLinks)
	if err != nil {
		msg := fmt.Sprintf("Invalid CustomLinks input: %v", customLinks)
		Error(w, http.StatusInternalServerError, msg, a.Logger)
		return
	}

	routes := getRoutesResponse{
		Sources:    "/chronograf/v1/sources",
		Layouts:    "/chronograf/v1/layouts",
		Me:         "/chronograf/v1/me",
		Mappings:   "/chronograf/v1/mappings",
		Dashboards: "/chronograf/v1/dashboards",
		Auth:       make([]AuthRoute, len(a.AuthRoutes)), // We want to return at least an empty array, rather than null
		ExternalLinks: getExternalLinksResponse{
			StatusFeed:  &a.StatusFeed,
			CustomLinks: customLinks,
		},
	}

	// The JSON response will have no field present for the LogoutLink if there is no logout link.
	if a.LogoutLink != "" {
		routes.Logout = &a.LogoutLink
	}

	for i, route := range a.AuthRoutes {
		routes.Auth[i] = route
	}

	encodeJSON(w, http.StatusOK, routes, a.Logger)
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"log"
	"net"
	"net/http"
	"sync"

	"github.com/gorilla/websocket"
	"github.com/pborman/uuid"
)

type Server struct {
	sync.Mutex
	upgrader websocket.Upgrader
	webServer http.Server
	config Config
	destinations map[string]*websocket.Conn
  clientHosts map[string]*websocket.Conn
}

func (s Server) Authorize(hello ClientHello) (challenge string, err error) {
	if (hello.AuthenticationMethod != WEBSOCKET) {
		return "", errors.New("UNSUPPORTED")
	}
	if val, ok := s.clientHosts[hello.DestinationAddress]; ok {
		resp := ServerMessage{
			Status: OKAY,
			Challenge: uuid.New(),
		}
		dat, _ := json.Marshal(resp)
		if err = val.WriteMessage(websocket.TextMessage, dat); err != nil {
			return "", err
		}
		return resp.Challenge, nil;
	}

	return "", errors.New("No active connection from requested destination.")
}

func (s Server) Cleanup(remoteAddr string) {
	if conn, ok := s.destinations[remoteAddr]; ok {
		conn.Close()
		delete(s.destinations, remoteAddr)
		if addrHost, _, err := net.SplitHostPort(remoteAddr); err == nil {
			if cc, ok := s.clientHosts[addrHost]; ok && cc == conn {
				delete(s.clientHosts, addrHost)

				// See if there's another connection from the same address to promote.
				for addr, otherConn := range s.destinations {
					if destAddr, _, err := net.SplitHostPort(addr); err == nil && destAddr == addrHost {
						s.clientHosts[destAddr] = otherConn
						break
					}
				}
			}
		}
	}
}

func IPHandler(server *Server) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		addrHost, _, err := net.SplitHostPort(r.RemoteAddr)
		fmt.Fprintf(w, "externalip({ip:\"%s\"})", addrHost)
	});
}

func SocketHandler(server *Server) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		c, err := server.upgrader.Upgrade(w, r, nil)
		if err != nil {
			return
		}
		addrHost, _, err := net.SplitHostPort(r.RemoteAddr)
		if err != nil {
			return
		}
		if _, ok := server.clientHosts[addrHost]; !ok {
			server.clientHosts[addrHost] = c
		}
		senderState := CLIENTHELLO
		var sendStream chan<- []byte
		challenge := ""

		defer server.Cleanup(r.RemoteAddr)
		for {
			msgType, msg, err := c.ReadMessage()
			if err != nil {
				log.Println("read err:", err)
				break
			}
			if (senderState == CLIENTHELLO && msgType == websocket.TextMessage) {
				hello := ClientHello{}
				err := json.Unmarshal(msg, &hello)
				if err != nil {
					log.Println("Hello err:", err)
					break
				}

				chal, err := server.Authorize(hello);
				if err != nil {
					log.Println("Authorize err:", err)
					resp := ServerMessage{
						Status: UNAUTHORIZED,
					}
					dat, _ := json.Marshal(resp)
					c.WriteMessage(websocket.TextMessage, dat)
					break
				}
				challenge = chal
				senderState = HELLORECEIVED
				continue
			} else if (senderState == HELLORECEIVED && msgType == websocket.TextMessage) {
				auth := ClientAuthorization{}
				err := json.Unmarshal(msg, &auth)
				if err != nil {
					log.Println("Auth err:", err)
					break
				}
				if challenge != "" && challenge == auth.Challenge {
					senderState = AUTHORIZED
					// Further messages should now be considered a gopacket packet source.
					sendStream = CreateStream(server.config, auth.DestinationAddress)
					defer close(sendStream)

					resp := ServerMessage{
						Status: OKAY,
					}
					dat, _ := json.Marshal(resp)
					if err = c.WriteMessage(websocket.TextMessage, dat); err != nil {
						break
					}
				} else {
					log.Println("Bad Challenge from", r.RemoteAddr, " expected ", auth.Challenge, " but got ", challenge)
					resp := ServerMessage{
						Status: UNAUTHORIZED,
					}
					dat, _ := json.Marshal(resp)
					c.WriteMessage(websocket.TextMessage, dat)
					break
				}
				continue
			} else if (senderState == AUTHORIZED && msgType == websocket.BinaryMessage) {
				// Main forwarding loop.
				sendStream <- msg
				continue
			}
			// Else - unexpected message
			log.Println("Unexpected message", msg)
			break
		}
	})
}

func NewServer(conf Config) *Server {
	server := &Server{
		config:     conf,
		destinations: make(map[string]*websocket.Conn),
		clientHosts: make(map[string]*websocket.Conn),
	}

	addr := fmt.Sprintf("0.0.0.0:%d", conf.Port)
	mux := http.NewServeMux()
	mux.Handle("/sp3", SocketHandler(server))
	// By default serve a demo site.
	mux.Handle("/client/", http.StripPrefix("/client/", http.FileServer(http.Dir("../client"))))
	mux.Handle("/ip.js", IPHandler(server))

	webServer := &http.Server{Addr: addr, Handler: mux}
	webServer.ListenAndServe()

	server.webServer = *webServer
	return server
}
<commit_msg>fmt error<commit_after>package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"log"
	"net"
	"net/http"
	"sync"

	"github.com/gorilla/websocket"
	"github.com/pborman/uuid"
)

type Server struct {
	sync.Mutex
	upgrader websocket.Upgrader
	webServer http.Server
	config Config
	destinations map[string]*websocket.Conn
  clientHosts map[string]*websocket.Conn
}

func (s Server) Authorize(hello ClientHello) (challenge string, err error) {
	if (hello.AuthenticationMethod != WEBSOCKET) {
		return "", errors.New("UNSUPPORTED")
	}
	if val, ok := s.clientHosts[hello.DestinationAddress]; ok {
		resp := ServerMessage{
			Status: OKAY,
			Challenge: uuid.New(),
		}
		dat, _ := json.Marshal(resp)
		if err = val.WriteMessage(websocket.TextMessage, dat); err != nil {
			return "", err
		}
		return resp.Challenge, nil;
	}

	return "", errors.New("No active connection from requested destination.")
}

func (s Server) Cleanup(remoteAddr string) {
	if conn, ok := s.destinations[remoteAddr]; ok {
		conn.Close()
		delete(s.destinations, remoteAddr)
		if addrHost, _, err := net.SplitHostPort(remoteAddr); err == nil {
			if cc, ok := s.clientHosts[addrHost]; ok && cc == conn {
				delete(s.clientHosts, addrHost)

				// See if there's another connection from the same address to promote.
				for addr, otherConn := range s.destinations {
					if destAddr, _, err := net.SplitHostPort(addr); err == nil && destAddr == addrHost {
						s.clientHosts[destAddr] = otherConn
						break
					}
				}
			}
		}
	}
}

func IPHandler(server *Server) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		addrHost, _, _ := net.SplitHostPort(r.RemoteAddr)
		fmt.Fprintf(w, "externalip({ip:\"%s\"})", addrHost)
	});
}

func SocketHandler(server *Server) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		c, err := server.upgrader.Upgrade(w, r, nil)
		if err != nil {
			return
		}
		addrHost, _, err := net.SplitHostPort(r.RemoteAddr)
		if err != nil {
			return
		}
		if _, ok := server.clientHosts[addrHost]; !ok {
			server.clientHosts[addrHost] = c
		}
		senderState := CLIENTHELLO
		var sendStream chan<- []byte
		challenge := ""

		defer server.Cleanup(r.RemoteAddr)
		for {
			msgType, msg, err := c.ReadMessage()
			if err != nil {
				log.Println("read err:", err)
				break
			}
			if (senderState == CLIENTHELLO && msgType == websocket.TextMessage) {
				hello := ClientHello{}
				err := json.Unmarshal(msg, &hello)
				if err != nil {
					log.Println("Hello err:", err)
					break
				}

				chal, err := server.Authorize(hello);
				if err != nil {
					log.Println("Authorize err:", err)
					resp := ServerMessage{
						Status: UNAUTHORIZED,
					}
					dat, _ := json.Marshal(resp)
					c.WriteMessage(websocket.TextMessage, dat)
					break
				}
				challenge = chal
				senderState = HELLORECEIVED
				continue
			} else if (senderState == HELLORECEIVED && msgType == websocket.TextMessage) {
				auth := ClientAuthorization{}
				err := json.Unmarshal(msg, &auth)
				if err != nil {
					log.Println("Auth err:", err)
					break
				}
				if challenge != "" && challenge == auth.Challenge {
					senderState = AUTHORIZED
					// Further messages should now be considered a gopacket packet source.
					sendStream = CreateStream(server.config, auth.DestinationAddress)
					defer close(sendStream)

					resp := ServerMessage{
						Status: OKAY,
					}
					dat, _ := json.Marshal(resp)
					if err = c.WriteMessage(websocket.TextMessage, dat); err != nil {
						break
					}
				} else {
					log.Println("Bad Challenge from", r.RemoteAddr, " expected ", auth.Challenge, " but got ", challenge)
					resp := ServerMessage{
						Status: UNAUTHORIZED,
					}
					dat, _ := json.Marshal(resp)
					c.WriteMessage(websocket.TextMessage, dat)
					break
				}
				continue
			} else if (senderState == AUTHORIZED && msgType == websocket.BinaryMessage) {
				// Main forwarding loop.
				sendStream <- msg
				continue
			}
			// Else - unexpected message
			log.Println("Unexpected message", msg)
			break
		}
	})
}

func NewServer(conf Config) *Server {
	server := &Server{
		config:     conf,
		destinations: make(map[string]*websocket.Conn),
		clientHosts: make(map[string]*websocket.Conn),
	}

	addr := fmt.Sprintf("0.0.0.0:%d", conf.Port)
	mux := http.NewServeMux()
	mux.Handle("/sp3", SocketHandler(server))
	// By default serve a demo site.
	mux.Handle("/client/", http.StripPrefix("/client/", http.FileServer(http.Dir("../client"))))
	mux.Handle("/ip.js", IPHandler(server))

	webServer := &http.Server{Addr: addr, Handler: mux}
	webServer.ListenAndServe()

	server.webServer = *webServer
	return server
}
<|endoftext|>


<commit_before>package server

import (
	"fmt"
	"github.com/talbor49/HoneyBee/grammar"
	"log"
	"net"
	"os"
)

const (
	port      = "4590"
	ip        = "0.0.0.0"
	bufferLen = 1024
)

//DatabaseConnection is an extension of the net.Conn struct, added additional required properties.
type DatabaseConnection struct {
	net.Conn
	Bucket      string
	Connections int
	Username    string
}

// StartServer starts the database server - listens at a specific port for any incoming TCP connections.
func StartServer() {
	addr := fmt.Sprintf("%s:%s", ip, port)
	listener, err := net.Listen("tcp", addr)
	if err != nil {
		log.Fatal(err)
		os.Exit(1)
	}
	log.Printf("Listening on: %s", addr)
	// Close the listener socket when the application closes.
	defer listener.Close()

	for {
		conn, err := listener.Accept()
		if err != nil {
			log.Fatalf("Error accepting message from client, %s", err)
			os.Exit(1)
		}
		// Handle connections in a new goroutine
		dbconn := DatabaseConnection{conn, "", 0, ""}
		go handleConnection(dbconn)
	}
}

func handleConnection(conn DatabaseConnection) {
	// authenticate and process further requests
	defer conn.Close()

	var rawRequest []byte
	buff := make([]byte, bufferLen)

	for {
		reqLen, err := conn.Read(buff)
		if err != nil {
			log.Printf("Error reading buffer. %s", err)
			return
		}
		rawRequest = buff[:reqLen]
		if len(rawRequest) > 0 && rawRequest[0] == grammar.QUIT_REQUEST {
			break
		}
		go HandleRequest(rawRequest, &conn)
	}
	log.Println("Closed connection")
}
<commit_msg>Fixed port back to 8080<commit_after>package server

import (
	"fmt"
	"github.com/talbor49/HoneyBee/grammar"
	"log"
	"net"
	"os"
)

const (
	port      = "8080"
	ip        = "0.0.0.0"
	bufferLen = 1024
)

//DatabaseConnection is an extension of the net.Conn struct, added additional required properties.
type DatabaseConnection struct {
	net.Conn
	Bucket      string
	Connections int
	Username    string
}

// StartServer starts the database server - listens at a specific port for any incoming TCP connections.
func StartServer() {
	addr := fmt.Sprintf("%s:%s", ip, port)
	listener, err := net.Listen("tcp", addr)
	if err != nil {
		log.Fatal(err)
		os.Exit(1)
	}
	log.Printf("Listening on: %s", addr)
	// Close the listener socket when the application closes.
	defer listener.Close()

	for {
		conn, err := listener.Accept()
		if err != nil {
			log.Fatalf("Error accepting message from client, %s", err)
			os.Exit(1)
		}
		// Handle connections in a new goroutine
		dbconn := DatabaseConnection{conn, "", 0, ""}
		go handleConnection(dbconn)
	}
}

func handleConnection(conn DatabaseConnection) {
	// authenticate and process further requests
	defer conn.Close()

	var rawRequest []byte
	buff := make([]byte, bufferLen)

	for {
		reqLen, err := conn.Read(buff)
		if err != nil {
			log.Printf("Error reading buffer. %s", err)
			return
		}
		rawRequest = buff[:reqLen]
		if len(rawRequest) > 0 && rawRequest[0] == grammar.QUIT_REQUEST {
			break
		}
		go HandleRequest(rawRequest, &conn)
	}
	log.Println("Closed connection")
}
<|endoftext|>


<commit_before>package database

type Card struct {
	Id         string
	Column     string
	Revealed   bool
	Votes      int
	TotalVotes int
}

func (d *Database) AddCard(card Card) error {
	_, err := d.db.Exec("INSERT INTO cards(Id, Column, Revealed) VALUES (?, ?, ?)",
		card.Id,
		card.Column,
		card.Revealed)

	return err
}

func (d *Database) GetCard(id string) (Card, error) {
	row := d.db.QueryRow(`
    SELECT cards.Id, cards.Column, cards.Revealed, COUNT(votes.Id)
    FROM cards
    JOIN votes ON cards.Id = votes.Card
    GROUP BY cards.Id, cards.Column, cards.Revealed
    WHERE Id=?`,
		id)

	var card Card
	err := row.Scan(&card.Id, &card.Column, &card.Revealed, &card.Votes)

	return card, err
}

func (d *Database) MoveCard(id, columnId string) error {
	_, err := d.db.Exec("UPDATE cards SET Column=? WHERE Id=?",
		columnId,
		id)

	return err
}

func (d *Database) RevealCard(id string) error {
	_, err := d.db.Exec("UPDATE cards SET Revealed=1 WHERE Id=?",
		id)

	return err
}

func (d *Database) DeleteCard(id string) error {
	_, err := d.db.Exec("DELETE FROM cards WHERE Id=?",
		id)

	return err
}

func (d *Database) GroupCards(cardFrom, cardTo string) error {
	tx, err := d.db.Begin()
	if err != nil {
		return err
	}

	_, err = tx.Exec("UPDATE votes SET Card=? WHERE Card=?",
		cardTo,
		cardFrom)

	if err != nil {
		tx.Rollback()
		return err
	}

	_, err = tx.Exec("UPDATE contents SET Card=? WHERE Card=?",
		cardTo,
		cardFrom)

	if err != nil {
		tx.Rollback()
		return err
	}

	_, err = tx.Exec("DELETE FROM cards WHERE Id=?",
		cardFrom)

	if err != nil {
		tx.Rollback()
		return err
	}

	return tx.Commit()
}

func (d *Database) GetCards(username, columnId string) (cards []Card, err error) {
	rows, err := d.db.Query(`
    SELECT cards.Id,
           cards.Column,
           cards.Revealed,
           SUM(CASE WHEN votes.Username = ? THEN 1 ELSE 0 END),
           COUNT(votes.Id)
    FROM cards
    LEFT JOIN votes ON cards.Id = votes.Card
    WHERE cards.Column = ?
    GROUP BY cards.Id, cards.Column, cards.Revealed`,
		username, columnId)
	if err != nil {
		return cards, err
	}
	defer rows.Close()

	for rows.Next() {
		var card Card
		if err = rows.Scan(&card.Id, &card.Column, &card.Revealed, &card.Votes, &card.TotalVotes); err != nil {
			return cards, err
		}
		cards = append(cards, card)
	}

	return cards, rows.Err()
}
<commit_msg>Remove unused GetCard function<commit_after>package database

type Card struct {
	Id         string
	Column     string
	Revealed   bool
	Votes      int
	TotalVotes int
}

func (d *Database) AddCard(card Card) error {
	_, err := d.db.Exec("INSERT INTO cards(Id, Column, Revealed) VALUES (?, ?, ?)",
		card.Id,
		card.Column,
		card.Revealed)

	return err
}

func (d *Database) MoveCard(id, columnId string) error {
	_, err := d.db.Exec("UPDATE cards SET Column=? WHERE Id=?",
		columnId,
		id)

	return err
}

func (d *Database) RevealCard(id string) error {
	_, err := d.db.Exec("UPDATE cards SET Revealed=1 WHERE Id=?",
		id)

	return err
}

func (d *Database) DeleteCard(id string) error {
	_, err := d.db.Exec("DELETE FROM cards WHERE Id=?",
		id)

	return err
}

func (d *Database) GroupCards(cardFrom, cardTo string) error {
	tx, err := d.db.Begin()
	if err != nil {
		return err
	}

	_, err = tx.Exec("UPDATE votes SET Card=? WHERE Card=?",
		cardTo,
		cardFrom)

	if err != nil {
		tx.Rollback()
		return err
	}

	_, err = tx.Exec("UPDATE contents SET Card=? WHERE Card=?",
		cardTo,
		cardFrom)

	if err != nil {
		tx.Rollback()
		return err
	}

	_, err = tx.Exec("DELETE FROM cards WHERE Id=?",
		cardFrom)

	if err != nil {
		tx.Rollback()
		return err
	}

	return tx.Commit()
}

func (d *Database) GetCards(username, columnId string) (cards []Card, err error) {
	rows, err := d.db.Query(`
    SELECT cards.Id,
           cards.Column,
           cards.Revealed,
           SUM(CASE WHEN votes.Username = ? THEN 1 ELSE 0 END),
           COUNT(votes.Id)
    FROM cards
    LEFT JOIN votes ON cards.Id = votes.Card
    WHERE cards.Column = ?
    GROUP BY cards.Id, cards.Column, cards.Revealed`,
		username, columnId)
	if err != nil {
		return cards, err
	}
	defer rows.Close()

	for rows.Next() {
		var card Card
		if err = rows.Scan(&card.Id, &card.Column, &card.Revealed, &card.Votes, &card.TotalVotes); err != nil {
			return cards, err
		}
		cards = append(cards, card)
	}

	return cards, rows.Err()
}
<|endoftext|>


<commit_before>package dataframe

import (
	"fmt"
	"os"
	"reflect"
	"testing"
)

func TestFrame(t *testing.T) {
	c1 := NewColumn("second1")
	for i := 0; i < 100; i++ {
		d := c1.PushBack(NewStringValue(fmt.Sprintf("%d", i)))
		if i+1 != d {
			t.Fatalf("expected %d, got %d", i+1, d)
		}
	}
	c1.UpdateHeader("aaa")
	if c1.Header() != "aaa" {
		t.Fatalf("expected 'aaa', got %v", c1.Header())
	}
	c1.UpdateHeader("second1")
	if c1.Header() != "second1" {
		t.Fatalf("expected 'second1', got %v", c1.Header())
	}

	c2 := NewColumn("second2")
	for i := 0; i < 100; i++ {
		d := c2.PushBack(NewStringValue(fmt.Sprintf("%d", i)))
		if i+1 != d {
			t.Fatalf("expected %d, got %d", i+1, d)
		}
	}

	fr := New()
	if err := fr.AddColumn(c1); err != nil {
		t.Fatal(err)
	}
	if err := fr.AddColumn(c1); err == nil {
		t.Fatal("expected error")
	}
	if err := fr.AddColumn(c2); err != nil {
		t.Fatal(err)
	}
	if err := fr.AddColumn(c2); err == nil {
		t.Fatal("expected error")
	}

	if c, err := fr.Column("second1"); c == nil || err != nil {
		t.Fatal(err)
	}
	if c, err := fr.Column("second2"); c == nil || err != nil {
		t.Fatal(err)
	}

	if err := fr.UpdateHeader("second2", "aaa"); err != nil {
		t.Fatal(err)
	}
	if c, err := fr.Column("aaa"); c == nil || err != nil {
		t.Fatal(err)
	}
	if hs := fr.Headers(); !reflect.DeepEqual(hs, []string{"second1", "aaa"}) {
		t.Fatalf("expected equal, got %q != %q", hs, []string{"second1", "aaa"})
	}

	if err := fr.UpdateHeader("aaa", "second2"); err != nil {
		t.Fatal(err)
	}
	if hs := fr.Headers(); !reflect.DeepEqual(hs, []string{"second1", "second2"}) {
		t.Fatalf("expected equal, got %q != %q", hs, []string{"second1", "second2"})
	}
	if ok := fr.DeleteColumn("second1"); !ok {
		t.Fatalf("expected 'true', got %v", ok)
	}
	if cd := fr.CountColumn(); cd != 1 {
		t.Fatalf("expected 1, got %v", cd)
	}
	if ok := fr.DeleteColumn("second1"); ok {
		t.Fatalf("expected 'false', got %v", ok)
	}
	if c, err := fr.Column("second1"); c != nil || err == nil {
		t.Fatalf("expected <nil, 'second1 does not exist'>, but <%v, %v>", c, err)
	}
	if ok := fr.DeleteColumn("second2"); !ok {
		t.Fatalf("expected 'true', got %v", ok)
	}
	if cd := fr.CountColumn(); cd != 0 {
		t.Fatalf("expected 0, got %v", cd)
	}
}

func TestNewFromCSV(t *testing.T) {
	if _, err := NewFromCSV([]string{"second"}, "testdata/bench-01-all-aggregated.csv"); err == nil {
		t.Fatal("expected error, got nil")
	}
	fr, err := NewFromCSV(nil, "testdata/bench-01-all-aggregated.csv")
	if err != nil {
		t.Fatal(err)
	}
	cols := []string{"second", "avg_latency_ms_consul", "throughput_consul", "cumulative_throughput_consul", "avg_cpu_consul", "avg_memory_mb_consul", "avg_latency_ms_etcd3", "throughput_etcd3", "cumulative_throughput_etcd3", "avg_cpu_etcd3", "avg_memory_mb_etcd3", "avg_latency_ms_etcd2", "throughput_etcd2", "cumulative_throughput_etcd2", "avg_cpu_etcd2", "avg_memory_mb_etcd2", "avg_latency_ms_zk", "throughput_zk", "cumulative_throughput_zk", "avg_cpu_zk", "avg_memory_mb_zk"}
	if !reflect.DeepEqual(fr.Headers(), cols) {
		t.Fatalf("expected %q, got %q", cols, fr.Headers())
	}
	ac, err := fr.Column("avg_latency_ms_etcd3")
	if err != nil {
		t.Fatal(err)
	}
	if v, err := ac.Value(229); !v.IsNil() || err != nil {
		t.Fatalf("expected <nil, nil>, got <%v, %v>", v.IsNil(), err)
	}
	if v, err := ac.Value(0); v.IsNil() || !v.EqualTo(NewStringValue("4.484004")) || err != nil {
		t.Fatalf("expected <nil, nil>, got <%v, %v>", v, err)
	}
	ac2, err := fr.Column("avg_latency_ms_etcd2")
	if err != nil {
		t.Fatal(err)
	}
	if ac.CountRow() != ac2.CountRow() {
		t.Fatalf("expected equal %v != %v", ac.CountRow(), ac2.CountRow())
	}

	fpath := "test.csv"
	if err := fr.CSV(fpath); err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(fpath)

	{
		if _, err := NewFromCSV([]string{"second"}, fpath); err == nil {
			t.Fatal("expected error, got nil")
		}
		fr, err := NewFromCSV(nil, fpath)
		if err != nil {
			t.Fatal(err)
		}
		cols := []string{"second", "avg_latency_ms_consul", "throughput_consul", "cumulative_throughput_consul", "avg_cpu_consul", "avg_memory_mb_consul", "avg_latency_ms_etcd3", "throughput_etcd3", "cumulative_throughput_etcd3", "avg_cpu_etcd3", "avg_memory_mb_etcd3", "avg_latency_ms_etcd2", "throughput_etcd2", "cumulative_throughput_etcd2", "avg_cpu_etcd2", "avg_memory_mb_etcd2", "avg_latency_ms_zk", "throughput_zk", "cumulative_throughput_zk", "avg_cpu_zk", "avg_memory_mb_zk"}
		if !reflect.DeepEqual(fr.Headers(), cols) {
			t.Fatalf("expected %q, got %q", cols, fr.Headers())
		}
		ac, err := fr.Column("avg_latency_ms_etcd3")
		if err != nil {
			t.Fatal(err)
		}
		if v, err := ac.Value(229); !v.IsNil() || err != nil {
			t.Fatalf("expected <nil, nil>, got <%v, %v>", v.IsNil(), err)
		}
		if v, err := ac.Value(0); v.IsNil() || !v.EqualTo(NewStringValue("4.484004")) || err != nil {
			t.Fatalf("expected <nil, nil>, got <%v, %v>", v, err)
		}
		ac2, err := fr.Column("avg_latency_ms_etcd2")
		if err != nil {
			t.Fatal(err)
		}
		if ac.CountRow() != ac2.CountRow() {
			t.Fatalf("expected equal %v != %v", ac.CountRow(), ac2.CountRow())
		}
	}
}

func TestNewFromRows(t *testing.T) {
	fr, err := NewFromCSV(nil, "testdata/bench-01-all-aggregated.csv")
	if err != nil {
		t.Fatal(err)
	}
	header, rows := fr.Rows()
	fr2, err := NewFromRows(header, rows)
	if err != nil {
		t.Fatal(err)
	}
	fpath := "test.csv"
	if err := fr2.CSV(fpath); err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(fpath)

	fr, err = NewFromCSV(nil, fpath)
	if err != nil {
		t.Fatal(err)
	}
	cols := []string{"second", "avg_latency_ms_consul", "throughput_consul", "cumulative_throughput_consul", "avg_cpu_consul", "avg_memory_mb_consul", "avg_latency_ms_etcd3", "throughput_etcd3", "cumulative_throughput_etcd3", "avg_cpu_etcd3", "avg_memory_mb_etcd3", "avg_latency_ms_etcd2", "throughput_etcd2", "cumulative_throughput_etcd2", "avg_cpu_etcd2", "avg_memory_mb_etcd2", "avg_latency_ms_zk", "throughput_zk", "cumulative_throughput_zk", "avg_cpu_zk", "avg_memory_mb_zk"}
	if !reflect.DeepEqual(fr.Headers(), cols) {
		t.Fatalf("expected %q, got %q", cols, fr.Headers())
	}
	ac, err := fr.Column("avg_latency_ms_etcd3")
	if err != nil {
		t.Fatal(err)
	}
	if v, err := ac.Value(229); !v.IsNil() || err != nil {
		t.Fatalf("expected <nil, nil>, got <%v, %v>", v.IsNil(), err)
	}
	if v, err := ac.Value(0); v.IsNil() || !v.EqualTo(NewStringValue("4.484004")) || err != nil {
		t.Fatalf("expected <nil, nil>, got <%v, %v>", v, err)
	}
	ac2, err := fr.Column("avg_latency_ms_etcd2")
	if err != nil {
		t.Fatal(err)
	}
	if ac.CountRow() != ac2.CountRow() {
		t.Fatalf("expected equal %v != %v", ac.CountRow(), ac2.CountRow())
	}
}

func TestDataFrameFindFirst(t *testing.T) {
	fr, err := NewFromCSV(nil, "testdata/bench-01-etcd-1-monitor.csv")
	if err != nil {
		t.Fatal(err)
	}
	col, err := fr.Column("unix_ts")
	if err != nil {
		t.Fatal(err)
	}
	if col.CountRow() != 362 {
		t.Fatalf("expected 362, got %d", col.CountRow())
	}
	minTS := "1458758226"
	idx, ok := col.FindFirst(NewStringValue(minTS))
	if idx != 361 || !ok {
		t.Fatalf("expected 361, true, got %d, %v", idx, ok)
	}
	v, err := col.Value(idx)
	if err != nil {
		t.Fatal(err)
	}
	if !v.EqualTo(NewStringValue(minTS)) {
		t.Fatalf("unexpected: %v != %v", v, minTS)
	}

	if err := col.Deletes(0, 2); err != nil {
		t.Fatal(err)
	}
	if col.CountRow() != 360 {
		t.Fatalf("expected 360, got %d", col.CountRow())
	}
	{
		idx, ok := col.FindFirst(NewStringValue(minTS))
		if idx != 359 || !ok {
			t.Fatalf("expected 359, true, got %d, %v", idx, ok)
		}
		v, err := col.Value(idx)
		if err != nil {
			t.Fatal(err)
		}
		if !v.EqualTo(NewStringValue(minTS)) {
			t.Fatalf("unexpected: %v != %v", v, minTS)
		}
	}
}

func TestMoveColumn(t *testing.T) {
	fr := New()
	if err := fr.AddColumn(NewColumn("0")); err != nil {
		t.Fatal(err)
	}
	if err := fr.AddColumn(NewColumn("1")); err != nil {
		t.Fatal(err)
	}
	if err := fr.AddColumn(NewColumn("2")); err != nil {
		t.Fatal(err)
	}
	if err := fr.AddColumn(NewColumn("3")); err != nil {
		t.Fatal(err)
	}

	if err := fr.MoveColumn("1", 0); err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual([]string{"1", "0", "2", "3"}, fr.Headers()) {
		t.Fatalf("header expected %+v, got %+v", []string{"1", "0", "2", "3"}, fr.Headers())
	}

	if err := fr.MoveColumn("1", 3); err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual([]string{"0", "2", "1", "3"}, fr.Headers()) {
		t.Fatalf("header expected %+v, got %+v", []string{"0", "2", "1", "3"}, fr.Headers())
	}

	if err := fr.MoveColumn("1", 1); err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual([]string{"0", "1", "2", "3"}, fr.Headers()) {
		t.Fatalf("header expected %+v, got %+v", []string{"0", "1", "2", "3"}, fr.Headers())
	}

	if err := fr.MoveColumn("3", 1); err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual([]string{"0", "3", "1", "2"}, fr.Headers()) {
		t.Fatalf("header expected %+v, got %+v", []string{"0", "3", "1", "2"}, fr.Headers())
	}
}

func TestSort(t *testing.T) {
	fr, err := NewFromCSV(nil, "testdata/bench-01-all-aggregated.csv")
	if err != nil {
		t.Fatal(err)
	}
	if err := fr.Sort("second", SortType_Number, SortOption_Descending); err != nil {
		t.Fatal(err)
	}
	fpath := "test.csv"
	if err := fr.CSV(fpath); err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(fpath)
}
<commit_msg>dataframe: add more tests<commit_after>package dataframe

import (
	"fmt"
	"os"
	"reflect"
	"testing"
)

func TestFrame(t *testing.T) {
	c1 := NewColumn("second1")
	for i := 0; i < 100; i++ {
		d := c1.PushBack(NewStringValue(fmt.Sprintf("%d", i)))
		if i+1 != d {
			t.Fatalf("expected %d, got %d", i+1, d)
		}
	}
	c1.UpdateHeader("aaa")
	if c1.Header() != "aaa" {
		t.Fatalf("expected 'aaa', got %v", c1.Header())
	}
	c1.UpdateHeader("second1")
	if c1.Header() != "second1" {
		t.Fatalf("expected 'second1', got %v", c1.Header())
	}

	c2 := NewColumn("second2")
	for i := 0; i < 100; i++ {
		d := c2.PushBack(NewStringValue(fmt.Sprintf("%d", i)))
		if i+1 != d {
			t.Fatalf("expected %d, got %d", i+1, d)
		}
	}

	fr := New()
	if err := fr.AddColumn(c1); err != nil {
		t.Fatal(err)
	}
	if err := fr.AddColumn(c1); err == nil {
		t.Fatal("expected error")
	}
	if err := fr.AddColumn(c2); err != nil {
		t.Fatal(err)
	}
	if err := fr.AddColumn(c2); err == nil {
		t.Fatal("expected error")
	}

	if c, err := fr.Column("second1"); c == nil || err != nil {
		t.Fatal(err)
	}
	if c, err := fr.Column("second2"); c == nil || err != nil {
		t.Fatal(err)
	}

	if err := fr.UpdateHeader("second2", "aaa"); err != nil {
		t.Fatal(err)
	}
	if c, err := fr.Column("aaa"); c == nil || err != nil {
		t.Fatal(err)
	}
	if hs := fr.Headers(); !reflect.DeepEqual(hs, []string{"second1", "aaa"}) {
		t.Fatalf("expected equal, got %q != %q", hs, []string{"second1", "aaa"})
	}

	if err := fr.UpdateHeader("aaa", "second2"); err != nil {
		t.Fatal(err)
	}
	if hs := fr.Headers(); !reflect.DeepEqual(hs, []string{"second1", "second2"}) {
		t.Fatalf("expected equal, got %q != %q", hs, []string{"second1", "second2"})
	}
	if ok := fr.DeleteColumn("second1"); !ok {
		t.Fatalf("expected 'true', got %v", ok)
	}
	if cd := fr.CountColumn(); cd != 1 {
		t.Fatalf("expected 1, got %v", cd)
	}
	if ok := fr.DeleteColumn("second1"); ok {
		t.Fatalf("expected 'false', got %v", ok)
	}
	if c, err := fr.Column("second1"); c != nil || err == nil {
		t.Fatalf("expected <nil, 'second1 does not exist'>, but <%v, %v>", c, err)
	}
	if ok := fr.DeleteColumn("second2"); !ok {
		t.Fatalf("expected 'true', got %v", ok)
	}
	if cd := fr.CountColumn(); cd != 0 {
		t.Fatalf("expected 0, got %v", cd)
	}
}

func TestNewFromCSV(t *testing.T) {
	if _, err := NewFromCSV([]string{"second"}, "testdata/bench-01-all-aggregated.csv"); err == nil {
		t.Fatal("expected error, got nil")
	}
	fr, err := NewFromCSV(nil, "testdata/bench-01-all-aggregated.csv")
	if err != nil {
		t.Fatal(err)
	}
	cols := []string{"second", "avg_latency_ms_consul", "throughput_consul", "cumulative_throughput_consul", "avg_cpu_consul", "avg_memory_mb_consul", "avg_latency_ms_etcd3", "throughput_etcd3", "cumulative_throughput_etcd3", "avg_cpu_etcd3", "avg_memory_mb_etcd3", "avg_latency_ms_etcd2", "throughput_etcd2", "cumulative_throughput_etcd2", "avg_cpu_etcd2", "avg_memory_mb_etcd2", "avg_latency_ms_zk", "throughput_zk", "cumulative_throughput_zk", "avg_cpu_zk", "avg_memory_mb_zk"}
	if !reflect.DeepEqual(fr.Headers(), cols) {
		t.Fatalf("expected %q, got %q", cols, fr.Headers())
	}
	ac, err := fr.Column("avg_latency_ms_etcd3")
	if err != nil {
		t.Fatal(err)
	}
	if v, err := ac.Value(229); !v.IsNil() || err != nil {
		t.Fatalf("expected <nil, nil>, got <%v, %v>", v.IsNil(), err)
	}
	if v, err := ac.Value(0); v.IsNil() || !v.EqualTo(NewStringValue("4.484004")) || err != nil {
		t.Fatalf("expected <nil, nil>, got <%v, %v>", v, err)
	}
	ac2, err := fr.Column("avg_latency_ms_etcd2")
	if err != nil {
		t.Fatal(err)
	}
	if ac.CountRow() != ac2.CountRow() {
		t.Fatalf("expected equal %v != %v", ac.CountRow(), ac2.CountRow())
	}

	fpath := "test.csv"
	if err := fr.CSV(fpath); err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(fpath)

	{
		if _, err := NewFromCSV([]string{"second"}, fpath); err == nil {
			t.Fatal("expected error, got nil")
		}
		fr, err := NewFromCSV(nil, fpath)
		if err != nil {
			t.Fatal(err)
		}
		cols := []string{"second", "avg_latency_ms_consul", "throughput_consul", "cumulative_throughput_consul", "avg_cpu_consul", "avg_memory_mb_consul", "avg_latency_ms_etcd3", "throughput_etcd3", "cumulative_throughput_etcd3", "avg_cpu_etcd3", "avg_memory_mb_etcd3", "avg_latency_ms_etcd2", "throughput_etcd2", "cumulative_throughput_etcd2", "avg_cpu_etcd2", "avg_memory_mb_etcd2", "avg_latency_ms_zk", "throughput_zk", "cumulative_throughput_zk", "avg_cpu_zk", "avg_memory_mb_zk"}
		if !reflect.DeepEqual(fr.Headers(), cols) {
			t.Fatalf("expected %q, got %q", cols, fr.Headers())
		}
		ac, err := fr.Column("avg_latency_ms_etcd3")
		if err != nil {
			t.Fatal(err)
		}
		if v, err := ac.Value(229); !v.IsNil() || err != nil {
			t.Fatalf("expected <nil, nil>, got <%v, %v>", v.IsNil(), err)
		}
		if v, err := ac.Value(0); v.IsNil() || !v.EqualTo(NewStringValue("4.484004")) || err != nil {
			t.Fatalf("expected <nil, nil>, got <%v, %v>", v, err)
		}
		ac2, err := fr.Column("avg_latency_ms_etcd2")
		if err != nil {
			t.Fatal(err)
		}
		if ac.CountRow() != ac2.CountRow() {
			t.Fatalf("expected equal %v != %v", ac.CountRow(), ac2.CountRow())
		}
	}
}

func TestNewFromRows(t *testing.T) {
	fr, err := NewFromCSV(nil, "testdata/bench-01-all-aggregated.csv")
	if err != nil {
		t.Fatal(err)
	}
	header, rows := fr.Rows()
	fr2, err := NewFromRows(header, rows)
	if err != nil {
		t.Fatal(err)
	}
	fpath := "test.csv"
	if err := fr2.CSV(fpath); err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(fpath)

	fr, err = NewFromCSV(nil, fpath)
	if err != nil {
		t.Fatal(err)
	}
	cols := []string{"second", "avg_latency_ms_consul", "throughput_consul", "cumulative_throughput_consul", "avg_cpu_consul", "avg_memory_mb_consul", "avg_latency_ms_etcd3", "throughput_etcd3", "cumulative_throughput_etcd3", "avg_cpu_etcd3", "avg_memory_mb_etcd3", "avg_latency_ms_etcd2", "throughput_etcd2", "cumulative_throughput_etcd2", "avg_cpu_etcd2", "avg_memory_mb_etcd2", "avg_latency_ms_zk", "throughput_zk", "cumulative_throughput_zk", "avg_cpu_zk", "avg_memory_mb_zk"}
	if !reflect.DeepEqual(fr.Headers(), cols) {
		t.Fatalf("expected %q, got %q", cols, fr.Headers())
	}
	ac, err := fr.Column("avg_latency_ms_etcd3")
	if err != nil {
		t.Fatal(err)
	}
	if v, err := ac.Value(229); !v.IsNil() || err != nil {
		t.Fatalf("expected <nil, nil>, got <%v, %v>", v.IsNil(), err)
	}
	if v, err := ac.Value(0); v.IsNil() || !v.EqualTo(NewStringValue("4.484004")) || err != nil {
		t.Fatalf("expected <nil, nil>, got <%v, %v>", v, err)
	}
	ac2, err := fr.Column("avg_latency_ms_etcd2")
	if err != nil {
		t.Fatal(err)
	}
	if ac.CountRow() != ac2.CountRow() {
		t.Fatalf("expected equal %v != %v", ac.CountRow(), ac2.CountRow())
	}
}

func TestDataFrameFindFirst(t *testing.T) {
	fr, err := NewFromCSV(nil, "testdata/bench-01-etcd-1-monitor.csv")
	if err != nil {
		t.Fatal(err)
	}
	col, err := fr.Column("unix_ts")
	if err != nil {
		t.Fatal(err)
	}
	if col.CountRow() != 362 {
		t.Fatalf("expected 362, got %d", col.CountRow())
	}
	minTS := "1458758226"
	idx, ok := col.FindFirst(NewStringValue(minTS))
	if idx != 361 || !ok {
		t.Fatalf("expected 361, true, got %d, %v", idx, ok)
	}
	v, err := col.Value(idx)
	if err != nil {
		t.Fatal(err)
	}
	if !v.EqualTo(NewStringValue(minTS)) {
		t.Fatalf("unexpected: %v != %v", v, minTS)
	}

	if err := col.Deletes(0, 2); err != nil {
		t.Fatal(err)
	}
	if col.CountRow() != 360 {
		t.Fatalf("expected 360, got %d", col.CountRow())
	}
	{
		idx, ok := col.FindFirst(NewStringValue(minTS))
		if idx != 359 || !ok {
			t.Fatalf("expected 359, true, got %d, %v", idx, ok)
		}
		v, err := col.Value(idx)
		if err != nil {
			t.Fatal(err)
		}
		if !v.EqualTo(NewStringValue(minTS)) {
			t.Fatalf("unexpected: %v != %v", v, minTS)
		}
	}
}

func TestMoveColumn(t *testing.T) {
	fr := New()
	if err := fr.AddColumn(NewColumn("0")); err != nil {
		t.Fatal(err)
	}
	if err := fr.AddColumn(NewColumn("1")); err != nil {
		t.Fatal(err)
	}
	if err := fr.AddColumn(NewColumn("2")); err != nil {
		t.Fatal(err)
	}
	if err := fr.AddColumn(NewColumn("3")); err != nil {
		t.Fatal(err)
	}

	if err := fr.MoveColumn("1", 0); err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual([]string{"1", "0", "2", "3"}, fr.Headers()) {
		t.Fatalf("header expected %+v, got %+v", []string{"1", "0", "2", "3"}, fr.Headers())
	}

	if err := fr.MoveColumn("1", 3); err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual([]string{"0", "2", "1", "3"}, fr.Headers()) {
		t.Fatalf("header expected %+v, got %+v", []string{"0", "2", "1", "3"}, fr.Headers())
	}

	if err := fr.MoveColumn("1", 1); err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual([]string{"0", "1", "2", "3"}, fr.Headers()) {
		t.Fatalf("header expected %+v, got %+v", []string{"0", "1", "2", "3"}, fr.Headers())
	}

	if err := fr.MoveColumn("3", 1); err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual([]string{"0", "3", "1", "2"}, fr.Headers()) {
		t.Fatalf("header expected %+v, got %+v", []string{"0", "3", "1", "2"}, fr.Headers())
	}

	if err := fr.AddColumn(NewColumn("A")); err != nil {
		t.Fatal(err)
	}
	if err := fr.AddColumn(NewColumn("B")); err != nil {
		t.Fatal(err)
	}
	if err := fr.AddColumn(NewColumn("C")); err != nil {
		t.Fatal(err)
	}
	if err := fr.MoveColumn("A", 1); err != nil {
		t.Fatal(err)
	}
	if err := fr.MoveColumn("B", 1); err != nil {
		t.Fatal(err)
	}
	if err := fr.MoveColumn("C", 1); err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual([]string{"0", "C", "B", "A", "3", "1", "2"}, fr.Headers()) {
		t.Fatalf("header expected %+v, got %+v", []string{"0", "C", "B", "A", "3", "1", "2"}, fr.Headers())
	}
}

func TestSort(t *testing.T) {
	fr, err := NewFromCSV(nil, "testdata/bench-01-all-aggregated.csv")
	if err != nil {
		t.Fatal(err)
	}
	if err := fr.Sort("second", SortType_Number, SortOption_Descending); err != nil {
		t.Fatal(err)
	}
	fpath := "test.csv"
	if err := fr.CSV(fpath); err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(fpath)
}
<|endoftext|>


<commit_before>// +build testtools

package main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"strconv"
	"time"

	"github.com/github/git-lfs/api"
	"github.com/github/git-lfs/httputil"
	"github.com/github/git-lfs/progress"
	"github.com/github/git-lfs/tools"
)

// This test custom adapter just acts as a bridge for uploads/downloads
// in order to demonstrate & test the custom transfer adapter protocols
// All we actually do is relay the requests back to the normal storage URLs
// of our test server for simplicity, but this proves the principle
func main() {

	scanner := bufio.NewScanner(os.Stdin)
	writer := bufio.NewWriter(os.Stdout)
	errWriter := bufio.NewWriter(os.Stderr)

	for scanner.Scan() {
		line := scanner.Text()
		var req request
		if err := json.Unmarshal([]byte(line), &req); err != nil {
			errWriter.WriteString(fmt.Sprintf("Unable to parse request: %v\n", line))
			continue
		}

		switch req.Id {
		case "init":
			errWriter.WriteString(fmt.Sprintf("Initialised test custom adapter for %s\n", req.Operation))
			resp := &initResponse{}
			sendResponse(resp, writer)
		case "download":
			errWriter.WriteString(fmt.Sprintf("Received download request for %s\n", req.Oid))
			performDownload(req.Oid, req.Size, req.Action, writer, errWriter)
		case "upload":
			errWriter.WriteString(fmt.Sprintf("Received upload request for %s\n", req.Oid))
			performUpload(req.Oid, req.Size, req.Action, req.Path, writer, errWriter)
		case "terminate":
			errWriter.WriteString("Terminating test custom adapter gracefully.\n")
			break
		}
	}

}

func sendResponse(r interface{}, writer *bufio.Writer) error {
	b, err := json.Marshal(r)
	if err != nil {
		return err
	}
	// Line oriented JSON
	b = append(b, '\n')
	_, err = writer.Write(b)
	if err != nil {
		return err
	}
	writer.Flush()
	return nil
}

func sendTransferError(oid string, code int, message string, writer, errWriter *bufio.Writer) {
	resp := &transferResponse{"complete", oid, "", &transferError{code, message}}
	err := sendResponse(resp, writer)
	if err != nil {
		errWriter.WriteString(fmt.Sprintf("Unable to send transfer error: %v", err))
	}
}

func sendProgress(oid string, bytesSoFar int64, bytesSinceLast int, writer, errWriter *bufio.Writer) {
	resp := &progressResponse{"progress", oid, bytesSoFar, bytesSinceLast}
	err := sendResponse(resp, writer)
	if err != nil {
		errWriter.WriteString(fmt.Sprintf("Unable to send progress update: %v", err))
	}
}

func performDownload(oid string, size int64, a *action, writer, errWriter *bufio.Writer) {
	// We just use the URLs we're given, so we're just a proxy for the direct method
	// but this is enough to test intermediate custom adapters
	req, err := httputil.NewHttpRequest("GET", a.Href, a.Header)
	if err != nil {
		sendTransferError(oid, 2, err.Error(), writer, errWriter)
		return
	}
	res, err := httputil.DoHttpRequest(req, true)
	if err != nil {
		sendTransferError(oid, res.StatusCode, err.Error(), writer, errWriter)
		return
	}
	defer res.Body.Close()

	dlFile, err := ioutil.TempFile("", "lfscustomdl")
	if err != nil {
		sendTransferError(oid, 3, err.Error(), writer, errWriter)
		return
	}
	defer dlFile.Close()
	dlfilename := dlFile.Name()
	// Wrap callback to give name context
	cb := func(totalSize int64, readSoFar int64, readSinceLast int) error {
		sendProgress(oid, readSoFar, readSinceLast, writer, errWriter)
		return nil
	}
	_, err = tools.CopyWithCallback(dlFile, res.Body, res.ContentLength, cb)
	if err != nil {
		sendTransferError(oid, 4, fmt.Sprintf("cannot write data to tempfile %q: %v", dlfilename, err), writer, errWriter)
		os.Remove(dlfilename)
		return
	}
	if err := dlFile.Close(); err != nil {
		sendTransferError(oid, 5, fmt.Sprintf("can't close tempfile %q: %v", dlfilename, err), writer, errWriter)
		os.Remove(dlfilename)
		return
	}

	// completed
	complete := &transferResponse{"complete", oid, dlfilename, nil}
	err = sendResponse(complete, writer)
	if err != nil {
		errWriter.WriteString(fmt.Sprintf("Unable to send transfer error: %v", err))
	}
}

func performUpload(oid string, size int64, a *action, fromPath string, writer, errWriter *bufio.Writer) {
	// We just use the URLs we're given, so we're just a proxy for the direct method
	// but this is enough to test intermediate custom adapters
	req, err := httputil.NewHttpRequest("PUT", a.Href, a.Header)
	if err != nil {
		sendTransferError(oid, 2, err.Error(), writer, errWriter)
		return
	}

	if len(req.Header.Get("Content-Type")) == 0 {
		req.Header.Set("Content-Type", "application/octet-stream")
	}

	if req.Header.Get("Transfer-Encoding") == "chunked" {
		req.TransferEncoding = []string{"chunked"}
	} else {
		req.Header.Set("Content-Length", strconv.FormatInt(size, 10))
	}

	req.ContentLength = size

	f, err := os.OpenFile(fromPath, os.O_RDONLY, 0644)
	if err != nil {
		sendTransferError(oid, 3, fmt.Sprintf("Cannot read data from %q: %v", fromPath, err), writer, errWriter)
		return
	}
	defer f.Close()

	// Ensure progress callbacks made while uploading
	// Wrap callback to give name context
	cb := func(totalSize int64, readSoFar int64, readSinceLast int) error {
		sendProgress(oid, readSoFar, readSinceLast, writer, errWriter)
		return nil
	}
	var reader io.Reader
	reader = &progress.CallbackReader{
		C:         cb,
		TotalSize: size,
		Reader:    f,
	}

	req.Body = ioutil.NopCloser(reader)

	res, err := httputil.DoHttpRequest(req, true)
	if err != nil {
		sendTransferError(oid, res.StatusCode, fmt.Sprintf("Error uploading data for %s: %v", oid, err), writer, errWriter)
		return
	}

	if res.StatusCode > 299 {
		sendTransferError(oid, res.StatusCode, fmt.Sprintf("Invalid status for %s: %d", httputil.TraceHttpReq(req), res.StatusCode), writer, errWriter)
		return
	}

	io.Copy(ioutil.Discard, res.Body)
	res.Body.Close()

}

// Structs reimplemented so closer to a real external implementation
type header struct {
	Key   string `json:"key"`
	Value string `json:"value"`
}
type action struct {
	Href      string            `json:"href"`
	Header    map[string]string `json:"header,omitempty"`
	ExpiresAt time.Time         `json:"expires_at,omitempty"`
}
type transferError struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
}

// Combined request struct which can accept anything
type request struct {
	Id                  string  `json:"id"`
	Operation           string  `json:"operation"`
	Concurrent          bool    `json:"concurrent"`
	ConcurrentTransfers int     `json:"concurrenttransfers"`
	Oid                 string  `json:"oid"`
	Size                int64   `json:"size"`
	Path                string  `json:"path"`
	Action              *action `json:"action"`
}

type initResponse struct {
	Error *api.ObjectError `json:"error,omitempty"`
}
type transferResponse struct {
	Id    string         `json:"id"`
	Oid   string         `json:"oid"`
	Path  string         `json:"path,omitempty"` // always blank for upload
	Error *transferError `json:"error,omitempty"`
}
type progressResponse struct {
	Id             string `json:"id"`
	Oid            string `json:"oid"`
	BytesSoFar     int64  `json:"bytesSoFar"`
	BytesSinceLast int    `json:"bytesSinceLast"`
}
<commit_msg>Make sure we flush stderr consistently from custom adapter<commit_after>// +build testtools

package main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/github/git-lfs/api"
	"github.com/github/git-lfs/httputil"
	"github.com/github/git-lfs/progress"
	"github.com/github/git-lfs/tools"
)

// This test custom adapter just acts as a bridge for uploads/downloads
// in order to demonstrate & test the custom transfer adapter protocols
// All we actually do is relay the requests back to the normal storage URLs
// of our test server for simplicity, but this proves the principle
func main() {

	scanner := bufio.NewScanner(os.Stdin)
	writer := bufio.NewWriter(os.Stdout)
	errWriter := bufio.NewWriter(os.Stderr)

	for scanner.Scan() {
		line := scanner.Text()
		var req request
		if err := json.Unmarshal([]byte(line), &req); err != nil {
			writeToStderr(fmt.Sprintf("Unable to parse request: %v\n", line), errWriter)
			continue
		}

		switch req.Id {
		case "init":
			writeToStderr(fmt.Sprintf("Initialised test custom adapter for %s\n", req.Operation), errWriter)
			resp := &initResponse{}
			sendResponse(resp, writer, errWriter)
		case "download":
			writeToStderr(fmt.Sprintf("Received download request for %s\n", req.Oid), errWriter)
			performDownload(req.Oid, req.Size, req.Action, writer, errWriter)
		case "upload":
			writeToStderr(fmt.Sprintf("Received upload request for %s\n", req.Oid), errWriter)
			performUpload(req.Oid, req.Size, req.Action, req.Path, writer, errWriter)
		case "terminate":
			writeToStderr("Terminating test custom adapter gracefully.\n", errWriter)
			break
		}
	}

}

func writeToStderr(msg string, errWriter *bufio.Writer) {
	if !strings.HasSuffix(msg, "\n") {
		msg = msg + "\n"
	}
	errWriter.WriteString(msg)
	errWriter.Flush()
}

func sendResponse(r interface{}, writer, errWriter *bufio.Writer) error {
	b, err := json.Marshal(r)
	if err != nil {
		return err
	}
	// Line oriented JSON
	b = append(b, '\n')
	_, err = writer.Write(b)
	if err != nil {
		return err
	}
	writer.Flush()
	writeToStderr(fmt.Sprintf("Sent message %v", string(b)), errWriter)
	return nil
}

func sendTransferError(oid string, code int, message string, writer, errWriter *bufio.Writer) {
	resp := &transferResponse{"complete", oid, "", &transferError{code, message}}
	err := sendResponse(resp, writer, errWriter)
	if err != nil {
		writeToStderr(fmt.Sprintf("Unable to send transfer error: %v\n", err), errWriter)
	}
}

func sendProgress(oid string, bytesSoFar int64, bytesSinceLast int, writer, errWriter *bufio.Writer) {
	resp := &progressResponse{"progress", oid, bytesSoFar, bytesSinceLast}
	err := sendResponse(resp, writer, errWriter)
	if err != nil {
		writeToStderr(fmt.Sprintf("Unable to send progress update: %v\n", err), errWriter)
	}
}

func performDownload(oid string, size int64, a *action, writer, errWriter *bufio.Writer) {
	// We just use the URLs we're given, so we're just a proxy for the direct method
	// but this is enough to test intermediate custom adapters
	req, err := httputil.NewHttpRequest("GET", a.Href, a.Header)
	if err != nil {
		sendTransferError(oid, 2, err.Error(), writer, errWriter)
		return
	}
	res, err := httputil.DoHttpRequest(req, true)
	if err != nil {
		sendTransferError(oid, res.StatusCode, err.Error(), writer, errWriter)
		return
	}
	defer res.Body.Close()

	dlFile, err := ioutil.TempFile("", "lfscustomdl")
	if err != nil {
		sendTransferError(oid, 3, err.Error(), writer, errWriter)
		return
	}
	defer dlFile.Close()
	dlfilename := dlFile.Name()
	// Wrap callback to give name context
	cb := func(totalSize int64, readSoFar int64, readSinceLast int) error {
		sendProgress(oid, readSoFar, readSinceLast, writer, errWriter)
		return nil
	}
	_, err = tools.CopyWithCallback(dlFile, res.Body, res.ContentLength, cb)
	if err != nil {
		sendTransferError(oid, 4, fmt.Sprintf("cannot write data to tempfile %q: %v", dlfilename, err), writer, errWriter)
		os.Remove(dlfilename)
		return
	}
	if err := dlFile.Close(); err != nil {
		sendTransferError(oid, 5, fmt.Sprintf("can't close tempfile %q: %v", dlfilename, err), writer, errWriter)
		os.Remove(dlfilename)
		return
	}

	// completed
	complete := &transferResponse{"complete", oid, dlfilename, nil}
	err = sendResponse(complete, writer, errWriter)
	if err != nil {
		writeToStderr(fmt.Sprintf("Unable to send completion message: %v\n", err), errWriter)
	}
}

func performUpload(oid string, size int64, a *action, fromPath string, writer, errWriter *bufio.Writer) {
	// We just use the URLs we're given, so we're just a proxy for the direct method
	// but this is enough to test intermediate custom adapters
	req, err := httputil.NewHttpRequest("PUT", a.Href, a.Header)
	if err != nil {
		sendTransferError(oid, 2, err.Error(), writer, errWriter)
		return
	}

	if len(req.Header.Get("Content-Type")) == 0 {
		req.Header.Set("Content-Type", "application/octet-stream")
	}

	if req.Header.Get("Transfer-Encoding") == "chunked" {
		req.TransferEncoding = []string{"chunked"}
	} else {
		req.Header.Set("Content-Length", strconv.FormatInt(size, 10))
	}

	req.ContentLength = size

	f, err := os.OpenFile(fromPath, os.O_RDONLY, 0644)
	if err != nil {
		sendTransferError(oid, 3, fmt.Sprintf("Cannot read data from %q: %v", fromPath, err), writer, errWriter)
		return
	}
	defer f.Close()

	// Ensure progress callbacks made while uploading
	// Wrap callback to give name context
	cb := func(totalSize int64, readSoFar int64, readSinceLast int) error {
		sendProgress(oid, readSoFar, readSinceLast, writer, errWriter)
		return nil
	}
	var reader io.Reader
	reader = &progress.CallbackReader{
		C:         cb,
		TotalSize: size,
		Reader:    f,
	}

	req.Body = ioutil.NopCloser(reader)

	res, err := httputil.DoHttpRequest(req, true)
	if err != nil {
		sendTransferError(oid, res.StatusCode, fmt.Sprintf("Error uploading data for %s: %v", oid, err), writer, errWriter)
		return
	}

	if res.StatusCode > 299 {
		sendTransferError(oid, res.StatusCode, fmt.Sprintf("Invalid status for %s: %d", httputil.TraceHttpReq(req), res.StatusCode), writer, errWriter)
		return
	}

	io.Copy(ioutil.Discard, res.Body)
	res.Body.Close()

}

// Structs reimplemented so closer to a real external implementation
type header struct {
	Key   string `json:"key"`
	Value string `json:"value"`
}
type action struct {
	Href      string            `json:"href"`
	Header    map[string]string `json:"header,omitempty"`
	ExpiresAt time.Time         `json:"expires_at,omitempty"`
}
type transferError struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
}

// Combined request struct which can accept anything
type request struct {
	Id                  string  `json:"id"`
	Operation           string  `json:"operation"`
	Concurrent          bool    `json:"concurrent"`
	ConcurrentTransfers int     `json:"concurrenttransfers"`
	Oid                 string  `json:"oid"`
	Size                int64   `json:"size"`
	Path                string  `json:"path"`
	Action              *action `json:"action"`
}

type initResponse struct {
	Error *api.ObjectError `json:"error,omitempty"`
}
type transferResponse struct {
	Id    string         `json:"id"`
	Oid   string         `json:"oid"`
	Path  string         `json:"path,omitempty"` // always blank for upload
	Error *transferError `json:"error,omitempty"`
}
type progressResponse struct {
	Id             string `json:"id"`
	Oid            string `json:"oid"`
	BytesSoFar     int64  `json:"bytesSoFar"`
	BytesSinceLast int    `json:"bytesSinceLast"`
}
<|endoftext|>


<commit_before>package storage

import (
	"net/http"
	"time"

	"github.com/docker/distribution"
	"github.com/docker/distribution/digest"
)

// layerReader implements Layer and provides facilities for reading and
// seeking.
type layerReader struct {
	fileReader

	digest digest.Digest
}

var _ distribution.Layer = &layerReader{}

func (lr *layerReader) Digest() digest.Digest {
	return lr.digest
}

func (lr *layerReader) Length() int64 {
	return lr.size
}

func (lr *layerReader) CreatedAt() time.Time {
	return lr.modtime
}

// Close the layer. Should be called when the resource is no longer needed.
func (lr *layerReader) Close() error {
	return lr.closeWithErr(distribution.ErrLayerClosed)
}

func (lr *layerReader) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Docker-Content-Digest", lr.digest.String())

	if url, err := lr.fileReader.driver.URLFor(lr.path, map[string]interface{}{}); err == nil {
		http.Redirect(w, r, url, http.StatusTemporaryRedirect)
	}
	http.ServeContent(w, r, lr.digest.String(), lr.CreatedAt(), lr)
}
<commit_msg>Insert request method option storage driver URLFor<commit_after>package storage

import (
	"net/http"
	"time"

	"github.com/docker/distribution"
	"github.com/docker/distribution/digest"
)

// layerReader implements Layer and provides facilities for reading and
// seeking.
type layerReader struct {
	fileReader

	digest digest.Digest
}

var _ distribution.Layer = &layerReader{}

func (lr *layerReader) Digest() digest.Digest {
	return lr.digest
}

func (lr *layerReader) Length() int64 {
	return lr.size
}

func (lr *layerReader) CreatedAt() time.Time {
	return lr.modtime
}

// Close the layer. Should be called when the resource is no longer needed.
func (lr *layerReader) Close() error {
	return lr.closeWithErr(distribution.ErrLayerClosed)
}

func (lr *layerReader) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Docker-Content-Digest", lr.digest.String())

	if url, err := lr.fileReader.driver.URLFor(lr.path, map[string]interface{}{"method": r.Method}); err == nil {
		http.Redirect(w, r, url, http.StatusTemporaryRedirect)
	}
	http.ServeContent(w, r, lr.digest.String(), lr.CreatedAt(), lr)
}
<|endoftext|>


<commit_before>package main

import (
    "flag"
    "fmt"
    "encoding/json"
    "log"
    "net/http"
    "github.com/gorilla/mux"
    "github.com/boltdb/bolt"
)

type KeyValue struct{
    Bucket string `json:"bucket,omitempty"`
    Key string `json:"key,omitempty"`
    Value string `json:"value,omitempty"`
}

var db *bolt.DB
var DB_PATH = "/home/stuart/openRap/my.db"

func main(){
    httpPort := flag.String("port", "9001", "The port for http to run")
    flag.Parse()
    db = DbInit()
    router := mux.NewRouter()
    registerRoutes(router)
    log.Fatal(http.ListenAndServe(":"+*httpPort,router))
}

func DbInit() *bolt.DB {
    db,err := bolt.Open(DB_PATH, 0600,nil)
    if err != nil {
        log.Fatal(err)
    }
    return db
    //defer db.Close()

}

func registerRoutes(r *mux.Router){
    r.HandleFunc("/bucket",AddBucket).Methods("POST")
    r.HandleFunc("/entry",AddKeyValue).Methods("POST")
    r.HandleFunc("/{bucket}/{key}",GetKeyValue).Methods("GET")
}

// Unused, to be used in future
func AddBucket(w http.ResponseWriter, r *http.Request){
    err := db.Update(func(tx *bolt.Tx) error {
        _,err := tx.CreateBucketIfNotExists([]byte("MyBucket"))
        if err != nil {
            return err
        }
        return nil
    })
    if err != nil {
        log.Fatal(err)
        http.Error(w,"Error in creating Bucket",http.StatusInternalServerError)
    }
    w.Header().Set("Content-Type", "text/plain")
    w.Write([]byte("Bucket Created Successfully!!!"))
}
func AddKeyValue(w http.ResponseWriter, r *http.Request){
    var keyValue KeyValue
    json.NewDecoder(r.Body).Decode(&keyValue)
    fmt.Println(keyValue)
    err := db.Update(func(tx *bolt.Tx) error {
        b,err := tx.CreateBucketIfNotExists([]byte(keyValue.Bucket))
        if err != nil {
            //log.Fatal(err)
            return err
        }
        err = b.Put([]byte(keyValue.Key), []byte(keyValue.Value))
        return err
    })
    if err != nil {
        log.Fatal(err)
    }
    w.Header().Set("Content-Type", "text/plain")
    w.Write([]byte("Value Created Successfully!!!"))

}
func GetKeyValue(w http.ResponseWriter, r *http.Request){
    vars := mux.Vars(r)
    db.View(func(tx *bolt.Tx) error {
        bucket := tx.Bucket([]byte(vars["bucket"]))
        if bucket == nil {
            w.Header().Set("Content-Type", "text/plain")
            w.Write([]byte("No buckets found"))
            return nil
        }
        val := bucket.Get([]byte(vars["key"]))
        fmt.Println(val)
        fmt.Println(string(val))
        w.Header().Set("Content-Type", "text/plain")
        w.Write([]byte(string(val)))
        return nil
    })
}

<commit_msg>code refactor<commit_after>package main

import (
    "flag"
    "fmt"
    "encoding/json"
    "log"
    "net/http"
    "github.com/gorilla/mux"
    "github.com/boltdb/bolt"
)

type KeyValue struct{
    Bucket string `json:"bucket,omitempty"`
    Key string `json:"key,omitempty"`
    Value string `json:"value,omitempty"`
}

var db *bolt.DB
var DB_PATH = "/home/stuart/openRap/my.db"

func main(){
    httpPort := flag.String("port", "9001", "The port for http to run")
    flag.Parse()
    db = DbInit()
    router := mux.NewRouter()
    registerRoutes(router)
    log.Fatal(http.ListenAndServe(":"+*httpPort,router))
}

func DbInit() *bolt.DB {
    db,err := bolt.Open(DB_PATH, 0600,nil)
    if err != nil {
        log.Fatal(err)
    }
    return db
    //defer db.Close()

}

func registerRoutes(r *mux.Router){
    r.HandleFunc("/bucket",AddBucket).Methods("POST")
    r.HandleFunc("/entry",AddKeyValue).Methods("POST")
    r.HandleFunc("/{bucket}/{key}",GetKeyValue).Methods("GET")
}

// Unused, to be used in future
func AddBucket(w http.ResponseWriter, r *http.Request){
    err := db.Update(func(tx *bolt.Tx) error {
        _,err := tx.CreateBucketIfNotExists([]byte("MyBucket"))
        if err != nil {
            return err
        }
        return nil
    })
    if err != nil {
        log.Fatal(err)
        http.Error(w,"Error in creating Bucket",http.StatusInternalServerError)
    }
    w.Header().Set("Content-Type", "text/plain")
    w.Write([]byte("Bucket Created Successfully!!!"))
}
func AddKeyValue(w http.ResponseWriter, r *http.Request){
    var keyValue KeyValue
    json.NewDecoder(r.Body).Decode(&keyValue)
    fmt.Println(keyValue)
    err := db.Update(func(tx *bolt.Tx) error {
        b,err := tx.CreateBucketIfNotExists([]byte(keyValue.Bucket))
        if err != nil {
            //log.Fatal(err)
            return err
        }
        err = b.Put([]byte(keyValue.Key), []byte(keyValue.Value))
        return err
    })
    if err != nil {
        log.Fatal(err)
    }
    w.Header().Set("Content-Type", "text/plain")
    w.Write([]byte("Value Created Successfully!!!"))

}
func GetKeyValue(w http.ResponseWriter, r *http.Request){
    vars := mux.Vars(r)
    db.View(func(tx *bolt.Tx) error {
        bucket := tx.Bucket([]byte(vars["bucket"]))
        w.Header().Set("Content-Type", "text/plain")
        if bucket != nil {
            val := bucket.Get([]byte(vars["key"]))
            fmt.Println(val)
            fmt.Println(string(val))
            w.Write([]byte(string(val)))
            return nil
        }
        w.Write([]byte("No buckets found"))
        return nil
    })
}

<|endoftext|>


<commit_before>package main

import "os/exec"

var DefaultPaths = []string{
	"/var/log/*.log",
	"/var/log/*/*.log",
}

func openBrowser(url string) error {
	return exec.Command("xdg-open", url).Run()
}
<commit_msg>Don't open xdg-open or x-www-browser if not present on system<commit_after>package main

import "os/exec"

var DefaultPaths = []string{
	"/var/log/*.log",
	"/var/log/*/*.log",
}

func openBrowser(url string) error {
	open, err := exec.LookPath("xdg-open")
	if err != nil {
		open, err = exec.LookPath("x-www-browser")
		if err != nil {
			return nil
		}
	}

	return exec.Command(open, url).Run()
}
<|endoftext|>


<commit_before>package bintray

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/enr/go-commons/lang"
	"io"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strings"
)

// A Client manages communication with the Bintray API.
type BintrayClient struct {
	// HTTP client used to communicate with the API.
	client *http.Client

	subject string
	apikey  string

	// Base URL for API requests. Defaults to the public Bintray API, but can be
	// set to a domain endpoint to use with Bintray Enterprise. BaseURL should
	// always be specified with a trailing slash.
	BaseURL *url.URL

	// User agent used when communicating with the Bintray API.
	UserAgent string

	downloadsHost string
}

// NewClient returns a new BintrayClient API client. If a nil httpClient is
// provided, http.DefaultClient will be used.
func NewClient(httpClient *http.Client, subject, apikey string) *BintrayClient {
	if httpClient == nil {
		httpClient = http.DefaultClient
	}
	baseURL, _ := url.Parse(defaultBaseURL)
	c := &BintrayClient{client: httpClient, BaseURL: baseURL, UserAgent: userAgent, subject: subject, apikey: apikey}
	return c
}

// Find if package is present
// GET /packages/:subject/:repo/:package
func (c *BintrayClient) PackageExists(subject, repository, pkg string) (bool, error) {
	if subject == "" || repository == "" || pkg == "" {
		return false, errors.New("PackageExists: subject, repository and package name shouldn't be empty!")
	}
	url := "/packages/" + subject + "/" + repository + "/" + pkg
	req, err := c.newRequestWithReader("GET", url, nil, 0)
	if err != nil {
		return false, err
	}
	resp, err := c.execute(req)
	if err != nil {
		return false, err
	}
	return (resp.StatusCode == 200), nil
}

func (c *BintrayClient) GetVersions(subject, repository, pkg string) ([]string, error) {
	if subject == "" || repository == "" || pkg == "" {
		return nil, errors.New("GetVersions: subject, repository and package name shouldn't be empty!")
	}
	url := "/packages/" + subject + "/" + repository + "/" + pkg
	req, err := c.newRequestWithReader("GET", url, nil, 0)
	if err != nil {
		return nil, err
	}
	resp, err := c.execute(req)

	if err != nil {
		fmt.Printf("Error calling %s - %v", url, err)
		return nil, err
	}
	body, err := resp.BodyAsBytes()
	if err != nil {
		return nil, err
	}
	versions, err := lang.ExtractJsonFieldValue(body, "versions")
	if err != nil {
		return nil, err
	}
	return lang.JsonArrayToStringSlice(versions, "versions")
}

//POST /packages/:subject/:repo/:package/versions
func (c *BintrayClient) CreateVersionWithMeta(subject, repository, pkg, version string, reqJson map[string]interface{}) error {
	return c.executeCreateVersion(subject, repository, pkg, version, reqJson)
}

//POST /packages/:subject/:repo/:package/versions
func (c *BintrayClient) CreateVersion(subject, repository, pkg, version string) error {
	reqJson := map[string]interface{}{"name": version}
	return c.executeCreateVersion(subject, repository, pkg, version, reqJson)
}

func (c *BintrayClient) executeCreateVersion(subject, repository, pkg, version string, reqJson map[string]interface{}) error {
	if subject == "" || repository == "" || pkg == "" || version == "" {
		return errors.New("create version: subject, repository, package name and version shouldn't be empty!")
	}
	if _, vnameExists := reqJson["name"]; !vnameExists {
		return errors.New("create version: metadata must contain the name key")
	}
	requestData, err := json.Marshal(reqJson)
	if err != nil {
		return err
	}
	url := "/packages/" + subject + "/" + repository + "/" + pkg + "/versions"
	req, err := c.newRequestWithBody("POST", url, string(requestData))
	if err != nil {
		return err
	}
	_, err = c.execute(req)
	return err
}

//PUT /content/:subject/:repo/:package/:version/:path
func (c *BintrayClient) UploadFile(subject, repository, pkg, version, projectGroupId, projectName, filePath string, mavenRepo bool) error {
	fullPath, _ := filepath.Abs(filePath)
	var entityPath string
	var uploadUrl string
	fileName := filepath.Base(fullPath)
	if mavenRepo {
		entityPath = strings.Replace(projectGroupId, ".", "/", -1) + "/" + projectName + "/" + version + "/" + fileName
		uploadUrl = "content/" + subject + "/" + repository + "/" + pkg + "/" + version + "/" + entityPath
	} else {
		entityPath = version + "/" + fileName
		uploadUrl = "content/" + subject + "/" + repository + "/" + pkg + "/" + entityPath
	}
	file, err := os.Open(fullPath)
	if err != nil {
		return err
	}
	defer file.Close()
	fi, err := file.Stat()
	if err != nil {
		return err
	}

	req, err := c.newRequestWithReader("PUT", uploadUrl, file, fi.Size())
	if err != nil {
		return err
	}
	_, err = c.execute(req)
	/*
	if serr, ok := err.(httpError); ok {
		if serr.statusCode == 409 {
			//conflict. skip
			//continue but dont publish.
			//TODO - provide an option to replace existing artifact
			//TODO - ?check exists before attempting upload?
		} else {

		}
	} else if err != nil {

	}
	*/
	return err
}

// cambiare a return boolean, error
// true se body.files > 0
func (c *BintrayClient) Publish(subject, repository, pkg, version string) error {
	if subject == "" || repository == "" || pkg == "" || version == "" {
		return errors.New("Publish: subject, repository, package name and version shouldn't be empty!")
	}
	url := "/content/" + subject + "/" + repository + "/" + pkg + "/" + version + "/publish"
	req, err := c.newRequestWithReader("POST", url, nil, 0)
	if err != nil {
		return err
	}
	resp, err := c.execute(req)
	var objmap map[string]*json.RawMessage
	jsonBlob, _ := resp.BodyAsBytes()
	err = json.Unmarshal(jsonBlob, &objmap)
	if err != nil {
		fmt.Println("error:", err)
	}
	filesNum := 0
	if _, ok := objmap["files"]; ok {
		//var filesNum int
		err = json.Unmarshal(*objmap["files"], &filesNum)
		//fmt.Printf("files filesNum=%d\n", filesNum)
	}
	// return (filesNum > 0), err
	return err
}

// execute sends an API request and returns the API response and error if any.
func (c *BintrayClient) execute(req *http.Request) (*BintrayResponse, error) {
	resp, err := c.client.Do(req)
	if err != nil {
		return nil, err
	}
	return newResponse(resp), err
}

// newRequestWithBody creates an API request using the given string as the body.
// A relative URL can be provided in urlStr, in which case it is resolved relative to the BaseURL of the Client.
// Relative URLs should always be specified without a preceding slash.
func (c *BintrayClient) newRequestWithBody(method, urlStr, body string) (*http.Request, error) {
	requestData := []byte(body)
	requestLength := int64(len(requestData))
	requestReader := bytes.NewReader(requestData)

	return c.newRequestWithReader(method, urlStr, requestReader, requestLength)
}

// newRequestWithReader creates an API request.
// A relative URL can be provided in urlStr, in which case it is resolved relative to the BaseURL of the Client.
// Relative URLs should always be specified without a preceding slash.
func (c *BintrayClient) newRequestWithReader(method, urlStr string, requestReader io.Reader, requestLength int64) (*http.Request, error) {
	rel, err := url.Parse(urlStr)
	if err != nil {
		return nil, err
	}
	u := c.BaseURL.ResolveReference(rel)
	req, err := http.NewRequest(method, u.String(), requestReader)
	if err != nil {
		return nil, err
	}
	if requestLength > 0 {
		req.ContentLength = int64(requestLength)
	}
	req.Header.Add("User-Agent", c.UserAgent)
	if c.subject != "" {
		req.SetBasicAuth(c.subject, c.apikey)
	}
	return req, nil
}
<commit_msg>fixed compile error when calling lang functions<commit_after>package bintray

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/enr/go-commons/lang"
	"io"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strings"
)

// A Client manages communication with the Bintray API.
type BintrayClient struct {
	// HTTP client used to communicate with the API.
	client *http.Client

	subject string
	apikey  string

	// Base URL for API requests. Defaults to the public Bintray API, but can be
	// set to a domain endpoint to use with Bintray Enterprise. BaseURL should
	// always be specified with a trailing slash.
	BaseURL *url.URL

	// User agent used when communicating with the Bintray API.
	UserAgent string

	downloadsHost string
}

// NewClient returns a new BintrayClient API client. If a nil httpClient is
// provided, http.DefaultClient will be used.
func NewClient(httpClient *http.Client, subject, apikey string) *BintrayClient {
	if httpClient == nil {
		httpClient = http.DefaultClient
	}
	baseURL, _ := url.Parse(defaultBaseURL)
	c := &BintrayClient{client: httpClient, BaseURL: baseURL, UserAgent: userAgent, subject: subject, apikey: apikey}
	return c
}

// Find if package is present
// GET /packages/:subject/:repo/:package
func (c *BintrayClient) PackageExists(subject, repository, pkg string) (bool, error) {
	if subject == "" || repository == "" || pkg == "" {
		return false, errors.New("PackageExists: subject, repository and package name shouldn't be empty!")
	}
	url := "/packages/" + subject + "/" + repository + "/" + pkg
	req, err := c.newRequestWithReader("GET", url, nil, 0)
	if err != nil {
		return false, err
	}
	resp, err := c.execute(req)
	if err != nil {
		return false, err
	}
	return (resp.StatusCode == 200), nil
}

func (c *BintrayClient) GetVersions(subject, repository, pkg string) ([]string, error) {
	if subject == "" || repository == "" || pkg == "" {
		return nil, errors.New("GetVersions: subject, repository and package name shouldn't be empty!")
	}
	url := "/packages/" + subject + "/" + repository + "/" + pkg
	req, err := c.newRequestWithReader("GET", url, nil, 0)
	if err != nil {
		return nil, err
	}
	resp, err := c.execute(req)

	if err != nil {
		fmt.Printf("Error calling %s - %v", url, err)
		return nil, err
	}
	body, err := resp.BodyAsBytes()
	if err != nil {
		return nil, err
	}
	versions, err := lang.ExtractJSONFieldValue(body, "versions")
	if err != nil {
		return nil, err
	}
	return lang.JSONArrayToStringSlice(versions, "versions")
}

//POST /packages/:subject/:repo/:package/versions
func (c *BintrayClient) CreateVersionWithMeta(subject, repository, pkg, version string, reqJson map[string]interface{}) error {
	return c.executeCreateVersion(subject, repository, pkg, version, reqJson)
}

//POST /packages/:subject/:repo/:package/versions
func (c *BintrayClient) CreateVersion(subject, repository, pkg, version string) error {
	reqJson := map[string]interface{}{"name": version}
	return c.executeCreateVersion(subject, repository, pkg, version, reqJson)
}

func (c *BintrayClient) executeCreateVersion(subject, repository, pkg, version string, reqJson map[string]interface{}) error {
	if subject == "" || repository == "" || pkg == "" || version == "" {
		return errors.New("create version: subject, repository, package name and version shouldn't be empty!")
	}
	if _, vnameExists := reqJson["name"]; !vnameExists {
		return errors.New("create version: metadata must contain the name key")
	}
	requestData, err := json.Marshal(reqJson)
	if err != nil {
		return err
	}
	url := "/packages/" + subject + "/" + repository + "/" + pkg + "/versions"
	req, err := c.newRequestWithBody("POST", url, string(requestData))
	if err != nil {
		return err
	}
	_, err = c.execute(req)
	return err
}

//PUT /content/:subject/:repo/:package/:version/:path
func (c *BintrayClient) UploadFile(subject, repository, pkg, version, projectGroupId, projectName, filePath string, mavenRepo bool) error {
	fullPath, _ := filepath.Abs(filePath)
	var entityPath string
	var uploadUrl string
	fileName := filepath.Base(fullPath)
	if mavenRepo {
		entityPath = strings.Replace(projectGroupId, ".", "/", -1) + "/" + projectName + "/" + version + "/" + fileName
		uploadUrl = "content/" + subject + "/" + repository + "/" + pkg + "/" + version + "/" + entityPath
	} else {
		entityPath = version + "/" + fileName
		uploadUrl = "content/" + subject + "/" + repository + "/" + pkg + "/" + entityPath
	}
	file, err := os.Open(fullPath)
	if err != nil {
		return err
	}
	defer file.Close()
	fi, err := file.Stat()
	if err != nil {
		return err
	}

	req, err := c.newRequestWithReader("PUT", uploadUrl, file, fi.Size())
	if err != nil {
		return err
	}
	_, err = c.execute(req)
	/*
		if serr, ok := err.(httpError); ok {
			if serr.statusCode == 409 {
				//conflict. skip
				//continue but dont publish.
				//TODO - provide an option to replace existing artifact
				//TODO - ?check exists before attempting upload?
			} else {

			}
		} else if err != nil {

		}
	*/
	return err
}

// cambiare a return boolean, error
// true se body.files > 0
func (c *BintrayClient) Publish(subject, repository, pkg, version string) error {
	if subject == "" || repository == "" || pkg == "" || version == "" {
		return errors.New("Publish: subject, repository, package name and version shouldn't be empty!")
	}
	url := "/content/" + subject + "/" + repository + "/" + pkg + "/" + version + "/publish"
	req, err := c.newRequestWithReader("POST", url, nil, 0)
	if err != nil {
		return err
	}
	resp, err := c.execute(req)
	var objmap map[string]*json.RawMessage
	jsonBlob, _ := resp.BodyAsBytes()
	err = json.Unmarshal(jsonBlob, &objmap)
	if err != nil {
		fmt.Println("error:", err)
	}
	filesNum := 0
	if _, ok := objmap["files"]; ok {
		//var filesNum int
		err = json.Unmarshal(*objmap["files"], &filesNum)
		//fmt.Printf("files filesNum=%d\n", filesNum)
	}
	// return (filesNum > 0), err
	return err
}

// execute sends an API request and returns the API response and error if any.
func (c *BintrayClient) execute(req *http.Request) (*BintrayResponse, error) {
	resp, err := c.client.Do(req)
	if err != nil {
		return nil, err
	}
	return newResponse(resp), err
}

// newRequestWithBody creates an API request using the given string as the body.
// A relative URL can be provided in urlStr, in which case it is resolved relative to the BaseURL of the Client.
// Relative URLs should always be specified without a preceding slash.
func (c *BintrayClient) newRequestWithBody(method, urlStr, body string) (*http.Request, error) {
	requestData := []byte(body)
	requestLength := int64(len(requestData))
	requestReader := bytes.NewReader(requestData)

	return c.newRequestWithReader(method, urlStr, requestReader, requestLength)
}

// newRequestWithReader creates an API request.
// A relative URL can be provided in urlStr, in which case it is resolved relative to the BaseURL of the Client.
// Relative URLs should always be specified without a preceding slash.
func (c *BintrayClient) newRequestWithReader(method, urlStr string, requestReader io.Reader, requestLength int64) (*http.Request, error) {
	rel, err := url.Parse(urlStr)
	if err != nil {
		return nil, err
	}
	u := c.BaseURL.ResolveReference(rel)
	req, err := http.NewRequest(method, u.String(), requestReader)
	if err != nil {
		return nil, err
	}
	if requestLength > 0 {
		req.ContentLength = int64(requestLength)
	}
	req.Header.Add("User-Agent", c.UserAgent)
	if c.subject != "" {
		req.SetBasicAuth(c.subject, c.apikey)
	}
	return req, nil
}
<|endoftext|>


<commit_before>// Copyright 2015 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package blob

import (
	"fmt"

	"github.com/jacobsa/gcloud/gcs"
)

// Return a blob store that stores blobs in the supplied GCS bucket. GCS object
// names look like:
//
//     <prefix><score>
//
// where <score> is the result of calling Score.Hex.
//
// The blob store trusts that it has full ownership of this portion of the
// bucket's key space -- if a score name exists, then it points to the correct
// data.
//
// The returned store does not support Flush or Contains; these methods must
// not be called.
func NewGCSStore(
	bucket gcs.Bucket,
	prefix string) (store Store)

type gcsStore struct {
	bucket    gcs.Bucket
	keyPrefix string
}

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

func (s *kvBasedBlobStore) makeKey(score Score) (key string) {
	key = s.keyPrefix + score.Hex()
	return
}

////////////////////////////////////////////////////////////////////////
// Public interface
////////////////////////////////////////////////////////////////////////

func (s *kvBasedBlobStore) Store(blob []byte) (score Score, err error) {
	// Will this blob ever fit?
	if len(blob) > s.maxBytesBuffered {
		err = fmt.Errorf(
			"%v-byte blob is larger than buffer size of %v",
			len(blob),
			s.maxBytesBuffered)

		return
	}

	// Compute a score and a key for use under the lock below.
	score = ComputeScore(blob)
	key := s.makeKey(score)

	s.mu.Lock()
	defer s.mu.Unlock()

	// Wait until there is room for this request.
	for !s.hasRoom(len(blob)) {
		s.inFlightChanged.Wait()
	}

	// Have we already decided on a final error?
	if s.writeErr != nil {
		err = fmt.Errorf("Error from previous write: %v", s.writeErr)
		return
	}

	// If we already have a request for this score in flight, we can avoid
	// spawning another one. (If the existing one fails, the user will see an
	// error from Flush.)
	if _, ok := s.inFlight[score]; ok {
		return
	}

	// If the KV store already contains the key, we need not do anything further.
	if s.kvStore.Contains(key) {
		return
	}

	// Mark this blob as in flight.
	s.inFlight[score] = len(blob)
	s.bytesBuffered += len(blob)
	s.inFlightChanged.Broadcast()

	// Spawn a goroutine that will make the blob durable in the background.
	go s.makeDurable(score, key, blob)

	return
}

func (s *kvBasedBlobStore) Flush() (err error) {
	s.mu.Lock()
	defer s.mu.Unlock()

	// Wait until there are no requests in flight.
	for len(s.inFlight) != 0 {
		s.inFlightChanged.Wait()
	}

	err = s.writeErr
	return
}

func (s *kvBasedBlobStore) Contains(score Score) (b bool) {
	s.mu.Lock()
	defer s.mu.Unlock()

	// Do we have an in-flight request?
	if _, ok := s.inFlight[score]; ok {
		b = true
		return
	}

	// Does the key exist in the KV store?
	key := s.makeKey(score)
	if s.kvStore.Contains(key) {
		b = true
		return
	}

	return
}

func (s *kvBasedBlobStore) Load(score Score) (blob []byte, err error) {
	// Choose the appropriate key.
	key := s.makeKey(score)

	// Call the key/value store.
	if blob, err = s.kvStore.Get(key); err != nil {
		err = fmt.Errorf("Get: %v", err)
		return
	}

	return
}
<commit_msg>gcsStore.Store<commit_after>// Copyright 2015 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package blob

import (
	"bytes"
	"fmt"

	"golang.org/x/net/context"

	"github.com/jacobsa/gcloud/gcs"
)

// Return a blob store that stores blobs in the supplied GCS bucket. GCS object
// names look like:
//
//     <prefix><score>
//
// where <score> is the result of calling Score.Hex.
//
// The blob store trusts that it has full ownership of this portion of the
// bucket's namespace -- if a score name exists, then it points to the correct
// data.
//
// The returned store does not support Flush or Contains; these methods must
// not be called.
func NewGCSStore(
	bucket gcs.Bucket,
	prefix string) (store Store)

type gcsStore struct {
	bucket     gcs.Bucket
	namePrefix string
}

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

func (s *gcsStore) makeName(score Score) (name string) {
	name = s.namePrefix + score.Hex()
	return
}

////////////////////////////////////////////////////////////////////////
// Public interface
////////////////////////////////////////////////////////////////////////

func (s *gcsStore) Store(blob []byte) (score Score, err error) {
	// Compute a score and an object name.
	score = ComputeScore(blob)
	name := s.makeName(score)

	// Create the object.
	//
	// TODO(jacobsa): Set MD5 and CRC32C. See issue #18.
	req := &gcs.CreateObjectRequest{
		Name:     name,
		Contents: bytes.NewReader(blob),
	}

	_, err = s.bucket.CreateObject(context.Background(), req)
	if err != nil {
		err = fmt.Errorf("CreateObject: %v", err)
	}

	return
}

func (s *kvBasedBlobStore) Flush() (err error) {
	s.mu.Lock()
	defer s.mu.Unlock()

	// Wait until there are no requests in flight.
	for len(s.inFlight) != 0 {
		s.inFlightChanged.Wait()
	}

	err = s.writeErr
	return
}

func (s *kvBasedBlobStore) Contains(score Score) (b bool) {
	s.mu.Lock()
	defer s.mu.Unlock()

	// Do we have an in-flight request?
	if _, ok := s.inFlight[score]; ok {
		b = true
		return
	}

	// Does the key exist in the KV store?
	key := s.makeKey(score)
	if s.kvStore.Contains(key) {
		b = true
		return
	}

	return
}

func (s *kvBasedBlobStore) Load(score Score) (blob []byte, err error) {
	// Choose the appropriate key.
	key := s.makeKey(score)

	// Call the key/value store.
	if blob, err = s.kvStore.Get(key); err != nil {
		err = fmt.Errorf("Get: %v", err)
		return
	}

	return
}
<|endoftext|>


<commit_before>// Copyright 2015 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package discovery

import (
	"crypto/tls"
	"fmt"
	"io"
	"net"
	"net/http"
	"net/url"
	"strconv"
	"time"
)

type InsecureOption int

const (
	defaultDialTimeout = 20 * time.Second
)

const (
	InsecureNone InsecureOption = 0

	InsecureTLS InsecureOption = 1 << iota
	InsecureHTTP
)

var (
	// Client is the default http.Client used for discovery requests.
	Client            *http.Client
	ClientInsecureTLS *http.Client

	// httpDo is the internal object used by discovery to retrieve URLs; it is
	// defined here so it can be overridden for testing
	httpDo            httpDoer
	httpDoInsecureTLS httpDoer
)

// httpDoer is an interface used to wrap http.Client for real requests and
// allow easy mocking in local tests.
type httpDoer interface {
	Do(req *http.Request) (resp *http.Response, err error)
}

func init() {
	t := &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		Dial: func(n, a string) (net.Conn, error) {
			return net.DialTimeout(n, a, defaultDialTimeout)
		},
	}
	Client = &http.Client{
		Transport: t,
	}
	httpDo = Client

	// copy for InsecureTLS
	tInsecureTLS := *t
	tInsecureTLS.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
	ClientInsecureTLS = &http.Client{
		Transport: &tInsecureTLS,
	}
	httpDoInsecureTLS = ClientInsecureTLS
}

func httpsOrHTTP(name string, hostHeaders map[string]http.Header, insecure InsecureOption, port uint) (urlStr string, body io.ReadCloser, err error) {
	fetch := func(scheme string, port uint) (urlStr string, res *http.Response, err error) {
		u, err := url.Parse(scheme + "://" + name)
		if err != nil {
			return "", nil, err
		}
		u.RawQuery = "ac-discovery=1"
		if port != 0 {
			u.Host += ":" + strconv.FormatUint(uint64(port), 10)
		}
		urlStr = u.String()
		req, err := http.NewRequest("GET", urlStr, nil)
		if err != nil {
			return "", nil, err
		}
		if hostHeader, ok := hostHeaders[u.Host]; ok {
			req.Header = hostHeader
		}
		if insecure&InsecureTLS != 0 {
			res, err = httpDoInsecureTLS.Do(req)
			return
		}
		res, err = httpDo.Do(req)
		return
	}
	closeBody := func(res *http.Response) {
		if res != nil {
			res.Body.Close()
		}
	}
	urlStr, res, err := fetch("https", port)
	if err != nil || res.StatusCode != http.StatusOK {
		if insecure&InsecureHTTP != 0 {
			closeBody(res)
			urlStr, res, err = fetch("http", port)
		}
	}

	if res != nil && res.StatusCode != http.StatusOK {
		err = fmt.Errorf("expected a 200 OK got %d", res.StatusCode)
	}

	if err != nil {
		closeBody(res)
		return "", nil, err
	}
	return urlStr, res.Body, nil
}
<commit_msg>Discovery: fix govet failure<commit_after>// Copyright 2015 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package discovery

import (
	"crypto/tls"
	"fmt"
	"io"
	"net"
	"net/http"
	"net/url"
	"strconv"
	"time"
)

type InsecureOption int

const (
	defaultDialTimeout = 20 * time.Second
)

const (
	InsecureNone InsecureOption = 0

	InsecureTLS InsecureOption = 1 << iota
	InsecureHTTP
)

var (
	// Client is the default http.Client used for discovery requests.
	Client            *http.Client
	ClientInsecureTLS *http.Client

	// httpDo is the internal object used by discovery to retrieve URLs; it is
	// defined here so it can be overridden for testing
	httpDo            httpDoer
	httpDoInsecureTLS httpDoer
)

// httpDoer is an interface used to wrap http.Client for real requests and
// allow easy mocking in local tests.
type httpDoer interface {
	Do(req *http.Request) (resp *http.Response, err error)
}

func init() {
	t := &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		Dial: func(n, a string) (net.Conn, error) {
			return net.DialTimeout(n, a, defaultDialTimeout)
		},
	}
	Client = &http.Client{
		Transport: t,
	}
	httpDo = Client

	// copy for InsecureTLS
	tInsecureTLS := http.Transport{
		Proxy: http.ProxyFromEnvironment,
		Dial: func(n, a string) (net.Conn, error) {
			return net.DialTimeout(n, a, defaultDialTimeout)
		},
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	ClientInsecureTLS = &http.Client{
		Transport: &tInsecureTLS,
	}
	httpDoInsecureTLS = ClientInsecureTLS
}

func httpsOrHTTP(name string, hostHeaders map[string]http.Header, insecure InsecureOption, port uint) (urlStr string, body io.ReadCloser, err error) {
	fetch := func(scheme string, port uint) (urlStr string, res *http.Response, err error) {
		u, err := url.Parse(scheme + "://" + name)
		if err != nil {
			return "", nil, err
		}
		u.RawQuery = "ac-discovery=1"
		if port != 0 {
			u.Host += ":" + strconv.FormatUint(uint64(port), 10)
		}
		urlStr = u.String()
		req, err := http.NewRequest("GET", urlStr, nil)
		if err != nil {
			return "", nil, err
		}
		if hostHeader, ok := hostHeaders[u.Host]; ok {
			req.Header = hostHeader
		}
		if insecure&InsecureTLS != 0 {
			res, err = httpDoInsecureTLS.Do(req)
			return
		}
		res, err = httpDo.Do(req)
		return
	}
	closeBody := func(res *http.Response) {
		if res != nil {
			res.Body.Close()
		}
	}
	urlStr, res, err := fetch("https", port)
	if err != nil || res.StatusCode != http.StatusOK {
		if insecure&InsecureHTTP != 0 {
			closeBody(res)
			urlStr, res, err = fetch("http", port)
		}
	}

	if res != nil && res.StatusCode != http.StatusOK {
		err = fmt.Errorf("expected a 200 OK got %d", res.StatusCode)
	}

	if err != nil {
		closeBody(res)
		return "", nil, err
	}
	return urlStr, res.Body, nil
}
<|endoftext|>