<commit_before>package nsqd

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"io"
	"io/ioutil"
	"time"
)

const (
	MsgIDLength       = 16
	minValidMsgLength = MsgIDLength + 8 + 2 // Timestamp + Attempts
)

type MessageID [MsgIDLength]byte

type Message struct {
	ID        MessageID
	Body      []byte
	Timestamp int64
	Attempts  uint16

	// for in-flight handling
	deliveryTS time.Time
	clientID   int64
	pri        int64
	index      int
	deferred   time.Duration
}

func NewMessage(id MessageID, body []byte) *Message {
	return &Message{
		ID:        id,
		Body:      body,
		Timestamp: time.Now().UnixNano(),
	}
}

func (m *Message) WriteTo(w io.Writer) (int64, error) {
	var buf [10]byte
	var total int64

	binary.BigEndian.PutUint64(buf[:8], uint64(m.Timestamp))
	binary.BigEndian.PutUint16(buf[8:10], uint16(m.Attempts))

	n, err := w.Write(buf[:])
	total += int64(n)
	if err != nil {
		return total, err
	}

	n, err = w.Write(m.ID[:])
	total += int64(n)
	if err != nil {
		return total, err
	}

	n, err = w.Write(m.Body)
	total += int64(n)
	if err != nil {
		return total, err
	}

	return total, nil
}

func decodeMessage(b []byte) (*Message, error) {
	var msg Message

	if len(b) < minValidMsgLength {
		return nil, fmt.Errorf("invalid message buffer size (%d)", len(b))
	}

	msg.Timestamp = int64(binary.BigEndian.Uint64(b[:8]))
	msg.Attempts = binary.BigEndian.Uint16(b[8:10])

	buf := bytes.NewBuffer(b[10:])

	_, err := io.ReadFull(buf, msg.ID[:])
	if err != nil {
		return nil, err
	}

	msg.Body, err = ioutil.ReadAll(buf)
	if err != nil {
		return nil, err
	}

	return &msg, nil
}

func writeMessageToBackend(buf *bytes.Buffer, msg *Message, bq BackendQueue) error {
	buf.Reset()
	_, err := msg.WriteTo(buf)
	if err != nil {
		return err
	}
	return bq.Put(buf.Bytes())
}
<commit_msg>DecodeMessage: skip bytes Buffer, reducing alloc overhead<commit_after>package nsqd

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"io"
	"time"
)

const (
	MsgIDLength       = 16
	minValidMsgLength = MsgIDLength + 8 + 2 // Timestamp + Attempts
)

type MessageID [MsgIDLength]byte

type Message struct {
	ID        MessageID
	Body      []byte
	Timestamp int64
	Attempts  uint16

	// for in-flight handling
	deliveryTS time.Time
	clientID   int64
	pri        int64
	index      int
	deferred   time.Duration
}

func NewMessage(id MessageID, body []byte) *Message {
	return &Message{
		ID:        id,
		Body:      body,
		Timestamp: time.Now().UnixNano(),
	}
}

func (m *Message) WriteTo(w io.Writer) (int64, error) {
	var buf [10]byte
	var total int64

	binary.BigEndian.PutUint64(buf[:8], uint64(m.Timestamp))
	binary.BigEndian.PutUint16(buf[8:10], uint16(m.Attempts))

	n, err := w.Write(buf[:])
	total += int64(n)
	if err != nil {
		return total, err
	}

	n, err = w.Write(m.ID[:])
	total += int64(n)
	if err != nil {
		return total, err
	}

	n, err = w.Write(m.Body)
	total += int64(n)
	if err != nil {
		return total, err
	}

	return total, nil
}

// decodeMessage deserializes data (as []byte) and creates a new Message
// message format:
// [x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x]...
// |       (int64)        ||    ||      (hex string encoded in ASCII)           || (binary)
// |       8-byte         ||    ||                 16-byte                      || N-byte
// ------------------------------------------------------------------------------------------...
//   nanosecond timestamp    ^^                   message ID                       message body
//                        (uint16)
//                         2-byte
//                        attempts
func decodeMessage(b []byte) (*Message, error) {
	var msg Message

	if len(b) < minValidMsgLength {
		return nil, fmt.Errorf("invalid message buffer size (%d)", len(b))
	}

	msg.Timestamp = int64(binary.BigEndian.Uint64(b[:8]))
	msg.Attempts = binary.BigEndian.Uint16(b[8:10])
	copy(msg.ID[:], b[10:10+MsgIDLength])
	msg.Body = b[10+MsgIDLength:]

	return &msg, nil
}

func writeMessageToBackend(buf *bytes.Buffer, msg *Message, bq BackendQueue) error {
	buf.Reset()
	_, err := msg.WriteTo(buf)
	if err != nil {
		return err
	}
	return bq.Put(buf.Bytes())
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"errors"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"os/exec"
	"os/signal"
	"strconv"
	"strings"
	"sync"
	"syscall"
	"time"

	"code.google.com/p/go.net/websocket"
	"github.com/heroku/hk/term"
	"github.com/kr/pty"
	"github.com/nu7hatch/gouuid"
)

const VERSION = "v0.1.0"

var daemon *bool = flag.Bool("d", false, "run the server daemon")
var broadcast *bool = flag.Bool("b", false, "only allow readonly viewers and no copilot")
var private *bool = flag.Bool("p", false, "only allow a copilot and no viewers")
var server *string = flag.String("s", "termsha.re:80", "use a different server to start session")
var version *bool = flag.Bool("v", false, "print version and exit")

var banner = ` _                          _
| |_ ___ _ __ _ __ ___  ___| |__   __ _ _ __ ___
| __/ _ \ '__| '_ ` + "`" + ` _ \/ __| '_ \ / _` + "`" + ` | '__/ _ \
| ||  __/ |  | | | | | \__ \ | | | (_| | | |  __/
 \__\___|_|  |_| |_| |_|___/_| |_|\__,_|_|  \___|

Session URL: {{URL}}

`

func init() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage:  %v [session-url]\n\n", os.Args[0])
		fmt.Fprintln(os.Stderr, "Starts termshare sesion or connects to session if session-url is specified\n")
		flag.PrintDefaults()
	}
}

type session struct {
	Name          string
	Broadcast     bool
	Private       bool
	Viewers       *viewers
	Pilot         io.ReadWriteCloser
	Copilot       io.ReadWriteCloser
	CopilotBuffer *bufferWriter
	EOF           chan struct{}
}

type sessions struct {
	sync.Mutex
	s map[string]*session
}

func (s sessions) Get(name string) (sess *session, err error) {
	s.Lock()
	defer s.Unlock()
	sess, found := s.s[name]
	if !found {
		err = errors.New("session not found")
		return
	}
	return
}

func (s sessions) Create(name string, broadcast, private bool) (*session, error) {
	if sess, _ := s.Get(name); sess != nil {
		return nil, errors.New("session already exists")
	}
	sess := &session{
		Name:          name,
		Broadcast:     broadcast,
		Private:       private,
		Viewers:       &viewers{v: make(map[io.Writer]struct{})},
		EOF:           make(chan struct{}),
		CopilotBuffer: &bufferWriter{},
	}
	s.Lock()
	defer s.Unlock()
	s.s[name] = sess
	return sess, nil
}

func (s sessions) Delete(name string) {
	s.Lock()
	defer s.Unlock()
	delete(s.s, name)
}

type viewers struct {
	sync.Mutex
	v map[io.Writer]struct{}
}

func (v viewers) Write(data []byte) (n int, err error) {
	v.Lock()
	defer v.Unlock()
	for w := range v.v {
		n, err = w.Write(data)
		if err != nil || n != len(data) {
			delete(v.v, w)
		}
	}
	return len(data), nil
}

func (v viewers) Add(viewer io.Writer) {
	v.Lock()
	defer v.Unlock()
	v.v[viewer] = struct{}{}
}

type flushWriter struct {
	f http.Flusher
	w io.Writer
}

func (fw flushWriter) Write(p []byte) (n int, err error) {
	n, err = fw.w.Write(p)
	if fw.f != nil {
		fw.f.Flush()
	}
	return
}

func FlushWriter(writer io.Writer) flushWriter {
	fw := flushWriter{w: writer}
	if f, ok := writer.(http.Flusher); ok {
		fw.f = f
	}
	return fw
}

type bufferWriter struct {
	w *websocket.Conn
	b *bytes.Buffer
}

func (bw *bufferWriter) Write(p []byte) (n int, err error) {
	if bw.b == nil {
		bw.b = new(bytes.Buffer)
	}
	if bw.b.Len() > 0 && bw.w != nil {
		if _, err = bw.b.WriteTo(bw.w); err != nil {
			bw.w = nil
			err = nil
		}
	}
	if bw.w != nil {
		n, err = bw.w.Write(p)
		if err != nil {
			bw.w = nil
			return bw.b.Write(p)
		}
		return n, err
	} else {
		return bw.b.Write(p)
	}
}

func createSession() {
	name, err := uuid.NewV4()
	if err != nil {
		panic(err)
	}
	resp, err := http.Post("http://"+*server+"/"+name.String(), "application/x-www-form-urlencoded", strings.NewReader(""))
	if err != nil {
		panic(err)
	}
	var body []byte
	if resp.StatusCode == 200 {
		body, err = ioutil.ReadAll(resp.Body)
		resp.Body.Close()
		if err != nil {
			panic(err)
		}
	} else {
		resp.Body.Close()
		log.Fatal("unable to open session")
	}
	fmt.Println(string(body))

	conn, err := websocket.Dial("ws://"+*server+"/"+name.String(), "", "http://"+*server)
	if err != nil {
		panic(err)
	}
	cols, err := term.Cols()
	if err != nil {
		panic(err)
	}
	lines, err := term.Lines()
	if err != nil {
		panic(err)
	}
	cmd := exec.Command(os.Getenv("SHELL"))
	cmd.Env = []string{
		"PS1=[termshare] \\W$ ",
		"TERM=" + os.Getenv("TERM"),
		"HOME=" + os.Getenv("HOME"),
		"USER=" + os.Getenv("USER"),
		"COLUMNS=" + strconv.Itoa(cols),
		"LINES=" + strconv.Itoa(lines),
	}
	pty, err := pty.Start(cmd)
	if err != nil {
		panic(err)
	}
	if err := term.MakeRaw(os.Stdin); err != nil {
		panic(err)
	}
	exitSignal := make(chan os.Signal)
	signal.Notify(exitSignal, os.Interrupt, syscall.SIGTERM)
	go func() {
		<-exitSignal
		term.Restore(os.Stdin)
		os.Exit(0)
	}()
	defer term.Restore(os.Stdin)
	eof := make(chan bool, 1)
	go func() {
		io.Copy(io.MultiWriter(os.Stdout, conn), pty)
		eof <- true
	}()
	go func() {
		io.Copy(pty, os.Stdin)
		eof <- true
	}()
	go func() {
		io.Copy(pty, conn)
		eof <- true
	}()
	go func() {
		for {
			_, err := conn.Write([]byte("\x00"))
			if err != nil {
				return
			}
			time.Sleep(10 * time.Second)
		}
	}()
	<-eof
}

func joinSession(sessionUrl string) {
	url, err := url.Parse(sessionUrl)
	if err != nil {
		log.Fatal(err)
	}
	if !strings.Contains(url.Host, ":") {
		url.Host = url.Host + ":80"
	}
	conn, err := websocket.Dial("ws://"+url.Host+url.Path, "", "http://"+url.Host)
	if err != nil {
		log.Fatal(err)
	}
	if err := term.MakeRaw(os.Stdin); err != nil {
		log.Fatal(err)
	}
	exitSignal := make(chan os.Signal)
	signal.Notify(exitSignal, os.Interrupt, syscall.SIGTERM)
	go func() {
		<-exitSignal
		term.Restore(os.Stdin)
		os.Exit(0)
	}()
	defer term.Restore(os.Stdin)
	eof := make(chan bool, 1)
	go func() {
		io.Copy(os.Stdout, conn)
		eof <- true
	}()
	go func() {
		io.Copy(conn, os.Stdin)
		eof <- true
	}()
	<-eof
}

