<commit_before>package falcore

import (
	"bufio"
	"crypto/rand"
	"crypto/tls"
	"errors"
	"fmt"
	"io"
	"net"
	"net/http"
	"os"
	"runtime"
	"strconv"
	"sync"
	"syscall"
	"time"
)

type Server struct {
	Addr             string
	Pipeline         *Pipeline
	listener         net.Listener
	listenerFile     *os.File
	stopAccepting    chan int
	handlerWaitGroup *sync.WaitGroup
	logPrefix        string
	AcceptReady      chan int
	sendfile         bool
	sockOpt          int
	bufferPool       *bufferPool
}

func NewServer(port int, pipeline *Pipeline) *Server {
	s := new(Server)
	s.Addr = fmt.Sprintf(":%v", port)
	s.Pipeline = pipeline
	s.stopAccepting = make(chan int)
	s.AcceptReady = make(chan int, 1)
	s.handlerWaitGroup = new(sync.WaitGroup)
	s.logPrefix = fmt.Sprintf("%d", syscall.Getpid())

	// openbsd/netbsd don't have TCP_NOPUSH so it's likely sendfile will be slower
	// without these socket options, just enable for linux, mac and freebsd.
	// TODO (Graham) windows has TransmitFile zero-copy mechanism, try to use it
	switch runtime.GOOS {
	case "linux":
		s.sendfile = true
		s.sockOpt = 0x3 // syscall.TCP_CORK
	case "freebsd", "darwin":
		s.sendfile = true
		s.sockOpt = 0x4 // syscall.TCP_NOPUSH
	default:
		s.sendfile = false
	}

	// buffer pool for reusing connection bufio.Readers
	s.bufferPool = newBufferPool(100, 8192)

	return s
}

func (srv *Server) FdListen(fd int) error {
	var err error
	srv.listenerFile = os.NewFile(uintptr(fd), "")
	if srv.listener, err = net.FileListener(srv.listenerFile); err != nil {
		return err
	}
	if _, ok := srv.listener.(*net.TCPListener); !ok {
		return errors.New("Broken listener isn't TCP")
	}
	return nil
}

func (srv *Server) socketListen() error {
	var la *net.TCPAddr
	var err error
	if la, err = net.ResolveTCPAddr("tcp", srv.Addr); err != nil {
		return err
	}

	var l *net.TCPListener
	if l, err = net.ListenTCP("tcp", la); err != nil {
		return err
	}
	srv.listener = l
	// setup listener to be non-blocking if we're not on windows.
	// this is required for hot restart to work.
	return srv.setupNonBlockingListener(err, l)
}

func (srv *Server) ListenAndServe() error {
	if srv.Addr == "" {
		srv.Addr = ":http"
	}
	if srv.listener == nil {
		if err := srv.socketListen(); err != nil {
			return err
		}
	}
	return srv.serve()
}

func (srv *Server) SocketFd() int {
	return int(srv.listenerFile.Fd())
}

func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error {
	if srv.Addr == "" {
		srv.Addr = ":https"
	}
	config := &tls.Config{
		Rand:       rand.Reader,
		Time:       time.Now,
		NextProtos: []string{"http/1.1"},
	}

	var err error
	config.Certificates = make([]tls.Certificate, 1)
	config.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile)
	if err != nil {
		return err
	}

	if srv.listener == nil {
		if err := srv.socketListen(); err != nil {
			return err
		}
	}

	srv.listener = tls.NewListener(srv.listener, config)

	return srv.serve()
}

func (srv *Server) StopAccepting() {
	close(srv.stopAccepting)
}

func (srv *Server) Port() int {
	if l := srv.listener; l != nil {
		a := l.Addr()
		if _, p, e := net.SplitHostPort(a.String()); e == nil && p != "" {
			server_port, _ := strconv.Atoi(p)
			return server_port
		}
	}
	return 0
}

func (srv *Server) serve() (e error) {
	var accept = true
	srv.AcceptReady <- 1
	for accept {
		var c net.Conn
		if l, ok := srv.listener.(*net.TCPListener); ok {
			l.SetDeadline(time.Now().Add(3e9))
		}
		c, e = srv.listener.Accept()
		if e != nil {
			if ope, ok := e.(*net.OpError); ok {
				if !(ope.Timeout() && ope.Temporary()) {
					Error("%s SERVER Accept Error: %v", srv.serverLogPrefix(), ope)
				}
			} else {
				Error("%s SERVER Accept Error: %v", srv.serverLogPrefix(), e)
			}
		} else {
			//Trace("Handling!")
			srv.handlerWaitGroup.Add(1)
			go srv.handler(c)
		}
		select {
		case <-srv.stopAccepting:
			accept = false
		default:
		}
	}
	Trace("Stopped accepting, waiting for handlers")
	// wait for handlers
	srv.handlerWaitGroup.Wait()
	return nil
}

func (srv *Server) sentinel(c net.Conn, connClosed chan int) {
	select {
	case <-srv.stopAccepting:
		c.SetReadDeadline(time.Now().Add(3 * time.Second))
	case <-connClosed:
	}
}

func (srv *Server) handler(c net.Conn) {
	startTime := time.Now()
	bpe := srv.bufferPool.take(c)
	defer srv.bufferPool.give(bpe)
	var closeSentinelChan = make(chan int)
	go srv.sentinel(c, closeSentinelChan)
	defer srv.connectionFinished(c, closeSentinelChan)
	var err error
	var req *http.Request
	// no keepalive (for now)
	reqCount := 0
	keepAlive := true
	for err == nil && keepAlive {
		if req, err = http.ReadRequest(bpe.br); err == nil {
			if req.Header.Get("Connection") != "Keep-Alive" {
				keepAlive = false
			}
			request := newRequest(req, c, startTime)
			reqCount++
			var res *http.Response

			pssInit := new(PipelineStageStat)
			pssInit.Name = "server.Init"
			pssInit.StartTime = startTime
			pssInit.EndTime = time.Now()
			request.appendPipelineStage(pssInit)
			// execute the pipeline
			if res = srv.Pipeline.execute(request); res == nil {
				res = SimpleResponse(req, 404, nil, "Not Found")
			}
			// cleanup
			request.startPipelineStage("server.ResponseWrite")
			req.Body.Close()

			// shutting down?
			select {
			case <-srv.stopAccepting:
				keepAlive = false
				res.Close = true
			default:
			}
			// The res.Write omits Content-length on 0 length bodies, and by spec,
			// it SHOULD. While this is not MUST, it's kinda broken.  See sec 4.4
			// of rfc2616 and a 200 with a zero length does not satisfy any of the
			// 5 conditions if Connection: keep-alive is set :(
			// I'm forcing chunked which seems to work because I couldn't get the
			// content length to write if it was 0.
			// Specifically, the android http client waits forever if there's no
			// content-length instead of assuming zero at the end of headers. der.
			if res.ContentLength == 0 && len(res.TransferEncoding) == 0 && !((res.StatusCode-100 < 100) || res.StatusCode == 204 || res.StatusCode == 304) {
				res.TransferEncoding = []string{"identity"}
			}
			if res.ContentLength < 0 {
				res.TransferEncoding = []string{"chunked"}
			}

			// write response
			if srv.sendfile {
				res.Write(c)
				srv.cycleNonBlock(c)
			} else {
				wbuf := bufio.NewWriter(c)
				res.Write(wbuf)
				wbuf.Flush()
			}
			if res.Body != nil {
				res.Body.Close()
			}
			request.finishPipelineStage()
			request.finishRequest()
			srv.requestFinished(request)

			if res.Close {
				keepAlive = false
			}

			// Reset the startTime
			// this isn't great since there may be lag between requests; but it's the best we've got
			startTime = time.Now()
		} else {
			// EOF is socket closed
			if nerr, ok := err.(net.Error); err != io.EOF && !(ok && nerr.Timeout()) {
				Error("%s %v ERROR reading request: <%T %v>", srv.serverLogPrefix(), c.RemoteAddr(), err, err)
			}
		}
	}
	//Debug("%s Processed %v requests on connection %v", srv.serverLogPrefix(), reqCount, c.RemoteAddr())
}

func (srv *Server) serverLogPrefix() string {
	return srv.logPrefix
}

func (srv *Server) requestFinished(request *Request) {
	if srv.Pipeline.RequestDoneCallback != nil {
		// Don't block the connecion for this
		go srv.Pipeline.RequestDoneCallback.FilterRequest(request)
	}
}

func (srv *Server) connectionFinished(c net.Conn, closeChan chan int) {
	c.Close()
	close(closeChan)
	srv.handlerWaitGroup.Done()
}
<commit_msg>fixing keep-alive for 1.0 clients, i'm looking at you apache bench<commit_after>package falcore

import (
	"bufio"
	"crypto/rand"
	"crypto/tls"
	"errors"
	"fmt"
	"io"
	"net"
	"net/http"
	"os"
	"runtime"
	"strconv"
	"sync"
	"syscall"
	"time"
)

type Server struct {
	Addr             string
	Pipeline         *Pipeline
	listener         net.Listener
	listenerFile     *os.File
	stopAccepting    chan int
	handlerWaitGroup *sync.WaitGroup
	logPrefix        string
	AcceptReady      chan int
	sendfile         bool
	sockOpt          int
	bufferPool       *bufferPool
}

func NewServer(port int, pipeline *Pipeline) *Server {
	s := new(Server)
	s.Addr = fmt.Sprintf(":%v", port)
	s.Pipeline = pipeline
	s.stopAccepting = make(chan int)
	s.AcceptReady = make(chan int, 1)
	s.handlerWaitGroup = new(sync.WaitGroup)
	s.logPrefix = fmt.Sprintf("%d", syscall.Getpid())

	// openbsd/netbsd don't have TCP_NOPUSH so it's likely sendfile will be slower
	// without these socket options, just enable for linux, mac and freebsd.
	// TODO (Graham) windows has TransmitFile zero-copy mechanism, try to use it
	switch runtime.GOOS {
	case "linux":
		s.sendfile = true
		s.sockOpt = 0x3 // syscall.TCP_CORK
	case "freebsd", "darwin":
		s.sendfile = true
		s.sockOpt = 0x4 // syscall.TCP_NOPUSH
	default:
		s.sendfile = false
	}

	// buffer pool for reusing connection bufio.Readers
	s.bufferPool = newBufferPool(100, 8192)

	return s
}

func (srv *Server) FdListen(fd int) error {
	var err error
	srv.listenerFile = os.NewFile(uintptr(fd), "")
	if srv.listener, err = net.FileListener(srv.listenerFile); err != nil {
		return err
	}
	if _, ok := srv.listener.(*net.TCPListener); !ok {
		return errors.New("Broken listener isn't TCP")
	}
	return nil
}

func (srv *Server) socketListen() error {
	var la *net.TCPAddr
	var err error
	if la, err = net.ResolveTCPAddr("tcp", srv.Addr); err != nil {
		return err
	}

	var l *net.TCPListener
	if l, err = net.ListenTCP("tcp", la); err != nil {
		return err
	}
	srv.listener = l
	// setup listener to be non-blocking if we're not on windows.
	// this is required for hot restart to work.
	return srv.setupNonBlockingListener(err, l)
}

func (srv *Server) ListenAndServe() error {
	if srv.Addr == "" {
		srv.Addr = ":http"
	}
	if srv.listener == nil {
		if err := srv.socketListen(); err != nil {
			return err
		}
	}
	return srv.serve()
}

func (srv *Server) SocketFd() int {
	return int(srv.listenerFile.Fd())
}

func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error {
	if srv.Addr == "" {
		srv.Addr = ":https"
	}
	config := &tls.Config{
		Rand:       rand.Reader,
		Time:       time.Now,
		NextProtos: []string{"http/1.1"},
	}

	var err error
	config.Certificates = make([]tls.Certificate, 1)
	config.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile)
	if err != nil {
		return err
	}

	if srv.listener == nil {
		if err := srv.socketListen(); err != nil {
			return err
		}
	}

	srv.listener = tls.NewListener(srv.listener, config)

	return srv.serve()
}

func (srv *Server) StopAccepting() {
	close(srv.stopAccepting)
}

func (srv *Server) Port() int {
	if l := srv.listener; l != nil {
		a := l.Addr()
		if _, p, e := net.SplitHostPort(a.String()); e == nil && p != "" {
			server_port, _ := strconv.Atoi(p)
			return server_port
		}
	}
	return 0
}

func (srv *Server) serve() (e error) {
	var accept = true
	srv.AcceptReady <- 1
	for accept {
		var c net.Conn
		if l, ok := srv.listener.(*net.TCPListener); ok {
			l.SetDeadline(time.Now().Add(3e9))
		}
		c, e = srv.listener.Accept()
		if e != nil {
			if ope, ok := e.(*net.OpError); ok {
				if !(ope.Timeout() && ope.Temporary()) {
					Error("%s SERVER Accept Error: %v", srv.serverLogPrefix(), ope)
				}
			} else {
				Error("%s SERVER Accept Error: %v", srv.serverLogPrefix(), e)
			}
		} else {
			//Trace("Handling!")
			srv.handlerWaitGroup.Add(1)
			go srv.handler(c)
		}
		select {
		case <-srv.stopAccepting:
			accept = false
		default:
		}
	}
	Trace("Stopped accepting, waiting for handlers")
	// wait for handlers
	srv.handlerWaitGroup.Wait()
	return nil
}

func (srv *Server) sentinel(c net.Conn, connClosed chan int) {
	select {
	case <-srv.stopAccepting:
		c.SetReadDeadline(time.Now().Add(3 * time.Second))
	case <-connClosed:
	}
}

