<commit_before>package shell

import (
	"context"
	"errors"
	"fmt"
	"io"
	"os"
	"os/exec"
	"reflect"
	"strings"
	"sync"
	"syscall"

	"github.com/zetamatta/go-findfile"

	"../dos"
	. "../ifdbg"
)

const FLAG_AMP2NEWCONSOLE = false

var WildCardExpansionAlways = false

type CommandNotFound struct {
	Name string
	Err  error
}

// from "TDM-GCC-64/x86_64-w64-mingw32/include/winbase.h"
const (
	CREATE_NEW_CONSOLE       = 0x10
	CREATE_NEW_PROCESS_GROUP = 0x200
)

func (this CommandNotFound) Stringer() string {
	return fmt.Sprintf("'%s' is not recognized as an internal or external command,\noperable program or batch file", this.Name)
}

func (this CommandNotFound) Error() string {
	return this.Stringer()
}

type Cmd struct {
	Stdout       *os.File
	Stderr       *os.File
	Stdin        *os.File
	Args         []string
	HookCount    int
	Tag          interface{}
	PipeSeq      [2]uint
	IsBackGround bool
	RawArgs      []string

	OnFork  func(*Cmd) error
	OffFork func(*Cmd) error
	Closers []io.Closer
}

func (this *Cmd) GetRawArgs() []string {
	return this.RawArgs
}

func (this *Cmd) Close() {
	if this.Closers != nil {
		for _, c := range this.Closers {
			c.Close()
		}
		this.Closers = nil
	}
}

func New() *Cmd {
	this := Cmd{
		Stdin:  os.Stdin,
		Stdout: os.Stdout,
		Stderr: os.Stderr,
	}
	this.PipeSeq[0] = pipeSeq
	this.PipeSeq[1] = 0
	return &this
}

func (this *Cmd) Clone() (*Cmd, error) {
	rv := new(Cmd)
	rv.Args = this.Args
	rv.RawArgs = this.RawArgs
	rv.Stdin = this.Stdin
	rv.Stdout = this.Stdout
	rv.Stderr = this.Stderr
	rv.HookCount = this.HookCount
	rv.Tag = this.Tag
	rv.PipeSeq = this.PipeSeq
	rv.Closers = nil
	rv.OnFork = this.OnFork
	rv.OffFork = this.OffFork
	return rv, nil
}

type ArgsHookT func(it *Cmd, args []string) ([]string, error)

var argsHook = func(it *Cmd, args []string) ([]string, error) {
	return args, nil
}

func SetArgsHook(argsHook_ ArgsHookT) (rv ArgsHookT) {
	rv, argsHook = argsHook, argsHook_
	return
}

type HookT func(context.Context, *Cmd) (int, bool, error)

var hook = func(context.Context, *Cmd) (int, bool, error) {
	return 0, false, nil
}

func SetHook(hook_ HookT) (rv HookT) {
	rv, hook = hook, hook_
	return
}

var OnCommandNotFound = func(this *Cmd, err error) error {
	err = &CommandNotFound{this.Args[0], err}
	return err
}

var LastErrorLevel int

func nvl(a *os.File, b *os.File) *os.File {
	if a != nil {
		return a
	} else {
		return b
	}
}

func makeCmdline(args, rawargs []string) string {
	buffer := make([]byte, 0, 1024)
	for i, s := range args {
		if i > 0 {
			buffer = append(buffer, ' ')
		}
		if (len(rawargs) > i && len(rawargs[i]) > 0 && rawargs[i][0] == '"') || strings.ContainsAny(s, " &|<>\t\"") {
			buffer = append(buffer, '"')
			qs := strings.Replace(s, `"`, `\"`, -1)
			buffer = append(buffer, qs...)
			buffer = append(buffer, '"')
		} else {
			buffer = append(buffer, s...)
		}
	}
	return string(buffer)
}

func (this *Cmd) spawnvp_noerrmsg(ctx context.Context) (int, error) {
	// command is empty.
	if len(this.Args) <= 0 {
		return 0, nil
	}
	if DBG {
		print("spawnvp_noerrmsg('", this.Args[0], "')\n")
	}

	// aliases and lua-commands
	if errorlevel, done, err := hook(ctx, this); done || err != nil {
		return errorlevel, err
	}

	// command not found hook
	var err error
	path1 := dos.LookPath(this.Args[0], "NYAGOSPATH")
	if path1 == "" {
		return 255, OnCommandNotFound(this, os.ErrNotExist)
	}
	this.Args[0] = path1

	if DBG {
		print("exec.LookPath(", this.Args[0], ")==", path1, "\n")
	}

	if WildCardExpansionAlways {
		this.Args = findfile.Globs(this.Args)
	}

	cmd1 := exec.Command(this.Args[0], this.Args[1:]...)
	cmd1.Stdin = this.Stdin
	cmd1.Stdout = this.Stdout
	cmd1.Stderr = this.Stderr

	// executable-file
	if FLAG_AMP2NEWCONSOLE {
		if cmd1.SysProcAttr != nil && (cmd1.SysProcAttr.CreationFlags&CREATE_NEW_CONSOLE) != 0 {
			err = cmd1.Start()
			return 0, err
		}
	}

	if cmd1.SysProcAttr == nil {
		cmd1.SysProcAttr = new(syscall.SysProcAttr)
	}
	cmdline := makeCmdline(cmd1.Args, this.RawArgs)
	if DBG {
		println(cmdline)
	}
	cmd1.SysProcAttr.CmdLine = cmdline
	err = cmd1.Run()

	errorlevel, errorlevelOk := dos.GetErrorLevel(cmd1)
	if errorlevelOk {
		return errorlevel, err
	} else {
		return 255, err
	}
}

type AlreadyReportedError struct {
	Err error
}

func (this AlreadyReportedError) Error() string {
	return ""
}

func IsAlreadyReported(err error) bool {
	_, ok := err.(AlreadyReportedError)
	return ok
}

func (this *Cmd) Spawnvp() (int, error) {
	return this.SpawnvpContext(context.Background())
}

func (this *Cmd) SpawnvpContext(ctx context.Context) (int, error) {
	errorlevel, err := this.spawnvp_noerrmsg(ctx)
	if err != nil && err != io.EOF && !IsAlreadyReported(err) {
		if DBG {
			val := reflect.ValueOf(err)
			fmt.Fprintf(this.Stderr, "error-type=%s\n", val.Type())
		}
		fmt.Fprintln(this.Stderr, err.Error())
		err = AlreadyReportedError{err}
	}
	return errorlevel, err
}

var pipeSeq uint = 0

func (this *Cmd) Interpret(text string) (int, error) {
	return this.InterpretContext(context.Background(), text)
}

type gotoEol struct{}

var GotoEol = gotoEol{}

func (this *Cmd) InterpretContext(ctx_ context.Context, text string) (errorlevel int, finalerr error) {
	if DBG {
		print("Interpret('", text, "')\n")
	}
	if this == nil {
		return 255, errors.New("Fatal Error: Interpret: instance is nil")
	}
	errorlevel = 0
	finalerr = nil

	statements, statementsErr := Parse(text)
	if statementsErr != nil {
		if DBG {
			print("Parse Error:", statementsErr.Error(), "\n")
		}
		return 0, statementsErr
	}
	if argsHook != nil {
		if DBG {
			print("call argsHook\n")
		}
		for _, pipeline := range statements {
			for _, state := range pipeline {
				var err error
				state.Args, err = argsHook(this, state.Args)
				if err != nil {
					return 255, err
				}
			}
		}
		if DBG {
			print("done argsHook\n")
		}
	}
	for _, pipeline := range statements {
		for i, state := range pipeline {
			if state.Term == "|" && (i+1 >= len(pipeline) || len(pipeline[i+1].Args) <= 0) {
				return 255, errors.New("The syntax of the command is incorrect.")
			}
		}
	}

	for _, pipeline := range statements {

		var pipeIn *os.File = nil
		pipeSeq++
		isBackGround := this.IsBackGround
		for _, state := range pipeline {
			if state.Term == "&" {
				isBackGround = true
				break
			}
		}
		var wg sync.WaitGroup
		shutdown_immediately := false
		for i, state := range pipeline {
			if DBG {
				print(i, ": pipeline loop(", state.Args[0], ")\n")
			}
			cmd, err := this.Clone()
			if err != nil {
				return 255, err
			}
			cmd.PipeSeq[0] = pipeSeq
			cmd.PipeSeq[1] = uint(1 + i)
			cmd.IsBackGround = isBackGround

			ctx := context.WithValue(ctx_, GotoEol, func() {
				shutdown_immediately = true
				gotoeol, ok := ctx_.Value(GotoEol).(func())
				if ok {
					gotoeol()
				}
			})

			if pipeIn != nil {
				cmd.Stdin = pipeIn
				cmd.Closers = append(cmd.Closers, pipeIn)
				pipeIn = nil
			}

			if state.Term[0] == '|' {
				var pipeOut *os.File
				pipeIn, pipeOut, err = os.Pipe()
				cmd.Stdout = pipeOut
				if state.Term == "|&" {
					cmd.Stderr = pipeOut
				}
				cmd.Closers = append(cmd.Closers, pipeOut)
			}

			for _, red := range state.Redirect {
				var fd *os.File
				fd, err = red.OpenOn(cmd)
				if err != nil {
					return 0, err
				}
				defer fd.Close()
			}

			cmd.Args = state.Args
			cmd.RawArgs = state.RawArgs
			if i > 0 {
				cmd.IsBackGround = true
			}
			if i == len(pipeline)-1 && state.Term != "&" {
				// foreground execution.
				errorlevel, finalerr = cmd.SpawnvpContext(ctx)
				LastErrorLevel = errorlevel
				cmd.Close()
			} else {
				// background
				if !isBackGround {
					wg.Add(1)
				}
				if cmd.OnFork != nil {
					if err := cmd.OnFork(cmd); err != nil {
						fmt.Fprintln(cmd.Stderr, err.Error())
						return -1, err
					}
				}
				go func(cmd1 *Cmd) {
					if !isBackGround {
						defer wg.Done()
					}
					cmd1.SpawnvpContext(ctx)
					if cmd1.OffFork != nil {
						if err := cmd1.OffFork(cmd1); err != nil {
							fmt.Fprintln(cmd1.Stderr, err.Error())
							goto exit
						}
					}
				exit:
					cmd1.Close()
				}(cmd)
			}
		}
		if !isBackGround {
			wg.Wait()
			if shutdown_immediately {
				return errorlevel, nil
			}
			if len(pipeline) > 0 {
				switch pipeline[len(pipeline)-1].Term {
				case "&&":
					if errorlevel != 0 {
						return errorlevel, nil
					}
				case "||":
					if errorlevel == 0 {
						return errorlevel, nil
					}
				}
			}
		}
	}
	return
}
<commit_msg>Remove shell.FLAG_AMP2NEWCONSOLE which is unused<commit_after>package shell

import (
	"context"
	"errors"
	"fmt"
	"io"
	"os"
	"os/exec"
	"reflect"
	"strings"
	"sync"
	"syscall"

	"github.com/zetamatta/go-findfile"

	"../dos"
	. "../ifdbg"
)

var WildCardExpansionAlways = false

type CommandNotFound struct {
	Name string
	Err  error
}

// from "TDM-GCC-64/x86_64-w64-mingw32/include/winbase.h"
const (
	CREATE_NEW_CONSOLE       = 0x10
	CREATE_NEW_PROCESS_GROUP = 0x200
)

func (this CommandNotFound) Stringer() string {
	return fmt.Sprintf("'%s' is not recognized as an internal or external command,\noperable program or batch file", this.Name)
}

func (this CommandNotFound) Error() string {
	return this.Stringer()
}

type Cmd struct {
	Stdout       *os.File
	Stderr       *os.File
	Stdin        *os.File
	Args         []string
	HookCount    int
	Tag          interface{}
	PipeSeq      [2]uint
	IsBackGround bool
	RawArgs      []string

	OnFork  func(*Cmd) error
	OffFork func(*Cmd) error
	Closers []io.Closer
}

func (this *Cmd) GetRawArgs() []string {
	return this.RawArgs
}

func (this *Cmd) Close() {
	if this.Closers != nil {
		for _, c := range this.Closers {
			c.Close()
		}
		this.Closers = nil
	}
}

func New() *Cmd {
	this := Cmd{
		Stdin:  os.Stdin,
		Stdout: os.Stdout,
		Stderr: os.Stderr,
	}
	this.PipeSeq[0] = pipeSeq
	this.PipeSeq[1] = 0
	return &this
}

func (this *Cmd) Clone() (*Cmd, error) {
	rv := new(Cmd)
	rv.Args = this.Args
	rv.RawArgs = this.RawArgs
	rv.Stdin = this.Stdin
	rv.Stdout = this.Stdout
	rv.Stderr = this.Stderr
	rv.HookCount = this.HookCount
	rv.Tag = this.Tag
	rv.PipeSeq = this.PipeSeq
	rv.Closers = nil
	rv.OnFork = this.OnFork
	rv.OffFork = this.OffFork
	return rv, nil
}

type ArgsHookT func(it *Cmd, args []string) ([]string, error)

var argsHook = func(it *Cmd, args []string) ([]string, error) {
	return args, nil
}

func SetArgsHook(argsHook_ ArgsHookT) (rv ArgsHookT) {
	rv, argsHook = argsHook, argsHook_
	return
}

type HookT func(context.Context, *Cmd) (int, bool, error)

var hook = func(context.Context, *Cmd) (int, bool, error) {
	return 0, false, nil
}

func SetHook(hook_ HookT) (rv HookT) {
	rv, hook = hook, hook_
	return
}

var OnCommandNotFound = func(this *Cmd, err error) error {
	err = &CommandNotFound{this.Args[0], err}
	return err
}

var LastErrorLevel int