func startDaemon() {
	sessions := sessions{s: make(map[string]*session)}

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		switch {
		case r.RequestURI == "/":
			http.Redirect(w, r, "https://github.com/progrium/termshare", 301)
		case r.RequestURI == "/favicon.ico":
			return
		case r.RequestURI == "/download":
			var os string
			if strings.Contains(r.Header.Get("User-Agent"), "darwin") {
				os = "Darwin"
			} else {
				os = "Linux"
			}
			http.Redirect(w, r, "http://github.com/progrium/termshare/releases/download/"+VERSION+"/termshare_"+VERSION+"_"+os+"_x86_64.tgz", 301)
		default:
			parts := strings.Split(r.RequestURI, "/")
			sessionName := parts[1]
			session, err := sessions.Get(sessionName)
			if r.Method == "POST" {
				_, err = sessions.Create(sessionName, false, false)
				if err != nil {
					log.Println(err)
					w.WriteHeader(http.StatusConflict)
					return
				}
				log.Println(sessionName + ": session created")
				w.Write([]byte(strings.Replace(banner, "{{URL}}", "http://termsha.re/"+sessionName, 1)))
				return
			}
			if err != nil {
				//w.WriteHeader(http.StatusNotFound)
				return
			}
			isWebsocket := r.Header.Get("Upgrade") == "websocket"
			switch {
			case session.Pilot == nil && isWebsocket:
				websocket.Handler(func(conn *websocket.Conn) {
					session.Pilot = conn
					log.Println(sessionName + ": pilot connected")
					_, err := io.Copy(io.MultiWriter(session.Viewers, session.CopilotBuffer), session.Pilot)
					if err != nil {
						if err == io.EOF {
							close(session.EOF)
						} else {
							log.Println("pilot writing error: ", err)
						}
					}
				}).ServeHTTP(w, r)
			case session.Pilot != nil && session.Copilot == nil && !session.Broadcast && isWebsocket:
				websocket.Handler(func(conn *websocket.Conn) {
					session.Copilot = conn
					session.CopilotBuffer.w = conn
					session.Pilot.Write([]byte("\x07")) // ding!
					log.Println(sessionName + ": copilot connected")
					eof := make(chan struct{})
					go func() {
						io.Copy(session.Pilot, session.Copilot)
						session.Copilot = nil
						session.CopilotBuffer.w = nil
						eof <- struct{}{}
					}()
					<-eof
				}).ServeHTTP(w, r)
			case session.Pilot != nil && !session.Private:
				if isWebsocket {
					websocket.Handler(func(conn *websocket.Conn) {
						session.Viewers.Add(conn)
						log.Println(sessionName + ": viewer connected (websocket)")
						<-session.EOF
					}).ServeHTTP(w, r)
				} else {
					if strings.HasPrefix(r.Header.Get("User-Agent"), "curl/") {
						session.Viewers.Add(FlushWriter(w))
						log.Println(sessionName + ": viewer connected (http stream)")
						<-session.EOF
					} else {
						log.Println(sessionName + ": viewer connected (browser)")
						http.ServeFile(w, r, "./term.html")
					}
				}
			}
		}
	})
	log.Println("Termshare server started...")
	log.Fatal(http.ListenAndServe(":"+os.Getenv("PORT"), nil))
}

func main() {
	flag.Parse()

	if *version {
		fmt.Println(VERSION)
		return
	}

	if *daemon {
		startDaemon()
	} else {
		if flag.Arg(0) == "" {
			createSession()
		} else {
			joinSession(flag.Arg(0))
		}
	}
}
<commit_msg>gittip goal<commit_after>package main

import (
	"bytes"
	"errors"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"os/exec"
	"os/signal"
	"strconv"
	"strings"
	"sync"
	"syscall"
	"time"

	"code.google.com/p/go.net/websocket"
	"github.com/heroku/hk/term"
	"github.com/kr/pty"
	"github.com/nu7hatch/gouuid"
)

const VERSION = "v0.1.0"

var daemon *bool = flag.Bool("d", false, "run the server daemon")
var broadcast *bool = flag.Bool("b", false, "only allow readonly viewers and no copilot")
var private *bool = flag.Bool("p", false, "only allow a copilot and no viewers")
var server *string = flag.String("s", "termsha.re:80", "use a different server to start session")
var version *bool = flag.Bool("v", false, "print version and exit")

var banner = ` _                          _
| |_ ___ _ __ _ __ ___  ___| |__   __ _ _ __ ___
| __/ _ \ '__| '_ ` + "`" + ` _ \/ __| '_ \ / _` + "`" + ` | '__/ _ \
| ||  __/ |  | | | | | \__ \ | | | (_| | | |  __/
 \__\___|_|  |_| |_| |_|___/_| |_|\__,_|_|  \___|

When termshare reaches $5/week on Gittip, it'll be run 100% over SSL.
Donate: https://www.gittip.com/termshare

Session URL: {{URL}}
`

func init() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage:  %v [session-url]\n\n", os.Args[0])
		fmt.Fprintln(os.Stderr, "Starts termshare sesion or connects to session if session-url is specified\n")
		flag.PrintDefaults()
	}
}

type session struct {
	Name          string
	Broadcast     bool
	Private       bool
	Viewers       *viewers
	Pilot         io.ReadWriteCloser
	Copilot       io.ReadWriteCloser
	CopilotBuffer *bufferWriter
	EOF           chan struct{}
}

type sessions struct {
	sync.Mutex
	s map[string]*session
}

func (s sessions) Get(name string) (sess *session, err error) {
	s.Lock()
	defer s.Unlock()
	sess, found := s.s[name]
	if !found {
		err = errors.New("session not found")
		return
	}
	return
}

func (s sessions) Create(name string, broadcast, private bool) (*session, error) {
	if sess, _ := s.Get(name); sess != nil {
		return nil, errors.New("session already exists")
	}
	sess := &session{
		Name:          name,
		Broadcast:     broadcast,
		Private:       private,
		Viewers:       &viewers{v: make(map[io.Writer]struct{})},
		EOF:           make(chan struct{}),
		CopilotBuffer: &bufferWriter{},
	}
	s.Lock()
	defer s.Unlock()
	s.s[name] = sess
	return sess, nil
}

func (s sessions) Delete(name string) {
	s.Lock()
	defer s.Unlock()
	delete(s.s, name)
}

type viewers struct {
	sync.Mutex
	v map[io.Writer]struct{}
}

func (v viewers) Write(data []byte) (n int, err error) {
	v.Lock()
	defer v.Unlock()
	for w := range v.v {
		n, err = w.Write(data)
		if err != nil || n != len(data) {
			delete(v.v, w)
		}
	}
	return len(data), nil
}

func (v viewers) Add(viewer io.Writer) {
	v.Lock()
	defer v.Unlock()
	v.v[viewer] = struct{}{}
}

type flushWriter struct {
	f http.Flusher
	w io.Writer
}

func (fw flushWriter) Write(p []byte) (n int, err error) {
	n, err = fw.w.Write(p)
	if fw.f != nil {
		fw.f.Flush()
	}
	return
}

func FlushWriter(writer io.Writer) flushWriter {
	fw := flushWriter{w: writer}
	if f, ok := writer.(http.Flusher); ok {
		fw.f = f
	}
	return fw
}

type bufferWriter struct {
	w *websocket.Conn
	b *bytes.Buffer
}

func (bw *bufferWriter) Write(p []byte) (n int, err error) {
	if bw.b == nil {
		bw.b = new(bytes.Buffer)
	}
	if bw.b.Len() > 0 && bw.w != nil {
		if _, err = bw.b.WriteTo(bw.w); err != nil {
			bw.w = nil
			err = nil
		}
	}
	if bw.w != nil {
		n, err = bw.w.Write(p)
		if err != nil {
			bw.w = nil
			return bw.b.Write(p)
		}
		return n, err
	} else {
		return bw.b.Write(p)
	}
}

func createSession() {
	name, err := uuid.NewV4()
	if err != nil {
		panic(err)
	}
	resp, err := http.Post("http://"+*server+"/"+name.String(), "application/x-www-form-urlencoded", strings.NewReader(""))
	if err != nil {
		panic(err)
	}
	var body []byte
	if resp.StatusCode == 200 {
		body, err = ioutil.ReadAll(resp.Body)
		resp.Body.Close()
		if err != nil {
			panic(err)
		}
	} else {
		resp.Body.Close()
		log.Fatal("unable to open session")
	}
	fmt.Println(string(body))

	conn, err := websocket.Dial("ws://"+*server+"/"+name.String(), "", "http://"+*server)
	if err != nil {
		panic(err)
	}
	cols, err := term.Cols()
	if err != nil {
		panic(err)
	}
	lines, err := term.Lines()
	if err != nil {
		panic(err)
	}
	cmd := exec.Command(os.Getenv("SHELL"))
	cmd.Env = []string{
		"PS1=[termshare] \\W$ ",
		"TERM=" + os.Getenv("TERM"),
		"HOME=" + os.Getenv("HOME"),
		"USER=" + os.Getenv("USER"),
		"COLUMNS=" + strconv.Itoa(cols),
		"LINES=" + strconv.Itoa(lines),
	}
	pty, err := pty.Start(cmd)
	if err != nil {
		panic(err)
	}
	if err := term.MakeRaw(os.Stdin); err != nil {
		panic(err)
	}
	exitSignal := make(chan os.Signal)
	signal.Notify(exitSignal, os.Interrupt, syscall.SIGTERM)
	go func() {
		<-exitSignal
		term.Restore(os.Stdin)
		os.Exit(0)
	}()
	defer term.Restore(os.Stdin)
	eof := make(chan bool, 1)
	go func() {
		io.Copy(io.MultiWriter(os.Stdout, conn), pty)
		eof <- true
	}()
	go func() {
		io.Copy(pty, os.Stdin)
		eof <- true
	}()
	go func() {
		io.Copy(pty, conn)
		eof <- true
	}()
	go func() {
		for {
			_, err := conn.Write([]byte("\x00"))
			if err != nil {
				return
			}
			time.Sleep(10 * time.Second)
		}
	}()
	<-eof
}

func joinSession(sessionUrl string) {
	url, err := url.Parse(sessionUrl)
	if err != nil {
		log.Fatal(err)
	}
	if !strings.Contains(url.Host, ":") {
		url.Host = url.Host + ":80"
	}
	conn, err := websocket.Dial("ws://"+url.Host+url.Path, "", "http://"+url.Host)
	if err != nil {
		log.Fatal(err)
	}
	if err := term.MakeRaw(os.Stdin); err != nil {
		log.Fatal(err)
	}
	exitSignal := make(chan os.Signal)
	signal.Notify(exitSignal, os.Interrupt, syscall.SIGTERM)
	go func() {
		<-exitSignal
		term.Restore(os.Stdin)
		os.Exit(0)
	}()
	defer term.Restore(os.Stdin)
	eof := make(chan bool, 1)
	go func() {
		io.Copy(os.Stdout, conn)
		eof <- true
	}()
	go func() {
		io.Copy(conn, os.Stdin)
		eof <- true
	}()
	<-eof
}

func startDaemon() {
	sessions := sessions{s: make(map[string]*session)}

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		switch {
		case r.RequestURI == "/":
			http.Redirect(w, r, "https://github.com/progrium/termshare", 301)
		case r.RequestURI == "/favicon.ico":
			return
		case r.RequestURI == "/download":
			var os string
			if strings.Contains(r.Header.Get("User-Agent"), "darwin") {
				os = "Darwin"
			} else {
				os = "Linux"
			}
			http.Redirect(w, r, "http://github.com/progrium/termshare/releases/download/"+VERSION+"/termshare_"+VERSION+"_"+os+"_x86_64.tgz", 301)
		default:
			parts := strings.Split(r.RequestURI, "/")
			sessionName := parts[1]
			session, err := sessions.Get(sessionName)
			if r.Method == "POST" {
				_, err = sessions.Create(sessionName, false, false)
				if err != nil {
					log.Println(err)
					w.WriteHeader(http.StatusConflict)
					return
				}
				log.Println(sessionName + ": session created")
				w.Write([]byte(strings.Replace(banner, "{{URL}}", "http://termsha.re/"+sessionName, 1)))
				return
			}
			if err != nil {
				//w.WriteHeader(http.StatusNotFound)
				return
			}
			isWebsocket := r.Header.Get("Upgrade") == "websocket"
			switch {
			case session.Pilot == nil && isWebsocket:
				websocket.Handler(func(conn *websocket.Conn) {
					session.Pilot = conn
					log.Println(sessionName + ": pilot connected")
					_, err := io.Copy(io.MultiWriter(session.Viewers, session.CopilotBuffer), session.Pilot)
					if err != nil {
						if err == io.EOF {
							close(session.EOF)
						} else {
							log.Println("pilot writing error: ", err)
						}
					}
				}).ServeHTTP(w, r)
			case session.Pilot != nil && session.Copilot == nil && !session.Broadcast && isWebsocket:
				websocket.Handler(func(conn *websocket.Conn) {
					session.Copilot = conn
					session.CopilotBuffer.w = conn
					session.Pilot.Write([]byte("\x07")) // ding!
					log.Println(sessionName + ": copilot connected")
					eof := make(chan struct{})
					go func() {
						io.Copy(session.Pilot, session.Copilot)
						session.Copilot = nil
						session.CopilotBuffer.w = nil
						eof <- struct{}{}
					}()
					<-eof
				}).ServeHTTP(w, r)
			case session.Pilot != nil && !session.Private:
				if isWebsocket {
					websocket.Handler(func(conn *websocket.Conn) {
						session.Viewers.Add(conn)
						log.Println(sessionName + ": viewer connected (websocket)")
						<-session.EOF
					}).ServeHTTP(w, r)
				} else {
					if strings.HasPrefix(r.Header.Get("User-Agent"), "curl/") {
						session.Viewers.Add(FlushWriter(w))
						log.Println(sessionName + ": viewer connected (http stream)")
						<-session.EOF
					} else {
						log.Println(sessionName + ": viewer connected (browser)")
						http.ServeFile(w, r, "./term.html")
					}
				}
			}
		}
	})
	log.Println("Termshare server started...")
	log.Fatal(http.ListenAndServe(":"+os.Getenv("PORT"), nil))
}

