<commit_before>package main

import (
	"fmt"
	"flag"
	"io/ioutil"
	"os"
	"log"

	"github.com/coreos/coreos-cloudinit/cloudinit"
)

const version = "0.1.0"

func main() {
	var userdata []byte
	var err error

	var printVersion bool
	flag.BoolVar(&printVersion, "version", false, "Print the version and exit")

	var file string
	flag.StringVar(&file, "from-file", "", "Read user-data from provided file")

	var url string
	flag.StringVar(&url, "from-url", "", "Download user-data from provided url")

	var workspace string
	flag.StringVar(&workspace, "workspace", "/var/lib/coreos-cloudinit", "Base directory coreos-cloudinit should use to store data")

	flag.Parse()

	if printVersion == true {
		fmt.Printf("coreos-cloudinit version %s\n", version)
		os.Exit(0)
	}

	if file != "" && url != "" {
		fmt.Println("Provide one of --from-file or --from-url")
		os.Exit(1)
	}

	if file != "" {
		log.Printf("Reading user-data from file: %s", file)
		userdata, err = ioutil.ReadFile(file)
		if err != nil {
			log.Fatal(err.Error())
		}
	} else if url != "" {
		log.Printf("Reading user-data from metadata service")
		svc := cloudinit.NewMetadataService(url)
		userdata, err = svc.UserData()
		if err != nil {
			log.Fatal(err.Error())
		}
	} else {
		fmt.Println("Provide one of --from-file or --from-url")
		os.Exit(1)
	}

	parsed, err := cloudinit.ParseUserData(userdata)
	if err != nil {
		log.Fatalf("Failed parsing user-data: %v", err)
	}

	err = cloudinit.PrepWorkspace(workspace)
	if err != nil {
		log.Fatalf("Failed preparing workspace: %v", err)
	}

	switch t := parsed.(type) {
	case cloudinit.CloudConfig:
		err = cloudinit.ResolveCloudConfig(t)
	case cloudinit.Script:
		var path string
		path, err = cloudinit.PersistScriptInWorkspace(t, workspace)
		if err == nil {
			var name string
			name, err = cloudinit.ExecuteScript(path)
			cloudinit.PersistScriptUnitNameInWorkspace(name, workspace)
		}
	}

	if err != nil {
		log.Fatalf("Failed resolving user-data: %v", err)
	}
}
<commit_msg>chore(release): Bump version back to v0.1.0+git<commit_after>package main

import (
	"fmt"
	"flag"
	"io/ioutil"
	"os"
	"log"

	"github.com/coreos/coreos-cloudinit/cloudinit"
)

const version = "0.1.0+git"

