<commit_before>package main

import (
	"./subtitle"
	"errors"
	"fmt"
	"github.com/0xe2-0x9a-0x9b/Go-SDL/sdl"
	"github.com/0xe2-0x9a-0x9b/Go-SDL/ttf"
	"log"
	"sort"
	"strings"
	"time"
)

const (
	DEFAULT_FONT_PATH = "/usr/share/fonts/truetype/nanum/NanumGothicBold.ttf"
	DEFAULT_FONT_SIZE = 60
)

var (
	BG_COLOR    = sdl.Color{0, 0, 0, 0}
	TEXT_COLOR  = sdl.Color{255, 255, 255, 0}
	waitFinishC = make(chan bool)
)

type sdlCtx struct {
	surface *sdl.Surface
	w, h    int

	currScript *subtitle.Script
	font       *ttf.Font
	lineHeight int

	fontSize int
	fontPath string
}

func NewSdlContext(w, h int) *sdlCtx {
	if sdl.Init(sdl.INIT_EVERYTHING) != 0 {
		log.Fatal("failed to init sdl", sdl.GetError())
		return nil
	}

	if ttf.Init() != 0 {
		log.Fatal("failed to init ttf", sdl.GetError())
		return nil
	}

	var ctx sdlCtx
	if err := ctx.setSurface(w, h); err != nil {
		log.Fatal(err)
	}

	var vInfo = sdl.GetVideoInfo()
	log.Println("HW_available = ", vInfo.HW_available)
	log.Println("WM_available = ", vInfo.WM_available)
	log.Println("Video_mem = ", vInfo.Video_mem, "kb")

	title := "Subtitle Player"
	icon := "" // path/to/icon
	sdl.WM_SetCaption(title, icon)

	sdl.EnableUNICODE(1)

	go func() {
	EVENT_LOOP:
		for {
			err := ctx.handelEvent()
			if err != nil {
				fmt.Println(err)
				break EVENT_LOOP
			}
		}
		log.Println("sdl: exit event loop")
		quitC <- true
	}()

	return &ctx
}

func (c *sdlCtx) Release() {
	if c.font != nil {
		c.font.Close()
	}
	if c.surface != nil {
		c.surface.Free()
	}
	ttf.Quit()
	sdl.Quit()

	/* log.Printf("sdl Released...") */
}

func (c *sdlCtx) DisplayScript(script *subtitle.Script) {
	c.displayScript(script, true, false)
}

func (c *sdlCtx) Clear() {
	if c.currScript == nil {
		return
	}
	log.Println("clear")
	c.surface.FillRect(nil, 0 /* BG_COLOR */)
	c.surface.Flip()
	c.currScript = nil
}

func (c *sdlCtx) setFont(path string, size int) error {
	if size < 10 {
		log.Println("set font size to minimum, 10")
		size = 10
	}

	c.font = ttf.OpenFont(path, size)
	if c.font == nil {
		errMsg := fmt.Sprintf("failed to open font from %s: %s",
			path, sdl.GetError())
		return errors.New(errMsg)
	}

	c.fontSize = size
	c.fontPath = path
	c.lineHeight = c.font.LineSkip()

	log.Println(c.fontSize, c.lineHeight)
	/* ctx.font.SetStyle(ttf.STYLE_UNDERLINE) */
	return nil
}

func (c *sdlCtx) changeFontSize(by int) {
	if c.font == nil {
		return
	}
	c.setFont(c.fontPath, c.fontSize+by)
	c.displayScript(c.currScript, false, true)
}

func (c *sdlCtx) setSurface(w, h int) error {
	log.Printf("setSurface to %dx%d", w, h)
	c.surface = sdl.SetVideoMode(w, h, 32, sdl.RESIZABLE) /* sdl.FULLSCREEN */
	if c.surface == nil {
		errMsg := fmt.Sprintf("sdl: failed to set video to %dx%d: %s",
			w, h, sdl.GetError())
		return errors.New(errMsg)
	}

	c.w, c.h = w, h
	if c.currScript != nil {
		c.displayScript(c.currScript, false, true)
	}

	return nil
}

func (c *sdlCtx) handelEvent() error {
	// KeySym to time.Duration mapping
	kmVias := map[uint32]time.Duration{
		sdl.K_z:     -100 * time.Microsecond,
		sdl.K_x:     +100 * time.Microsecond,
		sdl.K_LEFT:  -1 * time.Second,
		sdl.K_RIGHT: +1 * time.Second,
		sdl.K_DOWN:  -10 * time.Second,
		sdl.K_UP:    +10 * time.Second,
	}

	kmFontSize := map[uint32]int{
		sdl.K_PLUS:     +5,
		sdl.K_KP_PLUS:  +5,
		sdl.K_MINUS:    -5,
		sdl.K_KP_MINUS: -5,
	}

	kmNavScript := map[uint32]int{
		sdl.K_SPACE: 0,
		// sdl. : -1,
		// sdl. : +1,
	}

	select {
	case event := <-sdl.Events:
		/* log.Printf("%#v\n", event) */
		switch e := event.(type) {
		case sdl.QuitEvent:
			return errors.New("sdl: received QuitEvent")

		case sdl.ResizeEvent:
			if err := c.setSurface(int(e.W), int(e.H)); err != nil {
				log.Fatal(err)
			}

		case sdl.KeyboardEvent:
			// Ignore release key
			if e.State == 0 {
				return nil
			}

			keysym := e.Keysym.Sym
			// tune timestamp
			if vias, ok := kmVias[keysym]; ok {
				viasC <- vias
				break
			}
			// tune font size
			if vias, ok := kmFontSize[keysym]; ok {
				c.changeFontSize(vias)
				break
			}

			// pause/resume
			if vias, ok := kmNavScript[keysym]; ok {
				log.Println("TODO: nav vias=", vias)
				navC <- vias
				break
			}
			log.Printf("Sim:%08x, Mod:%04x, Unicode:%02x, %t\n",
				e.Keysym.Sym, e.Keysym.Mod, e.Keysym.Unicode,
				e.Keysym.Unicode)
		}
	}
	return nil
}

func (c *sdlCtx) displayScript(script *subtitle.Script,
	andClear bool, forceUpdate bool) {
	if forceUpdate == false && c.currScript == script {
		return
	}
	c.currScript = script

	log.Printf("display %s", script.Text)

	if c.font == nil {
		log.Println("set default font")
		err := c.setFont(DEFAULT_FONT_PATH, DEFAULT_FONT_SIZE)
		if err != nil {
			log.Fatal("failed to set default font")
			return
		}
	}

	c.surface.FillRect(nil, 0 /* BG_COLOR */)
	offsetX := 10
	offsetY := 10

	for _, line := range strings.Split(script.Text, "\n") {
		runeLine := []rune(line)
		runeLineLen := len(runeLine)
		runeLineStart := 0

		for runeLineStart != runeLineLen {
			/* log.Println("start =", runeLineStart, "len =", runeLineLen) */
			runeSubLine := runeLine[runeLineStart:]
			i := sort.Search(len(runeSubLine), func(i int) bool {
				w, _, _ := c.font.SizeUTF8(string(runeSubLine[:i]))
				return (w - 20) >= c.w
			})
			/* log.Println("runeSubLine=", string(runeSubLine)) */

			if i != len(runeSubLine) && i > 1 {
				i -= 1
			}
			if i > runeLineLen {
				i = runeLineLen
			}
			/* log.Println("returned i=", i) */

			subline := string(runeLine[runeLineStart : runeLineStart+i])
			subline = strings.TrimSpace(subline)
			/* log.Println("subline=", subline) */
			runeLineStart += i
			if runeLineStart > runeLineLen {
				runeLineStart = runeLineLen
			}

			w, _, err := c.font.SizeUTF8(subline)
			if err != 0 {
				log.Fatal("Failed to get size of the font")
			}
			offsetX = (c.w - w) / 2

			glypse := ttf.RenderUTF8_Blended(c.font, subline, TEXT_COLOR)
			lt := sdl.Rect{int16(offsetX), int16(offsetY), 0, 0}
			c.surface.Blit(&lt, glypse, nil)
			offsetY += c.lineHeight
		}

	}
	c.surface.Flip()

	if andClear == false {
		return
	}

	go func() {
		<-time.After(script.Duration())
		if c.currScript != nil && c.currScript == script {
			c.surface.FillRect(nil, 0 /* BG_COLOR */)
			c.surface.Flip()
		}
	}()
}
<commit_msg>Show text without markups<commit_after>package main

import (
	"./subtitle"
	"errors"
	"fmt"
	"github.com/0xe2-0x9a-0x9b/Go-SDL/sdl"
	"github.com/0xe2-0x9a-0x9b/Go-SDL/ttf"
	"log"
	"sort"
	"strings"
	"time"
)

const (
	DEFAULT_FONT_PATH = "/usr/share/fonts/truetype/nanum/NanumGothicBold.ttf"
	DEFAULT_FONT_SIZE = 60
)

var (
	BG_COLOR    = sdl.Color{0, 0, 0, 0}
	TEXT_COLOR  = sdl.Color{255, 255, 255, 0}
	waitFinishC = make(chan bool)
)

type sdlCtx struct {
	surface *sdl.Surface
	w, h    int

	currScript *subtitle.Script
	font       *ttf.Font
	lineHeight int

	fontSize int
	fontPath string
}

func NewSdlContext(w, h int) *sdlCtx {
	if sdl.Init(sdl.INIT_EVERYTHING) != 0 {
		log.Fatal("failed to init sdl", sdl.GetError())
		return nil
	}

	if ttf.Init() != 0 {
		log.Fatal("failed to init ttf", sdl.GetError())
		return nil
	}

	var ctx sdlCtx
	if err := ctx.setSurface(w, h); err != nil {
		log.Fatal(err)
	}

	var vInfo = sdl.GetVideoInfo()
	log.Println("HW_available = ", vInfo.HW_available)
	log.Println("WM_available = ", vInfo.WM_available)
	log.Println("Video_mem = ", vInfo.Video_mem, "kb")

	title := "Subtitle Player"
	icon := "" // path/to/icon
	sdl.WM_SetCaption(title, icon)

	sdl.EnableUNICODE(1)

	go func() {
	EVENT_LOOP:
		for {
			err := ctx.handelEvent()
			if err != nil {
				fmt.Println(err)
				break EVENT_LOOP
			}
		}
		log.Println("sdl: exit event loop")
		quitC <- true
	}()

	return &ctx
}

func (c *sdlCtx) Release() {
	if c.font != nil {
		c.font.Close()
	}
	if c.surface != nil {
		c.surface.Free()
	}
	ttf.Quit()
	sdl.Quit()

	/* log.Printf("sdl Released...") */
}

func (c *sdlCtx) DisplayScript(script *subtitle.Script) {
	c.displayScript(script, true, false)
}

func (c *sdlCtx) Clear() {
	if c.currScript == nil {
		return
	}
	log.Println("clear")
	c.surface.FillRect(nil, 0 /* BG_COLOR */)
	c.surface.Flip()
	c.currScript = nil
}

func (c *sdlCtx) setFont(path string, size int) error {
	if size < 10 {
		log.Println("set font size to minimum, 10")
		size = 10
	}

	c.font = ttf.OpenFont(path, size)
	if c.font == nil {
		errMsg := fmt.Sprintf("failed to open font from %s: %s",
			path, sdl.GetError())
		return errors.New(errMsg)
	}

	c.fontSize = size
	c.fontPath = path
	c.lineHeight = c.font.LineSkip()

	log.Println(c.fontSize, c.lineHeight)
	/* ctx.font.SetStyle(ttf.STYLE_UNDERLINE) */
	return nil
}

func (c *sdlCtx) changeFontSize(by int) {
	if c.font == nil {
		return
	}
	c.setFont(c.fontPath, c.fontSize+by)
	c.displayScript(c.currScript, false, true)
}

func (c *sdlCtx) setSurface(w, h int) error {
	log.Printf("setSurface to %dx%d", w, h)
	c.surface = sdl.SetVideoMode(w, h, 32, sdl.RESIZABLE) /* sdl.FULLSCREEN */
	if c.surface == nil {
		errMsg := fmt.Sprintf("sdl: failed to set video to %dx%d: %s",
			w, h, sdl.GetError())
		return errors.New(errMsg)
	}

	c.w, c.h = w, h
	if c.currScript != nil {
		c.displayScript(c.currScript, false, true)
	}

	return nil
}