func main() {
	flag.Parse()

	if *version {
		fmt.Println(VERSION)
		return
	}

	if *daemon {
		startDaemon()
	} else {
		if flag.Arg(0) == "" {
			createSession()
		} else {
			joinSession(flag.Arg(0))
		}
	}
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 Santiago Arias | Remy Jourde
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package tournaments

import (
	"errors"
	"net/http"
	"strconv"

	"appengine"

	"github.com/taironas/gonawin/extract"
	"github.com/taironas/gonawin/helpers"
	"github.com/taironas/gonawin/helpers/log"
	templateshlp "github.com/taironas/gonawin/helpers/templates"

	mdl "github.com/taironas/gonawin/models"
)

// Tournament ranking handler:
// Use this handler to get the ranking of a tournament.
// The ranking is an array of users (members) or teams,
// You can specify the rankby parameter to be "users" or "teams".
//	GET	/j/tournament/[0-9]+/ranking/
//
// The response is an array of users.
//
func Ranking(w http.ResponseWriter, r *http.Request, u *mdl.User) error {
	if r.Method != "GET" {
		return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
	}

	c := appengine.NewContext(r)
	desc := "Tournament Ranking Handler:"

	extract := extract.NewContext(c, desc, r)

	var err error
	var t *mdl.Tournament
	if t, err = extract.Tournament(); err != nil {
		return err
	}

	rankby := r.FormValue("rankby")
	// if wrong data, we set rankby to "users"
	if rankby != "teams" && rankby != "users" {
		rankby = "users"
	}

	strlimit := r.FormValue("limit")
	limit := 100
	if len(strlimit) > 0 {
		if n, err := strconv.ParseInt(strlimit, 10, 64); err != nil {
			log.Infof(c, "%s, unable to parse %v, error:%v", strlimit, err)
		} else {
			if n > 0 {
				limit = int(n)
			}
		}
	}

	if rankby == "users" {
		log.Infof(c, "%s ready to build a user array", desc)
		users := t.RankingByUser(c, limit)

		fieldsToKeep := []string{"Id", "Username", "Alias", "Score"}
		usersJson := make([]mdl.UserJson, len(users))
		helpers.TransformFromArrayOfPointers(&users, &usersJson, fieldsToKeep)

		data := struct {
			Users []mdl.UserJson
		}{
			usersJson,
		}

		return templateshlp.RenderJson(w, c, data)

	} else if rankby == "teams" {
		log.Infof(c, "%s ready to build team array", desc)
		teams := t.RankingByTeam(c, limit)

		fieldsToKeep := []string{"Id", "Name", "Accuracy"}
		teamsJson := make([]mdl.TeamJSON, len(teams))
		helpers.TransformFromArrayOfPointers(&teams, &teamsJson, fieldsToKeep)

		data := struct {
			Teams []mdl.TeamJSON
		}{
			teamsJson,
		}
		return templateshlp.RenderJson(w, c, data)
	}
	return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
}
<commit_msg>go lint controllers/tournaments/ranking.go<commit_after>/*
 * Copyright (c) 2014 Santiago Arias | Remy Jourde
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package tournaments

import (
	"errors"
	"net/http"
	"strconv"

	"appengine"

	"github.com/taironas/gonawin/extract"
	"github.com/taironas/gonawin/helpers"
	"github.com/taironas/gonawin/helpers/log"
	templateshlp "github.com/taironas/gonawin/helpers/templates"

	mdl "github.com/taironas/gonawin/models"
)

// Ranking is the Tournament ranking handler:
// Use this handler to get the ranking of a tournament.
// The ranking is an array of users (members) or teams,
// You can specify the rankby parameter to be "users" or "teams".
//	GET	/j/tournament/[0-9]+/ranking/
//
// The response is an array of users.
//
func Ranking(w http.ResponseWriter, r *http.Request, u *mdl.User) error {
	if r.Method != "GET" {
		return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
	}

	c := appengine.NewContext(r)
	desc := "Tournament Ranking Handler:"

	extract := extract.NewContext(c, desc, r)

	var err error
	var t *mdl.Tournament
	if t, err = extract.Tournament(); err != nil {
		return err
	}

	rankby := r.FormValue("rankby")
	// if wrong data, we set rankby to "users"
	if rankby != "teams" && rankby != "users" {
		rankby = "users"
	}

	strlimit := r.FormValue("limit")
	limit := 100
	if len(strlimit) > 0 {
		if n, err := strconv.ParseInt(strlimit, 10, 64); err != nil {
			log.Infof(c, "%s, unable to parse %v, error:%v", strlimit, err)
		} else {
			if n > 0 {
				limit = int(n)
			}
		}
	}

	if rankby == "users" {
		log.Infof(c, "%s ready to build a user array", desc)
		users := t.RankingByUser(c, limit)

		fieldsToKeep := []string{"Id", "Username", "Alias", "Score"}
		usersJSON := make([]mdl.UserJson, len(users))
		helpers.TransformFromArrayOfPointers(&users, &usersJSON, fieldsToKeep)

		data := struct {
			Users []mdl.UserJson
		}{
			usersJSON,
		}

		return templateshlp.RenderJson(w, c, data)

	} else if rankby == "teams" {
		log.Infof(c, "%s ready to build team array", desc)
		teams := t.RankingByTeam(c, limit)

		fieldsToKeep := []string{"Id", "Name", "Accuracy"}
		teamsJSON := make([]mdl.TeamJSON, len(teams))
		helpers.TransformFromArrayOfPointers(&teams, &teamsJSON, fieldsToKeep)

		data := struct {
			Teams []mdl.TeamJSON
		}{
			teamsJSON,
		}
		return templateshlp.RenderJson(w, c, data)
	}
	return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
}
<|endoftext|>


<commit_before>// logstashbrcvr project logstashbrcvr.go
package main

/*

The overall idea is to get Logstash downtime failures into NewRelic.
So this simple HTTP service receives heartbeat messages from Logstash [1] on the *private* HTTP endpoint
':8080/rcv' and "relays" these heartbeats to an Nginx proxy definition (see below). Nginx itself then exposes
that proxied endpoint to an *public* HTTP endpoint ':9090/mon' where New Relic (or something similar) can monitor
the availability of Logstash (or any service which provides heartbeats over HTTP).

Example Nginx proxy configuration:

	upstream logstashbrcv {
	    # the internal HTTP endpoint
	    server <private-ip>:8080;
	}

	# the proxy itself
	server {
	    listen <public-IP>:9090;

	    location / {
	        // Fail after 10 seconds without read from proxied service.
	        proxy_read_timeout 10s;
	        proxy_pass http://logstashhbrcv;
	    }

	}

                                                                        +-------------------------------+
                                                                        | NewRelic availability checker |
                                                                        +-----------------^-------------+
                                                                                |
                                                                                |
                                                                                |
                                                                                |
                                                                                |
+--------------------+            +----------------------+             +------------------v-----------------+
|                    |            |                      |             |                                    |
| Logstash heartbeat |            | logstashbrcvr        |             | Nginx with publicly accessible URL |
| http output plugin +------------> HTTP "Relay" Service +-------------+ for NewRelic availability checker  |
|                    |            |                      |             | proxying logstashbrcvr             |
+--------------------+            +----------------------+             +------------------------------------+

(ASCI art created with http://asciiflow.com/)

[1] https://www.elastic.co/blog/how-to-check-logstashs-pulse

*/

import (
	"fmt"
	"log"
	"net/http"
)

// DEBUG LOGGING
const debug debugging = true // or flip to false
type debugging bool

func (d debugging) Printf(format string, args ...interface{}) {
	if d {
		log.Printf("  DEBUG  "+format, args...)
	}
}

type HeartbeatReceiver struct {
	heartbeatsChan *chan bool
}

type HeartbeatMonitor struct {
	heartbeatsChan *chan bool
}

// Implement http.Handler iface.
func (hbMon *HeartbeatMonitor) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	// Read from channel containing the hearbeats in a non-blocking fashion.
	// In case reading was unsuccessful, return error to client.
	select {
	case <-*hbMon.heartbeatsChan:
		// We've got a heartbeat from the channel.
		debug.Printf("(HeartbeatMonitor.ServeHTTP)  >>  Served heartbeat from channel.\n")
		fmt.Fprintf(w, "{\"status\": \"ok\"}\n")
		return
	default:
		debug.Printf("(HeartbeatMonitor.ServeHTTP)  >>  No hearbeat in channel.\n")
		// Return error code to HTTP client.
		http.NotFound(w, req)
		return
	}
}

// Implement http.Handler iface.
func (hbRcv *HeartbeatReceiver) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	// The idea here is to only "forward" heartbeat messages coming from Logstash to the
	// New Relic facing URL to enable availability checking.
	select {
	case *hbRcv.heartbeatsChan <- true:
		debug.Printf("(HeartbeatReceiver.ServeHTTP) >>  Forwarded received heartbeat message.\n")
	// Make channel sending non-blocking to prevent errors on Logstash's site (which would be counterproductive).
	// "If the send cannot go through immediately the default case will be selected."
	// Reference: http://blog.golang.org/go-concurrency-patterns-timing-out-and
	default:
		debug.Printf("(HeartbeatReceiver.ServeHTTP) >>  Dropping heartbeat message (channel full).\n")
	}

}

func main() {

	// The buffered heartbeat exchange channel.
	heartbeatsChan := make(chan bool, 1)
	// Use the same channel in both HTTP endpoints.
	hbRcv := HeartbeatReceiver{
		heartbeatsChan: &heartbeatsChan,
	}
	hbMon := HeartbeatMonitor{
		heartbeatsChan: &heartbeatsChan,
	}
	// Define routes and corresponding handler functions.
	http.Handle("/rcv", &hbRcv)
	http.Handle("/mon", &hbMon)
	// Start the webserver providing the two defines endpoints.
	if err := http.ListenAndServe(":8080", nil); err != nil {
		log.Fatal("ListenAndServe:", err)
	}

}
<commit_msg>heartbeat is an input, not output plugin.<commit_after>// logstashbrcvr project logstashbrcvr.go
package main

/*

The overall idea is to get Logstash downtime failures into NewRelic.
So this simple HTTP service receives heartbeat messages from Logstash [1] on the *private* HTTP endpoint
':8080/rcv' and "relays" these heartbeats to an Nginx proxy definition (see below). Nginx itself then exposes
that proxied endpoint to an *public* HTTP endpoint ':9090/mon' where New Relic (or something similar) can monitor
the availability of Logstash (or any service which provides heartbeats over HTTP).

Example Nginx proxy configuration:

	upstream logstashbrcv {
	    # the internal HTTP endpoint
	    server <private-ip>:8080;
	}

	# the proxy itself
	server {
	    listen <public-IP>:9090;

	    location / {
	        // Fail after 10 seconds without read from proxied service.
	        proxy_read_timeout 10s;
	        proxy_pass http://logstashhbrcv;
	    }

	}

                                                                        +-------------------------------+
                                                                        | NewRelic availability checker |
                                                                        +-----------------^-------------+
                                                                                |
                                                                                |
                                                                                |
                                                                                |
                                                                                |
+--------------------+            +----------------------+             +------------------v-----------------+
|                    |            |                      |             |                                    |
| Logstash heartbeat |            | logstashbrcvr        |             | Nginx with publicly accessible URL |
| http input plugin  +------------> HTTP "Relay" Service +-------------+ for NewRelic availability checker  |
|                    |            |                      |             | proxying logstashbrcvr             |
+--------------------+            +----------------------+             +------------------------------------+

(ASCI art created with http://asciiflow.com/)

[1] https://www.elastic.co/blog/how-to-check-logstashs-pulse

*/

import (
	"fmt"
	"log"
	"net/http"
)

// DEBUG LOGGING
const debug debugging = true // or flip to false
type debugging bool

func (d debugging) Printf(format string, args ...interface{}) {
	if d {
		log.Printf("  DEBUG  "+format, args...)
	}
}

type HeartbeatReceiver struct {
	heartbeatsChan *chan bool
}

type HeartbeatMonitor struct {
	heartbeatsChan *chan bool
}

// Implement http.Handler iface.
func (hbMon *HeartbeatMonitor) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	// Read from channel containing the hearbeats in a non-blocking fashion.
	// In case reading was unsuccessful, return error to client.
	select {
	case <-*hbMon.heartbeatsChan:
		// We've got a heartbeat from the channel.
		debug.Printf("(HeartbeatMonitor.ServeHTTP)  >>  Served heartbeat from channel.\n")
		fmt.Fprintf(w, "{\"status\": \"ok\"}\n")
		return
	default:
		debug.Printf("(HeartbeatMonitor.ServeHTTP)  >>  No hearbeat in channel.\n")
		// Return error code to HTTP client.
		http.NotFound(w, req)
		return
	}
}