func nvl(a *os.File, b *os.File) *os.File {
	if a != nil {
		return a
	} else {
		return b
	}
}

func makeCmdline(args, rawargs []string) string {
	buffer := make([]byte, 0, 1024)
	for i, s := range args {
		if i > 0 {
			buffer = append(buffer, ' ')
		}
		if (len(rawargs) > i && len(rawargs[i]) > 0 && rawargs[i][0] == '"') || strings.ContainsAny(s, " &|<>\t\"") {
			buffer = append(buffer, '"')
			qs := strings.Replace(s, `"`, `\"`, -1)
			buffer = append(buffer, qs...)
			buffer = append(buffer, '"')
		} else {
			buffer = append(buffer, s...)
		}
	}
	return string(buffer)
}

func (this *Cmd) spawnvp_noerrmsg(ctx context.Context) (int, error) {
	// command is empty.
	if len(this.Args) <= 0 {
		return 0, nil
	}
	if DBG {
		print("spawnvp_noerrmsg('", this.Args[0], "')\n")
	}

	// aliases and lua-commands
	if errorlevel, done, err := hook(ctx, this); done || err != nil {
		return errorlevel, err
	}

	// command not found hook
	var err error
	path1 := dos.LookPath(this.Args[0], "NYAGOSPATH")
	if path1 == "" {
		return 255, OnCommandNotFound(this, os.ErrNotExist)
	}
	this.Args[0] = path1

	if DBG {
		print("exec.LookPath(", this.Args[0], ")==", path1, "\n")
	}

	if WildCardExpansionAlways {
		this.Args = findfile.Globs(this.Args)
	}

	cmd1 := exec.Command(this.Args[0], this.Args[1:]...)
	cmd1.Stdin = this.Stdin
	cmd1.Stdout = this.Stdout
	cmd1.Stderr = this.Stderr

	if cmd1.SysProcAttr == nil {
		cmd1.SysProcAttr = new(syscall.SysProcAttr)
	}
	cmdline := makeCmdline(cmd1.Args, this.RawArgs)
	if DBG {
		println(cmdline)
	}
	cmd1.SysProcAttr.CmdLine = cmdline
	err = cmd1.Run()

	errorlevel, errorlevelOk := dos.GetErrorLevel(cmd1)
	if errorlevelOk {
		return errorlevel, err
	} else {
		return 255, err
	}
}

type AlreadyReportedError struct {
	Err error
}

func (this AlreadyReportedError) Error() string {
	return ""
}

func IsAlreadyReported(err error) bool {
	_, ok := err.(AlreadyReportedError)
	return ok
}

func (this *Cmd) Spawnvp() (int, error) {
	return this.SpawnvpContext(context.Background())
}

func (this *Cmd) SpawnvpContext(ctx context.Context) (int, error) {
	errorlevel, err := this.spawnvp_noerrmsg(ctx)
	if err != nil && err != io.EOF && !IsAlreadyReported(err) {
		if DBG {
			val := reflect.ValueOf(err)
			fmt.Fprintf(this.Stderr, "error-type=%s\n", val.Type())
		}
		fmt.Fprintln(this.Stderr, err.Error())
		err = AlreadyReportedError{err}
	}
	return errorlevel, err
}

var pipeSeq uint = 0

func (this *Cmd) Interpret(text string) (int, error) {
	return this.InterpretContext(context.Background(), text)
}

type gotoEol struct{}

var GotoEol = gotoEol{}

func (this *Cmd) InterpretContext(ctx_ context.Context, text string) (errorlevel int, finalerr error) {
	if DBG {
		print("Interpret('", text, "')\n")
	}
	if this == nil {
		return 255, errors.New("Fatal Error: Interpret: instance is nil")
	}
	errorlevel = 0
	finalerr = nil

	statements, statementsErr := Parse(text)
	if statementsErr != nil {
		if DBG {
			print("Parse Error:", statementsErr.Error(), "\n")
		}
		return 0, statementsErr
	}
	if argsHook != nil {
		if DBG {
			print("call argsHook\n")
		}
		for _, pipeline := range statements {
			for _, state := range pipeline {
				var err error
				state.Args, err = argsHook(this, state.Args)
				if err != nil {
					return 255, err
				}
			}
		}
		if DBG {
			print("done argsHook\n")
		}
	}
	for _, pipeline := range statements {
		for i, state := range pipeline {
			if state.Term == "|" && (i+1 >= len(pipeline) || len(pipeline[i+1].Args) <= 0) {
				return 255, errors.New("The syntax of the command is incorrect.")
			}
		}
	}

	for _, pipeline := range statements {

		var pipeIn *os.File = nil
		pipeSeq++
		isBackGround := this.IsBackGround
		for _, state := range pipeline {
			if state.Term == "&" {
				isBackGround = true
				break
			}
		}
		var wg sync.WaitGroup
		shutdown_immediately := false
		for i, state := range pipeline {
			if DBG {
				print(i, ": pipeline loop(", state.Args[0], ")\n")
			}
			cmd, err := this.Clone()
			if err != nil {
				return 255, err
			}
			cmd.PipeSeq[0] = pipeSeq
			cmd.PipeSeq[1] = uint(1 + i)
			cmd.IsBackGround = isBackGround

			ctx := context.WithValue(ctx_, GotoEol, func() {
				shutdown_immediately = true
				gotoeol, ok := ctx_.Value(GotoEol).(func())
				if ok {
					gotoeol()
				}
			})

			if pipeIn != nil {
				cmd.Stdin = pipeIn
				cmd.Closers = append(cmd.Closers, pipeIn)
				pipeIn = nil
			}

			if state.Term[0] == '|' {
				var pipeOut *os.File
				pipeIn, pipeOut, err = os.Pipe()
				cmd.Stdout = pipeOut
				if state.Term == "|&" {
					cmd.Stderr = pipeOut
				}
				cmd.Closers = append(cmd.Closers, pipeOut)
			}

			for _, red := range state.Redirect {
				var fd *os.File
				fd, err = red.OpenOn(cmd)
				if err != nil {
					return 0, err
				}
				defer fd.Close()
			}

			cmd.Args = state.Args
			cmd.RawArgs = state.RawArgs
			if i > 0 {
				cmd.IsBackGround = true
			}
			if i == len(pipeline)-1 && state.Term != "&" {
				// foreground execution.
				errorlevel, finalerr = cmd.SpawnvpContext(ctx)
				LastErrorLevel = errorlevel
				cmd.Close()
			} else {
				// background
				if !isBackGround {
					wg.Add(1)
				}
				if cmd.OnFork != nil {
					if err := cmd.OnFork(cmd); err != nil {
						fmt.Fprintln(cmd.Stderr, err.Error())
						return -1, err
					}
				}
				go func(cmd1 *Cmd) {
					if !isBackGround {
						defer wg.Done()
					}
					cmd1.SpawnvpContext(ctx)
					if cmd1.OffFork != nil {
						if err := cmd1.OffFork(cmd1); err != nil {
							fmt.Fprintln(cmd1.Stderr, err.Error())
							goto exit
						}
					}
				exit:
					cmd1.Close()
				}(cmd)
			}
		}
		if !isBackGround {
			wg.Wait()
			if shutdown_immediately {
				return errorlevel, nil
			}
			if len(pipeline) > 0 {
				switch pipeline[len(pipeline)-1].Term {
				case "&&":
					if errorlevel != 0 {
						return errorlevel, nil
					}
				case "||":
					if errorlevel == 0 {
						return errorlevel, nil
					}
				}
			}
		}
	}
	return
}
<|endoftext|>


<commit_before>package podipcontroller

import (
	"context"
	"fmt"
	"reflect"
	"strings"
	"time"

	"github.com/openshift/origin/pkg/monitor/monitorapi"
	corev1 "k8s.io/api/core/v1"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/labels"
	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
	"k8s.io/apimachinery/pkg/util/sets"
	"k8s.io/apimachinery/pkg/util/wait"
	informercorev1 "k8s.io/client-go/informers/core/v1"
	listerscorev1 "k8s.io/client-go/listers/core/v1"
	"k8s.io/client-go/tools/cache"
	"k8s.io/client-go/util/workqueue"
)

type Recorder interface {
	Record(conditions ...monitorapi.Condition)
}

type SimultaneousPodIPController struct {
	recorder Recorder

	podIPsToCurrentPodLocators map[string]sets.String
	podLister                  listerscorev1.PodLister

	cachesToSync []cache.InformerSynced

	queue workqueue.RateLimitingInterface
}

func NewSimultaneousPodIPController(
	recorder Recorder,
	podInformer informercorev1.PodInformer,
) *SimultaneousPodIPController {
	c := &SimultaneousPodIPController{
		recorder:                   recorder,
		podIPsToCurrentPodLocators: map[string]sets.String{},
		podLister:                  podInformer.Lister(),
		cachesToSync:               []cache.InformerSynced{podInformer.Informer().HasSynced},
		queue:                      workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "SimultaneousPodIPController"),
	}

	podInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
		AddFunc: c.Enqueue,
		UpdateFunc: func(oldObj, newObj interface{}) {
			oldPod, oldOk := oldObj.(*corev1.Pod)
			newPod, newOk := newObj.(*corev1.Pod)
			if oldOk && newOk {
				// if the podIPs have not changed, then we don't need to requeue because we will have queued when the change happened.
				// if another pod is created that conflicts, we'll have a separate notification for that pod.
				if reflect.DeepEqual(oldPod.Status.PodIPs, newPod.Status.PodIPs) {
					return
				}
			}
			c.Enqueue(newObj)
		},
		DeleteFunc: c.Enqueue,
	})

	return c
}

func (c *SimultaneousPodIPController) Enqueue(obj interface{}) {
	key, err := cache.MetaNamespaceKeyFunc(obj)
	if err != nil {
		utilruntime.HandleError(fmt.Errorf("invalid queue key '%v': %v", obj, err))
		return
	}
	c.queue.Add(key)
}

func (c *SimultaneousPodIPController) Run(ctx context.Context) {
	defer utilruntime.HandleCrash()

	fmt.Printf("Starting SimultaneousPodIPController")
	defer func() {
		fmt.Printf("Shutting down SimultaneousPodIPController")
		c.queue.ShutDown()
		fmt.Printf("SimultaneousPodIPController shut down")
	}()

	if !cache.WaitForNamedCacheSync("SimultaneousPodIPController", ctx.Done(), c.cachesToSync...) {
		return
	}

	go func() {
		// this only works because we have a single thread consuming
		wait.UntilWithContext(ctx, c.runWorker, time.Second)
	}()

	<-ctx.Done()
}

func (c *SimultaneousPodIPController) runWorker(ctx context.Context) {
	for c.processNextItem(ctx) {
	}
}

func (c *SimultaneousPodIPController) processNextItem(ctx context.Context) bool {
	key, quit := c.queue.Get()
	if quit {
		return false
	}
	defer c.queue.Done(key)

	err := c.sync(ctx, key.(string))

	if err == nil {
		c.queue.Forget(key)
		return true
	}

	utilruntime.HandleError(fmt.Errorf("%v failed with : %w", key, err))
	c.queue.AddRateLimited(key)

	return true
}

func (c *SimultaneousPodIPController) sync(ctx context.Context, key string) error {
	// Convert the namespace/name string into a distinct namespace and name
	namespace, name, err := cache.SplitMetaNamespaceKey(key)
	if err != nil {
		utilruntime.HandleError(fmt.Errorf("invalid resource key: %s", key))
		return nil
	}

	pod, err := c.podLister.Pods(namespace).Get(name)
	if apierrors.IsNotFound(err) {
		return nil
	}
	if err != nil {
		return err
	}

	// only consider pod network pods because host network pods will have duplicated IPs
	if pod.Spec.HostNetwork {
		return nil
	}
	if isPodIPReleased(pod) {
		return nil
	}

	otherPods, err := c.podLister.List(labels.Everything())
	if err != nil {
		return err
	}

	podLocator := monitorapi.LocatePod(pod)
	for _, currIP := range pod.Status.PodIPs {
		currPodIP := currIP.IP
		podNames := sets.NewString()

		// iterate through every ip of every pod.  I wonder how badly this will scale.
		// with the filtering for pod updates to only include those that changed podIPs, it will likely be fine.
		for _, otherPod := range otherPods {
			if otherPod.Spec.HostNetwork {
				continue
			}
			if isPodIPReleased(otherPod) {
				continue
			}

			for _, otherIP := range otherPod.Status.PodIPs {
				otherPodIP := otherIP.IP
				if currPodIP == otherPodIP {
					otherPodLocator := monitorapi.LocatePod(otherPod)
					podNames.Insert(otherPodLocator)
				}
			}
		}

		if len(podNames) > 1 {
			// the .Record function adds a timestamp of now to the condition so we track time.
			c.recorder.Record(monitorapi.Condition{
				Level:   monitorapi.Error,
				Locator: podLocator,
				Message: monitorapi.ReasonedMessagef(monitorapi.PodIPReused, "podIP %v is currently assigned to multiple pods: %v", currPodIP, strings.Join(podNames.List(), ";")),
			})
		}
	}

	return nil
}

// isPodIPReleased returns true if the podIP can be reused.
// This happens on pod deletion and when the pod will not start any more containers
func isPodIPReleased(pod *corev1.Pod) bool {
	if pod.DeletionTimestamp != nil {
		return true
	}

	if pod.Status.Phase == corev1.PodSucceeded || pod.Status.Phase == corev1.PodFailed {
		return true
	}

	return false
}
<commit_msg>Add newlines to SimultaneousPodIPController<commit_after>package podipcontroller

import (
	"context"
	"fmt"
	"reflect"
	"strings"
	"time"

	"github.com/openshift/origin/pkg/monitor/monitorapi"
	corev1 "k8s.io/api/core/v1"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/labels"
	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
	"k8s.io/apimachinery/pkg/util/sets"
	"k8s.io/apimachinery/pkg/util/wait"
	informercorev1 "k8s.io/client-go/informers/core/v1"
	listerscorev1 "k8s.io/client-go/listers/core/v1"
	"k8s.io/client-go/tools/cache"
	"k8s.io/client-go/util/workqueue"
)