func (c *sdlCtx) handelEvent() error {
	// KeySym to time.Duration mapping
	kmVias := map[uint32]time.Duration{
		sdl.K_z:     -100 * time.Microsecond,
		sdl.K_x:     +100 * time.Microsecond,
		sdl.K_LEFT:  -1 * time.Second,
		sdl.K_RIGHT: +1 * time.Second,
		sdl.K_DOWN:  -10 * time.Second,
		sdl.K_UP:    +10 * time.Second,
	}

	kmFontSize := map[uint32]int{
		sdl.K_PLUS:     +5,
		sdl.K_KP_PLUS:  +5,
		sdl.K_MINUS:    -5,
		sdl.K_KP_MINUS: -5,
	}

	kmNavScript := map[uint32]int{
		sdl.K_SPACE: 0,
		// sdl. : -1,
		// sdl. : +1,
	}

	select {
	case event := <-sdl.Events:
		/* log.Printf("%#v\n", event) */
		switch e := event.(type) {
		case sdl.QuitEvent:
			return errors.New("sdl: received QuitEvent")

		case sdl.ResizeEvent:
			if err := c.setSurface(int(e.W), int(e.H)); err != nil {
				log.Fatal(err)
			}

		case sdl.KeyboardEvent:
			// Ignore release key
			if e.State == 0 {
				return nil
			}

			keysym := e.Keysym.Sym
			// tune timestamp
			if vias, ok := kmVias[keysym]; ok {
				viasC <- vias
				break
			}
			// tune font size
			if vias, ok := kmFontSize[keysym]; ok {
				c.changeFontSize(vias)
				break
			}

			// pause/resume
			if vias, ok := kmNavScript[keysym]; ok {
				log.Println("TODO: nav vias=", vias)
				navC <- vias
				break
			}
			log.Printf("Sim:%08x, Mod:%04x, Unicode:%02x, %t\n",
				e.Keysym.Sym, e.Keysym.Mod, e.Keysym.Unicode,
				e.Keysym.Unicode)
		}
	}
	return nil
}

func (c *sdlCtx) displayScript(script *subtitle.Script,
	andClear bool, forceUpdate bool) {
	if forceUpdate == false && c.currScript == script {
		return
	}
	c.currScript = script

	log.Printf("display %s", script.Text)

	if c.font == nil {
		log.Println("set default font")
		err := c.setFont(DEFAULT_FONT_PATH, DEFAULT_FONT_SIZE)
		if err != nil {
			log.Fatal("failed to set default font")
			return
		}
	}

	c.surface.FillRect(nil, 0 /* BG_COLOR */)
	offsetX := 10
	offsetY := 10

	for _, line := range strings.Split(script.TextWithoutMarkup(), "\n") {
		runeLine := []rune(line)
		runeLineLen := len(runeLine)
		runeLineStart := 0

		for runeLineStart != runeLineLen {
			/* log.Println("start =", runeLineStart, "len =", runeLineLen) */
			runeSubLine := runeLine[runeLineStart:]
			i := sort.Search(len(runeSubLine), func(i int) bool {
				w, _, _ := c.font.SizeUTF8(string(runeSubLine[:i]))
				return (w - 20) >= c.w
			})
			/* log.Println("runeSubLine=", string(runeSubLine)) */

			if i != len(runeSubLine) && i > 1 {
				i -= 1
			}
			if i > runeLineLen {
				i = runeLineLen
			}
			/* log.Println("returned i=", i) */

			subline := string(runeLine[runeLineStart : runeLineStart+i])
			subline = strings.TrimSpace(subline)
			/* log.Println("subline=", subline) */
			runeLineStart += i
			if runeLineStart > runeLineLen {
				runeLineStart = runeLineLen
			}

			w, _, err := c.font.SizeUTF8(subline)
			if err != 0 {
				log.Fatal("Failed to get size of the font")
			}
			offsetX = (c.w - w) / 2

			glypse := ttf.RenderUTF8_Blended(c.font, subline, TEXT_COLOR)
			lt := sdl.Rect{int16(offsetX), int16(offsetY), 0, 0}
			c.surface.Blit(&lt, glypse, nil)
			offsetY += c.lineHeight
		}

	}
	c.surface.Flip()

	if andClear == false {
		return
	}

	go func() {
		<-time.After(script.Duration())
		if c.currScript != nil && c.currScript == script {
			c.surface.FillRect(nil, 0 /* BG_COLOR */)
			c.surface.Flip()
		}
	}()
}
<|endoftext|>


<commit_before><commit_msg>rename fileExists -> fileDoesNotExist<commit_after><|endoftext|>


<commit_before><commit_msg>add fleet/fleets to unit test<commit_after><|endoftext|>


<commit_before><commit_msg>Begin searching the install path again. Stop excess printing.<commit_after><|endoftext|>


<commit_before>package server

// Server is custom server.
type Server struct {
	host string
	port int
}

// Host sets server's host.
func Host(host string) Option {
	return func(s *Server) {
		s.host = host
	}
}

// Port sets server's port.
func Port(port int) Option {
	return func(s *Server) {
		s.port = port
	}
}

// Option handle server option.
type Option func(s *Server)

// New creates new server.
func New(options ...Option) *Server {
	srv := &Server{}
	for _, o := range options {
		o(srv)
	}
	return srv
}
<commit_msg>options/server: add server.setHost<commit_after>package server

import "fmt"

// Server is custom server.
type Server struct {
	host string
	port int
}

func (s *Server) setHost(host string) error {
	if host == "" {
		return fmt.Errorf("server: %s: invalid host", host)
	}
	s.host = host
	return nil
}

// Host sets server's host.
func Host(host string) Option {
	return func(s *Server) {
		s.host = host
	}
}

// Port sets server's port.
func Port(port int) Option {
	return func(s *Server) {
		s.port = port
	}
}

// Option handle server option.
type Option func(s *Server)

// New creates new server.
func New(options ...Option) *Server {
	srv := &Server{}
	for _, o := range options {
		o(srv)
	}
	return srv
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"
	"log"
	"os"
	"strconv"

	. "github.com/3d0c/gmf"
)

var (
	section     *io.SectionReader
	srcfileName string
	seq         int
)

func customReader() ([]byte, int) {
	var file *os.File
	var err error

	if section == nil {
		file, err = os.Open(srcfileName)
		if err != nil {
			panic(err)
		}

		fi, err := file.Stat()
		if err != nil {
			panic(err)
		}

		section = io.NewSectionReader(file, 0, fi.Size())
	}

	b := make([]byte, IO_BUFFER_SIZE)

	n, err := section.Read(b)
	if err != nil && err == io.EOF {
		file.Close()
		return b, n
	}
	if err != nil {
		return nil, n
	}

	return b, n
}

func writeFile(b []byte) {
	name := "./tmp-img/" + strconv.Itoa(seq) + ".jpg"

	fp, err := os.Create(name)
	if err != nil {
		log.Fatal(err)
	}
	defer func() {
		if err := fp.Close(); err != nil {
			log.Fatal(err)
		}
		seq++
	}()

	if n, err := fp.Write(b); err != nil {
		log.Fatal(err)
	} else {
		log.Println(n, "bytes written to", name)
	}
}

func main() {
	if len(os.Args) > 1 {
		srcfileName = os.Args[1]
	} else {
		srcfileName = "tmp/big_buck_bunny.webm"
	}

	ictx := NewCtx()
	defer ictx.CloseInputAndRelease()

	if err := ictx.SetInputFormat("webm"); err != nil {
		log.Fatal(err)
	}

	avioCtx, err := NewAVIOContext(ictx, &AVIOHandlers{ReadPacket: customReader})
	defer Release(avioCtx)
	if err != nil {
		log.Fatal(err)
	}

	ictx.SetPb(avioCtx).OpenInput("")

	ist, err := ictx.GetBestStream(AVMEDIA_TYPE_VIDEO)
	if err != nil {
		log.Println("No video stream found in", srcfileName)
	}

	codec, err := FindEncoder(AV_CODEC_ID_JPEG2000)
	if err != nil {
		log.Fatal(err)
	}

	cc := NewCodecCtx(codec)
	defer Release(cc)

	cc.SetPixFmt(AV_PIX_FMT_RGB24).
		SetWidth(ist.CodecCtx().Width()).
		SetHeight(ist.CodecCtx().Height()).
		SetTimeBase(AVR{Num: 1, Den: 1})

	if codec.IsExperimental() {
		cc.SetStrictCompliance(FF_COMPLIANCE_EXPERIMENTAL)
	}

	if err := cc.Open(nil); err != nil {
		log.Fatal(err)
	}

	swsCtx := NewSwsCtx(ist.CodecCtx(), cc, SWS_BICUBIC)
	defer Release(swsCtx)

	dstFrame := NewFrame().
		SetWidth(ist.CodecCtx().Width()).
		SetHeight(ist.CodecCtx().Height()).
		SetFormat(AV_PIX_FMT_RGB24)
	defer Release(dstFrame)

	if err := dstFrame.ImgAlloc(); err != nil {
		log.Fatal(err)
	}

	i := 0
	for p := range ictx.GetNewPackets() {
		if p.StreamIndex() != ist.Index() {
			continue
		}

		fmt.Println(p)

		for frame := range p.Frames(ist.CodecCtx()) {
			swsCtx.Scale(frame, dstFrame)

			if p, err := dstFrame.Encode(cc); p != nil {
				writeFile(p.Data())
			} else if err != nil {
				log.Fatal(err)
			}

			i++
		}

		Release(p)
	}

	fmt.Println(i, "packets")
}
<commit_msg>[video-to-jpeg-avio] Broken example app<commit_after>package main

import (
	"fmt"
	"io"
	"log"
	"os"
	"strconv"

	. "github.com/3d0c/gmf"
)

var (
	section     *io.SectionReader
	srcfileName string
	seq         int
)

func customReader() ([]byte, int) {
	var file *os.File
	var err error

	if section == nil {
		file, err = os.Open(srcfileName)
		if err != nil {
			panic(err)
		}

		fi, err := file.Stat()
		if err != nil {
			panic(err)
		}

		section = io.NewSectionReader(file, 0, fi.Size())
	}

	b := make([]byte, IO_BUFFER_SIZE)

	n, err := section.Read(b)
	if err != nil && err == io.EOF {
		file.Close()
		return b, n
	}
	if err != nil {
		return nil, n
	}

	return b, n
}

func writeFile(b []byte) {
	name := "tmp-img/" + strconv.Itoa(seq) + ".jpg"

	fp, err := os.Create(name)
	if err != nil {
		log.Fatal(err)
	}
	defer func() {
		if err := fp.Close(); err != nil {
			log.Fatal(err)
		}
		seq++
	}()

	if n, err := fp.Write(b); err != nil {
		log.Fatal(err)
	} else {
		log.Println(n, "bytes written to", name)
	}
}

func main() {
	if len(os.Args) > 1 {
		srcfileName = os.Args[1]
	} else {
		srcfileName = "tmp/big_buck_bunny.webm"
	}

	ictx := NewCtx()
	defer ictx.CloseInputAndRelease()

	if err := ictx.SetInputFormat("webm"); err != nil {
		log.Fatal(err)
	}

	avioCtx, err := NewAVIOContext(ictx, &AVIOHandlers{ReadPacket: customReader})
	defer Release(avioCtx)
	if err != nil {
		log.Fatal(err)
	}

	ictx.SetPb(avioCtx).OpenInput("")

	ist, err := ictx.GetBestStream(AVMEDIA_TYPE_VIDEO)
	if err != nil {
		log.Println("No video stream found in", srcfileName)
	}

	codec, err := FindEncoder(AV_CODEC_ID_JPEG2000)
	if err != nil {
		log.Fatal(err)
	}

	cc := NewCodecCtx(codec)
	defer Release(cc)

	cc.SetPixFmt(AV_PIX_FMT_RGB24).
		SetWidth(ist.CodecCtx().Width()).
		SetHeight(ist.CodecCtx().Height()).
		SetTimeBase(AVR{Num: 1, Den: 1})

	if codec.IsExperimental() {
		cc.SetStrictCompliance(FF_COMPLIANCE_EXPERIMENTAL)
	}

	if err := cc.Open(nil); err != nil {
		log.Fatal(err)
	}

	swsCtx := NewSwsCtx(ist.CodecCtx(), cc, SWS_BICUBIC)
	defer Release(swsCtx)

	dstFrame := NewFrame().
		SetWidth(ist.CodecCtx().Width()).
		SetHeight(ist.CodecCtx().Height()).
		SetFormat(AV_PIX_FMT_RGB24)
	defer Release(dstFrame)

	if err := dstFrame.ImgAlloc(); err != nil {
		log.Fatal(err)
	}

	i := 0
	for p := range ictx.GetNewPackets() {
		if p.StreamIndex() != ist.Index() {
			continue
		}

		fmt.Println(p)

		for frame := range p.Frames(ist.CodecCtx()) {
			swsCtx.Scale(frame, dstFrame)

			if p, err := dstFrame.Encode(cc); p != nil {
				writeFile(p.Data())
			} else if err != nil {
				log.Fatal(err)
			}

			i++
		}

		Release(p)
	}

	fmt.Println(i, "packets")
}
<|endoftext|>


<commit_before><commit_msg>Improves startup validation<commit_after><|endoftext|>


<commit_before>/*
 * Copyright (C) 2016 Red Hat, Inc.
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 */

package topology