// Implement http.Handler iface.
func (hbRcv *HeartbeatReceiver) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	// The idea here is to only "forward" heartbeat messages coming from Logstash to the
	// New Relic facing URL to enable availability checking.
	select {
	case *hbRcv.heartbeatsChan <- true:
		debug.Printf("(HeartbeatReceiver.ServeHTTP) >>  Forwarded received heartbeat message.\n")
	// Make channel sending non-blocking to prevent errors on Logstash's site (which would be counterproductive).
	// "If the send cannot go through immediately the default case will be selected."
	// Reference: http://blog.golang.org/go-concurrency-patterns-timing-out-and
	default:
		debug.Printf("(HeartbeatReceiver.ServeHTTP) >>  Dropping heartbeat message (channel full).\n")
	}

}

func main() {

	// The buffered heartbeat exchange channel.
	heartbeatsChan := make(chan bool, 1)
	// Use the same channel in both HTTP endpoints.
	hbRcv := HeartbeatReceiver{
		heartbeatsChan: &heartbeatsChan,
	}
	hbMon := HeartbeatMonitor{
		heartbeatsChan: &heartbeatsChan,
	}
	// Define routes and corresponding handler functions.
	http.Handle("/rcv", &hbRcv)
	http.Handle("/mon", &hbMon)
	// Start the webserver providing the two defines endpoints.
	if err := http.ListenAndServe(":8080", nil); err != nil {
		log.Fatal("ListenAndServe:", err)
	}

}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	std "github.com/balzaczyy/golucene/analysis/standard"
	_ "github.com/balzaczyy/golucene/core/codec/lucene49"
	docu "github.com/balzaczyy/golucene/core/document"
	"github.com/balzaczyy/golucene/core/index"
	"github.com/balzaczyy/golucene/core/search"
	"github.com/balzaczyy/golucene/core/store"
	"github.com/balzaczyy/golucene/core/util"
	"log"
	"math/rand"
	"os"
	"strings"
	"time"
)

func main() {
	if len(os.Args) != 2 {
		fmt.Println("Usage: go run indexFile.go hamlet.go")
		return
	}

	start := time.Now()
	nRead, nWords := 0, 0
	defer func() {
		log.Printf("Processed %v lines and %v words in %v.", nRead, nWords, time.Now().Sub(start))
	}()

	util.SetDefaultInfoStream(util.NewPrintStreamInfoStream(os.Stdout))
	index.DefaultSimilarity = func() index.Similarity {
		return search.NewDefaultSimilarity()
	}

	directory, err := store.OpenFSDirectory("app/index")
	if err != nil {
		log.Panicf("Failed to open directory: %v", err)
	}
	defer directory.Close()

	analyzer := std.NewStandardAnalyzer(util.VERSION_49)
	conf := index.NewIndexWriterConfig(util.VERSION_49, analyzer)
	writer, err := index.NewIndexWriter(directory, conf)
	if err != nil {
		log.Panicf("Failed to create writer: %v", err)
	}

	f, err := os.Open(os.Args[1])
	if err != nil {
		log.Panicf("Failed to open file '%v': %v", os.Args[1], err)
	}
	defer f.Close()

	var word string
	var wordInLine int
	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		text := scanner.Text()
		if len(text) == 0 {
			continue
		}
		nRead++
		for i, w := range strings.Split(text, "\\s+") {
			nWords++
			if rand.Intn(nWords+i) == 0 {
				word, wordInLine = w, nRead-1
			}
		}

		d := docu.NewDocument()
		d.Add(docu.NewTextFieldFromString("text", text, docu.STORE_YES))
		if err = writer.AddDocument(d.Fields()); err != nil {
			log.Panicf("Failed to process line '%v': %v", text, err)
		}
	}

	if err = writer.Close(); err != nil {
		log.Panicf("Failed to flush index: %v", err)
	}

	log.Printf("Testing selected keyword: %v", word)
	reader, err := index.OpenDirectoryReader(directory)
	if err != nil {
		log.Panicf("Failed to open writer: %v", err)
	}
	defer reader.Close()

	ss := search.NewIndexSearcher(reader)
	searchStart := time.Now()
	hits, err := ss.SearchTop(search.NewTermQuery(index.NewTerm("text", word)), 1000)
	if err != nil {
		log.Panicf("Failed to search top hits: %v", err)
	}
	log.Printf("Found %v hits in %v.", hits.TotalHits, time.Now().Sub(searchStart))
	var found bool
	for _, hit := range hits.ScoreDocs {
		if hit.Doc == wordInLine {
			found = true
		}
	}
	if !found {
		log.Panicf("Failed to found expected hit: %v", wordInLine)
	}
	doc, err := reader.Document(wordInLine)
	if err != nil {
		log.Panicf("Failed to obtain document '%v': %v", wordInLine, err)
	}
	var matched bool
	for _, w := range strings.Split(doc.Get("text"), "\\s") {
		if word == w {
			matched = true
		}
	}
	if !matched {
		log.Panicf("Word '%v' not found in text '%v'.", word, doc.Get("text"))
	}
	log.Println("Index done and verified.")
}
<commit_msg>fix word strip<commit_after>package main

import (
	"bufio"
	"fmt"
	ac "github.com/balzaczyy/golucene/analysis/core"
	std "github.com/balzaczyy/golucene/analysis/standard"
	_ "github.com/balzaczyy/golucene/core/codec/lucene49"
	docu "github.com/balzaczyy/golucene/core/document"
	"github.com/balzaczyy/golucene/core/index"
	"github.com/balzaczyy/golucene/core/search"
	"github.com/balzaczyy/golucene/core/store"
	"github.com/balzaczyy/golucene/core/util"
	"log"
	"math/rand"
	"os"
	"strings"
	"time"
)

func main() {
	if len(os.Args) != 2 {
		fmt.Println("Usage: go run indexFile.go hamlet.go")
		return
	}

	start := time.Now()
	nRead, nWords := 0, 0
	defer func() {
		log.Printf("Processed %v lines and %v words in %v.", nRead, nWords, time.Now().Sub(start))
	}()

	util.SetDefaultInfoStream(util.NewPrintStreamInfoStream(os.Stdout))
	index.DefaultSimilarity = func() index.Similarity {
		return search.NewDefaultSimilarity()
	}

	directory, err := store.OpenFSDirectory("app/index")
	if err != nil {
		log.Panicf("Failed to open directory: %v", err)
	}
	defer directory.Close()

	analyzer := std.NewStandardAnalyzer(util.VERSION_49)
	conf := index.NewIndexWriterConfig(util.VERSION_49, analyzer)
	writer, err := index.NewIndexWriter(directory, conf)
	if err != nil {
		log.Panicf("Failed to create writer: %v", err)
	}

	f, err := os.Open(os.Args[1])
	if err != nil {
		log.Panicf("Failed to open file '%v': %v", os.Args[1], err)
	}
	defer f.Close()

	var word string
	var wordInLine int
	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		text := scanner.Text()
		if len(text) == 0 {
			continue
		}
		nRead++
		for _, w := range strings.Fields(text) {
			if w = stripWord(w); len(w) == 0 {
				continue // no valid alphabet
			}
			if _, ok := ac.ENGLISH_STOP_WORDS_SET[w]; ok {
				continue // ignore stop word
			}
			if strings.Contains(w, ",") {
				panic(w)
			}
			nWords++
			if rand.Intn(nWords) == 0 {
				word, wordInLine = w, nRead-1
			}
		}

		d := docu.NewDocument()
		d.Add(docu.NewTextFieldFromString("text", text, docu.STORE_YES))
		if err = writer.AddDocument(d.Fields()); err != nil {
			log.Panicf("Failed to process line '%v': %v", text, err)
		}
	}

	if err = writer.Close(); err != nil {
		log.Panicf("Failed to flush index: %v", err)
	}

	log.Printf("Testing selected keyword: %v", word)
	reader, err := index.OpenDirectoryReader(directory)
	if err != nil {
		log.Panicf("Failed to open writer: %v", err)
	}
	defer reader.Close()

	ss := search.NewIndexSearcher(reader)
	searchStart := time.Now()
	hits, err := ss.SearchTop(search.NewTermQuery(index.NewTerm("text", word)), 1000)
	if err != nil {
		log.Panicf("Failed to search top hits: %v", err)
	}
	log.Printf("Found %v hits in %v.", hits.TotalHits, time.Now().Sub(searchStart))
	var found bool
	for _, hit := range hits.ScoreDocs {
		if hit.Doc == wordInLine {
			found = true
		}
	}
	if !found {
		log.Panicf("Failed to found expected hit: %v", wordInLine)
	}
	doc, err := reader.Document(wordInLine)
	if err != nil {
		log.Panicf("Failed to obtain document '%v': %v", wordInLine, err)
	}
	var matched bool
	for _, w := range strings.Fields(doc.Get("text")) {
		w = stripWord(w)
		if word == w {
			matched = true
		}
	}
	if !matched {
		log.Panicf("Word '%v' not found in text '%v'.", word, doc.Get("text"))
	}
	log.Println("Index done and verified.")
}

func stripWord(w string) string {
	w = strings.ToLower(w)
	start := -1
	for i, v := range w {
		isAlpha := (v >= 'a' && v <= 'z')
		if start >= 0 && !isAlpha {
			return w[start:i]
		}
		if start < 0 && isAlpha {
			start = i
		}
	}
	if start < 0 {
		return ""
	}
	return w[start:]
}
<|endoftext|>


<commit_before>package lookup

import (
    "strings"
    spider "github.com/logindaveye/dict/spider"
    rw "github.com/logindaveye/dict/rw"
)

// const DICTIONARY_PATH string = "/usr/share/dict/dictionary"
const DICTIONARY_PATH string = "/usr/share/dict/spider_word"

func searchWordLine(word string) string {
    //read dictionary file
	data := rw.Read(DICTIONARY_PATH)
	wordLines := strings.Split(string(data), "\n")

	// binary search
	low := 0
	high := len(wordLines)
	index := -1

	for low <= high { //fix bug low and high can't equal
		h := low + (high-low)/2
        if h >= len(wordLines) { //if index out of range return -1
            index = -1
            break
        }
		target := strings.Split(wordLines[h], "#")[0]
		// if strings.ToLower(target) == strings.ToLower(word) {
		if target == word {
			index = h
			break
		// } else if strings.ToLower(target) < strings.ToLower(word) {
		} else if target < word {
			low = h + 1
		} else {
			high = h - 1
		}
	}

	if index == -1 {
		return "not found"
    } else {
		return wordLines[index]
	}
}

func Lookup(word string) spider.Foods{
    food := new(spider.Foods)

    wordLine := searchWordLine(word)
    if wordLine == "not found" {
        return *food
    }

    food.Word = strings.Split(wordLine, "#")[0]
    food.Pronounce = strings.Split(wordLine, "#")[1]
    food.Meaning = strings.Split(wordLine, "#")[2]

    return *food
}
<commit_msg>h := (low + high)/2<commit_after>package lookup

import (
    "strings"
    spider "github.com/logindaveye/dict/spider"
    rw "github.com/logindaveye/dict/rw"
)

// const DICTIONARY_PATH string = "/usr/share/dict/dictionary"
const DICTIONARY_PATH string = "/usr/share/dict/spider_word"

func searchWordLine(word string) string {
    //read dictionary file
	data := rw.Read(DICTIONARY_PATH)
	wordLines := strings.Split(string(data), "\n")

	// binary search
	low := 0
	high := len(wordLines)
	index := -1

	for low <= high { //fix bug low and high can't equal
		h := (low + high)/2
        if h >= len(wordLines) { //if index out of range return -1
            index = -1
            break
        }
		target := strings.Split(wordLines[h], "#")[0]
		// if strings.ToLower(target) == strings.ToLower(word) {
		if target == word {
			index = h
			break
		// } else if strings.ToLower(target) < strings.ToLower(word) {
		} else if target < word {
			low = h + 1
		} else {
			high = h - 1
		}
	}

	if index == -1 {
		return "not found"
    } else {
		return wordLines[index]
	}
}

func Lookup(word string) spider.Foods{
    food := new(spider.Foods)

    wordLine := searchWordLine(word)
    if wordLine == "not found" {
        return *food
    }

    food.Word = strings.Split(wordLine, "#")[0]
    food.Pronounce = strings.Split(wordLine, "#")[1]
    food.Meaning = strings.Split(wordLine, "#")[2]

    return *food
}
<|endoftext|>


<commit_before>package ginServer

import (
	"encoding/json"
	"io/ioutil"
	"net/http"
	"strings"
	"time"

	"github.com/gin-gonic/contrib/sessions"
	"github.com/gin-gonic/gin"
)

const TimeFormat = "Mon, 02 Jan 2006 15:04:05 GMT"
const StatusNotModified = 304 // RFC 7232, 4.1

var unixEpochTime = time.Unix(0, 0)

type ErrorResponse struct {
	Message string `json:"message"`
}

type LocaleLanguage struct {
	Locale   string
	Language string
}

func GetSessionKey(c *gin.Context, key string) string {
	session := sessions.Default(c)
	value := session.Get(key)
	if value == nil {
		return ""
	} else {
		return session.Get(key).(string)
	}
}