type Recorder interface {
	Record(conditions ...monitorapi.Condition)
}

type SimultaneousPodIPController struct {
	recorder Recorder

	podIPsToCurrentPodLocators map[string]sets.String
	podLister                  listerscorev1.PodLister

	cachesToSync []cache.InformerSynced

	queue workqueue.RateLimitingInterface
}

func NewSimultaneousPodIPController(
	recorder Recorder,
	podInformer informercorev1.PodInformer,
) *SimultaneousPodIPController {
	c := &SimultaneousPodIPController{
		recorder:                   recorder,
		podIPsToCurrentPodLocators: map[string]sets.String{},
		podLister:                  podInformer.Lister(),
		cachesToSync:               []cache.InformerSynced{podInformer.Informer().HasSynced},
		queue:                      workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "SimultaneousPodIPController"),
	}

	podInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
		AddFunc: c.Enqueue,
		UpdateFunc: func(oldObj, newObj interface{}) {
			oldPod, oldOk := oldObj.(*corev1.Pod)
			newPod, newOk := newObj.(*corev1.Pod)
			if oldOk && newOk {
				// if the podIPs have not changed, then we don't need to requeue because we will have queued when the change happened.
				// if another pod is created that conflicts, we'll have a separate notification for that pod.
				if reflect.DeepEqual(oldPod.Status.PodIPs, newPod.Status.PodIPs) {
					return
				}
			}
			c.Enqueue(newObj)
		},
		DeleteFunc: c.Enqueue,
	})

	return c
}

func (c *SimultaneousPodIPController) Enqueue(obj interface{}) {
	key, err := cache.MetaNamespaceKeyFunc(obj)
	if err != nil {
		utilruntime.HandleError(fmt.Errorf("invalid queue key '%v': %v", obj, err))
		return
	}
	c.queue.Add(key)
}

func (c *SimultaneousPodIPController) Run(ctx context.Context) {
	defer utilruntime.HandleCrash()

	fmt.Printf("Starting SimultaneousPodIPController\n")
	defer func() {
		fmt.Printf("Shutting down SimultaneousPodIPController\n")
		c.queue.ShutDown()
		fmt.Printf("SimultaneousPodIPController shut down\n")
	}()

	if !cache.WaitForNamedCacheSync("SimultaneousPodIPController", ctx.Done(), c.cachesToSync...) {
		return
	}

	go func() {
		// this only works because we have a single thread consuming
		wait.UntilWithContext(ctx, c.runWorker, time.Second)
	}()

	<-ctx.Done()
}

func (c *SimultaneousPodIPController) runWorker(ctx context.Context) {
	for c.processNextItem(ctx) {
	}
}

func (c *SimultaneousPodIPController) processNextItem(ctx context.Context) bool {
	key, quit := c.queue.Get()
	if quit {
		return false
	}
	defer c.queue.Done(key)

	err := c.sync(ctx, key.(string))

	if err == nil {
		c.queue.Forget(key)
		return true
	}

	utilruntime.HandleError(fmt.Errorf("%v failed with : %w", key, err))
	c.queue.AddRateLimited(key)

	return true
}

func (c *SimultaneousPodIPController) sync(ctx context.Context, key string) error {
	// Convert the namespace/name string into a distinct namespace and name
	namespace, name, err := cache.SplitMetaNamespaceKey(key)
	if err != nil {
		utilruntime.HandleError(fmt.Errorf("invalid resource key: %s", key))
		return nil
	}

	pod, err := c.podLister.Pods(namespace).Get(name)
	if apierrors.IsNotFound(err) {
		return nil
	}
	if err != nil {
		return err
	}

	// only consider pod network pods because host network pods will have duplicated IPs
	if pod.Spec.HostNetwork {
		return nil
	}
	if isPodIPReleased(pod) {
		return nil
	}

	otherPods, err := c.podLister.List(labels.Everything())
	if err != nil {
		return err
	}

	podLocator := monitorapi.LocatePod(pod)
	for _, currIP := range pod.Status.PodIPs {
		currPodIP := currIP.IP
		podNames := sets.NewString()

		// iterate through every ip of every pod.  I wonder how badly this will scale.
		// with the filtering for pod updates to only include those that changed podIPs, it will likely be fine.
		for _, otherPod := range otherPods {
			if otherPod.Spec.HostNetwork {
				continue
			}
			if isPodIPReleased(otherPod) {
				continue
			}

			for _, otherIP := range otherPod.Status.PodIPs {
				otherPodIP := otherIP.IP
				if currPodIP == otherPodIP {
					otherPodLocator := monitorapi.LocatePod(otherPod)
					podNames.Insert(otherPodLocator)
				}
			}
		}

		if len(podNames) > 1 {
			// the .Record function adds a timestamp of now to the condition so we track time.
			c.recorder.Record(monitorapi.Condition{
				Level:   monitorapi.Error,
				Locator: podLocator,
				Message: monitorapi.ReasonedMessagef(monitorapi.PodIPReused, "podIP %v is currently assigned to multiple pods: %v", currPodIP, strings.Join(podNames.List(), ";")),
			})
		}
	}

	return nil
}

// isPodIPReleased returns true if the podIP can be reused.
// This happens on pod deletion and when the pod will not start any more containers
func isPodIPReleased(pod *corev1.Pod) bool {
	if pod.DeletionTimestamp != nil {
		return true
	}

	if pod.Status.Phase == corev1.PodSucceeded || pod.Status.Phase == corev1.PodFailed {
		return true
	}

	return false
}
<|endoftext|>


<commit_before>/*
Copyright 2016 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 logwatchers

import (
	"k8s.io/node-problem-detector/pkg/systemlogmonitor/logwatchers/types"

	"github.com/golang/glog"
)

// createFuncs is a table of createFuncs for all supported log watchers.
var createFuncs = map[string]types.WatcherCreateFunc{}

// registerLogWatcher registers a createFunc for a log watcher.
func registerLogWatcher(name string, create types.WatcherCreateFunc) {
	createFuncs[name] = create
}

// GetLogWatcherOrDie get a log watcher based on the passed in configuration.
// The function panics when encounts an error.
func GetLogWatcherOrDie(config types.WatcherConfig) types.LogWatcher {
	create, ok := createFuncs[config.Plugin]
	if !ok {
		glog.Fatalf("No create function found for plugin %q", config.Plugin)
	}
	glog.Infof("Use log watcher of plugin %q", config.Plugin)
	return create(config)
}
<commit_msg>Typo fix: encounts->encounters<commit_after>/*
Copyright 2016 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 logwatchers

import (
	"k8s.io/node-problem-detector/pkg/systemlogmonitor/logwatchers/types"

	"github.com/golang/glog"
)

// createFuncs is a table of createFuncs for all supported log watchers.
var createFuncs = map[string]types.WatcherCreateFunc{}

// registerLogWatcher registers a createFunc for a log watcher.
func registerLogWatcher(name string, create types.WatcherCreateFunc) {
	createFuncs[name] = create
}

// GetLogWatcherOrDie get a log watcher based on the passed in configuration.
// The function panics when encounters an error.
func GetLogWatcherOrDie(config types.WatcherConfig) types.LogWatcher {
	create, ok := createFuncs[config.Plugin]
	if !ok {
		glog.Fatalf("No create function found for plugin %q", config.Plugin)
	}
	glog.Infof("Use log watcher of plugin %q", config.Plugin)
	return create(config)
}
<|endoftext|>


<commit_before>package main

// index template
const index = `[[define "index"]]<!doctype html>

[[template "head" . ]]

<ng-include src="'pages/global.html'"></ng-include>

[[template "header" . ]]

[[end]]`

// head items
const head = `[[define "head"]]
<base href="/[[ .base ]]">
<title data-ng-bind="page.title">[[ .title ]]</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="[[ .desc ]]" />
[[if .nsfw -]]<meta name="rating" content="adult" />
<meta name="rating" content="RTA-5042-1996-1400-1577-RTA" />[[- end]]
<link rel="stylesheet" href="/assets/prim/[[ .primcss ]]" />
<link rel="stylesheet" href="/assets/styles/[[ .style ]]" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">

[[template "angular" . ]][[template "headinclude" . ]]
[[end]]`

// angular config
const angular = `[[define "angular"]][[end]]`

// site header
const header = `[[define "header"]]

[[template "navmenuinclude" . ]][[template "navmenu" . ]]

<ng-include src="'pages/menus/nav.html'"></ng-include>

Sign in

<ng-include src="'pages/menus/user.html'"></ng-include>

[[end]]`

const navmenu = `[[define "navmenu"]][[ range $ib := .imageboards -]]<li><a target="_self" href="//[[ $ib.Address ]]/">[[ $ib.Title ]]</a></li>[[- end]][[end]]`
<commit_msg>move stylesheets above js<commit_after>package main

// index template
const index = `[[define "index"]]<!doctype html>

[[template "head" . ]]

<ng-include src="'pages/global.html'"></ng-include>

[[template "header" . ]]

[[end]]`

// head items
const head = `[[define "head"]]
<base href="/[[ .base ]]">
<title data-ng-bind="page.title">[[ .title ]]</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="[[ .desc ]]" />
[[if .nsfw -]]<meta name="rating" content="adult" />
<meta name="rating" content="RTA-5042-1996-1400-1577-RTA" />[[- end]]
<link rel="stylesheet" href="/assets/prim/[[ .primcss ]]" />
<link rel="stylesheet" href="/assets/styles/[[ .style ]]" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">

[[template "angular" . ]][[template "headinclude" . ]]
[[end]]`

// angular config
const angular = `[[define "angular"]][[end]]`

// site header
const header = `[[define "header"]]

[[template "navmenuinclude" . ]][[template "navmenu" . ]]

<ng-include src="'pages/menus/nav.html'"></ng-include>

Sign in

<ng-include src="'pages/menus/user.html'"></ng-include>

[[end]]`

const navmenu = `[[define "navmenu"]]
[[ range $ib := .imageboards -]]
[[ $ib.Title ]]
[[- end]]
[[end]]`
<|endoftext|>


<commit_before>package multipass

import "html/template"

const (
	loginPage = iota
	tokenInvalidPage
	tokenSentPage
	continueOrSignoutPage
)

type page struct {
	PJAX        bool
	Page        int
	NextURL     string
	LoginPath   string
	SignoutPath string
}

func loadTemplates() (*template.Template, error) {
	tmpl := template.New("")
	template.Must(tmpl.New("head").Parse(`<!DOCTYPE html>

	<meta charset="utf-8">
	<meta name="description" content="Multipass">
	<title>Multipass</title>

`))

	template.Must(tmpl.New("tail").Parse(`</body></html>`))

	template.Must(tmpl.New("loginform").Parse(`
<form action="{{ .LoginPath }}" method=POST class="login-form">
	<input type=hidden name=url value="{{ .NextURL }}" />
	<input type=text name=handle placeholder="Your handle ..." />
	<input type=submit value="Submit" class="btn btn-default">
</form>`))

	template.Must(tmpl.New("signoutform").Parse(`
<form action="{{ .SignoutPath }}" method=POST class="login-form">
	<input type=hidden name=url value="{{ .NextURL }}" />
	<input type=submit value="Signout" class="btn btn-danger">
</form>`))

	template.Must(tmpl.New("page").Parse(`
	{{ if ne .PJAX true }}{{ template "head"}}{{end}}

Multipass

		{{ if eq .Page 0 }}
			{{ template "loginform" . }}

This resource is protected. Submit your handle to gain access.

		{{ else if eq .Page 1 }}

Your access token has expired or is invalid. Submit your handle to request a one.

			{{ template "loginform" . }}

This resource is protected.

		{{ else if eq .Page 2 }}

A message with an access token was sent to your handle; Follow the login link in the message to gain access.

		{{ else if eq .Page 3 }}

Continue to access the private resource or signout.

			Continue
			{{ template "signoutform" . }}

This resource is protected.

		{{ else }}

Default page

		{{ end }}

{{ if ne .PJAX true }}{{ template "tail" }}{{ end }}`))

	template.Must(tmpl.New("style").Parse(`
* {
	-webkit-box-sizing: border-box;
	-moz-box-sizing: border-box;
	box-sizing: border-box;
}
article, aside, details, figcaption, figure, footer, header, hgroup,
main, nav, section, summary {
	display: block;
}
body {
	margin: 0;
}
.wrapper {
	display: -webkit-flex;
	-webkit-flex-direction: column;
}
.login-box {
	width: 480px;
	margin: 4rem auto;
	text-align: center;
	padding: 1rem 0;
	border: solid .16rem #0d8eba;
	border-radius: .8rem;
	padding: 1rem 2rem;
	background-color: #fff;
}
.login-box h1 {
	font-family: sans-serif;
	font-size: 3rem;
	color: #444;
}
.login-form {
}
.login-form input {
}
.login-form input[type=text] {
	font-size: 1.2rem;
	padding: 0 1rem;
	border-color: #ddd;
	color: #444;
	margin: .6rem 0;
	width: 100%;
	height: 2.8rem;
	border-radius: .4rem;
	border-style: solid;
	border-width: .16rem;
}
.login-form input[type=submit] {
}
.btn {
	font-family: sans-serif;
	font-size: 1.2rem;
	margin: 1rem 0;
	padding: .5rem 1rem;
	width: 100%;
	height: 2.8rem;
	border-radius: .4rem;
	border-style: solid;
	border-width: .16rem;
	text-transform: uppercase;
	color: #fff;
	height: 3rem;
	cursor: pointer;
}
a.btn {
	text-decoration: none;
	color: white;
	display: block;
}
.btn-default {
	background-color: #0d8eba;
	border-color: #0d8eba;
}
.btn-success {
	background-color: #0dba77;
	border-color: #0dba77;
}
.btn-danger {
	background-color: #ba2f0d;
	border-color: #ba2f0d;
}
.notice {
	font-style: italic;
	color: #666;
}
/* Narrow */
@media only screen and (max-width: 480px) {
	body {
		background-color: #0d8eba;
	}
	.login-box {
		width: 100%;
		border: none;
		border-radius: 0;
	}
}
/* Medium */
@media only screen and (min-width: 481px) and (max-width: 960px) {
}
/* Wide */
@media only screen and (min-width: 961px) {
}
`))
	return tmpl, nil
}
<commit_msg>Fix text alignment on HTML buttons<commit_after>package multipass

import "html/template"

const (
	loginPage = iota
	tokenInvalidPage
	tokenSentPage
	continueOrSignoutPage
)

type page struct {
	PJAX        bool
	Page        int
	NextURL     string
	LoginPath   string
	SignoutPath string
}

func loadTemplates() (*template.Template, error) {
	tmpl := template.New("")
	template.Must(tmpl.New("head").Parse(`<!DOCTYPE html>

	<meta charset="utf-8">
	<meta name="description" content="Multipass">
	<title>Multipass</title>