import (
	"fmt"

	"github.com/nu7hatch/gouuid"
	"github.com/skydive-project/skydive/common"
	"github.com/skydive-project/skydive/logging"
	"github.com/skydive-project/skydive/topology/graph"
)

// Describe the relation type between nodes
const (
	OwnershipLink = "ownership"
	Layer2Link    = "layer2"
)

// Describe the relation type between nodes in the graph
var (
	OwnershipMetadata = graph.Metadata{"RelationType": OwnershipLink}
	Layer2Metadata    = graph.Metadata{"RelationType": Layer2Link}

	ErrNetworkPathNotFound = func(name string) error { return fmt.Errorf("Failed to determine network namespace path for %s", name) }
)

// NamespaceFromNode returns the namespace name and the path of a node in the graph
func NamespaceFromNode(g *graph.Graph, n *graph.Node) (string, string, error) {
	name, _ := n.GetFieldString("Name")
	if name == "" {
		return "", "", fmt.Errorf("No Name for node %v", n)
	}

	nodes := g.LookupShortestPath(n, graph.Metadata{"Type": "host"}, OwnershipMetadata)
	if len(nodes) == 0 {
		return "", "", ErrNetworkPathNotFound(name)
	}

	for _, node := range nodes {
		tp, _ := node.GetFieldString("Type")
		if tp == "" {
			return "", "", fmt.Errorf("No Type for node %v", n)
		}

		if tp == "netns" {
			name, _ := node.GetFieldString("Name")
			if name == "" {
				return "", "", fmt.Errorf("No Name for node %v", node)
			}

			path, _ := node.GetFieldString("Path")
			if path == "" {
				return "", "", fmt.Errorf("No Path for node %v", node)
			}

			return name, path, nil
		}
	}

	return "", "", nil
}

// NewNetNSContextByNode creates a new network namespace context based on the node
func NewNetNSContextByNode(g *graph.Graph, n *graph.Node) (*common.NetNSContext, error) {
	name, path, err := NamespaceFromNode(g, n)
	if err != nil || name == "" || path == "" {
		return nil, err
	}

	logging.GetLogger().Debugf("Switching to namespace %s (path: %s)", name, path)
	return common.NewNetNsContext(path)
}

// HostNodeTIDMap a map that store the value node TID and the key node host
type HostNodeTIDMap map[string][]string

// BuildHostNodeTIDMap creates a new node and host (key) map
func BuildHostNodeTIDMap(nodes []*graph.Node) HostNodeTIDMap {
	hnmap := make(HostNodeTIDMap)
	for _, node := range nodes {
		if tid, _ := node.GetFieldString("TID"); tid != "" {
			hnmap[node.Host()] = append(hnmap[node.Host()], tid)
		}
	}
	return hnmap
}

// HaveOwnershipLink returns true if parent and child have an ownership link
func HaveOwnershipLink(g *graph.Graph, parent *graph.Node, child *graph.Node) bool {
	return g.AreLinked(parent, child, OwnershipMetadata)
}

// IsOwnershipLinked checks whether the node has an OwnershipLink
func IsOwnershipLinked(g *graph.Graph, node *graph.Node) bool {
	edges := g.GetNodeEdges(node, OwnershipMetadata)
	return len(edges) != 0
}

// GetOwnershipLink get ownership Link between the parent and the child node or nil
func GetOwnershipLink(g *graph.Graph, parent *graph.Node, child *graph.Node) *graph.Edge {
	return g.GetFirstLink(parent, child, OwnershipMetadata)
}

// AddOwnershipLink Link between the parent and the child node, the child can have only one parent, previous will be overwritten
func AddOwnershipLink(g *graph.Graph, parent *graph.Node, child *graph.Node, metadata graph.Metadata, h ...string) *graph.Edge {
	// a child node can only have one parent of type ownership, so delete the previous link
	for _, e := range g.GetNodeEdges(child, OwnershipMetadata) {
		if e.GetChild() == child.ID {
			logging.GetLogger().Debugf("Delete previous ownership link: %v", e)
			g.DelEdge(e)
		}
	}

	m := OwnershipMetadata
	for k, v := range metadata {
		m[k] = v
	}

	id, _ := uuid.NewV5(uuid.NamespaceOID, []byte(parent.ID+child.ID+OwnershipLink))
	return g.NewEdge(graph.Identifier(id.String()), parent, child, m, h...)
}

// HaveLayer2Link returns true if parent and child have the same layer 2
func HaveLayer2Link(g *graph.Graph, node1 *graph.Node, node2 *graph.Node, metadata graph.Metadata) bool {
	return g.AreLinked(node1, node2, Layer2Metadata)
}

// AddLayer2Link Link the parent and the child node
func AddLayer2Link(g *graph.Graph, node1 *graph.Node, node2 *graph.Node, metadata graph.Metadata) *graph.Edge {
	m := Layer2Metadata
	for k, v := range metadata {
		m[k] = v
	}

	id, _ := uuid.NewV5(uuid.NamespaceOID, []byte(node1.ID+node2.ID+Layer2Link))
	return g.NewEdge(graph.Identifier(id.String()), node1, node2, m)
}
<commit_msg>topology: don't alter OwnershipMetadata pseudo constant<commit_after>/*
 * Copyright (C) 2016 Red Hat, Inc.
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 */

package topology

import (
	"fmt"

	"github.com/nu7hatch/gouuid"
	"github.com/skydive-project/skydive/common"
	"github.com/skydive-project/skydive/logging"
	"github.com/skydive-project/skydive/topology/graph"
)

// Describe the relation type between nodes
const (
	OwnershipLink = "ownership"
	Layer2Link    = "layer2"
)

// Describe the relation type between nodes in the graph
var (
	OwnershipMetadata = graph.Metadata{"RelationType": OwnershipLink}
	Layer2Metadata    = graph.Metadata{"RelationType": Layer2Link}

	ErrNetworkPathNotFound = func(name string) error { return fmt.Errorf("Failed to determine network namespace path for %s", name) }
)

// NamespaceFromNode returns the namespace name and the path of a node in the graph
func NamespaceFromNode(g *graph.Graph, n *graph.Node) (string, string, error) {
	name, _ := n.GetFieldString("Name")
	if name == "" {
		return "", "", fmt.Errorf("No Name for node %v", n)
	}

	nodes := g.LookupShortestPath(n, graph.Metadata{"Type": "host"}, OwnershipMetadata)
	if len(nodes) == 0 {
		return "", "", ErrNetworkPathNotFound(name)
	}

	for _, node := range nodes {
		tp, _ := node.GetFieldString("Type")
		if tp == "" {
			return "", "", fmt.Errorf("No Type for node %v", n)
		}

		if tp == "netns" {
			name, _ := node.GetFieldString("Name")
			if name == "" {
				return "", "", fmt.Errorf("No Name for node %v", node)
			}

			path, _ := node.GetFieldString("Path")
			if path == "" {
				return "", "", fmt.Errorf("No Path for node %v", node)
			}

			return name, path, nil
		}
	}

	return "", "", nil
}

// NewNetNSContextByNode creates a new network namespace context based on the node
func NewNetNSContextByNode(g *graph.Graph, n *graph.Node) (*common.NetNSContext, error) {
	name, path, err := NamespaceFromNode(g, n)
	if err != nil || name == "" || path == "" {
		return nil, err
	}

	logging.GetLogger().Debugf("Switching to namespace %s (path: %s)", name, path)
	return common.NewNetNsContext(path)
}

// HostNodeTIDMap a map that store the value node TID and the key node host
type HostNodeTIDMap map[string][]string

// BuildHostNodeTIDMap creates a new node and host (key) map
func BuildHostNodeTIDMap(nodes []*graph.Node) HostNodeTIDMap {
	hnmap := make(HostNodeTIDMap)
	for _, node := range nodes {
		if tid, _ := node.GetFieldString("TID"); tid != "" {
			hnmap[node.Host()] = append(hnmap[node.Host()], tid)
		}
	}
	return hnmap
}

// HaveOwnershipLink returns true if parent and child have an ownership link
func HaveOwnershipLink(g *graph.Graph, parent *graph.Node, child *graph.Node) bool {
	return g.AreLinked(parent, child, OwnershipMetadata)
}

// IsOwnershipLinked checks whether the node has an OwnershipLink
func IsOwnershipLinked(g *graph.Graph, node *graph.Node) bool {
	edges := g.GetNodeEdges(node, OwnershipMetadata)
	return len(edges) != 0
}

// GetOwnershipLink get ownership Link between the parent and the child node or nil
func GetOwnershipLink(g *graph.Graph, parent *graph.Node, child *graph.Node) *graph.Edge {
	return g.GetFirstLink(parent, child, OwnershipMetadata)
}

// AddOwnershipLink Link between the parent and the child node, the child can have only one parent, previous will be overwritten
func AddOwnershipLink(g *graph.Graph, parent *graph.Node, child *graph.Node, metadata graph.Metadata, h ...string) *graph.Edge {
	// a child node can only have one parent of type ownership, so delete the previous link
	for _, e := range g.GetNodeEdges(child, OwnershipMetadata) {
		if e.GetChild() == child.ID {
			logging.GetLogger().Debugf("Delete previous ownership link: %v", e)
			g.DelEdge(e)
		}
	}

	m := graph.Metadata{"RelationType": OwnershipLink}
	for k, v := range metadata {
		m[k] = v
	}

	id, _ := uuid.NewV5(uuid.NamespaceOID, []byte(parent.ID+child.ID+OwnershipLink))
	return g.NewEdge(graph.Identifier(id.String()), parent, child, m, h...)
}

// HaveLayer2Link returns true if parent and child have the same layer 2
func HaveLayer2Link(g *graph.Graph, node1 *graph.Node, node2 *graph.Node, metadata graph.Metadata) bool {
	return g.AreLinked(node1, node2, Layer2Metadata)
}

// AddLayer2Link Link the parent and the child node
func AddLayer2Link(g *graph.Graph, node1 *graph.Node, node2 *graph.Node, metadata graph.Metadata) *graph.Edge {
	m := Layer2Metadata
	for k, v := range metadata {
		m[k] = v
	}

	id, _ := uuid.NewV5(uuid.NamespaceOID, []byte(node1.ID+node2.ID+Layer2Link))
	return g.NewEdge(graph.Identifier(id.String()), node1, node2, m)
}
<|endoftext|>


<commit_before>package search

import (
	"fmt"
	"net/http"

	"github.com/algolia/algoliasearch-client-go/algolia/call"
	"github.com/algolia/algoliasearch-client-go/algolia/compression"
	iopt "github.com/algolia/algoliasearch-client-go/algolia/internal/opt"
	"github.com/algolia/algoliasearch-client-go/algolia/opt"
	"github.com/algolia/algoliasearch-client-go/algolia/transport"
)

const (
	// DefaultMaxBatchSize defines the default maximum batch size to be used to
	// automatically split record batches when using Index.SaveObjects.
	DefaultMaxBatchSize = 1000
)

// Client provides methods to interact with the Algolia Search API on multiple
// indices which belong to the same Algolia application.
type Client struct {
	appID        string
	maxBatchSize int
	transport    *transport.Transport
}

// NewClient instantiates a new client able to interact with the Algolia
// Search API on multiple indices which belong to the same Algolia application.
func NewClient(appID, apiKey string) *Client {
	return NewClientWithConfig(
		Configuration{
			AppID:       appID,
			APIKey:      apiKey,
			Compression: compression.GZIP,
		},
	)
}

// NewClientWithConfig instantiates a new client able to interact with the
// Algolia Search API on multiple indices which belong to the same Algolia
// application.
func NewClientWithConfig(config Configuration) *Client {
	var (
		hosts        []*transport.StatefulHost
		maxBatchSize int
	)

	if len(config.Hosts) == 0 {
		hosts = defaultHosts(config.AppID)
	} else {
		for _, h := range config.Hosts {
			hosts = append(hosts, transport.NewStatefulHost(h, call.IsReadWrite))
		}
	}

	if config.MaxBatchSize == 0 {
		maxBatchSize = DefaultMaxBatchSize
	} else {
		maxBatchSize = config.MaxBatchSize
	}

	return &Client{
		appID:        config.AppID,
		maxBatchSize: maxBatchSize,
		transport: transport.New(
			hosts,
			config.Requester,
			config.AppID,
			config.APIKey,
			config.ReadTimeout,
			config.WriteTimeout,
			config.Headers,
			config.ExtraUserAgent,
			config.Compression,
		),
	}
}

// InitIndex instantiates a new index able to interact with the Algolia
// Search API on a single index.
func (c *Client) InitIndex(indexName string) *Index {
	return newIndex(c, indexName)
}

func (c *Client) path(format string, a ...interface{}) string {
	return "/1" + fmt.Sprintf(format, a...)
}

// ListIndices lists the indices of the Algolia application. The response is
// paginated and hence, may not return all indices in a single call. Multiple
// calls may be necessary to retrieve all indices.
func (c *Client) ListIndices(opts ...interface{}) (res ListIndicesRes, err error) {
	path := c.path("/indexes")
	err = c.transport.Request(&res, http.MethodGet, path, nil, call.Read, opts...)
	return
}