func SetSessionKey(c *gin.Context, key string, value string) {
	session := sessions.Default(c)
	session.Set(key, value)
	session.Save()
}

func SaveSession(c *gin.Context) {
	session := sessions.Default(c)
	session.Save()
}

func ClearSession(c *gin.Context) {
	session := sessions.Default(c)
	session.Clear()
}

func GetLocaleLanguage(c *gin.Context) (ll LocaleLanguage) {
	header := c.Request.Header.Get("Accept-Language")
	allLanguages := strings.Split(header, ";")

	locals := strings.Split(allLanguages[0], ",")
	localsSplit := strings.Split(locals[0], "-")

	if len(localsSplit) == 1 && len(locals) == 2 {
		localsSplit = strings.Split(locals[1], "-")
	}

	ll.Language = localsSplit[0]
	if len(localsSplit) == 2 {
		ll.Locale = localsSplit[1]
	}
	return
}

func GetRequestBody(c *gin.Context) ([]byte, error) {
	body := c.Request.Body
	return ioutil.ReadAll(body)
}

// Reads a file from the path parameter and returns to the client as text/html.
func ReadHTMLFile(path string, c *gin.Context) {
	page, err := ioutil.ReadFile(path)
	if err != nil {
		c.AbortWithError(http.StatusInternalServerError, err)
		return
	}

	pageHTML := string(page)

	c.Header("Content-Type", "text/html")
	c.String(http.StatusOK, pageHTML)
}

func ReadJSFile(path string, c *gin.Context) {
	page, err := ioutil.ReadFile(path)
	if err != nil {
		c.AbortWithError(http.StatusInternalServerError, err)
		return
	}

	pageHTML := string(page)

	c.Header("Content-Type", "text/javascript")
	c.String(http.StatusOK, pageHTML)
}

// Takes a string and returns to the client as text/html.
func RenderHTML(html string, c *gin.Context) {
	c.Header("Content-Type", "text/html")
	c.String(http.StatusOK, html)
}

// Reads a file from the path parameter and returns to the client application/json
func ReadJSONFile(path string, c *gin.Context) {
	js, err := ioutil.ReadFile(path)
	if err != nil {
		c.AbortWithError(http.StatusInternalServerError, err)
		return
	}
	c.Header("Content-Type", "application/json")
	c.Writer.Write(js)
}

// Returns to the client application/json format for the passed interface.
func RespondJSON(v interface{}, c *gin.Context) {

	if v == nil {
		c.JSON(http.StatusNotFound, v)
		return
	}
	c.JSON(http.StatusOK, v)
}

//  Returns an byte array comprised of a JSON formated object with the error message.
func RespondError(message string) []byte {
	var msg ErrorResponse
	msg.Message = message
	b, _ := json.Marshal(msg)
	return b
}

func ReadGzipJSFile(path string, c *gin.Context) {

	c.Header("Content-Type", "application/javascript")
	c.Header("Content-Encoding", "gzip")
	c.File(path)
}

func RespondGzipJSFile(data []byte, modTime time.Time, c *gin.Context) {
	c.Header("Content-Type", "application/javascript")
	c.Header("Content-Encoding", "gzip")
	checkLastModified(c.Writer, c.Request, modTime)
	c.Writer.Write(data)
}

func ReadGzipCSSFile(path string, c *gin.Context) {

	c.Header("Content-Type", "text/css")
	c.Header("Content-Encoding", "gzip")
	c.File(path)

}

func RespondGzipCSSFile(data []byte, modTime time.Time, c *gin.Context) {
	c.Header("Content-Type", "text/css")
	c.Header("Content-Encoding", "gzip")
	checkLastModified(c.Writer, c.Request, modTime)
	c.Writer.Write(data)
}

func ReadPngFile(path string, c *gin.Context) {

	c.Header("Content-Type", "image/png")
	c.File(path)

}

// modtime is the modification time of the resource to be served, or IsZero().
// return value is whether this request is now complete.
func checkLastModified(w http.ResponseWriter, r *http.Request, modtime time.Time) bool {
	if modtime.IsZero() || modtime.Equal(unixEpochTime) {
		// If the file doesn't have a modtime (IsZero), or the modtime
		// is obviously garbage (Unix time == 0), then ignore modtimes
		// and don't process the If-Modified-Since header.
		return false
	}

	// The Date-Modified header truncates sub-second precision, so
	// use mtime < t+1s instead of mtime <= t to check for unmodified.
	if t, err := time.Parse(TimeFormat, r.Header.Get("If-Modified-Since")); err == nil && modtime.Before(t.Add(1*time.Second)) {
		h := w.Header()
		delete(h, "Content-Type")
		delete(h, "Content-Length")
		w.WriteHeader(StatusNotModified)
		return true
	}
	w.Header().Set("Last-Modified", modtime.UTC().Format(TimeFormat))
	return false
}
<commit_msg>Helper funcs<commit_after>package ginServer

import (
	"encoding/json"
	"io/ioutil"
	"net/http"
	"strings"
	"time"

	"github.com/gin-gonic/contrib/sessions"
	"github.com/gin-gonic/gin"
)

const TimeFormat = "Mon, 02 Jan 2006 15:04:05 GMT"
const StatusNotModified = 304 // RFC 7232, 4.1

var unixEpochTime = time.Unix(0, 0)

type ErrorResponse struct {
	Message string `json:"message"`
}

type LocaleLanguage struct {
	Locale   string
	Language string
}

func GetSessionKey(c *gin.Context, key string) string {
	session := sessions.Default(c)
	value := session.Get(key)
	if value == nil {
		return ""
	} else {
		return session.Get(key).(string)
	}
}

func SetSessionKey(c *gin.Context, key string, value string) {
	session := sessions.Default(c)
	session.Set(key, value)
	session.Save()
}

func SaveSession(c *gin.Context) {
	session := sessions.Default(c)
	session.Save()
}

func ClearSession(c *gin.Context) {
	session := sessions.Default(c)
	session.Clear()
}

func GetLocaleLanguage(c *gin.Context) (ll LocaleLanguage) {
	header := c.Request.Header.Get("Accept-Language")
	allLanguages := strings.Split(header, ";")

	locals := strings.Split(allLanguages[0], ",")
	localsSplit := strings.Split(locals[0], "-")

	if len(localsSplit) == 1 && len(locals) == 2 {
		localsSplit = strings.Split(locals[1], "-")
	}

	ll.Language = localsSplit[0]
	if len(localsSplit) == 2 {
		ll.Locale = localsSplit[1]
	}
	return
}

func GetRequestBody(c *gin.Context) ([]byte, error) {
	body := c.Request.Body
	return ioutil.ReadAll(body)
}

// Reads a file from the path parameter and returns to the client as text/html.
func ReadHTMLFile(path string, c *gin.Context) {
	page, err := ioutil.ReadFile(path)
	if err != nil {
		c.AbortWithError(http.StatusInternalServerError, err)
		return
	}

	pageHTML := string(page)

	c.Header("Content-Type", "text/html")
	c.String(http.StatusOK, pageHTML)
}

func ReadJSFile(path string, c *gin.Context) {
	page, err := ioutil.ReadFile(path)
	if err != nil {
		c.AbortWithError(http.StatusInternalServerError, err)
		return
	}

	pageHTML := string(page)

	c.Header("Content-Type", "text/javascript")
	c.String(http.StatusOK, pageHTML)
}

// Takes a string and returns to the client as text/html.
func RenderHTML(html string, c *gin.Context) {
	c.Header("Content-Type", "text/html")
	c.String(http.StatusOK, html)
}

// Reads a file from the path parameter and returns to the client application/json
func ReadJSONFile(path string, c *gin.Context) {
	js, err := ioutil.ReadFile(path)
	if err != nil {
		c.AbortWithError(http.StatusInternalServerError, err)
		return
	}
	c.Header("Content-Type", "application/json")
	c.Writer.Write(js)
}

// Returns to the client application/json format for the passed interface.
func RespondJSON(v interface{}, c *gin.Context) {

	if v == nil {
		c.JSON(http.StatusNotFound, v)
		return
	}
	c.JSON(http.StatusOK, v)
}

//  Returns an byte array comprised of a JSON formated object with the error message.
func RespondError(message string) []byte {
	var msg ErrorResponse
	msg.Message = message
	b, _ := json.Marshal(msg)
	return b
}

func ReadGzipJSFile(path string, c *gin.Context) {

	c.Header("Content-Type", "application/javascript")
	c.Header("Content-Encoding", "gzip")
	c.File(path)
}

func RespondGzipJSFile(data []byte, modTime time.Time, c *gin.Context) {
	c.Header("Content-Type", "application/javascript")
	c.Header("Content-Encoding", "gzip")
	checkLastModified(c.Writer, c.Request, modTime)
	c.Writer.Write(data)
}

func RespondTtfFile(data []byte, modTime time.Time, c *gin.Context) {
	c.Header("Content-Type", "application/x-font-ttf")
	checkLastModified(c.Writer, c.Request, modTime)
	c.Writer.Write(data)
}

func RespondOtfFile(data []byte, modTime time.Time, c *gin.Context) {
	c.Header("Content-Type", "application/x-font-otf")
	checkLastModified(c.Writer, c.Request, modTime)
	c.Writer.Write(data)
}

func RespondWoffFile(data []byte, modTime time.Time, c *gin.Context) {
	c.Header("Content-Type", "application/font-woff")
	checkLastModified(c.Writer, c.Request, modTime)
	c.Writer.Write(data)
}

func RespondWoff2File(data []byte, modTime time.Time, c *gin.Context) {
	c.Header("Content-Type", "application/font-woff2")
	checkLastModified(c.Writer, c.Request, modTime)
	c.Writer.Write(data)
}

func RespondEotFile(data []byte, modTime time.Time, c *gin.Context) {
	c.Header("Content-Type", "application/vnd.ms-fontobject")
	checkLastModified(c.Writer, c.Request, modTime)
	c.Writer.Write(data)
}

func RespondSvgFile(data []byte, modTime time.Time, c *gin.Context) {
	c.Header("Content-Type", "image/svg+xml")
	checkLastModified(c.Writer, c.Request, modTime)
	c.Writer.Write(data)
}

func ReadGzipCSSFile(path string, c *gin.Context) {

	c.Header("Content-Type", "text/css")
	c.Header("Content-Encoding", "gzip")
	c.File(path)

}

func RespondGzipCSSFile(data []byte, modTime time.Time, c *gin.Context) {
	c.Header("Content-Type", "text/css")
	c.Header("Content-Encoding", "gzip")
	checkLastModified(c.Writer, c.Request, modTime)
	c.Writer.Write(data)
}

func ReadPngFile(path string, c *gin.Context) {

	c.Header("Content-Type", "image/png")
	c.File(path)

}

// modtime is the modification time of the resource to be served, or IsZero().
// return value is whether this request is now complete.
func checkLastModified(w http.ResponseWriter, r *http.Request, modtime time.Time) bool {
	if modtime.IsZero() || modtime.Equal(unixEpochTime) {
		// If the file doesn't have a modtime (IsZero), or the modtime
		// is obviously garbage (Unix time == 0), then ignore modtimes
		// and don't process the If-Modified-Since header.
		return false
	}

	// The Date-Modified header truncates sub-second precision, so
	// use mtime < t+1s instead of mtime <= t to check for unmodified.
	if t, err := time.Parse(TimeFormat, r.Header.Get("If-Modified-Since")); err == nil && modtime.Before(t.Add(1*time.Second)) {
		h := w.Header()
		delete(h, "Content-Type")
		delete(h, "Content-Length")
		w.WriteHeader(StatusNotModified)
		return true
	}
	w.Header().Set("Last-Modified", modtime.UTC().Format(TimeFormat))
	return false
}
<|endoftext|>


<commit_before>package index

import (
	"fmt"
	. "github.com/balzaczyy/golucene/core/codec/spi"
	. "github.com/balzaczyy/golucene/core/index/model"
	"github.com/balzaczyy/golucene/core/store"
	"github.com/balzaczyy/golucene/core/util"
)

/* Default general purpose indexing chain, which handles indexing all types of fields */
type DefaultIndexingChain struct {
	bytesUsed  util.Counter
	docState   *docState
	docWriter  *DocumentsWriterPerThread
	fieldInfos *FieldInfosBuilder

	// Writes postings and term vectors:
	termsHash TermsHash

	storedFieldsWriter StoredFieldsWriter // lazy init
	lastStoredDocId    int

	fieldHash []*PerField

	nextFieldGen int64

	// Holds fields seen in each document
	fields []*PerField
}

func newDefaultIndexingChain(docWriter *DocumentsWriterPerThread) *DefaultIndexingChain {
	termVectorsWriter := newTermVectorsConsumer(docWriter)
	return &DefaultIndexingChain{
		docWriter:  docWriter,
		fieldInfos: docWriter.fieldInfos,
		docState:   docWriter.docState,
		bytesUsed:  docWriter._bytesUsed,
		termsHash:  newFreqProxTermsWriter(docWriter, termVectorsWriter),
		fields:     make([]*PerField, 1),
	}
}