`))

	template.Must(tmpl.New("tail").Parse(`</body></html>`))

	template.Must(tmpl.New("loginform").Parse(`
<form action="{{ .LoginPath }}" method=POST class="login-form">
	<input type=hidden name=url value="{{ .NextURL }}" />
	<input type=text name=handle placeholder="Your handle ..." />
	<input type=submit value="Submit" class="btn btn-default">
</form>`))

	template.Must(tmpl.New("signoutform").Parse(`
<form action="{{ .SignoutPath }}" method=POST class="login-form">
	<input type=hidden name=url value="{{ .NextURL }}" />
	<input type=submit value="Signout" class="btn btn-danger">
</form>`))

	template.Must(tmpl.New("page").Parse(`
	{{ if ne .PJAX true }}{{ template "head"}}{{end}}

Multipass

		{{ if eq .Page 0 }}
			{{ template "loginform" . }}

This resource is protected. Submit your handle to gain access.

		{{ else if eq .Page 1 }}

Your access token has expired or is invalid. Submit your handle to request a one.

			{{ template "loginform" . }}

This resource is protected.

		{{ else if eq .Page 2 }}

A message with an access token was sent to your handle; Follow the login link in the message to gain access.

		{{ else if eq .Page 3 }}

Continue to access the private resource or signout.

			Continue
			{{ template "signoutform" . }}

This resource is protected.

		{{ else }}

Default page

		{{ end }}

{{ if ne .PJAX true }}{{ template "tail" }}{{ end }}`))

	template.Must(tmpl.New("style").Parse(`
* {
	-webkit-box-sizing: border-box;
	-moz-box-sizing: border-box;
	box-sizing: border-box;
}
article, aside, details, figcaption, figure, footer, header, hgroup,
main, nav, section, summary {
	display: block;
}
body {
	margin: 0;
}
.wrapper {
	display: -webkit-flex;
	-webkit-flex-direction: column;
}
.login-box {
	width: 480px;
	margin: 4rem auto;
	text-align: center;
	padding: 1rem 0;
	border: solid .16rem #0d8eba;
	border-radius: .8rem;
	padding: 1rem 2rem;
	background-color: #fff;
}
.login-box h1 {
	font-family: sans-serif;
	font-size: 3rem;
	color: #444;
}
.login-form {
}
.login-form input {
}
.login-form input[type=text] {
	font-size: 1.2rem;
	padding: 0 1rem;
	border-color: #ddd;
	color: #444;
	margin: .6rem 0;
	width: 100%;
	height: 2.8rem;
	border-radius: .4rem;
	border-style: solid;
	border-width: .16rem;
}
.login-form input[type=submit] {
}
.btn {
	font-family: sans-serif;
	font-size: 1.2rem;
	line-height: 2rem;
	margin: 1rem 0;
	padding: .5rem 1rem;
	width: 100%;
	height: 2.8rem;
	border-radius: .4rem;
	border-style: solid;
	border-width: .16rem;
	text-transform: uppercase;
	color: #fff;
	height: 3rem;
	cursor: pointer;
}
a.btn {
	text-decoration: none;
	color: white;
	display: block;
}
.btn-default {
	background-color: #0d8eba;
	border-color: #0d8eba;
}
.btn-success {
	background-color: #0dba77;
	border-color: #0dba77;
}
.btn-danger {
	background-color: #ba2f0d;
	border-color: #ba2f0d;
}
.notice {
	font-style: italic;
	color: #666;
}
/* Narrow */
@media only screen and (max-width: 480px) {
	body {
		background-color: #0d8eba;
	}
	.login-box {
		width: 100%;
		border: none;
		border-radius: 0;
	}
}
/* Medium */
@media only screen and (min-width: 481px) and (max-width: 960px) {
}
/* Wide */
@media only screen and (min-width: 961px) {
}
`))
	return tmpl, nil
}
<|endoftext|>


<commit_before>package feedloggr

const tmplCSS string = `
body {
	margin: 30px 5%;
	line-height: 1.5;
	font-size: 13px;
	font-family: monospace;
	background-color: #FFF;
	color: #444;
}
a, a:visited {
	color: #444;
	text-decoration: none;
}
a:hover {
	color: #000;
	text-decoration: underline;
}