// GetLogs returns the most recent information logs of the Algolia application.
func (c *Client) GetLogs(opts ...interface{}) (res GetLogsRes, err error) {
	if offset := iopt.ExtractOffset(opts...); offset != nil {
		opts = opt.InsertExtraURLParam(opts, "offset", offset.Get())
	}
	if length := iopt.ExtractLength(opts...); length != nil {
		opts = opt.InsertExtraURLParam(opts, "length", length.Get())
	}
	if t := iopt.ExtractType(opts...).Get(); len(t) > 0 {
		opts = opt.InsertExtraURLParam(opts, "type", t[0])
	}
	if indexName := iopt.ExtractIndexName(opts...); indexName != nil {
		opts = opt.InsertExtraURLParam(opts, "indexName", indexName.Get())
	}
	path := c.path("/logs")
	err = c.transport.Request(&res, http.MethodGet, path, nil, call.Read, opts...)
	return
}

// CustomRequest is a low-level function which build a request from the given
// parameters and send it through the requester, making use of the underlying
// retry strategy.
func (c *Client) CustomRequest(
	res interface{},
	method string,
	path string,
	body interface{},
	k call.Kind,
	opts ...interface{},
) error {
	return c.transport.Request(&res, method, path, body, k, opts...)
}
<commit_msg>changed(compression): set back default compression to 'None' on POST/PUT requests<commit_after>package search

import (
	"fmt"
	"net/http"

	"github.com/algolia/algoliasearch-client-go/algolia/call"
	"github.com/algolia/algoliasearch-client-go/algolia/compression"
	iopt "github.com/algolia/algoliasearch-client-go/algolia/internal/opt"
	"github.com/algolia/algoliasearch-client-go/algolia/opt"
	"github.com/algolia/algoliasearch-client-go/algolia/transport"
)

const (
	// DefaultMaxBatchSize defines the default maximum batch size to be used to
	// automatically split record batches when using Index.SaveObjects.
	DefaultMaxBatchSize = 1000
)

// Client provides methods to interact with the Algolia Search API on multiple
// indices which belong to the same Algolia application.
type Client struct {
	appID        string
	maxBatchSize int
	transport    *transport.Transport
}

// NewClient instantiates a new client able to interact with the Algolia
// Search API on multiple indices which belong to the same Algolia application.
func NewClient(appID, apiKey string) *Client {
	return NewClientWithConfig(
		Configuration{
			AppID:       appID,
			APIKey:      apiKey,
			Compression: compression.None,
		},
	)
}

// NewClientWithConfig instantiates a new client able to interact with the
// Algolia Search API on multiple indices which belong to the same Algolia
// application.
func NewClientWithConfig(config Configuration) *Client {
	var (
		hosts        []*transport.StatefulHost
		maxBatchSize int
	)

	if len(config.Hosts) == 0 {
		hosts = defaultHosts(config.AppID)
	} else {
		for _, h := range config.Hosts {
			hosts = append(hosts, transport.NewStatefulHost(h, call.IsReadWrite))
		}
	}

	if config.MaxBatchSize == 0 {
		maxBatchSize = DefaultMaxBatchSize
	} else {
		maxBatchSize = config.MaxBatchSize
	}

	return &Client{
		appID:        config.AppID,
		maxBatchSize: maxBatchSize,
		transport: transport.New(
			hosts,
			config.Requester,
			config.AppID,
			config.APIKey,
			config.ReadTimeout,
			config.WriteTimeout,
			config.Headers,
			config.ExtraUserAgent,
			config.Compression,
		),
	}
}

// InitIndex instantiates a new index able to interact with the Algolia
// Search API on a single index.
func (c *Client) InitIndex(indexName string) *Index {
	return newIndex(c, indexName)
}

func (c *Client) path(format string, a ...interface{}) string {
	return "/1" + fmt.Sprintf(format, a...)
}

// ListIndices lists the indices of the Algolia application. The response is
// paginated and hence, may not return all indices in a single call. Multiple
// calls may be necessary to retrieve all indices.
func (c *Client) ListIndices(opts ...interface{}) (res ListIndicesRes, err error) {
	path := c.path("/indexes")
	err = c.transport.Request(&res, http.MethodGet, path, nil, call.Read, opts...)
	return
}

// GetLogs returns the most recent information logs of the Algolia application.
func (c *Client) GetLogs(opts ...interface{}) (res GetLogsRes, err error) {
	if offset := iopt.ExtractOffset(opts...); offset != nil {
		opts = opt.InsertExtraURLParam(opts, "offset", offset.Get())
	}
	if length := iopt.ExtractLength(opts...); length != nil {
		opts = opt.InsertExtraURLParam(opts, "length", length.Get())
	}
	if t := iopt.ExtractType(opts...).Get(); len(t) > 0 {
		opts = opt.InsertExtraURLParam(opts, "type", t[0])
	}
	if indexName := iopt.ExtractIndexName(opts...); indexName != nil {
		opts = opt.InsertExtraURLParam(opts, "indexName", indexName.Get())
	}
	path := c.path("/logs")
	err = c.transport.Request(&res, http.MethodGet, path, nil, call.Read, opts...)
	return
}

// CustomRequest is a low-level function which build a request from the given
// parameters and send it through the requester, making use of the underlying
// retry strategy.
func (c *Client) CustomRequest(
	res interface{},
	method string,
	path string,
	body interface{},
	k call.Kind,
	opts ...interface{},
) error {
	return c.transport.Request(&res, method, path, body, k, opts...)
}
<|endoftext|>


<commit_before>
////////////////////////////////////////////////////////////////////////////////
//                          DO NOT MODIFY THIS FILE!
//
//  This file was automatically generated via the commands:
//
//      go get github.com/coryb/autoplay
//      autoplay --name autoplay/ask.go --squash \\r\\b go run ask.go
//
////////////////////////////////////////////////////////////////////////////////
package main

import (
	"bufio"
	"fmt"
	"os"
	"os/exec"

	"github.com/kr/pty"
)

func main() {
	fh, tty, _ := pty.Open()
	defer tty.Close()
	defer fh.Close()
	c := exec.Command("go", "run", "ask.go")
	c.Stdin = tty
	c.Stdout = tty
	c.Stderr = tty
	c.Start()
	buf := bufio.NewReaderSize(fh, 1024)

	expect("Asking many.\r\n", buf)
	expect("\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat is your name? \x1b[0m\x1b[37m(Johnny Appleseed) \x1b[0m", buf)
	fh.Write([]byte("L"))
	expect("L", buf)
	fh.Write([]byte("a"))
	expect("a", buf)
	fh.Write([]byte("r"))
	expect("r", buf)
	fh.Write([]byte("r"))
	expect("r", buf)
	fh.Write([]byte("y"))
	expect("y", buf)
	fh.Write([]byte(" "))
	expect(" ", buf)
	fh.Write([]byte("B"))
	expect("B", buf)
	fh.Write([]byte("i"))
	expect("i", buf)
	fh.Write([]byte("r"))
	expect("r", buf)
	fh.Write([]byte("d"))
	expect("d", buf)
	fh.Write([]byte("\r"))
	expect("\r\n", buf)
	expect("\x1b[1A\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat is your name? \x1b[0m\x1b[36mLarry Bird\x1b[0m\r\n", buf)
	expect("\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose a color:\x1b[0m\r\n", buf)
	expect("\x1b[1;99m  red\x1b[0m\r\n", buf)
	expect("\x1b[1;99m  blue\x1b[0m\r\n", buf)
	expect("\x1b[1;99m  green\x1b[0m\r\n", buf)
	expect("\x1b[1;36m❯ yellow\x1b[0m\r\n", buf)
	expect("\x1b[?25l\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose a color:\x1b[0m\r\n", buf)
	expect("\x1b[1;99m  red\x1b[0m\r\n", buf)
	expect("\x1b[1;99m  blue\x1b[0m\r\n", buf)
	expect("\x1b[1;99m  green\x1b[0m\r\n", buf)
	expect("\x1b[1;36m❯ yellow\x1b[0m\r\n", buf)
	fh.Write([]byte("\x1b"))
	fh.Write([]byte("["))
	fh.Write([]byte("A"))
	expect("\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose a color:\x1b[0m\r\n", buf)
	expect("\x1b[1;99m  red\x1b[0m\r\n", buf)
	expect("\x1b[1;99m  blue\x1b[0m\r\n", buf)
	expect("\x1b[1;36m❯ green\x1b[0m\r\n", buf)
	expect("\x1b[1;99m  yellow\x1b[0m\r\n", buf)
	fh.Write([]byte("\x1b"))
	fh.Write([]byte("["))
	fh.Write([]byte("A"))
	expect("\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose a color:\x1b[0m\r\n", buf)
	expect("\x1b[1;99m  red\x1b[0m\r\n", buf)
	expect("\x1b[1;36m❯ blue\x1b[0m\r\n", buf)
	expect("\x1b[1;99m  green\x1b[0m\r\n", buf)
	expect("\x1b[1;99m  yellow\x1b[0m\r\n", buf)
	fh.Write([]byte("\r"))
	expect("\x1b[?25h\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose a color:\x1b[0m\x1b[36m blue\x1b[0m\r\n", buf)
	expect("Asking one.\r\n", buf)
	expect("\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat is your name? \x1b[0m\x1b[37m(Johnny Appleseed) \x1b[0m", buf)
	fh.Write([]byte("L"))
	expect("L", buf)
	fh.Write([]byte("a"))
	expect("a", buf)
	fh.Write([]byte("r"))
	expect("r", buf)
	fh.Write([]byte("r"))
	expect("r", buf)
	fh.Write([]byte("y"))
	expect("y", buf)
	fh.Write([]byte(" "))
	expect(" ", buf)
	fh.Write([]byte("K"))
	expect("K", buf)
	fh.Write([]byte("i"))
	expect("i", buf)
	fh.Write([]byte("n"))
	expect("n", buf)
	fh.Write([]byte("g"))
	expect("g", buf)
	fh.Write([]byte("\r"))
	expect("\r\n", buf)
	expect("\x1b[1A\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat is your name? \x1b[0m\x1b[36mLarry King\x1b[0m\r\n", buf)
	expect("Answered with Larry King.\r\n", buf)
	expect("Asking one with validation.\r\n", buf)
	expect("\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat is your name? \x1b[0m", buf)
	fh.Write([]byte("\r"))
	expect("\r\n", buf)
	expect("\x1b[1A\x1b[31m✘ Sorry, your reply was invalid: Value is required\x1b[0m\r\n", buf)
	expect("\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat is your name? \x1b[0m", buf)
	fh.Write([]byte("L"))
	expect("L", buf)
	fh.Write([]byte("a"))
	expect("a", buf)
	fh.Write([]byte("r"))
	expect("r", buf)
	fh.Write([]byte("r"))
	expect("r", buf)
	fh.Write([]byte("y"))
	expect("y", buf)
	fh.Write([]byte(" "))
	expect(" ", buf)
	fh.Write([]byte("W"))
	expect("W", buf)
	fh.Write([]byte("a"))
	expect("a", buf)
	fh.Write([]byte("l"))
	expect("l", buf)
	fh.Write([]byte("l"))
	expect("l", buf)
	fh.Write([]byte("\r"))
	expect("\r\n", buf)
	expect("\x1b[1A\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat is your name? \x1b[0m\x1b[36mLarry Wall\x1b[0m\r\n", buf)
	expect("Answered with Larry Wall.\r\n", buf)

	c.Wait()
	tty.Close()
	fh.Close()
}

func expect(expected string, buf *bufio.Reader) {
	sofar := []rune{}
	for _, r := range expected {
		got, _, _ := buf.ReadRune()
		sofar = append(sofar, got)
		if got != r {
			fmt.Fprintln(os.Stderr)
			fmt.Fprintf(os.Stderr, "Expected: %q\n", expected[:len(sofar)])
			fmt.Fprintf(os.Stderr, "Got:      %q\n", string(sofar))
			panic(fmt.Errorf("Unexpected Rune %q, Expected %q\n", got, r))
		} else {
			fmt.Printf("%c", r)
		}
	}
}
<commit_msg>add some code to debug travis error<commit_after>////////////////////////////////////////////////////////////////////////////////
//                          DO NOT MODIFY THIS FILE!
//
//  This file was automatically generated via the commands:
//
//      go get github.com/coryb/autoplay
//      autoplay --name autoplay/ask.go --squash \\r\\b go run ask.go
//
////////////////////////////////////////////////////////////////////////////////
package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"os/exec"
	"strconv"
	"strings"
	"time"
	"unicode"

	"github.com/kr/pty"
	"github.com/mgutz/ansi"
)