// TODO: can we remove this lazy-init / make cleaner / do it another way...?
func (c *DefaultIndexingChain) initStoredFieldsWriter() (err error) {
	if c.storedFieldsWriter == nil {
		c.storedFieldsWriter, err = c.docWriter.codec.StoredFieldsFormat().FieldsWriter(
			c.docWriter.directory, c.docWriter.segmentInfo, store.IO_CONTEXT_DEFAULT)
	}
	return
}

func (c *DefaultIndexingChain) flush(state *SegmentWriteState) error {
	panic("not implemented yet")
}

/*
Catch up for all docs before us that had no stored fields, or hit
non-aborting errors before writing stored fields.
*/
func (c *DefaultIndexingChain) fillStoredFields(docId int) (err error) {
	for err == nil && c.lastStoredDocId < docId {
		err = c.startStoredFields()
		if err == nil {
			err = c.finishStoredFields()
		}
	}
	return
}

func (c *DefaultIndexingChain) abort() {
	// E.g. close any open files in the stored fields writer:
	if c.storedFieldsWriter != nil {
		c.storedFieldsWriter.Abort() // ignore error
	}

	// E.g. close any open files in the term vectors writer:
	c.termsHash.abort()

	for i, _ := range c.fieldHash {
		c.fieldHash[i] = nil
	}
}

/* Calls StoredFieldsWriter.startDocument, aborting the segment if it hits any error. */
func (c *DefaultIndexingChain) startStoredFields() (err error) {
	var success = false
	defer func() {
		if !success {
			c.docWriter.setAborting()
		}
	}()

	if err = c.initStoredFieldsWriter(); err != nil {
		return
	}
	if err = c.storedFieldsWriter.StartDocument(); err != nil {
		return
	}
	success = true

	c.lastStoredDocId++
	return nil
}

/* Calls StoredFieldsWriter.finishDocument(), aborting the segment if it hits any error. */
func (c *DefaultIndexingChain) finishStoredFields() error {
	var success = false
	defer func() {
		if !success {
			c.docWriter.setAborting()
		}
	}()
	if err := c.storedFieldsWriter.FinishDocument(); err != nil {
		return err
	}
	success = true
	return nil
}

func (c *DefaultIndexingChain) processDocument() (err error) {
	// How many indexed field names we've seen (collapses multiple
	// field instances by the same name):
	fieldCount := 0

	fieldGen := c.nextFieldGen
	c.nextFieldGen++

	// NOTE: we need to passes here, in case there are multi-valued
	// fields, because we must process all instances of a given field
	// at once, since the anlayzer is free to reuse TOkenStream across
	// fields (i.e., we cannot have more than one TokenStream running
	// "at once"):

	c.termsHash.startDocument()

	if err = c.fillStoredFields(c.docState.docID); err != nil {
		return
	}
	if err = c.startStoredFields(); err != nil {
		return
	}

	if err = func() error {
		defer func() {
			if !c.docWriter.aborting {
				// Finish each indexed field name seen in the document:
				for _, field := range c.fields[:fieldCount] {
					err = mergeError(err, field.finish())
				}
				err = mergeError(err, c.finishStoredFields())
			}
		}()

		for _, field := range c.docState.doc {
			if fieldCount, err = c.processField(field, fieldGen, fieldCount); err != nil {
				return err
			}
		}
		return nil
	}(); err != nil {
		return
	}

	var success = false
	defer func() {
		if !success {
			// Must abort, on the possibility that on-disk term vectors are now corrupt:
			c.docWriter.setAborting()
		}
	}()

	if err = c.termsHash.finishDocument(); err != nil {
		return
	}
	success = true
	return nil
}

func (c *DefaultIndexingChain) processField(field IndexableField,
	fieldGen int64, fieldCount int) (int, error) {

	var fieldName string = field.Name()
	var fieldType IndexableFieldType = field.FieldType()
	var fp *PerField

	// Invert indexed fields:
	if fieldType.Indexed() {

		// if the field omits norms, the boost cannot be indexed.
		if fieldType.OmitNorms() && field.Boost() != 1 {
			panic(fmt.Sprintf(
				"You cannot set an index-time boost: norms are omitted for field '%v'",
				fieldName))
		}

		fp = c.getOrAddField(fieldName, fieldType, true)
		first := fp.fieldGen != fieldGen
		if err := fp.invert(field, first); err != nil {
			return 0, err
		}

		if first {
			c.fields[fieldCount] = fp
			fieldCount++
			fp.fieldGen = fieldGen
		}
	} else {
		panic("not implemented yet")
	}

	// Add stored fields:
	if fieldType.Stored() {
		panic("not implemented yet")
	} else {
		panic("not implemented yet")
	}

	if dvType := fieldType.DocValueType(); int(dvType) != 0 {
		if fp == nil {
			panic("not implemented yet")
		}
		panic("not implemented yet")
	}

	return fieldCount, nil
}

func (c *DefaultIndexingChain) getOrAddField(name string,
	fieldType IndexableFieldType, invert bool) *PerField {
	panic("not implemented yet")
}

type PerField struct {
	*DefaultIndexingChain // acess at least docState, termsHash.

	fieldInfo  *FieldInfo
	similarity Similarity

	// We use this to know when a PerField is seen for the first time
	// in the current document.
	fieldGen int64
}

func newPerField(parent *DefaultIndexingChain,
	fieldInfo *FieldInfo, invert bool) *PerField {

	ans := &PerField{
		DefaultIndexingChain: parent,
		fieldInfo:            fieldInfo,
		similarity:           parent.docState.similarity,
		fieldGen:             -1,
	}
	if invert {
		ans.setInvertState()
	}
	return ans
}

func (f *PerField) setInvertState() {
	panic("not implemented yet")
}

func (f *PerField) finish() error {
	panic("not implemented yet")
}

/*
Inverts one field for one document; first is true if this is the
first time we are seeing this field name in this document.
*/
func (f *PerField) invert(field IndexableField, first bool) error {
	panic("not implemented yet")
}
<commit_msg>implement DefaultIndexingChain.getOrAddField()<commit_after>package index

import (
	"fmt"
	. "github.com/balzaczyy/golucene/core/codec/spi"
	. "github.com/balzaczyy/golucene/core/index/model"
	"github.com/balzaczyy/golucene/core/store"
	"github.com/balzaczyy/golucene/core/util"
)

/* Default general purpose indexing chain, which handles indexing all types of fields */
type DefaultIndexingChain struct {
	bytesUsed  util.Counter
	docState   *docState
	docWriter  *DocumentsWriterPerThread
	fieldInfos *FieldInfosBuilder

	// Writes postings and term vectors:
	termsHash TermsHash

	storedFieldsWriter StoredFieldsWriter // lazy init
	lastStoredDocId    int

	fieldHash []*PerField
	hashMask  int

	totalFieldCount int
	nextFieldGen    int64

	// Holds fields seen in each document
	fields []*PerField
}

func newDefaultIndexingChain(docWriter *DocumentsWriterPerThread) *DefaultIndexingChain {
	termVectorsWriter := newTermVectorsConsumer(docWriter)
	return &DefaultIndexingChain{
		docWriter:  docWriter,
		fieldInfos: docWriter.fieldInfos,
		docState:   docWriter.docState,
		bytesUsed:  docWriter._bytesUsed,
		termsHash:  newFreqProxTermsWriter(docWriter, termVectorsWriter),
		fieldHash:  make([]*PerField, 2),
		hashMask:   1,
		fields:     make([]*PerField, 1),
	}
}

// TODO: can we remove this lazy-init / make cleaner / do it another way...?
func (c *DefaultIndexingChain) initStoredFieldsWriter() (err error) {
	if c.storedFieldsWriter == nil {
		c.storedFieldsWriter, err = c.docWriter.codec.StoredFieldsFormat().FieldsWriter(
			c.docWriter.directory, c.docWriter.segmentInfo, store.IO_CONTEXT_DEFAULT)
	}
	return
}

func (c *DefaultIndexingChain) flush(state *SegmentWriteState) error {
	panic("not implemented yet")
}

/*
Catch up for all docs before us that had no stored fields, or hit
non-aborting errors before writing stored fields.
*/
func (c *DefaultIndexingChain) fillStoredFields(docId int) (err error) {
	for err == nil && c.lastStoredDocId < docId {
		err = c.startStoredFields()
		if err == nil {
			err = c.finishStoredFields()
		}
	}
	return
}

func (c *DefaultIndexingChain) abort() {
	// E.g. close any open files in the stored fields writer:
	if c.storedFieldsWriter != nil {
		c.storedFieldsWriter.Abort() // ignore error
	}

	// E.g. close any open files in the term vectors writer:
	c.termsHash.abort()

	for i, _ := range c.fieldHash {
		c.fieldHash[i] = nil
	}
}

func (c *DefaultIndexingChain) rehash() {
	panic("not implemented yet")
}

/* Calls StoredFieldsWriter.startDocument, aborting the segment if it hits any error. */
func (c *DefaultIndexingChain) startStoredFields() (err error) {
	var success = false
	defer func() {
		if !success {
			c.docWriter.setAborting()
		}
	}()

	if err = c.initStoredFieldsWriter(); err != nil {
		return
	}
	if err = c.storedFieldsWriter.StartDocument(); err != nil {
		return
	}
	success = true

	c.lastStoredDocId++
	return nil
}

/* Calls StoredFieldsWriter.finishDocument(), aborting the segment if it hits any error. */
func (c *DefaultIndexingChain) finishStoredFields() error {
	var success = false
	defer func() {
		if !success {
			c.docWriter.setAborting()
		}
	}()
	if err := c.storedFieldsWriter.FinishDocument(); err != nil {
		return err
	}
	success = true
	return nil
}

func (c *DefaultIndexingChain) processDocument() (err error) {
	// How many indexed field names we've seen (collapses multiple
	// field instances by the same name):
	fieldCount := 0

	fieldGen := c.nextFieldGen
	c.nextFieldGen++

	// NOTE: we need to passes here, in case there are multi-valued
	// fields, because we must process all instances of a given field
	// at once, since the anlayzer is free to reuse TOkenStream across
	// fields (i.e., we cannot have more than one TokenStream running
	// "at once"):

	c.termsHash.startDocument()

	if err = c.fillStoredFields(c.docState.docID); err != nil {
		return
	}
	if err = c.startStoredFields(); err != nil {
		return
	}

	if err = func() error {
		defer func() {
			if !c.docWriter.aborting {
				// Finish each indexed field name seen in the document:
				for _, field := range c.fields[:fieldCount] {
					err = mergeError(err, field.finish())
				}
				err = mergeError(err, c.finishStoredFields())
			}
		}()

		for _, field := range c.docState.doc {
			if fieldCount, err = c.processField(field, fieldGen, fieldCount); err != nil {
				return err
			}
		}
		return nil
	}(); err != nil {
		return
	}

	var success = false
	defer func() {
		if !success {
			// Must abort, on the possibility that on-disk term vectors are now corrupt:
			c.docWriter.setAborting()
		}
	}()

	if err = c.termsHash.finishDocument(); err != nil {
		return
	}
	success = true
	return nil
}

func (c *DefaultIndexingChain) processField(field IndexableField,
	fieldGen int64, fieldCount int) (int, error) {

	var fieldName string = field.Name()
	var fieldType IndexableFieldType = field.FieldType()
	var fp *PerField

	// Invert indexed fields:
	if fieldType.Indexed() {

		// if the field omits norms, the boost cannot be indexed.
		if fieldType.OmitNorms() && field.Boost() != 1 {
			panic(fmt.Sprintf(
				"You cannot set an index-time boost: norms are omitted for field '%v'",
				fieldName))
		}

		fp = c.getOrAddField(fieldName, fieldType, true)
		first := fp.fieldGen != fieldGen
		if err := fp.invert(field, first); err != nil {
			return 0, err
		}

		if first {
			c.fields[fieldCount] = fp
			fieldCount++
			fp.fieldGen = fieldGen
		}
	} else {
		panic("not implemented yet")
	}

	// Add stored fields:
	if fieldType.Stored() {
		panic("not implemented yet")
	} else {
		panic("not implemented yet")
	}

	if dvType := fieldType.DocValueType(); int(dvType) != 0 {
		if fp == nil {
			panic("not implemented yet")
		}
		panic("not implemented yet")
	}

	return fieldCount, nil
}

func (c *DefaultIndexingChain) getOrAddField(name string,
	fieldType IndexableFieldType, invert bool) *PerField {

	// Make sure we have a PerField allocated
	hashPos := hashstr(name) & c.hashMask
	fp := c.fieldHash[hashPos]
	for fp != nil && fp.fieldInfo.Name != name {
		fp = fp.next
	}

	if fp == nil {
		// First time we are seeing this field in this segment

		fi := c.fieldInfos.AddOrUpdate(name, fieldType)

		fp = newPerField(c, fi, invert)
		fp.next = c.fieldHash[hashPos]
		c.fieldHash[hashPos] = fp
		c.totalFieldCount++

		// At most 50% load factor:
		if c.totalFieldCount >= len(c.fieldHash)/2 {
			c.rehash()
		}

		if c.totalFieldCount > len(c.fieldHash) {
			newFields := make([]*PerField, util.Oversize(c.totalFieldCount, util.NUM_BYTES_OBJECT_REF))
			copy(newFields, c.fields)
			c.fields = newFields
		}

	} else {
		panic("not implemented yet")
	}

	return fp
}