func main() {
	var userdata []byte
	var err error

	var printVersion bool
	flag.BoolVar(&printVersion, "version", false, "Print the version and exit")

	var file string
	flag.StringVar(&file, "from-file", "", "Read user-data from provided file")

	var url string
	flag.StringVar(&url, "from-url", "", "Download user-data from provided url")

	var workspace string
	flag.StringVar(&workspace, "workspace", "/var/lib/coreos-cloudinit", "Base directory coreos-cloudinit should use to store data")

	flag.Parse()

	if printVersion == true {
		fmt.Printf("coreos-cloudinit version %s\n", version)
		os.Exit(0)
	}

	if file != "" && url != "" {
		fmt.Println("Provide one of --from-file or --from-url")
		os.Exit(1)
	}

	if file != "" {
		log.Printf("Reading user-data from file: %s", file)
		userdata, err = ioutil.ReadFile(file)
		if err != nil {
			log.Fatal(err.Error())
		}
	} else if url != "" {
		log.Printf("Reading user-data from metadata service")
		svc := cloudinit.NewMetadataService(url)
		userdata, err = svc.UserData()
		if err != nil {
			log.Fatal(err.Error())
		}
	} else {
		fmt.Println("Provide one of --from-file or --from-url")
		os.Exit(1)
	}

	parsed, err := cloudinit.ParseUserData(userdata)
	if err != nil {
		log.Fatalf("Failed parsing user-data: %v", err)
	}

	err = cloudinit.PrepWorkspace(workspace)
	if err != nil {
		log.Fatalf("Failed preparing workspace: %v", err)
	}

	switch t := parsed.(type) {
	case cloudinit.CloudConfig:
		err = cloudinit.ResolveCloudConfig(t)
	case cloudinit.Script:
		var path string
		path, err = cloudinit.PersistScriptInWorkspace(t, workspace)
		if err == nil {
			var name string
			name, err = cloudinit.ExecuteScript(path)
			cloudinit.PersistScriptUnitNameInWorkspace(name, workspace)
		}
	}

	if err != nil {
		log.Fatalf("Failed resolving user-data: %v", err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/chrneumann/mimemail"
	"github.com/monsti/form"
	"github.com/monsti/rpc/client"
	"github.com/monsti/util"
	"github.com/monsti/util/l10n"
	"github.com/monsti/util/template"
	htmlT "html/template"
	"log"
	"os"
	"path/filepath"
)

type cfsettings struct {
	// Absolute paths to used directories.
	Directories struct {
		// HTML Templates
		Templates string
		// Locales, i.e. the gettext machine objects (.mo)
		Locales string
	}
}

var renderer template.Renderer
var settings cfsettings

type contactFormData struct {
	Name, Email, Subject, Message string
}

func handle(req client.Request, res *client.Response, c client.Connection) {
	switch req.Action {
	case "edit":
		edit(req, res, c)
	default:
		view(req, res, c)
	}
}

func view(req client.Request, res *client.Response, c client.Connection) {
	G := l10n.UseCatalog(req.Session.Locale)
	data := contactFormData{}
	form := form.NewForm(&data, form.Fields{
		"Name":    form.Field{G("Name"), "", form.Required(G("Required.")), nil},
		"Email":   form.Field{G("Email"), "", form.Required(G("Required.")), nil},
		"Subject": form.Field{G("Subject"), "", form.Required(G("Required.")), nil},
		"Message": form.Field{G("Message"), "", form.Required(G("Required.")),
			new(form.TextArea)}})
	context := template.Context{}
	switch req.Method {
	case "GET":
		if _, submitted := req.Query["submitted"]; submitted {
			context["Submitted"] = 1
		}
	case "POST":
		if form.Fill(c.GetFormData()) {
			c.SendMail(mimemail.Mail{
				From:    mimemail.Address{data.Name, data.Email},
				Subject: data.Subject,
				Body:    []byte(data.Message)})
			res.Redirect = req.Node.Path + "/?submitted"
			return
		}
	default:
		panic("Request method not supported: " + req.Method)
	}
	res.Node = &req.Node
	body := c.GetNodeData(req.Node.Path, "body.html")
	context["Body"] = htmlT.HTML(string(body))
	context["Form"] = form.RenderData()
	fmt.Fprint(res, renderer.Render("contactform/view", context,
		req.Session.Locale, ""))
}

type editFormData struct {
	Title, Body string
}

func edit(req client.Request, res *client.Response, c client.Connection) {
	G := l10n.UseCatalog(req.Session.Locale)
	data := editFormData{}
	form := form.NewForm(&data, form.Fields{
		"Title": form.Field{G("Title"), "", form.Required(G("Required.")), nil},
		"Body": form.Field{G("Body"), "", form.Required(G("Required.")),
			new(form.AlohaEditor)}})
	switch req.Method {
	case "GET":
		data.Title = req.Node.Title
		data.Body = string(c.GetNodeData(req.Node.Path, "body.html"))
	case "POST":
		if form.Fill(c.GetFormData()) {
			node := req.Node
			node.Title = data.Title
			c.UpdateNode(node)
			c.WriteNodeData(req.Node.Path, "body.html", data.Body)
			res.Redirect = req.Node.Path
			return
		}
	default:
		panic("Request method not supported: " + req.Method)
	}
	fmt.Fprint(res, renderer.Render("contactform/edit",
		template.Context{"Form": form.RenderData()},
		req.Session.Locale, ""))
}

func main() {
	logger := log.New(os.Stderr, "contactform", log.LstdFlags)
	flag.Parse()
	cfgPath := util.GetConfigPath("contactform", flag.Arg(0))
	if err := util.ParseYAML(cfgPath, &settings); err != nil {
		logger.Fatal("Could not load monsti-contactform configuration file: ", err)
	}
	util.MakeAbsolute(&settings.Directories.Templates, filepath.Dir(cfgPath))
	util.MakeAbsolute(&settings.Directories.Locales, filepath.Dir(cfgPath))
	l10n.Setup("monsti-contactform", settings.Directories.Locales)
	renderer.Root = settings.Directories.Templates
	client.NewConnection("contactform", logger).Serve(handle)
}
<commit_msg>Refactor to use new service API.<commit_after>// This file is part of Monsti, a web content management system.
// Copyright 2012-2013 Christian Neumann
//
// Monsti is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option) any
// later version.
//
// Monsti is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
// A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
// details.
//
// You should have received a copy of the GNU Affero General Public License
// along with Monsti.  If not, see <http://www.gnu.org/licenses/>.

/*
 Monsti is a simple and resource efficient CMS.

 This package implements the contactform node type.
*/
package main

import (
	"flag"
	"fmt"
	"github.com/chrneumann/mimemail"
	"github.com/monsti/form"
	"github.com/monsti/service"
	"github.com/monsti/util"
	"github.com/monsti/util/l10n"
	"github.com/monsti/util/template"
	htmlT "html/template"
	"log"
	"os"
)

var settings struct {
	Monsti util.MonstiSettings
}

var logger *log.Logger
var renderer template.Renderer

type contactFormData struct {
	Name, Email, Subject, Message string
}

func view(req service.Request, res *service.Response, s *service.Session) {
	G := l10n.UseCatalog(req.Session.Locale)
	data := contactFormData{}
	form := form.NewForm(&data, form.Fields{
		"Name":    form.Field{G("Name"), "", form.Required(G("Required.")), nil},
		"Email":   form.Field{G("Email"), "", form.Required(G("Required.")), nil},
		"Subject": form.Field{G("Subject"), "", form.Required(G("Required.")), nil},
		"Message": form.Field{G("Message"), "", form.Required(G("Required.")),
			new(form.TextArea)}})
	context := template.Context{}
	switch req.Method {
	case "GET":
		if _, submitted := req.Query["submitted"]; submitted {
			context["Submitted"] = 1
		}
	case "POST":
		if form.Fill(req.FormData) {
			mail := mimemail.Mail{
				From:    mimemail.Address{data.Name, data.Email},
				Subject: data.Subject,
				Body:    []byte(data.Message)}
			site := settings.Monsti.Sites[req.Site]
			owner := mimemail.Address{site.Owner.Name, site.Owner.Email}
			mail.To = []mimemail.Address{owner}
			mail = mimemail.Mail{}
			err := s.Mail().SendMail(&mail)
			if err != nil {
				panic("Could not send mail: " + err.Error())
			}
			res.Redirect = req.Node.Path + "/?submitted"
			return
		}
	default:
		panic("Request method not supported: " + req.Method)
	}
	res.Node = &req.Node
	body, err := s.Data().GetNodeData(req.Site, req.Node.Path, "body.html")
	if err != nil {
		panic("Could not get node data: " + err.Error())
	}
	context["Body"] = htmlT.HTML(string(body))
	context["Form"] = form.RenderData()
	fmt.Fprint(res, renderer.Render("contactform/view", context,
		req.Session.Locale, ""))
}

type editFormData struct {
	Title, Body string
}

func edit(req service.Request, res *service.Response, s *service.Session) {
	G := l10n.UseCatalog(req.Session.Locale)
	data := editFormData{}
	form := form.NewForm(&data, form.Fields{
		"Title": form.Field{G("Title"), "", form.Required(G("Required.")), nil},
		"Body": form.Field{G("Body"), "", form.Required(G("Required.")),
			new(form.AlohaEditor)}})
	dataCli := s.Data()
	switch req.Method {
	case "GET":
		data.Title = req.Node.Title
		nodeData, err := dataCli.GetNodeData(req.Site, req.Node.Path, "body.html")
		if err != nil {
			panic("Could not get node data: " + err.Error())
		}
		data.Body = string(nodeData)
	case "POST":
		if form.Fill(req.FormData) {
			node := req.Node
			node.Title = data.Title
			if err := dataCli.UpdateNode(req.Site, node); err != nil {
				panic("Could not update node: " + err.Error())
			}
			if err := dataCli.WriteNodeData(req.Site, req.Node.Path, "body.html",
				data.Body); err != nil {
				panic("Could not update node data: " + err.Error())
			}
			res.Redirect = req.Node.Path
			return
		}
	default:
		panic("Request method not supported: " + req.Method)
	}
	fmt.Fprint(res, renderer.Render("contactform/edit",
		template.Context{"Form": form.RenderData()},
		req.Session.Locale, ""))
}

func main() {
	logger = log.New(os.Stderr, "contactform ", log.LstdFlags)
	// Load configuration
	flag.Parse()
	if flag.NArg() != 1 {
		logger.Fatal("Expecting configuration path.")
	}
	cfgPath := util.GetConfigPath(flag.Arg(0))
	if err := util.LoadModuleSettings("contactform", cfgPath, &settings); err != nil {
		logger.Fatal("Could not load settings: ", err)
	}
	if err := settings.Monsti.LoadSiteSettings(); err != nil {
		logger.Fatal("Could not load site settings: ", err)
	}

	infoPath := settings.Monsti.GetServicePath(service.Info.String())

	l10n.Setup("monsti", settings.Monsti.GetLocalePath())
	renderer.Root = settings.Monsti.GetTemplatesPath()

	provider := service.NewNodeProvider(logger, infoPath)
	contactform := service.NodeTypeHandler{
		Name:       "ContactForm",
		ViewAction: view,
		EditAction: edit,
	}
	provider.AddNodeType(&contactform)
	if err := provider.Serve(settings.Monsti.GetServicePath(
		service.Node.String() + "_contactform")); err != nil {
		panic("Could not setup node provider: " + err.Error())
	}
}
<|endoftext|>


<commit_before>package main

import (
       "fmt"
       "os"
       "bufio"
)

func main () {
     counts := make(map[string]int)
     input := bufio.NewScanner(os.Stdin)

     for input.Scan() {
     	 counts[input.Text()]++
     }

     // NOTE ignore errors from input.Err()

     for line, n := range counts {
     	 if n > 1 {
	    fmt.Printf("%d\t%s\n", n, line)
	 }
     }
}<commit_msg>comment<commit_after>package main

import (
       "fmt"
       "os"
       "bufio"
)

/*
 * Print lines that appear more than once.
 */

func main () {
     counts := make(map[string]int)
     input := bufio.NewScanner(os.Stdin)

     for input.Scan() {
     	 counts[input.Text()]++
     }

     // NOTE ignore errors from input.Err()

     for line, n := range counts {
     	 if n > 1 {
	    fmt.Printf("%d\t%s\n", n, line)
	 }
     }
}<|endoftext|>


<commit_before>// Copyright 2016 Hajime Hoshi
//
// 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.

// +build example

package main

import (
	"fmt"
	"image/color"
	"io/ioutil"
	"log"
	"time"

	"github.com/hajimehoshi/ebiten"
	"github.com/hajimehoshi/ebiten/audio"
	"github.com/hajimehoshi/ebiten/audio/vorbis"
	"github.com/hajimehoshi/ebiten/audio/wav"
	"github.com/hajimehoshi/ebiten/ebitenutil"
)

const (
	screenWidth  = 320
	screenHeight = 240

	// This sample rate doesn't match with wav/ogg's sample rate,
	// but decoders adjust them.
	sampleRate = 48000
)

var (
	playerBarImage     *ebiten.Image
	playerCurrentImage *ebiten.Image
)

func init() {
	playerBarImage, _ = ebiten.NewImage(300, 4, ebiten.FilterNearest)
	playerBarImage.Fill(&color.RGBA{0x80, 0x80, 0x80, 0xff})

	playerCurrentImage, _ = ebiten.NewImage(4, 10, ebiten.FilterNearest)
	playerCurrentImage.Fill(&color.RGBA{0xff, 0xff, 0xff, 0xff})
}

type Player struct {
	audioContext     *audio.Context
	audioPlayer      *audio.Player
	total            time.Duration
	seekedCh         chan error
	mouseButtonState map[ebiten.MouseButton]int
	keyState         map[ebiten.Key]int
	volume128        int
}

var (
	musicPlayer *Player
	seBytes     []byte
	seCh        = make(chan []byte)
)

func playerBarRect() (x, y, w, h int) {
	w, h = playerBarImage.Size()
	x = (screenWidth - w) / 2
	y = screenHeight - h - 16
	return
}

func NewPlayer(audioContext *audio.Context) (*Player, error) {
	const bytesPerSample = 4 // TODO: This should be defined in audio package
	oggF, err := ebitenutil.OpenFile("_resources/audio/game.ogg")
	if err != nil {
		return nil, err
	}
	s, err := vorbis.Decode(audioContext, oggF)
	if err != nil {
		return nil, err
	}
	p, err := audio.NewPlayer(audioContext, s)
	if err != nil {
		return nil, err
	}
	player := &Player{
		audioContext:     audioContext,
		audioPlayer:      p,
		total:            time.Second * time.Duration(s.Size()) / bytesPerSample / sampleRate,
		mouseButtonState: map[ebiten.MouseButton]int{},
		keyState:         map[ebiten.Key]int{},
		volume128:        128,
	}
	player.audioPlayer.Play()
	return player, nil
}

func (p *Player) update() error {
	p.updateBar()
	p.updatePlayPause()
	p.updateSE()
	p.updateVolume()
	if err := p.audioContext.Update(); err != nil {
		return err
	}
	select {
	case err := <-p.seekedCh:
		if err != nil {
			return err
		}
		close(p.seekedCh)
		p.seekedCh = nil
	default:
	}
	return nil
}

func (p *Player) updateSE() {
	if seBytes == nil {
		return
	}
	if !ebiten.IsKeyPressed(ebiten.KeyP) {
		p.keyState[ebiten.KeyP] = 0
		return
	}
	p.keyState[ebiten.KeyP]++
	if p.keyState[ebiten.KeyP] != 1 {
		return
	}
	sePlayer, _ := audio.NewPlayerFromBytes(p.audioContext, seBytes)
	sePlayer.Play()
}

func (p *Player) updateVolume() {
	if ebiten.IsKeyPressed(ebiten.KeyZ) {
		p.volume128--
	}
	if ebiten.IsKeyPressed(ebiten.KeyX) {
		p.volume128++
	}
	if p.volume128 < 0 {
		p.volume128 = 0
	}
	if 128 < p.volume128 {
		p.volume128 = 128
	}
	p.audioPlayer.SetVolume(float64(p.volume128) / 128)
}

func (p *Player) updatePlayPause() {
	if !ebiten.IsKeyPressed(ebiten.KeyS) {
		p.keyState[ebiten.KeyS] = 0
		return
	}
	p.keyState[ebiten.KeyS]++
	if p.keyState[ebiten.KeyS] != 1 {
		return
	}
	if p.audioPlayer.IsPlaying() {
		p.audioPlayer.Pause()
		return
	}
	p.audioPlayer.Play()
}

func (p *Player) updateBar() {
	if p.seekedCh != nil {
		return
	}
	if !ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {
		p.mouseButtonState[ebiten.MouseButtonLeft] = 0
		return
	}
	p.mouseButtonState[ebiten.MouseButtonLeft]++
	if p.mouseButtonState[ebiten.MouseButtonLeft] != 1 {
		return
	}
	x, y := ebiten.CursorPosition()
	bx, by, bw, bh := playerBarRect()
	const padding = 4
	if y < by-padding || by+bh+padding <= y {
		return
	}
	if x < bx || bx+bw <= x {
		return
	}
	pos := time.Duration(x-bx) * p.total / time.Duration(bw)
	p.seekedCh = make(chan error, 1)
	go func() {
		// This can't be done parallely! !?!?
		p.seekedCh <- p.audioPlayer.Seek(pos)
	}()
}

func (p *Player) close() error {
	return p.audioPlayer.Close()
}

func (p *Player) draw(screen *ebiten.Image) {
	op := &ebiten.DrawImageOptions{}
	x, y, w, h := playerBarRect()
	op.GeoM.Translate(float64(x), float64(y))
	screen.DrawImage(playerBarImage, op)
	currentTimeStr := "00:00"
	c := p.audioPlayer.Current()

	// Current Time
	m := (c / time.Minute) % 100
	s := (c / time.Second) % 60
	currentTimeStr = fmt.Sprintf("%02d:%02d", m, s)

	// Bar
	cw, ch := playerCurrentImage.Size()
	cx := int(time.Duration(w)*c/p.total) + x - cw/2
	cy := y - (ch-h)/2
	op = &ebiten.DrawImageOptions{}
	op.GeoM.Translate(float64(cx), float64(cy))
	screen.DrawImage(playerCurrentImage, op)

	msg := fmt.Sprintf(`FPS: %0.2f
Press S to toggle Play/Pause
Press P to play SE
Press Z or X to change volume of the music
%s`, ebiten.CurrentFPS(), currentTimeStr)
	if p.seekedCh != nil {
		msg += "\nSeeking..."
	}
	ebitenutil.DebugPrint(screen, msg)
}

func update(screen *ebiten.Image) error {
	if seBytes == nil {
		select {
		case seBytes = <-seCh:
		default:
		}
	}
	if err := musicPlayer.update(); err != nil {
		return err
	}
	if ebiten.IsRunningSlowly() {
		return nil
	}
	musicPlayer.draw(screen)
	return nil
}

func main() {
	wavF, err := ebitenutil.OpenFile("_resources/audio/jab.wav")
	if err != nil {
		log.Fatal(err)
	}
	audioContext, err := audio.NewContext(sampleRate)
	if err != nil {
		log.Fatal(err)
	}
	go func() {
		s, err := wav.Decode(audioContext, wavF)
		if err != nil {
			log.Fatal(err)
			return
		}
		b, err := ioutil.ReadAll(s)
		if err != nil {
			log.Fatal(err)
			return
		}
		seCh <- b
		close(seCh)
	}()
	musicPlayer, err = NewPlayer(audioContext)
	if err != nil {
		log.Fatal(err)
	}
	if err := ebiten.Run(update, screenWidth, screenHeight, 2, "Audio (Ebiten Demo)"); err != nil {
		log.Fatal(err)
	}
	if musicPlayer != nil {
		if err := musicPlayer.close(); err != nil {
			log.Fatal(err)
		}
	}
}
<commit_msg>examples/audio: Refactoring: Add Input struct (#302)<commit_after>// Copyright 2016 Hajime Hoshi
//
// 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.

// +build example

package main

import (
	"fmt"
	"image/color"
	"io/ioutil"
	"log"
	"time"

	"github.com/hajimehoshi/ebiten"
	"github.com/hajimehoshi/ebiten/audio"
	"github.com/hajimehoshi/ebiten/audio/vorbis"
	"github.com/hajimehoshi/ebiten/audio/wav"
	"github.com/hajimehoshi/ebiten/ebitenutil"
)

const (
	screenWidth  = 320
	screenHeight = 240

	// This sample rate doesn't match with wav/ogg's sample rate,
	// but decoders adjust them.
	sampleRate = 48000
)

var (
	playerBarImage     *ebiten.Image
	playerCurrentImage *ebiten.Image
)

func init() {
	playerBarImage, _ = ebiten.NewImage(300, 4, ebiten.FilterNearest)
	playerBarImage.Fill(&color.RGBA{0x80, 0x80, 0x80, 0xff})

	playerCurrentImage, _ = ebiten.NewImage(4, 10, ebiten.FilterNearest)
	playerCurrentImage.Fill(&color.RGBA{0xff, 0xff, 0xff, 0xff})
}

type Input struct {
	mouseButtonStates map[ebiten.MouseButton]int
	keyStates         map[ebiten.Key]int
}

func (i *Input) update() {
	for _, key := range []ebiten.Key{ebiten.KeyP, ebiten.KeyS, ebiten.KeyX, ebiten.KeyZ} {
		if !ebiten.IsKeyPressed(key) {
			i.keyStates[key] = 0
		} else {
			i.keyStates[key]++
		}
	}
	if !ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {
		i.mouseButtonStates[ebiten.MouseButtonLeft] = 0
	} else {
		i.mouseButtonStates[ebiten.MouseButtonLeft]++
	}
}

func (i *Input) isKeyTriggered(key ebiten.Key) bool {
	return i.keyStates[key] == 1
}

func (i *Input) isKeyPressed(key ebiten.Key) bool {
	return i.keyStates[key] > 0
}

func (i *Input) isMouseButtonTriggered(mouseButton ebiten.MouseButton) bool {
	return i.mouseButtonStates[mouseButton] == 1
}

type Player struct {
	input        *Input
	audioContext *audio.Context
	audioPlayer  *audio.Player
	total        time.Duration
	seekedCh     chan error
	volume128    int
}

var (
	musicPlayer *Player
	seBytes     []byte
	seCh        = make(chan []byte)
)

func playerBarRect() (x, y, w, h int) {
	w, h = playerBarImage.Size()
	x = (screenWidth - w) / 2
	y = screenHeight - h - 16
	return
}

func NewPlayer(audioContext *audio.Context) (*Player, error) {
	const bytesPerSample = 4 // TODO: This should be defined in audio package
	oggF, err := ebitenutil.OpenFile("_resources/audio/game.ogg")
	if err != nil {
		return nil, err
	}
	s, err := vorbis.Decode(audioContext, oggF)
	if err != nil {
		return nil, err
	}
	p, err := audio.NewPlayer(audioContext, s)
	if err != nil {
		return nil, err
	}
	player := &Player{
		input: &Input{
			mouseButtonStates: map[ebiten.MouseButton]int{},
			keyStates:         map[ebiten.Key]int{},
		},
		audioContext: audioContext,
		audioPlayer:  p,
		total:        time.Second * time.Duration(s.Size()) / bytesPerSample / sampleRate,
		volume128:    128,
	}
	player.audioPlayer.Play()
	return player, nil
}

func (p *Player) update() error {
	p.input.update()
	p.updateBar()
	p.updatePlayPause()
	p.updateSE()
	p.updateVolume()
	if err := p.audioContext.Update(); err != nil {
		return err
	}
	select {
	case err := <-p.seekedCh:
		if err != nil {
			return err
		}
		close(p.seekedCh)
		p.seekedCh = nil
	default:
	}
	return nil
}

func (p *Player) updateSE() {
	if seBytes == nil {
		return
	}
	if !p.input.isKeyTriggered(ebiten.KeyP) {
		return
	}
	sePlayer, _ := audio.NewPlayerFromBytes(p.audioContext, seBytes)
	sePlayer.Play()
}

func (p *Player) updateVolume() {
	if p.input.isKeyPressed(ebiten.KeyZ) {
		p.volume128--
	}
	if p.input.isKeyPressed(ebiten.KeyX) {
		p.volume128++
	}
	if p.volume128 < 0 {
		p.volume128 = 0
	}
	if 128 < p.volume128 {
		p.volume128 = 128
	}
	p.audioPlayer.SetVolume(float64(p.volume128) / 128)
}

func (p *Player) updatePlayPause() {
	if !p.input.isKeyTriggered(ebiten.KeyS) {
		return
	}
	if p.audioPlayer.IsPlaying() {
		p.audioPlayer.Pause()
		return
	}
	p.audioPlayer.Play()
}

func (p *Player) updateBar() {
	if p.seekedCh != nil {
		return
	}
	if !p.input.isMouseButtonTriggered(ebiten.MouseButtonLeft) {
		return
	}
	x, y := ebiten.CursorPosition()
	bx, by, bw, bh := playerBarRect()
	const padding = 4
	if y < by-padding || by+bh+padding <= y {
		return
	}
	if x < bx || bx+bw <= x {
		return
	}
	pos := time.Duration(x-bx) * p.total / time.Duration(bw)
	p.seekedCh = make(chan error, 1)
	go func() {
		p.seekedCh <- p.audioPlayer.Seek(pos)
	}()
}

func (p *Player) close() error {
	return p.audioPlayer.Close()
}

func (p *Player) draw(screen *ebiten.Image) {
	op := &ebiten.DrawImageOptions{}
	x, y, w, h := playerBarRect()
	op.GeoM.Translate(float64(x), float64(y))
	screen.DrawImage(playerBarImage, op)
	currentTimeStr := "00:00"
	c := p.audioPlayer.Current()

	// Current Time
	m := (c / time.Minute) % 100
	s := (c / time.Second) % 60
	currentTimeStr = fmt.Sprintf("%02d:%02d", m, s)

	// Bar
	cw, ch := playerCurrentImage.Size()
	cx := int(time.Duration(w)*c/p.total) + x - cw/2
	cy := y - (ch-h)/2
	op = &ebiten.DrawImageOptions{}
	op.GeoM.Translate(float64(cx), float64(cy))
	screen.DrawImage(playerCurrentImage, op)

	msg := fmt.Sprintf(`FPS: %0.2f
Press S to toggle Play/Pause
Press P to play SE
Press Z or X to change volume of the music
%s`, ebiten.CurrentFPS(), currentTimeStr)
	if p.seekedCh != nil {
		msg += "\nSeeking..."
	}
	ebitenutil.DebugPrint(screen, msg)
}

func update(screen *ebiten.Image) error {
	if seBytes == nil {
		select {
		case seBytes = <-seCh:
		default:
		}
	}
	if err := musicPlayer.update(); err != nil {
		return err
	}
	if ebiten.IsRunningSlowly() {
		return nil
	}
	musicPlayer.draw(screen)
	return nil
}

func main() {
	wavF, err := ebitenutil.OpenFile("_resources/audio/jab.wav")
	if err != nil {
		log.Fatal(err)
	}
	audioContext, err := audio.NewContext(sampleRate)
	if err != nil {
		log.Fatal(err)
	}
	go func() {
		s, err := wav.Decode(audioContext, wavF)
		if err != nil {
			log.Fatal(err)
			return
		}
		b, err := ioutil.ReadAll(s)
		if err != nil {
			log.Fatal(err)
			return
		}
		seCh <- b
		close(seCh)
	}()
	musicPlayer, err = NewPlayer(audioContext)
	if err != nil {
		log.Fatal(err)
	}
	if err := ebiten.Run(update, screenWidth, screenHeight, 2, "Audio (Ebiten Demo)"); err != nil {
		log.Fatal(err)
	}
	if musicPlayer != nil {
		if err := musicPlayer.close(); err != nil {
			log.Fatal(err)
		}
	}
}
<|endoftext|>


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

package stat

import (
	"sync"

	"github.com/gonum/matrix/mat64"
)

// CovarianceMatrix calculates a covariance matrix (also known as a
// variance-covariance matrix) from a matrix of data, using a two-pass
// algorithm.  It will have better performance if a BLAS engine is
// registered in gonum/matrix/mat64.
//
// The matrix returned will be symmetric, square, and positive-semidefinite.
func CovarianceMatrix(x mat64.Matrix) *mat64.Dense {

	// matrix version of the two pass algorithm.  This doesn't use
	// the correction found in the Covariance and Variance functions.
	if mat64.Registered() == nil {
		// implementation that doesn't rely on a blasEngine
		return covarianceMatrixWithoutBLAS(x)
	}
	r, _ := x.Dims()

	// determine the mean of each of the columns
	b := ones(1, r)
	b.Mul(b, x)
	b.Scale(1/float64(r), b)
	mu := b.RowView(0)

	// subtract the mean from the data
	xc := mat64.DenseCopyOf(x)
	for i := 0; i < r; i++ {
		rv := xc.RowView(i)
		for j, mean := range mu {
			rv[j] -= mean
		}
	}

	var xt mat64.Dense
	xt.TCopy(xc)

	// TODO: indicate that the resulting matrix is symmetric, which
	// should improve performance.
	var ss mat64.Dense
	ss.Mul(&xt, xc)
	ss.Scale(1/float64(r-1), &ss)
	return &ss
}

type covMatSlice struct {
	i, j int
	x, y []float64
}

func covarianceMatrixWithoutBLAS(x mat64.Matrix) *mat64.Dense {
	r, c := x.Dims()

	// split out the matrix into columns
	cols := make([][]float64, c)
	for j := range cols {
		cols[j] = make([]float64, r)
	}

	if xRaw, ok := x.(mat64.RawMatrixer); ok {
		for k, v := range xRaw.RawMatrix().Data {
			i := k / c
			j := k % c
			cols[j][i] = v
		}
	} else {
		for j := 0; j < c; j++ {
			for i := 0; i < r; i++ {
				cols[j][i] = x.At(i, j)
			}
		}
	}

	// center the columns
	for j := range cols {
		mean := Mean(cols[j], nil)
		for i := range cols[j] {
			cols[j][i] -= mean
		}
	}

	blockSize := 1024
	if blockSize > c {
		blockSize = c
	}
	var wg sync.WaitGroup
	wg.Add(blockSize)
	colCh := make(chan covMatSlice, blockSize)

	m := mat64.NewDense(c, c, nil)
	for i := 0; i < blockSize; i++ {
		go func(in <-chan covMatSlice) {
			for {
				xy, more := <-in
				if !more {
					wg.Done()
					return
				}

				if xy.i == xy.j {
					m.Set(xy.i, xy.j, centeredVariance(xy.x))
					continue
				}
				v := centeredCovariance(xy.x, xy.y)
				m.Set(xy.i, xy.j, v)
				m.Set(xy.j, xy.i, v)
			}
		}(colCh)
	}
	go func(out chan<- covMatSlice) {
		for i := 0; i < c; i++ {
			for j := 0; j <= i; j++ {
				out <- covMatSlice{
					i: i,
					j: j,
					x: cols[i],
					y: cols[j],
				}
			}
		}
		close(out)
	}(colCh)
	// create the output matrix
	wg.Wait()
	return m
}

// ones is a matrix of all ones.
func ones(r, c int) *mat64.Dense {
	x := make([]float64, r*c)
	for i := range x {
		x[i] = 1
	}
	return mat64.NewDense(r, c, x)
}

// centeredVariance calculates the sum of squares of a single
// series, for calculating variance.
func centeredVariance(x []float64) float64 {
	var ss float64
	for _, xv := range x {
		ss += xv * xv
	}
	return ss / float64(len(x)-1)
}

// centeredCovariance calculates the sum of squares of two
// series, for calculating variance.  The input lengths are
// assumed to be identical.
func centeredCovariance(x, y []float64) float64 {
	var ss float64
	for i, xv := range x {
		ss += xv * y[i]
	}
	return ss / float64(len(x)-1)
}
<commit_msg>remove non-blas codepath<commit_after>// Copyright ©2014 The gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package stat

import (
	"github.com/gonum/matrix/mat64"
)

// CovarianceMatrix calculates a covariance matrix (also known as a
// variance-covariance matrix) from a matrix of data, using a two-pass
// algorithm.  It requires a registered BLAS engine in gonum/matrix/mat64.
//
// The matrix returned will be symmetric, square, and positive-semidefinite.
func CovarianceMatrix(x mat64.Matrix) *mat64.Dense {

	// matrix version of the two pass algorithm.  This doesn't use
	// the correction found in the Covariance and Variance functions.

	r, _ := x.Dims()

	// determine the mean of each of the columns
	ones := make([]float64, r)
	for i := range ones {
		ones[i] = 1
	}
	b := mat64.NewDense(1, r, ones)
	b.Mul(b, x)
	b.Scale(1/float64(r), b)
	mu := b.RowView(0)

	// subtract the mean from the data
	xc := mat64.DenseCopyOf(x)
	for i := 0; i < r; i++ {
		rv := xc.RowView(i)
		for j, mean := range mu {
			rv[j] -= mean
		}
	}

	var xt mat64.Dense
	xt.TCopy(xc)

	// TODO: indicate that the resulting matrix is symmetric, which
	// should improve performance.
	var ss mat64.Dense
	ss.Mul(&xt, xc)
	ss.Scale(1/float64(r-1), &ss)
	return &ss
}
<|endoftext|>


<commit_before>package oplog

var VERSION string = "1.1.0"
<commit_msg>Bump version to 1.1.1<commit_after>package oplog

var VERSION string = "1.1.1"
<|endoftext|>


<commit_before>/*
Copyright 2019 The Kubernetes Authors 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.
*/

package oci

import (
	"encoding/json"
	"os/exec"
	"strings"
	"time"

	"github.com/pkg/errors"
)

// SysInfo Info represents common system Information between docker and podman that minikube cares
type SysInfo struct {
	CPUs        int   // CPUs is Number of CPUs
	TotalMemory int64 // TotalMemory Total available ram
}

// DaemonInfo returns common docker/podman daemon system info that minikube cares about
func DaemonInfo(ociBin string) (SysInfo, error) {
	var info SysInfo
	if ociBin == Podman {
		p, err := podmanSystemInfo()
		info.CPUs = p.Host.Cpus
		info.TotalMemory = p.Host.MemTotal
		return info, err
	}
	d, err := dockerSystemInfo()
	info.CPUs = d.NCPU
	info.TotalMemory = d.MemTotal
	return info, err
}

// dockerSysInfo represents the output of docker system info --format '{{json .}}'
type dockerSysInfo struct {
	ID                string      `json:"ID"`
	Containers        int         `json:"Containers"`
	ContainersRunning int         `json:"ContainersRunning"`
	ContainersPaused  int         `json:"ContainersPaused"`
	ContainersStopped int         `json:"ContainersStopped"`
	Images            int         `json:"Images"`
	Driver            string      `json:"Driver"`
	DriverStatus      [][]string  `json:"DriverStatus"`
	SystemStatus      interface{} `json:"SystemStatus"`
	Plugins           struct {
		Volume        []string    `json:"Volume"`
		Network       []string    `json:"Network"`
		Authorization interface{} `json:"Authorization"`
		Log           []string    `json:"Log"`
	} `json:"Plugins"`
	MemoryLimit        bool      `json:"MemoryLimit"`
	SwapLimit          bool      `json:"SwapLimit"`
	KernelMemory       bool      `json:"KernelMemory"`
	KernelMemoryTCP    bool      `json:"KernelMemoryTCP"`
	CPUCfsPeriod       bool      `json:"CpuCfsPeriod"`
	CPUCfsQuota        bool      `json:"CpuCfsQuota"`
	CPUShares          bool      `json:"CPUShares"`
	CPUSet             bool      `json:"CPUSet"`
	PidsLimit          bool      `json:"PidsLimit"`
	IPv4Forwarding     bool      `json:"IPv4Forwarding"`
	BridgeNfIptables   bool      `json:"BridgeNfIptables"`
	BridgeNfIP6Tables  bool      `json:"BridgeNfIp6tables"`
	Debug              bool      `json:"Debug"`
	NFd                int       `json:"NFd"`
	OomKillDisable     bool      `json:"OomKillDisable"`
	NGoroutines        int       `json:"NGoroutines"`
	SystemTime         time.Time `json:"SystemTime"`
	LoggingDriver      string    `json:"LoggingDriver"`
	CgroupDriver       string    `json:"CgroupDriver"`
	NEventsListener    int       `json:"NEventsListener"`
	KernelVersion      string    `json:"KernelVersion"`
	OperatingSystem    string    `json:"OperatingSystem"`
	OSType             string    `json:"OSType"`
	Architecture       string    `json:"Architecture"`
	IndexServerAddress string    `json:"IndexServerAddress"`
	RegistryConfig     struct {
		AllowNondistributableArtifactsCIDRs     []interface{} `json:"AllowNondistributableArtifactsCIDRs"`
		AllowNondistributableArtifactsHostnames []interface{} `json:"AllowNondistributableArtifactsHostnames"`
		InsecureRegistryCIDRs                   []string      `json:"InsecureRegistryCIDRs"`
		IndexConfigs                            struct {
			DockerIo struct {
				Name     string        `json:"Name"`
				Mirrors  []interface{} `json:"Mirrors"`
				Secure   bool          `json:"Secure"`
				Official bool          `json:"Official"`
			} `json:"docker.io"`
		} `json:"IndexConfigs"`
		Mirrors []interface{} `json:"Mirrors"`
	} `json:"RegistryConfig"`
	NCPU              int           `json:"NCPU"`
	MemTotal          int64         `json:"MemTotal"`
	GenericResources  interface{}   `json:"GenericResources"`
	DockerRootDir     string        `json:"DockerRootDir"`
	HTTPProxy         string        `json:"HttpProxy"`
	HTTPSProxy        string        `json:"HttpsProxy"`
	NoProxy           string        `json:"NoProxy"`
	Name              string        `json:"Name"`
	Labels            []interface{} `json:"Labels"`
	ExperimentalBuild bool          `json:"ExperimentalBuild"`
	ServerVersion     string        `json:"ServerVersion"`
	ClusterStore      string        `json:"ClusterStore"`
	ClusterAdvertise  string        `json:"ClusterAdvertise"`
	Runtimes          struct {
		Runc struct {
			Path string `json:"path"`
		} `json:"runc"`
	} `json:"Runtimes"`
	DefaultRuntime string `json:"DefaultRuntime"`
	Swarm          struct {
		NodeID           string      `json:"NodeID"`
		NodeAddr         string      `json:"NodeAddr"`
		LocalNodeState   string      `json:"LocalNodeState"`
		ControlAvailable bool        `json:"ControlAvailable"`
		Error            string      `json:"Error"`
		RemoteManagers   interface{} `json:"RemoteManagers"`
	} `json:"Swarm"`
	LiveRestoreEnabled bool   `json:"LiveRestoreEnabled"`
	Isolation          string `json:"Isolation"`
	InitBinary         string `json:"InitBinary"`
	ContainerdCommit   struct {
		ID       string `json:"ID"`
		Expected string `json:"Expected"`
	} `json:"ContainerdCommit"`
	RuncCommit struct {
		ID       string `json:"ID"`
		Expected string `json:"Expected"`
	} `json:"RuncCommit"`
	InitCommit struct {
		ID       string `json:"ID"`
		Expected string `json:"Expected"`
	} `json:"InitCommit"`
	SecurityOptions []string    `json:"SecurityOptions"`
	ProductLicense  string      `json:"ProductLicense"`
	Warnings        interface{} `json:"Warnings"`
	ClientInfo      struct {
		Debug    bool          `json:"Debug"`
		Plugins  []interface{} `json:"Plugins"`
		Warnings interface{}   `json:"Warnings"`
	} `json:"ClientInfo"`
}

// podmanSysInfo represents the output of podman system info --format '{{json .}}'
type podmanSysInfo struct {
	Host struct {
		BuildahVersion string `json:"BuildahVersion"`
		CgroupVersion  string `json:"CgroupVersion"`
		Conmon         struct {
			Package string `json:"package"`
			Path    string `json:"path"`
			Version string `json:"version"`
		} `json:"Conmon"`
		Distribution struct {
			Distribution string `json:"distribution"`
			Version      string `json:"version"`
		} `json:"Distribution"`
		MemFree    int   `json:"MemFree"`
		MemTotal   int64 `json:"MemTotal"`
		OCIRuntime struct {
			Name    string `json:"name"`
			Package string `json:"package"`
			Path    string `json:"path"`
			Version string `json:"version"`
		} `json:"OCIRuntime"`
		SwapFree    int    `json:"SwapFree"`
		SwapTotal   int    `json:"SwapTotal"`
		Arch        string `json:"arch"`
		Cpus        int    `json:"cpus"`
		Eventlogger string `json:"eventlogger"`
		Hostname    string `json:"hostname"`
		Kernel      string `json:"kernel"`
		Os          string `json:"os"`
		Rootless    bool   `json:"rootless"`
		Uptime      string `json:"uptime"`
	} `json:"host"`
	Registries struct {
		Search []string `json:"search"`
	} `json:"registries"`
	Store struct {
		ConfigFile     string `json:"ConfigFile"`
		ContainerStore struct {
			Number int `json:"number"`
		} `json:"ContainerStore"`
		GraphDriverName string `json:"GraphDriverName"`
		GraphOptions    struct {
		} `json:"GraphOptions"`
		GraphRoot   string `json:"GraphRoot"`
		GraphStatus struct {
			BackingFilesystem string `json:"Backing Filesystem"`
			NativeOverlayDiff string `json:"Native Overlay Diff"`
			SupportsDType     string `json:"Supports d_type"`
			UsingMetacopy     string `json:"Using metacopy"`
		} `json:"GraphStatus"`
		ImageStore struct {
			Number int `json:"number"`
		} `json:"ImageStore"`
		RunRoot    string `json:"RunRoot"`
		VolumePath string `json:"VolumePath"`
	} `json:"store"`
}

// dockerSystemInfo returns docker system info --format '{{json .}}'
func dockerSystemInfo() (dockerSysInfo, error) {
	var ds dockerSysInfo
	rr, err := runCmd(exec.Command(Docker, "system", "info", "--format", "{{json .}}"))
	if err != nil {
		return ds, errors.Wrap(err, "get docker system info")
	}

	if err := json.Unmarshal([]byte(strings.TrimSpace(rr.Stdout.String())), &ds); err != nil {
		return ds, errors.Wrapf(err, "unmarshal docker system info")
	}

	return ds, nil
}

// podmanSysInfo returns podman system info --format '{{json .}}'
func podmanSystemInfo() (podmanSysInfo, error) {
	var ps podmanSysInfo
	rr, err := runCmd(exec.Command("sudo", Podman, "system", "info", "--format", "'{{json .}}'"))
	if err != nil {
		return ps, errors.Wrap(err, "get podman system info")
	}

	if err := json.Unmarshal([]byte(strings.TrimSpace(rr.Stdout.String())), &ps); err != nil {
		return ps, errors.Wrapf(err, "unmarshal podman system info")
	}
	return ps, nil
}
<commit_msg>Remove extra quotes added in conflict resolution<commit_after>/*
Copyright 2019 The Kubernetes Authors 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.
*/

package oci

import (
	"encoding/json"
	"os/exec"
	"strings"
	"time"

	"github.com/pkg/errors"
)

// SysInfo Info represents common system Information between docker and podman that minikube cares
type SysInfo struct {
	CPUs        int   // CPUs is Number of CPUs
	TotalMemory int64 // TotalMemory Total available ram
}

// DaemonInfo returns common docker/podman daemon system info that minikube cares about
func DaemonInfo(ociBin string) (SysInfo, error) {
	var info SysInfo
	if ociBin == Podman {
		p, err := podmanSystemInfo()
		info.CPUs = p.Host.Cpus
		info.TotalMemory = p.Host.MemTotal
		return info, err
	}
	d, err := dockerSystemInfo()
	info.CPUs = d.NCPU
	info.TotalMemory = d.MemTotal
	return info, err
}

// dockerSysInfo represents the output of docker system info --format '{{json .}}'
type dockerSysInfo struct {
	ID                string      `json:"ID"`
	Containers        int         `json:"Containers"`
	ContainersRunning int         `json:"ContainersRunning"`
	ContainersPaused  int         `json:"ContainersPaused"`
	ContainersStopped int         `json:"ContainersStopped"`
	Images            int         `json:"Images"`
	Driver            string      `json:"Driver"`
	DriverStatus      [][]string  `json:"DriverStatus"`
	SystemStatus      interface{} `json:"SystemStatus"`
	Plugins           struct {
		Volume        []string    `json:"Volume"`
		Network       []string    `json:"Network"`
		Authorization interface{} `json:"Authorization"`
		Log           []string    `json:"Log"`
	} `json:"Plugins"`
	MemoryLimit        bool      `json:"MemoryLimit"`
	SwapLimit          bool      `json:"SwapLimit"`
	KernelMemory       bool      `json:"KernelMemory"`
	KernelMemoryTCP    bool      `json:"KernelMemoryTCP"`
	CPUCfsPeriod       bool      `json:"CpuCfsPeriod"`
	CPUCfsQuota        bool      `json:"CpuCfsQuota"`
	CPUShares          bool      `json:"CPUShares"`
	CPUSet             bool      `json:"CPUSet"`
	PidsLimit          bool      `json:"PidsLimit"`
	IPv4Forwarding     bool      `json:"IPv4Forwarding"`
	BridgeNfIptables   bool      `json:"BridgeNfIptables"`
	BridgeNfIP6Tables  bool      `json:"BridgeNfIp6tables"`
	Debug              bool      `json:"Debug"`
	NFd                int       `json:"NFd"`
	OomKillDisable     bool      `json:"OomKillDisable"`
	NGoroutines        int       `json:"NGoroutines"`
	SystemTime         time.Time `json:"SystemTime"`
	LoggingDriver      string    `json:"LoggingDriver"`
	CgroupDriver       string    `json:"CgroupDriver"`
	NEventsListener    int       `json:"NEventsListener"`
	KernelVersion      string    `json:"KernelVersion"`
	OperatingSystem    string    `json:"OperatingSystem"`
	OSType             string    `json:"OSType"`
	Architecture       string    `json:"Architecture"`
	IndexServerAddress string    `json:"IndexServerAddress"`
	RegistryConfig     struct {
		AllowNondistributableArtifactsCIDRs     []interface{} `json:"AllowNondistributableArtifactsCIDRs"`
		AllowNondistributableArtifactsHostnames []interface{} `json:"AllowNondistributableArtifactsHostnames"`
		InsecureRegistryCIDRs                   []string      `json:"InsecureRegistryCIDRs"`
		IndexConfigs                            struct {
			DockerIo struct {
				Name     string        `json:"Name"`
				Mirrors  []interface{} `json:"Mirrors"`
				Secure   bool          `json:"Secure"`
				Official bool          `json:"Official"`
			} `json:"docker.io"`
		} `json:"IndexConfigs"`
		Mirrors []interface{} `json:"Mirrors"`
	} `json:"RegistryConfig"`
	NCPU              int           `json:"NCPU"`
	MemTotal          int64         `json:"MemTotal"`
	GenericResources  interface{}   `json:"GenericResources"`
	DockerRootDir     string        `json:"DockerRootDir"`
	HTTPProxy         string        `json:"HttpProxy"`
	HTTPSProxy        string        `json:"HttpsProxy"`
	NoProxy           string        `json:"NoProxy"`
	Name              string        `json:"Name"`
	Labels            []interface{} `json:"Labels"`
	ExperimentalBuild bool          `json:"ExperimentalBuild"`
	ServerVersion     string        `json:"ServerVersion"`
	ClusterStore      string        `json:"ClusterStore"`
	ClusterAdvertise  string        `json:"ClusterAdvertise"`
	Runtimes          struct {
		Runc struct {
			Path string `json:"path"`
		} `json:"runc"`
	} `json:"Runtimes"`
	DefaultRuntime string `json:"DefaultRuntime"`
	Swarm          struct {
		NodeID           string      `json:"NodeID"`
		NodeAddr         string      `json:"NodeAddr"`
		LocalNodeState   string      `json:"LocalNodeState"`
		ControlAvailable bool        `json:"ControlAvailable"`
		Error            string      `json:"Error"`
		RemoteManagers   interface{} `json:"RemoteManagers"`
	} `json:"Swarm"`
	LiveRestoreEnabled bool   `json:"LiveRestoreEnabled"`
	Isolation          string `json:"Isolation"`
	InitBinary         string `json:"InitBinary"`
	ContainerdCommit   struct {
		ID       string `json:"ID"`
		Expected string `json:"Expected"`
	} `json:"ContainerdCommit"`
	RuncCommit struct {
		ID       string `json:"ID"`
		Expected string `json:"Expected"`
	} `json:"RuncCommit"`
	InitCommit struct {
		ID       string `json:"ID"`
		Expected string `json:"Expected"`
	} `json:"InitCommit"`
	SecurityOptions []string    `json:"SecurityOptions"`
	ProductLicense  string      `json:"ProductLicense"`
	Warnings        interface{} `json:"Warnings"`
	ClientInfo      struct {
		Debug    bool          `json:"Debug"`
		Plugins  []interface{} `json:"Plugins"`
		Warnings interface{}   `json:"Warnings"`
	} `json:"ClientInfo"`
}

// podmanSysInfo represents the output of podman system info --format '{{json .}}'
type podmanSysInfo struct {
	Host struct {
		BuildahVersion string `json:"BuildahVersion"`
		CgroupVersion  string `json:"CgroupVersion"`
		Conmon         struct {
			Package string `json:"package"`
			Path    string `json:"path"`
			Version string `json:"version"`
		} `json:"Conmon"`
		Distribution struct {
			Distribution string `json:"distribution"`
			Version      string `json:"version"`
		} `json:"Distribution"`
		MemFree    int   `json:"MemFree"`
		MemTotal   int64 `json:"MemTotal"`
		OCIRuntime struct {
			Name    string `json:"name"`
			Package string `json:"package"`
			Path    string `json:"path"`
			Version string `json:"version"`
		} `json:"OCIRuntime"`
		SwapFree    int    `json:"SwapFree"`
		SwapTotal   int    `json:"SwapTotal"`
		Arch        string `json:"arch"`
		Cpus        int    `json:"cpus"`
		Eventlogger string `json:"eventlogger"`
		Hostname    string `json:"hostname"`
		Kernel      string `json:"kernel"`
		Os          string `json:"os"`
		Rootless    bool   `json:"rootless"`
		Uptime      string `json:"uptime"`
	} `json:"host"`
	Registries struct {
		Search []string `json:"search"`
	} `json:"registries"`
	Store struct {
		ConfigFile     string `json:"ConfigFile"`
		ContainerStore struct {
			Number int `json:"number"`
		} `json:"ContainerStore"`
		GraphDriverName string `json:"GraphDriverName"`
		GraphOptions    struct {
		} `json:"GraphOptions"`
		GraphRoot   string `json:"GraphRoot"`
		GraphStatus struct {
			BackingFilesystem string `json:"Backing Filesystem"`
			NativeOverlayDiff string `json:"Native Overlay Diff"`
			SupportsDType     string `json:"Supports d_type"`
			UsingMetacopy     string `json:"Using metacopy"`
		} `json:"GraphStatus"`
		ImageStore struct {
			Number int `json:"number"`
		} `json:"ImageStore"`
		RunRoot    string `json:"RunRoot"`
		VolumePath string `json:"VolumePath"`
	} `json:"store"`
}

// dockerSystemInfo returns docker system info --format '{{json .}}'
func dockerSystemInfo() (dockerSysInfo, error) {
	var ds dockerSysInfo
	rr, err := runCmd(exec.Command(Docker, "system", "info", "--format", "{{json .}}"))
	if err != nil {
		return ds, errors.Wrap(err, "get docker system info")
	}

	if err := json.Unmarshal([]byte(strings.TrimSpace(rr.Stdout.String())), &ds); err != nil {
		return ds, errors.Wrapf(err, "unmarshal docker system info")
	}

	return ds, nil
}

// podmanSysInfo returns podman system info --format '{{json .}}'
func podmanSystemInfo() (podmanSysInfo, error) {
	var ps podmanSysInfo
	rr, err := runCmd(exec.Command("sudo", Podman, "system", "info", "--format", "{{json .}}"))
	if err != nil {
		return ps, errors.Wrap(err, "get podman system info")
	}

	if err := json.Unmarshal([]byte(strings.TrimSpace(rr.Stdout.String())), &ps); err != nil {
		return ps, errors.Wrapf(err, "unmarshal podman system info")
	}
	return ps, nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 Ludovic Fauvet
// Licensed under the MIT license

package main

import (
	"fmt"
	"runtime"
)

var (
	VERSION = "0.2"
)

func printVersion() {
	fmt.Println("Version:", VERSION)
	fmt.Println("GoVersion:", runtime.Version())
	fmt.Println("Operating System:", runtime.GOOS)
	fmt.Println("Architecture:", runtime.GOARCH)
	fmt.Println("Gomaxprocs:", runtime.GOMAXPROCS(0))
}
<commit_msg>Change version number to 0.3-dev<commit_after>// Copyright (c) 2014 Ludovic Fauvet
// Licensed under the MIT license

package main

import (
	"fmt"
	"runtime"
)

var (
	VERSION = "0.3-dev"
)

func printVersion() {
	fmt.Println("Version:", VERSION)
	fmt.Println("GoVersion:", runtime.Version())
	fmt.Println("Operating System:", runtime.GOOS)
	fmt.Println("Architecture:", runtime.GOARCH)
	fmt.Println("Gomaxprocs:", runtime.GOMAXPROCS(0))
}
<|endoftext|>


<commit_before>package main

const Version string = "0.1.0"
<commit_msg>Bump up version<commit_after>package main

const Version string = "0.1.1"
<|endoftext|>


<commit_before>// (c) Copyright IBM Corp. 2021
// (c) Copyright Instana Inc. 2021

package instana

// Version is the version of Instana sensor
const Version = "1.41.0"
<commit_msg>Bump version to v1.42.0<commit_after>// (c) Copyright IBM Corp. 2021
// (c) Copyright Instana Inc. 2021

package instana

// Version is the version of Instana sensor
const Version = "1.42.0"
<|endoftext|>


<commit_before>package sorg

const (
	// Release is the asset version of the site. Bump when any assets are
	// updated to blow away any browser caches.
	Release = "23"
)
<commit_msg>Bump release number to force refresh assets<commit_after>package sorg

const (
	// Release is the asset version of the site. Bump when any assets are
	// updated to blow away any browser caches.
	Release = "24"
)
<|endoftext|>


<commit_before>package main

const Version = "0.1.20140623"

// EOF
<commit_msg>version: 0.1.20140624<commit_after>package main

const Version = "0.1.20140624"

// EOF
<|endoftext|>


<commit_before>// Copyright 2015 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

// +build linux

package host

import (
	"runtime"
	"syscall"
	"testing"

	"github.com/google/syzkaller/prog"
)

func TestSupportedSyscalls(t *testing.T) {
	t.Parallel()
	target, err := prog.GetTarget("linux", runtime.GOARCH)
	if err != nil {
		t.Fatal(err)
	}
	supp, _, err := DetectSupportedSyscalls(target, "none")
	if err != nil {
		t.Skipf("skipping: %v", err)
	}
	// These are safe to execute with invalid arguments.
	safe := []string{
		"memfd_create",
		"sendfile",
		"bpf$MAP_CREATE",
		"open",
		"openat",
		"read",
		"write",
		"stat",
	}
	for _, name := range safe {
		c := target.SyscallMap[name]
		if c == nil {
			t.Fatalf("can't find syscall '%v'", name)
		}
		a := ^uintptr(0) - 4097 // hopefully invalid
		_, _, err := syscall.Syscall6(uintptr(c.NR), a, a, a, a, a, a)
		if err == 0 {
			t.Fatalf("%v did not fail", name)
		}
		if ok := err != syscall.ENOSYS; ok != supp[c] {
			t.Fatalf("syscall %v: perse=%v kallsyms=%v", name, ok, supp[c])
		}
	}
}

func TestKallsymsParse(t *testing.T) {
	tests := []struct {
		Arch     string
		Kallsyms []byte
		Syscalls []string
	}{
		{
			"amd64",
			[]byte(`
ffffffff817cdcc0 T __sys_bind
ffffffff817cdda0 T __x64_sys_bind
ffffffff817cddc0 T __ia32_sys_bind
ffffffff817cdde0 T __sys_listen
ffffffff817cde80 T __x64_sys_listen
ffffffff817cde90 T __ia32_sys_listen
ffffffff817cdea0 T __sys_accept4
ffffffff817ce080 T __x64_sys_accept4
ffffffff817ce0a0 T __ia32_sys_accept4
			`),
			[]string{"bind", "listen", "accept4"},
		},
		{
			"arm64",
			[]byte(`
ffff000010a3ddf8 T __sys_bind
ffff000010a3def8 T __arm64_sys_bind
ffff000010a3df20 T __sys_listen
ffff000010a3dfd8 T __arm64_sys_listen
ffff000010a3e000 T __sys_accept4
ffff000010a3e1f0 T __arm64_sys_accept4
			`),
			[]string{"bind", "listen", "accept4"},
		},
		{
			"ppc64le",
			[]byte(`
c0000000011ec810 T __sys_bind
c0000000011eca10 T sys_bind
c0000000011eca10 T __se_sys_bind
c0000000011eca70 T __sys_listen
c0000000011ecc10 T sys_listen
c0000000011ecc10 T __se_sys_listen
c0000000011ecc70 T __sys_accept4
c0000000011ed050 T sys_accept4
c0000000011ed050 T __se_sys_accept4
			`),
			[]string{"bind", "listen", "accept4"},
		},
		{
			"arm",
			[]byte(`
c037c67c T __se_sys_setfsuid
c037c694 T __sys_setfsgid
c037c790 T sys_setfsgid
c037c790 T __se_sys_setfsgid
c037c7a8 T sys_getpid
c037c7d0 T sys_gettid
c037c7f8 T sys_getppid
			`),
			[]string{"setfsgid", "getpid", "gettid", "getppid"},
		},
	}

	for _, test := range tests {
		syscallSet := parseKallsyms(test.Kallsyms, test.Arch)
		if len(syscallSet) != len(test.Syscalls) {
			t.Fatalf("wrong number of parse syscalls, expected: %v, got: %v",
				len(test.Syscalls), len(syscallSet))
		}
		for _, syscall := range test.Syscalls {
			if _, ok := syscallSet[syscall]; !ok {
				t.Fatalf("syscall %v not found in parsed syscall list", syscall)
			}
		}
	}
}
<commit_msg>pkg/host: Add test for kallsymsRenameMap<commit_after>// Copyright 2015 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

// +build linux

package host

import (
	"runtime"
	"syscall"
	"testing"

	"github.com/google/syzkaller/prog"
)

func TestSupportedSyscalls(t *testing.T) {
	t.Parallel()
	target, err := prog.GetTarget("linux", runtime.GOARCH)
	if err != nil {
		t.Fatal(err)
	}
	supp, _, err := DetectSupportedSyscalls(target, "none")
	if err != nil {
		t.Skipf("skipping: %v", err)
	}
	// These are safe to execute with invalid arguments.
	safe := []string{
		"memfd_create",
		"sendfile",
		"bpf$MAP_CREATE",
		"open",
		"openat",
		"read",
		"write",
		"stat",
	}
	for _, name := range safe {
		c := target.SyscallMap[name]
		if c == nil {
			t.Fatalf("can't find syscall '%v'", name)
		}
		a := ^uintptr(0) - 4097 // hopefully invalid
		_, _, err := syscall.Syscall6(uintptr(c.NR), a, a, a, a, a, a)
		if err == 0 {
			t.Fatalf("%v did not fail", name)
		}
		if ok := err != syscall.ENOSYS; ok != supp[c] {
			t.Fatalf("syscall %v: perse=%v kallsyms=%v", name, ok, supp[c])
		}
	}
}

func TestKallsymsParse(t *testing.T) {
	tests := []struct {
		Arch              string
		Kallsyms          []byte
		ParsedSyscalls    []string
		SupportedSyscalls []string
	}{
		{
			"amd64",
			[]byte(`
ffffffff817cdcc0 T __sys_bind
ffffffff817cdda0 T __x64_sys_bind
ffffffff817cddc0 T __ia32_sys_bind
ffffffff817cdde0 T __sys_listen
ffffffff817cde80 T __x64_sys_listen
ffffffff817cde90 T __ia32_sys_listen
ffffffff817cdea0 T __sys_accept4
ffffffff817ce080 T __x64_sys_accept4
ffffffff817ce0a0 T __ia32_sys_accept4
			`),
			[]string{"bind", "listen", "accept4"},
			[]string{"bind", "listen", "accept4"},
		},
		{
			"arm64",
			[]byte(`
ffff000010a3ddf8 T __sys_bind
ffff000010a3def8 T __arm64_sys_bind
ffff000010a3df20 T __sys_listen
ffff000010a3dfd8 T __arm64_sys_listen
ffff000010a3e000 T __sys_accept4
ffff000010a3e1f0 T __arm64_sys_accept4
			`),
			[]string{"bind", "listen", "accept4"},
			[]string{"bind", "listen", "accept4"},
		},
		{
			"ppc64le",
			[]byte(`
c0000000011ec810 T __sys_bind
c0000000011eca10 T sys_bind
c0000000011eca10 T __se_sys_bind
c0000000011eca70 T __sys_listen
c0000000011ecc10 T sys_listen
c0000000011ecc10 T __se_sys_listen
c0000000011ecc70 T __sys_accept4
c0000000011ed050 T sys_accept4
c0000000011ed050 T __se_sys_accept4
			`),
			[]string{"bind", "listen", "accept4"},
			[]string{"bind", "listen", "accept4"},
		},
		{
			"arm",
			[]byte(`
c037c67c T __se_sys_setfsuid
c037c694 T __sys_setfsgid
c037c790 T sys_setfsgid
c037c790 T __se_sys_setfsgid
c037c7a8 T sys_getpid
c037c7d0 T sys_gettid
c037c7f8 T sys_getppid
			`),
			[]string{"setfsgid", "getpid", "gettid", "getppid"},
			[]string{"setfsgid", "getpid", "gettid", "getppid"},
		},
		// Test kallsymsRenameMap
		{
			"ppc64le",
			[]byte(`
c00000000037eb00 T sys_newstat
			`),
			[]string{"newstat"},
			[]string{"stat"},
		},
	}

	for _, test := range tests {
		syscallSet := parseKallsyms(test.Kallsyms, test.Arch)
		if len(syscallSet) != len(test.ParsedSyscalls) {
			t.Fatalf("wrong number of parse syscalls, expected: %v, got: %v",
				len(test.ParsedSyscalls), len(syscallSet))
		}
		for _, syscall := range test.ParsedSyscalls {
			if _, ok := syscallSet[syscall]; !ok {
				t.Fatalf("syscall %v not found in parsed syscall list", syscall)
			}
		}
		for _, syscall := range test.SupportedSyscalls {
			if newname := kallsymsRenameMap[syscall]; newname != "" {
				syscall = newname
			}

			if _, ok := syscallSet[syscall]; !ok {
				t.Fatalf("syscall %v not found in supported syscall list", syscall)
			}
		}
	}
}
<|endoftext|>


<commit_before>//go:build !windows
// +build !windows

package idtools // import "github.com/docker/docker/pkg/idtools"

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"sync"
	"syscall"

	"github.com/docker/docker/pkg/system"
	"github.com/opencontainers/runc/libcontainer/user"
)

var (
	entOnce   sync.Once
	getentCmd string
)

func mkdirAs(path string, mode os.FileMode, owner Identity, mkAll, chownExisting bool) error {
	path, err := filepath.Abs(path)
	if err != nil {
		return err
	}

	stat, err := system.Stat(path)
	if err == nil {
		if !stat.IsDir() {
			return &os.PathError{Op: "mkdir", Path: path, Err: syscall.ENOTDIR}
		}
		if !chownExisting {
			return nil
		}

		// short-circuit--we were called with an existing directory and chown was requested
		return setPermissions(path, mode, owner.UID, owner.GID, stat)
	}

	// make an array containing the original path asked for, plus (for mkAll == true)
	// all path components leading up to the complete path that don't exist before we MkdirAll
	// so that we can chown all of them properly at the end.  If chownExisting is false, we won't
	// chown the full directory path if it exists
	var paths []string
	if os.IsNotExist(err) {
		paths = []string{path}
	}

	if mkAll {
		// walk back to "/" looking for directories which do not exist
		// and add them to the paths array for chown after creation
		dirPath := path
		for {
			dirPath = filepath.Dir(dirPath)
			if dirPath == "/" {
				break
			}
			if _, err := os.Stat(dirPath); err != nil && os.IsNotExist(err) {
				paths = append(paths, dirPath)
			}
		}
		if err := os.MkdirAll(path, mode); err != nil {
			return err
		}
	} else {
		if err := os.Mkdir(path, mode); err != nil && !os.IsExist(err) {
			return err
		}
	}
	// even if it existed, we will chown the requested path + any subpaths that
	// didn't exist when we called MkdirAll
	for _, pathComponent := range paths {
		if err := setPermissions(pathComponent, mode, owner.UID, owner.GID, nil); err != nil {
			return err
		}
	}
	return nil
}

// CanAccess takes a valid (existing) directory and a uid, gid pair and determines
// if that uid, gid pair has access (execute bit) to the directory
func CanAccess(path string, pair Identity) bool {
	statInfo, err := system.Stat(path)
	if err != nil {
		return false
	}
	perms := os.FileMode(statInfo.Mode()).Perm()
	if perms&0o001 == 0o001 {
		// world access
		return true
	}
	if statInfo.UID() == uint32(pair.UID) && (perms&0o100 == 0o100) {
		// owner access.
		return true
	}
	if statInfo.GID() == uint32(pair.GID) && (perms&0o010 == 0o010) {
		// group access.
		return true
	}
	return false
}

// LookupUser uses traditional local system files lookup (from libcontainer/user) on a username,
// followed by a call to `getent` for supporting host configured non-files passwd and group dbs
func LookupUser(name string) (user.User, error) {
	// first try a local system files lookup using existing capabilities
	usr, err := user.LookupUser(name)
	if err == nil {
		return usr, nil
	}
	// local files lookup failed; attempt to call `getent` to query configured passwd dbs
	usr, err = getentUser(name)
	if err != nil {
		return user.User{}, err
	}
	return usr, nil
}

// LookupUID uses traditional local system files lookup (from libcontainer/user) on a uid,
// followed by a call to `getent` for supporting host configured non-files passwd and group dbs
func LookupUID(uid int) (user.User, error) {
	// first try a local system files lookup using existing capabilities
	usr, err := user.LookupUid(uid)
	if err == nil {
		return usr, nil
	}
	// local files lookup failed; attempt to call `getent` to query configured passwd dbs
	return getentUser(strconv.Itoa(uid))
}

func getentUser(name string) (user.User, error) {
	reader, err := callGetent("passwd", name)
	if err != nil {
		return user.User{}, err
	}
	users, err := user.ParsePasswd(reader)
	if err != nil {
		return user.User{}, err
	}
	if len(users) == 0 {
		return user.User{}, fmt.Errorf("getent failed to find passwd entry for %q", name)
	}
	return users[0], nil
}

// LookupGroup uses traditional local system files lookup (from libcontainer/user) on a group name,
// followed by a call to `getent` for supporting host configured non-files passwd and group dbs
func LookupGroup(name string) (user.Group, error) {
	// first try a local system files lookup using existing capabilities
	group, err := user.LookupGroup(name)
	if err == nil {
		return group, nil
	}
	// local files lookup failed; attempt to call `getent` to query configured group dbs
	return getentGroup(name)
}

// LookupGID uses traditional local system files lookup (from libcontainer/user) on a group ID,
// followed by a call to `getent` for supporting host configured non-files passwd and group dbs
func LookupGID(gid int) (user.Group, error) {
	// first try a local system files lookup using existing capabilities
	group, err := user.LookupGid(gid)
	if err == nil {
		return group, nil
	}
	// local files lookup failed; attempt to call `getent` to query configured group dbs
	return getentGroup(strconv.Itoa(gid))
}

func getentGroup(name string) (user.Group, error) {
	reader, err := callGetent("group", name)
	if err != nil {
		return user.Group{}, err
	}
	groups, err := user.ParseGroup(reader)
	if err != nil {
		return user.Group{}, err
	}
	if len(groups) == 0 {
		return user.Group{}, fmt.Errorf("getent failed to find groups entry for %q", name)
	}
	return groups[0], nil
}

func callGetent(database, key string) (io.Reader, error) {
	entOnce.Do(func() { getentCmd, _ = resolveBinary("getent") })
	// if no `getent` command on host, can't do anything else
	if getentCmd == "" {
		return nil, fmt.Errorf("unable to find getent command")
	}
	out, err := execCmd(getentCmd, database, key)
	if err != nil {
		exitCode, errC := getExitCode(err)
		if errC != nil {
			return nil, err
		}
		switch exitCode {
		case 1:
			return nil, fmt.Errorf("getent reported invalid parameters/database unknown")
		case 2:
			return nil, fmt.Errorf("getent unable to find entry %q in %s database", key, database)
		case 3:
			return nil, fmt.Errorf("getent database doesn't support enumeration")
		default:
			return nil, err
		}
	}
	return bytes.NewReader(out), nil
}

// getExitCode returns the ExitStatus of the specified error if its type is
// exec.ExitError, returns 0 and an error otherwise.
func getExitCode(err error) (int, error) {
	exitCode := 0
	if exiterr, ok := err.(*exec.ExitError); ok {
		if procExit, ok := exiterr.Sys().(syscall.WaitStatus); ok {
			return procExit.ExitStatus(), nil
		}
	}
	return exitCode, fmt.Errorf("failed to get exit code")
}

// setPermissions performs a chown/chmod only if the uid/gid don't match what's requested
// Normally a Chown is a no-op if uid/gid match, but in some cases this can still cause an error, e.g. if the
// dir is on an NFS share, so don't call chown unless we absolutely must.
// Likewise for setting permissions.
func setPermissions(p string, mode os.FileMode, uid, gid int, stat *system.StatT) error {
	if stat == nil {
		var err error
		stat, err = system.Stat(p)
		if err != nil {
			return err
		}
	}
	if os.FileMode(stat.Mode()).Perm() != mode.Perm() {
		if err := os.Chmod(p, mode.Perm()); err != nil {
			return err
		}
	}
	if stat.UID() == uint32(uid) && stat.GID() == uint32(gid) {
		return nil
	}
	return os.Chown(p, uid, gid)
}

// LoadIdentityMapping takes a requested username and
// using the data from /etc/sub{uid,gid} ranges, creates the
// proper uid and gid remapping ranges for that user/group pair
func LoadIdentityMapping(name string) (IdentityMapping, error) {
	usr, err := LookupUser(name)
	if err != nil {
		return IdentityMapping{}, fmt.Errorf("could not get user for username %s: %v", name, err)
	}

	subuidRanges, err := lookupSubUIDRanges(usr)
	if err != nil {
		return IdentityMapping{}, err
	}
	subgidRanges, err := lookupSubGIDRanges(usr)
	if err != nil {
		return IdentityMapping{}, err
	}

	return IdentityMapping{
		UIDMaps: subuidRanges,
		GIDMaps: subgidRanges,
	}, nil
}

func lookupSubUIDRanges(usr user.User) ([]IDMap, error) {
	rangeList, err := parseSubuid(strconv.Itoa(usr.Uid))
	if err != nil {
		return nil, err
	}
	if len(rangeList) == 0 {
		rangeList, err = parseSubuid(usr.Name)
		if err != nil {
			return nil, err
		}
	}
	if len(rangeList) == 0 {
		return nil, fmt.Errorf("no subuid ranges found for user %q", usr.Name)
	}
	return createIDMap(rangeList), nil
}

func lookupSubGIDRanges(usr user.User) ([]IDMap, error) {
	rangeList, err := parseSubgid(strconv.Itoa(usr.Uid))
	if err != nil {
		return nil, err
	}
	if len(rangeList) == 0 {
		rangeList, err = parseSubgid(usr.Name)
		if err != nil {
			return nil, err
		}
	}
	if len(rangeList) == 0 {
		return nil, fmt.Errorf("no subgid ranges found for user %q", usr.Name)
	}
	return createIDMap(rangeList), nil
}
<commit_msg>pkg/idtools: don't use system.Stat() on unix<commit_after>//go:build !windows
// +build !windows

package idtools // import "github.com/docker/docker/pkg/idtools"

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"sync"
	"syscall"

	"github.com/opencontainers/runc/libcontainer/user"
)

var (
	entOnce   sync.Once
	getentCmd string
)

func mkdirAs(path string, mode os.FileMode, owner Identity, mkAll, chownExisting bool) error {
	path, err := filepath.Abs(path)
	if err != nil {
		return err
	}

	stat, err := os.Stat(path)
	if err == nil {
		if !stat.IsDir() {
			return &os.PathError{Op: "mkdir", Path: path, Err: syscall.ENOTDIR}
		}
		if !chownExisting {
			return nil
		}

		// short-circuit--we were called with an existing directory and chown was requested
		return setPermissions(path, mode, owner.UID, owner.GID, stat)
	}

	// make an array containing the original path asked for, plus (for mkAll == true)
	// all path components leading up to the complete path that don't exist before we MkdirAll
	// so that we can chown all of them properly at the end.  If chownExisting is false, we won't
	// chown the full directory path if it exists
	var paths []string
	if os.IsNotExist(err) {
		paths = []string{path}
	}

	if mkAll {
		// walk back to "/" looking for directories which do not exist
		// and add them to the paths array for chown after creation
		dirPath := path
		for {
			dirPath = filepath.Dir(dirPath)
			if dirPath == "/" {
				break
			}
			if _, err := os.Stat(dirPath); err != nil && os.IsNotExist(err) {
				paths = append(paths, dirPath)
			}
		}
		if err := os.MkdirAll(path, mode); err != nil {
			return err
		}
	} else {
		if err := os.Mkdir(path, mode); err != nil && !os.IsExist(err) {
			return err
		}
	}
	// even if it existed, we will chown the requested path + any subpaths that
	// didn't exist when we called MkdirAll
	for _, pathComponent := range paths {
		if err := setPermissions(pathComponent, mode, owner.UID, owner.GID, nil); err != nil {
			return err
		}
	}
	return nil
}

// CanAccess takes a valid (existing) directory and a uid, gid pair and determines
// if that uid, gid pair has access (execute bit) to the directory
func CanAccess(path string, pair Identity) bool {
	statInfo, err := os.Stat(path)
	if err != nil {
		return false
	}
	perms := statInfo.Mode().Perm()
	if perms&0o001 == 0o001 {
		// world access
		return true
	}
	ssi := statInfo.Sys().(*syscall.Stat_t)
	if ssi.Uid == uint32(pair.UID) && (perms&0o100 == 0o100) {
		// owner access.
		return true
	}
	if ssi.Gid == uint32(pair.GID) && (perms&0o010 == 0o010) {
		// group access.
		return true
	}
	return false
}

// LookupUser uses traditional local system files lookup (from libcontainer/user) on a username,
// followed by a call to `getent` for supporting host configured non-files passwd and group dbs
func LookupUser(name string) (user.User, error) {
	// first try a local system files lookup using existing capabilities
	usr, err := user.LookupUser(name)
	if err == nil {
		return usr, nil
	}
	// local files lookup failed; attempt to call `getent` to query configured passwd dbs
	usr, err = getentUser(name)
	if err != nil {
		return user.User{}, err
	}
	return usr, nil
}

// LookupUID uses traditional local system files lookup (from libcontainer/user) on a uid,
// followed by a call to `getent` for supporting host configured non-files passwd and group dbs
func LookupUID(uid int) (user.User, error) {
	// first try a local system files lookup using existing capabilities
	usr, err := user.LookupUid(uid)
	if err == nil {
		return usr, nil
	}
	// local files lookup failed; attempt to call `getent` to query configured passwd dbs
	return getentUser(strconv.Itoa(uid))
}

func getentUser(name string) (user.User, error) {
	reader, err := callGetent("passwd", name)
	if err != nil {
		return user.User{}, err
	}
	users, err := user.ParsePasswd(reader)
	if err != nil {
		return user.User{}, err
	}
	if len(users) == 0 {
		return user.User{}, fmt.Errorf("getent failed to find passwd entry for %q", name)
	}
	return users[0], nil
}

// LookupGroup uses traditional local system files lookup (from libcontainer/user) on a group name,
// followed by a call to `getent` for supporting host configured non-files passwd and group dbs
func LookupGroup(name string) (user.Group, error) {
	// first try a local system files lookup using existing capabilities
	group, err := user.LookupGroup(name)
	if err == nil {
		return group, nil
	}
	// local files lookup failed; attempt to call `getent` to query configured group dbs
	return getentGroup(name)
}

// LookupGID uses traditional local system files lookup (from libcontainer/user) on a group ID,
// followed by a call to `getent` for supporting host configured non-files passwd and group dbs
func LookupGID(gid int) (user.Group, error) {
	// first try a local system files lookup using existing capabilities
	group, err := user.LookupGid(gid)
	if err == nil {
		return group, nil
	}
	// local files lookup failed; attempt to call `getent` to query configured group dbs
	return getentGroup(strconv.Itoa(gid))
}

func getentGroup(name string) (user.Group, error) {
	reader, err := callGetent("group", name)
	if err != nil {
		return user.Group{}, err
	}
	groups, err := user.ParseGroup(reader)
	if err != nil {
		return user.Group{}, err
	}
	if len(groups) == 0 {
		return user.Group{}, fmt.Errorf("getent failed to find groups entry for %q", name)
	}
	return groups[0], nil
}

func callGetent(database, key string) (io.Reader, error) {
	entOnce.Do(func() { getentCmd, _ = resolveBinary("getent") })
	// if no `getent` command on host, can't do anything else
	if getentCmd == "" {
		return nil, fmt.Errorf("unable to find getent command")
	}
	out, err := execCmd(getentCmd, database, key)
	if err != nil {
		exitCode, errC := getExitCode(err)
		if errC != nil {
			return nil, err
		}
		switch exitCode {
		case 1:
			return nil, fmt.Errorf("getent reported invalid parameters/database unknown")
		case 2:
			return nil, fmt.Errorf("getent unable to find entry %q in %s database", key, database)
		case 3:
			return nil, fmt.Errorf("getent database doesn't support enumeration")
		default:
			return nil, err
		}
	}
	return bytes.NewReader(out), nil
}

// getExitCode returns the ExitStatus of the specified error if its type is
// exec.ExitError, returns 0 and an error otherwise.
func getExitCode(err error) (int, error) {
	exitCode := 0
	if exiterr, ok := err.(*exec.ExitError); ok {
		if procExit, ok := exiterr.Sys().(syscall.WaitStatus); ok {
			return procExit.ExitStatus(), nil
		}
	}
	return exitCode, fmt.Errorf("failed to get exit code")
}

// setPermissions performs a chown/chmod only if the uid/gid don't match what's requested
// Normally a Chown is a no-op if uid/gid match, but in some cases this can still cause an error, e.g. if the
// dir is on an NFS share, so don't call chown unless we absolutely must.
// Likewise for setting permissions.
func setPermissions(p string, mode os.FileMode, uid, gid int, stat os.FileInfo) error {
	if stat == nil {
		var err error
		stat, err = os.Stat(p)
		if err != nil {
			return err
		}
	}
	if stat.Mode().Perm() != mode.Perm() {
		if err := os.Chmod(p, mode.Perm()); err != nil {
			return err
		}
	}
	ssi := stat.Sys().(*syscall.Stat_t)
	if ssi.Uid == uint32(uid) && ssi.Gid == uint32(gid) {
		return nil
	}
	return os.Chown(p, uid, gid)
}

// LoadIdentityMapping takes a requested username and
// using the data from /etc/sub{uid,gid} ranges, creates the
// proper uid and gid remapping ranges for that user/group pair
func LoadIdentityMapping(name string) (IdentityMapping, error) {
	usr, err := LookupUser(name)
	if err != nil {
		return IdentityMapping{}, fmt.Errorf("could not get user for username %s: %v", name, err)
	}

	subuidRanges, err := lookupSubUIDRanges(usr)
	if err != nil {
		return IdentityMapping{}, err
	}
	subgidRanges, err := lookupSubGIDRanges(usr)
	if err != nil {
		return IdentityMapping{}, err
	}

	return IdentityMapping{
		UIDMaps: subuidRanges,
		GIDMaps: subgidRanges,
	}, nil
}

func lookupSubUIDRanges(usr user.User) ([]IDMap, error) {
	rangeList, err := parseSubuid(strconv.Itoa(usr.Uid))
	if err != nil {
		return nil, err
	}
	if len(rangeList) == 0 {
		rangeList, err = parseSubuid(usr.Name)
		if err != nil {
			return nil, err
		}
	}
	if len(rangeList) == 0 {
		return nil, fmt.Errorf("no subuid ranges found for user %q", usr.Name)
	}
	return createIDMap(rangeList), nil
}

func lookupSubGIDRanges(usr user.User) ([]IDMap, error) {
	rangeList, err := parseSubgid(strconv.Itoa(usr.Uid))
	if err != nil {
		return nil, err
	}
	if len(rangeList) == 0 {
		rangeList, err = parseSubgid(usr.Name)
		if err != nil {
			return nil, err
		}
	}
	if len(rangeList) == 0 {
		return nil, fmt.Errorf("no subgid ranges found for user %q", usr.Name)
	}
	return createIDMap(rangeList), nil
}
<|endoftext|>


<commit_before>/*
Copyright 2014 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package rest

import (
	"k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/api/meta"
	genericvalidation "k8s.io/apimachinery/pkg/api/validation"
	"k8s.io/apimachinery/pkg/api/validation/path"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/apimachinery/pkg/util/validation/field"
	genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
	"k8s.io/apiserver/pkg/storage/names"
)

// RESTCreateStrategy defines the minimum validation, accepted input, and
// name generation behavior to create an object that follows Kubernetes
// API conventions.
type RESTCreateStrategy interface {
	runtime.ObjectTyper
	// The name generator is used when the standard GenerateName field is set.
	// The NameGenerator will be invoked prior to validation.
	names.NameGenerator

	// NamespaceScoped returns true if the object must be within a namespace.
	NamespaceScoped() bool
	// PrepareForCreate is invoked on create before validation to normalize
	// the object.  For example: remove fields that are not to be persisted,
	// sort order-insensitive list fields, etc.  This should not remove fields
	// whose presence would be considered a validation error.
	PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object)
	// Validate returns an ErrorList with validation errors or nil.  Validate
	// is invoked after default fields in the object have been filled in
	// before the object is persisted.  This method should not mutate the
	// object.
	Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList
	// Canonicalize allows an object to be mutated into a canonical form. This
	// ensures that code that operates on these objects can rely on the common
	// form for things like comparison.  Canonicalize is invoked after
	// validation has succeeded but before the object has been persisted.
	// This method may mutate the object.
	Canonicalize(obj runtime.Object)
}

// BeforeCreate ensures that common operations for all resources are performed on creation. It only returns
// errors that can be converted to api.Status. It invokes PrepareForCreate, then GenerateName, then Validate.
// It returns nil if the object should be created.
func BeforeCreate(strategy RESTCreateStrategy, ctx genericapirequest.Context, obj runtime.Object) error {
	objectMeta, kind, kerr := objectMetaAndKind(strategy, obj)
	if kerr != nil {
		return kerr
	}

	if strategy.NamespaceScoped() {
		if !ValidNamespace(ctx, objectMeta) {
			return errors.NewBadRequest("the namespace of the provided object does not match the namespace sent on the request")
		}
	} else {
		objectMeta.SetNamespace(metav1.NamespaceNone)
	}
	objectMeta.SetDeletionTimestamp(nil)
	objectMeta.SetDeletionGracePeriodSeconds(nil)
	strategy.PrepareForCreate(ctx, obj)
	FillObjectMetaSystemFields(ctx, objectMeta)
	if len(objectMeta.GetGenerateName()) > 0 && len(objectMeta.GetName()) == 0 {
		objectMeta.SetName(strategy.GenerateName(objectMeta.GetGenerateName()))
	}

	// ClusterName is ignored and should not be saved
	objectMeta.SetClusterName("")

	if errs := strategy.Validate(ctx, obj); len(errs) > 0 {
		return errors.NewInvalid(kind.GroupKind(), objectMeta.GetName(), errs)
	}

	// Custom validation (including name validation) passed
	// Now run common validation on object meta
	// Do this *after* custom validation so that specific error messages are shown whenever possible
	if errs := genericvalidation.ValidateObjectMetaAccessor(objectMeta, strategy.NamespaceScoped(), path.ValidatePathSegmentName, field.NewPath("metadata")); len(errs) > 0 {
		return errors.NewInvalid(kind.GroupKind(), objectMeta.GetName(), errs)
	}

	strategy.Canonicalize(obj)

	return nil
}

// CheckGeneratedNameError checks whether an error that occurred creating a resource is due
// to generation being unable to pick a valid name.
func CheckGeneratedNameError(strategy RESTCreateStrategy, err error, obj runtime.Object) error {
	if !errors.IsAlreadyExists(err) {
		return err
	}

	objectMeta, kind, kerr := objectMetaAndKind(strategy, obj)
	if kerr != nil {
		return kerr
	}

	if len(objectMeta.GetGenerateName()) == 0 {
		return err
	}

	return errors.NewServerTimeoutForKind(kind.GroupKind(), "POST", 0)
}

// objectMetaAndKind retrieves kind and ObjectMeta from a runtime object, or returns an error.
func objectMetaAndKind(typer runtime.ObjectTyper, obj runtime.Object) (metav1.Object, schema.GroupVersionKind, error) {
	objectMeta, err := meta.Accessor(obj)
	if err != nil {
		return nil, schema.GroupVersionKind{}, errors.NewInternalError(err)
	}
	kinds, _, err := typer.ObjectKinds(obj)
	if err != nil {
		return nil, schema.GroupVersionKind{}, errors.NewInternalError(err)
	}
	return objectMeta, kinds[0], nil
}

// NamespaceScopedStrategy has a method to tell if the object must be in a namespace.
type NamespaceScopedStrategy interface {
	// NamespaceScoped returns if the object must be in a namespace.
	NamespaceScoped() bool
}
<commit_msg>documentation for implementors of RESTCreateStrategy<commit_after>/*
Copyright 2014 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package rest

import (
	"k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/api/meta"
	genericvalidation "k8s.io/apimachinery/pkg/api/validation"
	"k8s.io/apimachinery/pkg/api/validation/path"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/apimachinery/pkg/util/validation/field"
	genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
	"k8s.io/apiserver/pkg/storage/names"
)

// RESTCreateStrategy defines the minimum validation, accepted input, and
// name generation behavior to create an object that follows Kubernetes
// API conventions.
type RESTCreateStrategy interface {
	runtime.ObjectTyper
	// The name generator is used when the standard GenerateName field is set.
	// The NameGenerator will be invoked prior to validation.
	names.NameGenerator

	// NamespaceScoped returns true if the object must be within a namespace.
	NamespaceScoped() bool
	// PrepareForCreate is invoked on create before validation to normalize
	// the object.  For example: remove fields that are not to be persisted,
	// sort order-insensitive list fields, etc.  This should not remove fields
	// whose presence would be considered a validation error.
	//
	// Often implemented as a type check and an initailization or clearing of
	// status. Clear the status because status changes are internal. External
	// callers of an api (users) should not be setting an initial status on
	// newly created objects.
	PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object)
	// Validate returns an ErrorList with validation errors or nil.  Validate
	// is invoked after default fields in the object have been filled in
	// before the object is persisted.  This method should not mutate the
	// object.
	Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList
	// Canonicalize allows an object to be mutated into a canonical form. This
	// ensures that code that operates on these objects can rely on the common
	// form for things like comparison.  Canonicalize is invoked after
	// validation has succeeded but before the object has been persisted.
	// This method may mutate the object. Often implemented as a type check or
	// empty method.
	Canonicalize(obj runtime.Object)
}

// BeforeCreate ensures that common operations for all resources are performed on creation. It only returns
// errors that can be converted to api.Status. It invokes PrepareForCreate, then GenerateName, then Validate.
// It returns nil if the object should be created.
func BeforeCreate(strategy RESTCreateStrategy, ctx genericapirequest.Context, obj runtime.Object) error {
	objectMeta, kind, kerr := objectMetaAndKind(strategy, obj)
	if kerr != nil {
		return kerr
	}

	if strategy.NamespaceScoped() {
		if !ValidNamespace(ctx, objectMeta) {
			return errors.NewBadRequest("the namespace of the provided object does not match the namespace sent on the request")
		}
	} else {
		objectMeta.SetNamespace(metav1.NamespaceNone)
	}
	objectMeta.SetDeletionTimestamp(nil)
	objectMeta.SetDeletionGracePeriodSeconds(nil)
	strategy.PrepareForCreate(ctx, obj)
	FillObjectMetaSystemFields(ctx, objectMeta)
	if len(objectMeta.GetGenerateName()) > 0 && len(objectMeta.GetName()) == 0 {
		objectMeta.SetName(strategy.GenerateName(objectMeta.GetGenerateName()))
	}

	// ClusterName is ignored and should not be saved
	objectMeta.SetClusterName("")

	if errs := strategy.Validate(ctx, obj); len(errs) > 0 {
		return errors.NewInvalid(kind.GroupKind(), objectMeta.GetName(), errs)
	}

	// Custom validation (including name validation) passed
	// Now run common validation on object meta
	// Do this *after* custom validation so that specific error messages are shown whenever possible
	if errs := genericvalidation.ValidateObjectMetaAccessor(objectMeta, strategy.NamespaceScoped(), path.ValidatePathSegmentName, field.NewPath("metadata")); len(errs) > 0 {
		return errors.NewInvalid(kind.GroupKind(), objectMeta.GetName(), errs)
	}

	strategy.Canonicalize(obj)

	return nil
}

// CheckGeneratedNameError checks whether an error that occurred creating a resource is due
// to generation being unable to pick a valid name.
func CheckGeneratedNameError(strategy RESTCreateStrategy, err error, obj runtime.Object) error {
	if !errors.IsAlreadyExists(err) {
		return err
	}

	objectMeta, kind, kerr := objectMetaAndKind(strategy, obj)
	if kerr != nil {
		return kerr
	}

	if len(objectMeta.GetGenerateName()) == 0 {
		return err
	}

	return errors.NewServerTimeoutForKind(kind.GroupKind(), "POST", 0)
}

// objectMetaAndKind retrieves kind and ObjectMeta from a runtime object, or returns an error.
func objectMetaAndKind(typer runtime.ObjectTyper, obj runtime.Object) (metav1.Object, schema.GroupVersionKind, error) {
	objectMeta, err := meta.Accessor(obj)
	if err != nil {
		return nil, schema.GroupVersionKind{}, errors.NewInternalError(err)
	}
	kinds, _, err := typer.ObjectKinds(obj)
	if err != nil {
		return nil, schema.GroupVersionKind{}, errors.NewInternalError(err)
	}
	return objectMeta, kinds[0], nil
}

// NamespaceScopedStrategy has a method to tell if the object must be in a namespace.
type NamespaceScopedStrategy interface {
	// NamespaceScoped returns if the object must be in a namespace.
	NamespaceScoped() bool
}
<|endoftext|>


<commit_before>package main

import (
	log "github.com/GameGophers/nsq-logger"
	"github.com/fzzy/radix/redis"
	"golang.org/x/net/context"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
	"os"
	pb "proto"
	"runtime"
	"strconv"
	"strings"
	"time"
)

const (
	SERVICE             = "[BGSAVE]"
	DEFAULT_SAVE_DELAY  = 100 * time.Millisecond
	DEFAULT_REDIS_HOST  = "127.0.0.1:6379"
	DEFAULT_MONGODB_URL = "mongodb://127.0.0.1/mydb"
	ENV_REDIS_HOST      = "REDIS_HOST"
	ENV_MONGODB_URL     = "MONGODB_URL"
	ENV_SAVE_DELAY      = "SAVE_DELAY"
	BUFSIZ              = 4096
	BATCH_SIZE          = 1024 // data save batch size
)

type server struct {
	wait        chan string
	redis_host  string
	mongodb_url string
}

func (s *server) init() {
	s.redis_host = DEFAULT_REDIS_HOST
	if env := os.Getenv(ENV_REDIS_HOST); env != "" {
		s.redis_host = env
	}

	s.mongodb_url = DEFAULT_MONGODB_URL
	if env := os.Getenv(ENV_MONGODB_URL); env != "" {
		s.mongodb_url = env
	}

	s.wait = make(chan string, BUFSIZ)
	go s.loader_task()
}

func (s *server) MarkDirty(ctx context.Context, in *pb.BgSave_Key) (*pb.BgSave_NullResult, error) {
	s.wait <- in.Name
	return &pb.BgSave_NullResult{}, nil
}

func (s *server) MarkDirties(ctx context.Context, in *pb.BgSave_Keys) (*pb.BgSave_NullResult, error) {
	for k := range in.Names {
		s.wait <- in.Names[k]
	}
	return &pb.BgSave_NullResult{}, nil
}

// background loader, copy chan into map, execute dump every DEFAULT_SAVE_DELAY
func (s *server) loader_task() {
	for {
		dirty := make(map[string]bool)
		timer := time.After(DEFAULT_SAVE_DELAY)
		select {
		case key := <-s.wait:
			dirty[key] = true
		case <-timer:
			s.dump(dirty)
			dirty = make(map[string]bool)
		}
	}
}

// dump all dirty data into backend database
func (s *server) dump(dirty map[string]bool) {
	// start connection to redis
	client, err := redis.Dial("tcp", s.redis_host)
	if err != nil {
		log.Critical(err)
		return
	}
	defer client.Close()

	// start connection to mongodb
	sess, err := mgo.Dial(s.mongodb_url)
	if err != nil {
		log.Critical(err)
		return
	}
	defer sess.Close()
	// database is provided in url
	db := sess.DB("")

	// copy dirty map into array
	dirty_list := make([]interface{}, 0, len(dirty))
	for k := range dirty {
		dirty_list = append(dirty_list, k)
	}

	if len(dirty_list) == 0 { // ignore emtpy dirty list
		return
	}

	// write data in batch
	var sublist []interface{}
	for i := 0; i < len(dirty_list); i += BATCH_SIZE {
		if (i+1)*BATCH_SIZE > len(dirty_list) { // reach end
			sublist = dirty_list[i*BATCH_SIZE:]
		} else {
			sublist = dirty_list[i*BATCH_SIZE : (i+1)*BATCH_SIZE]
		}

		// mget data from redis
		records, err := client.Cmd("mget", sublist...).ListBytes()
		if err != nil {
			log.Critical(err)
			return
		}

		// save to mongodb
		var tmp map[string]interface{}
		for k, v := range sublist {
			err := bson.Unmarshal(records[k], &tmp)
			if err != nil {
				log.Critical(err)
				continue
			}

			// split key into TABLE NAME and RECORD ID
			strs := strings.Split(v.(string), ":")
			if len(strs) != 2 { // log the wrong key
				log.Critical("cannot split key", v)
				continue
			}
			tblname, id_str := strs[0], strs[1]
			// save data to mongodb
			id, err := strconv.Atoi(id_str)
			if err != nil {
				log.Critical(err)
				continue
			}

			_, err = db.C(tblname).Upsert(bson.M{"Id": id}, tmp)
			if err != nil {
				log.Critical(err)
				continue
			}
		}
	}
	runtime.GC()
}
<commit_msg>optimize<commit_after>package main

import (
	log "github.com/GameGophers/nsq-logger"
	"github.com/fzzy/radix/redis"
	"golang.org/x/net/context"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
	"os"
	pb "proto"
	"runtime"
	"strconv"
	"strings"
	"time"
)

const (
	SERVICE             = "[BGSAVE]"
	DEFAULT_SAVE_DELAY  = 100 * time.Millisecond
	DEFAULT_REDIS_HOST  = "127.0.0.1:6379"
	DEFAULT_MONGODB_URL = "mongodb://127.0.0.1/mydb"
	ENV_REDIS_HOST      = "REDIS_HOST"
	ENV_MONGODB_URL     = "MONGODB_URL"
	BUFSIZ              = 4096
	BATCH_SIZE          = 1024 // data save batch size
)

type server struct {
	wait         chan string
	redis_client *redis.Client
	mgodb        *mgo.Database
}

func (s *server) init() {
	// read redis host
	redis_host := DEFAULT_REDIS_HOST
	if env := os.Getenv(ENV_REDIS_HOST); env != "" {
		redis_host = env
	}
	// start connection to redis
	client, err := redis.Dial("tcp", redis_host)
	if err != nil {
		log.Critical(err)
		os.Exit(-1)
	}
	s.redis_client = client

	// read mongodb host
	mongodb_url := DEFAULT_MONGODB_URL
	if env := os.Getenv(ENV_MONGODB_URL); env != "" {
		mongodb_url = env
	}

	// start connection to mongodb
	sess, err := mgo.Dial(mongodb_url)
	if err != nil {
		log.Critical(err)
		os.Exit(-1)
	}
	// database is provided in url
	s.mgodb = sess.DB("")

	// wait chan
	s.wait = make(chan string, BUFSIZ)
	go s.loader_task()
}

func (s *server) MarkDirty(ctx context.Context, in *pb.BgSave_Key) (*pb.BgSave_NullResult, error) {
	s.wait <- in.Name
	return &pb.BgSave_NullResult{}, nil
}

func (s *server) MarkDirties(ctx context.Context, in *pb.BgSave_Keys) (*pb.BgSave_NullResult, error) {
	for k := range in.Names {
		s.wait <- in.Names[k]
	}
	return &pb.BgSave_NullResult{}, nil
}

// background loader, copy chan into map, execute dump every DEFAULT_SAVE_DELAY
func (s *server) loader_task() {
	for {
		dirty := make(map[string]bool)
		timer := time.After(DEFAULT_SAVE_DELAY)
		select {
		case key := <-s.wait:
			dirty[key] = true
		case <-timer:
			s.dump(dirty)
			dirty = make(map[string]bool)
		}
	}
}

// dump all dirty data into backend database
func (s *server) dump(dirty map[string]bool) {
	// copy dirty map into array
	dirty_list := make([]interface{}, 0, len(dirty))
	for k := range dirty {
		dirty_list = append(dirty_list, k)
	}

	if len(dirty_list) == 0 { // ignore emtpy dirty list
		return
	}

	// write data in batch
	var sublist []interface{}
	for i := 0; i < len(dirty_list); i += BATCH_SIZE {
		if (i+1)*BATCH_SIZE > len(dirty_list) { // reach end
			sublist = dirty_list[i*BATCH_SIZE:]
		} else {
			sublist = dirty_list[i*BATCH_SIZE : (i+1)*BATCH_SIZE]
		}

		// mget data from redis
		records, err := s.redis_client.Cmd("mget", sublist...).ListBytes()
		if err != nil {
			log.Critical(err)
			return
		}

		// save to mongodb
		var tmp map[string]interface{}
		for k, v := range sublist {
			err := bson.Unmarshal(records[k], &tmp)
			if err != nil {
				log.Critical(err)
				continue
			}

			// split key into TABLE NAME and RECORD ID
			strs := strings.Split(v.(string), ":")
			if len(strs) != 2 { // log the wrong key
				log.Critical("cannot split key", v)
				continue
			}
			tblname, id_str := strs[0], strs[1]
			// save data to mongodb
			id, err := strconv.Atoi(id_str)
			if err != nil {
				log.Critical(err)
				continue
			}

			_, err = s.mgodb.C(tblname).Upsert(bson.M{"Id": id}, tmp)
			if err != nil {
				log.Critical(err)
				continue
			}
		}
	}
	runtime.GC()
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
)

type Repository struct {
	Name        string `json:"name"`
	URL         string `json:"url"`
	Description string `json:"description"`
	Homepage    string `json:"homepage"`
}

type Commit struct {
	ID        string `json:"id"`
	Message   string `json:"message"`
	Timestamp string `json:"timestamp"`
	URL       string `json:"url"`
	Author    Author `json:"author"`
}

type Author struct {
	Name  string `json:"name"`
	Email string `json:"email"`
}

type PushEvent struct {
	Before            string     `json:"before"`
	After             string     `json:"after"`
	Ref               string     `json:"ref"`
	UserID            int        `json:"user_id"`
	UserName          string     `json:"user_name"`
	ProjectID         int        `json:"project_id"`
	Repository        Repository `json:"repository"`
	Commits           []Commit   `json:"commits"`
	TotalCommitsCount int        `json:"total_commits_count"`
}

func main() {
	mux := http.NewServeMux()

	mux.HandleFunc("/push", pushEventHandler)
	mux.HandleFunc("/tag", tagEventHandler)

	http.ListenAndServe(":12138", mux)
}

func pushEventHandler(w http.ResponseWriter, req *http.Request) {
	data, err := ioutil.ReadAll(req.Body)
	if err != nil {
		fmt.Println(err)
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	event := &PushEvent{}
	err = json.Unmarshal(data, event)
	if err != nil {
		fmt.Println(err)
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	fmt.Printf("%v\n", event)
}

func tagEventHandler(w http.ResponseWriter, req *http.Request) {
	data, err := ioutil.ReadAll(req.Body)
	if err != nil {
		fmt.Println(err)
		w.WriteHeader(http.StatusBadRequest)
		return
	}
	fmt.Printf("%v\n", data)
}
<commit_msg>print string<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
)

type Repository struct {
	Name        string `json:"name"`
	URL         string `json:"url"`
	Description string `json:"description"`
	Homepage    string `json:"homepage"`
}

type Commit struct {
	ID        string `json:"id"`
	Message   string `json:"message"`
	Timestamp string `json:"timestamp"`
	URL       string `json:"url"`
	Author    Author `json:"author"`
}

type Author struct {
	Name  string `json:"name"`
	Email string `json:"email"`
}

type PushEvent struct {
	Before            string     `json:"before"`
	After             string     `json:"after"`
	Ref               string     `json:"ref"`
	UserID            int        `json:"user_id"`
	UserName          string     `json:"user_name"`
	ProjectID         int        `json:"project_id"`
	Repository        Repository `json:"repository"`
	Commits           []Commit   `json:"commits"`
	TotalCommitsCount int        `json:"total_commits_count"`
}

func main() {
	mux := http.NewServeMux()

	mux.HandleFunc("/push", pushEventHandler)
	mux.HandleFunc("/tag", tagEventHandler)

	http.ListenAndServe(":12138", mux)
}

func pushEventHandler(w http.ResponseWriter, req *http.Request) {
	data, err := ioutil.ReadAll(req.Body)
	if err != nil {
		fmt.Println(err)
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	event := &PushEvent{}
	err = json.Unmarshal(data, event)
	if err != nil {
		fmt.Println(err)
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	fmt.Printf("%v\n", event)
}

func tagEventHandler(w http.ResponseWriter, req *http.Request) {
	data, err := ioutil.ReadAll(req.Body)
	if err != nil {
		fmt.Println(err)
		w.WriteHeader(http.StatusBadRequest)
		return
	}
	fmt.Printf("%v\n", string(data))
}
<|endoftext|>