func main() {
	fh, tty, _ := pty.Open()
	defer tty.Close()
	defer fh.Close()
	c := exec.Command("go", "run", "ask.go")
	c.Stdin = tty
	c.Stdout = tty
	c.Stderr = tty
	c.Start()
	buf := bufio.NewReaderSize(fh, 1024)

	expect("Asking many.\r\n", buf)
	expect("\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat is your name? \x1b[0m\x1b[37m(Johnny Appleseed) \x1b[0m", buf)
	fh.Write([]byte("L"))
	expect("L", buf)
	fh.Write([]byte("a"))
	expect("a", buf)
	fh.Write([]byte("r"))
	expect("r", buf)
	fh.Write([]byte("r"))
	expect("r", buf)
	fh.Write([]byte("y"))
	expect("y", buf)
	fh.Write([]byte(" "))
	expect(" ", buf)
	fh.Write([]byte("B"))
	expect("B", buf)
	fh.Write([]byte("i"))
	expect("i", buf)
	fh.Write([]byte("r"))
	expect("r", buf)
	fh.Write([]byte("d"))
	expect("d", buf)
	fh.Write([]byte("\r"))
	expect("\r\n", buf)
	expect("\x1b[1A\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat is your name? \x1b[0m\x1b[36mLarry Bird\x1b[0m\r\n", buf)
	expect("\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose a color:\x1b[0m\r\n", buf)
	expect("\x1b[1;99m  red\x1b[0m\r\n", buf)
	expect("\x1b[1;99m  blue\x1b[0m\r\n", buf)
	expect("\x1b[1;99m  green\x1b[0m\r\n", buf)
	expect("\x1b[1;36m❯ yellow\x1b[0m\r\n", buf)
	expect("\x1b[?25l\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose a color:\x1b[0m\r\n", buf)
	expect("\x1b[1;99m  red\x1b[0m\r\n", buf)
	expect("\x1b[1;99m  blue\x1b[0m\r\n", buf)
	expect("\x1b[1;99m  green\x1b[0m\r\n", buf)
	expect("\x1b[1;36m❯ yellow\x1b[0m\r\n", buf)
	fh.Write([]byte("\x1b"))
	fh.Write([]byte("["))
	fh.Write([]byte("A"))
	expect("\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose a color:\x1b[0m\r\n", buf)
	expect("\x1b[1;99m  red\x1b[0m\r\n", buf)
	expect("\x1b[1;99m  blue\x1b[0m\r\n", buf)
	expect("\x1b[1;36m❯ green\x1b[0m\r\n", buf)
	expect("\x1b[1;99m  yellow\x1b[0m\r\n", buf)
	fh.Write([]byte("\x1b"))
	fh.Write([]byte("["))
	fh.Write([]byte("A"))
	expect("\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose a color:\x1b[0m\r\n", buf)
	expect("\x1b[1;99m  red\x1b[0m\r\n", buf)
	expect("\x1b[1;36m❯ blue\x1b[0m\r\n", buf)
	expect("\x1b[1;99m  green\x1b[0m\r\n", buf)
	expect("\x1b[1;99m  yellow\x1b[0m\r\n", buf)
	fh.Write([]byte("\r"))
	expect("\x1b[?25h\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose a color:\x1b[0m\x1b[36m blue\x1b[0m\r\n", buf)
	expect("Asking one.\r\n", buf)
	expect("\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat is your name? \x1b[0m\x1b[37m(Johnny Appleseed) \x1b[0m", buf)
	fh.Write([]byte("L"))
	expect("L", buf)
	fh.Write([]byte("a"))
	expect("a", buf)
	fh.Write([]byte("r"))
	expect("r", buf)
	fh.Write([]byte("r"))
	expect("r", buf)
	fh.Write([]byte("y"))
	expect("y", buf)
	fh.Write([]byte(" "))
	expect(" ", buf)
	fh.Write([]byte("K"))
	expect("K", buf)
	fh.Write([]byte("i"))
	expect("i", buf)
	fh.Write([]byte("n"))
	expect("n", buf)
	fh.Write([]byte("g"))
	expect("g", buf)
	fh.Write([]byte("\r"))
	expect("\r\n", buf)
	expect("\x1b[1A\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat is your name? \x1b[0m\x1b[36mLarry King\x1b[0m\r\n", buf)
	expect("Answered with Larry King.\r\n", buf)
	expect("Asking one with validation.\r\n", buf)
	expect("\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat is your name? \x1b[0m", buf)
	fh.Write([]byte("\r"))
	expect("\r\n", buf)
	expect("\x1b[1A\x1b[31m✘ Sorry, your reply was invalid: Value is required\x1b[0m\r\n", buf)
	expect("\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat is your name? \x1b[0m", buf)
	fh.Write([]byte("L"))
	expect("L", buf)
	fh.Write([]byte("a"))
	expect("a", buf)
	fh.Write([]byte("r"))
	expect("r", buf)
	fh.Write([]byte("r"))
	expect("r", buf)
	fh.Write([]byte("y"))
	expect("y", buf)
	fh.Write([]byte(" "))
	expect(" ", buf)
	fh.Write([]byte("W"))
	expect("W", buf)
	fh.Write([]byte("a"))
	expect("a", buf)
	fh.Write([]byte("l"))
	expect("l", buf)
	fh.Write([]byte("l"))
	expect("l", buf)
	fh.Write([]byte("\r"))
	expect("\r\n", buf)
	expect("\x1b[1A\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat is your name? \x1b[0m\x1b[36mLarry Wall\x1b[0m\r\n", buf)
	expect("Answered with Larry Wall.\r\n", buf)

	c.Wait()
	tty.Close()
	fh.Close()
}

func expect(expected string, buf *bufio.Reader) {
	sofar := []rune{}
	for _, r := range expected {
		got, _, err := buf.ReadRune()
		if err == io.EOF || got == unicode.ReplacementChar {
			time.Sleep(10 * time.Millisecond)
			continue
		}

		sofar = append(sofar, got)
		if got != r {
			fmt.Fprintln(os.Stderr)
			fmt.Fprintln(os.Stderr, ansi.ColorCode("reset"))
			red := ansi.ColorCode("red")
			reset := ansi.ColorCode("reset")

			expStart := strings.TrimSuffix(strconv.Quote(expected[:len(sofar)-1]), "\"")
			expMiss := strings.TrimSuffix(strings.TrimPrefix(strconv.Quote(string(expected[len(sofar)-1])), "\""), "\"")
			expEnd := strings.TrimPrefix(strconv.Quote(expected[len(sofar):]), "\"")

			fmt.Fprintf(os.Stderr, "Expected: %s%s%s%s%s\n", expStart, red, expMiss, reset, expEnd)

			p := make([]byte, buf.Buffered())
			buf.Read(p)

			gotStart := strings.TrimSuffix(strconv.Quote(string(sofar[:len(sofar)-1])), "\"")
			gotMiss := strings.TrimSuffix(strings.TrimPrefix(strconv.Quote(string(sofar[len(sofar)-1])), "\""), "\"")
			gotEnd := strings.TrimPrefix(strconv.Quote(string(p)), "\"")

			fmt.Fprintf(os.Stderr, "Got:      %s.%s.%s.%s.%s\n", gotStart, red, gotMiss, reset, gotEnd)
			panic(fmt.Errorf("Unexpected Rune %q, Expected %q\n", got, r))
		} else {
			fmt.Printf("%c", r)
		}
	}
}
<|endoftext|>


<commit_before>// Package ca provides easy to use certificate authority related functions.
// This is a lightweight wrapper around "crypto/x509" package for
// creating CA certs, client certs, signing requests, and more.
//
// This package is mostly based on the example code provided at:
// http://golang.org/src/crypto/tls/generate_cert.go
package ca

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/pem"
	"fmt"
	"math/big"
	"net"
	"strings"
	"time"
)

// GenCA generates a self-signed CA certificate.
//
// host = Comma-separated hostnames and/or IPs to generate a certificate for. i.e. "localhost,127.0.0.1"
// validFor = Validity period for the certificate. Defaults to time.Duration max (290 years).
// ca, caPriv = CA certificate/private key to sign the new certificate. If not given, the generated certificate will be a self-signed CA.
// keyLength = Key length for the new certificate. Defaults to 3248 bits RSA key.
// cn, org = Common name and organization fields of the certificate.
//
// Returns PEM encoded X.509 certificate and private key pair.
//
// Note: While writing the binary cert/key pair to file system, it is useful to use standard naming like: 'cert.pem', 'key.pem'.
func GenCA(host string, validFor time.Duration, keyLength int, cn, org string) (cert, key []byte, err error) {
	return nil, nil, nil
}

// GenSigningCert generates an intermediate signing certificate for signing server or client certificates.
// Returns PEM encoded X.509 certificate and private key pair.
func GenSigningCert() (cert, key []byte, err error) {
	return nil, nil, nil
}

// GenServerCert generates a hosting certificate for servers using TLS.
// Returns PEM encoded X.509 certificate and private key pair.
func GenServerCert() (cert, key []byte, err error) {
	return nil, nil, nil
}

// GenClientCert generates a client certificate signed by the provided signing certificate.
// Generated certificate will have its extended key usage set to 'client authentication' and will be ready for use in TLS client authentication.
// Returns PEM encoded X.509 certificate and private key pair.
func GenClientCert(signCert *x509.Certificate, signKey *rsa.PrivateKey) (cert, key []byte, err error) {
	return nil, nil, nil
}

func getBaseCert(host string, validFor time.Duration, keyLength int, cn, org string) (*x509.Certificate, *rsa.PrivateKey, error) {
	if keyLength == 0 {
		keyLength = 3248
	}

	privKey, err := rsa.GenerateKey(rand.Reader, keyLength)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to generate certificate private RSA key: %v", err)
	}

	notBefore := time.Now()
	notAfter := notBefore.Add(290 * 365 * 24 * time.Hour) //290 years
	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to generate the certificate serial number: %v", err)
	}

	if validFor != 0 {
		notAfter = notBefore.Add(validFor)
	}

	cert := x509.Certificate{
		BasicConstraintsValid: true,
		SerialNumber:          serialNumber,
		Subject: pkix.Name{
			CommonName:   cn,
			Organization: []string{org},
		},
		NotBefore: notBefore,
		NotAfter:  notAfter,
		KeyUsage:  x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
	}

	setHosts(host, &cert)

	return &cert, privKey, nil
}

func setHosts(host string, cert *x509.Certificate) {
	hosts := strings.Split(host, ",")
	for _, h := range hosts {
		if ip := net.ParseIP(h); ip != nil {
			cert.IPAddresses = append(cert.IPAddresses, ip)
		} else {
			cert.DNSNames = append(cert.DNSNames, h)
		}
	}
}

// genCert generates a PEM encoded X.509 certificate and private key pair (i.e. 'cert.pem', 'key.pem').
// This code is based on the sample from http://golang.org/src/crypto/tls/generate_cert.go (taken at Jan 30, 2015).
// If no private key is provided, the certificate is marked as self-signed CA.
// host = Comma-separated hostnames and IPs to generate a certificate for. i.e. "localhost,127.0.0.1"
// validFor = Validity period for the certificate. Defaults to time.Duration max (290 years).
// ca, caPriv = CA certificate/private key to sign the new certificate. If not given, the generated certificate will be a self-signed CA.
// keyLength = Key length for the new certificate. Defaults to 3248 bits RSA key.
// cn, org = Common name and organization fields of the certificate.
func genCert(host string, validFor time.Duration, ca *x509.Certificate, caPriv *rsa.PrivateKey, keyLength int, cn, org string) (pemBytes, privBytes []byte, err error) {
	cert, privKey, err := getBaseCert(host, validFor, keyLength, cn, org)

	cert.IsCA = ca == nil
	signerCert := cert
	signerPriv := privKey
	if cert.IsCA {
		cert.KeyUsage |= x509.KeyUsageCertSign
		cert.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}
	} else {
		cert.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}
		signerCert = ca
		signerPriv = caPriv
	}

	derBytes, err := x509.CreateCertificate(rand.Reader, cert, signerCert, privKey.PublicKey, signerPriv)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to create certificate: %v", err)
	}

	pemBytes = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
	privBytes = pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privKey)})
	return
}
<commit_msg>fix test<commit_after>// Package ca provides easy to use certificate authority related functions.
// This is a lightweight wrapper around "crypto/x509" package for
// creating CA certs, client certs, signing requests, and more.
//
// This package is mostly based on the example code provided at:
// http://golang.org/src/crypto/tls/generate_cert.go
package ca

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/pem"
	"fmt"
	"math/big"
	"net"
	"strings"
	"time"
)

// GenCA generates a self-signed CA certificate.
//
// host = Comma-separated hostnames and/or IPs to generate a certificate for. i.e. "localhost,127.0.0.1"
// validFor = Validity period for the certificate. Defaults to time.Duration max (290 years).
// ca, caPriv = CA certificate/private key to sign the new certificate. If not given, the generated certificate will be a self-signed CA.
// keyLength = Key length for the new certificate. Defaults to 3248 bits RSA key.
// cn, org = Common name and organization fields of the certificate.
//
// Returns PEM encoded X.509 certificate and private key pair.
//
// Note: While writing the binary cert/key pair to file system, it is useful to use standard naming like: 'cert.pem', 'key.pem'.
func GenCA(host string, validFor time.Duration, keyLength int, cn, org string) (cert, key []byte, err error) {
	return nil, nil, nil
}

