<commit_before>package display

import (
	"fmt"
	"os"
	"strings"
)

func MOTD() {
	os.Stderr.WriteString(fmt.Sprintf(`

                                   **
                                ********
                             ***************
                          *********************
                            *****************
                          ::    *********    ::
                             ::    ***    ::
                           ++   :::   :::   ++
                              ++   :::   ++
                                 ++   ++
                                    +
                    _  _ ____ _  _ ____ ___  ____ _  _
                    |\ | |__| |\ | |  | |__) |  |  \/
                    | \| |  | | \| |__| |__) |__| _/\_
`))
}

func InfoProductionHost() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
+ WARNING:
+ You are on a live, production Linux server.
+ This host is primarily responsible for running docker containers.
+ Changes made to this machine have real consequences.
+ Proceed at your own risk.
--------------------------------------------------------------------------------

`))
}

func InfoProductionContainer() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
+ WARNING:
+ You are in a live, production Linux container.
+ Changes made to this machine have real consequences.
+ Proceed at your own risk.
--------------------------------------------------------------------------------

`))
}

func InfoLocalContainer() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
+ You are inside a Linux container on your local machine.
+ Anything here can be undone, so have fun and explore!
--------------------------------------------------------------------------------

`))
}

func TunnelEstablished(component, port string) {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
+ Secure tunnel established to %s
+ Use the following credentials to connect
--------------------------------------------------------------------------------

Host: 127.0.0.1
Port: %s
User: available in your dashboard (if applicable)
Pass: available in your dashboard (if applicable)

`, component, port))
}

func InfoDevContainer(ip string) {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
+ You are in a Linux container
+ Your local source code has been mounted into the container
+ Changes to your code in either the container or desktop will be mirrored
+ If you run a server, access it at >> %s
--------------------------------------------------------------------------------

`, ip))
}
func InfoDevRunContainer(cmd, ip string) {
	os.Stderr.WriteString(fmt.Sprintf(`

      **
   *********
***************   Your command will run in an isolated Linux container
:: ********* ::   Code changes in either the container or desktop are mirrored
" ::: *** ::: "   ------------------------------------------------------------
  ""  :::  ""     If you run a server, access it at >> %s
    "" " ""
       "

RUNNING > %s
`, ip, cmd))

	os.Stderr.WriteString(fmt.Sprintf("%s\n", strings.Repeat("-", len(cmd)+10)))

}

func InfoSimDeploy(ip string) {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
+ Your app is running in simulated production environment
+ Access your app at >> %s
--------------------------------------------------------------------------------

`, ip))
}

func DevRunEmpty() {
	os.Stderr.WriteString(fmt.Sprintf(`
! You don't have any web or worker start commands specified in your
  boxfile.yml. More information about start commands is available here:

  https://docs.nanobox.io/boxfile/web/#start-command

`))
}

func FirstDeploy() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
+ HEADS UP:
+ This is the first deploy to this app and the upload takes longer than usual.
+ Future deploys only sync the differences and will be much faster.
--------------------------------------------------------------------------------

`))
}

func FirstBuild() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
+ HEADS UP:
+ This is the first build for this project and will take longer than usual.
+ Future builds will pull from the cache and will be much faster.
--------------------------------------------------------------------------------

`))
}

func ProviderSetup() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
+ HEADS UP:
+ Nanobox will run a single VM transparently within VirtualBox.
+ All apps and containers will be launched within the same VM.
--------------------------------------------------------------------------------

`))
}

func MigrateOldRequired() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
+ WARNING:
+ Nanobox has been successfully upgraded! This change constitutes a major
+ architectural refactor as well as data re-structure. To use this version we
+ need to purge your current apps. No worries, nanobox will re-build them for
+ you the next time you use "nanobox run".
--------------------------------------------------------------------------------
`))

}

func MigrateProviderRequired() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
+ WARNING:
+ It looks like you want to use a different provider, cool! Just FYI, we have
+ to bring down your existing apps as providers are not compatible. No worries,
+ nanobox will re-build them for you the next time you use "nanobox run".
--------------------------------------------------------------------------------
`))
}

func BadTerminal() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
This console is currently not supported by nanobox
Please refer to the docs for more information
--------------------------------------------------------------------------------
`))
}

func MissingDependencies(provider string, missingParts []string) {
	fmt.Printf("Using nanobox with %s requires tools that appear to not be available on your system.\n", provider)
	fmt.Println(strings.Join(missingParts, "\n"))
	if provider == "native" {
		provider = "docker"
	}
	fmt.Printf("View these requirements at docs.nanobox.io/install/requirements/%s/\n", provider)
}

func DeployComplete() {
	os.Stderr.WriteString(fmt.Sprintf(`
%s Success, this deploy is on the way!
  Check your dashboard for progress.

`, TaskComplete))
}

func LoginComplete() {
	os.Stderr.WriteString(fmt.Sprintf(`
%s You've successfully logged in
`, TaskComplete))
}

func NetworkCreateError(name, network string) {
	os.Stderr.WriteString(fmt.Sprintf(`
Nanobox is trying to create a native docker network, and it
looks like we have a conflict. An existing docker network is
already using the %s address space.

You will need to either remove the conflicting network, or set
an alternative address space with the following:

nanobox config set %s <unused ip/cidr>
`, network, name))
}

func VMCommunicationError() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
Nanobox has started a VM that needs access to your machine for mounting.
This VM is unable to communicate with the host machine currently. Please
verify that you don't have a firewall blocking this connection, and try again!
--------------------------------------------------------------------------------
`))
}

func NoGonanaUser() {
	os.Stderr.WriteString(fmt.Sprintf(`
We could not connect as the gonano user but we were able to
fall back to the default user
`, TaskComplete))
}

func MissingBoxfile() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
MISSING BOXFILE.YML
Nanobox is looking for a boxfile.yml config file. You might want to
check out our getting-started guide on configuring your app:

https://guides.nanobox.io/
--------------------------------------------------------------------------------
`))
}

func InvalidBoxfile() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
INVALID BOXFILE.YML
Nanobox requires valid yaml in your boxfile.yml config file. Please paste the
contents of your boxfile into www.yamllint.com to validate.
--------------------------------------------------------------------------------
`))
}

func TooManyKeys() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
POSSIBLY TOO MANY KEYS
Nanobox imports your ssh key directory for fetching dependencies but it appears
you may have more than we can handle. You might want to check out our docs on
specifying a key to use:

https://docs.nanobox.io/local-config/configure-nanobox/
--------------------------------------------------------------------------------
`))
}

func WorldWritable() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
Virtualbox was unable to create the virtual machine because a folder in the path
is globaly accessable and it should be private.
--------------------------------------------------------------------------------
`))

}

func LoginRequired() {
	os.Stderr.WriteString(fmt.Sprintf(`
It appears you are running Nanobox for the first time.
Login to your Nanobox account:
`))
}

func UnexpectedPrivilage() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
+ ERROR:
+ Nanobox is designed to run as a standard user (non root)
+ Please run all nanobox commands as a non privileged user
--------------------------------------------------------------------------------

`))
}

func BadPortType(protocol string) {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
+ WARNING:
+ The boxfile.yml does not support port protocol '%s'. Using 'tcp' as default.
--------------------------------------------------------------------------------
`, protocol))
}

func PortInUse(port string) {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
ADDRESS IN USE
It appears your local port (%s) is in use. Please specify a different port with
the '-p' flag. (eg. 'nanobox tunnel data.db -p 5444')
--------------------------------------------------------------------------------
`, port))
}

func PortPrivileged(port string) {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
PRIVILEGED PORT
Port '%s' is a privileged port. Please specify a port greater than 1023 with
the '-p' flag. (eg. 'nanobox tunnel data.db -p 5444')
--------------------------------------------------------------------------------
`, port))
}

func ConsoleNodeNotFound() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
NODE NOT FOUND
It appears the node you are trying to console to does not exist. Please double
check your boxfile.yml. If your boxfile.yml does contain a node by the name you
specified, please contact support.
--------------------------------------------------------------------------------
`))
}

func ConsoleLocalCode() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
CANNOT CONSOLE TO LOCAL CODE NODE
It appears you are trying to console to a local code node. When consoling to a
local web/worker, please use 'nanobox run'.
--------------------------------------------------------------------------------
`))
}

func LocalEngineNotFound() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
LOCAL ENGINE NOT FOUND
It appears the local engine sepcified does not exist at the location defined.
Please double check your boxfile.yml and the path to the engine. If the path
you specified exists, please contact support.
--------------------------------------------------------------------------------
`))
}
<commit_msg>updated the link to the install documentation<commit_after>package display

import (
	"fmt"
	"os"
	"strings"
)

func MOTD() {
	os.Stderr.WriteString(fmt.Sprintf(`

                                   **
                                ********
                             ***************
                          *********************
                            *****************
                          ::    *********    ::
                             ::    ***    ::
                           ++   :::   :::   ++
                              ++   :::   ++
                                 ++   ++
                                    +
                    _  _ ____ _  _ ____ ___  ____ _  _
                    |\ | |__| |\ | |  | |__) |  |  \/
                    | \| |  | | \| |__| |__) |__| _/\_
`))
}

func InfoProductionHost() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
+ WARNING:
+ You are on a live, production Linux server.
+ This host is primarily responsible for running docker containers.
+ Changes made to this machine have real consequences.
+ Proceed at your own risk.
--------------------------------------------------------------------------------

`))
}

func InfoProductionContainer() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
+ WARNING:
+ You are in a live, production Linux container.
+ Changes made to this machine have real consequences.
+ Proceed at your own risk.
--------------------------------------------------------------------------------

`))
}

func InfoLocalContainer() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
+ You are inside a Linux container on your local machine.
+ Anything here can be undone, so have fun and explore!
--------------------------------------------------------------------------------

`))
}

func TunnelEstablished(component, port string) {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
+ Secure tunnel established to %s
+ Use the following credentials to connect
--------------------------------------------------------------------------------

Host: 127.0.0.1
Port: %s
User: available in your dashboard (if applicable)
Pass: available in your dashboard (if applicable)

`, component, port))
}