func (srv *Server) handler(c net.Conn) {
	startTime := time.Now()
	bpe := srv.bufferPool.take(c)
	defer srv.bufferPool.give(bpe)
	var closeSentinelChan = make(chan int)
	go srv.sentinel(c, closeSentinelChan)
	defer srv.connectionFinished(c, closeSentinelChan)
	var err error
	var req *http.Request
	// no keepalive (for now)
	reqCount := 0
	keepAlive := true
	for err == nil && keepAlive {
		if req, err = http.ReadRequest(bpe.br); err == nil {
			if req.Header.Get("Connection") != "Keep-Alive" {
				keepAlive = false
			}
			request := newRequest(req, c, startTime)
			reqCount++
			var res *http.Response

			pssInit := new(PipelineStageStat)
			pssInit.Name = "server.Init"
			pssInit.StartTime = startTime
			pssInit.EndTime = time.Now()
			request.appendPipelineStage(pssInit)
			// execute the pipeline
			if res = srv.Pipeline.execute(request); res == nil {
				res = SimpleResponse(req, 404, nil, "Not Found")
			}
			// cleanup
			request.startPipelineStage("server.ResponseWrite")
			req.Body.Close()

			// shutting down?
			select {
			case <-srv.stopAccepting:
				keepAlive = false
				res.Close = true
			default:
			}
			// The res.Write omits Content-length on 0 length bodies, and by spec,
			// it SHOULD. While this is not MUST, it's kinda broken.  See sec 4.4
			// of rfc2616 and a 200 with a zero length does not satisfy any of the
			// 5 conditions if Connection: keep-alive is set :(
			// I'm forcing chunked which seems to work because I couldn't get the
			// content length to write if it was 0.
			// Specifically, the android http client waits forever if there's no
			// content-length instead of assuming zero at the end of headers. der.
			if res.ContentLength == 0 && len(res.TransferEncoding) == 0 && !((res.StatusCode-100 < 100) || res.StatusCode == 204 || res.StatusCode == 304) {
				res.TransferEncoding = []string{"identity"}
			}
			if res.ContentLength < 0 {
				res.TransferEncoding = []string{"chunked"}
			}

			// For HTTP/1.0 and Keep-Alive, sending the Connection: Keep-Alive response header is required
			// because close is default (opposite of 1.1)
			if keepAlive && !req.ProtoAtLeast(1, 1) {
				res.Header.Add("Connection", "Keep-Alive")
			}

			// write response
			if srv.sendfile {
				res.Write(c)
				srv.cycleNonBlock(c)
			} else {
				wbuf := bufio.NewWriter(c)
				res.Write(wbuf)
				wbuf.Flush()
			}
			if res.Body != nil {
				res.Body.Close()
			}
			request.finishPipelineStage()
			request.finishRequest()
			srv.requestFinished(request)

			if res.Close {
				keepAlive = false
			}

			// Reset the startTime
			// this isn't great since there may be lag between requests; but it's the best we've got
			startTime = time.Now()
		} else {
			// EOF is socket closed
			if nerr, ok := err.(net.Error); err != io.EOF && !(ok && nerr.Timeout()) {
				Error("%s %v ERROR reading request: <%T %v>", srv.serverLogPrefix(), c.RemoteAddr(), err, err)
			}
		}
	}
	//Debug("%s Processed %v requests on connection %v", srv.serverLogPrefix(), reqCount, c.RemoteAddr())
}

func (srv *Server) serverLogPrefix() string {
	return srv.logPrefix
}

func (srv *Server) requestFinished(request *Request) {
	if srv.Pipeline.RequestDoneCallback != nil {
		// Don't block the connecion for this
		go srv.Pipeline.RequestDoneCallback.FilterRequest(request)
	}
}

func (srv *Server) connectionFinished(c net.Conn, closeChan chan int) {
	c.Close()
	close(closeChan)
	srv.handlerWaitGroup.Done()
}
<|endoftext|>


<commit_before>// Copyright © 2016 Aaron Longwell
//
// Use of this source code is governed by an MIT licese.
// Details in the LICENSE file.

package trello

import (
	"fmt"
	"time"
)

type Board struct {
	client         *Client
	ID             string `json:"id"`
	Name           string `json:"name"`
	Desc           string `json:"desc"`
	Closed         bool   `json:"closed"`
	IdOrganization string `json:"idOrganization"`
	Pinned         bool   `json:"pinned"`
	Url            string `json:"url"`
	ShortUrl       string `json:"shortUrl"`
	Prefs          struct {
		PermissionLevel       string            `json:"permissionLevel"`
		Voting                string            `json:"voting"`
		Comments              string            `json:"comments"`
		Invitations           string            `json:"invitations"`
		SelfJoin              bool              `json:"selfjoin"`
		CardCovers            bool              `json:"cardCovers"`
		CardAging             string            `json:"cardAging"`
		CalendarFeedEnabled   bool              `json:"calendarFeedEnabled"`
		Background            string            `json:"background"`
		BackgroundColor       string            `json:"backgroundColor"`
		BackgroundImage       string            `json:"backgroundImage"`
		BackgroundImageScaled []BackgroundImage `json:"backgroundImageScaled"`
		BackgroundTile        bool              `json:"backgroundTile"`
		BackgroundBrightness  string            `json:"backgroundBrightness"`
		CanBePublic           bool              `json:"canBePublic"`
		CanBeOrg              bool              `json:"canBeOrg"`
		CanBePrivate          bool              `json:"canBePrivate"`
		CanInvite             bool              `json:"canInvite"`
	} `json:"prefs"`
	LabelNames struct {
		Black  string `json:"black,omitempty"`
		Blue   string `json:"blue,omitempty"`
		Green  string `json:"green,omitempty"`
		Lime   string `json:"lime,omitempty"`
		Orange string `json:"orange,omitempty"`
		Pink   string `json:"pink,omitempty"`
		Purple string `json:"purple,omitempty"`
		Red    string `json:"red,omitempty"`
		Sky    string `json:"sky,omitempty"`
		Yellow string `json:"yellow,omitempty"`
	} `json:"labelNames"`
	Lists        []*List      `json:"lists"`
	Actions      []*Action    `json:"actions"`
	Organization Organization `json:"organization"`
}

type BackgroundImage struct {
	Width  int    `json:"width"`
	Height int    `json:"height"`
	URL    string `json:"url"`
}

func (b *Board) CreatedAt() time.Time {
	t, _ := IDToTime(b.ID)
	return t
}

/**
 * Board retrieves a Trello board by its ID.
 */
func (c *Client) GetBoard(boardID string, args Arguments) (board *Board, err error) {
	path := fmt.Sprintf("boards/%s", boardID)
	err = c.Get(path, args, &board)
	if board != nil {
		board.client = c
	}
	return
}

func (m *Member) GetBoards(args Arguments) (boards []*Board, err error) {
	path := fmt.Sprintf("members/%s/boards", m.ID)
	err = m.client.Get(path, args, &boards)
	for i := range boards {
		boards[i].client = m.client
	}
	return
}
<commit_msg>Add NewBoard constructor setting default values as API<commit_after>// Copyright © 2016 Aaron Longwell
//
// Use of this source code is governed by an MIT licese.
// Details in the LICENSE file.

package trello

import (
	"fmt"
	"time"
)

type Board struct {
	client         *Client
	ID             string `json:"id"`
	Name           string `json:"name"`
	Desc           string `json:"desc"`
	Closed         bool   `json:"closed"`
	IdOrganization string `json:"idOrganization"`
	Pinned         bool   `json:"pinned"`
	Url            string `json:"url"`
	ShortUrl       string `json:"shortUrl"`
	Prefs          struct {
		PermissionLevel       string            `json:"permissionLevel"`
		Voting                string            `json:"voting"`
		Comments              string            `json:"comments"`
		Invitations           string            `json:"invitations"`
		SelfJoin              bool              `json:"selfjoin"`
		CardCovers            bool              `json:"cardCovers"`
		CardAging             string            `json:"cardAging"`
		CalendarFeedEnabled   bool              `json:"calendarFeedEnabled"`
		Background            string            `json:"background"`
		BackgroundColor       string            `json:"backgroundColor"`
		BackgroundImage       string            `json:"backgroundImage"`
		BackgroundImageScaled []BackgroundImage `json:"backgroundImageScaled"`
		BackgroundTile        bool              `json:"backgroundTile"`
		BackgroundBrightness  string            `json:"backgroundBrightness"`
		CanBePublic           bool              `json:"canBePublic"`
		CanBeOrg              bool              `json:"canBeOrg"`
		CanBePrivate          bool              `json:"canBePrivate"`
		CanInvite             bool              `json:"canInvite"`
	} `json:"prefs"`
	LabelNames struct {
		Black  string `json:"black,omitempty"`
		Blue   string `json:"blue,omitempty"`
		Green  string `json:"green,omitempty"`
		Lime   string `json:"lime,omitempty"`
		Orange string `json:"orange,omitempty"`
		Pink   string `json:"pink,omitempty"`
		Purple string `json:"purple,omitempty"`
		Red    string `json:"red,omitempty"`
		Sky    string `json:"sky,omitempty"`
		Yellow string `json:"yellow,omitempty"`
	} `json:"labelNames"`
	Lists        []*List      `json:"lists"`
	Actions      []*Action    `json:"actions"`
	Organization Organization `json:"organization"`
}

// NewBoard is a constructor that sets the default values
// for Prefs.SelfJoin and Prefs.CardCovers also set by the API.
func NewBoard(name string) Board {
	b := Board{Name: name}

	// default values in line with API POST
	b.Prefs.SelfJoin = true
	b.Prefs.CardCovers = true

	return b
}

type BackgroundImage struct {
	Width  int    `json:"width"`
	Height int    `json:"height"`
	URL    string `json:"url"`
}

func (b *Board) CreatedAt() time.Time {
	t, _ := IDToTime(b.ID)
	return t
}

/**
 * Board retrieves a Trello board by its ID.
 */
func (c *Client) GetBoard(boardID string, args Arguments) (board *Board, err error) {
	path := fmt.Sprintf("boards/%s", boardID)
	err = c.Get(path, args, &board)
	if board != nil {
		board.client = c
	}
	return
}

func (m *Member) GetBoards(args Arguments) (boards []*Board, err error) {
	path := fmt.Sprintf("members/%s/boards", m.ID)
	err = m.client.Get(path, args, &boards)
	for i := range boards {
		boards[i].client = m.client
	}
	return
}
<|endoftext|>


<commit_before>package testservices

import (
	"context"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
)

const tmpPermissionForDirectory = os.FileMode(0755)

type TestGcsService struct {
	CopyResponse map[string]func(src, dst string) error
}

func (s *TestGcsService) Copy(ctx context.Context, src, dst string, recursive bool) error {
	res, ok := s.CopyResponse[src]
	if !ok {
		res, ok = s.CopyResponse[dst]
		if !ok {
			panic(fmt.Sprintf("no response for source %q", src))
		}
	}
	return res(src, dst)
}

func copyFile(src, dst string) error {
	from, err := os.Open(src)
	if err != nil {
		log.Fatal(err)
	}
	defer from.Close()

	to, err := os.OpenFile(dst, os.O_RDWR|os.O_CREATE, 0777)
	if err != nil {
		return err
	}
	defer to.Close()

	_, err = io.Copy(to, from)
	if err != nil {
		return err
	}
	return nil
}

func copy(src, dest string, info os.FileInfo) error {
	if info.IsDir() {
		return copyDir(src, dest, info)
	}
	if !strings.HasSuffix(dest, "yaml") && !strings.HasSuffix(dest, "yml") {
		dest = filepath.Join(dest, info.Name())
	}
	return copyFile(src, dest)
}

func copyDir(srcdir, destdir string, info os.FileInfo) error {
	contents, err := ioutil.ReadDir(srcdir)
	if err != nil {
		return err
	}
	for _, content := range contents {
		cs := filepath.Join(srcdir, content.Name())

		cd := destdir
		if content.IsDir() {
			cd = filepath.Join(destdir, content.Name())
		}
		// Make dest dir with 0755 so that everything writable.
		if err := os.MkdirAll(cd, tmpPermissionForDirectory); err != nil {
			return err
		}
		if err := copy(cs, cd, content); err != nil {
			return err
		}
	}
	return nil
}

//Copy simulates the gsutil copy.
func Copy(src, dest string) error {
	info, err := os.Stat(src)
	if err != nil {
		return err
	}
	return copy(src, dest, info)
}
<commit_msg>Add space after //<commit_after>package testservices

import (
	"context"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
)

const tmpPermissionForDirectory = os.FileMode(0755)

type TestGcsService struct {
	CopyResponse map[string]func(src, dst string) error
}

func (s *TestGcsService) Copy(ctx context.Context, src, dst string, recursive bool) error {
	res, ok := s.CopyResponse[src]
	if !ok {
		res, ok = s.CopyResponse[dst]
		if !ok {
			panic(fmt.Sprintf("no response for source %q", src))
		}
	}
	return res(src, dst)
}

func copyFile(src, dst string) error {
	from, err := os.Open(src)
	if err != nil {
		log.Fatal(err)
	}
	defer from.Close()

	to, err := os.OpenFile(dst, os.O_RDWR|os.O_CREATE, 0777)
	if err != nil {
		return err
	}
	defer to.Close()

	_, err = io.Copy(to, from)
	if err != nil {
		return err
	}
	return nil
}