// GenSigningCert generates an intermediate signing certificate for signing server or client certificates.
// Returns PEM encoded X.509 certificate and private key pair.
func GenSigningCert() (cert, key []byte, err error) {
	return nil, nil, nil
}

// GenServerCert generates a hosting certificate for servers using TLS.
// Returns PEM encoded X.509 certificate and private key pair.
func GenServerCert() (cert, key []byte, err error) {
	return nil, nil, nil
}

// GenClientCert generates a client certificate signed by the provided signing certificate.
// Generated certificate will have its extended key usage set to 'client authentication' and will be ready for use in TLS client authentication.
// Returns PEM encoded X.509 certificate and private key pair.
func GenClientCert(signCert *x509.Certificate, signKey *rsa.PrivateKey) (cert, key []byte, err error) {
	return nil, nil, nil
}

func getBaseCert(host string, validFor time.Duration, keyLength int, cn, org string) (*x509.Certificate, *rsa.PrivateKey, error) {
	if keyLength == 0 {
		keyLength = 3248
	}

	privKey, err := rsa.GenerateKey(rand.Reader, keyLength)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to generate certificate private RSA key: %v", err)
	}

	notBefore := time.Now()
	notAfter := notBefore.Add(290 * 365 * 24 * time.Hour) //290 years
	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to generate the certificate serial number: %v", err)
	}

	if validFor != 0 {
		notAfter = notBefore.Add(validFor)
	}

	cert := x509.Certificate{
		BasicConstraintsValid: true,
		SerialNumber:          serialNumber,
		Subject: pkix.Name{
			CommonName:   cn,
			Organization: []string{org},
		},
		NotBefore: notBefore,
		NotAfter:  notAfter,
		KeyUsage:  x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
	}

	setHosts(host, &cert)

	return &cert, privKey, nil
}

func setHosts(host string, cert *x509.Certificate) {
	hosts := strings.Split(host, ",")
	for _, h := range hosts {
		if ip := net.ParseIP(h); ip != nil {
			cert.IPAddresses = append(cert.IPAddresses, ip)
		} else {
			cert.DNSNames = append(cert.DNSNames, h)
		}
	}
}

// genCert generates a PEM encoded X.509 certificate and private key pair (i.e. 'cert.pem', 'key.pem').
// This code is based on the sample from http://golang.org/src/crypto/tls/generate_cert.go (taken at Jan 30, 2015).
// If no private key is provided, the certificate is marked as self-signed CA.
// host = Comma-separated hostnames and IPs to generate a certificate for. i.e. "localhost,127.0.0.1"
// validFor = Validity period for the certificate. Defaults to time.Duration max (290 years).
// ca, caPriv = CA certificate/private key to sign the new certificate. If not given, the generated certificate will be a self-signed CA.
// keyLength = Key length for the new certificate. Defaults to 3248 bits RSA key.
// cn, org = Common name and organization fields of the certificate.
func genCert(host string, validFor time.Duration, ca *x509.Certificate, caPriv *rsa.PrivateKey, keyLength int, cn, org string) (pemBytes, privBytes []byte, err error) {
	cert, privKey, err := getBaseCert(host, validFor, keyLength, cn, org)

	cert.IsCA = ca == nil
	signerCert := cert
	signerPriv := privKey
	if cert.IsCA {
		cert.KeyUsage |= x509.KeyUsageCertSign
		cert.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}
	} else {
		cert.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}
		signerCert = ca
		signerPriv = caPriv
	}

	derBytes, err := x509.CreateCertificate(rand.Reader, cert, signerCert, &privKey.PublicKey, signerPriv)
	if err != nil {
		return nil, nil, err
	}

	pemBytes = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
	privBytes = pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privKey)})
	return
}
<|endoftext|>


<commit_before>package ezdb

import (
	"errors"
	"fmt"
	"github.com/jmhodges/levigo"
	"strconv"
)

var (
	DefCacheSize int = 1024 * 1024 * 16
)

type DB struct {
	LevigoDB *levigo.DB
	ro       *levigo.ReadOptions
	roIt     *levigo.ReadOptions
	wo       *levigo.WriteOptions
	cache    *levigo.Cache
}

var DEBUG = true

var ERR_KEY_DOES_NOT_EXIST = "key does not exist"

func Open(path string, cacheSize int) (db *DB, err error) {
	db = new(DB)

	if db.cache = levigo.NewLRUCache(cacheSize); db.cache == nil {
		err = errors.New("levigo.NewLRUCache() == nil")
		if DEBUG {
			fmt.Println(err)
		}
		return nil, err
	}
	opts := levigo.NewOptions()
	opts.SetCache(db.cache)
	opts.SetCreateIfMissing(true)

	if db.LevigoDB, err = levigo.Open(path, opts); err != nil {
		fmt.Println(err)
		return nil, err
	}

	db.ro = levigo.NewReadOptions()
	db.roIt = levigo.NewReadOptions()
	db.roIt.SetFillCache(false)
	db.wo = levigo.NewWriteOptions()

	return db, err
}

// Close an ezdb.DB database.
func (db *DB) Close() {
	if db == nil {
		return
	}

	if db.roIt != nil {
		db.roIt.Close()
	}

	if db.ro != nil {
		db.ro.Close()
	}

	if db.wo != nil {
		db.wo.Close()
	}

	if db.LevigoDB != nil {
		db.LevigoDB.Close()
	}
	// delete cache AFTER delete db or it will hang.
	// See cache in http://leveldb.googlecode.com/svn/trunk/doc/index.html
	if db.cache != nil {
		db.cache.Close()
	}
}

func (db *DB) Put(key, value []byte) (err error) {
	return db.LevigoDB.Put(db.wo, key, value)
}

func (db *DB) Get(key []byte) (value []byte, err error) {
	return db.LevigoDB.Get(db.ro, key)
}

func (db *DB) Delete(key []byte) (err error) {
	return db.LevigoDB.Delete(db.wo, key)
}

func (db *DB) PutStr(key, value string) (err error) {
	return db.Put([]byte(key), []byte(value))
}

func (db *DB) KeyExist(key string) (exist bool, err error) {
	v, err := db.Get([]byte(key))
	if err != nil {
		return false, err
	}

	if v == nil {
		return false, nil
	} else {
		return true, nil
	}
}

func (db *DB) GetStr(key string) (value string, err error) {
	v, err := db.Get([]byte(key))
	if v == nil {
		return "", errors.New(ERR_KEY_DOES_NOT_EXIST)
	} else {
		return string(v), err
	}
}

func (db *DB) PutInt64(key string, value int64) (err error) {
	s := strconv.FormatInt(value, 10)
	return db.PutStr(key, s)
}

func (db *DB) GetInt64(key string) (value int64, err error) {
	s, err := db.GetStr(key)
	if err != nil {
		return 0, err
	}
	return strconv.ParseInt(s, 10, 64)
}

func (db *DB) PutUint64(key string, value uint64) (err error) {
	s := strconv.FormatUint(value, 10)
	return db.PutStr(key, s)
}

func (db *DB) GetUint64(key string) (value uint64, err error) {
	s, err := db.GetStr(key)
	if err != nil {
		return 0, err
	}
	return strconv.ParseUint(s, 10, 64)
}

func (db *DB) DeleteStr(key string) (err error) {
	return db.Delete([]byte(key))
}

func (db *DB) NewIterator() *levigo.Iterator {
	return db.LevigoDB.NewIterator(db.roIt)
}
<commit_msg>Create DB folder if it does not exist in Open()<commit_after>package ezdb

import (
	"errors"
	"github.com/jmhodges/levigo"
	"github.com/northbright/fnlog"
	"github.com/northbright/pathhelper"
	"log"
	"os"
	"path"
	"path/filepath"
	"strconv"
)

var (
	DefCacheSize          int = 1024 * 1024 * 16
	logger                *log.Logger
	DefDBFolderPermission os.FileMode = 0755
)

type DB struct {
	LevigoDB *levigo.DB
	ro       *levigo.ReadOptions
	roIt     *levigo.ReadOptions
	wo       *levigo.WriteOptions
	cache    *levigo.Cache
}

var DEBUG = true

var ERR_KEY_DOES_NOT_EXIST = "key does not exist"

func Open(dbPath string, cacheSize int) (db *DB, err error) {
	db = new(DB)

	if db.cache = levigo.NewLRUCache(cacheSize); db.cache == nil {
		err = errors.New("levigo.NewLRUCache() == nil")
		if DEBUG {
			logger.Println(err)
		}
		return nil, err
	}
	opts := levigo.NewOptions()
	opts.SetCache(db.cache)
	opts.SetCreateIfMissing(true)

	// Create DB folder if it does not exist
	absPath := ""
	if !filepath.IsAbs(dbPath) {
		currentDir := ""
		if currentDir, err = pathhelper.GetCurrentExecDir(); err != nil {
			logger.Printf("pathhelper.GetCurrentExeDir() err: %v", err)
			return nil, err
		}
		absPath = path.Join(currentDir, dbPath)
	} else {
		absPath = dbPath
	}

	if err = os.MkdirAll(absPath, DefDBFolderPermission); err != nil {
		logger.Printf("os.MkDirAll(%v, %v) err: %v", absPath, DefDBFolderPermission, err)
		return nil, err
	}

	if db.LevigoDB, err = levigo.Open(absPath, opts); err != nil {
		logger.Println(err)
		return nil, err
	}

	db.ro = levigo.NewReadOptions()
	db.roIt = levigo.NewReadOptions()
	db.roIt.SetFillCache(false)
	db.wo = levigo.NewWriteOptions()

	return db, err
}

// Close an ezdb.DB database.
func (db *DB) Close() {
	if db == nil {
		return
	}

	if db.roIt != nil {
		db.roIt.Close()
	}

	if db.ro != nil {
		db.ro.Close()
	}

	if db.wo != nil {
		db.wo.Close()
	}

	if db.LevigoDB != nil {
		db.LevigoDB.Close()
	}
	// delete cache AFTER delete db or it will hang.
	// See cache in http://leveldb.googlecode.com/svn/trunk/doc/index.html
	if db.cache != nil {
		db.cache.Close()
	}
}

func (db *DB) Put(key, value []byte) (err error) {
	return db.LevigoDB.Put(db.wo, key, value)
}

func (db *DB) Get(key []byte) (value []byte, err error) {
	return db.LevigoDB.Get(db.ro, key)
}

func (db *DB) Delete(key []byte) (err error) {
	return db.LevigoDB.Delete(db.wo, key)
}

func (db *DB) PutStr(key, value string) (err error) {
	return db.Put([]byte(key), []byte(value))
}

func (db *DB) KeyExist(key string) (exist bool, err error) {
	v, err := db.Get([]byte(key))
	if err != nil {
		return false, err
	}

	if v == nil {
		return false, nil
	} else {
		return true, nil
	}
}

func (db *DB) GetStr(key string) (value string, err error) {
	v, err := db.Get([]byte(key))
	if v == nil {
		return "", errors.New(ERR_KEY_DOES_NOT_EXIST)
	} else {
		return string(v), err
	}
}

func (db *DB) PutInt64(key string, value int64) (err error) {
	s := strconv.FormatInt(value, 10)
	return db.PutStr(key, s)
}

func (db *DB) GetInt64(key string) (value int64, err error) {
	s, err := db.GetStr(key)
	if err != nil {
		return 0, err
	}
	return strconv.ParseInt(s, 10, 64)
}

func (db *DB) PutUint64(key string, value uint64) (err error) {
	s := strconv.FormatUint(value, 10)
	return db.PutStr(key, s)
}

func (db *DB) GetUint64(key string) (value uint64, err error) {
	s, err := db.GetStr(key)
	if err != nil {
		return 0, err
	}
	return strconv.ParseUint(s, 10, 64)
}

func (db *DB) DeleteStr(key string) (err error) {
	return db.Delete([]byte(key))
}

func (db *DB) NewIterator() *levigo.Iterator {
	return db.LevigoDB.NewIterator(db.roIt)
}

func init() {
	logger = fnlog.New("")
}
<|endoftext|>


<commit_before>package jdb

import (
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"sync"
	"time"
)

var (
	ErrReadOnly           = errors.New("readonly")
	ErrNotImpl            = errors.New("not implemented")
	ErrNilValue           = errors.New("value can't be nil")
	ErrClosed             = errors.New("db is closed, you may access read-only operations")
	ErrMissingMarshaler   = errors.New("missing marshaler")
	ErrMissingUnmarshaler = errors.New("missing unmarshaler")
)

//type Bucket map[string]Value