func InfoDevContainer(ip string) {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
+ You are in a Linux container
+ Your local source code has been mounted into the container
+ Changes to your code in either the container or desktop will be mirrored
+ If you run a server, access it at >> %s
--------------------------------------------------------------------------------

`, ip))
}
func InfoDevRunContainer(cmd, ip string) {
	os.Stderr.WriteString(fmt.Sprintf(`

      **
   *********
***************   Your command will run in an isolated Linux container
:: ********* ::   Code changes in either the container or desktop are mirrored
" ::: *** ::: "   ------------------------------------------------------------
  ""  :::  ""     If you run a server, access it at >> %s
    "" " ""
       "

RUNNING > %s
`, ip, cmd))

	os.Stderr.WriteString(fmt.Sprintf("%s\n", strings.Repeat("-", len(cmd)+10)))

}

func InfoSimDeploy(ip string) {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
+ Your app is running in simulated production environment
+ Access your app at >> %s
--------------------------------------------------------------------------------

`, ip))
}

func DevRunEmpty() {
	os.Stderr.WriteString(fmt.Sprintf(`
! You don't have any web or worker start commands specified in your
  boxfile.yml. More information about start commands is available here:

  https://docs.nanobox.io/boxfile/web/#start-command

`))
}

func FirstDeploy() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
+ HEADS UP:
+ This is the first deploy to this app and the upload takes longer than usual.
+ Future deploys only sync the differences and will be much faster.
--------------------------------------------------------------------------------

`))
}

func FirstBuild() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
+ HEADS UP:
+ This is the first build for this project and will take longer than usual.
+ Future builds will pull from the cache and will be much faster.
--------------------------------------------------------------------------------

`))
}

func ProviderSetup() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
+ HEADS UP:
+ Nanobox will run a single VM transparently within VirtualBox.
+ All apps and containers will be launched within the same VM.
--------------------------------------------------------------------------------

`))
}

func MigrateOldRequired() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
+ WARNING:
+ Nanobox has been successfully upgraded! This change constitutes a major
+ architectural refactor as well as data re-structure. To use this version we
+ need to purge your current apps. No worries, nanobox will re-build them for
+ you the next time you use "nanobox run".
--------------------------------------------------------------------------------
`))

}

func MigrateProviderRequired() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
+ WARNING:
+ It looks like you want to use a different provider, cool! Just FYI, we have
+ to bring down your existing apps as providers are not compatible. No worries,
+ nanobox will re-build them for you the next time you use "nanobox run".
--------------------------------------------------------------------------------
`))
}

func BadTerminal() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
This console is currently not supported by nanobox
Please refer to the docs for more information
--------------------------------------------------------------------------------
`))
}

func MissingDependencies(provider string, missingParts []string) {
	fmt.Printf("Using nanobox with %s requires tools that appear to not be available on your system.\n", provider)
	fmt.Println(strings.Join(missingParts, "\n"))
	if provider == "native" {
		provider = "docker"
	}
	fmt.Printf("View these requirements at docs.nanobox.io/install\n", provider)
}

func DeployComplete() {
	os.Stderr.WriteString(fmt.Sprintf(`
%s Success, this deploy is on the way!
  Check your dashboard for progress.

`, TaskComplete))
}

func LoginComplete() {
	os.Stderr.WriteString(fmt.Sprintf(`
%s You've successfully logged in
`, TaskComplete))
}

func NetworkCreateError(name, network string) {
	os.Stderr.WriteString(fmt.Sprintf(`
Nanobox is trying to create a native docker network, and it
looks like we have a conflict. An existing docker network is
already using the %s address space.

You will need to either remove the conflicting network, or set
an alternative address space with the following:

nanobox config set %s <unused ip/cidr>
`, network, name))
}

func VMCommunicationError() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
Nanobox has started a VM that needs access to your machine for mounting.
This VM is unable to communicate with the host machine currently. Please
verify that you don't have a firewall blocking this connection, and try again!
--------------------------------------------------------------------------------
`))
}

func NoGonanaUser() {
	os.Stderr.WriteString(fmt.Sprintf(`
We could not connect as the gonano user but we were able to
fall back to the default user
`, TaskComplete))
}

func MissingBoxfile() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
MISSING BOXFILE.YML
Nanobox is looking for a boxfile.yml config file. You might want to
check out our getting-started guide on configuring your app:

https://guides.nanobox.io/
--------------------------------------------------------------------------------
`))
}

func InvalidBoxfile() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
INVALID BOXFILE.YML
Nanobox requires valid yaml in your boxfile.yml config file. Please paste the
contents of your boxfile into www.yamllint.com to validate.
--------------------------------------------------------------------------------
`))
}

func TooManyKeys() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
POSSIBLY TOO MANY KEYS
Nanobox imports your ssh key directory for fetching dependencies but it appears
you may have more than we can handle. You might want to check out our docs on
specifying a key to use:

https://docs.nanobox.io/local-config/configure-nanobox/
--------------------------------------------------------------------------------
`))
}

func WorldWritable() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
Virtualbox was unable to create the virtual machine because a folder in the path
is globaly accessable and it should be private.
--------------------------------------------------------------------------------
`))

}

func LoginRequired() {
	os.Stderr.WriteString(fmt.Sprintf(`
It appears you are running Nanobox for the first time.
Login to your Nanobox account:
`))
}

func UnexpectedPrivilage() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
+ ERROR:
+ Nanobox is designed to run as a standard user (non root)
+ Please run all nanobox commands as a non privileged user
--------------------------------------------------------------------------------

`))
}

func BadPortType(protocol string) {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
+ WARNING:
+ The boxfile.yml does not support port protocol '%s'. Using 'tcp' as default.
--------------------------------------------------------------------------------
`, protocol))
}

func PortInUse(port string) {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
ADDRESS IN USE
It appears your local port (%s) is in use. Please specify a different port with
the '-p' flag. (eg. 'nanobox tunnel data.db -p 5444')
--------------------------------------------------------------------------------
`, port))
}

func PortPrivileged(port string) {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
PRIVILEGED PORT
Port '%s' is a privileged port. Please specify a port greater than 1023 with
the '-p' flag. (eg. 'nanobox tunnel data.db -p 5444')
--------------------------------------------------------------------------------
`, port))
}

func ConsoleNodeNotFound() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
NODE NOT FOUND
It appears the node you are trying to console to does not exist. Please double
check your boxfile.yml. If your boxfile.yml does contain a node by the name you
specified, please contact support.
--------------------------------------------------------------------------------
`))
}

func ConsoleLocalCode() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
CANNOT CONSOLE TO LOCAL CODE NODE
It appears you are trying to console to a local code node. When consoling to a
local web/worker, please use 'nanobox run'.
--------------------------------------------------------------------------------
`))
}

func LocalEngineNotFound() {
	os.Stderr.WriteString(fmt.Sprintf(`