nav {
	text-align: center;
	margin-bottom: 20px;
}
nav > a:hover {
	background-color: #E6E6E6;
	border-color: #ADADAD;
}
section {
	background-color: #FFF;
	margin-bottom: 20px;
}
section > h1, nav > a {
	border: 1px solid #DDD;
	border-radius: 3px;
	padding: 10px;
	margin: 0;
	font-size: 16px;
	font-weight: bold;
	text-align: center;
}
section > h1 {
	background-color: #EEE;
}
section > ul, p {
	padding: 0;
	margin: 20px 0;
	list-style: none;
}
section > ul > li {
        margin-bottom: 5px;
}
section > ul > li > a:visited {
	color: #AAA;
}
section > ul > hr {
        padding: 0;
        border: 0;
        height: 1px;
        margin: 5px 0px;
        background-image: linear-gradient(to right, #ccc, #fff);
}
footer {
	text-align: center;
	font-size: 12px;
}
`

const tmplPage string = `
<!doctype html>

	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>{{.CurrentDate}} | Feedloggr</title>
	<link href="./style.css" rel="stylesheet" type="text/css">

		<
		Latest
		>

	{{range .Feeds}}

{{.Title}}

		{{if .Error}}

Error while updating feed:
{{.Error}}

		{{else}}

		{{- range $i, $row := .Items}}
			{{- if $i}}
{{end}}

{{$row.Title}}

		{{- end}}

		{{end}}

	{{else}}

Sorry, no news for today!

	{{end}}

		Generated with Feedloggr

`
<commit_msg>Fixes longtime bug with weird link text not being clickable/hover<commit_after>package feedloggr

const tmplCSS string = `
body {
	margin: 30px 5%;
	line-height: 1.5;
	font-size: 13px;
	font-family: monospace;
	background-color: #FFF;
	color: #444;
}
a, a:visited {
	color: #444;
	text-decoration: none;
}
a:hover {
	color: #000;
	text-decoration: underline;
}

nav {
	text-align: center;
	margin-bottom: 20px;
}
nav > a:hover {
	background-color: #E6E6E6;
	border-color: #ADADAD;
}
section {
	background-color: #FFF;
	margin-bottom: 20px;
}
section > h1, nav > a {
	border: 1px solid #DDD;
	border-radius: 3px;
	padding: 10px;
	margin: 0;
	font-size: 16px;
	font-weight: bold;
	text-align: center;
}
section > h1 {
	background-color: #EEE;
}
section > ul, section > p {
	padding: 0;
	margin: 20px 0;
	list-style: none;
}
section > ul > li {
        margin-bottom: 5px;
}
section > ul > a:visited {
	color: #AAA;
}
section > ul > hr {
        padding: 0;
        border: 0;
        height: 1px;
        margin: 5px 0px;
        background-image: linear-gradient(to right, #ccc, #fff);
}
footer {
	text-align: center;
	font-size: 12px;
}
`

const tmplPage string = `
<!doctype html>

	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>{{.CurrentDate}} | Feedloggr</title>
	<link href="./style.css" rel="stylesheet" type="text/css">

		<
		Latest
		>

	{{range .Feeds}}

{{.Title}}

		{{if .Error}}

Error while updating feed:
{{.Error}}

		{{else}}

		{{- range $i, $row := .Items}}
			{{- if $i}}
{{end}}

{{$row.Title}}

		{{- end}}

		{{end}}

	{{else}}

Sorry, no news for today!

	{{end}}

		Generated with Feedloggr

`
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"cred-alert/archiveiterator"
	"cred-alert/mimetype"
	"cred-alert/scanners"
	"cred-alert/scanners/filescanner"
	"cred-alert/sniff"
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"
	"strings"

	"code.cloudfoundry.org/lager"

	"github.com/jessevdk/go-flags"
)

type Opts struct {
	Directory string `short:"d" long:"directory" description:"the directory to scan" value-name:"DIR"`
	File      string `short:"f" long:"file" description:"the file to scan" value-name:"FILE"`
}

func main() {
	var opts Opts

	_, err := flags.ParseArgs(&opts, os.Args)
	if err != nil {
		os.Exit(1)
	}

	logger := lager.NewLogger("cred-alert-cli")
	logger.RegisterSink(lager.NewWriterSink(os.Stderr, lager.DEBUG))

	sniffer := sniff.NewDefaultSniffer()

	if opts.Directory != "" {
		scanDirectory(logger, sniffer, opts.Directory)
		os.Exit(0)
	}

	var f *os.File
	if opts.File != "" {
		var err error
		f, err = os.Open(opts.File)
		if err != nil {
			log.Fatalf("Failed to open file: %s", err.Error())
		}
		defer f.Close()
		scanFile(logger, sniffer, f, f.Name())
		os.Exit(0)
	}

	scanFile(logger, sniffer, os.Stdin, "STDIN")
}

func scanFile(logger lager.Logger, sniffer sniff.Sniffer, r io.Reader, name string) {
	logger = logger.WithData(lager.Data{"filename": name})
	br := bufio.NewReader(r)
	mime, ok := mimetype.IsArchive(br)
	if ok {
		iterator := archiveiterator.NewIterator(logger, br, mime, name)

		for {
			entry, name := iterator.Next()
			if entry == nil {
				break
			}
			scanFile(logger, sniffer, entry, name)
			entry.Close()
		}

		iterator.Close()
	} else {
		if strings.Contains(mime, "text") {
			scanner := filescanner.New(br, name)
			sniffer.Sniff(logger, scanner, handleViolation)
		}
	}
}

func handleViolation(line scanners.Line) error {
	fmt.Printf("Line matches pattern! File: %s, Line Number: %d, Content: %s\n", line.Path, line.LineNumber, line.Content)

	return nil
}

func scanDirectory(logger lager.Logger, sniffer sniff.Sniffer, directoryPath string) {
	stat, err := os.Stat(directoryPath)
	if err != nil {
		log.Fatalf("Cannot read directory %s\n", directoryPath)
	}

	if !stat.IsDir() {
		log.Fatalf("%s is not a directory\n", directoryPath)
	}

	walkFunc := func(path string, info os.FileInfo, err error) error {
		if !info.IsDir() {
			fh, err := os.Open(path)
			if err != nil {
				return err
			}
			defer fh.Close()

			scanner := filescanner.New(fh, fh.Name())
			sniffer.Sniff(logger, scanner, handleViolation)
		}
		return nil
	}

	err = filepath.Walk(directoryPath, walkFunc)
	if err != nil {
		log.Fatalf("Error traversing directory: %v", err)
	}
}
<commit_msg>Retain context in archive scanning [#126615597]<commit_after>package main

import (
	"bufio"
	"cred-alert/archiveiterator"
	"cred-alert/mimetype"
	"cred-alert/scanners"
	"cred-alert/scanners/filescanner"
	"cred-alert/sniff"
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"
	"strings"

	"code.cloudfoundry.org/lager"

	"github.com/jessevdk/go-flags"
)

type Opts struct {
	Directory string `short:"d" long:"directory" description:"the directory to scan" value-name:"DIR"`
	File      string `short:"f" long:"file" description:"the file to scan" value-name:"FILE"`
}

func main() {
	var opts Opts

	_, err := flags.ParseArgs(&opts, os.Args)
	if err != nil {
		os.Exit(1)
	}

	logger := lager.NewLogger("cred-alert-cli")
	logger.RegisterSink(lager.NewWriterSink(os.Stderr, lager.DEBUG))

	sniffer := sniff.NewDefaultSniffer()

	if opts.Directory != "" {
		scanDirectory(logger, sniffer, opts.Directory)
		os.Exit(0)
	}

	var f *os.File
	if opts.File != "" {
		var err error
		f, err = os.Open(opts.File)
		if err != nil {
			log.Fatalf("Failed to open file: %s", err.Error())
		}
		defer f.Close()
		scanFile(logger, sniffer, f, f.Name(), []string{})
		os.Exit(0)
	}

	scanFile(logger, sniffer, os.Stdin, "STDIN", []string{})
}

func scanFile(logger lager.Logger, sniffer sniff.Sniffer, r io.Reader, name string, ancestors []string) {
	logger = logger.WithData(lager.Data{
		"filename":  name,
		"ancestors": ancestors,
	})

	br := bufio.NewReader(r)
	mime, ok := mimetype.IsArchive(br)
	ancestors = append(ancestors, fmt.Sprintf(`%s (%s)`, name, mime))

	if ok {
		iterator := archiveiterator.NewIterator(logger, br, mime, name)

		for {
			entry, name := iterator.Next()
			if entry == nil {
				break
			}
			scanFile(logger, sniffer, entry, name, ancestors)
			entry.Close()
		}

		iterator.Close()
	} else {
		if strings.Contains(mime, "text") {
			scanner := filescanner.New(br, name)
			sniffer.Sniff(logger, scanner, handleViolation)
		}
	}
}

func handleViolation(line scanners.Line) error {
	fmt.Printf("Line matches pattern! File: %s, Line Number: %d, Content: %s\n", line.Path, line.LineNumber, line.Content)

	return nil
}

func scanDirectory(logger lager.Logger, sniffer sniff.Sniffer, directoryPath string) {
	stat, err := os.Stat(directoryPath)
	if err != nil {
		log.Fatalf("Cannot read directory %s\n", directoryPath)
	}

	if !stat.IsDir() {
		log.Fatalf("%s is not a directory\n", directoryPath)
	}

	walkFunc := func(path string, info os.FileInfo, err error) error {
		if !info.IsDir() {
			fh, err := os.Open(path)
			if err != nil {
				return err
			}
			defer fh.Close()

			scanner := filescanner.New(fh, fh.Name())
			sniffer.Sniff(logger, scanner, handleViolation)
		}
		return nil
	}

	err = filepath.Walk(directoryPath, walkFunc)
	if err != nil {
		log.Fatalf("Error traversing directory: %v", err)
	}
}
<|endoftext|>


<commit_before>package artifice

import (
	"context"
	"time"

	"github.com/antihax/evedata/internal/redisqueue"
)

func init() {
	registerTrigger("npcCorporations", npcCorporationsTrigger, time.NewTicker(time.Second*172800))
	registerTrigger("alliance", allianceTrigger, time.NewTicker(time.Second*3600))
	registerTrigger("characterUpdate", characterUpdate, time.NewTicker(time.Second*120))
	registerTrigger("corporationUpdate", corporationUpdate, time.NewTicker(time.Second*120))
}

func npcCorporationsTrigger(s *Artifice) error {
	corporations, _, err := s.esi.ESI.CorporationApi.GetCorporationsNpccorps(context.Background(), nil)
	if err != nil {
		return err
	}

	work := []redisqueue.Work{}
	for _, corporation := range corporations {
		work = append(work, redisqueue.Work{Operation: "corporation", Parameter: corporation})
		work = append(work, redisqueue.Work{Operation: "loyaltyStore", Parameter: corporation})
	}

	return s.QueueWork(work, redisqueue.Priority_Lowest)
}

func allianceTrigger(s *Artifice) error {
	alliances, r, err := s.esi.ESI.AllianceApi.GetAlliances(context.Background(), nil)
	if err != nil {
		return err
	}

	work := []redisqueue.Work{}
	for _, alliance := range alliances {
		work = append(work, redisqueue.Work{Operation: "alliance", Parameter: alliance})
	}

	return s.QueueWork(work, redisqueue.Priority_Lowest)
}

func characterUpdate(s *Artifice) error {
	entities, err := s.db.Query(
		`SELECT characterID AS id FROM evedata.characters A
			WHERE cacheUntil < UTC_TIMESTAMP() AND dead = 0
			AND characterID > 90000000
            ORDER BY cacheUntil ASC LIMIT 100000`)
	if err != nil {
		return err
	}
	defer entities.Close()

	work := []redisqueue.Work{}

	// Loop the entities
	for entities.Next() {
		var id int32

		err = entities.Scan(&id)
		if err != nil {
			return err
		}

		work = append(work, redisqueue.Work{Operation: "character", Parameter: id})
	}

	return s.QueueWork(work, redisqueue.Priority_Lowest)
}

func corporationUpdate(s *Artifice) error {
	entities, err := s.db.Query(
		`SELECT corporationID AS id FROM evedata.corporations A
		 WHERE cacheUntil < UTC_TIMESTAMP() AND memberCount > 0 AND corporationId> 90000000
		 ORDER BY cacheUntil ASC LIMIT 100000`)
	if err != nil {
		return err
	}
	defer entities.Close()

	work := []redisqueue.Work{}

	// Loop the entities
	for entities.Next() {
		var id int32

		err = entities.Scan(&id)
		if err != nil {
			return err
		}

		work = append(work, redisqueue.Work{Operation: "corporation", Parameter: id})

	}

	return s.QueueWork(work, redisqueue.Priority_Lowest)
}
<commit_msg>Breaking Builds 101<commit_after>package artifice

import (
	"context"
	"time"

	"github.com/antihax/evedata/internal/redisqueue"
)

func init() {
	registerTrigger("npcCorporations", npcCorporationsTrigger, time.NewTicker(time.Second*172800))
	registerTrigger("alliance", allianceTrigger, time.NewTicker(time.Second*3600))
	registerTrigger("characterUpdate", characterUpdate, time.NewTicker(time.Second*120))
	registerTrigger("corporationUpdate", corporationUpdate, time.NewTicker(time.Second*120))
}

func npcCorporationsTrigger(s *Artifice) error {
	corporations, _, err := s.esi.ESI.CorporationApi.GetCorporationsNpccorps(context.Background(), nil)
	if err != nil {
		return err
	}

	work := []redisqueue.Work{}
	for _, corporation := range corporations {
		work = append(work, redisqueue.Work{Operation: "corporation", Parameter: corporation})
		work = append(work, redisqueue.Work{Operation: "loyaltyStore", Parameter: corporation})
	}

	return s.QueueWork(work, redisqueue.Priority_Lowest)
}

func allianceTrigger(s *Artifice) error {
	alliances, _, err := s.esi.ESI.AllianceApi.GetAlliances(context.Background(), nil)
	if err != nil {
		return err
	}

	work := []redisqueue.Work{}
	for _, alliance := range alliances {
		work = append(work, redisqueue.Work{Operation: "alliance", Parameter: alliance})
	}

	return s.QueueWork(work, redisqueue.Priority_Lowest)
}

func characterUpdate(s *Artifice) error {
	entities, err := s.db.Query(
		`SELECT characterID AS id FROM evedata.characters A
			WHERE cacheUntil < UTC_TIMESTAMP() AND dead = 0
			AND characterID > 90000000
            ORDER BY cacheUntil ASC LIMIT 100000`)
	if err != nil {
		return err
	}
	defer entities.Close()

	work := []redisqueue.Work{}

	// Loop the entities
	for entities.Next() {
		var id int32

		err = entities.Scan(&id)
		if err != nil {
			return err
		}

		work = append(work, redisqueue.Work{Operation: "character", Parameter: id})
	}

	return s.QueueWork(work, redisqueue.Priority_Lowest)
}

func corporationUpdate(s *Artifice) error {
	entities, err := s.db.Query(
		`SELECT corporationID AS id FROM evedata.corporations A
		 WHERE cacheUntil < UTC_TIMESTAMP() AND memberCount > 0 AND corporationId> 90000000
		 ORDER BY cacheUntil ASC LIMIT 100000`)
	if err != nil {
		return err
	}
	defer entities.Close()

	work := []redisqueue.Work{}

	// Loop the entities
	for entities.Next() {
		var id int32

		err = entities.Scan(&id)
		if err != nil {
			return err
		}

		work = append(work, redisqueue.Work{Operation: "corporation", Parameter: id})

	}

	return s.QueueWork(work, redisqueue.Priority_Lowest)
}
<|endoftext|>


<commit_before>// Copyright 2016 The Prometheus 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 remote

import (
	"sync"

	"github.com/prometheus/common/model"

	"github.com/prometheus/prometheus/config"
	"github.com/prometheus/prometheus/relabel"
)

// Storage collects multiple remote storage queues.
type ReloadableStorage struct {
	mtx            sync.RWMutex
	externalLabels model.LabelSet
	conf           config.RemoteWriteConfig

	queue *StorageQueueManager
}

// New returns a new remote Storage.
func NewConfigurable() *ReloadableStorage {
	return &ReloadableStorage{}
}

// ApplyConfig updates the state as the new config requires.
func (s *ReloadableStorage) ApplyConfig(conf *config.Config) error {
	s.mtx.Lock()
	defer s.mtx.Unlock()

	// TODO: we should only stop & recreate queues which have changes,
	// as this can be quite disruptive.
	var newQueue *StorageQueueManager

	if conf.RemoteWriteConfig.URL != nil {
		c, err := NewClient(conf.RemoteWriteConfig)
		if err != nil {
			return err
		}
		newQueue = NewStorageQueueManager(c, nil)
	}

	if s.queue != nil {
		s.queue.Stop()
	}
	s.queue = newQueue
	s.conf = conf.RemoteWriteConfig
	s.externalLabels = conf.GlobalConfig.ExternalLabels
	if s.queue != nil {
		s.queue.Start()
	}
	return nil
}

// Stop the background processing of the storage queues.
func (s *ReloadableStorage) Stop() {
	if s.queue != nil {
		s.queue.Stop()
	}
}

// Append implements storage.SampleAppender. Always returns nil.
func (s *ReloadableStorage) Append(smpl *model.Sample) error {
	s.mtx.RLock()
	defer s.mtx.RUnlock()

	var snew model.Sample
	snew = *smpl
	snew.Metric = smpl.Metric.Clone()

	for ln, lv := range s.externalLabels {
		if _, ok := smpl.Metric[ln]; !ok {
			snew.Metric[ln] = lv
		}
	}
	snew.Metric = model.Metric(
		relabel.Process(model.LabelSet(snew.Metric), s.conf.WriteRelabelConfigs...))

	if snew.Metric == nil {
		return nil
	}
	if s.queue != nil {
		s.queue.Append(&snew)
	}
	return nil
}

// NeedsThrottling implements storage.SampleAppender. It will always return
// false as a remote storage drops samples on the floor if backlogging instead
// of asking for throttling.
func (s *ReloadableStorage) NeedsThrottling() bool {
	return false
}
<commit_msg>Don't clone the metric if there's no remote writes.<commit_after>// Copyright 2016 The Prometheus 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 remote

import (
	"sync"

	"github.com/prometheus/common/model"

	"github.com/prometheus/prometheus/config"
	"github.com/prometheus/prometheus/relabel"
)

// Storage collects multiple remote storage queues.
type ReloadableStorage struct {
	mtx            sync.RWMutex
	externalLabels model.LabelSet
	conf           config.RemoteWriteConfig

	queue *StorageQueueManager
}

// New returns a new remote Storage.
func NewConfigurable() *ReloadableStorage {
	return &ReloadableStorage{}
}

// ApplyConfig updates the state as the new config requires.
func (s *ReloadableStorage) ApplyConfig(conf *config.Config) error {
	s.mtx.Lock()
	defer s.mtx.Unlock()

	// TODO: we should only stop & recreate queues which have changes,
	// as this can be quite disruptive.
	var newQueue *StorageQueueManager

	if conf.RemoteWriteConfig.URL != nil {
		c, err := NewClient(conf.RemoteWriteConfig)
		if err != nil {
			return err
		}
		newQueue = NewStorageQueueManager(c, nil)
	}

	if s.queue != nil {
		s.queue.Stop()
	}
	s.queue = newQueue
	s.conf = conf.RemoteWriteConfig
	s.externalLabels = conf.GlobalConfig.ExternalLabels
	if s.queue != nil {
		s.queue.Start()
	}
	return nil
}

// Stop the background processing of the storage queues.
func (s *ReloadableStorage) Stop() {
	if s.queue != nil {
		s.queue.Stop()
	}
}

// Append implements storage.SampleAppender. Always returns nil.
func (s *ReloadableStorage) Append(smpl *model.Sample) error {
	s.mtx.RLock()
	defer s.mtx.RUnlock()

	if s.queue == nil {
		return nil
	}

	var snew model.Sample
	snew = *smpl
	snew.Metric = smpl.Metric.Clone()

	for ln, lv := range s.externalLabels {
		if _, ok := smpl.Metric[ln]; !ok {
			snew.Metric[ln] = lv
		}
	}
	snew.Metric = model.Metric(
		relabel.Process(model.LabelSet(snew.Metric), s.conf.WriteRelabelConfigs...))

	if snew.Metric == nil {
		return nil
	}
	s.queue.Append(&snew)
	return nil
}

// NeedsThrottling implements storage.SampleAppender. It will always return
// false as a remote storage drops samples on the floor if backlogging instead
// of asking for throttling.
func (s *ReloadableStorage) NeedsThrottling() bool {
	return false
}
<|endoftext|>


<commit_before>package similarity_simple

import (
	"errors"
	"math"
)

type Vector []float64

func isZeroVector(v Vector) bool {
	vsize := len(v)
	for i := 0; i < vsize; i++ {
		if v[i] != 0.0 {
			return false
		}
	}
	return true
}

func dotProduct(v1 Vector, v2 Vector) (dp float64, err error) {
	dp = 0.0

	if len(v1) != len(v2) {
		return dp, errors.New("Length of two vectors don't match")
	}

	vsize := len(v1)
	for i := 0; i < vsize; i++ {
		dp += (v1[i] * v2[i])
	}

	return dp, nil
}

func normalize(v Vector) (nv float64) {
	nv = 0.0

	vsize := len(v)
	for i := 0; i < vsize; i++ {
		nv += (v[i] * v[i])
	}

	return math.Sqrt(nv)
}

func CosineSimilarity(v1 Vector, v2 Vector) (sim float64, err error) {
	sim = 0.0
	if len(v1) == 0 || len(v2) == 0 {
		return sim, errors.New("Length of vector is 0")
	} else if isZeroVector(v1) && isZeroVector(v2) {
		return sim, errors.New("Both are zero vector")
	}

	dp, err := dotProduct(v1, v2)
	if err != nil {
		return sim, err
	}

	sim = dp / (normalize(v1) * normalize(v2))

	return sim, nil
}
<commit_msg>Add pearson similarity<commit_after>package similarity_simple

import (
	"errors"
	"math"
)

type Vector []float64

func isZeroVector(v Vector) bool {
	vsize := len(v)
	for i := 0; i < vsize; i++ {
		if v[i] != 0.0 {
			return false
		}
	}
	return true
}

func dotProduct(v1 Vector, v2 Vector) (dp float64, err error) {
	dp = 0.0

	if len(v1) != len(v2) {
		return dp, errors.New("Length of two vectors don't match")
	}

	vsize := len(v1)
	for i := 0; i < vsize; i++ {
		dp += (v1[i] * v2[i])
	}

	return dp, nil
}

func normalize(v Vector) (nv float64) {
	nv = 0.0

	vsize := len(v)
	for i := 0; i < vsize; i++ {
		nv += (v[i] * v[i])
	}

	return math.Sqrt(nv)
}

func checkVector(x Vector, y Vector) (err error) {
	if len(x) == 0 || len(y) == 0 {
		return errors.New("Length of vector is 0")
	} else if isZeroVector(x) && isZeroVector(y) {
		return errors.New("Both are zero vector")
	} else {
		return nil
	}
}

func vSum(v Vector) float64 {
	sum := 0.0
	vsize := len(v)
	for i := 0; i < vsize; i++ {
		sum += v[i]
	}
	return sum
}

func vSumSq(v Vector) float64 {
	sumSq := 0.0
	vsize := len(v)
	for i := 0; i < vsize; i++ {
		sumSq += (v[i] * v[i])
	}
	return sumSq
}

func CosineSimilarity(v1 Vector, v2 Vector) (sim float64, err error) {
	sim = 0.0
	if err := checkVector(v1, v2); err != nil {
		return sim, err
	}

	dp, err := dotProduct(v1, v2)
	if err != nil {
		return sim, err
	}

	sim = dp / (normalize(v1) * normalize(v2))

	return sim, nil
}

func PearsonSimilarity(x Vector, y Vector) (sim float64, err error) {
	sim = 0.0
	if err := checkVector(x, y); err != nil {
		return sim, nil
	}

	dp, err := dotProduct(x, y)
	if err != nil {
		return sim, err
	}

	sumx := vSum(x)
	sumy := vSum(y)

	sumxSq := vSumSq(x)
	sumySq := vSumSq(y)

	n := float64(len(x))
	num := dp - (sumx * sumy / n)
	den := (sumxSq - math.Pow(sumx, 2)/n) *
		(sumySq - math.Pow(sumy, 2)/n)
	den = math.Sqrt(den)

	if den == 0.0 {
		return sim, errors.New("Pearson similarity could not calculated because of division by zero")
	} else {
		sim = num / den
	}

	return sim, nil
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"math/rand"
)

var (
	flagNbIter = flag.Int("n", 10000, "Number of iterations")
	flagSeed   = flag.Int("s", 0, "Seed for random numbers")
)

type Simulation struct {
	ay          *AvailabilityYear
	r2, r2x, r3 Result
}

func NewSimulation() *Simulation {
	return &Simulation{ay: NewAvailabilityYear()}
}

func (s *Simulation) RunOnce() {

	r := rand.New(rand.NewSource(int64(*flagSeed)))
	for i := 0; i < *flagNbIter; i++ {
		s.ay.Reset()
		s.ay.Build(r)
		s.ay.Simulate()
		s.ay.Evaluate()
		s.r2.Update(s.ay.r2)
		s.r2x.Update(s.ay.r2x)
		s.r3.Update(s.ay.r3)
	}
	fmt.Println(s.r2, s.r2x, s.r3)
}

func main() {

	flag.Parse()

	s := NewSimulation()
	s.RunOnce()
}
<commit_msg>Parallelized calculation<commit_after>package main

import (
	"flag"
	"fmt"
	"math/rand"
	"runtime"
)

var (
	flagNbIter   = flag.Int("n", 10, "Number of iterations")
	flagBatch    = flag.Int("b", 1000000, "Size of batch")
	flagSeed     = flag.Int("s", 0, "Seed for random numbers")
	flagParallel = flag.Int("p", runtime.NumCPU(), "Parallelism level")
)

type Simulation struct {
	id          int
	r           *rand.Rand
	ay          *AvailabilityYear
	r2, r2x, r3 Result
}

func NewSimulation(n int) *Simulation {
	return &Simulation{
		id: n,
		r:  rand.New(rand.NewSource(int64(n + *flagSeed))),
		ay: NewAvailabilityYear(),
	}
}

func (s *Simulation) Run(n int) {
	for i := 0; i < *flagBatch; i++ {
		s.ay.Reset()
		s.ay.Build(s.r)
		s.ay.Simulate()
		s.ay.Evaluate()
		s.r2.Update(s.ay.r2)
		s.r2x.Update(s.ay.r2x)
		s.r3.Update(s.ay.r3)
	}
}

func handleWorker(n int, input chan int, done chan bool) {
	simu := NewSimulation(n)
	for x := range input {
		simu.Run(x)
	}
	fmt.Println(n, simu.r2, simu.r2x, simu.r3)
	done <- true
}

func main() {

	flag.Parse()
	fmt.Printf("Starting %d iterations over %d threads with %d batch size\n", *flagNbIter, *flagParallel, *flagBatch)

	input := make(chan int, 16)
	done := make(chan bool)
	for i := 0; i < *flagParallel; i++ {
		go handleWorker(i, input, done)
	}
	for i := 0; i < *flagNbIter; i++ {
		input <- i
	}
	close(input)
	for i := 0; i < *flagParallel; i++ {
		_ = <-done
	}

	fmt.Println("Done.")
}
<|endoftext|>


<commit_before>package net

import (
	"io"
	"log"
	"net"
	"sync"

	"../redlot"
)

var info struct {
	sync.RWMutex
	ConnCounter uint64
	TotalCalls  uint64
	reply       Reply
}

func init() {
	// Register commands.
	// system info
	REG("INFO", STATUS_REPLY, Info)

	// KV type
	REG("GET", BULK_REPLY, redlot.Get)
	REG("SET", STATUS_REPLY, redlot.Set)
	REG("DEL", STATUS_REPLY, redlot.Del)
	REG("EXISTS", INT_REPLY, redlot.Exists)

}

func Serve(addr string, options *redlot.Options) {
	// Open LevelDB with options.
	redlot.Open(options)

	// Create sockets listener.
	l, err := net.Listen("tcp4", addr)
	if err != nil {
		log.Fatalf("Listen error: %v\n", err.Error())
	}
	defer l.Close()

	for {
		conn, err := l.Accept()
		if err != nil {
			log.Fatalf("Wait for a connection error: %s\n", err.Error())
		}

		// Count connecion
		info.Lock()
		info.ConnCounter++
		info.Unlock()

		go func(c net.Conn) {
			for {
				req, err := newRequset(c)
				if err == io.EOF {
					break
				}
				if err != nil {
					continue
				}

				info.Lock()
				info.TotalCalls++
				info.Unlock()

				reply := RUN(req.Cmd, req.Args)
				reply.WriteTo(c)
			}

			c.Close()
			info.Lock()
			info.ConnCounter--
			info.Unlock()

		}(conn)

	}
}
<commit_msg>Register SETX,SETEX,TTL commands.<commit_after>package net

import (
	"io"
	"log"
	"net"
	"sync"

	"../redlot"
)

var info struct {
	sync.RWMutex
	ConnCounter uint64
	TotalCalls  uint64
	reply       Reply
}

func init() {
	// Register commands.
	// system info
	REG("INFO", STATUS_REPLY, Info)

	// KV type
	REG("GET", BULK_REPLY, redlot.Get)
	REG("SET", STATUS_REPLY, redlot.Set)
	REG("DEL", STATUS_REPLY, redlot.Del)
	REG("EXISTS", INT_REPLY, redlot.Exists)
	REG("SETX", STATUS_REPLY, redlot.Setx)
	REG("SETEX", STATUS_REPLY, redlot.Setx) // Alias of SETX
	REG("TTL", INT_REPLY, redlot.Ttl)

}

func Serve(addr string, options *redlot.Options) {
	// Open LevelDB with options.
	redlot.Open(options)

	// Create sockets listener.
	l, err := net.Listen("tcp4", addr)
	if err != nil {
		log.Fatalf("Listen error: %v\n", err.Error())
	}
	defer l.Close()

	for {
		conn, err := l.Accept()
		if err != nil {
			log.Fatalf("Wait for a connection error: %s\n", err.Error())
		}

		// Count connecion
		info.Lock()
		info.ConnCounter++
		info.Unlock()

		go func(c net.Conn) {
			for {
				req, err := newRequset(c)
				if err == io.EOF {
					break
				}
				if err != nil {
					continue
				}

				info.Lock()
				info.TotalCalls++
				info.Unlock()

				reply := RUN(req.Cmd, req.Args)
				reply.WriteTo(c)
			}

			c.Close()
			info.Lock()
			info.ConnCounter--
			info.Unlock()

		}(conn)

	}
}
<|endoftext|>


<commit_before>// Copyright 2016 Marc-Antoine Ruel. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.

// Packages the static files in a .go file.
//go:generate go run ../package/main.go -out static_files_gen.go ../../../web

// dlibox drives the dlibox LED strip on a Raspberry Pi. It runs a web server
// for remote control.
package main

import (
	"io"
	"log"
	"os"
	"runtime"
	"strconv"
	"sync"

	"github.com/maruel/dlibox/go/donotuse/conn/spi"
	"github.com/maruel/dlibox/go/donotuse/devices"
	"github.com/maruel/dlibox/go/donotuse/devices/apa102"
	"github.com/maruel/dlibox/go/donotuse/host"
	"github.com/maruel/dlibox/go/modules"
	"github.com/maruel/dlibox/go/screen"
)

// APA102 contains light specific settings.
type APA102 struct {
	sync.Mutex
	// BusNumber is the SPI bus number to use, defaults to -1.
	BusNumber int
	// Speed of the transfer.
	SPIspeed int64
	// Number of lights controlled by this device. If lower than the actual
	// number of lights, the remaining lights will flash oddly.
	NumberLights int
}

func (a *APA102) ResetDefault() {
	a.Lock()
	defer a.Unlock()
	a.BusNumber = -1
	a.SPIspeed = 10000000
	a.NumberLights = 150
}

func (a *APA102) Validate() error {
	a.Lock()
	defer a.Unlock()
	return nil
}

// initLEDs initializes the LED strip.
func initLEDs(b modules.Bus, fake bool, config *APA102) (*leds, error) {
	var l *leds
	var fakeBytes []byte
	num := config.NumberLights
	if fake {
		// Output (terminal with ANSI codes or APA102).
		// Hardcode to 100 characters when using a terminal output.
		// TODO(maruel): Query the terminal and use its width.
		num = 100
		fakeBytes = []byte("1")
		l = &leds{Display: screen.New(num), b: b, fps: 30}
	} else {
		fps := 60
		if host.MaxSpeed() < 900000 || runtime.NumCPU() < 4 {
			// Use 30Hz on slower devices because it is too slow.
			fps = 30
		}
		s, err := spi.New(config.BusNumber, 0)
		if err != nil {
			return nil, err
		}
		if err = s.Speed(config.SPIspeed); err != nil {
			return nil, err
		}
		a, err := apa102.New(s, config.NumberLights, 255, 6500)
		if err != nil {
			return nil, err
		}
		l = &leds{Display: a, b: b, s: s, fps: fps}
	}
	c, err := b.Subscribe("leds/#", modules.ExactlyOnce)
	if err != nil {
		l.Close()
		return nil, err
	}
	if err := b.Publish(modules.Message{"leds/fake", fakeBytes}, modules.MinOnce, true); err != nil {
		log.Printf("leds: publish failed: %v", err)
	}
	if err := b.Publish(modules.Message{"leds/fps", []byte(strconv.Itoa(l.fps))}, modules.MinOnce, true); err != nil {
		log.Printf("leds: publish failed: %v", err)
	}
	if err := b.Publish(modules.Message{"leds/num", []byte(strconv.Itoa(num))}, modules.MinOnce, true); err != nil {
		log.Printf("leds: publish failed: %v", err)
	}
	if err := b.Publish(modules.Message{"leds/temperature", []byte("255")}, modules.MinOnce, true); err != nil {
		log.Printf("leds: publish failed: %v", err)
	}
	if err := b.Publish(modules.Message{"leds/intensity", []byte("6500")}, modules.MinOnce, true); err != nil {
		log.Printf("leds: publish failed: %v", err)
	}
	go func() {
		for msg := range c {
			l.onMsg(msg)
		}
	}()
	return l, nil
}

type leds struct {
	devices.Display
	s   io.Closer
	fps int
	b   modules.Bus
}

func (l *leds) Close() error {
	err := l.b.Unsubscribe("leds/#")
	if err != nil {
		log.Printf("leds: failed to unsubscribe: leds/#: %v", err)
	}
	if l.s != nil {
		if err1 := l.s.Close(); err1 != nil {
			err = err1
		}
	} else {
		if _, err1 := os.Stdout.Write([]byte("\033[0m\n")); err1 != nil {
			err = err1
		}
	}
	return err
}

func (l *leds) onMsg(msg modules.Message) {
	switch msg.Topic {
	case "leds/fake":
	case "leds/fps":
	case "leds/intensity":
		v, err := strconv.Atoi(string(msg.Payload))
		if err != nil {
			log.Printf("leds: %s: %v", msg, err)
			return
		}
		a, ok := l.Display.(*apa102.Dev)
		if !ok {
			log.Printf("leds: can't set intensity with fake LED")
			return
		}
		if v < 0 {
			v = 0
		} else if v > 255 {
			v = 255
		}
		a.Intensity = uint8(v)
	case "leds/num":
	case "leds/temperature":
		v, err := strconv.Atoi(string(msg.Payload))
		if err != nil {
			log.Printf("leds: %s: %v", msg, err)
			return
		}
		a, ok := l.Display.(*apa102.Dev)
		if !ok {
			log.Printf("leds: can't set temperature with fake LED")
			return
		}
		if v < 1000 {
			v = 1000
		} else if v > 35000 {
			v = 35000
		}
		a.Temperature = uint16(v)
	default:
		log.Printf("leds: unknown msg: %# v", msg)
	}
}
<commit_msg>Fix LED publish.<commit_after>// Copyright 2016 Marc-Antoine Ruel. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.

// Packages the static files in a .go file.
//go:generate go run ../package/main.go -out static_files_gen.go ../../../web

// dlibox drives the dlibox LED strip on a Raspberry Pi. It runs a web server
// for remote control.
package main

import (
	"io"
	"log"
	"os"
	"runtime"
	"strconv"
	"sync"

	"github.com/maruel/dlibox/go/donotuse/conn/spi"
	"github.com/maruel/dlibox/go/donotuse/devices"
	"github.com/maruel/dlibox/go/donotuse/devices/apa102"
	"github.com/maruel/dlibox/go/donotuse/host"
	"github.com/maruel/dlibox/go/modules"
	"github.com/maruel/dlibox/go/screen"
)

// APA102 contains light specific settings.
type APA102 struct {
	sync.Mutex
	// BusNumber is the SPI bus number to use, defaults to -1.
	BusNumber int
	// Speed of the transfer.
	SPIspeed int64
	// Number of lights controlled by this device. If lower than the actual
	// number of lights, the remaining lights will flash oddly.
	NumberLights int
}

func (a *APA102) ResetDefault() {
	a.Lock()
	defer a.Unlock()
	a.BusNumber = -1
	a.SPIspeed = 10000000
	a.NumberLights = 150
}

func (a *APA102) Validate() error {
	a.Lock()
	defer a.Unlock()
	return nil
}

// initLEDs initializes the LED strip.
func initLEDs(b modules.Bus, fake bool, config *APA102) (*leds, error) {
	var l *leds
	var fakeBytes []byte
	num := config.NumberLights
	if fake {
		// Output (terminal with ANSI codes or APA102).
		// Hardcode to 100 characters when using a terminal output.
		// TODO(maruel): Query the terminal and use its width.
		num = 100
		fakeBytes = []byte("1")
		l = &leds{Display: screen.New(num), b: b, fps: 30}
	} else {
		fps := 60
		if host.MaxSpeed() < 900000 || runtime.NumCPU() < 4 {
			// Use 30Hz on slower devices because it is too slow.
			fps = 30
		}
		s, err := spi.New(config.BusNumber, 0)
		if err != nil {
			return nil, err
		}
		if err = s.Speed(config.SPIspeed); err != nil {
			return nil, err
		}
		a, err := apa102.New(s, config.NumberLights, 255, 6500)
		if err != nil {
			return nil, err
		}
		l = &leds{Display: a, b: b, s: s, fps: fps}
	}
	c, err := b.Subscribe("leds/#", modules.ExactlyOnce)
	if err != nil {
		l.Close()
		return nil, err
	}
	if err := b.Publish(modules.Message{"leds/fake", fakeBytes}, modules.MinOnce, true); err != nil {
		log.Printf("leds: publish failed: %v", err)
	}
	if err := b.Publish(modules.Message{"leds/fps", []byte(strconv.Itoa(l.fps))}, modules.MinOnce, true); err != nil {
		log.Printf("leds: publish failed: %v", err)
	}
	if err := b.Publish(modules.Message{"leds/num", []byte(strconv.Itoa(num))}, modules.MinOnce, true); err != nil {
		log.Printf("leds: publish failed: %v", err)
	}
	if err := b.Publish(modules.Message{"leds/intensity", []byte("255")}, modules.MinOnce, true); err != nil {
		log.Printf("leds: publish failed: %v", err)
	}
	if err := b.Publish(modules.Message{"leds/temperature", []byte("6500")}, modules.MinOnce, true); err != nil {
		log.Printf("leds: publish failed: %v", err)
	}
	go func() {
		for msg := range c {
			l.onMsg(msg)
		}
	}()
	return l, nil
}

type leds struct {
	devices.Display
	s   io.Closer
	fps int
	b   modules.Bus
}

func (l *leds) Close() error {
	err := l.b.Unsubscribe("leds/#")
	if err != nil {
		log.Printf("leds: failed to unsubscribe: leds/#: %v", err)
	}
	if l.s != nil {
		if err1 := l.s.Close(); err1 != nil {
			err = err1
		}
	} else {
		if _, err1 := os.Stdout.Write([]byte("\033[0m\n")); err1 != nil {
			err = err1
		}
	}
	return err
}

func (l *leds) onMsg(msg modules.Message) {
	switch msg.Topic {
	case "leds/fake":
	case "leds/fps":
	case "leds/intensity":
		v, err := strconv.Atoi(string(msg.Payload))
		if err != nil {
			log.Printf("leds: %s: %v", msg, err)
			return
		}
		a, ok := l.Display.(*apa102.Dev)
		if !ok {
			log.Printf("leds: can't set intensity with fake LED")
			return
		}
		if v < 0 {
			v = 0
		} else if v > 255 {
			v = 255
		}
		a.Intensity = uint8(v)
	case "leds/num":
	case "leds/temperature":
		v, err := strconv.Atoi(string(msg.Payload))
		if err != nil {
			log.Printf("leds: %s: %v", msg, err)
			return
		}
		a, ok := l.Display.(*apa102.Dev)
		if !ok {
			log.Printf("leds: can't set temperature with fake LED")
			return
		}
		if v < 1000 {
			v = 1000
		} else if v > 35000 {
			v = 35000
		}
		a.Temperature = uint16(v)
	default:
		log.Printf("leds: unknown msg: %# v", msg)
	}
}
<|endoftext|>


<commit_before>package logger

import (
	"fmt"
	"os"
	"path"
	"strings"
	"sync"
	"syscall"

	keybase1 "github.com/keybase/client/protocol/go"
	logging "github.com/op/go-logging"
	"golang.org/x/net/context"
)

const (
	fancyFormat   = "%{color}%{time:15:04:05.000000} ▶ [%{level:.4s} %{module} %{shortfile}] %{id:03x}%{color:reset} %{message}"
	plainFormat   = "[%{level:.4s}] %{id:03x} %{message}"
	fileFormat    = "%{time:15:04:05.000000} ▶ [%{level:.4s} %{module} %{shortfile}] %{id:03x} %{message}"
	defaultFormat = "%{color}%{message}%{color:reset}"
)

const permDir os.FileMode = 0700

var initLoggingBackendOnce sync.Once
var logRotateMutex sync.Mutex

// CtxStandardLoggerKey is a type defining context keys used by the
// Standard logger.
type CtxStandardLoggerKey int

const (
	// CtxLogTags defines a context key that can hold a slice of context
	// keys, the value of which should be logged by a Standard logger if
	// one of those keys is seen in a context during a log call.
	CtxLogTagsKey CtxStandardLoggerKey = iota
)

type CtxLogTags map[interface{}]string

// NewContext returns a new Context that carries adds the given log
// tag mappings (context key -> display string).
func NewContextWithLogTags(
	ctx context.Context, logTagsToAdd CtxLogTags) context.Context {
	currTags, ok := LogTagsFromContext(ctx)
	if !ok {
		currTags = make(CtxLogTags)
	}
	for key, tag := range logTagsToAdd {
		currTags[key] = tag
	}
	return context.WithValue(ctx, CtxLogTagsKey, currTags)
}

// LogTagsFromContext returns the log tags being passed along with the
// given context.
func LogTagsFromContext(ctx context.Context) (CtxLogTags, bool) {
	logTags, ok := ctx.Value(CtxLogTagsKey).(CtxLogTags)
	return logTags, ok
}

type ExternalLogger interface {
	Log(level keybase1.LogLevel, format string, args []interface{})
}

type Standard struct {
	internal       *logging.Logger
	filename       string
	configureMutex sync.Mutex
	module         string

	externalLoggers      map[uint64]ExternalLogger
	externalLoggersCount uint64
	externalLogLevel     keybase1.LogLevel
	externalLoggersMutex sync.RWMutex
}

// New creates a new Standard logger for module.
func New(module string) *Standard {
	return NewWithCallDepth(module, 0)
}

// NewWithCallDepth creates a new Standard logger for module, and when
// printing file names and line numbers, it goes extraCallDepth up the
// stack from where logger was invoked.
func NewWithCallDepth(module string, extraCallDepth int) *Standard {
	log := logging.MustGetLogger(module)
	log.ExtraCalldepth = 1 + extraCallDepth
	ret := &Standard{
		internal:             log,
		module:               module,
		externalLoggers:      make(map[uint64]ExternalLogger),
		externalLoggersCount: 0,
		externalLogLevel:     keybase1.LogLevel_INFO,
	}
	ret.initLogging()
	return ret
}

func (log *Standard) initLogging() {
	// Logging is always done to stderr. It's the responsibility of the
	// launcher (like launchd on OSX, or the autoforking code) to set up stderr
	// to point to the appropriate log file.
	initLoggingBackendOnce.Do(func() {
		logBackend := logging.NewLogBackend(os.Stderr, "", 0)
		logging.SetBackend(logBackend)
	})
	logging.SetLevel(logging.INFO, log.module)
}

func (log *Standard) prepareString(
	ctx context.Context, fmts string) string {
	if ctx == nil {
		return fmts
	}
	logTags, ok := LogTagsFromContext(ctx)
	if !ok || len(logTags) == 0 {
		return fmts
	}
	var tags []string
	for key, tag := range logTags {
		if v := ctx.Value(key); v != nil {
			tags = append(tags, fmt.Sprintf("%s=%s", tag, v))
		}
	}
	return fmts + " [tags:" + strings.Join(tags, ",") + "]"
}

func (log *Standard) Debug(fmt string, arg ...interface{}) {
	log.internal.Debug(fmt, arg...)
	log.logToExternalLoggers(keybase1.LogLevel_DEBUG, fmt, arg)
}

func (log *Standard) CDebugf(ctx context.Context, fmt string,
	arg ...interface{}) {
	if log.internal.IsEnabledFor(logging.DEBUG) {
		log.Debug(log.prepareString(ctx, fmt), arg...)
	}
}

func (log *Standard) Info(fmt string, arg ...interface{}) {
	log.internal.Info(fmt, arg...)
	log.logToExternalLoggers(keybase1.LogLevel_INFO, fmt, arg)
}

func (log *Standard) CInfof(ctx context.Context, fmt string,
	arg ...interface{}) {
	if log.internal.IsEnabledFor(logging.INFO) {
		log.Info(log.prepareString(ctx, fmt), arg...)
	}
}

func (log *Standard) Notice(fmt string, arg ...interface{}) {
	log.internal.Notice(fmt, arg...)
	log.logToExternalLoggers(keybase1.LogLevel_NOTICE, fmt, arg)
}

func (log *Standard) CNoticef(ctx context.Context, fmt string,
	arg ...interface{}) {
	if log.internal.IsEnabledFor(logging.NOTICE) {
		log.Notice(log.prepareString(ctx, fmt), arg...)
	}
}

func (log *Standard) Warning(fmt string, arg ...interface{}) {
	log.internal.Warning(fmt, arg...)
	log.logToExternalLoggers(keybase1.LogLevel_WARN, fmt, arg)
}

func (log *Standard) CWarningf(ctx context.Context, fmt string,
	arg ...interface{}) {
	if log.internal.IsEnabledFor(logging.WARNING) {
		log.Warning(log.prepareString(ctx, fmt), arg...)
	}
}

func (log *Standard) Error(fmt string, arg ...interface{}) {
	log.internal.Error(fmt, arg...)
	log.logToExternalLoggers(keybase1.LogLevel_ERROR, fmt, arg)
}

func (log *Standard) Errorf(fmt string, arg ...interface{}) {
	log.Error(fmt, arg...)
}

func (log *Standard) CErrorf(ctx context.Context, fmt string,
	arg ...interface{}) {
	if log.internal.IsEnabledFor(logging.ERROR) {
		log.Error(log.prepareString(ctx, fmt), arg...)
	}
}

func (log *Standard) Critical(fmt string, arg ...interface{}) {
	log.internal.Critical(fmt, arg...)
	log.logToExternalLoggers(keybase1.LogLevel_CRITICAL, fmt, arg)
}

func (log *Standard) CCriticalf(ctx context.Context, fmt string,
	arg ...interface{}) {
	if log.internal.IsEnabledFor(logging.CRITICAL) {
		log.Critical(log.prepareString(ctx, fmt), arg...)
	}
}

func (log *Standard) Fatalf(fmt string, arg ...interface{}) {
	log.internal.Fatalf(fmt, arg...)
	log.logToExternalLoggers(keybase1.LogLevel_FATAL, fmt, arg)
}

func (log *Standard) CFatalf(ctx context.Context, fmt string,
	arg ...interface{}) {
	log.Fatalf(log.prepareString(ctx, fmt), arg...)
}

func (log *Standard) Profile(fmts string, arg ...interface{}) {
	log.Debug(fmts, arg...)
}

func (log *Standard) Configure(style string, debug bool, filename string) {
	log.configureMutex.Lock()
	defer log.configureMutex.Unlock()

	log.filename = filename

	var logfmt string
	if debug {
		logfmt = fancyFormat
	} else {
		logfmt = defaultFormat
	}

	// Override the format above if an explicit style was specified.
	switch style {
	case "default":
		logfmt = defaultFormat // Default
	case "plain":
		logfmt = plainFormat // Plain
	case "file":
		logfmt = fileFormat // Good for logging to files
	case "fancy":
		logfmt = fancyFormat // Fancy, good for terminals with color
	}

	if debug {
		logging.SetLevel(logging.DEBUG, log.module)
	}

	logging.SetFormatter(logging.MustStringFormatter(logfmt))
}

func (log *Standard) RotateLogFile() error {
	logRotateMutex.Lock()
	defer logRotateMutex.Unlock()
	log.internal.Info("Rotating log file; closing down old file")
	_, file, err := OpenLogFile(log.filename)
	if err != nil {
		return err
	}
	err = PickFirstError(
		syscall.Close(1),
		syscall.Close(2),
		syscall.Dup2(int(file.Fd()), 1),
		syscall.Dup2(int(file.Fd()), 2),
		file.Close(),
	)
	if err != nil {
		log.internal.Warning("Couldn't rotate file: %v", err)
	}
	log.internal.Info("Rotated log file; opening up new file")
	return nil
}

func OpenLogFile(filename string) (name string, file *os.File, err error) {
	name = filename
	if err = MakeParentDirs(name); err != nil {
		return
	}
	file, err = os.OpenFile(name, (os.O_APPEND | os.O_WRONLY | os.O_CREATE), 0600)
	if err != nil {
		return
	}
	return
}

func FileExists(path string) (bool, error) {
	_, err := os.Stat(path)
	if err == nil {
		return true, nil
	}
	if os.IsNotExist(err) {
		return false, nil
	}
	return false, err
}

func MakeParentDirs(filename string) error {
	dir, _ := path.Split(filename)
	exists, err := FileExists(dir)
	if err != nil {
		return err
	}

	if !exists {
		err = os.MkdirAll(dir, permDir)
		if err != nil {
			return err
		}
	}
	return nil
}

func PickFirstError(errors ...error) error {
	for _, e := range errors {
		if e != nil {
			return e
		}
	}
	return nil
}

func (log *Standard) AddExternalLogger(externalLogger ExternalLogger) uint64 {
	log.externalLoggersMutex.Lock()
	defer log.externalLoggersMutex.Unlock()

	handle := log.externalLoggersCount
	log.externalLoggersCount++
	log.externalLoggers[handle] = externalLogger
	return handle
}

func (log *Standard) RemoveExternalLogger(handle uint64) {
	log.externalLoggersMutex.Lock()
	defer log.externalLoggersMutex.Unlock()

	delete(log.externalLoggers, handle)
}

func (log *Standard) logToExternalLoggers(level keybase1.LogLevel, format string, args ...interface{}) {
	log.externalLoggersMutex.RLock()
	defer log.externalLoggersMutex.RUnlock()

	// Short circuit logs that are more verbose than the current external log
	// level.
	if level < log.externalLogLevel {
		return
	}

	for _, externalLogger := range log.externalLoggers {
		go externalLogger.Log(level, format, args)
	}
}

func (log *Standard) SetLogLevel(level keybase1.LogLevel) {
	log.externalLoggersMutex.Lock()
	defer log.externalLoggersMutex.Unlock()

	log.externalLogLevel = level
}
<commit_msg>accidentally specified a vararg when I meant a list<commit_after>package logger

import (
	"fmt"
	"os"
	"path"
	"strings"
	"sync"
	"syscall"

	keybase1 "github.com/keybase/client/protocol/go"
	logging "github.com/op/go-logging"
	"golang.org/x/net/context"
)

const (
	fancyFormat   = "%{color}%{time:15:04:05.000000} ▶ [%{level:.4s} %{module} %{shortfile}] %{id:03x}%{color:reset} %{message}"
	plainFormat   = "[%{level:.4s}] %{id:03x} %{message}"
	fileFormat    = "%{time:15:04:05.000000} ▶ [%{level:.4s} %{module} %{shortfile}] %{id:03x} %{message}"
	defaultFormat = "%{color}%{message}%{color:reset}"
)

const permDir os.FileMode = 0700

var initLoggingBackendOnce sync.Once
var logRotateMutex sync.Mutex

// CtxStandardLoggerKey is a type defining context keys used by the
// Standard logger.
type CtxStandardLoggerKey int

const (
	// CtxLogTags defines a context key that can hold a slice of context
	// keys, the value of which should be logged by a Standard logger if
	// one of those keys is seen in a context during a log call.
	CtxLogTagsKey CtxStandardLoggerKey = iota
)

type CtxLogTags map[interface{}]string

// NewContext returns a new Context that carries adds the given log
// tag mappings (context key -> display string).
func NewContextWithLogTags(
	ctx context.Context, logTagsToAdd CtxLogTags) context.Context {
	currTags, ok := LogTagsFromContext(ctx)
	if !ok {
		currTags = make(CtxLogTags)
	}
	for key, tag := range logTagsToAdd {
		currTags[key] = tag
	}
	return context.WithValue(ctx, CtxLogTagsKey, currTags)
}

// LogTagsFromContext returns the log tags being passed along with the
// given context.
func LogTagsFromContext(ctx context.Context) (CtxLogTags, bool) {
	logTags, ok := ctx.Value(CtxLogTagsKey).(CtxLogTags)
	return logTags, ok
}

type ExternalLogger interface {
	Log(level keybase1.LogLevel, format string, args []interface{})
}

type Standard struct {
	internal       *logging.Logger
	filename       string
	configureMutex sync.Mutex
	module         string

	externalLoggers      map[uint64]ExternalLogger
	externalLoggersCount uint64
	externalLogLevel     keybase1.LogLevel
	externalLoggersMutex sync.RWMutex
}

// New creates a new Standard logger for module.
func New(module string) *Standard {
	return NewWithCallDepth(module, 0)
}

// NewWithCallDepth creates a new Standard logger for module, and when
// printing file names and line numbers, it goes extraCallDepth up the
// stack from where logger was invoked.
func NewWithCallDepth(module string, extraCallDepth int) *Standard {
	log := logging.MustGetLogger(module)
	log.ExtraCalldepth = 1 + extraCallDepth
	ret := &Standard{
		internal:             log,
		module:               module,
		externalLoggers:      make(map[uint64]ExternalLogger),
		externalLoggersCount: 0,
		externalLogLevel:     keybase1.LogLevel_INFO,
	}
	ret.initLogging()
	return ret
}

func (log *Standard) initLogging() {
	// Logging is always done to stderr. It's the responsibility of the
	// launcher (like launchd on OSX, or the autoforking code) to set up stderr
	// to point to the appropriate log file.
	initLoggingBackendOnce.Do(func() {
		logBackend := logging.NewLogBackend(os.Stderr, "", 0)
		logging.SetBackend(logBackend)
	})
	logging.SetLevel(logging.INFO, log.module)
}

func (log *Standard) prepareString(
	ctx context.Context, fmts string) string {
	if ctx == nil {
		return fmts
	}
	logTags, ok := LogTagsFromContext(ctx)
	if !ok || len(logTags) == 0 {
		return fmts
	}
	var tags []string
	for key, tag := range logTags {
		if v := ctx.Value(key); v != nil {
			tags = append(tags, fmt.Sprintf("%s=%s", tag, v))
		}
	}
	return fmts + " [tags:" + strings.Join(tags, ",") + "]"
}

func (log *Standard) Debug(fmt string, arg ...interface{}) {
	log.internal.Debug(fmt, arg...)
	log.logToExternalLoggers(keybase1.LogLevel_DEBUG, fmt, arg)
}

func (log *Standard) CDebugf(ctx context.Context, fmt string,
	arg ...interface{}) {
	if log.internal.IsEnabledFor(logging.DEBUG) {
		log.Debug(log.prepareString(ctx, fmt), arg...)
	}
}

func (log *Standard) Info(fmt string, arg ...interface{}) {
	log.internal.Info(fmt, arg...)
	log.logToExternalLoggers(keybase1.LogLevel_INFO, fmt, arg)
}

func (log *Standard) CInfof(ctx context.Context, fmt string,
	arg ...interface{}) {
	if log.internal.IsEnabledFor(logging.INFO) {
		log.Info(log.prepareString(ctx, fmt), arg...)
	}
}

func (log *Standard) Notice(fmt string, arg ...interface{}) {
	log.internal.Notice(fmt, arg...)
	log.logToExternalLoggers(keybase1.LogLevel_NOTICE, fmt, arg)
}

func (log *Standard) CNoticef(ctx context.Context, fmt string,
	arg ...interface{}) {
	if log.internal.IsEnabledFor(logging.NOTICE) {
		log.Notice(log.prepareString(ctx, fmt), arg...)
	}
}

func (log *Standard) Warning(fmt string, arg ...interface{}) {
	log.internal.Warning(fmt, arg...)
	log.logToExternalLoggers(keybase1.LogLevel_WARN, fmt, arg)
}

func (log *Standard) CWarningf(ctx context.Context, fmt string,
	arg ...interface{}) {
	if log.internal.IsEnabledFor(logging.WARNING) {
		log.Warning(log.prepareString(ctx, fmt), arg...)
	}
}

func (log *Standard) Error(fmt string, arg ...interface{}) {
	log.internal.Error(fmt, arg...)
	log.logToExternalLoggers(keybase1.LogLevel_ERROR, fmt, arg)
}

func (log *Standard) Errorf(fmt string, arg ...interface{}) {
	log.Error(fmt, arg...)
}

func (log *Standard) CErrorf(ctx context.Context, fmt string,
	arg ...interface{}) {
	if log.internal.IsEnabledFor(logging.ERROR) {
		log.Error(log.prepareString(ctx, fmt), arg...)
	}
}

func (log *Standard) Critical(fmt string, arg ...interface{}) {
	log.internal.Critical(fmt, arg...)
	log.logToExternalLoggers(keybase1.LogLevel_CRITICAL, fmt, arg)
}

func (log *Standard) CCriticalf(ctx context.Context, fmt string,
	arg ...interface{}) {
	if log.internal.IsEnabledFor(logging.CRITICAL) {
		log.Critical(log.prepareString(ctx, fmt), arg...)
	}
}

func (log *Standard) Fatalf(fmt string, arg ...interface{}) {
	log.internal.Fatalf(fmt, arg...)
	log.logToExternalLoggers(keybase1.LogLevel_FATAL, fmt, arg)
}

func (log *Standard) CFatalf(ctx context.Context, fmt string,
	arg ...interface{}) {
	log.Fatalf(log.prepareString(ctx, fmt), arg...)
}

func (log *Standard) Profile(fmts string, arg ...interface{}) {
	log.Debug(fmts, arg...)
}

func (log *Standard) Configure(style string, debug bool, filename string) {
	log.configureMutex.Lock()
	defer log.configureMutex.Unlock()

	log.filename = filename

	var logfmt string
	if debug {
		logfmt = fancyFormat
	} else {
		logfmt = defaultFormat
	}

	// Override the format above if an explicit style was specified.
	switch style {
	case "default":
		logfmt = defaultFormat // Default
	case "plain":
		logfmt = plainFormat // Plain
	case "file":
		logfmt = fileFormat // Good for logging to files
	case "fancy":
		logfmt = fancyFormat // Fancy, good for terminals with color
	}

	if debug {
		logging.SetLevel(logging.DEBUG, log.module)
	}

	logging.SetFormatter(logging.MustStringFormatter(logfmt))
}

func (log *Standard) RotateLogFile() error {
	logRotateMutex.Lock()
	defer logRotateMutex.Unlock()
	log.internal.Info("Rotating log file; closing down old file")
	_, file, err := OpenLogFile(log.filename)
	if err != nil {
		return err
	}
	err = PickFirstError(
		syscall.Close(1),
		syscall.Close(2),
		syscall.Dup2(int(file.Fd()), 1),
		syscall.Dup2(int(file.Fd()), 2),
		file.Close(),
	)
	if err != nil {
		log.internal.Warning("Couldn't rotate file: %v", err)
	}
	log.internal.Info("Rotated log file; opening up new file")
	return nil
}

func OpenLogFile(filename string) (name string, file *os.File, err error) {
	name = filename
	if err = MakeParentDirs(name); err != nil {
		return
	}
	file, err = os.OpenFile(name, (os.O_APPEND | os.O_WRONLY | os.O_CREATE), 0600)
	if err != nil {
		return
	}
	return
}

func FileExists(path string) (bool, error) {
	_, err := os.Stat(path)
	if err == nil {
		return true, nil
	}
	if os.IsNotExist(err) {
		return false, nil
	}
	return false, err
}

func MakeParentDirs(filename string) error {
	dir, _ := path.Split(filename)
	exists, err := FileExists(dir)
	if err != nil {
		return err
	}

	if !exists {
		err = os.MkdirAll(dir, permDir)
		if err != nil {
			return err
		}
	}
	return nil
}

func PickFirstError(errors ...error) error {
	for _, e := range errors {
		if e != nil {
			return e
		}
	}
	return nil
}

func (log *Standard) AddExternalLogger(externalLogger ExternalLogger) uint64 {
	log.externalLoggersMutex.Lock()
	defer log.externalLoggersMutex.Unlock()

	handle := log.externalLoggersCount
	log.externalLoggersCount++
	log.externalLoggers[handle] = externalLogger
	return handle
}

func (log *Standard) RemoveExternalLogger(handle uint64) {
	log.externalLoggersMutex.Lock()
	defer log.externalLoggersMutex.Unlock()

	delete(log.externalLoggers, handle)
}

func (log *Standard) logToExternalLoggers(level keybase1.LogLevel, format string, args []interface{}) {
	log.externalLoggersMutex.RLock()
	defer log.externalLoggersMutex.RUnlock()

	// Short circuit logs that are more verbose than the current external log
	// level.
	if level < log.externalLogLevel {
		return
	}

	for _, externalLogger := range log.externalLoggers {
		go externalLogger.Log(level, format, args)
	}
}

func (log *Standard) SetLogLevel(level keybase1.LogLevel) {
	log.externalLoggersMutex.Lock()
	defer log.externalLoggersMutex.Unlock()

	log.externalLogLevel = level
}
<|endoftext|>