const primeRK = 16777619

/* simple string hash used by Go strings package */
func hashstr(sep string) int {
	hash := uint32(0)
	for i := 0; i < len(sep); i++ {
		hash = hash*primeRK + uint32(sep[i])
	}
	return int(hash)
}

type PerField struct {
	*DefaultIndexingChain // acess at least docState, termsHash.

	fieldInfo  *FieldInfo
	similarity Similarity

	// We use this to know when a PerField is seen for the first time
	// in the current document.
	fieldGen int64

	// Used by the hash table
	next *PerField
}

func newPerField(parent *DefaultIndexingChain,
	fieldInfo *FieldInfo, invert bool) *PerField {

	ans := &PerField{
		DefaultIndexingChain: parent,
		fieldInfo:            fieldInfo,
		similarity:           parent.docState.similarity,
		fieldGen:             -1,
	}
	if invert {
		ans.setInvertState()
	}
	return ans
}

func (f *PerField) setInvertState() {
	panic("not implemented yet")
}

func (f *PerField) finish() error {
	panic("not implemented yet")
}

/*
Inverts one field for one document; first is true if this is the
first time we are seeing this field name in this document.
*/
func (f *PerField) invert(field IndexableField, first bool) error {
	panic("not implemented yet")
}
<|endoftext|>


<commit_before>package agent

import (
	"bufio"
	"io"

	"golang.org/x/crypto/ssh"
)

type Client struct {
	config  *ssh.ClientConfig
	session *ssh.Session
}

func NewClient(config *ssh.ClientConfig) *Client {
	return &Client{
		config: config,
	}
}

func (c *Client) Dial(endpoint string) error {
	conn, err := ssh.Dial("tcp4", endpoint, c.config)
	if err != nil {
		return err
	}

	session, err := conn.NewSession()
	if err != nil {
		return err
	}

	c.session = session
	return nil
}

func (c *Client) Close() error {
	if c.session == nil {
		return nil
	}
	return c.session.Close()
}

func (c *Client) Run(out chan string, command string) error {
	rd, err := c.session.StdoutPipe()
	if err != nil {
		return err
	}

	go func(out chan string, in io.Reader) {
		b := bufio.NewScanner(in)
		for b.Scan() {
			out <- b.Text()
		}
		close(out)
	}(out, rd)

	err = c.session.Start(command)
	if err != nil {
		return err
	}

	err = c.session.Wait()
	if err != nil {
		return err
	}

	c.Close()
	return nil
}
<commit_msg>Reworked ssh connection cleanup to teardown tcp connections properly<commit_after>package agent

import (
	"bufio"
	"io"

	"golang.org/x/crypto/ssh"
)

type Client struct {
	config  *ssh.ClientConfig
	session *ssh.Session
	conn    *ssh.Client
}

func NewClient(config *ssh.ClientConfig) *Client {
	return &Client{
		config: config,
	}
}

func (c *Client) Dial(endpoint string) error {
	conn, err := ssh.Dial("tcp4", endpoint, c.config)
	if err != nil {
		return err
	}

	session, err := conn.NewSession()
	if err != nil {
		conn.Close()
		return err
	}

	c.conn = conn
	c.session = session
	return nil
}

func (c *Client) Close() error {
	var sessErr, connErr error
	if c.conn != nil {
		if c.session != nil {
			sessErr = c.session.Close()
		}
		connErr = c.conn.Conn.Close()
	}
	if connErr != nil {
		return connErr
	}
	if sessErr != nil {
		return sessErr
	}
	return nil
}