--------------------------------------------------------------------------------
LOCAL ENGINE NOT FOUND
It appears the local engine sepcified does not exist at the location defined.
Please double check your boxfile.yml and the path to the engine. If the path
you specified exists, please contact support.
--------------------------------------------------------------------------------
`))
}
<|endoftext|>


<commit_before>/*
Package schedule grabs DJ schedule data from Ponyville FM's servers.
*/
package schedule

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

// ScheduleResult is a wrapper for a list of ScheduleEntry records.
type ScheduleResult struct {
	Result []ScheduleEntry `json:"result"`
}

// ScheduleEntry is an individual schedule datum.
type ScheduleEntry struct {
	StartTime   string `json:"start_time"`
	StartUnix   int    `json:"start_unix"`
	Duration    string `json:"duration"`
	EndTime     string `json:"end_time"`
	EndUnix     int    `json:"end_unix"`
	Name        string `json:"name"`
	Host        string `json:"host"`
	Description string `json:"description"`
	Showcard    string `json:"showcard"`
	Background  string `json:"background"`
	Timezone    string `json:"timezone"`
	Status      string `json:"status"`
}

func (s ScheduleEntry) String() string {
	startTimeUnix := time.Unix(int64(s.StartUnix), 0)
	dur := startTimeUnix.Sub(time.Unix(time.Now().Unix(), 0))

	if dur > 0 {
		return fmt.Sprintf(
			"In %s (%v %v): %s - %s",
			dur, s.StartTime, s.Timezone, s.Host, s.Name,
		)
	} else {
		return fmt.Sprintf(
			"Now: %s - %s",
			s.Host, s.Name,
		)
	}
}

var (
	latestInfo Wrapper

	bugTime = flag.Int("pvfm-schedule-poke-delay", 15, "how stale the info can get")
)

// Wrapper is a time, info pair. This is used to invalidate the cache of
// data from ponyvillefm.com.
type Wrapper struct {
	Age  time.Time
	Info *ScheduleResult
}

// Get returns schedule entries, only fetching new data at most every n
// seconds, where n is defined above.
func Get() ([]ScheduleEntry, error) {
	now := time.Now()

	if now.Before(latestInfo.Age.Add(time.Second * time.Duration(*bugTime))) {
		return latestInfo.Info.Result, nil
	}

	s := &ScheduleResult{}
	c := http.Client{
		Timeout: time.Duration(time.Second * 15),
	}

	resp, err := c.Get("http://ponyvillefm.com/data/schedule")
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	content, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal(content, s)
	if err != nil {
		return nil, err
	}

	// Update the age/contents of the latestInfo
	latestInfo.Info = s
	latestInfo.Age = now

	return s.Result, nil
}
<commit_msg>Extract a variable to make intent clearer<commit_after>/*
Package schedule grabs DJ schedule data from Ponyville FM's servers.
*/
package schedule

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

// ScheduleResult is a wrapper for a list of ScheduleEntry records.
type ScheduleResult struct {
	Result []ScheduleEntry `json:"result"`
}

// ScheduleEntry is an individual schedule datum.
type ScheduleEntry struct {
	StartTime   string `json:"start_time"`
	StartUnix   int    `json:"start_unix"`
	Duration    string `json:"duration"`
	EndTime     string `json:"end_time"`
	EndUnix     int    `json:"end_unix"`
	Name        string `json:"name"`
	Host        string `json:"host"`
	Description string `json:"description"`
	Showcard    string `json:"showcard"`
	Background  string `json:"background"`
	Timezone    string `json:"timezone"`
	Status      string `json:"status"`
}

func (s ScheduleEntry) String() string {
	startTimeUnix := time.Unix(int64(s.StartUnix), 0)
	nowWithoutNanoseconds := time.Unix(time.Now().Unix(), 0)
	dur := startTimeUnix.Sub(nowWithoutNanoseconds)

	if dur > 0 {
		return fmt.Sprintf(
			"In %s (%v %v): %s - %s",
			dur, s.StartTime, s.Timezone, s.Host, s.Name,
		)
	} else {
		return fmt.Sprintf(
			"Now: %s - %s",
			s.Host, s.Name,
		)
	}
}

var (
	latestInfo Wrapper

	bugTime = flag.Int("pvfm-schedule-poke-delay", 15, "how stale the info can get")
)

// Wrapper is a time, info pair. This is used to invalidate the cache of
// data from ponyvillefm.com.
type Wrapper struct {
	Age  time.Time
	Info *ScheduleResult
}

// Get returns schedule entries, only fetching new data at most every n
// seconds, where n is defined above.
func Get() ([]ScheduleEntry, error) {
	now := time.Now()

	if now.Before(latestInfo.Age.Add(time.Second * time.Duration(*bugTime))) {
		return latestInfo.Info.Result, nil
	}

	s := &ScheduleResult{}
	c := http.Client{
		Timeout: time.Duration(time.Second * 15),
	}

	resp, err := c.Get("http://ponyvillefm.com/data/schedule")
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	content, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal(content, s)
	if err != nil {
		return nil, err
	}

	// Update the age/contents of the latestInfo
	latestInfo.Info = s
	latestInfo.Age = now

	return s.Result, nil
}
<|endoftext|>


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

package main

import (
	"archive/zip"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"math/rand"
	"os"
	"regexp"
	"runtime"
	"time"

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

var (
	flagCorpus   = flag.String("corpus", "", "corpus directory")
	flagExecutor = flag.String("executor", "", "path to executor binary")
	flagOutput   = flag.Bool("output", false, "print executor output to console")
	flagDebug    = flag.Bool("debug", false, "executor debug output")
	flagProcs    = flag.Int("procs", runtime.NumCPU(), "number of parallel processes")
	flagThreaded = flag.Bool("threaded", true, "use threaded mode in executor")
	flagCollide  = flag.Bool("collide", true, "collide syscalls to provoke data races")
	flagNobody   = flag.Bool("nobody", false, "impersonate into nobody")
	flagTimeout  = flag.Duration("timeout", 5*time.Second, "executor timeout")

	failedRe = regexp.MustCompile("runtime error: |panic: |Panic: ")
)

func main() {
	flag.Parse()
	corpus := readCorpus()
	var flags uint64
	if *flagThreaded {
		flags |= ipc.FlagThreaded
	}
	if *flagCollide {
		flags |= ipc.FlagCollide
	}
	if *flagNobody {
		flags |= ipc.FlagDropPrivs
	}
	if *flagDebug {
		flags |= ipc.FlagDebug
	}

	for p := 0; p < *flagProcs; p++ {
		go func() {
			env, err := ipc.MakeEnv(*flagExecutor, 10*time.Second, flags)
			if err != nil {
				failf("failed to create execution environment: %v", err)
			}
			rs := rand.NewSource(time.Now().UnixNano())
			rnd := rand.New(rs)
			for i := 0; ; i++ {
				var p *prog.Prog
				if len(corpus) == 0 || i%10 != 0 {
					p = prog.Generate(rs, 50, nil)
					execute(env, p)
					p.Mutate(rs, 50, nil)
					execute(env, p)
				} else {
					p = corpus[rnd.Intn(len(corpus))].Clone()
					p.Mutate(rs, 50, nil)
					execute(env, p)
				}
			}
		}()
	}
	select {}
}

func execute(env *ipc.Env, p *prog.Prog) {
	if *flagExecutor == "" {
		return
	}
	output, _, _, _, _, err := env.Exec(p)
	if err != nil {
		fmt.Printf("failed to execute executor: %v\n", err)
	}
	failed := failedRe.Match(output)
	if failed {
		fmt.Printf("PROGRAM:\n%s\n", p.Serialize())
	}
	if failed || *flagOutput {
		os.Stdout.Write(output)
	}
}

func readCorpus() []*prog.Prog {
	if *flagCorpus == "" {
		return nil
	}
	zipr, err := zip.OpenReader(*flagCorpus)
	if err != nil {
		failf("failed to open bin file: %v", err)
	}
	var progs []*prog.Prog
	for _, zipf := range zipr.File {
		r, err := zipf.Open()
		if err != nil {
			failf("failed to uzip file from input archive: %v", err)
		}
		data, err := ioutil.ReadAll(r)
		if err != nil {
			failf("failed to read corpus file: %v", err)
		}
		p, err := prog.Deserialize(data)
		if err != nil {
			failf("failed to deserialize corpus program: %v", err)
		}
		progs = append(progs, p)
		r.Close()
	}
	zipr.Close()
	return progs
}

func failf(msg string, args ...interface{}) {
	log.Fatalf(msg, args...)
}
<commit_msg>tools/stress: minor improvements<commit_after>// Copyright 2015 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package main

import (
	"archive/zip"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"math/rand"
	"os"
	"regexp"
	"runtime"
	"sync/atomic"
	"time"

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

var (
	flagCorpus   = flag.String("corpus", "", "corpus directory")
	flagExecutor = flag.String("executor", "", "path to executor binary")
	flagOutput   = flag.Bool("output", false, "print executor output to console")
	flagDebug    = flag.Bool("debug", false, "executor debug output")
	flagProcs    = flag.Int("procs", 2*runtime.NumCPU(), "number of parallel processes")
	flagThreaded = flag.Bool("threaded", true, "use threaded mode in executor")
	flagCollide  = flag.Bool("collide", true, "collide syscalls to provoke data races")
	flagNobody   = flag.Bool("nobody", true, "impersonate into nobody")
	flagTimeout  = flag.Duration("timeout", 10*time.Second, "executor timeout")

	failedRe = regexp.MustCompile("runtime error: |panic: |Panic: ")

	statExec uint64
)

const programLength = 30

func main() {
	flag.Parse()
	corpus := readCorpus()
	log.Printf("parsed %v programs", len(corpus))
	var flags uint64
	if *flagThreaded {
		flags |= ipc.FlagThreaded
	}
	if *flagCollide {
		flags |= ipc.FlagCollide
	}
	if *flagNobody {
		flags |= ipc.FlagDropPrivs
	}
	if *flagDebug {
		flags |= ipc.FlagDebug
	}

	for p := 0; p < *flagProcs; p++ {
		p := p
		go func() {
			env, err := ipc.MakeEnv(*flagExecutor, *flagTimeout, flags)
			if err != nil {
				failf("failed to create execution environment: %v", err)
			}
			rs := rand.NewSource(time.Now().UnixNano() + int64(p)*1e12)
			rnd := rand.New(rs)
			for i := 0; ; i++ {
				var p *prog.Prog
				if len(corpus) == 0 || i%2 != 0 {
					p = prog.Generate(rs, programLength, nil)
					execute(env, p)
					p.Mutate(rs, programLength, nil)
					execute(env, p)
				} else {
					p = corpus[rnd.Intn(len(corpus))].Clone()
					p.Mutate(rs, programLength, nil)
					execute(env, p)
					p.Mutate(rs, programLength, nil)
					execute(env, p)
				}
			}
		}()
	}
	for range time.NewTicker(5 * time.Second).C {
		log.Printf("executed %v programs", atomic.LoadUint64(&statExec))
	}
}

func execute(env *ipc.Env, p *prog.Prog) {
	if *flagExecutor == "" {
		return
	}
	atomic.AddUint64(&statExec, 1)
	output, _, _, _, _, err := env.Exec(p)
	if err != nil {
		fmt.Printf("failed to execute executor: %v\n", err)
	}
	failed := failedRe.Match(output)
	if failed {
		fmt.Printf("PROGRAM:\n%s\n", p.Serialize())
	}
	if failed || *flagOutput {
		os.Stdout.Write(output)
	}
}

func readCorpus() []*prog.Prog {
	if *flagCorpus == "" {
		return nil
	}
	zipr, err := zip.OpenReader(*flagCorpus)
	if err != nil {
		failf("failed to open bin file: %v", err)
	}
	var progs []*prog.Prog
	for _, zipf := range zipr.File {
		r, err := zipf.Open()
		if err != nil {
			failf("failed to uzip file from input archive: %v", err)
		}
		data, err := ioutil.ReadAll(r)
		if err != nil {
			failf("failed to read corpus file: %v", err)
		}
		p, err := prog.Deserialize(data)
		if err != nil {
			failf("failed to deserialize corpus program: %v", err)
		}
		progs = append(progs, p)
		r.Close()
	}
	zipr.Close()
	return progs
}

func failf(msg string, args ...interface{}) {
	log.Fatalf(msg, args...)
}
<|endoftext|>


<commit_before>/*
Package "dense" provides an implementation of "Matrix" which stores elements in a slide.
*/
package dense

import (
	"github.com/mitsuse/matrix-go/internal/rewriters"
	"github.com/mitsuse/matrix-go/internal/types"
	"github.com/mitsuse/matrix-go/internal/validates"
)

type matrixImpl struct {
	rows     int
	columns  int
	elements []float64
	rewriter rewriters.Rewriter
}

func New(rows, columns int) func(elements ...float64) types.Matrix {
	validates.ShapeShouldBePositive(rows, columns)

	constructor := func(elements ...float64) types.Matrix {
		size := rows * columns

		if len(elements) != size {
			panic(validates.INVALID_ELEMENTS_PANIC)
		}

		m := &matrixImpl{
			rows:     rows,
			columns:  columns,
			elements: make([]float64, size),
			rewriter: rewriters.Reflect(),
		}
		copy(m.elements, elements)

		return m
	}

	return constructor
}

func Zeros(rows, columns int) types.Matrix {
	return New(rows, columns)(make([]float64, rows*columns)...)
}

func (m *matrixImpl) Shape() (rows, columns int) {
	return m.rewriter.Rewrite(m.rows, m.columns)
}

func (m *matrixImpl) Rows() (rows int) {
	rows, _ = m.Shape()
	return rows
}

func (m *matrixImpl) Columns() (columns int) {
	_, columns = m.Shape()
	return columns
}

func (m *matrixImpl) All() types.Cursor {
	return newAllCursor(m)
}

func (m *matrixImpl) NonZeros() types.Cursor {
	return newNonZerosCursor(m)
}

func (m *matrixImpl) Diagonal() types.Cursor {
	return newDiagonalCursor(m)
}

func (m *matrixImpl) Get(row, column int) (element float64) {
	rows, columns := m.Shape()

	validates.IndexShouldBeInRange(rows, columns, row, column)

	row, column = m.rewriter.Rewrite(row, column)

	return m.elements[row*m.columns+column]
}

func (m *matrixImpl) Update(row, column int, element float64) types.Matrix {
	rows, columns := m.Shape()

	validates.IndexShouldBeInRange(rows, columns, row, column)

	row, column = m.rewriter.Rewrite(row, column)

	m.elements[row*m.columns+column] = element

	return m
}

func (m *matrixImpl) Equal(n types.Matrix) bool {
	validates.ShapeShouldBeSame(m, n)

	cursor := n.All()

	for cursor.HasNext() {
		element, row, column := cursor.Get()
		if m.Get(row, column) != element {
			return false
		}
	}

	return true
}

func (m *matrixImpl) Add(n types.Matrix) types.Matrix {
	validates.ShapeShouldBeSame(m, n)

	cursor := n.NonZeros()

	for cursor.HasNext() {
		element, row, column := cursor.Get()
		m.Update(row, column, m.Get(row, column)+element)
	}

	return m
}

func (m *matrixImpl) Subtract(n types.Matrix) types.Matrix {
	validates.ShapeShouldBeSame(m, n)

	cursor := n.NonZeros()

	for cursor.HasNext() {
		element, row, column := cursor.Get()
		m.Update(row, column, m.Get(row, column)-element)
	}

	return m
}

func (m *matrixImpl) Dot(n types.Matrix) types.Matrix {
	validates.ShapeShouldBeMultipliable(m, n)

	rows := m.Rows()
	columns := n.Columns()

	r := Zeros(rows, columns)

	cursor := n.NonZeros()

	for cursor.HasNext() {
		element, j, k := cursor.Get()

		for i := 0; i < rows; i++ {
			r.Update(i, k, r.Get(i, k)+m.Get(i, j)*element)
		}
	}

	return r
}

func (m *matrixImpl) Multiply(s float64) types.Matrix {
	for index, element := range m.elements {
		m.elements[index] = element * s
	}

	return m
}

func (m *matrixImpl) Transpose() types.Matrix {
	n := &matrixImpl{
		rows:     m.rows,
		columns:  m.columns,
		elements: m.elements,
		rewriter: m.rewriter.Transpose(),
	}

	return n
}
<commit_msg>Package "dense" provides an implementation of dense matrix.<commit_after>/*
Package "dense" provides an implementation of mutable dense matrix.
*/
package dense

import (
	"github.com/mitsuse/matrix-go/internal/rewriters"
	"github.com/mitsuse/matrix-go/internal/types"
	"github.com/mitsuse/matrix-go/internal/validates"
)

type matrixImpl struct {
	rows     int
	columns  int
	elements []float64
	rewriter rewriters.Rewriter
}

func New(rows, columns int) func(elements ...float64) types.Matrix {
	validates.ShapeShouldBePositive(rows, columns)

	constructor := func(elements ...float64) types.Matrix {
		size := rows * columns

		if len(elements) != size {
			panic(validates.INVALID_ELEMENTS_PANIC)
		}

		m := &matrixImpl{
			rows:     rows,
			columns:  columns,
			elements: make([]float64, size),
			rewriter: rewriters.Reflect(),
		}
		copy(m.elements, elements)

		return m
	}

	return constructor
}

func Zeros(rows, columns int) types.Matrix {
	return New(rows, columns)(make([]float64, rows*columns)...)
}

func (m *matrixImpl) Shape() (rows, columns int) {
	return m.rewriter.Rewrite(m.rows, m.columns)
}

func (m *matrixImpl) Rows() (rows int) {
	rows, _ = m.Shape()
	return rows
}

func (m *matrixImpl) Columns() (columns int) {
	_, columns = m.Shape()
	return columns
}

func (m *matrixImpl) All() types.Cursor {
	return newAllCursor(m)
}

func (m *matrixImpl) NonZeros() types.Cursor {
	return newNonZerosCursor(m)
}

func (m *matrixImpl) Diagonal() types.Cursor {
	return newDiagonalCursor(m)
}

func (m *matrixImpl) Get(row, column int) (element float64) {
	rows, columns := m.Shape()

	validates.IndexShouldBeInRange(rows, columns, row, column)

	row, column = m.rewriter.Rewrite(row, column)

	return m.elements[row*m.columns+column]
}

func (m *matrixImpl) Update(row, column int, element float64) types.Matrix {
	rows, columns := m.Shape()

	validates.IndexShouldBeInRange(rows, columns, row, column)

	row, column = m.rewriter.Rewrite(row, column)

	m.elements[row*m.columns+column] = element

	return m
}

func (m *matrixImpl) Equal(n types.Matrix) bool {
	validates.ShapeShouldBeSame(m, n)

	cursor := n.All()

	for cursor.HasNext() {
		element, row, column := cursor.Get()
		if m.Get(row, column) != element {
			return false
		}
	}

	return true
}

func (m *matrixImpl) Add(n types.Matrix) types.Matrix {
	validates.ShapeShouldBeSame(m, n)

	cursor := n.NonZeros()

	for cursor.HasNext() {
		element, row, column := cursor.Get()
		m.Update(row, column, m.Get(row, column)+element)
	}

	return m
}

func (m *matrixImpl) Subtract(n types.Matrix) types.Matrix {
	validates.ShapeShouldBeSame(m, n)

	cursor := n.NonZeros()

	for cursor.HasNext() {
		element, row, column := cursor.Get()
		m.Update(row, column, m.Get(row, column)-element)
	}

	return m
}

func (m *matrixImpl) Dot(n types.Matrix) types.Matrix {
	validates.ShapeShouldBeMultipliable(m, n)

	rows := m.Rows()
	columns := n.Columns()

	r := Zeros(rows, columns)

	cursor := n.NonZeros()

	for cursor.HasNext() {
		element, j, k := cursor.Get()

		for i := 0; i < rows; i++ {
			r.Update(i, k, r.Get(i, k)+m.Get(i, j)*element)
		}
	}

	return r
}

func (m *matrixImpl) Multiply(s float64) types.Matrix {
	for index, element := range m.elements {
		m.elements[index] = element * s
	}

	return m
}

func (m *matrixImpl) Transpose() types.Matrix {
	n := &matrixImpl{
		rows:     m.rows,
		columns:  m.columns,
		elements: m.elements,
		rewriter: m.rewriter.Transpose(),
	}

	return n
}
<|endoftext|>


<commit_before>/*
Package "dense" provides an implementation of mutable dense matrix.
*/
package dense

import (
	"github.com/mitsuse/matrix-go/internal/rewriters"
	"github.com/mitsuse/matrix-go/internal/types"
	"github.com/mitsuse/matrix-go/internal/validates"
)

type matrixImpl struct {
	rows     int
	columns  int
	elements []float64
	rewriter rewriters.Rewriter
}

// Create a new matrix with given elements.
func New(rows, columns int) func(elements ...float64) types.Matrix {
	validates.ShapeShouldBePositive(rows, columns)

	constructor := func(elements ...float64) types.Matrix {
		size := rows * columns

		if len(elements) != size {
			panic(validates.INVALID_ELEMENTS_PANIC)
		}

		m := &matrixImpl{
			rows:     rows,
			columns:  columns,
			elements: make([]float64, size),
			rewriter: rewriters.Reflect(),
		}
		copy(m.elements, elements)

		return m
	}

	return constructor
}

// Create a new zero matrix.
func Zeros(rows, columns int) types.Matrix {
	return New(rows, columns)(make([]float64, rows*columns)...)
}

func (m *matrixImpl) Shape() (rows, columns int) {
	return m.rewriter.Rewrite(m.rows, m.columns)
}

func (m *matrixImpl) Rows() (rows int) {
	rows, _ = m.Shape()
	return rows
}

func (m *matrixImpl) Columns() (columns int) {
	_, columns = m.Shape()
	return columns
}

func (m *matrixImpl) All() types.Cursor {
	return newAllCursor(m)
}

func (m *matrixImpl) NonZeros() types.Cursor {
	return newNonZerosCursor(m)
}

func (m *matrixImpl) Diagonal() types.Cursor {
	return newDiagonalCursor(m)
}

func (m *matrixImpl) Get(row, column int) (element float64) {
	rows, columns := m.Shape()

	validates.IndexShouldBeInRange(rows, columns, row, column)

	row, column = m.rewriter.Rewrite(row, column)

	return m.elements[row*m.columns+column]
}

func (m *matrixImpl) Update(row, column int, element float64) types.Matrix {
	rows, columns := m.Shape()

	validates.IndexShouldBeInRange(rows, columns, row, column)

	row, column = m.rewriter.Rewrite(row, column)

	m.elements[row*m.columns+column] = element

	return m
}

func (m *matrixImpl) Equal(n types.Matrix) bool {
	validates.ShapeShouldBeSame(m, n)

	cursor := n.All()

	for cursor.HasNext() {
		element, row, column := cursor.Get()
		if m.Get(row, column) != element {
			return false
		}
	}

	return true
}

func (m *matrixImpl) Add(n types.Matrix) types.Matrix {
	validates.ShapeShouldBeSame(m, n)

	cursor := n.NonZeros()

	for cursor.HasNext() {
		element, row, column := cursor.Get()
		m.Update(row, column, m.Get(row, column)+element)
	}

	return m
}

func (m *matrixImpl) Subtract(n types.Matrix) types.Matrix {
	validates.ShapeShouldBeSame(m, n)

	cursor := n.NonZeros()

	for cursor.HasNext() {
		element, row, column := cursor.Get()
		m.Update(row, column, m.Get(row, column)-element)
	}

	return m
}

func (m *matrixImpl) Multiply(n types.Matrix) types.Matrix {
	validates.ShapeShouldBeMultipliable(m, n)

	rows := m.Rows()
	columns := n.Columns()

	r := Zeros(rows, columns)

	cursor := n.NonZeros()

	for cursor.HasNext() {
		element, j, k := cursor.Get()

		for i := 0; i < rows; i++ {
			r.Update(i, k, r.Get(i, k)+m.Get(i, j)*element)
		}
	}

	return r
}

func (m *matrixImpl) Scalar(s float64) types.Matrix {
	for index, element := range m.elements {
		m.elements[index] = element * s
	}

	return m
}

func (m *matrixImpl) Transpose() types.Matrix {
	n := &matrixImpl{
		rows:     m.rows,
		columns:  m.columns,
		elements: m.elements,
		rewriter: m.rewriter.Transpose(),
	}

	return n
}
<commit_msg>Add the documentation for pacnics caused by matrix creation.<commit_after>/*
Package "dense" provides an implementation of mutable dense matrix.
*/
package dense

import (
	"github.com/mitsuse/matrix-go/internal/rewriters"
	"github.com/mitsuse/matrix-go/internal/types"
	"github.com/mitsuse/matrix-go/internal/validates"
)

type matrixImpl struct {
	rows     int
	columns  int
	elements []float64
	rewriter rewriters.Rewriter
}

// Create a new matrix with given elements.
// When "rows" and "columns" is not positive,
// validates.NON_POSITIVE_SIZE_PANIC will be caused.
// In addition,
// when the product of "row"s and "column" doesn't equal to the size of "elements",
// validates.INVALID_ELEMENTS_PANIC will be caused.
func New(rows, columns int) func(elements ...float64) types.Matrix {
	validates.ShapeShouldBePositive(rows, columns)

	constructor := func(elements ...float64) types.Matrix {
		size := rows * columns

		if len(elements) != size {
			panic(validates.INVALID_ELEMENTS_PANIC)
		}

		m := &matrixImpl{
			rows:     rows,
			columns:  columns,
			elements: make([]float64, size),
			rewriter: rewriters.Reflect(),
		}
		copy(m.elements, elements)

		return m
	}

	return constructor
}

// Create a new zero matrix.
// When "rows" and "columns" is not positive,
// validates.NON_POSITIVE_SIZE_PANIC will be caused.
func Zeros(rows, columns int) types.Matrix {
	return New(rows, columns)(make([]float64, rows*columns)...)
}

func (m *matrixImpl) Shape() (rows, columns int) {
	return m.rewriter.Rewrite(m.rows, m.columns)
}

func (m *matrixImpl) Rows() (rows int) {
	rows, _ = m.Shape()
	return rows
}

func (m *matrixImpl) Columns() (columns int) {
	_, columns = m.Shape()
	return columns
}

func (m *matrixImpl) All() types.Cursor {
	return newAllCursor(m)
}

func (m *matrixImpl) NonZeros() types.Cursor {
	return newNonZerosCursor(m)
}

func (m *matrixImpl) Diagonal() types.Cursor {
	return newDiagonalCursor(m)
}

func (m *matrixImpl) Get(row, column int) (element float64) {
	rows, columns := m.Shape()

	validates.IndexShouldBeInRange(rows, columns, row, column)

	row, column = m.rewriter.Rewrite(row, column)

	return m.elements[row*m.columns+column]
}

func (m *matrixImpl) Update(row, column int, element float64) types.Matrix {
	rows, columns := m.Shape()

	validates.IndexShouldBeInRange(rows, columns, row, column)

	row, column = m.rewriter.Rewrite(row, column)

	m.elements[row*m.columns+column] = element

	return m
}

func (m *matrixImpl) Equal(n types.Matrix) bool {
	validates.ShapeShouldBeSame(m, n)

	cursor := n.All()

	for cursor.HasNext() {
		element, row, column := cursor.Get()
		if m.Get(row, column) != element {
			return false
		}
	}

	return true
}

func (m *matrixImpl) Add(n types.Matrix) types.Matrix {
	validates.ShapeShouldBeSame(m, n)

	cursor := n.NonZeros()

	for cursor.HasNext() {
		element, row, column := cursor.Get()
		m.Update(row, column, m.Get(row, column)+element)
	}

	return m
}

func (m *matrixImpl) Subtract(n types.Matrix) types.Matrix {
	validates.ShapeShouldBeSame(m, n)

	cursor := n.NonZeros()

	for cursor.HasNext() {
		element, row, column := cursor.Get()
		m.Update(row, column, m.Get(row, column)-element)
	}

	return m
}

func (m *matrixImpl) Multiply(n types.Matrix) types.Matrix {
	validates.ShapeShouldBeMultipliable(m, n)

	rows := m.Rows()
	columns := n.Columns()

	r := Zeros(rows, columns)

	cursor := n.NonZeros()

	for cursor.HasNext() {
		element, j, k := cursor.Get()

		for i := 0; i < rows; i++ {
			r.Update(i, k, r.Get(i, k)+m.Get(i, j)*element)
		}
	}

	return r
}

func (m *matrixImpl) Scalar(s float64) types.Matrix {
	for index, element := range m.elements {
		m.elements[index] = element * s
	}

	return m
}

func (m *matrixImpl) Transpose() types.Matrix {
	n := &matrixImpl{
		rows:     m.rows,
		columns:  m.columns,
		elements: m.elements,
		rewriter: m.rewriter.Transpose(),
	}

	return n
}
<|endoftext|>


<commit_before>/*
Copyright 2017 The Kubernetes Authors.

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

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

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

package model

import (
	"time"

	"github.com/golang/glog"
	apiv1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/resource"
)

// MetricName represents the name of the resource monitored by recommender.
type MetricName string

// ResourceAmount represents quantity of a certain resource within a container.
type ResourceAmount int64

// Resources is a map from resource name to the corresponding ResourceAmount.
type Resources map[MetricName]ResourceAmount

const (
	// ResourceCPU represents CPU in millicores (1core = 1000millicores).
	ResourceCPU MetricName = "cpu"
	// ResourceMemory represents memory, in bytes. (500Gi = 500GiB = 500 * 1024 * 1024 * 1024).
	ResourceMemory MetricName = "memory"
)

// CPUAmountFromCores converts CPU cores to a ResourceAmount.
func CPUAmountFromCores(cores float64) ResourceAmount {
	return ResourceAmount(cores * 1000.0)
}

// CoresFromCPUAmount converts ResourceAmount to number of cores expressed as float64.
func CoresFromCPUAmount(cpuAmunt ResourceAmount) float64 {
	return float64(cpuAmunt) / 1000.0
}

// QuantityFromCPUAmount converts CPU cores to a resource.Quantity.
func QuantityFromCPUAmount(cpuAmount ResourceAmount) resource.Quantity {
	return *resource.NewScaledQuantity(int64(cpuAmount), -3)
}

// MemoryAmountFromBytes converts memory bytes to a ResourceAmount.
func MemoryAmountFromBytes(bytes float64) ResourceAmount {
	return ResourceAmount(bytes)
}

// BytesFromMemoryAmount converts ResourceAmount to number of bytes expressed as float64.
func BytesFromMemoryAmount(memoryAmount ResourceAmount) float64 {
	return float64(memoryAmount)
}

// QuantityFromMemoryAmount converts memory bytes to a resource.Quantity.
func QuantityFromMemoryAmount(memoryAmount ResourceAmount) resource.Quantity {
	return *resource.NewScaledQuantity(int64(memoryAmount), 0)
}

// ResourcesAsResourceList converts internal Resources representation to ResourcesList.
func ResourcesAsResourceList(resources Resources) apiv1.ResourceList {
	result := make(apiv1.ResourceList)
	for key, resourceAmount := range resources {
		var newKey apiv1.ResourceName
		var quantity resource.Quantity
		switch key {
		case ResourceCPU:
			newKey = apiv1.ResourceCPU
			quantity = QuantityFromCPUAmount(resourceAmount)
		case ResourceMemory:
			newKey = apiv1.ResourceMemory
			quantity = QuantityFromMemoryAmount(resourceAmount)
		default:
			glog.Errorf("Cannot translate %v resource name", key)
			continue
		}
		result[newKey] = quantity
	}
	return result
}

// PodID contains information needed to identify a Pod within a cluster.
type PodID struct {
	// Namespaces where the Pod is defined.
	Namespace string
	// PodName is the name of the pod unique within a namespace.
	PodName string
}

// ContainerID contains information needed to identify a Container within a cluster.
type ContainerID struct {
	PodID
	// ContainerName is the name of the container, unique within a pod.
	ContainerName string
}

// VpaID contains information needed to identify a VPA API object within a cluster.
type VpaID struct {
	Namespace string
	VpaName   string
}

// ContainerMetricsSnapshot contains information about usage of certain container within defined time window.
type ContainerMetricsSnapshot struct {
	// ID identifies a specific container those metrics are coming from.
	ID ContainerID
	// End time of the measurement interval.
	SnapshotTime time.Time
	// Duration of the measurement interval, which is [SnapshotTime - SnapshotWindow, SnapshotTime].
	SnapshotWindow time.Duration
	// Actual usage of the resources over the measurement interval.
	Usage Resources
}

// BasicPodSpec contains basic information defining a pod and its containers.
type BasicPodSpec struct {
	// ID identifies a pod within a cluster.
	ID PodID
	// Labels of the pod. It is used to match pods with certain VPA opjects.
	PodLabels map[string]string
	// List of containers within this pod.
	Containers []BasicContainerSpec
}

// BasicContainerSpec contains basic information defining a container.
type BasicContainerSpec struct {
	// ID identifies the container within a cluster.
	ID ContainerID
	// Name of the image running within the container.
	Image string
	// Currently requested resources for this container.
	Request Resources
}
<commit_msg>Fixed comments.<commit_after>/*
Copyright 2017 The Kubernetes Authors.

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

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

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

package model

import (
	"time"

	"github.com/golang/glog"
	apiv1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/resource"
)

// MetricName represents the name of the resource monitored by recommender.
type MetricName string

// ResourceAmount represents quantity of a certain resource within a container.
type ResourceAmount int64

// Resources is a map from resource name to the corresponding ResourceAmount.
type Resources map[MetricName]ResourceAmount

const (
	// ResourceCPU represents CPU in millicores (1core = 1000millicores).
	ResourceCPU MetricName = "cpu"
	// ResourceMemory represents memory, in bytes. (500Gi = 500GiB = 500 * 1024 * 1024 * 1024).
	ResourceMemory MetricName = "memory"
)

// CPUAmountFromCores converts CPU cores to a ResourceAmount.
func CPUAmountFromCores(cores float64) ResourceAmount {
	return ResourceAmount(cores * 1000.0)
}

// CoresFromCPUAmount converts ResourceAmount to number of cores expressed as float64.
func CoresFromCPUAmount(cpuAmount ResourceAmount) float64 {
	return float64(cpuAmount) / 1000.0
}

// QuantityFromCPUAmount converts CPU ResourceAmount to a resource.Quantity.
func QuantityFromCPUAmount(cpuAmount ResourceAmount) resource.Quantity {
	return *resource.NewScaledQuantity(int64(cpuAmount), -3)
}

// MemoryAmountFromBytes converts memory bytes to a ResourceAmount.
func MemoryAmountFromBytes(bytes float64) ResourceAmount {
	return ResourceAmount(bytes)
}

// BytesFromMemoryAmount converts ResourceAmount to number of bytes expressed as float64.
func BytesFromMemoryAmount(memoryAmount ResourceAmount) float64 {
	return float64(memoryAmount)
}

// QuantityFromMemoryAmount converts memory ResourceAmount to a resource.Quantity.
func QuantityFromMemoryAmount(memoryAmount ResourceAmount) resource.Quantity {
	return *resource.NewScaledQuantity(int64(memoryAmount), 0)
}

// ResourcesAsResourceList converts internal Resources representation to ResourcesList.
func ResourcesAsResourceList(resources Resources) apiv1.ResourceList {
	result := make(apiv1.ResourceList)
	for key, resourceAmount := range resources {
		var newKey apiv1.ResourceName
		var quantity resource.Quantity
		switch key {
		case ResourceCPU:
			newKey = apiv1.ResourceCPU
			quantity = QuantityFromCPUAmount(resourceAmount)
		case ResourceMemory:
			newKey = apiv1.ResourceMemory
			quantity = QuantityFromMemoryAmount(resourceAmount)
		default:
			glog.Errorf("Cannot translate %v resource name", key)
			continue
		}
		result[newKey] = quantity
	}
	return result
}

// PodID contains information needed to identify a Pod within a cluster.
type PodID struct {
	// Namespaces where the Pod is defined.
	Namespace string
	// PodName is the name of the pod unique within a namespace.
	PodName string
}

// ContainerID contains information needed to identify a Container within a cluster.
type ContainerID struct {
	PodID
	// ContainerName is the name of the container, unique within a pod.
	ContainerName string
}

// VpaID contains information needed to identify a VPA API object within a cluster.
type VpaID struct {
	Namespace string
	VpaName   string
}

// ContainerMetricsSnapshot contains information about usage of certain container within defined time window.
type ContainerMetricsSnapshot struct {
	// ID identifies a specific container those metrics are coming from.
	ID ContainerID
	// End time of the measurement interval.
	SnapshotTime time.Time
	// Duration of the measurement interval, which is [SnapshotTime - SnapshotWindow, SnapshotTime].
	SnapshotWindow time.Duration
	// Actual usage of the resources over the measurement interval.
	Usage Resources
}

// BasicPodSpec contains basic information defining a pod and its containers.
type BasicPodSpec struct {
	// ID identifies a pod within a cluster.
	ID PodID
	// Labels of the pod. It is used to match pods with certain VPA opjects.
	PodLabels map[string]string
	// List of containers within this pod.
	Containers []BasicContainerSpec
}

// BasicContainerSpec contains basic information defining a container.
type BasicContainerSpec struct {
	// ID identifies the container within a cluster.
	ID ContainerID
	// Name of the image running within the container.
	Image string
	// Currently requested resources for this container.
	Request Resources
}
<|endoftext|>


<commit_before>// Package avl contains an implmentation of an AVL tree that contains []byte
// keys.
package avl

import (
	"bytes"
	"sync"
)

// New returns a new AVL Tree structure.
func New() *Tree {
	return &Tree{mu: &sync.Mutex{}}
}

// Tree is AVL tree designed to store slices of bytes.
type Tree struct {
	Head *Node
	mu   *sync.Mutex
}

// Insert adds the value to the tree.
func (t *Tree) Insert(b []byte) {
	defer t.mu.Unlock()
	t.mu.Lock()

	t.Head = t.Head.insert(b)
}

// Search returns the node of the tree with the value given, otherwise nil.
func (t *Tree) Search(b []byte) *Node {
	defer t.mu.Unlock()
	t.mu.Lock()
	n := t.Head
	for n != nil {
		switch bytes.Compare(b, n.Val) {
		case -1:
			n = n.Left
		case 0:
			return n
		case 1:
			n = n.Right
		}
	}
	return nil
}

// Delete removes the node of the tree with the value of b.  It reports if the
// value existed in the tree.
func (t *Tree) Delete(b []byte) {
	defer t.mu.Unlock()
	t.mu.Lock()

	t.Head = t.Head.delete(b)
}

// Node is a node in the AVL tree.
type Node struct {
	Val    []byte
	Left   *Node
	Right  *Node
	height int
}

// Height returns the height of this node's subtree, zero if n is nil.
func (n *Node) Height() int {
	if n == nil {
		return 0
	}
	return n.height
}

// insert inserts a node with the given value into the tree and returns the
// value that should be used as this subtree's root.
func (n *Node) insert(b []byte) *Node {
	if n == nil {
		return &Node{Val: b, height: 1}
	}

	switch bytes.Compare(b, n.Val) {
	case -1:
		n.Left = n.Left.insert(b)
	case 0, 1:
		n.Right = n.Right.insert(b)
	}
	return n.rebalance()
}

// delete finds the given node in the tree and deletes it, returning the Node
// that should replace it in the tree above.
func (n *Node) delete(b []byte) *Node {
	if n == nil {
		return nil
	}

	switch bytes.Compare(b, n.Val) {
	case -1:
		n.Left = n.Left.delete(b)
		n.rebalance()
		return n
	case 1:
		n.Right = n.Right.delete(b)
		n.rebalance()
		return n
	}
	// case 0
	if n.Left == nil {
		// don't need to rebalance here since n.Right isn't actually changing
		// and thus should still be balanced.
		return n.Right
	}

	// We're going to replace n with the minimal node from the right subtree
	// (and then n drops into garbage collection).
	min := findMin(n.Right)
	min.Right = removeMin(n.Right)
	min.Left = n.Left

	// return min or however the subtree under min rebalances.
	return min.rebalance()
}

// findmind returns the node with minimal key in n's subtree
func findMin(n *Node) *Node {
	for n.Left != nil {
		n = n.Left
	}
	return n
}

// removeMin removes the minimal (leftmost) node in this tree and then returns
// the tree that remains.
func removeMin(n *Node) *Node {
	if n.Left == nil {
		return n.Right
	}
	n.Left = removeMin(n.Left)
	return n.rebalance()
}

// rebalance rotates this tree if needed to regain balance, and returns the node
// that should replace this node in the tree above.
func (n *Node) rebalance() *Node {
	n.setHeight()
	// Since we constantly rebalance, we should only ever be at a max of +2 or
	// -2.
	switch n.balFactor() {
	case 2:
		if n.Right.balFactor() < 0 {
			// will need a right/left rotate
			n.Right = n.Right.rotateRight()
		}
		return n.rotateLeft()
	case -2:
		if n.Left.balFactor() > 0 {
			// will need a left/right rotate
			n.Left = n.Left.rotateLeft()
		}
		return n.rotateRight()
	default:
		// -1, 0, 1: already balanced
		return n
	}
}

func (n *Node) balFactor() int {
	if n == nil {
		return 0
	}
	return n.Right.Height() - n.Left.Height()
}

func (n *Node) setHeight() {
	n.height = max(n.Left.Height(), n.Right.Height()) + 1
}

// rotateRight rotates the tree under the given node right, returning the node
// that should replace this node's spot.
func (n *Node) rotateRight() *Node {
	// store our new root
	l := n.Left
	n.Left = l.Right
	l.Right = n
	n.setHeight()
	l.setHeight()
	return l
}

// rotateLeft rotates the tree under the given node left, returning the node
// that should replace this node in the tree above.
func (n *Node) rotateLeft() *Node {
	// store our new root
	r := n.Right
	n.Right = r.Left
	r.Left = n
	n.setHeight()
	r.setHeight()
	return r
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}
<commit_msg>fix godoc<commit_after>// Package avl contains an implmentation of an AVL tree that contains []byte
// keys.
package avl

import (
	"bytes"
	"sync"
)

// New returns a new AVL Tree structure.
func New() *Tree {
	return &Tree{mu: &sync.Mutex{}}
}

// Tree is AVL tree designed to store slices of bytes.
type Tree struct {
	Head *Node
	mu   *sync.Mutex
}

// Insert adds the value to the tree.
func (t *Tree) Insert(b []byte) {
	defer t.mu.Unlock()
	t.mu.Lock()

	t.Head = t.Head.insert(b)
}

// Search returns the node of the tree with the value given, otherwise nil.
func (t *Tree) Search(b []byte) *Node {
	defer t.mu.Unlock()
	t.mu.Lock()
	n := t.Head
	for n != nil {
		switch bytes.Compare(b, n.Val) {
		case -1:
			n = n.Left
		case 0:
			return n
		case 1:
			n = n.Right
		}
	}
	return nil
}

// Delete removes the node of the tree with the value of b.
func (t *Tree) Delete(b []byte) {
	defer t.mu.Unlock()
	t.mu.Lock()

	t.Head = t.Head.delete(b)
}

// Node is a node in the AVL tree.
type Node struct {
	Val    []byte
	Left   *Node
	Right  *Node
	height int
}

// Height returns the height of this node's subtree, zero if n is nil.
func (n *Node) Height() int {
	if n == nil {
		return 0
	}
	return n.height
}

// insert inserts a node with the given value into the tree and returns the
// value that should be used as this subtree's root.
func (n *Node) insert(b []byte) *Node {
	if n == nil {
		return &Node{Val: b, height: 1}
	}

	switch bytes.Compare(b, n.Val) {
	case -1:
		n.Left = n.Left.insert(b)
	case 0, 1:
		n.Right = n.Right.insert(b)
	}
	return n.rebalance()
}

// delete finds the given node in the tree and deletes it, returning the Node
// that should replace it in the tree above.
func (n *Node) delete(b []byte) *Node {
	if n == nil {
		return nil
	}

	switch bytes.Compare(b, n.Val) {
	case -1:
		n.Left = n.Left.delete(b)
		n.rebalance()
		return n
	case 1:
		n.Right = n.Right.delete(b)
		n.rebalance()
		return n
	}
	// case 0
	if n.Left == nil {
		// don't need to rebalance here since n.Right isn't actually changing
		// and thus should still be balanced.
		return n.Right
	}

	// We're going to replace n with the minimal node from the right subtree
	// (and then n drops into garbage collection).
	min := findMin(n.Right)
	min.Right = removeMin(n.Right)
	min.Left = n.Left

	// return min or however the subtree under min rebalances.
	return min.rebalance()
}

// findmind returns the node with minimal key in n's subtree
func findMin(n *Node) *Node {
	for n.Left != nil {
		n = n.Left
	}
	return n
}

// removeMin removes the minimal (leftmost) node in this tree and then returns
// the tree that remains.
func removeMin(n *Node) *Node {
	if n.Left == nil {
		return n.Right
	}
	n.Left = removeMin(n.Left)
	return n.rebalance()
}

// rebalance rotates this tree if needed to regain balance, and returns the node
// that should replace this node in the tree above.
func (n *Node) rebalance() *Node {
	n.setHeight()
	// Since we constantly rebalance, we should only ever be at a max of +2 or
	// -2.
	switch n.balFactor() {
	case 2:
		if n.Right.balFactor() < 0 {
			// will need a right/left rotate
			n.Right = n.Right.rotateRight()
		}
		return n.rotateLeft()
	case -2:
		if n.Left.balFactor() > 0 {
			// will need a left/right rotate
			n.Left = n.Left.rotateLeft()
		}
		return n.rotateRight()
	default:
		// -1, 0, 1: already balanced
		return n
	}
}

func (n *Node) balFactor() int {
	if n == nil {
		return 0
	}
	return n.Right.Height() - n.Left.Height()
}

func (n *Node) setHeight() {
	n.height = max(n.Left.Height(), n.Right.Height()) + 1
}

// rotateRight rotates the tree under the given node right, returning the node
// that should replace this node's spot.
func (n *Node) rotateRight() *Node {
	// store our new root
	l := n.Left
	n.Left = l.Right
	l.Right = n
	n.setHeight()
	l.setHeight()
	return l
}

// rotateLeft rotates the tree under the given node left, returning the node
// that should replace this node in the tree above.
func (n *Node) rotateLeft() *Node {
	// store our new root
	r := n.Right
	n.Right = r.Left
	r.Left = n
	n.setHeight()
	r.setHeight()
	return r
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}
<|endoftext|>


<commit_before>// Package for dealing with bag structures.
package bagins

import (
	"errors"
	"fmt"
	"github.com/APTrust/bagins/bagutil"
	"os"
	"path"
)

// Basic type referencing main elements of a bag.
type Bag struct {
	pth       string // the bag is under.
	payload   *Payload
	manifests map[string]*Manifest
	tagfiles  map[string]*TagFile
	cs        *bagutil.ChecksumAlgorithm
}

// Creates a new bag in the provided location and name.  Returns an error
// if the location does not exist or if the bag does already exist.
func NewBag(location string, name string, cs *bagutil.ChecksumAlgorithm) (*Bag, error) {
	// Start with creating the directories.
	bagPath := path.Join(location, name)
	err := os.Mkdir(bagPath, 0755)
	if err != nil {
		return nil, err
	}
	err = os.Mkdir(path.Join(bagPath, "/data/"), 0755)
	if err != nil {
		return nil, err
	}

	// Create the bag object.
	bag := new(Bag)
	defer bag.Close()
	bag.pth = bagPath
	bag.cs = cs
	bag.manifests = make(map[string]*Manifest)
	bag.manifests[cs.Name()], err = NewManifest(bag.Path(), cs)
	if err != nil {
		return nil, err
	}
	bag.tagfiles = make(map[string]*TagFile)

	bag.payload, err = NewPayload(location)
	if err != nil {
		return nil, err
	}
	tf, err := bag.createBagItFile()
	if err != nil {
		return nil, err
	}
	bag.tagfiles["bagit"] = tf

	return bag, nil
}

// Creates the required bagit.txt file as per the specification
// http://tools.ietf.org/html/draft-kunze-bagit-09#section-2.1.1
func (b *Bag) createBagItFile() (*TagFile, error) {
	bagit, err := NewTagFile(path.Join(b.Path(), "bagit.txt"))
	if err != nil {
		return nil, err
	}
	bagit.Data["BagIt-Version"] = "0.97"
	bagit.Data["Tag-File-Character-Encoding"] = "UTF-8"
	return bagit, nil
}

// Adds a file to the bag payload and adds the generated checksum to the
// manifest.
func (b *Bag) PackFile(src string, dst string) error {
	return errors.New("Not implemented")
}

// Performans a Bag.Add on all files found under the src location including all
// subdirectories.
func (b *Bag) PackDir(src string) (errs []error) {
	data, errs := b.payload.AddAll(src, b.cs.Algo())
	if mf, err := b.Manifest(); err != nil {
		errs = append(errs, err)
	} else {
		for key := range data {
			mf.Data[key] = data[key]
		}
	}

	return errs
}

func (b *Bag) AddManifest(algo string) error {
	return errors.New("Not implemented")
}

func (b *Bag) AddTagfile(name string) error {
	return errors.New("Not implemented")
}

// Returns the data fields for the baginfo.txt tag file in key, value pairs.
func (b *Bag) BagInfo() (*TagFile, error) {
	tf, err := b.TagFile(b.Path() + "bag-info")
	if err != nil {
		return nil, err
	}
	return tf, nil
}

func (b *Bag) TagFile(name string) (*TagFile, error) {
	if tf, ok := b.tagfiles[name]; ok {
		return tf, nil
	}
	return nil, fmt.Errorf("Unable to find tagfile %s", name)
}

func (b *Bag) Manifest() (*Manifest, error) {
	mf, err := b.ManifestFile(b.cs.Name())
	if err != nil {
		return nil, err
	}
	return mf, nil
}

func (b *Bag) ManifestFile(algo string) (*Manifest, error) {
	if mf, ok := b.manifests[algo]; ok {
		return mf, nil
	}
	return nil, fmt.Errorf("Unable to find manifest-%s.txt", algo)
}

func (b *Bag) Path() string {
	return b.pth
}

// This method writes all the relevant tag and manifest files to finish off the
// bag.
func (b *Bag) Close() (errs []error) {

	// Write all the manifest files.
	for key := range b.manifests {
		if mf, err := b.ManifestFile(key); err != nil {
			errs = append(errs, err)
		} else {
			if err = mf.Create(); err != nil {
				errs = append(errs, err)
			}
		}

	}

	// TODO Write all the tag files.
	for key := range b.tagfiles {
		if tf, err := b.TagFile(key); err != nil {
			errs = append(errs, err)
		} else {
			if err = tf.Create(); err != nil {
				errs = append(errs, err)
			}
		}
	}
	return
}
<commit_msg>Marked up some ToDos.<commit_after>// Package for dealing with bag structures.
package bagins

import (
	"errors"
	"fmt"
	"github.com/APTrust/bagins/bagutil"
	"os"
	"path"
)

// Basic type referencing main elements of a bag.
type Bag struct {
	pth       string // the bag is under.
	payload   *Payload
	manifests map[string]*Manifest
	tagfiles  map[string]*TagFile
	cs        *bagutil.ChecksumAlgorithm
}

// Creates a new bag in the provided location and name.  Returns an error
// if the location does not exist or if the bag does already exist.
func NewBag(location string, name string, cs *bagutil.ChecksumAlgorithm) (*Bag, error) {
	// Start with creating the directories.
	bagPath := path.Join(location, name)
	err := os.Mkdir(bagPath, 0755)
	if err != nil {
		return nil, err
	}
	err = os.Mkdir(path.Join(bagPath, "/data/"), 0755)
	if err != nil {
		return nil, err
	}

	// Create the bag object.
	bag := new(Bag)
	defer bag.Close()
	bag.pth = bagPath
	bag.cs = cs
	bag.manifests = make(map[string]*Manifest)
	bag.manifests[cs.Name()], err = NewManifest(bag.Path(), cs)
	if err != nil {
		return nil, err
	}
	bag.tagfiles = make(map[string]*TagFile)

	bag.payload, err = NewPayload(location)
	if err != nil {
		return nil, err
	}
	tf, err := bag.createBagItFile()
	if err != nil {
		return nil, err
	}
	bag.tagfiles["bagit"] = tf

	// TODO initiate a baginfo.txt file as well, even if it's blank.

	return bag, nil
}

// Creates the required bagit.txt file as per the specification
// http://tools.ietf.org/html/draft-kunze-bagit-09#section-2.1.1
func (b *Bag) createBagItFile() (*TagFile, error) {
	bagit, err := NewTagFile(path.Join(b.Path(), "bagit.txt"))
	if err != nil {
		return nil, err
	}
	bagit.Data["BagIt-Version"] = "0.97"
	bagit.Data["Tag-File-Character-Encoding"] = "UTF-8"
	return bagit, nil
}

// Adds a file to the bag payload and adds the generated checksum to the
// manifest.
func (b *Bag) PackFile(src string, dst string) error {
	return errors.New("Not implemented")
}

// Performans a Bag.Add on all files found under the src location including all
// subdirectories.
func (b *Bag) PackDir(src string) (errs []error) {
	data, errs := b.payload.AddAll(src, b.cs.Algo())
	if mf, err := b.Manifest(); err != nil {
		errs = append(errs, err)
	} else {
		for key := range data {
			mf.Data[key] = data[key]
		}
	}

	return errs
}

func (b *Bag) AddManifest(algo string) error {
	return errors.New("Not implemented")
}

func (b *Bag) AddTagfile(name string) error {
	return errors.New("Not implemented")
}

// Returns the data fields for the baginfo.txt tag file in key, value pairs.
func (b *Bag) BagInfo() (*TagFile, error) {
	tf, err := b.TagFile(b.Path() + "bag-info")
	if err != nil {
		return nil, err
	}
	return tf, nil
}

func (b *Bag) TagFile(name string) (*TagFile, error) {
	if tf, ok := b.tagfiles[name]; ok {
		return tf, nil
	}
	return nil, fmt.Errorf("Unable to find tagfile %s", name)
}

func (b *Bag) Manifest() (*Manifest, error) {
	mf, err := b.ManifestFile(b.cs.Name())
	if err != nil {
		return nil, err
	}
	return mf, nil
}

func (b *Bag) ManifestFile(algo string) (*Manifest, error) {
	if mf, ok := b.manifests[algo]; ok {
		return mf, nil
	}
	return nil, fmt.Errorf("Unable to find manifest-%s.txt", algo)
}

func (b *Bag) Path() string {
	return b.pth
}

// This method writes all the relevant tag and manifest files to finish off the
// bag.
func (b *Bag) Close() (errs []error) {

	// Write all the manifest files.
	for key := range b.manifests {
		if mf, err := b.ManifestFile(key); err != nil {
			errs = append(errs, err)
		} else {
			if err = mf.Create(); err != nil {
				errs = append(errs, err)
			}
		}

	}

	// TODO Write all the tag files.
	for key := range b.tagfiles {
		if tf, err := b.TagFile(key); err != nil {
			errs = append(errs, err)
		} else {
			if err = tf.Create(); err != nil {
				errs = append(errs, err)
			}
		}
	}
	return
}
<|endoftext|>


<commit_before>package uiprogress

var (
	// Fill is the default character representing completed progress
	Fill byte = '='

	// Head is the default character that moves when progress is updated
	Head byte = '>'

	// Empty is the default character that represents the empty progress
	Empty byte = '-'

	// LeftEnd is the default character in the left most part of the progress indicator
	LeftEnd byte = '['

	// RightEnd is the default character in the right most part of the progress indicator
	RightEnd byte = ']'

	// Width is the default width of the progress bar
	Width = 70

	// ErrMaxCurrentReached is error when trying to set current value that exceeds the total value
	// ErrMaxCurrentReached = errors.New("errors: current value is greater total value")
)

// Bar represents a progress bar
type Bar struct {
	// total of the total  for the progress bar
	total int

	// LeftEnd is character in the left most part of the progress indicator. Defaults to '['
	LeftEnd byte

	// RightEnd is character in the right most part of the progress indicator. Defaults to ']'
	RightEnd byte

	// Fill is the character representing completed progress. Defaults to '='
	Fill byte

	// Head is the character that moves when progress is updated.  Defaults to '>'
	Head byte

	// Empty is the character that represents the empty progress. Default is '-'
	Empty byte

	// Width is the width of the progress bar
	Width int

	currentUpdateCh chan int

	redrawRequestCh chan *redrawRequest

	// appendFuncs  []DecoratorFunc
	// prependFuncs []DecoratorFunc
}

// DecoratorFunc is a function that can be prepended and appended to the progress bar
type DecoratorFunc func(b *Bar) string

// NewBar returns a new progress bar
func NewBar(total int) *Bar {
	b := &Bar{
		total:           total,
		Width:           Width,
		LeftEnd:         LeftEnd,
		RightEnd:        RightEnd,
		Head:            Head,
		Fill:            Fill,
		Empty:           Empty,
		currentUpdateCh: make(chan int),
		redrawRequestCh: make(chan *redrawRequest),
	}
	go b.server()
	return b
}

type redrawRequest struct {
	bufch chan []byte
}

func (b *Bar) Update(n int) {
	b.currentUpdateCh <- n
}

// String returns the string representation of the bar
func (b *Bar) String() string {
	bufch := make(chan []byte)
	b.redrawRequestCh <- &redrawRequest{bufch}
	return string(<-bufch)
}

func (b *Bar) server() {
	var current int
	// blockStartTime := time.Now()
	// timePerItemEstimate time.Duration
	// remainingTime       time.Duration
	for {
		select {
		case n := <-b.currentUpdateCh:
			if n > b.total {
				return
			}
			current = n
			// fmt.Printf("current = %+v\n", current)
			// blockStartTime = time.Now()
		case r := <-b.redrawRequestCh:
			r.bufch <- b.draw(current)
		}
	}
}

func (b *Bar) draw(current int) []byte {
	completedWidth := current * b.Width / b.total

	buf := make([]byte, b.Width)
	for i := 0; i < completedWidth; i++ {
		buf[i] = b.Fill
	}
	for i := completedWidth; i < b.Width; i++ {
		buf[i] = b.Empty
	}
	// set head bit
	if completedWidth > 0 && completedWidth < b.Width {
		buf[completedWidth-1] = b.Head
	}

	// set left and right ends bits
	buf[0], buf[len(buf)-1] = b.LeftEnd, b.RightEnd

	// render append functions to the right of the bar
	// for _, f := range b.appendFuncs {
	// 	pb = append(pb, ' ')
	// 	pb = append(pb, []byte(f(b))...)
	// }

	// render prepend functions to the left of the bar
	// for _, f := range b.prependFuncs {
	// 	args := []byte(f(b))
	// 	args = append(args, ' ')
	// 	pb = append(args, pb...)
	// }
	return buf
}

// CompletedPercent return the percent completed
// func (b *Bar) CompletedPercent() int {
// 	return int(100 * float64(b.current) / float64(b.Total))
// }

// AppendFunc runs the decorator function and renders the output on the right of the progress bar
// func (b *Bar) AppendFunc(f DecoratorFunc) *Bar {
// 	b.appendFuncs = append(b.appendFuncs, f)
// 	return b
// }

// PrependFunc runs decorator function and render the output left the progress bar
// func (b *Bar) PrependFunc(f DecoratorFunc) *Bar {
// 	b.prependFuncs = append(b.prependFuncs, f)
// 	return b
// }

// AppendCompleted appends the completion percent to the progress bar
// func (b *Bar) AppendCompleted() *Bar {
// 	b.AppendFunc(func(b *Bar) string {
// 		return b.CompletedPercentString()
// 	})
// 	return b
// }

// CompletedPercentString returns the formatted string representation of the completed percent
// func (b *Bar) CompletedPercentString() string {
// 	return fmt.Sprintf("%3d%%", b.CompletedPercent())
// }

// PrependElapsed prepends the time elapsed to the begining of the bar
// func (b *Bar) PrependElapsed() *Bar {
// 	b.PrependFunc(func(b *Bar) string {
// 		return strutil.PadLeft(b.TimeElapsedString(), 5, ' ')
// 	})
// 	return b
// }
<commit_msg>allocate bar's buffer once<commit_after>package uiprogress

var (
	// Fill is the default character representing completed progress
	Fill byte = '='

	// Head is the default character that moves when progress is updated
	Head byte = '>'

	// Empty is the default character that represents the empty progress
	Empty byte = '-'

	// LeftEnd is the default character in the left most part of the progress indicator
	LeftEnd byte = '['

	// RightEnd is the default character in the right most part of the progress indicator
	RightEnd byte = ']'

	// Width is the default width of the progress bar
	Width = 70

	// ErrMaxCurrentReached is error when trying to set current value that exceeds the total value
	// ErrMaxCurrentReached = errors.New("errors: current value is greater total value")
)

// Bar represents a progress bar
type Bar struct {
	// total of the total  for the progress bar
	total int

	// LeftEnd is character in the left most part of the progress indicator. Defaults to '['
	LeftEnd byte

	// RightEnd is character in the right most part of the progress indicator. Defaults to ']'
	RightEnd byte

	// Fill is the character representing completed progress. Defaults to '='
	Fill byte

	// Head is the character that moves when progress is updated.  Defaults to '>'
	Head byte

	// Empty is the character that represents the empty progress. Default is '-'
	Empty byte

	// Width is the width of the progress bar
	Width int

	currentUpdateCh chan int

	redrawRequestCh chan *redrawRequest

	// appendFuncs  []DecoratorFunc
	// prependFuncs []DecoratorFunc
}

// DecoratorFunc is a function that can be prepended and appended to the progress bar
type DecoratorFunc func(b *Bar) string

// NewBar returns a new progress bar
func NewBar(total int) *Bar {
	b := &Bar{
		total:           total,
		Width:           Width,
		LeftEnd:         LeftEnd,
		RightEnd:        RightEnd,
		Head:            Head,
		Fill:            Fill,
		Empty:           Empty,
		currentUpdateCh: make(chan int),
		redrawRequestCh: make(chan *redrawRequest),
	}
	go b.server()
	return b
}

type redrawRequest struct {
	bufch chan []byte
}

func (b *Bar) Update(n int) {
	b.currentUpdateCh <- n
}

// String returns the string representation of the bar
func (b *Bar) String() string {
	bufch := make(chan []byte)
	b.redrawRequestCh <- &redrawRequest{bufch}
	return string(<-bufch)
}

func (b *Bar) server() {
	var current int
	// blockStartTime := time.Now()
	// timePerItemEstimate time.Duration
	// remainingTime       time.Duration
	buf := make([]byte, b.Width)
	for {
		select {
		case n := <-b.currentUpdateCh:
			if n > b.total {
				return
			}
			current = n
			// fmt.Printf("current = %+v\n", current)
			// blockStartTime = time.Now()
		case r := <-b.redrawRequestCh:
			r.bufch <- b.draw(buf, current)
		}
	}
}

func (b *Bar) draw(buf []byte, current int) []byte {
	completedWidth := current * b.Width / b.total

	for i := 0; i < completedWidth; i++ {
		buf[i] = b.Fill
	}
	for i := completedWidth; i < b.Width; i++ {
		buf[i] = b.Empty
	}
	// set head bit
	if completedWidth > 0 && completedWidth < b.Width {
		buf[completedWidth-1] = b.Head
	}

	// set left and right ends bits
	buf[0], buf[len(buf)-1] = b.LeftEnd, b.RightEnd

	// render append functions to the right of the bar
	// for _, f := range b.appendFuncs {
	// 	pb = append(pb, ' ')
	// 	pb = append(pb, []byte(f(b))...)
	// }

	// render prepend functions to the left of the bar
	// for _, f := range b.prependFuncs {
	// 	args := []byte(f(b))
	// 	args = append(args, ' ')
	// 	pb = append(args, pb...)
	// }
	return buf
}

// CompletedPercent return the percent completed
// func (b *Bar) CompletedPercent() int {
// 	return int(100 * float64(b.current) / float64(b.Total))
// }

// AppendFunc runs the decorator function and renders the output on the right of the progress bar
// func (b *Bar) AppendFunc(f DecoratorFunc) *Bar {
// 	b.appendFuncs = append(b.appendFuncs, f)
// 	return b
// }

// PrependFunc runs decorator function and render the output left the progress bar
// func (b *Bar) PrependFunc(f DecoratorFunc) *Bar {
// 	b.prependFuncs = append(b.prependFuncs, f)
// 	return b
// }

// AppendCompleted appends the completion percent to the progress bar
// func (b *Bar) AppendCompleted() *Bar {
// 	b.AppendFunc(func(b *Bar) string {
// 		return b.CompletedPercentString()
// 	})
// 	return b
// }

// CompletedPercentString returns the formatted string representation of the completed percent
// func (b *Bar) CompletedPercentString() string {
// 	return fmt.Sprintf("%3d%%", b.CompletedPercent())
// }

// PrependElapsed prepends the time elapsed to the begining of the bar
// func (b *Bar) PrependElapsed() *Bar {
// 	b.PrependFunc(func(b *Bar) string {
// 		return strutil.PadLeft(b.TimeElapsedString(), 5, ' ')
// 	})
// 	return b
// }
<|endoftext|>