func copy(src, dest string, info os.FileInfo) error {
	if info.IsDir() {
		return copyDir(src, dest, info)
	}
	if !strings.HasSuffix(dest, "yaml") && !strings.HasSuffix(dest, "yml") {
		dest = filepath.Join(dest, info.Name())
	}
	return copyFile(src, dest)
}

func copyDir(srcdir, destdir string, info os.FileInfo) error {
	contents, err := ioutil.ReadDir(srcdir)
	if err != nil {
		return err
	}
	for _, content := range contents {
		cs := filepath.Join(srcdir, content.Name())

		cd := destdir
		if content.IsDir() {
			cd = filepath.Join(destdir, content.Name())
		}
		// Make dest dir with 0755 so that everything writable.
		if err := os.MkdirAll(cd, tmpPermissionForDirectory); err != nil {
			return err
		}
		if err := copy(cs, cd, content); err != nil {
			return err
		}
	}
	return nil
}

// Copy simulates the gsutil copy.
func Copy(src, dest string) error {
	info, err := os.Stat(src)
	if err != nil {
		return err
	}
	return copy(src, dest, info)
}
<|endoftext|>


<commit_before>package ytdl

import (
	"io/ioutil"
	"net/http"
	"testing"
)

func TestVideoInfo(t *testing.T) {
	testCases := map[string]bool{
		"https://www.youtube.com/watch?v=YQHsXMglC9A":            true,
		"https://www.youtube.com/watch?v=H-30B0cqh88":            true,
		"https://www.youtube.com/watch?v=dQw4w9WgXcQ":            true,
		"https://www.youtube.com/":                               false,
		"https://www.youtube.com/watch?v=qHGTs1NSB1s":            true,
		"https://www.facebook.com/video.php?v=10153820411888896": false,
	}

	for k, v := range testCases {
		_, err := GetVideoInfo(k)
		if (err != nil && v) || (err == nil && !v) {
			t.Error("Failed test case:", k, err)
		}
	}
}

func TestGetDownloadURL(t *testing.T) {
	testCases := []string{
		"https://www.youtube.com/watch?v=FrG4TEcSuRg",
		"https://www.youtube.com/watch?v=1gOQiFEwnZ8",
		"https://www.youtube.com/watch?v=MXgnIP4rMoI",
		"https://www.youtube.com/watch?v=peBgUMT26jM",
		"https://www.youtube.com/watch?v=aQZDbBGBJsM",
		"https://www.youtube.com/watch?v=cRS4mS4gKwg",
		"https://www.youtube.com/watch?v=0fllyJTBsRU",
		"https://www.youtube.com/watch?v=yx0PEdDCle4",
	}
	for _, url := range testCases {
		info, err := GetVideoInfo(url)
		if err != nil {
			t.Fatal(err)
		}
		format := info.Formats.Worst(FormatResolutionKey)[0]
		_, err = info.GetDownloadURL(format)
		if err != nil {
			t.Error("Failed test case:", url, err)
		}
	}
}

func TestDownloadVideo(t *testing.T) {
	info, err := GetVideoInfo("https://www.youtube.com/watch?v=FrG4TEcSuRg")
	if err != nil {
		t.Fatal(err)
	}
	format := info.Formats.Worst(FormatResolutionKey)[0]
	err = info.Download(format, ioutil.Discard)
	if err != nil {
		t.Error(err)
	}
}

func TestThumbnail(t *testing.T) {
	info, err := GetVideoInfo("https://www.youtube.com/watch?v=FrG4TEcSuRg")
	if err != nil {
		t.Fatal(err)
	}

	qualities := []ThumbnailQuality{
		ThumbnailQualityDefault,
		ThumbnailQualityHigh,
		ThumbnailQualityMaxRes,
		ThumbnailQualityMedium,
		ThumbnailQualitySD,
	}

	for _, v := range qualities {
		u := info.GetThumbnailURL(v)
		resp, err := http.Get(u.String())
		if err != nil {
			t.Error(err)
		} else if resp.StatusCode != 200 {
			t.Error("Invalid status code", resp.StatusCode, "for", v)
		}
		resp.Body.Close()
	}
}
<commit_msg>fixed test error issue<commit_after>package ytdl

import (
	"io/ioutil"
	"net/http"
	"testing"
)

func TestVideoInfo(t *testing.T) {
	testCases := map[string]bool{
		"https://www.youtube.com/watch?v=YQHsXMglC9A":            true,
		"https://www.youtube.com/watch?v=H-30B0cqh88":            true,
		"https://www.youtube.com/watch?v=dQw4w9WgXcQ":            true,
		"https://www.youtube.com/":                               false,
		"https://www.youtube.com/watch?v=qHGTs1NSB1s":            true,
		"https://www.facebook.com/video.php?v=10153820411888896": false,
	}

	for k, v := range testCases {
		_, err := GetVideoInfo(k)
		if (err != nil && v) || (err == nil && !v) {
			t.Error("Failed test case:", k, err)
		}
	}
}

func TestGetDownloadURL(t *testing.T) {
	testCases := []string{
		"https://www.youtube.com/watch?v=FrG4TEcSuRg",
		"https://www.youtube.com/watch?v=jgVhBThJdXc",
		"https://www.youtube.com/watch?v=MXgnIP4rMoI",
		"https://www.youtube.com/watch?v=peBgUMT26jM",
		"https://www.youtube.com/watch?v=aQZDbBGBJsM",
		"https://www.youtube.com/watch?v=cRS4mS4gKwg",
		"https://www.youtube.com/watch?v=0fllyJTBsRU",
	}
	for _, url := range testCases {
		info, err := GetVideoInfo(url)
		if err != nil {
			t.Fatal(err)
		}
		format := info.Formats.Worst(FormatResolutionKey)[0]
		_, err = info.GetDownloadURL(format)
		if err != nil {
			t.Error("Failed test case:", url, err)
		}
	}
}

func TestDownloadVideo(t *testing.T) {
	info, err := GetVideoInfo("https://www.youtube.com/watch?v=FrG4TEcSuRg")
	if err != nil {
		t.Fatal(err)
	}
	format := info.Formats.Worst(FormatResolutionKey)[0]
	err = info.Download(format, ioutil.Discard)
	if err != nil {
		t.Error(err)
	}
}

func TestThumbnail(t *testing.T) {
	info, err := GetVideoInfo("https://www.youtube.com/watch?v=FrG4TEcSuRg")
	if err != nil {
		t.Fatal(err)
	}

	qualities := []ThumbnailQuality{
		ThumbnailQualityDefault,
		ThumbnailQualityHigh,
		ThumbnailQualityMaxRes,
		ThumbnailQualityMedium,
		ThumbnailQualitySD,
	}

	for _, v := range qualities {
		u := info.GetThumbnailURL(v)
		resp, err := http.Get(u.String())
		if err != nil {
			t.Error(err)
		} else if resp.StatusCode != 200 {
			t.Error("Invalid status code", resp.StatusCode, "for", v)
		}
		resp.Body.Close()
	}
}
<|endoftext|>


<commit_before>package version

// VERSION ...
const VERSION = "1.1.34"
<commit_msg>v1.1.35<commit_after>package version

// VERSION ...
const VERSION = "1.1.35"
<|endoftext|>


<commit_before>package logpeck

import (
	"errors"
	log "github.com/Sirupsen/logrus"
	"github.com/hpcloud/tail"
)

type LogTask struct {
	LogPath string

	peckTasks map[string]*PeckTask
	tail      *tail.Tail
	stop      bool
	errMsg    string
}

func NewLogTask(path string) *LogTask {
	task := &LogTask{
		LogPath:   path,
		peckTasks: make(map[string]*PeckTask),
		tail:      nil,
		stop:      true,
	}
	return task
}

func (p *LogTask) AddPeckTask(task *PeckTask) error {
	p.peckTasks[task.Config.Name] = task
	return nil
}

func (p *LogTask) UpdatePeckTask(task *PeckTask) error {
	task.Stat = p.peckTasks[task.Config.Name].Stat
	p.peckTasks[task.Config.Name] = task
	return nil
}

func (p *LogTask) RemovePeckTask(config *PeckTaskConfig) error {
	delete(p.peckTasks, config.Name)
	return nil
}

func (p *LogTask) StartPeckTask(config *PeckTaskConfig) error {
	if !p.Exist(config) {
		panic(config)
	}
	if p.peckTasks[config.Name].IsStop() {
		p.peckTasks[config.Name].Start()
	} else {
		panic(config)
	}
	return nil
}

func (p *LogTask) StopPeckTask(config *PeckTaskConfig) error {
	if !p.Exist(config) {
		panic(config)
	}
	if !p.peckTasks[config.Name].IsStop() {
		p.peckTasks[config.Name].Stop()
	} else {
		panic(config)
	}
	return nil
}

func (p *LogTask) Exist(config *PeckTaskConfig) bool {
	_, ok := p.peckTasks[config.Name]
	return ok
}

func (p *LogTask) Empty() bool {
	if len(p.peckTasks) == 0 {
		return true
	} else {
		return false
	}
}

func peckLogBG(p *LogTask) {
	log.Infof("[LogTask %s] Start peck log", p.LogPath)
	for content := range p.tail.Lines {
		for name, task := range p.peckTasks {
			// process log
			log.Debugf("[LogTask %s] %s content[%s]", p.LogPath, name, content.Text)
			task.Process(content.Text)
		}
		if p.stop {
			break
		}
	}
}

func (p *LogTask) Start() error {
	if !p.stop {
		return errors.New("LogTask already started")
	}
	log.Infof("[LogTask %s] Start LogTask", p.LogPath)
	if p.tail == nil {
		tailConf := tail.Config{
			ReOpen: true,
			//Poll:   true,
			Follow: true,
			Location: &tail.SeekInfo{
				Offset: 0,
				Whence: 2,
			},
		}
		p.tail, _ = tail.TailFile(p.LogPath, tailConf)
	}

	go peckLogBG(p)
	p.stop = false
	return nil
}

func (p *LogTask) Stop() error {
	if p.stop {
		return errors.New("LogTask already stopped")
	}
	log.Infof(" [LogTask %s] Stop LogTask", p.LogPath)
	p.stop = true
	p.tail.Stop()
	p.tail = nil
	return nil
}

func (p *LogTask) IsStop() bool {
	return p.stop
}

func (p *LogTask) Close() error {
	// NOT IMPLEMENT
	return nil
}

func (p *LogTask) GetStat() *LogStat {
	// NOT IMPLEMENT
	return nil
}
<commit_msg>Use poll mode<commit_after>package logpeck

import (
	"errors"
	log "github.com/Sirupsen/logrus"
	"github.com/hpcloud/tail"
)

type LogTask struct {
	LogPath string

	peckTasks map[string]*PeckTask
	tail      *tail.Tail
	stop      bool
	errMsg    string
}

func NewLogTask(path string) *LogTask {
	task := &LogTask{
		LogPath:   path,
		peckTasks: make(map[string]*PeckTask),
		tail:      nil,
		stop:      true,
	}
	return task
}

func (p *LogTask) AddPeckTask(task *PeckTask) error {
	p.peckTasks[task.Config.Name] = task
	return nil
}

func (p *LogTask) UpdatePeckTask(task *PeckTask) error {
	task.Stat = p.peckTasks[task.Config.Name].Stat
	p.peckTasks[task.Config.Name] = task
	return nil
}

func (p *LogTask) RemovePeckTask(config *PeckTaskConfig) error {
	delete(p.peckTasks, config.Name)
	return nil
}

func (p *LogTask) StartPeckTask(config *PeckTaskConfig) error {
	if !p.Exist(config) {
		panic(config)
	}
	if p.peckTasks[config.Name].IsStop() {
		p.peckTasks[config.Name].Start()
	} else {
		panic(config)
	}
	return nil
}

func (p *LogTask) StopPeckTask(config *PeckTaskConfig) error {
	if !p.Exist(config) {
		panic(config)
	}
	if !p.peckTasks[config.Name].IsStop() {
		p.peckTasks[config.Name].Stop()
	} else {
		panic(config)
	}
	return nil
}

func (p *LogTask) Exist(config *PeckTaskConfig) bool {
	_, ok := p.peckTasks[config.Name]
	return ok
}

func (p *LogTask) Empty() bool {
	if len(p.peckTasks) == 0 {
		return true
	} else {
		return false
	}
}

func peckLogBG(p *LogTask) {
	log.Infof("[LogTask %s] Start peck log", p.LogPath)
	for content := range p.tail.Lines {
		for name, task := range p.peckTasks {
			// process log
			log.Debugf("[LogTask %s] %s content[%s]", p.LogPath, name, content.Text)
			task.Process(content.Text)
		}
		if p.stop {
			break
		}
	}
}

func (p *LogTask) Start() error {
	if !p.stop {
		return errors.New("LogTask already started")
	}
	log.Infof("[LogTask %s] Start LogTask", p.LogPath)
	if p.tail == nil {
		tailConf := tail.Config{
			ReOpen: true,
			Poll:   true,
			Follow: true,
			Location: &tail.SeekInfo{
				Offset: 0,
				Whence: 2,
			},
		}
		p.tail, _ = tail.TailFile(p.LogPath, tailConf)
	}

	go peckLogBG(p)
	p.stop = false
	return nil
}

func (p *LogTask) Stop() error {
	if p.stop {
		return errors.New("LogTask already stopped")
	}
	log.Infof(" [LogTask %s] Stop LogTask", p.LogPath)
	p.stop = true
	p.tail.Stop()
	p.tail = nil
	return nil
}

func (p *LogTask) IsStop() bool {
	return p.stop
}

func (p *LogTask) Close() error {
	// NOT IMPLEMENT
	return nil
}