type DB struct {
	mux sync.RWMutex
	f   *os.File

	root bucket

	maxIndex uint64

	txPool sync.Pool

	opts  Opts
	be    Backend
	stats struct {
		Rollbacks int64
		Commits   int64
	}
}

func New(fp string, opts *Opts) (*DB, error) {
	f, err := os.OpenFile(fp, os.O_CREATE|os.O_RDWR, 0600)
	if err != nil {
		return nil, err
	}

	if opts == nil {
		opts = &Opts{}
	}
	if opts.Backend == nil {
		opts.Backend = JSONBackend
	}

	db := &DB{
		opts: *opts,
		f:    f,
		be:   opts.Backend(),
	}

	if err = db.be.Init(f, f); err != nil {
		return nil, err
	}

	db.txPool.New = func() interface{} { return db.createTx() }

	if err = db.load(); err != nil {
		return nil, err
	}
	db.maxIndex++
	_, err = db.f.Seek(0, os.SEEK_END)
	return db, err
}

func (db *DB) load() error {
	st, err := db.f.Stat()
	if err != nil {
		return err
	}

	if st.Size() == 0 {
		return nil
	}

	db.f.Seek(0, os.SEEK_SET)
	for {
		var tx fileTx
		err := db.be.Decode(&tx)
		if err != nil {
			if err == io.EOF {
				err = nil
			}
			return err
		}

		db.applyTx(tx.Changeset, &db.root)
		db.maxIndex = tx.Index
	}
}

func (db *DB) createTx() *Tx {
	return &Tx{
		BucketTx: BucketTx{
			db: db,

			tmpBucket:  &bucket{},
			realBucket: &db.root,
		},
	}
}

func (db *DB) getTx(rw bool) *Tx {
	tx := db.txPool.Get().(*Tx)
	tx.rw = rw
	return tx
}

func (db *DB) putTx(tx *Tx) {
	if tb := tx.tmpBucket; tb != nil {
		for k := range tb.Buckets {
			delete(tb.Buckets, k)
		}
		for k := range tb.Data {
			delete(tb.Data, k)
		}
	}
	db.txPool.Put(tx)
}

func (db *DB) applyTx(src, dst *bucket) {
	for k, v := range src.Data {
		if v == nil {
			dst.Delete(k)
		} else {
			if db.opts.CopyOnSet {
				v = v.Copy()
			}
			dst.Set(k, v)
		}
	}

	for bn, b := range src.Buckets {
		if b == nil {
			dst.DeleteBucket(bn)
		} else {
			db.applyTx(b, dst.Bucket(bn))
		}
	}
}

func (db *DB) writeTx(tx *Tx) error {
	curPos, err := db.f.Seek(0, os.SEEK_CUR)
	if err != nil {
		return err
	}

	if err := db.be.Encode(&fileTx{
		Index:     db.maxIndex,
		TS:        time.Now().Unix(),
		Changeset: tx.tmpBucket,
	}); err != nil {
		db.stats.Rollbacks++
		db.f.Truncate(curPos)
		return err
	}

	if err := db.be.Flush(); err != nil {
		db.stats.Rollbacks++
		db.f.Truncate(curPos)
		return err
	}

	if err := db.f.Sync(); err != nil {
		db.stats.Rollbacks++
		db.f.Truncate(curPos)
		return err
	}

	db.applyTx(tx.tmpBucket, &db.root)
	db.stats.Commits++
	db.maxIndex++
	return nil
}

func (db *DB) Read(fn func(tx *Tx) error) error {
	tx := db.getTx(false)
	db.mux.RLock()
	defer func() {
		db.mux.RUnlock()
		db.putTx(tx)
	}()
	return fn(tx)
}

func (db *DB) Update(fn func(tx *Tx) error) error {
	tx := db.getTx(true)
	db.mux.Lock()
	defer func() {
		db.mux.Unlock()
		db.putTx(tx)
	}()
	if db.isClosed() {
		return ErrClosed
	}
	if err := fn(tx); err != nil {
		db.stats.Rollbacks++
		return err
	}
	return db.writeTx(tx)
}

// Get is a shorthand access a value in an optional bucket chain.
//	Example: v := db.Get("name", "users", "user-id-1")
func (db *DB) Get(key string, bucket ...string) Value {
	db.mux.RLock()
	defer db.mux.RUnlock()
	b := &db.root
	for _, bn := range bucket {
		if b = b.Buckets[bn]; b == nil {
			return nil
		}
	}
	return b.Get(key)
}

func (db *DB) GetObject(key string, out interface{}, bucket ...string) error {
	v := db.Get(key, bucket...)
	return db.be.Unmarshal(v, out)
}

// Set is a shorthand for an Update call with an optional Bucket chain.
//	Example: v := db.Set("name", Value("Moonknight"), "users", "user-id-1")
func (db *DB) Set(key string, val []byte, bucket ...string) error {
	return db.Update(func(tx *Tx) error {
		b := tx.tmpBucket
		for _, bn := range bucket {
			b = b.Bucket(bn)
		}
		b.Set(key, val)
		return nil
	})
}

func (db *DB) SetObject(key string, val interface{}, bucket ...string) error {
	v, err := db.be.Marshal(val)
	if err != nil {
		return err
	}
	return db.Set(key, v, bucket...)
}

func (db *DB) isClosed() bool {
	return int(db.f.Fd()) < 0
}

func (db *DB) Close() error {
	db.mux.Lock()
	err := db.close()
	db.mux.Unlock()
	return err
}

func (db *DB) close() error {
	if c, ok := db.be.(io.Closer); ok {
		if err := c.Close(); err != nil {
			return err
		}
	}
	return db.f.Close()
}

// Compact compacts the database, transactions will be lost, however the counter will still be valid.
func (db *DB) Compact() error {
	db.mux.Lock()
	f, err := ioutil.TempFile(filepath.Dir(db.f.Name()), "jdb-compact")

	defer func() {
		db.mux.Unlock()
		if err != nil {
			f.Close()
			os.Remove(f.Name())
		}
	}()

	if err != nil {
		return err
	}

	cp := db.opts.Backend()

	if err = cp.Init(f, f); err != nil {
		return err
	}

	if err = cp.Encode(&fileTx{
		Index:     db.maxIndex,
		TS:        time.Now().Unix(),
		Changeset: &db.root,
		Compact:   true,
	}); err != nil {
		return err
	}

	if err = cp.Flush(); err != nil {
		return err
	}

	if err = f.Sync(); err != nil {
		return err
	}

	db.close()

	if err := os.Rename(f.Name(), db.f.Name()); err != nil {
		f.Close()
		return &CompactError{f.Name(), db.f.Name(), err}
	}

	db.f, db.be = f, cp
	return nil
}

type CompactError struct {
	OldPath string
	NewPath string
	Err     error
}

func (ce *CompactError) Error() string {
	return fmt.Sprintf("rename error (%v), old path: %s, new path: %s", ce.Err, ce.OldPath, ce.NewPath)
}
<commit_msg>stop breaking backends that read/write extra metadata<commit_after>package jdb

import (
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"sync"
	"time"
)

var (
	ErrReadOnly           = errors.New("readonly")
	ErrNotImpl            = errors.New("not implemented")
	ErrNilValue           = errors.New("value can't be nil")
	ErrClosed             = errors.New("db is closed, you may access read-only operations")
	ErrMissingMarshaler   = errors.New("missing marshaler")
	ErrMissingUnmarshaler = errors.New("missing unmarshaler")
)

//type Bucket map[string]Value

type DB struct {
	mux sync.RWMutex
	f   *os.File

	root bucket

	maxIndex uint64

	txPool sync.Pool

	opts  Opts
	be    Backend
	stats struct {
		Rollbacks int64
		Commits   int64
	}
}

func New(fp string, opts *Opts) (*DB, error) {
	f, err := os.OpenFile(fp, os.O_CREATE|os.O_RDWR, 0600)
	if err != nil {
		return nil, err
	}

	if opts == nil {
		opts = &Opts{}
	}
	if opts.Backend == nil {
		opts.Backend = JSONBackend
	}

	db := &DB{
		opts: *opts,
		f:    f,
		be:   opts.Backend(),
	}

	if err = db.be.Init(f, f); err != nil {
		return nil, err
	}

	db.txPool.New = func() interface{} { return db.createTx() }

	if err = db.load(); err != nil {
		return nil, err
	}
	db.maxIndex++
	_, err = db.f.Seek(0, os.SEEK_END)
	return db, err
}

func (db *DB) load() error {
	st, err := db.f.Stat()
	if err != nil {
		return err
	}

	if st.Size() == 0 {
		return nil
	}

	for {
		var tx fileTx
		err := db.be.Decode(&tx)
		if err != nil {
			if err == io.EOF {
				err = nil
			}
			return err
		}

		db.applyTx(tx.Changeset, &db.root)
		db.maxIndex = tx.Index
	}
}

func (db *DB) createTx() *Tx {
	return &Tx{
		BucketTx: BucketTx{
			db: db,

			tmpBucket:  &bucket{},
			realBucket: &db.root,
		},
	}
}

func (db *DB) getTx(rw bool) *Tx {
	tx := db.txPool.Get().(*Tx)
	tx.rw = rw
	return tx
}

func (db *DB) putTx(tx *Tx) {
	if tb := tx.tmpBucket; tb != nil {
		for k := range tb.Buckets {
			delete(tb.Buckets, k)
		}
		for k := range tb.Data {
			delete(tb.Data, k)
		}
	}
	db.txPool.Put(tx)
}

func (db *DB) applyTx(src, dst *bucket) {
	for k, v := range src.Data {
		if v == nil {
			dst.Delete(k)
		} else {
			if db.opts.CopyOnSet {
				v = v.Copy()
			}
			dst.Set(k, v)
		}
	}

	for bn, b := range src.Buckets {
		if b == nil {
			dst.DeleteBucket(bn)
		} else {
			db.applyTx(b, dst.Bucket(bn))
		}
	}
}

func (db *DB) writeTx(tx *Tx) error {
	curPos, err := db.f.Seek(0, os.SEEK_CUR)
	if err != nil {
		return err
	}

	if err := db.be.Encode(&fileTx{
		Index:     db.maxIndex,
		TS:        time.Now().Unix(),
		Changeset: tx.tmpBucket,
	}); err != nil {
		db.stats.Rollbacks++
		db.f.Truncate(curPos)
		return err
	}

	if err := db.be.Flush(); err != nil {
		db.stats.Rollbacks++
		db.f.Truncate(curPos)
		return err
	}

	if err := db.f.Sync(); err != nil {
		db.stats.Rollbacks++
		db.f.Truncate(curPos)
		return err
	}

	db.applyTx(tx.tmpBucket, &db.root)
	db.stats.Commits++
	db.maxIndex++
	return nil
}

func (db *DB) Read(fn func(tx *Tx) error) error {
	tx := db.getTx(false)
	db.mux.RLock()
	defer func() {
		db.mux.RUnlock()
		db.putTx(tx)
	}()
	return fn(tx)
}

func (db *DB) Update(fn func(tx *Tx) error) error {
	tx := db.getTx(true)
	db.mux.Lock()
	defer func() {
		db.mux.Unlock()
		db.putTx(tx)
	}()
	if db.isClosed() {
		return ErrClosed
	}
	if err := fn(tx); err != nil {
		db.stats.Rollbacks++
		return err
	}
	return db.writeTx(tx)
}

// Get is a shorthand access a value in an optional bucket chain.
//	Example: v := db.Get("name", "users", "user-id-1")
func (db *DB) Get(key string, bucket ...string) Value {
	db.mux.RLock()
	defer db.mux.RUnlock()
	b := &db.root
	for _, bn := range bucket {
		if b = b.Buckets[bn]; b == nil {
			return nil
		}
	}
	return b.Get(key)
}

func (db *DB) GetObject(key string, out interface{}, bucket ...string) error {
	v := db.Get(key, bucket...)
	return db.be.Unmarshal(v, out)
}

// Set is a shorthand for an Update call with an optional Bucket chain.
//	Example: v := db.Set("name", Value("Moonknight"), "users", "user-id-1")
func (db *DB) Set(key string, val []byte, bucket ...string) error {
	return db.Update(func(tx *Tx) error {
		b := tx.tmpBucket
		for _, bn := range bucket {
			b = b.Bucket(bn)
		}
		b.Set(key, val)
		return nil
	})
}

func (db *DB) SetObject(key string, val interface{}, bucket ...string) error {
	v, err := db.be.Marshal(val)
	if err != nil {
		return err
	}
	return db.Set(key, v, bucket...)
}

func (db *DB) isClosed() bool {
	return int(db.f.Fd()) < 0
}

func (db *DB) Close() error {
	db.mux.Lock()
	err := db.close()
	db.mux.Unlock()
	return err
}

func (db *DB) close() error {
	if c, ok := db.be.(io.Closer); ok {
		if err := c.Close(); err != nil {
			return err
		}
	}
	return db.f.Close()
}