func (c *Client) Run(out chan string, command string) error {
	rd, err := c.session.StdoutPipe()
	if err != nil {
		return err
	}

	go func(out chan string, in io.Reader) {
		b := bufio.NewScanner(in)
		for b.Scan() {
			out <- b.Text()
		}
		close(out)
	}(out, rd)

	err = c.session.Start(command)
	if err != nil {
		return err
	}

	err = c.session.Wait()
	if err != nil {
		return err
	}

	c.Close()
	return nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 Pani Networks
// All Rights Reserved.
//
// 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.

// Configuration related functions for Romana Agent service.
package agent

import (
	"github.com/romana/core/common"
	"github.com/romana/core/topology"

	"log"
	"net"
)

// Config holds the agent's current configuration.
// This consists of data parsed from the config file as well as
// runtime or discovered configuration, such as the network
// config of the current host.
type NetworkConfig struct {
	// Current host network configuration
	currentHostIP        net.IP
	currentHostGW        net.IP
	currentHostGWNet     net.IPNet
	currentHostGWNetSize int
	// index of the current host in POC config file
	currentHostIndex int
	hosts            []common.HostMessage
	dc               topology.Datacenter
}

// EndpointNetmaskSize returns integer value (aka size) of endpoint netmask.
func (c *NetworkConfig) EndpointNetmaskSize() uint64 {
	// TODO make this depend on the IP version
	return 32 - uint64(c.dc.EndpointSpaceBits)
}

// PNetCIDR returns pseudo net cidr in net.IPNet format.
func (c *NetworkConfig) PNetCIDR() (cidr *net.IPNet, err error) {
	_, cidr, err = net.ParseCIDR(c.dc.Cidr)
	return
}

// TenantBits returns tenant bits value from POC config.
func (c *NetworkConfig) TenantBits() uint {
	return c.dc.TenantBits
}

// SegmentBits returns segment bits value from POC config.
func (c *NetworkConfig) SegmentBits() uint {
	return c.dc.SegmentBits
}

// EndpointBits returns endpoint bits value from POC config.
func (c *NetworkConfig) EndpointBits() uint {
	return c.dc.EndpointBits
}

// IdentifyCurrentHost is a function that discovers network configuration
// of the host we are running at.
// We need to know public IP and pani gateway IP of the current host.
// This is done by matching current host IP addresses against what topology
// service thinks the host address is.
// If no match found we assume we are running on host which is not
// the part of pani setup and spit error out.
func (agent Agent) identifyCurrentHost() error {
	addrs, _ := net.InterfaceAddrs()

	topologyUrl, err := common.GetServiceUrl(agent.config.Common.Api.RootServiceUrl, "topology")
	if err != nil {
		return agentError(err)
	}

	client, err := common.NewRestClient(topologyUrl)
	if err != nil {
		return agentError(err)
	}
	index := common.IndexResponse{}
	err = client.Get(topologyUrl, &index)
	if err != nil {
		return agentError(err)
	}
	dcUrl := index.Links.FindByRel("datacenter")
	dc := topology.Datacenter{}
	err = client.Get(dcUrl, &dc)
	if err != nil {
		return agentError(err)
	}

	hostUrl := index.Links.FindByRel("host-list")
	hosts := []common.HostMessage{}
	err = client.Get(hostUrl, &hosts)
	if err != nil {
		return agentError(err)
	}

	// Yeah, nested loop. Can't think anything better.
	for i := range addrs {
		// TODO This condition required to break from outer loop
		// when inner one *broken*. Don't look pretty,
		// but do we justify use of labels for that case ?
		if agent.networkConfig.currentHostGW != nil {
			break
		}

		romanaIp, _, err := net.ParseCIDR(addrs[i].String())
		if err != nil {
			log.Printf("Failed to parse %s", addrs[i].String())
			return err
		}
		agent.networkConfig.hosts = hosts
		for j := range hosts {
			_, romanaNet, err := net.ParseCIDR(hosts[j].RomanaIp)
			if err != nil {
				log.Printf("Failed to parse %s", hosts[j].RomanaIp)
				return err
			}
			log.Printf("Init:IdentifyCurrentHost %s belongs to %s %s",
				romanaNet,
				romanaIp,
				romanaNet.Contains(romanaIp))

			if romanaNet.Contains(romanaIp) {
				agent.networkConfig.currentHostIP = net.ParseIP(hosts[j].Ip)
				agent.networkConfig.currentHostGW = romanaIp
				agent.networkConfig.currentHostGWNet = *romanaNet
				agent.networkConfig.currentHostGWNetSize, _ = romanaNet.Mask.Size()
				agent.networkConfig.currentHostIndex = j
				break
			}
		}
	}
	if agent.networkConfig.currentHostGW == nil {
		return wrongHostError()
	}
	return nil
}
<commit_msg>Comments on config.go<commit_after>// Copyright (c) 2015 Pani Networks
// All Rights Reserved.
//
// 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.

// Configuration related functions for Romana Agent service.
package agent

import (
	"github.com/romana/core/common"
	"github.com/romana/core/topology"

	"log"
	"net"
)

// NetworkConfig holds the agent's current configuration.
// This consists of data parsed from the config file as well as
// runtime or discovered configuration, such as the network
// config of the current host.
type NetworkConfig struct {
	// Current host network configuration
	currentHostIP        net.IP
	currentHostGW        net.IP
	currentHostGWNet     net.IPNet
	currentHostGWNetSize int
	// index of the current host in POC config file
	currentHostIndex int
	hosts            []common.HostMessage
	dc               topology.Datacenter
}

// EndpointNetmaskSize returns integer value (aka size) of endpoint netmask.
func (c *NetworkConfig) EndpointNetmaskSize() uint64 {
	// TODO make this depend on the IP version
	return 32 - uint64(c.dc.EndpointSpaceBits)
}

// PNetCIDR returns pseudo net cidr in net.IPNet format.
func (c *NetworkConfig) PNetCIDR() (cidr *net.IPNet, err error) {
	_, cidr, err = net.ParseCIDR(c.dc.Cidr)
	return
}

// TenantBits returns tenant bits value from POC config.
func (c *NetworkConfig) TenantBits() uint {
	return c.dc.TenantBits
}

// SegmentBits returns segment bits value from POC config.
func (c *NetworkConfig) SegmentBits() uint {
	return c.dc.SegmentBits
}

// EndpointBits returns endpoint bits value from POC config.
func (c *NetworkConfig) EndpointBits() uint {
	return c.dc.EndpointBits
}

// IdentifyCurrentHost is a function that discovers network configuration
// of the host we are running at.
// We need to know public IP and pani gateway IP of the current host.
// This is done by matching current host IP addresses against what topology
// service thinks the host address is.
// If no match found we assume we are running on host which is not
// the part of pani setup and spit error out.
func (agent Agent) identifyCurrentHost() error {
	addrs, _ := net.InterfaceAddrs()

	topologyUrl, err := common.GetServiceUrl(agent.config.Common.Api.RootServiceUrl, "topology")
	if err != nil {
		return agentError(err)
	}

	client, err := common.NewRestClient(topologyUrl)
	if err != nil {
		return agentError(err)
	}
	index := common.IndexResponse{}
	err = client.Get(topologyUrl, &index)
	if err != nil {
		return agentError(err)
	}
	dcUrl := index.Links.FindByRel("datacenter")
	dc := topology.Datacenter{}
	err = client.Get(dcUrl, &dc)
	if err != nil {
		return agentError(err)
	}

	hostUrl := index.Links.FindByRel("host-list")
	hosts := []common.HostMessage{}
	err = client.Get(hostUrl, &hosts)
	if err != nil {
		return agentError(err)
	}

	// Yeah, nested loop. Can't think anything better.
	for i := range addrs {
		// TODO This condition required to break from outer loop
		// when inner one *broken*. Don't look pretty,
		// but do we justify use of labels for that case ?
		if agent.networkConfig.currentHostGW != nil {
			break
		}

		romanaIp, _, err := net.ParseCIDR(addrs[i].String())
		if err != nil {
			log.Printf("Failed to parse %s", addrs[i].String())
			return err
		}
		agent.networkConfig.hosts = hosts
		for j := range hosts {
			_, romanaNet, err := net.ParseCIDR(hosts[j].RomanaIp)
			if err != nil {
				log.Printf("Failed to parse %s", hosts[j].RomanaIp)
				return err
			}
			log.Printf("Init:IdentifyCurrentHost %s belongs to %s %s",
				romanaNet,
				romanaIp,
				romanaNet.Contains(romanaIp))

			if romanaNet.Contains(romanaIp) {
				agent.networkConfig.currentHostIP = net.ParseIP(hosts[j].Ip)
				agent.networkConfig.currentHostGW = romanaIp
				agent.networkConfig.currentHostGWNet = *romanaNet
				agent.networkConfig.currentHostGWNetSize, _ = romanaNet.Mask.Size()
				agent.networkConfig.currentHostIndex = j
				break
			}
		}
	}
	if agent.networkConfig.currentHostGW == nil {
		return wrongHostError()
	}
	return nil
}
<|endoftext|>


<commit_before>package agents

import "reflect"

type (
	// Agent should be implemented by all agents.
	Agent interface {
		// Check should run the agents check.
		Check() (interface{}, error)
	}
)

var (
	agents = make(map[string]reflect.Type)
)

// RegisterAgent will register the agent with the agent store.
func RegisterAgent(name string, agent interface{}) {
	_, found := agents[name]
	if found {
		panic("An agent with that name already exists")
	}

	agents[name] = reflect.TypeOf(agent)
}

// GetAgent will return an agent registred with the name.
func GetAgent(name string) Agent {
	return reflect.New(agents[name]).Interface().(Agent)
}
<commit_msg>Added ListAgents() to list all agents for helping when creating a GUI for adding checks.<commit_after>package agents

import (
	"reflect"
	"strings"
)

type (
	// Agent should be implemented by all agents.
	Agent interface {
		// Check should run the agents check.
		Check() (interface{}, error)
	}

	// ArgumentDescription contains everything needed for creating a GUI for
	// configuring an agent.
	ArgumentDescription struct {
		Name        string   `json:"name"`
		Type        string   `json:"type"`
		Description string   `json:"description"`
		EnumValues  []string `json:"enum"`
	}

	// AgentDescription describes an agent.
	AgentDescription struct {
		Name      string                `json:"name"`
		Arguments []ArgumentDescription `json:"arguments"`
	}
)

var (
	agents = make(map[string]reflect.Type)
)

// RegisterAgent will register the agent with the agent store.
func RegisterAgent(name string, agent interface{}) {
	_, found := agents[name]
	if found {
		panic("An agent with that name already exists")
	}

	agents[name] = reflect.TypeOf(agent)
}

// GetAgent will return an agent registred with the name.
func GetAgent(name string) Agent {
	return reflect.New(agents[name]).Interface().(Agent)
}

// ListAgents will return a list of all agents.
func ListAgents() []AgentDescription {
	list := make([]AgentDescription, 0, len(agents))

	for name, typ := range agents {
		list = append(list, AgentDescription{
			Name:      name,
			Arguments: getArguments(typ),
		})
	}

	return list
}

func getArguments(elem reflect.Type) []ArgumentDescription {
	parameters := []ArgumentDescription{}

	l := elem.NumField()

	for i := 0; i < l; i++ {
		f := elem.Field(i)

		jsonName := f.Tag.Get("json")

		if f.Anonymous {
			parameters = append(parameters, getArguments(f.Type)...)
		} else if jsonName != "" {
			p := ArgumentDescription{}

			p.Name = jsonName
			p.Type = f.Type.String()
			p.Description = f.Tag.Get("description")
			enum := f.Tag.Get("enum")
			if enum != "" {
				p.EnumValues = strings.Split(enum, ",")
				p.Type = "enum"
			} else {
				p.EnumValues = []string{}
			}

			parameters = append(parameters, p)
		}
	}

	return parameters
}
<|endoftext|>


<commit_before>// +build linux

package gopsutil

import (
	"strconv"
	"strings"
	"syscall"
)

func VirtualMemory() (*VirtualMemoryStat, error) {
	filename := "/proc/meminfo"
	lines, _ := readLines(filename)

	ret := &VirtualMemoryStat{}
	for _, line := range lines {
		fields := strings.Split(line, ":")
		if len(fields) != 2 {
			continue
		}
		key := strings.TrimSpace(fields[0])
		value := strings.TrimSpace(fields[1])
		value = strings.Replace(value, " kB", "", -1)

		t, err := strconv.ParseUint(value, 10, 64)
		if err != nil {
			return ret, err
		}
		switch key {
		case "MemTotal":
			ret.Total = t * 1000
		case "MemFree":
			ret.Free = t * 1000
		case "Buffers":
			ret.Buffers = t * 1000
		case "Cached":
			ret.Cached = t * 1000
		case "Active":
			ret.Active = t * 1000
		case "Inactive":
			ret.Inactive = t * 1000
		}
	}
	ret.Available = ret.Free + ret.Buffers + ret.Cached
	ret.Used = ret.Total - ret.Free
	ret.UsedPercent = float64(ret.Total-ret.Available) / float64(ret.Total) * 100.0

	return ret, nil
}

func SwapMemory() (*SwapMemoryStat, error) {
	sysinfo := &syscall.Sysinfo_t{}

	if err := syscall.Sysinfo(sysinfo); err != nil {
		return nil, err
	}
	ret := &SwapMemoryStat{
		Total: uint64(sysinfo.Totalswap),
		Free:  uint64(sysinfo.Freeswap),
	}
	ret.Used = ret.Total - ret.Free
	//check Infinity
	if ret.Total != 0 {
		ret.UsedPercent = float64(ret.Total-ret.Free) / float64(ret.Total) * 100.0
	} else {
		ret.UsedPercent = 0
	}

	return ret, nil
}
<commit_msg>[linux] fill SwapMemoryStat.Sin/Sout from /proc/vmstat<commit_after>// +build linux

package gopsutil

import (
	"strconv"
	"strings"
	"syscall"
)

func VirtualMemory() (*VirtualMemoryStat, error) {
	filename := "/proc/meminfo"
	lines, _ := readLines(filename)

	ret := &VirtualMemoryStat{}
	for _, line := range lines {
		fields := strings.Split(line, ":")
		if len(fields) != 2 {
			continue
		}
		key := strings.TrimSpace(fields[0])
		value := strings.TrimSpace(fields[1])
		value = strings.Replace(value, " kB", "", -1)

		t, err := strconv.ParseUint(value, 10, 64)
		if err != nil {
			return ret, err
		}
		switch key {
		case "MemTotal":
			ret.Total = t * 1000
		case "MemFree":
			ret.Free = t * 1000
		case "Buffers":
			ret.Buffers = t * 1000
		case "Cached":
			ret.Cached = t * 1000
		case "Active":
			ret.Active = t * 1000
		case "Inactive":
			ret.Inactive = t * 1000
		}
	}
	ret.Available = ret.Free + ret.Buffers + ret.Cached
	ret.Used = ret.Total - ret.Free
	ret.UsedPercent = float64(ret.Total-ret.Available) / float64(ret.Total) * 100.0

	return ret, nil
}

func SwapMemory() (*SwapMemoryStat, error) {
	sysinfo := &syscall.Sysinfo_t{}

	if err := syscall.Sysinfo(sysinfo); err != nil {
		return nil, err
	}
	ret := &SwapMemoryStat{
		Total: uint64(sysinfo.Totalswap),
		Free:  uint64(sysinfo.Freeswap),
	}
	ret.Used = ret.Total - ret.Free
	//check Infinity
	if ret.Total != 0 {
		ret.UsedPercent = float64(ret.Total-ret.Free) / float64(ret.Total) * 100.0
	} else {
		ret.UsedPercent = 0
	}
	lines, _ := readLines("/proc/vmstat")
	for _, l := range lines {
		fields := strings.Fields(l)
		if len(fields) < 2 {
			continue
		}
		switch fields[0] {
		case "pswpin":
			value, err := strconv.ParseUint(fields[1], 10, 64)
			if err != nil {
				continue
			}
			ret.Sin = value * 4 * 1024
		case "pswpout":
			value, err := strconv.ParseUint(fields[1], 10, 64)
			if err != nil {
				continue
			}
			ret.Sout = value * 4 * 1024
		}
	}
	return ret, nil
}
<|endoftext|>


<commit_before>// +build !windows

package main

import (
	"io"
	"os"
	"os/signal"
	"syscall"

	"github.com/gorilla/websocket"

	"github.com/lxc/lxd"
	"github.com/lxc/lxd/shared"
)

func (c *execCmd) getStdout() io.WriteCloser {
	return os.Stdout
}

func (c *execCmd) controlSocketHandler(d *lxd.Client, control *websocket.Conn) {
	ch := make(chan os.Signal)
	signal.Notify(ch, syscall.SIGWINCH)

	for {
		sig := <-ch

		shared.LogDebugf("Received '%s signal', updating window geometry.", sig)

		err := c.sendTermSize(control)
		if err != nil {
			shared.LogDebugf("error setting term size %s", err)
			break
		}
	}

	closeMsg := websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")
	control.WriteMessage(websocket.CloseMessage, closeMsg)
}
<commit_msg>lxc/exec_unix: add signals to forward<commit_after>// +build !windows

package main

import (
	"io"
	"os"
	"os/signal"
	"syscall"

	"github.com/gorilla/websocket"

	"github.com/lxc/lxd"
	"github.com/lxc/lxd/shared"
)

func (c *execCmd) getStdout() io.WriteCloser {
	return os.Stdout
}

func (c *execCmd) controlSocketHandler(d *lxd.Client, control *websocket.Conn) {
	ch := make(chan os.Signal)
	signal.Notify(ch,
		syscall.SIGWINCH,
		syscall.SIGTERM,
		syscall.SIGHUP,
		syscall.SIGINT,
		syscall.SIGQUIT,
		syscall.SIGABRT,
		syscall.SIGTSTP,
		syscall.SIGTTIN,
		syscall.SIGTTOU,
		syscall.SIGUSR1,
		syscall.SIGUSR2,
		syscall.SIGSEGV,
		syscall.SIGCONT)

	closeMsg := websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")
	defer control.WriteMessage(websocket.CloseMessage, closeMsg)

	for {
		sig := <-ch
		switch sig {
		case syscall.SIGWINCH:
			shared.LogDebugf("Received '%s signal', updating window geometry.", sig)
			err := c.sendTermSize(control)
			if err != nil {
				shared.LogDebugf("error setting term size %s", err)
				return
			}
		case syscall.SIGTERM:
			shared.LogDebugf("Received '%s signal', forwarding to executing program.", sig)
			err := c.forwardSignal(control, syscall.SIGTERM)
			if err != nil {
				shared.LogDebugf("Failed to forward signal '%s'.", syscall.SIGTERM)
				return
			}
		case syscall.SIGHUP:
			shared.LogDebugf("Received '%s signal', forwarding to executing program.", sig)
			err := c.forwardSignal(control, syscall.SIGHUP)
			if err != nil {
				shared.LogDebugf("Failed to forward signal '%s'.", syscall.SIGHUP)
				return
			}
		case syscall.SIGINT:
			shared.LogDebugf("Received '%s signal', forwarding to executing program.", sig)
			err := c.forwardSignal(control, syscall.SIGINT)
			if err != nil {
				shared.LogDebugf("Failed to forward signal '%s'.", syscall.SIGINT)
				return
			}
		case syscall.SIGQUIT:
			shared.LogDebugf("Received '%s signal', forwarding to executing program.", sig)
			err := c.forwardSignal(control, syscall.SIGQUIT)
			if err != nil {
				shared.LogDebugf("Failed to forward signal '%s'.", syscall.SIGQUIT)
				return
			}
		case syscall.SIGABRT:
			shared.LogDebugf("Received '%s signal', forwarding to executing program.", sig)
			err := c.forwardSignal(control, syscall.SIGABRT)
			if err != nil {
				shared.LogDebugf("Failed to forward signal '%s'.", syscall.SIGABRT)
				return
			}
		case syscall.SIGTSTP:
			shared.LogDebugf("Received '%s signal', forwarding to executing program.", sig)
			err := c.forwardSignal(control, syscall.SIGTSTP)
			if err != nil {
				shared.LogDebugf("Failed to forward signal '%s'.", syscall.SIGTSTP)
				return
			}
		case syscall.SIGTTIN:
			shared.LogDebugf("Received '%s signal', forwarding to executing program.", sig)
			err := c.forwardSignal(control, syscall.SIGTTIN)
			if err != nil {
				shared.LogDebugf("Failed to forward signal '%s'.", syscall.SIGTTIN)
				return
			}
		case syscall.SIGTTOU:
			shared.LogDebugf("Received '%s signal', forwarding to executing program.", sig)
			err := c.forwardSignal(control, syscall.SIGTTOU)
			if err != nil {
				shared.LogDebugf("Failed to forward signal '%s'.", syscall.SIGTTOU)
				return
			}
		case syscall.SIGUSR1:
			shared.LogDebugf("Received '%s signal', forwarding to executing program.", sig)
			err := c.forwardSignal(control, syscall.SIGUSR1)
			if err != nil {
				shared.LogDebugf("Failed to forward signal '%s'.", syscall.SIGUSR1)
				return
			}
		case syscall.SIGUSR2:
			shared.LogDebugf("Received '%s signal', forwarding to executing program.", sig)
			err := c.forwardSignal(control, syscall.SIGUSR2)
			if err != nil {
				shared.LogDebugf("Failed to forward signal '%s'.", syscall.SIGUSR2)
				return
			}
		case syscall.SIGSEGV:
			shared.LogDebugf("Received '%s signal', forwarding to executing program.", sig)
			err := c.forwardSignal(control, syscall.SIGSEGV)
			if err != nil {
				shared.LogDebugf("Failed to forward signal '%s'.", syscall.SIGSEGV)
				return
			}
		case syscall.SIGCONT:
			shared.LogDebugf("Received '%s signal', forwarding to executing program.", sig)
			err := c.forwardSignal(control, syscall.SIGCONT)
			if err != nil {
				shared.LogDebugf("Failed to forward signal '%s'.", syscall.SIGCONT)
				return
			}
		default:
			break
		}
	}
}
<|endoftext|>