func (p *LogTask) GetStat() *LogStat {
	// NOT IMPLEMENT
	return nil
}
<|endoftext|>


<commit_before>package main

import (
  "database/sql"
  _ "github.com/go-sql-driver/mysql"
  "github.com/codegangsta/martini"
  "encoding/json"
  "strconv"
  "net/http"
)

func main() {
  m := martini.Classic()

  db, err := sql.Open("mysql", "root@127.0.0.1/ops")
  if err != nil { panic(err) }
  defer db.Close()

  m.Map(db)

  schoolOne := School{
    Id: 1,
    Name: "Millard North High School",
    CountyId: 1,
    DistrictId: 1,
    ClassStats: []ClassStat{
      ClassStat{
        SchoolId: 1,
        Years: "2012-2013",
        Grade: "6",
        MaleStudents: "10",
        FemaleStudents: "15",
        TotalStudents: "25",
      },
    },
  }
  schoolTwo := School{Id: 2, Name: "Millard South High School", CountyId: 1, DistrictId: 1}
  schools := []School{schoolOne, schoolTwo}

  entry2012 := DistrictYear{
    EnrollmentSize: 15,
    District: District{
      Id: 15,
      Name: "OPS",
      Latitude: 72.12345,
      Longitude: 45.215,
    },
  }

  allDistricts := []DistrictsByYear{
    DistrictsByYear{
      Year: "2012-2013",
      Districts: []DistrictYear{entry2012},
    },
    DistrictsByYear{
      Year: "2011-2012",
      Districts: []DistrictYear{entry2012},
    },
  }

  m.Get("/schools", func(res http.ResponseWriter) string {
    return render(res, schools)
  })

  m.Get("/districts", func(res http.ResponseWriter) string {
    return render(res, allDistricts)
  })

  m.Get("/schools/:id", func(res http.ResponseWriter, params martini.Params) string {
    school := schoolFind(schools, params["id"])
    return render(res, school)
  })

  m.Get("/schools/:id/:year", func(res http.ResponseWriter, params martini.Params) string {
    return "WOOOOO"
  })

  m.Run()
}

func render(res http.ResponseWriter, data interface{}) string {
    thing, err := json.Marshal(data)
    if err != nil { panic(err) }
  return asJson(res, thing)
}
func asJson(res http.ResponseWriter, data []byte) string {
  res.Header().Set("Content-Type", "application/json")
  return string(data[:])
}

func schoolFind(schools []School, id string) School {
  schoolId, err := strconv.ParseInt(id, 0, 64)
  if err != nil { panic(err) }

  for _, value := range schools {
    if value.Id == schoolId {
      return value
    }
  }

  return School{}
}

type School struct {
  Id          int64
  Name        string `sql:"size:255"`
  CountyId    int64
  DistrictId  int64
  ClassStats  []ClassStat
}

type District struct {
  Id              int64
  Name            string
  Latitude        float64
  Longitude       float64
}

type DistrictsByYear struct {
  Year      string
  Districts []DistrictYear
}

type DistrictYear struct {
  EnrollmentSize  int64
  District        District
}

type ClassStat struct {
  SchoolId        int64
  Years           string
  Grade           string
  MaleStudents    string
  FemaleStudents  string
  TotalStudents   string
}
<commit_msg>make fake schoolTwo return ClassStats as empty slice<commit_after>package main

import (
  "database/sql"
  _ "github.com/go-sql-driver/mysql"
  "github.com/codegangsta/martini"
  "encoding/json"
  "strconv"
  "net/http"
)

func main() {
  m := martini.Classic()

  db, err := sql.Open("mysql", "root@127.0.0.1/ops")
  if err != nil { panic(err) }
  defer db.Close()

  m.Map(db)

  schoolOne := School{
    Id: 1,
    Name: "Millard North High School",
    CountyId: 1,
    DistrictId: 1,
    ClassStats: []ClassStat{
      ClassStat{
        SchoolId: 1,
        Years: "2012-2013",
        Grade: "6",
        MaleStudents: "10",
        FemaleStudents: "15",
        TotalStudents: "25",
      },
    },
  }
  schoolTwo := School{
    Id: 2,
    Name: "Millard South High School",
    CountyId: 1,
    DistrictId: 1,
    ClassStats: []ClassStat{},
  }
  schools := []School{schoolOne, schoolTwo}

  entry2012 := DistrictYear{
    EnrollmentSize: 15,
    District: District{
      Id: 15,
      Name: "OPS",
      Latitude: 72.12345,
      Longitude: 45.215,
    },
  }

  allDistricts := []DistrictsByYear{
    DistrictsByYear{
      Year: "2012-2013",
      Districts: []DistrictYear{entry2012},
    },
    DistrictsByYear{
      Year: "2011-2012",
      Districts: []DistrictYear{entry2012},
    },
  }

  m.Get("/schools", func(res http.ResponseWriter) string {
    return render(res, schools)
  })

  m.Get("/districts", func(res http.ResponseWriter) string {
    return render(res, allDistricts)
  })

  m.Get("/schools/:id", func(res http.ResponseWriter, params martini.Params) string {
    school := schoolFind(schools, params["id"])
    return render(res, school)
  })

  m.Get("/schools/:id/:year", func(res http.ResponseWriter, params martini.Params) string {
    return "WOOOOO"
  })

  m.Run()
}

func render(res http.ResponseWriter, data interface{}) string {
  thing, err := json.Marshal(data)
  if err != nil { panic(err) }
  return asJson(res, thing)
}

func asJson(res http.ResponseWriter, data []byte) string {
  res.Header().Set("Content-Type", "application/json")
  return string(data[:])
}

func schoolFind(schools []School, id string) School {
  schoolId, err := strconv.ParseInt(id, 0, 64)
  if err != nil { panic(err) }

  for _, value := range schools {
    if value.Id == schoolId {
      return value
    }
  }

  return School{}
}

type School struct {
  Id          int64
  Name        string `sql:"size:255"`
  CountyId    int64
  DistrictId  int64
  ClassStats  []ClassStat
}

type District struct {
  Id              int64
  Name            string
  Latitude        float64
  Longitude       float64
}

type DistrictsByYear struct {
  Year      string
  Districts []DistrictYear
}

type DistrictYear struct {
  EnrollmentSize  int64
  District        District
}

type ClassStat struct {
  SchoolId        int64
  Years           string
  Grade           string
  MaleStudents    string
  FemaleStudents  string
  TotalStudents   string
}
<|endoftext|>


<commit_before>package release

import (
	"crypto/sha256"
	"fmt"
	"io"
	"io/ioutil"

	"github.com/pkg/errors"
)

const (
	shortCheckSumLen int = 7
)

// Binary represents the binary file within release.
type Binary struct {
	Name     string    `yaml:"name"`
	Checksum string    `yaml:"checksum"`
	Version  string    `yaml:"version,omitempty"`
	Body     io.Reader `yaml:"-"`
}

// BuildBinary builds a Binary object. Return error if it is failed
// to calculate checksum of the body.
func BuildBinary(name string, body io.Reader) (*Binary, error) {
	sum, err := checksum(body)
	if err != nil {
		return nil, err
	}
	return &Binary{
		Name:     name,
		Checksum: sum,
		Body:     body,
	}, nil
}

func checksum(r io.Reader) (string, error) {
	if r == nil {
		return "", errors.New("try to read nil")
	}
	body, err := ioutil.ReadAll(r)
	if err != nil {
		return "", errors.New("failed to read data for checksum")
	}
	return fmt.Sprintf("%x", sha256.Sum256(body)), nil
}

// InvalidChecksumError represents an error of the checksum.
type InvalidChecksumError struct {
	got  string
	want string
}

// Error returns the error message for InvalidChecksumError.
func (e *InvalidChecksumError) Error() string {
	return fmt.Sprintf("got: %s, want: %s", e.got, e.want)
}

// IsChecksumError returns that the type of err matches InvalidChecksumError type or not.
func IsChecksumError(err error) bool {
	_, ok := errors.Cause(err).(*InvalidChecksumError)
	return ok
}

// CopyAndIsValidChecksum copies src to dst and calculate checksum of src, then check it.
func (b *Binary) CopyAndValidateChecksum(dst io.Writer, src io.Reader) (int64, error) {
	h := sha256.New()
	w := io.MultiWriter(h, dst)

	written, err := io.Copy(w, src)
	if err != nil {
		return written, err
	}
	sum := fmt.Sprintf("%x", h.Sum(nil))
	if b.Checksum != sum {
		return written, errors.WithStack(&InvalidChecksumError{got: sum, want: b.Checksum})
	}

	return written, nil
}

func (b *Binary) shortChecksum() string {
	return b.Checksum[0:shortCheckSumLen]
}

// Inspect prints the binary information.
func (b *Binary) Inspect(w io.Writer) {
	fmt.Fprintf(w, "%s/%s/%s\t", b.Name, b.Version, b.shortChecksum())
}
<commit_msg>golint<commit_after>package release

import (
	"crypto/sha256"
	"fmt"
	"io"
	"io/ioutil"

	"github.com/pkg/errors"
)

const (
	shortCheckSumLen int = 7
)

// Binary represents the binary file within release.
type Binary struct {
	Name     string    `yaml:"name"`
	Checksum string    `yaml:"checksum"`
	Version  string    `yaml:"version,omitempty"`
	Body     io.Reader `yaml:"-"`
}

// BuildBinary builds a Binary object. Return error if it is failed
// to calculate checksum of the body.
func BuildBinary(name string, body io.Reader) (*Binary, error) {
	sum, err := checksum(body)
	if err != nil {
		return nil, err
	}
	return &Binary{
		Name:     name,
		Checksum: sum,
		Body:     body,
	}, nil
}

func checksum(r io.Reader) (string, error) {
	if r == nil {
		return "", errors.New("try to read nil")
	}
	body, err := ioutil.ReadAll(r)
	if err != nil {
		return "", errors.New("failed to read data for checksum")
	}
	return fmt.Sprintf("%x", sha256.Sum256(body)), nil
}

// InvalidChecksumError represents an error of the checksum.
type InvalidChecksumError struct {
	got  string
	want string
}

// Error returns the error message for InvalidChecksumError.
func (e *InvalidChecksumError) Error() string {
	return fmt.Sprintf("got: %s, want: %s", e.got, e.want)
}

// IsChecksumError returns that the type of err matches InvalidChecksumError type or not.
func IsChecksumError(err error) bool {
	_, ok := errors.Cause(err).(*InvalidChecksumError)
	return ok
}

// CopyAndValidateChecksum copies src to dst and calculate checksum of src, then check it.
func (b *Binary) CopyAndValidateChecksum(dst io.Writer, src io.Reader) (int64, error) {
	h := sha256.New()
	w := io.MultiWriter(h, dst)

	written, err := io.Copy(w, src)
	if err != nil {
		return written, err
	}
	sum := fmt.Sprintf("%x", h.Sum(nil))
	if b.Checksum != sum {
		return written, errors.WithStack(&InvalidChecksumError{got: sum, want: b.Checksum})
	}

	return written, nil
}

func (b *Binary) shortChecksum() string {
	return b.Checksum[0:shortCheckSumLen]
}

// Inspect prints the binary information.
func (b *Binary) Inspect(w io.Writer) {
	fmt.Fprintf(w, "%s/%s/%s\t", b.Name, b.Version, b.shortChecksum())
}
<|endoftext|>


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

package buildcfg

import (
	"fmt"
	"reflect"
	"strings"

	"internal/goexperiment"
)

// Experiment contains the toolchain experiments enabled for the
// current build.
//
// (This is not necessarily the set of experiments the compiler itself
// was built with.)
//
// experimentBaseline specifies the experiment flags that are enabled by
// default in the current toolchain. This is, in effect, the "control"
// configuration and any variation from this is an experiment.
var Experiment, experimentBaseline = func() (goexperiment.Flags, goexperiment.Flags) {
	flags, baseline, err := ParseGOEXPERIMENT(GOOS, GOARCH, envOr("GOEXPERIMENT", defaultGOEXPERIMENT))
	if err != nil {
		Error = err
	}
	return flags, baseline
}()

const DefaultGOEXPERIMENT = defaultGOEXPERIMENT

// FramePointerEnabled enables the use of platform conventions for
// saving frame pointers.
//
// This used to be an experiment, but now it's always enabled on
// platforms that support it.
//
// Note: must agree with runtime.framepointer_enabled.
var FramePointerEnabled = GOARCH == "amd64" || GOARCH == "arm64"