// Compact compacts the database, transactions will be lost, however the counter will still be valid.
func (db *DB) Compact() error {
	db.mux.Lock()
	f, err := ioutil.TempFile(filepath.Dir(db.f.Name()), "jdb-compact")

	defer func() {
		db.mux.Unlock()
		if err != nil {
			f.Close()
			os.Remove(f.Name())
		}
	}()

	if err != nil {
		return err
	}

	cp := db.opts.Backend()

	if err = cp.Init(f, f); err != nil {
		return err
	}

	if err = cp.Encode(&fileTx{
		Index:     db.maxIndex,
		TS:        time.Now().Unix(),
		Changeset: &db.root,
		Compact:   true,
	}); err != nil {
		return err
	}

	if err = cp.Flush(); err != nil {
		return err
	}

	if err = f.Sync(); err != nil {
		return err
	}

	db.close()

	if err := os.Rename(f.Name(), db.f.Name()); err != nil {
		f.Close()
		return &CompactError{f.Name(), db.f.Name(), err}
	}

	db.f, db.be = f, cp
	return nil
}

type CompactError struct {
	OldPath string
	NewPath string
	Err     error
}

func (ce *CompactError) Error() string {
	return fmt.Sprintf("rename error (%v), old path: %s, new path: %s", ce.Err, ce.OldPath, ce.NewPath)
}
<|endoftext|>


<commit_before>// In computing, a disjoint-set data structure (or union find data structure) is a data structure that keeps track of a set of elements partitioned into a number of disjoint (nonoverlapping) subsets. A union-find algorithm is an algorithm that performs two useful operations on such a data structure:
//
//  Find  - determine which subset a particular element is in. This can be used for determining if two elements are in the same subset.
//  Union - join two subsets into a single subset.
package djs

// A type, typically a collection. This is the minimum contract any structure needs to conform in order
// to be used as underlaying data structure for union-find algorithm.
// Path compression is the only iprovement applied in this case.
type Interface interface {
	// Sets parent p to element c
	SetParent(c, p interface{})
	// Returns back a parent of element
	GetParent(c interface{}) interface{}
}

// Adds iteration to optionally perform initial state setup
type InitInterface interface {
	Interface
	Each(func(a interface{}))
}

// Additional methods to enable "union by rank".
type RankInterface interface {
	Interface
	GetRank(a interface{}) int
	SetRank(a interface{}, rank int)
}

func Init(u InitInterface) {
	u.Each(func(a interface{}) {
		u.SetParent(a, a)
		if g, ok := u.(RankInterface); ok {
			g.SetRank(a, 0)
		}
	})
}

func root(u Interface, a interface{}) interface{} {
	for ; a != u.GetParent(a); a = u.GetParent(a) {
		u.SetParent(a, u.GetParent(u.GetParent(a)))
	}
	return a
}

//  Determine which subset a particular element is in. This can be used for determining if two elements are in the same subset.
func Find(u Interface, a interface{}) interface{} {
	return root(u, a)
}

// Convenient method that compares result of Find for both elements.
func Connected(u Interface, a, b interface{}) bool {
	return root(u, a) == root(u, b)
}

// Join two subsets into a single subset.
func Union(u Interface, a, b interface{}) {
	aa := Find(u, a)
	bb := Find(u, b)

	if g, ok := u.(RankInterface); ok {
		ra := g.GetRank(aa)
		rb := g.GetRank(bb)
		if ra > rb {
			u.SetParent(bb, aa)
		} else if ra < rb {
			u.SetParent(aa, bb)
		} else {
			g.SetRank(aa, ra+1)
			u.SetParent(bb, aa)
		}
	} else {
		u.SetParent(aa, bb)
	}
}

// Convenience types for common cases

// UnionInt attaches the methods of Interface to []int
type UnionInt []int

func (m UnionInt) SetParent(c, p interface{})          { m[c.(int)] = p.(int) }
func (m UnionInt) GetParent(c interface{}) interface{} { return m[c.(int)] }

func (m UnionInt) Each(fn func(a interface{})) {
	for a := range m {
		fn(a)
	}
}

type rankUnion struct {
	sets  []int
	ranks []int
}

func (m *rankUnion) SetParent(c, p interface{})          { m.sets[c.(int)] = p.(int) }
func (m *rankUnion) GetParent(c interface{}) interface{} { return m.sets[c.(int)] }
func (m *rankUnion) SetRank(a interface{}, rank int)     { m.ranks[a.(int)] = rank }
func (m *rankUnion) GetRank(a interface{}) int           { return m.ranks[a.(int)] }
func (m *rankUnion) Each(fn func(a interface{})) {
	for a := range m.sets {
		fn(a)
	}
}

func NewRankUnion(size int) *rankUnion {
	ret := &rankUnion{sets: make([]int, size), ranks: make([]int, size)}
	Init(ret)
	return ret
}
<commit_msg>doc update<commit_after>// A disjoint-set data structure is a data structure that keeps track of a set of elements partitioned into a number of disjoint (nonoverlapping) subsets.
// A union-find algorithm is an algorithm that performs two useful operations on such a data structure:
//
//  Find  - determine which subset a particular element is in. This can be used for determining if two elements are in the same subset.
//  Union - join two subsets into a single subset.
package djs

// Interface is the minimum contract any structure needs to conform in order
// to be used as underlaying data structure for union-find algorithm.
// Path compression is the only improvement applied in this case.
type Interface interface {
	// Sets parent p to element c
	SetParent(c, p interface{})
	// Returns back a parent of element
	GetParent(c interface{}) interface{}
}

// InitInterface enables iteration to perform initial state setup
type InitInterface interface {
	Interface
	Each(func(a interface{}))
}

// RankInterface with more methods to enable "union by rank".
type RankInterface interface {
	Interface
	GetRank(a interface{}) int
	SetRank(a interface{}, rank int)
}

// Init sets all elements parent to itself (i.e. 1->1, 2->2, 3->3, ...) via SetParent(...) to achieve proper initial state
func Init(u InitInterface) {
	u.Each(func(a interface{}) {
		u.SetParent(a, a)
		if g, ok := u.(RankInterface); ok {
			g.SetRank(a, 0)
		}
	})
}

func root(u Interface, a interface{}) interface{} {
	for ; a != u.GetParent(a); a = u.GetParent(a) {
		u.SetParent(a, u.GetParent(u.GetParent(a)))
	}
	return a
}

//  Find determines which subset a particular element is in. This can be used for determining if two elements are in the same subset.
func Find(u Interface, a interface{}) interface{} {
	return root(u, a)
}

// Connected is a convenient method that compares result of Find for both elements.
func Connected(u Interface, a, b interface{}) bool {
	return root(u, a) == root(u, b)
}

// Union joins two subsets into a single subset.
func Union(u Interface, a, b interface{}) {
	aa := Find(u, a)
	bb := Find(u, b)

	if g, ok := u.(RankInterface); ok {
		ra := g.GetRank(aa)
		rb := g.GetRank(bb)
		if ra > rb {
			u.SetParent(bb, aa)
		} else if ra < rb {
			u.SetParent(aa, bb)
		} else {
			g.SetRank(aa, ra+1)
			u.SetParent(bb, aa)
		}
	} else {
		u.SetParent(aa, bb)
	}
}

// Convenience types for common cases

// UnionInt attaches the methods of Interface to []int
type UnionInt []int

func (m UnionInt) SetParent(c, p interface{})          { m[c.(int)] = p.(int) }
func (m UnionInt) GetParent(c interface{}) interface{} { return m[c.(int)] }

func (m UnionInt) Each(fn func(a interface{})) {
	for a := range m {
		fn(a)
	}
}

type rankUnion struct {
	sets  []int
	ranks []int
}

func (m *rankUnion) SetParent(c, p interface{})          { m.sets[c.(int)] = p.(int) }
func (m *rankUnion) GetParent(c interface{}) interface{} { return m.sets[c.(int)] }
func (m *rankUnion) SetRank(a interface{}, rank int)     { m.ranks[a.(int)] = rank }
func (m *rankUnion) GetRank(a interface{}) int           { return m.ranks[a.(int)] }
func (m *rankUnion) Each(fn func(a interface{})) {
	for a := range m.sets {
		fn(a)
	}
}

// NewRankUnion creates a convenient structure of specified size containing elements of type int. The structure also supports ranking.
func NewRankUnion(size int) *rankUnion {
	ret := &rankUnion{sets: make([]int, size), ranks: make([]int, size)}
	Init(ret)
	return ret
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"http"
	"log"
	"net"
	"rpc"
	"rpc/jsonrpc"
	"sync"
	"time"

	"github.com/bytbox/procfs.go/procfs"
)

var pfs *procfs.ProcFS
var pfsMutex sync.Mutex
var interval = flag.Int64("interval", 10, "update interval")
var jsonrpc_port = flag.String("jsonrpc", ":16070", "JSON-RPC service port")
var http_port = flag.String("http", ":6070", "HTTP service port")

func main() {
	flag.Parse()

	go updater()
	go serveRPC()
	go serveHTTP()

/*
	var pfs procfs.ProcFS
	pfs.Fill()
	str, err := json.MarshalIndent(pfs, "", "  ")
	if err != nil {
		log.Fatal("ERR: ", err)
	}
	println(string(str))
*/

	<-make(chan int)
}

// Maintain an updated version of ProcFS
func updater() {
	ticker := time.Tick(1e9 * *interval)
	for true {
		log.Print("Updating...")
		sn := time.Nanoseconds()
		var pfs2 procfs.ProcFS
		pfs2.Fill()
		pfsMutex.Lock()
		pfs = &pfs2
		pfsMutex.Unlock()
		en := time.Nanoseconds()
		log.Print("Done in ", (en-sn)/1000, "μs")
		<-ticker
	}
}

type ProcFSServer struct {}

func (ProcFSServer) Get(req string, reply *procfs.ProcFS) error {
	reply = pfs
	return nil
}

// Runs the JSON-RPC server
func serveRPC() {
	server := ProcFSServer{}
	rpc.Register(server)

	l, err := net.Listen("tcp", *jsonrpc_port)
	if err != nil {
		log.Fatal("ERR: ", err)
	}

	for {
		c, err := l.Accept()
		if err != nil {
			log.Print("WARN: ", err)
			continue
		}

		log.Print("Serving ", c.RemoteAddr())
		go jsonrpc.ServeConn(c)
	}
}

func serveHTTP() {

}
<commit_msg>Some progress<commit_after>package main

import (
	"flag"
	"http"
	"io"
	"io/ioutil"
	"log"
	"rpc"
	"rpc/jsonrpc"
	"sync"
	"time"

	"github.com/bytbox/procfs.go/procfs"
)

var pfs *procfs.ProcFS
var pfsMutex sync.Mutex
var interval = flag.Int64("interval", 10, "update interval")
var http_port = flag.String("http", ":6070", "HTTP service port")

func main() {
	flag.Parse()

	go updater()
	go serveHTTP()

	<-make(chan int)
}

// Maintain an updated version of ProcFS
func updater() {
	ticker := time.Tick(1e9 * *interval)
	for true {
		log.Print("Updating...")
		sn := time.Nanoseconds()
		var pfs2 procfs.ProcFS
		pfs2.Fill()
		pfsMutex.Lock()
		pfs = &pfs2
		pfsMutex.Unlock()
		en := time.Nanoseconds()
		log.Print("Done in ", (en-sn)/1000, "μs")
		<-ticker
	}
}

type ProcFSServer struct {}

func (ProcFSServer) Get(req string, reply *procfs.ProcFS) error {
	reply = pfs
	return nil
}

func serveHTTP() {
	server := ProcFSServer{}
	rpc.RegisterName("ProcFS", server)
	http.HandleFunc("/", HTMLServer)
	http.HandleFunc("/jsonrpc.js", JSServer)
	http.HandleFunc("/_goRPC_", RPCServer)

	err := http.ListenAndServe(*http_port, http.DefaultServeMux)
	if err != nil {
		log.Print("ERR: ", err)
	}
}

func HTMLServer(w http.ResponseWriter, req *http.Request) {
	c, err := ioutil.ReadFile("html/proc.html")
	if err != nil {
		log.Fatal("ERR: html/index.html not openable")
		return
	}
	w.Write(c)
}

func JSServer(w http.ResponseWriter, req *http.Request) {
	c, err := ioutil.ReadFile("html/jsonrpc.js")
	if err != nil {
		log.Fatal("ERR: html/index.html not openable")
		return
	}
	w.Write(c)
}

func RPCServer(w http.ResponseWriter, req *http.Request) {
	h, _, err := w.(http.Hijacker).Hijack()
	if err != nil {
		log.Print("ERR: ", err)
	}
	connected := "200 Connected to JSON-RPC"
	io.WriteString(h, "HTTP/1.0 "+connected+"\n\n")
	codec := jsonrpc.NewServerCodec(h)
	rpc.ServeRequest(codec)
	h.Close()
}

<|endoftext|>