// ParseGOEXPERIMENT parses a (GOOS, GOARCH, GOEXPERIMENT)
// configuration tuple and returns the enabled and baseline experiment
// flag sets.
//
// TODO(mdempsky): Move to internal/goexperiment.
func ParseGOEXPERIMENT(goos, goarch, goexp string) (flags, baseline goexperiment.Flags, err error) {
	regabiSupported := goarch == "amd64" || goarch == "arm64"

	baseline = goexperiment.Flags{
		RegabiWrappers: regabiSupported,
		RegabiReflect:  regabiSupported,
		RegabiArgs:     regabiSupported,
	}

	// Start with the statically enabled set of experiments.
	flags = baseline

	// Pick up any changes to the baseline configuration from the
	// GOEXPERIMENT environment. This can be set at make.bash time
	// and overridden at build time.
	if goexp != "" {
		// Create a map of known experiment names.
		names := make(map[string]func(bool))
		rv := reflect.ValueOf(&flags).Elem()
		rt := rv.Type()
		for i := 0; i < rt.NumField(); i++ {
			field := rv.Field(i)
			names[strings.ToLower(rt.Field(i).Name)] = field.SetBool
		}

		// "regabi" is an alias for all working regabi
		// subexperiments, and not an experiment itself. Doing
		// this as an alias make both "regabi" and "noregabi"
		// do the right thing.
		names["regabi"] = func(v bool) {
			flags.RegabiWrappers = v
			flags.RegabiReflect = v
			flags.RegabiArgs = v
		}

		// Parse names.
		for _, f := range strings.Split(goexp, ",") {
			if f == "" {
				continue
			}
			if f == "none" {
				// GOEXPERIMENT=none disables all experiment flags.
				// This is used by cmd/dist, which doesn't know how
				// to build with any experiment flags.
				flags = goexperiment.Flags{}
				continue
			}
			val := true
			if strings.HasPrefix(f, "no") {
				f, val = f[2:], false
			}
			set, ok := names[f]
			if !ok {
				err = fmt.Errorf("unknown GOEXPERIMENT %s", f)
				return
			}
			set(val)
		}
	}

	// regabiwrappers is always enabled on amd64.
	if goarch == "amd64" {
		flags.RegabiWrappers = true
	}
	// regabi is only supported on amd64 and arm64.
	if goarch != "amd64" && goarch != "arm64" {
		flags.RegabiWrappers = false
		flags.RegabiReflect = false
		flags.RegabiArgs = false
	}
	// Check regabi dependencies.
	if flags.RegabiArgs && !(flags.RegabiWrappers && flags.RegabiReflect) {
		err = fmt.Errorf("GOEXPERIMENT regabiargs requires regabiwrappers,regabireflect")
	}
	return
}

// expList returns the list of lower-cased experiment names for
// experiments that differ from base. base may be nil to indicate no
// experiments. If all is true, then include all experiment flags,
// regardless of base.
func expList(exp, base *goexperiment.Flags, all bool) []string {
	var list []string
	rv := reflect.ValueOf(exp).Elem()
	var rBase reflect.Value
	if base != nil {
		rBase = reflect.ValueOf(base).Elem()
	}
	rt := rv.Type()
	for i := 0; i < rt.NumField(); i++ {
		name := strings.ToLower(rt.Field(i).Name)
		val := rv.Field(i).Bool()
		baseVal := false
		if base != nil {
			baseVal = rBase.Field(i).Bool()
		}
		if all || val != baseVal {
			if val {
				list = append(list, name)
			} else {
				list = append(list, "no"+name)
			}
		}
	}
	return list
}

// GOEXPERIMENT is a comma-separated list of enabled or disabled
// experiments that differ from the baseline experiment configuration.
// GOEXPERIMENT is exactly what a user would set on the command line
// to get the set of enabled experiments.
func GOEXPERIMENT() string {
	return strings.Join(expList(&Experiment, &experimentBaseline, false), ",")
}

// EnabledExperiments returns a list of enabled experiments, as
// lower-cased experiment names.
func EnabledExperiments() []string {
	return expList(&Experiment, nil, false)
}

// AllExperiments returns a list of all experiment settings.
// Disabled experiments appear in the list prefixed by "no".
func AllExperiments() []string {
	return expList(&Experiment, nil, true)
}

// UpdateExperiments updates the Experiment global based on a new GOARCH value.
// This is only required for cmd/go, which can change GOARCH after
// program startup due to use of "go env -w".
func UpdateExperiments(goos, goarch, goexperiment string) {
	var err error
	Experiment, experimentBaseline, err = ParseGOEXPERIMENT(goos, goarch, goexperiment)
	if err != nil {
		Error = err
	}
}
<commit_msg>[dev.typeparams] internal/buildcfg: allow regabiwrappers on all GOARCH<commit_after>// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package buildcfg

import (
	"fmt"
	"reflect"
	"strings"

	"internal/goexperiment"
)

// Experiment contains the toolchain experiments enabled for the
// current build.
//
// (This is not necessarily the set of experiments the compiler itself
// was built with.)
//
// experimentBaseline specifies the experiment flags that are enabled by
// default in the current toolchain. This is, in effect, the "control"
// configuration and any variation from this is an experiment.
var Experiment, experimentBaseline = func() (goexperiment.Flags, goexperiment.Flags) {
	flags, baseline, err := ParseGOEXPERIMENT(GOOS, GOARCH, envOr("GOEXPERIMENT", defaultGOEXPERIMENT))
	if err != nil {
		Error = err
	}
	return flags, baseline
}()

const DefaultGOEXPERIMENT = defaultGOEXPERIMENT

// FramePointerEnabled enables the use of platform conventions for
// saving frame pointers.
//
// This used to be an experiment, but now it's always enabled on
// platforms that support it.
//
// Note: must agree with runtime.framepointer_enabled.
var FramePointerEnabled = GOARCH == "amd64" || GOARCH == "arm64"

// ParseGOEXPERIMENT parses a (GOOS, GOARCH, GOEXPERIMENT)
// configuration tuple and returns the enabled and baseline experiment
// flag sets.
//
// TODO(mdempsky): Move to internal/goexperiment.
func ParseGOEXPERIMENT(goos, goarch, goexp string) (flags, baseline goexperiment.Flags, err error) {
	regabiSupported := goarch == "amd64" || goarch == "arm64"

	baseline = goexperiment.Flags{
		RegabiWrappers: regabiSupported,
		RegabiReflect:  regabiSupported,
		RegabiArgs:     regabiSupported,
	}

	// Start with the statically enabled set of experiments.
	flags = baseline

	// Pick up any changes to the baseline configuration from the
	// GOEXPERIMENT environment. This can be set at make.bash time
	// and overridden at build time.
	if goexp != "" {
		// Create a map of known experiment names.
		names := make(map[string]func(bool))
		rv := reflect.ValueOf(&flags).Elem()
		rt := rv.Type()
		for i := 0; i < rt.NumField(); i++ {
			field := rv.Field(i)
			names[strings.ToLower(rt.Field(i).Name)] = field.SetBool
		}

		// "regabi" is an alias for all working regabi
		// subexperiments, and not an experiment itself. Doing
		// this as an alias make both "regabi" and "noregabi"
		// do the right thing.
		names["regabi"] = func(v bool) {
			flags.RegabiWrappers = v
			flags.RegabiReflect = v
			flags.RegabiArgs = v
		}

		// Parse names.
		for _, f := range strings.Split(goexp, ",") {
			if f == "" {
				continue
			}
			if f == "none" {
				// GOEXPERIMENT=none disables all experiment flags.
				// This is used by cmd/dist, which doesn't know how
				// to build with any experiment flags.
				flags = goexperiment.Flags{}
				continue
			}
			val := true
			if strings.HasPrefix(f, "no") {
				f, val = f[2:], false
			}
			set, ok := names[f]
			if !ok {
				err = fmt.Errorf("unknown GOEXPERIMENT %s", f)
				return
			}
			set(val)
		}
	}

	// regabiwrappers is always enabled on amd64.
	if goarch == "amd64" {
		flags.RegabiWrappers = true
	}
	// regabi is only supported on amd64 and arm64.
	if goarch != "amd64" && goarch != "arm64" {
		flags.RegabiReflect = false
		flags.RegabiArgs = false
	}
	// Check regabi dependencies.
	if flags.RegabiArgs && !(flags.RegabiWrappers && flags.RegabiReflect) {
		err = fmt.Errorf("GOEXPERIMENT regabiargs requires regabiwrappers,regabireflect")
	}
	return
}

// expList returns the list of lower-cased experiment names for
// experiments that differ from base. base may be nil to indicate no
// experiments. If all is true, then include all experiment flags,
// regardless of base.
func expList(exp, base *goexperiment.Flags, all bool) []string {
	var list []string
	rv := reflect.ValueOf(exp).Elem()
	var rBase reflect.Value
	if base != nil {
		rBase = reflect.ValueOf(base).Elem()
	}
	rt := rv.Type()
	for i := 0; i < rt.NumField(); i++ {
		name := strings.ToLower(rt.Field(i).Name)
		val := rv.Field(i).Bool()
		baseVal := false
		if base != nil {
			baseVal = rBase.Field(i).Bool()
		}
		if all || val != baseVal {
			if val {
				list = append(list, name)
			} else {
				list = append(list, "no"+name)
			}
		}
	}
	return list
}

// GOEXPERIMENT is a comma-separated list of enabled or disabled
// experiments that differ from the baseline experiment configuration.
// GOEXPERIMENT is exactly what a user would set on the command line
// to get the set of enabled experiments.
func GOEXPERIMENT() string {
	return strings.Join(expList(&Experiment, &experimentBaseline, false), ",")
}

// EnabledExperiments returns a list of enabled experiments, as
// lower-cased experiment names.
func EnabledExperiments() []string {
	return expList(&Experiment, nil, false)
}

// AllExperiments returns a list of all experiment settings.
// Disabled experiments appear in the list prefixed by "no".
func AllExperiments() []string {
	return expList(&Experiment, nil, true)
}

// UpdateExperiments updates the Experiment global based on a new GOARCH value.
// This is only required for cmd/go, which can change GOARCH after
// program startup due to use of "go env -w".
func UpdateExperiments(goos, goarch, goexperiment string) {
	var err error
	Experiment, experimentBaseline, err = ParseGOEXPERIMENT(goos, goarch, goexperiment)
	if err != nil {
		Error = err
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 CoreOS, Inc.
//
// 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 version

import (
	"os"
	"path"

	"github.com/coreos/etcd/pkg/fileutil"
	"github.com/coreos/etcd/pkg/types"
)

var (
	// MinClusterVersion is the min cluster version this etcd binary is compatible with.
	MinClusterVersion = "2.0.0"
	Version           = "2.1.0-rc.0+git"

	// Git SHA Value will be set during build
	GitSHA = "Not provided (use ./build instead of go build)"
)

// WalVersion is an enum for versions of etcd logs.
type DataDirVersion string

const (
	DataDirUnknown  DataDirVersion = "Unknown WAL"
	DataDir0_4      DataDirVersion = "0.4.x"
	DataDir2_0      DataDirVersion = "2.0.0"
	DataDir2_0Proxy DataDirVersion = "2.0 proxy"
	DataDir2_0_1    DataDirVersion = "2.0.1"
)

type Versions struct {
	Server  string `json:"etcdserver"`
	Cluster string `json:"etcdcluster"`
	// TODO: raft state machine version
}

func DetectDataDir(dirpath string) (DataDirVersion, error) {
	names, err := fileutil.ReadDir(dirpath)
	if err != nil {
		if os.IsNotExist(err) {
			err = nil
		}
		// Error reading the directory
		return DataDirUnknown, err
	}
	nameSet := types.NewUnsafeSet(names...)
	if nameSet.Contains("member") {
		ver, err := DetectDataDir(path.Join(dirpath, "member"))
		if ver == DataDir2_0 {
			return DataDir2_0_1, nil
		} else if ver == DataDir0_4 {
			// How in the blazes did it get there?
			return DataDirUnknown, nil
		}
		return ver, err
	}
	if nameSet.ContainsAll([]string{"snap", "wal"}) {
		// .../wal cannot be empty to exist.
		walnames, err := fileutil.ReadDir(path.Join(dirpath, "wal"))
		if err == nil && len(walnames) > 0 {
			return DataDir2_0, nil
		}
	}
	if nameSet.ContainsAll([]string{"proxy"}) {
		return DataDir2_0Proxy, nil
	}
	if nameSet.ContainsAll([]string{"snapshot", "conf", "log"}) {
		return DataDir0_4, nil
	}
	if nameSet.ContainsAll([]string{"standby_info"}) {
		return DataDir0_4, nil
	}

	return DataDirUnknown, nil
}
<commit_msg>*: bump to v2.1.1<commit_after>// Copyright 2015 CoreOS, Inc.
//
// 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 version

import (
	"os"
	"path"

	"github.com/coreos/etcd/pkg/fileutil"
	"github.com/coreos/etcd/pkg/types"
)

var (
	// MinClusterVersion is the min cluster version this etcd binary is compatible with.
	MinClusterVersion = "2.0.0"
	Version           = "2.1.1"

	// Git SHA Value will be set during build
	GitSHA = "Not provided (use ./build instead of go build)"
)

// WalVersion is an enum for versions of etcd logs.
type DataDirVersion string

const (
	DataDirUnknown  DataDirVersion = "Unknown WAL"
	DataDir0_4      DataDirVersion = "0.4.x"
	DataDir2_0      DataDirVersion = "2.0.0"
	DataDir2_0Proxy DataDirVersion = "2.0 proxy"
	DataDir2_0_1    DataDirVersion = "2.0.1"
)

type Versions struct {
	Server  string `json:"etcdserver"`
	Cluster string `json:"etcdcluster"`
	// TODO: raft state machine version
}

func DetectDataDir(dirpath string) (DataDirVersion, error) {
	names, err := fileutil.ReadDir(dirpath)
	if err != nil {
		if os.IsNotExist(err) {
			err = nil
		}
		// Error reading the directory
		return DataDirUnknown, err
	}
	nameSet := types.NewUnsafeSet(names...)
	if nameSet.Contains("member") {
		ver, err := DetectDataDir(path.Join(dirpath, "member"))
		if ver == DataDir2_0 {
			return DataDir2_0_1, nil
		} else if ver == DataDir0_4 {
			// How in the blazes did it get there?
			return DataDirUnknown, nil
		}
		return ver, err
	}
	if nameSet.ContainsAll([]string{"snap", "wal"}) {
		// .../wal cannot be empty to exist.
		walnames, err := fileutil.ReadDir(path.Join(dirpath, "wal"))
		if err == nil && len(walnames) > 0 {
			return DataDir2_0, nil
		}
	}
	if nameSet.ContainsAll([]string{"proxy"}) {
		return DataDir2_0Proxy, nil
	}
	if nameSet.ContainsAll([]string{"snapshot", "conf", "log"}) {
		return DataDir0_4, nil
	}
	if nameSet.ContainsAll([]string{"standby_info"}) {
		return DataDir0_4, nil
	}

	return DataDirUnknown, nil
}
<|endoftext|>


<commit_before>// Copyright 2018 Envoyproxy 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 util

// HTTP filter names
const (
	// Buffer HTTP filter
	Buffer = "envoy.buffer"
	// CORS HTTP filter
	CORS = "envoy.cors"
	// Dynamo HTTP filter
	Dynamo = "envoy.http_dynamo_filter"
	// Fault HTTP filter
	Fault = "envoy.fault"
	// GRPCHTTP1Bridge HTTP filter
	GRPCHTTP1Bridge = "envoy.grpc_http1_bridge"
	// GRPCJSONTranscoder HTTP filter
	GRPCJSONTranscoder = "envoy.grpc_json_transcoder"
	// GRPCWeb HTTP filter
	GRPCWeb = "envoy.grpc_web"
	// Gzip HTTP filter
	Gzip = "envoy.gzip"
	// IPTagging HTTP filter
	IPTagging = "envoy.ip_tagging"
	// HTTPRateLimit filter
	HTTPRateLimit = "envoy.rate_limit"
	// Router HTTP filter
	Router = "envoy.router"
	// Health checking HTTP filter
	HealthCheck = "envoy.health_check"
	// Lua HTTP filter
	Lua = "envoy.lua"
	// Squash HTTP filter
	Squash = "envoy.squash"
	// HTTPExternalAuthorization HTTP filter
	HTTPExternalAuthorization = "envoy.ext_authz"
)

// Network filter names
const (
	// ClientSSLAuth network filter
	ClientSSLAuth = "envoy.client_ssl_auth"
	// Echo network filter
	Echo = "envoy.echo"
	// HTTPConnectionManager network filter
	HTTPConnectionManager = "envoy.http_connection_manager"
	// TCPProxy network filter
	TCPProxy = "envoy.tcp_proxy"
	// RateLimit network filter
	RateLimit = "envoy.ratelimit"
	// MongoProxy network filter
	MongoProxy = "envoy.mongo_proxy"
	// ThriftProxy network filter
	ThriftProxy = "envoy.filters.network.thrift_proxy"
	// RedisProxy network filter
	RedisProxy = "envoy.redis_proxy"
	// ExternalAuthorization network filter
	ExternalAuthorization = "envoy.ext_authz"
)

// Listener filter names
const (
	// OriginalDestination listener filter
	OriginalDestination = "envoy.listener.original_dst"
	// ProxyProtocol listener filter
	ProxyProtocol = "envoy.listener.proxy_protocol"
)

// Tracing provider names
const (
	// Lightstep tracer name
	Lightstep = "envoy.lightstep"
	// Zipkin tracer name
	Zipkin = "envoy.zipkin"
	// DynamicOT tracer name
	DynamicOT = "envoy.dynamic.ot"
)

// Stats sink names
const (
	// Statsd sink
	Statsd = "envoy.statsd"
	// DogStatsD compatible stastsd sink
	DogStatsd = "envoy.dog_statsd"
	// MetricsService sink
	MetricsService = "envoy.metrics_service"
)

// Access log sink names
const (
	// FileAccessLog sink name
	FileAccessLog = "envoy.file_access_log"
	// HTTPGRPCAccessLog sink for the HTTP gRPC access log service
	HTTPGRPCAccessLog = "envoy.http_grpc_access_log"
)
<commit_msg>Add constant for TlsInspector listener filter name. (#120)<commit_after>// Copyright 2018 Envoyproxy 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 util

// HTTP filter names
const (
	// Buffer HTTP filter
	Buffer = "envoy.buffer"
	// CORS HTTP filter
	CORS = "envoy.cors"
	// Dynamo HTTP filter
	Dynamo = "envoy.http_dynamo_filter"
	// Fault HTTP filter
	Fault = "envoy.fault"
	// GRPCHTTP1Bridge HTTP filter
	GRPCHTTP1Bridge = "envoy.grpc_http1_bridge"
	// GRPCJSONTranscoder HTTP filter
	GRPCJSONTranscoder = "envoy.grpc_json_transcoder"
	// GRPCWeb HTTP filter
	GRPCWeb = "envoy.grpc_web"
	// Gzip HTTP filter
	Gzip = "envoy.gzip"
	// IPTagging HTTP filter
	IPTagging = "envoy.ip_tagging"
	// HTTPRateLimit filter
	HTTPRateLimit = "envoy.rate_limit"
	// Router HTTP filter
	Router = "envoy.router"
	// Health checking HTTP filter
	HealthCheck = "envoy.health_check"
	// Lua HTTP filter
	Lua = "envoy.lua"
	// Squash HTTP filter
	Squash = "envoy.squash"
	// HTTPExternalAuthorization HTTP filter
	HTTPExternalAuthorization = "envoy.ext_authz"
)

// Network filter names
const (
	// ClientSSLAuth network filter
	ClientSSLAuth = "envoy.client_ssl_auth"
	// Echo network filter
	Echo = "envoy.echo"
	// HTTPConnectionManager network filter
	HTTPConnectionManager = "envoy.http_connection_manager"
	// TCPProxy network filter
	TCPProxy = "envoy.tcp_proxy"
	// RateLimit network filter
	RateLimit = "envoy.ratelimit"
	// MongoProxy network filter
	MongoProxy = "envoy.mongo_proxy"
	// ThriftProxy network filter
	ThriftProxy = "envoy.filters.network.thrift_proxy"
	// RedisProxy network filter
	RedisProxy = "envoy.redis_proxy"
	// ExternalAuthorization network filter
	ExternalAuthorization = "envoy.ext_authz"
)

// Listener filter names
const (
	// OriginalDestination listener filter
	OriginalDestination = "envoy.listener.original_dst"
	// ProxyProtocol listener filter
	ProxyProtocol = "envoy.listener.proxy_protocol"
	// TlsInspector listener filter
	TlsInspector = "envoy.listener.tls_inspector"
)

// Tracing provider names
const (
	// Lightstep tracer name
	Lightstep = "envoy.lightstep"
	// Zipkin tracer name
	Zipkin = "envoy.zipkin"
	// DynamicOT tracer name
	DynamicOT = "envoy.dynamic.ot"
)

// Stats sink names
const (
	// Statsd sink
	Statsd = "envoy.statsd"
	// DogStatsD compatible stastsd sink
	DogStatsd = "envoy.dog_statsd"
	// MetricsService sink
	MetricsService = "envoy.metrics_service"
)

// Access log sink names
const (
	// FileAccessLog sink name
	FileAccessLog = "envoy.file_access_log"
	// HTTPGRPCAccessLog sink for the HTTP gRPC access log service
	HTTPGRPCAccessLog = "envoy.http_grpc_access_log"
)
<|endoftext|>


<commit_before>package main

import (
	"os"
	"os/signal"
	"context"
	"syscall"
	"net/http"
	"github.com/gorilla/mux"
	"encoding/json"
	"fmt"
	"sync"
)

var roomIds = []string{
	"kougi201",
	"kougi202",
	"kougi203",
	"kougi204",

	"kougi301",
	"kougi302",
	"kougi303",
	"kougi304",
}

type RoomStatus struct {
	Templature float32 `json:"templature"`
	Hot        uint    `json:"hot"`
	Cold       uint    `json:"cold"`
	lock       sync.RWMutex
}

func getRouter() *mux.Router {
	cwd, _ := os.Getwd()
	docroot := http.Dir(cwd + "/static")
	statMap := make(map[string]*RoomStatus)
	for id := range roomIds {
		statMap[roomIds[id]] = &RoomStatus{
			Templature: 30.0,
			Hot: 0,
			Cold: 0,
			lock: sync.RWMutex{},
		}
	}

	router := mux.NewRouter()
	router.HandleFunc("/api/v1/status", func(w http.ResponseWriter, req *http.Request) {
		w.Header().Set("Cache-Control", "no-store")

		roomId := req.URL.Query().Get("room")
		stat := statMap[roomId]
		if stat == nil {
			w.WriteHeader(500)
			return
		}
		stat.lock.RLock()
		defer stat.lock.RUnlock()

		js, err := json.Marshal(*stat)
		if err != nil {
			w.WriteHeader(500)
			return
		}

		w.WriteHeader(200)
		w.Write(js)
	}).Methods("GET")
	router.HandleFunc("/api/v1/status", func(w http.ResponseWriter, req *http.Request) {
		w.Header().Set("Cache-Control", "no-store")

		roomId := req.URL.Query().Get("room")
		stat := statMap[roomId]
		if stat == nil {
			w.WriteHeader(500)
			return
		}
		stat.lock.Lock()
		defer stat.lock.Unlock()

		switch req.FormValue("vote"){
		case "hot":
			stat.Hot++
		case "cold":
			stat.Cold++
		default:
			w.WriteHeader(400)
			return
		}

		w.WriteHeader(200)
		js, err := json.Marshal(*stat)
		if err != nil {
			w.WriteHeader(500)
			return
		}
		w.Write(js)
	}).Methods("POST")
	router.Handle(`/`, http.FileServer(docroot)).Methods("GET")
	router.Handle(`/{name:.*}`, http.FileServer(docroot)).Methods("GET")

	return router
}

func startHttpServer(ctx context.Context, router *mux.Router) (err error) {
	srv := http.Server{
		Addr: "0.0.0.0:8080",
		Handler: router,
	}
	go func() {
		<-ctx.Done()
		srv.Shutdown(ctx)
	}()
	fmt.Println("start server")
	srv.ListenAndServe()
	return
}

func main() {
	ctx, cancel := context.WithCancel(context.Background())

	sig := make(chan os.Signal)
	signal.Notify(sig, syscall.SIGTERM, syscall.SIGINT)
	go func() {
		<-sig
		fmt.Println("signal handled")
		cancel()
	}()

	router := getRouter()
	if err := startHttpServer(ctx, router); err != nil {
		panic(err)
	}
}<commit_msg>add a RoomID field to RoomStatus<commit_after>package main

import (
	"os"
	"os/signal"
	"context"
	"syscall"
	"net/http"
	"github.com/gorilla/mux"
	"encoding/json"
	"fmt"
	"sync"
)

var roomIds = []string{
	"kougi201",
	"kougi202",
	"kougi203",
	"kougi204",

	"kougi301",
	"kougi302",
	"kougi303",
	"kougi304",
}

type RoomStatus struct {
	RoomID     string  `json:"id"`
	Templature float32 `json:"templature"`
	Hot        uint    `json:"hot"`
	Cold       uint    `json:"cold"`
	lock       sync.RWMutex
}

func getRouter() *mux.Router {
	cwd, _ := os.Getwd()
	docroot := http.Dir(cwd + "/static")
	statMap := make(map[string]*RoomStatus)
	for _, id := range roomIds {
		statMap[id] = &RoomStatus{
			RoomID: id,
			Templature: 30.0,
			Hot: 0,
			Cold: 0,
			lock: sync.RWMutex{},
		}
	}

	router := mux.NewRouter()
	router.HandleFunc("/api/v1/status", func(w http.ResponseWriter, req *http.Request) {
		w.Header().Set("Cache-Control", "no-store")

		roomId := req.URL.Query().Get("room")
		stat := statMap[roomId]
		if stat == nil {
			w.WriteHeader(500)
			return
		}
		stat.lock.RLock()
		defer stat.lock.RUnlock()

		js, err := json.Marshal(*stat)
		if err != nil {
			w.WriteHeader(500)
			return
		}

		w.WriteHeader(200)
		w.Write(js)
	}).Methods("GET")
	router.HandleFunc("/api/v1/status", func(w http.ResponseWriter, req *http.Request) {
		w.Header().Set("Cache-Control", "no-store")

		roomId := req.URL.Query().Get("room")
		stat := statMap[roomId]
		if stat == nil {
			w.WriteHeader(500)
			return
		}
		stat.lock.Lock()
		defer stat.lock.Unlock()

		switch req.FormValue("vote"){
		case "hot":
			stat.Hot++
		case "cold":
			stat.Cold++
		default:
			w.WriteHeader(400)
			return
		}

		w.WriteHeader(200)
		js, err := json.Marshal(*stat)
		if err != nil {
			w.WriteHeader(500)
			return
		}
		w.Write(js)
	}).Methods("POST")
	router.Handle(`/`, http.FileServer(docroot)).Methods("GET")
	router.Handle(`/{name:.*}`, http.FileServer(docroot)).Methods("GET")

	return router
}

func startHttpServer(ctx context.Context, router *mux.Router) (err error) {
	srv := http.Server{
		Addr: "0.0.0.0:8080",
		Handler: router,
	}
	go func() {
		<-ctx.Done()
		srv.Shutdown(ctx)
	}()
	fmt.Println("start server")
	srv.ListenAndServe()
	return
}

func main() {
	ctx, cancel := context.WithCancel(context.Background())

	sig := make(chan os.Signal)
	signal.Notify(sig, syscall.SIGTERM, syscall.SIGINT)
	go func() {
		<-sig
		fmt.Println("signal handled")
		cancel()
	}()

	router := getRouter()
	if err := startHttpServer(ctx, router); err != nil {
		panic(err)
	}
}<|endoftext|>


<commit_before>// Package neptulon is a socket framework with middleware support.
package neptulon

import (
	"fmt"
	"log"
	"sync"
)

// Server is a Neptulon server.
type Server struct {
	debug      bool
	err        error
	errMutex   sync.RWMutex
	listener   *Listener
	middleware []func(conn *Conn, msg []byte) []byte
	conns      map[string]*Conn
	connMutex  sync.Mutex
}

// NewServer creates a Neptulon server. This is the default TLS constructor.
// Debug mode dumps raw TCP data to stderr (log.Println() default).
func NewServer(cert, privKey, clientCACert []byte, laddr string, debug bool) (*Server, error) {
	l, err := Listen(cert, privKey, clientCACert, laddr, debug)
	if err != nil {
		return nil, err
	}

	return &Server{
		debug:    debug,
		listener: l,
		conns:    make(map[string]*Conn),
	}, nil
}

// Middleware registers a new middleware to handle incoming messages.
func (s *Server) Middleware(middleware func(conn *Conn, msg []byte) []byte) {
	s.middleware = append(s.middleware, middleware)
}

// Run starts accepting connections on the internal listener and handles connections with registered middleware.
// This function blocks and never returns, unless there was an error while accepting a new connection or the listner was closed.
func (s *Server) Run() error {
	err := s.listener.Accept(handleConn(s), handleMsg(s), handleDisconn(s))
	if err != nil && s.debug {
		log.Fatalln("Listener returned an error while closing:", err)
	}

	s.errMutex.Lock()
	s.err = err
	s.errMutex.Unlock()

	return err
}

// Send sends a message throught the connection denoted by the connection ID.
func (s *Server) Send(connID string, msg []byte) error {
	return s.conns[connID].Write(msg)
}

// Stop stops a server instance.
func (s *Server) Stop() error {
	err := s.listener.Close()

	// close all active connections discarding any read/writes that is going on currently
	// this is not a problem as we always require an ACK but it will also mean that message deliveries will be at-least-once; to-and-from the server
	s.connMutex.Lock()
	for _, conn := range s.conns {
		conn.Close()
	}
	s.connMutex.Unlock()

	s.errMutex.RLock()
	if s.err != nil {
		return fmt.Errorf("Past internal error: %v", s.err)
	}
	s.errMutex.RUnlock()
	return err
}

func handleConn(s *Server) func(conn *Conn) {
	return func(conn *Conn) {
		s.connMutex.Lock()
		s.conns[conn.ID] = conn
		s.connMutex.Unlock()
	}
}

func handleMsg(s *Server) func(conn *Conn, msg []byte) {
	return func(conn *Conn, msg []byte) {
		for _, m := range s.middleware {
			res := m(conn, msg)
			if res == nil {
				continue
			}

			if err := conn.Write(res); err != nil {
				log.Fatalln("Errored while writing response to connection:", err)
			}

			break
		}
	}
}

func handleDisconn(s *Server) func(conn *Conn) {
	return func(conn *Conn) {
		s.connMutex.Lock()
		delete(s.conns, conn.ID)
		s.connMutex.Unlock()
	}
}
<commit_msg>remove connMutex for another approach<commit_after>// Package neptulon is a socket framework with middleware support.
package neptulon

import (
	"fmt"
	"log"
	"sync"
)

// Server is a Neptulon server.
type Server struct {
	debug      bool
	err        error
	errMutex   sync.RWMutex
	listener   *Listener
	middleware []func(conn *Conn, msg []byte) []byte
	conns      map[string]*Conn
}

// NewServer creates a Neptulon server. This is the default TLS constructor.
// Debug mode dumps raw TCP data to stderr (log.Println() default).
func NewServer(cert, privKey, clientCACert []byte, laddr string, debug bool) (*Server, error) {
	l, err := Listen(cert, privKey, clientCACert, laddr, debug)
	if err != nil {
		return nil, err
	}

	return &Server{
		debug:    debug,
		listener: l,
		conns:    make(map[string]*Conn),
	}, nil
}

// Middleware registers a new middleware to handle incoming messages.
func (s *Server) Middleware(middleware func(conn *Conn, msg []byte) []byte) {
	s.middleware = append(s.middleware, middleware)
}

// Run starts accepting connections on the internal listener and handles connections with registered middleware.
// This function blocks and never returns, unless there was an error while accepting a new connection or the listner was closed.
func (s *Server) Run() error {
	err := s.listener.Accept(handleConn(s), handleMsg(s), handleDisconn(s))
	if err != nil && s.debug {
		log.Fatalln("Listener returned an error while closing:", err)
	}

	s.errMutex.Lock()
	s.err = err
	s.errMutex.Unlock()

	return err
}

// Disconn registers a function to handle client disconnection.
func (s *Server) Disconn(handler func(conn *Conn)) {

}

// Send sends a message throught the connection denoted by the connection ID.
func (s *Server) Send(connID string, msg []byte) error {
	return s.conns[connID].Write(msg)
}

// Stop stops a server instance.
func (s *Server) Stop() error {
	err := s.listener.Close()

	// close all active connections discarding any read/writes that is going on currently
	// this is not a problem as we always require an ACK but it will also mean that message deliveries will be at-least-once; to-and-from the server
	for _, conn := range s.conns {
		conn.Close()
	}

	s.errMutex.RLock()
	if s.err != nil {
		return fmt.Errorf("Past internal error: %v", s.err)
	}
	s.errMutex.RUnlock()
	return err
}

func handleConn(s *Server) func(conn *Conn) {
	return func(conn *Conn) {
		s.conns[conn.ID] = conn
	}
}

func handleMsg(s *Server) func(conn *Conn, msg []byte) {
	return func(conn *Conn, msg []byte) {
		for _, m := range s.middleware {
			res := m(conn, msg)
			if res == nil {
				continue
			}

			if err := conn.Write(res); err != nil {
				log.Fatalln("Errored while writing response to connection:", err)
			}

			break
		}
	}
}

func handleDisconn(s *Server) func(conn *Conn) {
	return func(conn *Conn) {
		delete(s.conns, conn.ID)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/go-martini/martini"
	"net/http"
)

func main() {
	m := martini.Classic()
	//中间件处理器是工作于请求和路由之间的. 本质上来说和Martini其他的处理器没有分别.
	/*
		你可以通过Handlers函数对中间件堆有完全的控制. 它将会替换掉之前的任何设置过的处理器
		m.Handlers(
		  Middleware1,
		  Middleware2,
		  Middleware3,
		)
		中间件处理器可以非常好处理一些功能，像logging(日志), authorization(授权), authentication(认证), sessions(会话), error pages(错误页面),
		以及任何其他的操作需要在http请求发生之前或者之后的:
	*/
	// 验证api密匙
	m.Use(func(res http.ResponseWriter, req *http.Request) {
		if req.Header.Get("X-API-KEY") != "secret123" {
			res.WriteHeader(http.StatusUnauthorized)
		}
	})

	//路由匹配的顺序是按照他们被定义的顺序执行的. 最先被定义的路由将会首先被用户请求匹配并调用
	m.Get("/", func() (int, string) {
		return 418, "I'm a teaport" //状态码418
	})

	m.Patch("/", func() {
		// 更新
	})

	m.Post("/", func() {
		// 创建
	})

	m.Put("/", func() {
		// 替换
	})

	m.Delete("/", func() {
		// 删除
	})

	m.Options("/", func() {
		// http 选项
	})

	m.NotFound(func() {
		// 处理 404
	})

	//路由模型可能包含参数列表, 可以通过martini.Params服务来获取
	m.Get("/hello/:name", func(params martini.Params) string {
		return "Hello " + params["name"]
	})

	//路由匹配可以通过正则表达式或者glob的形式
	m.Get("/hello2/**", func(params martini.Params) string {
		return "Hello " + params["_1"]
	})
	m.Run()
}
<commit_msg>Netxt()请求放后执行<commit_after>package main

import (
	"github.com/go-martini/martini"
	"log"
	//"net/http"
)

func main() {
	m := martini.Classic()
	//中间件处理器是工作于请求和路由之间的. 本质上来说和Martini其他的处理器没有分别.
	/*
		你可以通过Handlers函数对中间件堆有完全的控制. 它将会替换掉之前的任何设置过的处理器
		m.Handlers(
		  Middleware1,
		  Middleware2,
		  Middleware3,
		)
		中间件处理器可以非常好处理一些功能，像logging(日志), authorization(授权), authentication(认证), sessions(会话), error pages(错误页面),
		以及任何其他的操作需要在http请求发生之前或者之后的:
	*/
	// 验证api密匙
	// m.Use(func(res http.ResponseWriter, req *http.Request) {
	// 	if req.Header.Get("X-API-KEY") != "secret123" {
	// 		res.WriteHeader(http.StatusUnauthorized)
	// 	}
	// })

	//Context.Next()是一个可选的函数用于中间件处理器暂时放弃执行直到其他的处理器都执行完毕. 这样就可以很好的处理在http请求完成后需要做的操作.
	// log 记录请求完成前后  (*译者注: 很巧妙，掌声鼓励.)
	m.Use(func(c martini.Context, log *log.Logger) {
		log.Println("before a request")

		c.Next()

		log.Println("after a request")
	})

	//路由匹配的顺序是按照他们被定义的顺序执行的. 最先被定义的路由将会首先被用户请求匹配并调用
	m.Get("/", func() (int, string) {
		return 418, "I'm a teaport" //状态码418
	})

	m.Patch("/", func() {
		// 更新
	})

	m.Post("/", func() {
		// 创建
	})

	m.Put("/", func() {
		// 替换
	})

	m.Delete("/", func() {
		// 删除
	})

	m.Options("/", func() {
		// http 选项
	})

	m.NotFound(func() {
		// 处理 404
	})

	//路由模型可能包含参数列表, 可以通过martini.Params服务来获取
	m.Get("/hello/:name", func(params martini.Params) string {
		return "Hello " + params["name"]
	})

	//路由匹配可以通过正则表达式或者glob的形式
	m.Get("/hello2/**", func(params martini.Params) string {
		log.Println("hello2")
		return "Hello " + params["_1"]
	})
	m.Run()
}
<|endoftext|>


<commit_before>package main

import (
  "database/sql"
  _ "github.com/go-sql-driver/mysql"
  "github.com/codegangsta/martini"
  "encoding/json"
  "strconv"
  "net/http"
)

func main() {
  m := martini.Classic()

  db, err := sql.Open("mysql", "root@127.0.0.1/ops")
  if err != nil { panic(err) }
  defer db.Close()

  m.Map(db)

  schoolOne := School{
    Id: 1,
    Name: "Millard North High School",
    CountyId: 1,
    DistrictId: 1,
    Latitude: -35.22,
    Longitude: 45.12,
    ClassStats: []ClassStat{
      ClassStat{
        SchoolId: 1,
        Years: "2012-2013",
        Grade: "6",
        MaleStudents: "10",
        FemaleStudents: "15",
        TotalStudents: "25",
      },
    },
  }
  schoolTwo := School{
    Id: 2,
    Name: "Millard South High School",
    CountyId: 1,
    DistrictId: 1,
    ClassStats: []ClassStat{},
  }
  schools := []School{schoolOne, schoolTwo}

  entry2012 := DistrictYear{
    EnrollmentSize: 15,
    District: District{
      Id: 15,
      Name: "OPS",
      Latitude: 72.12345,
      Longitude: 45.215,
    },
  }

  schoolYearOne := SchoolYear{
    EnrollmentSize: 55,
    School: schoolOne,
  }
  district66 := SchoolsByYear{
    Year: "2012-2013",
    Schools: []SchoolYear{
      schoolYearOne,
    },
  }

  allDistricts := []DistrictsByYear{
    DistrictsByYear{
      Year: "2012-2013",
      Districts: []DistrictYear{entry2012},
    },
    DistrictsByYear{
      Year: "2011-2012",
      Districts: []DistrictYear{entry2012},
    },
  }

  m.Get("/schools", func(res http.ResponseWriter) string {
    return render(res, schools)
  })

  m.Get("/districts", func(res http.ResponseWriter) string {
    return render(res, allDistricts)
  })

  m.Get("/districts/:id", func(res http.ResponseWriter) string {
    return render(res, district66)
  })

  m.Get("/schools/:id", func(res http.ResponseWriter, params martini.Params) string {
    school := schoolFind(schools, params["id"])
    return render(res, school)
  })

  m.Get("/schools/:id/:year", func(res http.ResponseWriter, params martini.Params) string {
    return "WOOOOO"
  })

  m.Run()
}

func render(res http.ResponseWriter, data interface{}) string {
  thing, err := json.Marshal(data)
  if err != nil { panic(err) }
  return asJson(res, thing)
}

func asJson(res http.ResponseWriter, data []byte) string {
  res.Header().Set("Content-Type", "application/json")
  res.Header().Set("Access-Control-Allow-Origin", "*")
  return string(data[:])
}

func schoolFind(schools []School, id string) School {
  schoolId, err := strconv.ParseInt(id, 0, 64)
  if err != nil { panic(err) }

  for _, value := range schools {
    if value.Id == schoolId {
      return value
    }
  }

  return School{}
}

type School struct {
  Id          int64
  Name        string `sql:"size:255"`
  CountyId    int64
  DistrictId  int64
  Latitude    float64
  Longitude   float64
  ClassStats  []ClassStat
}

type SchoolsByYear struct {
  Year        string
  Schools     []SchoolYear
}

type SchoolYear struct {
  EnrollmentSize  int64
  School          School
}

type District struct {
  Id              int64
  Name            string
  Latitude        float64
  Longitude       float64
}

type DistrictsWithSchools struct {
  District        District
  Schools         []School
}

type DistrictsByYear struct {
  Year      string
  Districts []DistrictYear
}

type DistrictYear struct {
  EnrollmentSize  int64
  District        District
}

type ClassStat struct {
  SchoolId        int64
  Years           string
  Grade           string
  MaleStudents    string
  FemaleStudents  string
  TotalStudents   string
}
<commit_msg>Implement /schools/:id<commit_after>package main

import (
  "database/sql"
  _ "github.com/go-sql-driver/mysql"
  "github.com/codegangsta/martini"
  "encoding/json"
  "strconv"
  "net/http"
)

func main() {
  m := martini.Classic()

  db, err := sql.Open("mysql", "root@127.0.0.1/ops")
  if err != nil { panic(err) }
  defer db.Close()

  m.Map(db)

  //All fake data
  schoolOne := School{
    Id: 1,
    Name: "Millard North High School",
    CountyId: 1,
    DistrictId: 1,
    Latitude: -35.22,
    Longitude: 45.12,
  }
  schoolTwo := School{
    Id: 2,
    Name: "Millard South High School",
    CountyId: 1,
    DistrictId: 1,
    Latitude: -35.22,
    Longitude: 45.12,
  }
  schools := []School{schoolOne, schoolTwo}

  entry2012 := DistrictYear{
    EnrollmentSize: 15,
    District: District{
      Id: 15,
      Name: "OPS",
      Latitude: 72.12345,
      Longitude: 45.215,
    },
  }

  schoolYearOne := SchoolYear{
    EnrollmentSize: 55,
    School: schoolOne,
  }
  district66 := SchoolsByYear{
    Year: "2012-2013",
    Schools: []SchoolYear{
      schoolYearOne,
    },
  }

  allDistricts := []DistrictsByYear{
    DistrictsByYear{
      Year: "2012-2013",
      Districts: []DistrictYear{entry2012},
    },
    DistrictsByYear{
      Year: "2011-2012",
      Districts: []DistrictYear{entry2012},
    },
  }

  edisonElementary := SchoolWithEnrollment{
    School: schoolOne,
    EnrollmentByYear: []EnrollmentByYear{
      EnrollmentByYear{
        Year: "2012-2013",
        Teachers: 55,
        Students: 3000,
        GradeEnrollment: []GradeEnrollment{
          GradeEnrollment{
            Grade: "6th",
            Enrollment: 544,
          },
          GradeEnrollment{
            Grade: "5th",
            Enrollment: 544,
          },
          GradeEnrollment{
            Grade: "4th",
            Enrollment: 544,
          },
          GradeEnrollment{
            Grade: "3th",
            Enrollment: 544,
          },
        },
      },
      EnrollmentByYear{
        Year: "2011-2012",
        Teachers: 55,
        Students: 3000,
        GradeEnrollment: []GradeEnrollment{
          GradeEnrollment{
            Grade: "6th",
            Enrollment: 544,
          },
          GradeEnrollment{
            Grade: "5th",
            Enrollment: 544,
          },
          GradeEnrollment{
            Grade: "4th",
            Enrollment: 544,
          },
          GradeEnrollment{
            Grade: "3th",
            Enrollment: 544,
          },
        },
      },
    },
  }

  //Routes
  m.Get("/schools", func(res http.ResponseWriter) string {
    return render(res, schools)
  })

  m.Get("/districts", func(res http.ResponseWriter) string {
    return render(res, allDistricts)
  })

  m.Get("/districts/:id", func(res http.ResponseWriter) string {
    return render(res, district66)
  })

  m.Get("/schools/:id", func(res http.ResponseWriter, params martini.Params) string {
    //school := schoolFind(schools, params["id"])
    return render(res, edisonElementary)
  })

  m.Run()
}

func render(res http.ResponseWriter, data interface{}) string {
  thing, err := json.Marshal(data)
  if err != nil { panic(err) }
  return asJson(res, thing)
}

func asJson(res http.ResponseWriter, data []byte) string {
  res.Header().Set("Content-Type", "application/json")
  res.Header().Set("Access-Control-Allow-Origin", "*")
  return string(data[:])
}

func schoolFind(schools []School, id string) School {
  schoolId, err := strconv.ParseInt(id, 0, 64)
  if err != nil { panic(err) }

  for _, value := range schools {
    if value.Id == schoolId {
      return value
    }
  }

  return School{}
}

type School struct {
  Id          int64
  Name        string `sql:"size:255"`
  CountyId    int64
  DistrictId  int64
  Latitude    float64
  Longitude   float64
}

type SchoolsByYear struct {
  Year        string
  Schools     []SchoolYear
}

type SchoolYear struct {
  EnrollmentSize  int64
  School          School
}

type District struct {
  Id              int64
  Name            string
  Latitude        float64
  Longitude       float64
}

type SchoolWithEnrollment struct {
  School            School
  EnrollmentByYear  []EnrollmentByYear
}

type EnrollmentByYear struct {
  Year          string
  Teachers      int64
  Students      int64
  GradeEnrollment []GradeEnrollment
}

type GradeEnrollment struct {
  Grade         string
  Enrollment    int64
}

type DistrictsWithSchools struct {
  District      District
  Schools       []School
}

type DistrictsByYear struct {
  Year      string
  Districts []DistrictYear
}

type DistrictYear struct {
  EnrollmentSize  int64
  District        District
}
<|endoftext|>


<commit_before>package main

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

	"github.com/getlantern/measured"
	"github.com/gorilla/context"

	"./devicefilter"
	"./forward"
	"./httpconnect"
	"./profilter"
	"./tokenfilter"
	"./utils"
)

type Server struct {
	connectComponent      *httpconnect.HTTPConnectHandler
	lanternProComponent   *profilter.LanternProFilter
	tokenFilterComponent  *tokenfilter.TokenFilter
	deviceFilterComponent *devicefilter.DeviceFilter
	firstComponent        http.Handler

	listener net.Listener
	tls      bool
}

func NewServer(token string, logLevel utils.LogLevel) *Server {
	stdWriter := io.Writer(os.Stdout)

	// The following middleware architecture can be seen as a chain of
	// filters that is run from last to first.
	// Don't forget to check Oxy and Gorilla's handlers for middleware.

	// Handles Direct Proxying
	forwardHandler, _ := forward.New(
		nil,
		forward.Logger(utils.NewTimeLogger(&stdWriter, logLevel)),
	)

	// Handles HTTP CONNECT
	connectHandler, _ := httpconnect.New(
		forwardHandler,
		httpconnect.Logger(utils.NewTimeLogger(&stdWriter, logLevel)),
	)
	// Identifies Lantern Pro users (currently NOOP)
	lanternPro, _ := profilter.New(
		connectHandler,
		profilter.Logger(utils.NewTimeLogger(&stdWriter, logLevel)),
	)
	// Returns a 404 to requests without the proper token.  Removes the
	// header before continuing.
	tokenFilter, _ := tokenfilter.New(
		lanternPro,
		tokenfilter.TokenSetter(token),
		tokenfilter.Logger(utils.NewTimeLogger(&stdWriter, logLevel)),
	)
	// Extracts the user ID and attaches the matching client to the request
	// context.  Returns a 404 to requests without the UID.  Removes the
	// header before continuing.
	deviceFilter, _ := devicefilter.New(
		tokenFilter,
		devicefilter.Logger(utils.NewTimeLogger(&stdWriter, logLevel)),
	)

	server := &Server{
		connectComponent:      connectHandler,
		lanternProComponent:   lanternPro,
		tokenFilterComponent:  tokenFilter,
		deviceFilterComponent: deviceFilter,
		firstComponent:        deviceFilter,
	}
	return server
}

func (s *Server) ServeHTTP(addr string, ready *chan bool) error {
	var err error
	if s.listener, err = net.Listen("tcp", addr); err != nil {
		return err
	}
	s.tls = false
	fmt.Printf("Listen http on %s\n", addr)
	return s.doServe(ready)
}

func (s *Server) ServeHTTPS(addr, keyfile, certfile string, ready *chan bool) error {
	var err error
	if s.listener, err = listenTLS(addr, keyfile, certfile); err != nil {
		return err
	}
	s.tls = true
	fmt.Printf("Listen http on %s\n", addr)
	return s.doServe(ready)
}

func (s *Server) doServe(ready *chan bool) error {
	// A dirty trick to associate a connection with the http.Request it
	// contains. In "net/http/server.go", handler will be called
	// immediately after ConnState changed to StateActive, so it's safe to
	// loop through all elements in a channel to find a match remote addr.
	q := make(chan net.Conn, 10)

	proxy := http.HandlerFunc(
		func(w http.ResponseWriter, req *http.Request) {
			for c := range q {
				if c.RemoteAddr().String() == req.RemoteAddr {
					context.Set(req, "conn", c)
					break
				} else {
					q <- c
				}
			}
			s.firstComponent.ServeHTTP(w, req)
		})

	if ready != nil {
		*ready <- true
	}
	hs := http.Server{Handler: proxy,
		ConnState: func(c net.Conn, s http.ConnState) {
			if s == http.StateActive {
				select {
				case q <- c:
				default:
					fmt.Print("Oops! the connection queue is full!\n")
				}
			}
		},
	}
	return hs.Serve(measured.Listener(s.listener, 10*time.Second))
}
<commit_msg>Add a counter for total connections<commit_after>package main

import (
	"fmt"
	"io"
	"net"
	"net/http"
	"os"
	"sync/atomic"
	"time"

	"github.com/getlantern/measured"
	"github.com/gorilla/context"

	"./devicefilter"
	"./forward"
	"./httpconnect"
	"./profilter"
	"./tokenfilter"
	"./utils"
)

type Server struct {
	connectComponent      *httpconnect.HTTPConnectHandler
	lanternProComponent   *profilter.LanternProFilter
	tokenFilterComponent  *tokenfilter.TokenFilter
	deviceFilterComponent *devicefilter.DeviceFilter
	firstComponent        http.Handler

	listener net.Listener
	tls      bool

	numConnections int64
}

func NewServer(token string, logLevel utils.LogLevel) *Server {
	stdWriter := io.Writer(os.Stdout)

	// The following middleware architecture can be seen as a chain of
	// filters that is run from last to first.
	// Don't forget to check Oxy and Gorilla's handlers for middleware.

	// Handles Direct Proxying
	forwardHandler, _ := forward.New(
		nil,
		forward.Logger(utils.NewTimeLogger(&stdWriter, logLevel)),
	)

	// Handles HTTP CONNECT
	connectHandler, _ := httpconnect.New(
		forwardHandler,
		httpconnect.Logger(utils.NewTimeLogger(&stdWriter, logLevel)),
	)
	// Identifies Lantern Pro users (currently NOOP)
	lanternPro, _ := profilter.New(
		connectHandler,
		profilter.Logger(utils.NewTimeLogger(&stdWriter, logLevel)),
	)
	// Returns a 404 to requests without the proper token.  Removes the
	// header before continuing.
	tokenFilter, _ := tokenfilter.New(
		lanternPro,
		tokenfilter.TokenSetter(token),
		tokenfilter.Logger(utils.NewTimeLogger(&stdWriter, logLevel)),
	)
	// Extracts the user ID and attaches the matching client to the request
	// context.  Returns a 404 to requests without the UID.  Removes the
	// header before continuing.
	deviceFilter, _ := devicefilter.New(
		tokenFilter,
		devicefilter.Logger(utils.NewTimeLogger(&stdWriter, logLevel)),
	)

	server := &Server{
		connectComponent:      connectHandler,
		lanternProComponent:   lanternPro,
		tokenFilterComponent:  tokenFilter,
		deviceFilterComponent: deviceFilter,
		firstComponent:        deviceFilter,
	}
	return server
}

func (s *Server) ServeHTTP(addr string, ready *chan bool) error {
	var err error
	if s.listener, err = net.Listen("tcp", addr); err != nil {
		return err
	}
	s.tls = false
	fmt.Printf("Listen http on %s\n", addr)
	return s.doServe(ready)
}

func (s *Server) ServeHTTPS(addr, keyfile, certfile string, ready *chan bool) error {
	var err error
	if s.listener, err = listenTLS(addr, keyfile, certfile); err != nil {
		return err
	}
	s.tls = true
	fmt.Printf("Listen http on %s\n", addr)
	return s.doServe(ready)
}

func (s *Server) doServe(ready *chan bool) error {
	// A dirty trick to associate a connection with the http.Request it
	// contains. In "net/http/server.go", handler will be called
	// immediately after ConnState changed to StateActive, so it's safe to
	// loop through all elements in a channel to find a match remote addr.
	q := make(chan net.Conn, 10)

	proxy := http.HandlerFunc(
		func(w http.ResponseWriter, req *http.Request) {
			for c := range q {
				if c.RemoteAddr().String() == req.RemoteAddr {
					context.Set(req, "conn", c)
					break
				} else {
					q <- c
				}
			}
			s.firstComponent.ServeHTTP(w, req)
		})

	if ready != nil {
		*ready <- true
	}
	hs := http.Server{Handler: proxy,
		ConnState: func(c net.Conn, state http.ConnState) {
			switch state {
			case http.StateNew:
				atomic.AddInt64(&s.numConnections, 1)
			case http.StateActive:
				select {
				case q <- c:
				default:
					fmt.Print("Oops! the connection queue is full!\n")
				}
			case http.StateClosed:
				atomic.AddInt64(&s.numConnections, -1)
			}
		},
	}
	return hs.Serve(measured.Listener(s.listener, 10*time.Second))
}
<|endoftext|>