<commit_before>package main

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"os/exec"
	"sync"
	"time"

	"github.com/kamilsk/semaphore"
)

// Task holds required jobs for execution.
type Task struct {
	Capacity int
	Timeout  time.Duration
	Jobs     []Job
}

// AddJob sets ID to a job and adds it to the task.
func (t *Task) AddJob(job Job) {
	job.ID = fmt.Sprintf("#%d", len(t.Jobs)+1)
	t.Jobs = append(t.Jobs, job)
}

// Run executes all jobs.
func (t *Task) Run() <-chan Result {
	results := make(chan Result, len(t.Jobs))

	go func() {
		defer func() { close(results) }()

		sem := semaphore.New(t.Capacity)
		deadline := semaphore.Multiplex(
			semaphore.WithTimeout(t.Timeout),
			semaphore.WithSignal(os.Interrupt),
		)

		wg := &sync.WaitGroup{}
		for i := range t.Jobs {
			wg.Add(1)
			go func(job Job) {
				result := Result{
					Job:    job,
					Stdout: bytes.NewBuffer(make([]byte, 1024)),
					Stderr: bytes.NewBuffer(make([]byte, 1024)),
				}

				defer func() {
					results <- result
					wg.Done()
				}()

				releaser, err := sem.Acquire(deadline)
				if err != nil {
					result.Error = err
					return
				}
				defer releaser()

				if err := result.Fetch(); err != nil {
					result.Error = err
					return
				}
			}(t.Jobs[i])
		}
		wg.Wait()
	}()

	return results
}

// Job represents a command for execution.
type Job struct {
	ID   string
	Name string
	Args []string
}

// Run prepares command and executes it.
func (j Job) Run(stdout, stderr io.Writer) error {
	c := exec.Command(j.Name, j.Args...)
	c.Stdout, c.Stderr = stdout, stderr
	return c.Run()
}

// Result holds the job execution result.
type Result struct {
	Job            Job
	Error          error
	Stdout, Stderr *bytes.Buffer
}

// Fetch executes the job and fetches its result into buffers.
func (r Result) Fetch() error {
	return r.Job.Run(r.Stdout, r.Stderr)
}
<commit_msg>complete task.go from cmd/semaphore<commit_after>package main

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"os/exec"
	"strings"
	"sync"
	"time"

	"github.com/kamilsk/semaphore"
	"github.com/pkg/errors"
)

// Task holds required jobs for execution.
type Task struct {
	Capacity int
	Timeout  time.Duration
	Jobs     []Job
}

// AddJob sets ID to a job and adds it to the task.
func (t *Task) AddJob(job Job) {
	job.ID = fmt.Sprintf("#%d", len(t.Jobs)+1)
	t.Jobs = append(t.Jobs, job)
}

// Run executes all jobs.
func (t *Task) Run() <-chan Result {
	results := make(chan Result, len(t.Jobs))

	go func() {
		defer func() { close(results) }()

		sem := semaphore.New(t.Capacity)
		deadline := semaphore.Multiplex(
			semaphore.WithTimeout(t.Timeout),
			semaphore.WithSignal(os.Interrupt),
		)

		wg := &sync.WaitGroup{}
		for i := range t.Jobs {
			wg.Add(1)
			go func(job Job) {
				result := Result{
					Job:    job,
					Stdout: bytes.NewBuffer(make([]byte, 1024)),
					Stderr: bytes.NewBuffer(make([]byte, 1024)),
				}

				defer func() {
					results <- result
					wg.Done()
				}()

				release, err := sem.Acquire(deadline)
				if err != nil {
					result.Error = errors.WithMessage(err, "semaphore")
					return
				}
				defer release()

				if err := result.Fetch(); err != nil {
					result.Error = err
					return
				}
			}(t.Jobs[i])
		}
		wg.Wait()
	}()

	return results
}

// Job represents a command for execution.
type Job struct {
	ID   string
	Name string
	Args []string
}

// Format implements Formatter interface.
func (j Job) Format(s fmt.State, verb rune) {
	switch verb {
	case 'v':
		if s.Flag('+') {
			fmt.Fprintf(s, "%s %+v", j.String(), j.Args)
			return
		}
		fallthrough
	case 's':
		io.WriteString(s, j.String())
	case 'q':
		fmt.Fprintf(s, "`%s`", strings.Join(append([]string{j.String()}, j.Args...), " "))
	}
}

// String implements Stringer interface.
func (j Job) String() string {
	return j.Name + "#" + j.ID
}

// Run prepares command and executes it.
func (j Job) Run(stdout, stderr io.Writer) error {
	c := exec.Command(j.Name, j.Args...)
	c.Stdout, c.Stderr = stdout, stderr
	return errors.WithMessage(c.Run(), fmt.Sprintf("an error occurred while executing %q", j))
}

// Result holds the job execution result.
type Result struct {
	Job            Job
	Error          error
	Stdout, Stderr *bytes.Buffer
}

// Fetch executes the job and fetches its result into buffers.
func (r Result) Fetch() error {
	return errors.WithMessage(r.Job.Run(r.Stdout, r.Stderr), fmt.Sprintf("the job %s ended with error", r.Job))
}
<|endoftext|>


<commit_before>package com

import (
	"fmt"
	"log"
	"testing"

	. "github.com/smartystreets/goconvey/convey"
)

func TestQuery(t *testing.T) {
	err := InitIP2Region("ip2region.db")
	if err != nil {
		log.Println(err)
	}

	Convey("func Query()", t, func() {
		Convey("correct", func() {
			ip, err := Query([]string{"127.0.0.1", "119.75.218.70"}, "memory")
			fmt.Println(ip, err)
		})
	})
}

// func BenchmarkMapMerge(b *testing.B) {
// 	Convey("bench Query()", b, func() {
// 		for i := 0; i < b.N; i++ {
// 			mapmerge()
// 		}
// 	})
// }
<commit_msg>fix test case<commit_after>package com

import (
	"log"
	"testing"

	. "github.com/smartystreets/goconvey/convey"
)

func TestQuery(t *testing.T) {
	err := InitIP2Region("ip2region.db")
	if err != nil {
		log.Println(err)
	}

	Convey("func Query()", t, func() {
		Convey("correct", func() {
			ip, err := Query([]string{"127.0.0.1", "119.75.218.70"}, "memory")
			So(err, ShouldBeNil)
			So(ip, ShouldNotBeNil)
		})
	})
}
<|endoftext|>


<commit_before>package command

import (
	"bufio"
	"errors"
	"flag"
	"fmt"
	"os"
	"os/signal"
	"strings"

	"github.com/awslabs/aws-sdk-go/service/rds"

	"github.com/uchimanajet7/rds-try/utils"
)

type RmCommand struct {
	*Command
	OptSnap  bool
	OptForce bool
	OptItem  string
}

var ErrInterruptedAskDelete = errors.New("OS Interrupted Ask Delete")

func (c *RmCommand) Help() string {
	// to-do: removal of the fixed value
	help_text := fmt.Sprintf("\nUsage: %s rm [options]\n\n", utils.GetAppName())
	help_text += "Options:\n"
	help_text += "  -s, --snap   list up own db snapshots\n"
	help_text += "  -f, --force  forced delete without confirmation\n"

	return help_text
}

func (c *RmCommand) Synopsis() string {
	return "delete your created db instances and snapshots"
}

func (c *RmCommand) Run(args []string) int {
	log.Infof("start command : rm")

	// reset flag
	fs := flag.NewFlagSet("rm", flag.ExitOnError)

	// register flag name
	fs.BoolVar(&c.OptSnap, "snap", false, "include own db snapshots to delete")
	fs.BoolVar(&c.OptSnap, "s", false, "include own db snapshots to delete")
	fs.BoolVar(&c.OptForce, "force", false, "forced delete without confirmation")
	fs.BoolVar(&c.OptForce, "f", false, "forced delete without confirmation")

	fs.Usage = func() { fmt.Println(c.Help()) }
	err := fs.Parse(args)
	if err != nil {
		log.Errorf("%s", err.Error())
		return 1
	}

	err = c.runDetails(fs)
	if err != nil {
		log.Errorf("%s", err.Error())
		return 1
	}
	log.Infof("end command : rm")

	return 0
}

func (c *RmCommand) runDetails(f *flag.FlagSet) error {
	// to get list created in this tool
	db_list, err := c.DescribeDBInstancesByTags()
	if err != nil {
		return err
	}
	ask_flg := true

	// show db list
	if len(db_list) <= 0 {
		ask_flg = false
		fmt.Printf("\ndb instance list not exist\n")
	} else {
		fmt.Printf("\nlist of own db instance\n")
		for i, db := range db_list {
			fmt.Printf("  [% d] DB Instance: %s\n", i+1, *db.DBInstanceIdentifier)
		}
	}
	// blank new line
	fmt.Println("")

	var snap_list []*rds.DBSnapshot
	if c.OptSnap {
		// to get list created in this tool
		snap_list, err = c.DescribeDBSnapshotsByTags()
		if err != nil {
			return err
		}

		// show snapshot list
		if len(snap_list) <= 0 {
			ask_flg = false
			fmt.Printf("db snapshot list not exist\n")
		} else {
			fmt.Printf("list of own db snapshot\n")
			for i, snap := range snap_list {
				fmt.Printf("  [% d] DB Snapshot: %s\n", i+1, *snap.DBSnapshotIdentifier)
			}
		}
		// blank new line
		fmt.Println("")
	}

	// list does not exist
	if !ask_flg {
		return nil
	}

	// confirm delete
	var ask_resp string
	if c.OptForce {
		ask_resp = "yes"
	} else {
		ask_resp, err = askQuestion("you want to delete all of those? [y/n]:")
		if err != nil {
			log.Errorf("%s", err.Error())
			return err
		}
	}
	// blank new line
	fmt.Println("")

	switch ask_resp {
	case "y", "Y", "yes", "YES", "Yes":
		// delete db instance
		err = c.DeleteDBResources(db_list)
		if err != nil {
			return err
		}
		// delete db snapshot
		if c.OptSnap {
			err = c.DeleteDBResources(snap_list)
			if err != nil {
				return err
			}
		}
	}

	return nil
}

// this method copied
// see also
// https://github.com/mitchellh/cli
func askQuestion(query string) (string, error) {
	// show query string
	fmt.Printf("%s ", query)

	// Register for interrupts so that we can catch it and immediately
	// return...
	sigCh := make(chan os.Signal, 1)
	signal.Notify(sigCh, os.Interrupt)
	defer signal.Stop(sigCh)

	// Ask for input in a go-routine so that we can ignore it.
	errCh := make(chan error, 1)
	lineCh := make(chan string, 1)
	go func() {
		r := bufio.NewReader(os.Stdin)
		line, err := r.ReadString('\n')
		if err != nil {
			errCh <- err
			return
		}

		lineCh <- strings.TrimRight(line, "\r\n")
	}()

	select {
	case err := <-errCh:
		return "", err
	case line := <-lineCh:
		return line, nil
	case <-sigCh:
		// Print a newline so that any further output starts properly
		// on a new line.
		fmt.Println("")

		return "", ErrInterruptedAskDelete
	}
}
<commit_msg>fixed condition of the delete confirmation<commit_after>package command

import (
	"bufio"
	"errors"
	"flag"
	"fmt"
	"os"
	"os/signal"
	"strings"

	"github.com/awslabs/aws-sdk-go/service/rds"

	"github.com/uchimanajet7/rds-try/utils"
)

type RmCommand struct {
	*Command
	OptSnap  bool
	OptForce bool
	OptItem  string
}

var ErrInterruptedAskDelete = errors.New("OS Interrupted Ask Delete")

func (c *RmCommand) Help() string {
	// to-do: removal of the fixed value
	help_text := fmt.Sprintf("\nUsage: %s rm [options]\n\n", utils.GetAppName())
	help_text += "Options:\n"
	help_text += "  -s, --snap   list up own db snapshots\n"
	help_text += "  -f, --force  forced delete without confirmation\n"

	return help_text
}

func (c *RmCommand) Synopsis() string {
	return "delete your created db instances and snapshots"
}

func (c *RmCommand) Run(args []string) int {
	log.Infof("start command : rm")

	// reset flag
	fs := flag.NewFlagSet("rm", flag.ExitOnError)

	// register flag name
	fs.BoolVar(&c.OptSnap, "snap", false, "include own db snapshots to delete")
	fs.BoolVar(&c.OptSnap, "s", false, "include own db snapshots to delete")
	fs.BoolVar(&c.OptForce, "force", false, "forced delete without confirmation")
	fs.BoolVar(&c.OptForce, "f", false, "forced delete without confirmation")

	fs.Usage = func() { fmt.Println(c.Help()) }
	err := fs.Parse(args)
	if err != nil {
		log.Errorf("%s", err.Error())
		return 1
	}

	err = c.runDetails(fs)
	if err != nil {
		log.Errorf("%s", err.Error())
		return 1
	}
	log.Infof("end command : rm")

	return 0
}

func (c *RmCommand) runDetails(f *flag.FlagSet) error {
	// to get list created in this tool
	db_list, err := c.DescribeDBInstancesByTags()
	if err != nil {
		return err
	}
	ask_flg := 0

	// show db list
	if len(db_list) <= 0 {
		fmt.Printf("\ndb instance list not exist\n")
	} else {
		ask_flg++
		fmt.Printf("\nlist of own db instance\n")
		for i, db := range db_list {
			fmt.Printf("  [% d] DB Instance: %s\n", i+1, *db.DBInstanceIdentifier)
		}
	}
	// blank new line
	fmt.Println("")

	var snap_list []*rds.DBSnapshot
	if c.OptSnap {
		// to get list created in this tool
		snap_list, err = c.DescribeDBSnapshotsByTags()
		if err != nil {
			return err
		}

		// show snapshot list
		if len(snap_list) <= 0 {
			fmt.Printf("db snapshot list not exist\n")
		} else {
			ask_flg++
			fmt.Printf("list of own db snapshot\n")
			for i, snap := range snap_list {
				fmt.Printf("  [% d] DB Snapshot: %s\n", i+1, *snap.DBSnapshotIdentifier)
			}
		}
		// blank new line
		fmt.Println("")
	}

	// list does not exist
	if ask_flg <= 0 {
		return nil
	}

	// confirm delete
	var ask_resp string
	if c.OptForce {
		ask_resp = "yes"
	} else {
		ask_resp, err = askQuestion("you want to delete all of those? [y/n]:")
		if err != nil {
			log.Errorf("%s", err.Error())
			return err
		}
	}
	// blank new line
	fmt.Println("")

	switch ask_resp {
	case "y", "Y", "yes", "YES", "Yes":
		// delete db instance
		err = c.DeleteDBResources(db_list)
		if err != nil {
			return err
		}
		// delete db snapshot
		if c.OptSnap {
			err = c.DeleteDBResources(snap_list)
			if err != nil {
				return err
			}
		}
	}

	return nil
}

// this method copied
// see also
// https://github.com/mitchellh/cli
func askQuestion(query string) (string, error) {
	// show query string
	fmt.Printf("%s ", query)

	// Register for interrupts so that we can catch it and immediately
	// return...
	sigCh := make(chan os.Signal, 1)
	signal.Notify(sigCh, os.Interrupt)
	defer signal.Stop(sigCh)

	// Ask for input in a go-routine so that we can ignore it.
	errCh := make(chan error, 1)
	lineCh := make(chan string, 1)
	go func() {
		r := bufio.NewReader(os.Stdin)
		line, err := r.ReadString('\n')
		if err != nil {
			errCh <- err
			return
		}

		lineCh <- strings.TrimRight(line, "\r\n")
	}()

	select {
	case err := <-errCh:
		return "", err
	case line := <-lineCh:
		return line, nil
	case <-sigCh:
		// Print a newline so that any further output starts properly
		// on a new line.
		fmt.Println("")

		return "", ErrInterruptedAskDelete
	}
}
<|endoftext|>


<commit_before>package commands

import (
	"github.com/bmizerany/assert"
	"regexp"
	"testing"
)

func TestTransformPushArgs(t *testing.T) {
	args := NewArgs([]string{"push", "origin,staging,qa", "bert_timeout"})
	transformPushArgs(args)
	cmds := args.Commands()

	assert.Equal(t, 3, len(cmds))
	assert.Equal(t, "git push origin bert_timeout", cmds[0].String())
	assert.Equal(t, "git push staging bert_timeout", cmds[1].String())

	args = NewArgs([]string{"push", "origin"})
	transformPushArgs(args)
	cmds = args.Commands()

	assert.Equal(t, 1, len(cmds))
	pushRegexp := regexp.MustCompile("git push origin .+")
	assert.T(t, pushRegexp.MatchString(cmds[0].String()))
}
<commit_msg>Disable TestTransformPushArgs<commit_after>package commands

import (
	"github.com/bmizerany/assert"
	"regexp"
	"testing"
)

func _TestTransformPushArgs(t *testing.T) {
	args := NewArgs([]string{"push", "origin,staging,qa", "bert_timeout"})
	transformPushArgs(args)
	cmds := args.Commands()

	assert.Equal(t, 3, len(cmds))
	assert.Equal(t, "git push origin bert_timeout", cmds[0].String())
	assert.Equal(t, "git push staging bert_timeout", cmds[1].String())

	args = NewArgs([]string{"push", "origin"})
	transformPushArgs(args)
	cmds = args.Commands()

	assert.Equal(t, 1, len(cmds))
	pushRegexp := regexp.MustCompile("git push origin .+")
	assert.T(t, pushRegexp.MatchString(cmds[0].String()))
}
<|endoftext|>


<commit_before>//  Copyright (c) 2014 Couchbase, Inc.
//  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 facets

import (
	"container/list"

	"github.com/blevesearch/bleve/index"
	"github.com/blevesearch/bleve/numeric_util"
	"github.com/blevesearch/bleve/search"
)

type numericRange struct {
	min *float64
	max *float64
}

type NumericFacetBuilder struct {
	size       int
	field      string
	termsCount map[string]int
	total      int
	missing    int
	ranges     map[string]*numericRange
}

func NewNumericFacetBuilder(field string, size int) *NumericFacetBuilder {
	return &NumericFacetBuilder{
		size:       size,
		field:      field,
		termsCount: make(map[string]int),
		ranges:     make(map[string]*numericRange, 0),
	}
}

func (fb *NumericFacetBuilder) AddRange(name string, min, max *float64) {
	r := numericRange{
		min: min,
		max: max,
	}
	fb.ranges[name] = &r
}

func (fb *NumericFacetBuilder) Update(ft index.FieldTerms) {
	terms, ok := ft[fb.field]
	if ok {
		for _, term := range terms {
			// only consider the values which are shifted 0
			prefixCoded := numeric_util.PrefixCoded(term)
			shift, err := prefixCoded.Shift()
			if err == nil && shift == 0 {
				i64, err := prefixCoded.Int64()
				if err == nil {
					f64 := numeric_util.Int64ToFloat64(i64)

					// look at each of the ranges for a match
					for rangeName, r := range fb.ranges {

						if (r.min == nil || f64 >= *r.min) && (r.max == nil || f64 < *r.max) {

							existingCount, existed := fb.termsCount[rangeName]
							if existed {
								fb.termsCount[rangeName] = existingCount + 1
							} else {
								fb.termsCount[rangeName] = 1
							}
							fb.total++
						}
					}
				}
			}
		}
	} else {
		fb.missing++
	}
}

func (fb *NumericFacetBuilder) Result() *search.FacetResult {
	rv := search.FacetResult{
		Field:   fb.field,
		Total:   fb.total,
		Missing: fb.missing,
	}

	// FIXME better implementation needed here this is quick and dirty
	topN := list.New()

	// walk entries and find top N
OUTER:
	for term, count := range fb.termsCount {
		numericRange := fb.ranges[term]
		tf := &search.NumericRangeFacet{
			Name:  term,
			Count: count,
			Min:   numericRange.min,
			Max:   numericRange.max,
		}

		for e := topN.Front(); e != nil; e = e.Next() {
			curr := e.Value.(*search.NumericRangeFacet)
			if tf.Count < curr.Count {

				topN.InsertBefore(tf, e)
				// if we just made the list too long
				if topN.Len() > fb.size {
					// remove the head
					topN.Remove(topN.Front())
				}
				continue OUTER
			}
		}
		// if we got to the end, we still have to add it
		topN.PushBack(tf)
		if topN.Len() > fb.size {
			// remove the head
			topN.Remove(topN.Front())
		}

	}

	// we now have the list of the top N facets
	rv.NumericRanges = make([]*search.NumericRangeFacet, topN.Len())
	i := 0
	notOther := 0
	for e := topN.Back(); e != nil; e = e.Prev() {
		rv.NumericRanges[i] = e.Value.(*search.NumericRangeFacet)
		i++
		notOther += e.Value.(*search.NumericRangeFacet).Count
	}
	rv.Other = fb.total - notOther

	return &rv
}
<commit_msg>Use sort.Sort for the numeric facet builder<commit_after>//  Copyright (c) 2014 Couchbase, Inc.
//  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 facets

import (
	"sort"

	"github.com/blevesearch/bleve/index"
	"github.com/blevesearch/bleve/numeric_util"
	"github.com/blevesearch/bleve/search"
)

type numericRange struct {
	min *float64
	max *float64
}

type NumericFacetBuilder struct {
	size       int
	field      string
	termsCount map[string]int
	total      int
	missing    int
	ranges     map[string]*numericRange
}

func NewNumericFacetBuilder(field string, size int) *NumericFacetBuilder {
	return &NumericFacetBuilder{
		size:       size,
		field:      field,
		termsCount: make(map[string]int),
		ranges:     make(map[string]*numericRange, 0),
	}
}

func (fb *NumericFacetBuilder) AddRange(name string, min, max *float64) {
	r := numericRange{
		min: min,
		max: max,
	}
	fb.ranges[name] = &r
}

func (fb *NumericFacetBuilder) Update(ft index.FieldTerms) {
	terms, ok := ft[fb.field]
	if ok {
		for _, term := range terms {
			// only consider the values which are shifted 0
			prefixCoded := numeric_util.PrefixCoded(term)
			shift, err := prefixCoded.Shift()
			if err == nil && shift == 0 {
				i64, err := prefixCoded.Int64()
				if err == nil {
					f64 := numeric_util.Int64ToFloat64(i64)

					// look at each of the ranges for a match
					for rangeName, r := range fb.ranges {

						if (r.min == nil || f64 >= *r.min) && (r.max == nil || f64 < *r.max) {

							existingCount, existed := fb.termsCount[rangeName]
							if existed {
								fb.termsCount[rangeName] = existingCount + 1
							} else {
								fb.termsCount[rangeName] = 1
							}
							fb.total++
						}
					}
				}
			}
		}
	} else {
		fb.missing++
	}
}

func (fb *NumericFacetBuilder) Result() *search.FacetResult {
	rv := search.FacetResult{
		Field:   fb.field,
		Total:   fb.total,
		Missing: fb.missing,
	}

	rv.NumericRanges = make([]*search.NumericRangeFacet, 0, len(fb.termsCount))

	for term, count := range fb.termsCount {
		numericRange := fb.ranges[term]
		tf := &search.NumericRangeFacet{
			Name:  term,
			Count: count,
			Min:   numericRange.min,
			Max:   numericRange.max,
		}

		rv.NumericRanges = append(rv.NumericRanges, tf)
	}

	sort.Sort(rv.NumericRanges)

	// we now have the list of the top N facets
	if fb.size < len(rv.NumericRanges) {
		rv.NumericRanges = rv.NumericRanges[:fb.size]
	}

	notOther := 0
	for _, nr := range rv.NumericRanges {
		notOther += nr.Count
	}
	rv.Other = fb.total - notOther

	return &rv
}
<|endoftext|>


<commit_before>package gogrs

import (
	"fmt"
	"testing"
	"time"
)

func TestStockRealTime(*testing.T) {
	r := &StockRealTime{
		No:        "2618",
		Timestamp: RandInt(),
		Date:      time.Now(),
	}
	r.URL()
	r.GetData()
}

func ExampleStockRealTime() {
	r := StockRealTime{
		No:        "2618",
		Timestamp: RandInt(),
		Date:      time.Date(2014, 12, 26, 0, 0, 0, 0, time.Local),
	}

	data, _ := r.GetData()
	fmt.Printf("%v", data)
}
<commit_msg>Tiny fixed import in realtime_stock_test.go<commit_after>package gogrs

import (
	"fmt"
	"testing"
	"time"

	"github.com/toomore/gogrs/utils"
)

func TestStockRealTime(*testing.T) {
	r := &StockRealTime{
		No:        "2618",
		Timestamp: utils.RandInt(),
		Date:      time.Now(),
	}
	r.URL()
	r.GetData()
}

func ExampleStockRealTime() {
	r := StockRealTime{
		No:        "2618",
		Timestamp: utils.RandInt(),
		Date:      time.Date(2014, 12, 26, 0, 0, 0, 0, time.Local),
	}

	data, _ := r.GetData()
	fmt.Printf("%v", data)
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"time"

	"private/routenplaner/src/src/common"
)

func (request *RouteRequest) expand(item *prioItem) {
	var prev *common.Node

	if item.node.ID == 2149039562 {
		fmt.Printf("y: %d", len(item.node.Neighbours))
	}

	for _, next_id := range item.node.Neighbours {
		if item.node.ID == 2149039562 {
			fmt.Printf("...auf %d...", next_id)
		}
		next := request.osm.Nodes.Get(next_id)

		if next == nil {
			fmt.Printf("Coulnd't find node %d\n", next_id)
			continue
		}

		// Schon besucht? Dann nächsten Knoten
		if _, has_visited := request.closedlist[next.ID]; has_visited {
			continue
		}
		request.closedlist[next.ID] = true

		// Vorgänger holen
		if item.prev != nil {
			prev = item.prev.node
		} else {
			prev = nil
		}

		// Weg von dem man kommt
		var prev_way *common.Way
		if prev != nil {
			// TODO: Hier ist verifier-node aktuell NIL, man müsste den prev vom
			// prev noch ermitteln
			prev_way = prev.CommonWay(nil, item.node, request.osm)
		}

		// Weg, den man nun einschlägt
		next_way := item.node.CommonWay(prev, next, request.osm)

		if prev != nil {
			//	fmt.Printf("%s -> %s [via: %d]\n", prev_way.Fullname(), next_way.Fullname(), item.node.ID)
		}

		// Hint-Manager erstellen für diesen Weg next_way
		hintMgr := newHintMgr(next_way)

		// Generelle Kosten für den Weg berechnen
		general_costs, allowed := profile_general(hintMgr, prev, item.node, next, prev_way, next_way, request)
		if !allowed {
			// Grundsätzlich nicht erlaubt, diese Kante zu nehmen (z. B. Abbiegebeschränkung)
			// WICHTIG!!!!!
			// Wenn das passiert, muss aber der Zielknoten (also next) nochmal freigegeben
			// werden. Es könnte ja sein, dass er Teil einer anderen Lösungsstrecke ist.
			fmt.Printf("not allowed from %d to %d\n", item.node.ID, next_id)
			delete(request.closedlist, next.ID)
			delete(request.g_values, next.ID)
			delete(request.prio_items, next.ID)
			continue
		}

		// Hole profilabhängige Kosten (z. B. fürs Fahrrad, Auto, usw.)
		profile_costs, allowed := request.costProfile(hintMgr, prev, item.node, next, prev_way, next_way, request)
		if !allowed {
			// Grundsätzlich nicht erlaubt, diese Kante zu nehmen (z. B. Abbiegebeschränkung)
			// WICHTIG!!!!!
			// Wenn das passiert, muss aber der Zielknoten (also next) nochmal freigegeben
			// werden. Es könnte ja sein, dass er Teil einer anderen Lösungsstrecke ist.
			fmt.Printf("not allowed\n")
			delete(request.closedlist, next.ID)
			delete(request.g_values, next.ID)
			delete(request.prio_items, next.ID)
			continue
		}
		// Vorläufiges g(next) und f(next) berechnen
		tentative_g := request.g_values[item.node.ID] + general_costs + profile_costs

		// Wir berechnen die Kosten in Fahrtzeit in Minuten
		// !ABHÄNGIG VOM PROFIL!
		var traveltime float64
		switch request.CostProfileText {
		case "car":
			traveltime = (distanceNodes(next, request.Destination) / STANDARD_CAR_SPEED) * 60 * 60 * 1000 // in millisekunden
		case "bike":
			traveltime = (distanceNodes(next, request.Destination) / STANDARD_BIKE_SPEED) * 60 * 60 * 1000 // in millisekunden
		default:
			panic("unspported profile")
		}
		f := tentative_g + int(traveltime+0.5) // 0.5, um es korrekt zu runden

		if item.node.ID == 2149039562 {
			fmt.Printf(" (%d / %.2f) ", f, float64(profile_costs)/1000.0)
		}

		// Kann man den aktuellen Knoten günstiger erreichen über item?
		if old_g, has_g := request.g_values[next.ID]; has_g {
			if old_g > tentative_g {
				// Besseren Weg zu diesem Knoten gefunden, g und prev+hint updaten
				request.g_values[next.ID] = tentative_g
				request.prio_items[next.ID].prev = item
				request.prio_items[next.ID].hint = hintMgr
				request.prio_items[next.ID].priority = f
				request.openlist.Notifiy(request.prio_items[next.ID]) // informiere OpenList über neuen Weert
			} else {
				// Kein besserer? Dann nächsten Knoten untersuchen
				continue
			}
		} else {
			// Knoten noch nicht bekannt? Einqueuen und eintragen
			request.prio_items[next.ID] = request.openlist.add(item, next, f, hintMgr)
			request.g_values[next.ID] = tentative_g
		}
	}
	if item.node.ID == 2149039562 {
		fmt.Printf("\n")
	}
}

const MAX_CALCULATION_TIME = time.Second * 3

func (request *RouteRequest) calculate() (*RouteResponse, error) {
	// TODO: Nicht 2 mal calculate() ausführen lassen

	request.calcuation_start = time.Now()
	request.openlist.add(nil, request.Departure, 0, nil)

	var next *prioItem
	for request.openlist.Len() > 0 {
		next = request.openlist.next()

		// TODO: An dieser Stelle auch Via berücksichtigen
		// 2 Optionen für Vias: Automatische Suche nach der besten Reihenfolge der Vias
		// oder Reihenfolge

		if next.node == request.Destination {
			// Ziel gefunden
			return makeRouteResponse(request, next), nil
		}

		request.expand(next)

		if time.Since(request.calcuation_start) > MAX_CALCULATION_TIME {
			return nil, errors.New("Calculation aborted, maximum calculation time exceeded")
		}
	}

	return nil, errors.New(fmt.Sprintf("No route found from %d to %d",
		request.Departure.ID, request.Destination.ID))
}
<commit_msg>Removed debug code<commit_after>package main

import (
	"errors"
	"fmt"
	"time"

	"private/routenplaner/src/src/common"
)

func (request *RouteRequest) expand(item *prioItem) {
	var prev *common.Node

	for _, next_id := range item.node.Neighbours {
		next := request.osm.Nodes.Get(next_id)

		if next == nil {
			fmt.Printf("Coulnd't find node %d\n", next_id)
			continue
		}

		// Schon besucht? Dann nächsten Knoten
		if _, has_visited := request.closedlist[next.ID]; has_visited {
			continue
		}
		request.closedlist[next.ID] = true

		// Vorgänger holen
		if item.prev != nil {
			prev = item.prev.node
		} else {
			prev = nil
		}

		// Weg von dem man kommt
		var prev_way *common.Way
		if prev != nil {
			// TODO: Hier ist verifier-node aktuell NIL, man müsste den prev vom
			// prev noch ermitteln
			prev_way = prev.CommonWay(nil, item.node, request.osm)
		}

		// Weg, den man nun einschlägt
		next_way := item.node.CommonWay(prev, next, request.osm)

		if prev != nil {
			//	fmt.Printf("%s -> %s [via: %d]\n", prev_way.Fullname(), next_way.Fullname(), item.node.ID)
		}

		// Hint-Manager erstellen für diesen Weg next_way
		hintMgr := newHintMgr(next_way)

		// Generelle Kosten für den Weg berechnen
		general_costs, allowed := profile_general(hintMgr, prev, item.node, next, prev_way, next_way, request)
		if !allowed {
			// Grundsätzlich nicht erlaubt, diese Kante zu nehmen (z. B. Abbiegebeschränkung)
			// WICHTIG!!!!!
			// Wenn das passiert, muss aber der Zielknoten (also next) nochmal freigegeben
			// werden. Es könnte ja sein, dass er Teil einer anderen Lösungsstrecke ist.
			fmt.Printf("not allowed from %d to %d\n", item.node.ID, next_id)
			delete(request.closedlist, next.ID)
			delete(request.g_values, next.ID)
			delete(request.prio_items, next.ID)
			continue
		}

		// Hole profilabhängige Kosten (z. B. fürs Fahrrad, Auto, usw.)
		profile_costs, allowed := request.costProfile(hintMgr, prev, item.node, next, prev_way, next_way, request)
		if !allowed {
			// Grundsätzlich nicht erlaubt, diese Kante zu nehmen (z. B. Abbiegebeschränkung)
			// WICHTIG!!!!!
			// Wenn das passiert, muss aber der Zielknoten (also next) nochmal freigegeben
			// werden. Es könnte ja sein, dass er Teil einer anderen Lösungsstrecke ist.
			fmt.Printf("not allowed\n")
			delete(request.closedlist, next.ID)
			delete(request.g_values, next.ID)
			delete(request.prio_items, next.ID)
			continue
		}
		// Vorläufiges g(next) und f(next) berechnen
		tentative_g := request.g_values[item.node.ID] + general_costs + profile_costs

		// Wir berechnen die Kosten in Fahrtzeit in Minuten
		// !ABHÄNGIG VOM PROFIL!
		var traveltime float64
		switch request.CostProfileText {
		case "car":
			traveltime = (distanceNodes(next, request.Destination) / STANDARD_CAR_SPEED) * 60 * 60 * 1000 // in millisekunden
		case "bike":
			traveltime = (distanceNodes(next, request.Destination) / STANDARD_BIKE_SPEED) * 60 * 60 * 1000 // in millisekunden
		default:
			panic("unspported profile")
		}
		f := tentative_g + int(traveltime+0.5) // 0.5, um es korrekt zu runden

		// Kann man den aktuellen Knoten günstiger erreichen über item?
		if old_g, has_g := request.g_values[next.ID]; has_g {
			if old_g > tentative_g {
				// Besseren Weg zu diesem Knoten gefunden, g und prev+hint updaten
				request.g_values[next.ID] = tentative_g
				request.prio_items[next.ID].prev = item
				request.prio_items[next.ID].hint = hintMgr
				request.prio_items[next.ID].priority = f
				request.openlist.Notifiy(request.prio_items[next.ID]) // informiere OpenList über neuen Weert
			} else {
				// Kein besserer? Dann nächsten Knoten untersuchen
				continue
			}
		} else {
			// Knoten noch nicht bekannt? Einqueuen und eintragen
			request.prio_items[next.ID] = request.openlist.add(item, next, f, hintMgr)
			request.g_values[next.ID] = tentative_g
		}
	}
}

const MAX_CALCULATION_TIME = time.Second * 3

func (request *RouteRequest) calculate() (*RouteResponse, error) {
	// TODO: Nicht 2 mal calculate() ausführen lassen

	request.calcuation_start = time.Now()
	request.openlist.add(nil, request.Departure, 0, nil)

	var next *prioItem
	for request.openlist.Len() > 0 {
		next = request.openlist.next()

		// TODO: An dieser Stelle auch Via berücksichtigen
		// 2 Optionen für Vias: Automatische Suche nach der besten Reihenfolge der Vias
		// oder Reihenfolge

		if next.node == request.Destination {
			// Ziel gefunden
			return makeRouteResponse(request, next), nil
		}

		request.expand(next)

		if time.Since(request.calcuation_start) > MAX_CALCULATION_TIME {
			return nil, errors.New("Calculation aborted, maximum calculation time exceeded")
		}
	}

	return nil, errors.New(fmt.Sprintf("No route found from %d to %d",
		request.Departure.ID, request.Destination.ID))
}
<|endoftext|>


<commit_before>package database

import (
	"bytes"
	"fmt"
	"github.com/SlyMarbo/rss"
	"io/ioutil"
	"math/rand"
	"net/http"
	sec "rs3/security"
	"sync"
	"time"
)

var db *database

func init() {
	rand.Seed(time.Now().UnixNano())
	db = newDatabase()
}

type User struct {
	Uid      []byte
	Pswrd    []byte
	Salt     *sec.Salt
	Nick     string
	Cookies  CookieJar
	Feeds    []*rss.Feed
	FeedUrls []string
	mutex    *sync.RWMutex
}

func newUser(uid, pwd []byte, salt *sec.Salt, nick string) *User {
	user := User{
		uid,
		pwd,
		salt,
		nick,
		make(CookieJar, 0),
		make([]*rss.Feed, 0),
		make([]string, 0),
		new(sync.RWMutex),
	}
	return &user
}

//256 rand number
type Cookie struct {
	exp     time.Time
	replace time.Time
	cookie  string
}

type CookieJar []Cookie

func newCookie() Cookie {
	var buf bytes.Buffer
	for i := 0; i < 5; i++ {
		buf.WriteString(fmt.Sprintf("%x", rand.Int63()))
	}
	cookie := Cookie{
		time.Now().Add(7 * 24 * time.Hour),
		time.Now().Add(14 * 24 * time.Hour),
		buf.String()[:256]}
	return cookie
}

type UserAlreadyExists struct{}

func (err UserAlreadyExists) Error() string {
	return "User ID Already Exists"
}

type UserDoesNotExist struct{}

func (err UserDoesNotExist) Error() string {
	return "User ID Does Not Exist"
}

type EmailAlreadyExists struct{}

func (err EmailAlreadyExists) Error() string {
	return "Email Already Exists"
}

type AuthenticationError struct{}

func (err AuthenticationError) Error() string {
	return "Authentication Failure, User ID or Password Incorrect"
}

type BackupFailure struct{}

func (err BackupFailure) Error() string {
	return "Failed to Backup Database"
}

type RestoreFailure struct{}

func (err RestoreFailure) Error() string {
	return "Failed to Restore Database"
}

type database struct {
	users  map[string]*User     //uid -> User
	salts  map[string]*sec.Salt //email -> Salt
	emails map[string]struct{}  //email -> null (for email existence check)
	mutex  *sync.RWMutex
}

type Database struct{}

// func NewDatabase() *Database
func newDatabase() *database {
	db := database{
		make(map[string]*User),
		make(map[string]*sec.Salt),
		make(map[string]struct{}),
		new(sync.RWMutex),
	}
	return &db
}

func Salt(email string) *sec.Salt {
	return db.salts[email]
}

//AddUser creates a new user and adds it to the database. It establishes that both the user
//does not exist and that their email is not in use
func AddUser(uid, pwd []byte, salt *sec.Salt, nick, email string) error {
	db.mutex.RLock()
	if _, ok := db.users[string(uid)]; ok {
		db.mutex.RUnlock()
		return new(UserAlreadyExists)
	}
	if _, ok := db.emails[string(uid)]; ok {
		db.mutex.RUnlock()
		return new(EmailAlreadyExists)
	}
	db.mutex.RUnlock()
	db.mutex.Lock()
	defer db.mutex.Unlock()
	user := newUser(uid, pwd, salt, nick)
	db.users[string(uid)] = user
	db.emails[email] = *new(struct{})
	return nil
}

//Delete user removes a user from the database provided they exist in the system
func DeleteUser(uid []byte) error {
	db.mutex.Lock()
	defer db.mutex.Unlock()
	if _, ok := db.users[string(uid)]; !ok {
		return new(UserDoesNotExist)
	}
	delete(db.users, string(uid))
	return nil
}

//Exists confirms whether or not a user exists in the system
func Exists(uid []byte) bool {
	db.mutex.RLock()
	defer db.mutex.RUnlock()
	_, ok := db.users[string(uid)]
	return ok
}

//Authenticate checks that the userID and password match.
func Authenticate(uid, pswd []byte) bool {
	db.mutex.RLock()
	defer db.mutex.RUnlock()
	user, ok := db.users[string(uid)]
	if !ok {
		return false
	} else {
		user.mutex.RLock()
		defer user.mutex.RUnlock()
		return (bytes.Compare(user.Pswrd, pswd) == 0)
	}
}

//Login logs a user into the system, returning the cookie string
//Authenticates the user first
//if user already has a valid cookie, returns that cookie as opposed to creating one
func Login(uid, pswd []byte) (string, time.Time, error) {
	db.mutex.RLock()
	defer db.mutex.RUnlock()
	if !Authenticate(uid, pswd) {
		return "", time.Now(), new(AuthenticationError)
	}
	user, ok := db.users[string(uid)]
	if !ok {
		return "", time.Now(), new(UserDoesNotExist)
	}
	if len(user.Cookies) != 0 {
		for i := 0; i < len(user.Cookies); i++ {
			if user.Cookies[i].exp.After(time.Now()) {
				return user.Cookies[i].cookie, user.Cookies[i].exp, nil
			}
		}
		c := newCookie()
		user.Cookies = append(user.Cookies, c)
		return c.cookie, c.exp, nil
	} else {
		user.Cookies = append(user.Cookies, newCookie())
		return user.Cookies[0].cookie, user.Cookies[0].exp, nil
	}
}

//Validate checks the cookie.
func Validate(cookie string, uid []byte) bool {
	db.mutex.RLock()
	defer db.mutex.RUnlock()
	user, ok := db.users[string(uid)]
	if !ok { //user does not exist
		return false
	}
	for _, uCookie := range user.Cookies {
		if uCookie.cookie == cookie {
			return true
		}
	}
	return false
}

//Nickname validates the cookie and returns the user's nickname
func Nickname(uid []byte, cookie string) (string, error) {
	if !Validate(cookie, uid) {
		return "", new(AuthenticationError)
	}
	db.mutex.RLock()
	defer db.mutex.RUnlock()
	user, ok := db.users[string(uid)]
	if !ok {
		return "", new(UserDoesNotExist)
	}
	return user.Nick, nil
}

//UpdatePassword changes the password of a given user
func UpdatePassword(uid, pwd, nPwd []byte) error {
	db.mutex.RLock()
	user, ok := db.users[string(uid)]
	if !ok {
		db.mutex.RUnlock()
		return new(UserDoesNotExist)
	}
	if !Authenticate(uid, pwd) {
		db.mutex.RUnlock()
		return new(AuthenticationError)
	}
	db.mutex.RUnlock()
	db.mutex.Lock()
	defer db.mutex.Unlock()
	user.Pswrd = nPwd
	return nil
}

//UpdateNickname updates a users nickname having first established the existence
//of a user and validated the cookie
func UpdateNickname(uid []byte, cookie string, nickname string) error {
	db.mutex.RLock()
	user, ok := db.users[string(uid)]
	if !ok {
		db.mutex.RUnlock()
		return new(UserDoesNotExist)
	}
	if !Validate(cookie, uid) {
		db.mutex.RUnlock()
		return new(AuthenticationError)
	}
	db.mutex.RUnlock()
	db.mutex.Lock()
	defer db.mutex.Unlock()
	user.Nick = nickname
	return nil
}

// removes all feeds from user’s account.
func ResetUserFeeds(uid []byte) error {
	db.mutex.RLock()
	user, ok := db.users[string(uid)]
	db.mutex.Unlock()
	if !ok {
		return new(UserDoesNotExist)
	}
	db.mutex.Lock()
	defer db.mutex.Unlock()
	user.Feeds = make([]*rss.Feed, 0)
	user.FeedUrls = make([]string, 0)
	return nil
}

// retrieves feed info.
func Feeds(uid []byte) ([]*rss.Feed, error) {
	if !Exists(uid) {
		return nil, new(UserDoesNotExist)
	}
	db.mutex.RLock()
	defer db.mutex.RUnlock()
	user, _ := db.users[string(uid)]
	return user.Feeds, nil
}

// pushes update to user’s account.
// func Update(userID []byte, delta *Delta) error {
// 	return nil
// }

func AddFeeds(uid []byte, cookie string, urls ...string) error {
	if !Exists(uid) {
		return new(UserDoesNotExist)
	}
	db.mutex.Lock()
	defer db.mutex.Unlock()
	user, _ := db.users[string(uid)]
	for _, url := range urls {
		resp, err := http.Get(url)
		if err != nil {
			return err
		}
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return err
		}
		feed, err := rss.Parse(body)
		if err != nil {
			return nil
		}
		user.Feeds = append(user.Feeds, feed)
		user.FeedUrls = append(user.FeedUrls, feed.Link)
	}
	return nil
}

func Debug() []byte {
	return nil
}

func (d *Database) Write([]byte) (int, error) {
	// restore
	return 0, nil
}

func (d *Database) Read([]byte) (int, error) {
	// backup
	return 0, nil
}

func Backup(path string) error {
	_, err := os.Create(path)
	if err != nil {
		return err
	}
	return nil
}

func Restore(path string) {
	return nil
}
<commit_msg>Add method for Salt retrieval<commit_after>package database

import (
	"bytes"
	"fmt"
	"github.com/SlyMarbo/rss"
	"io/ioutil"
	"math/rand"
	"net/http"
	"os"
	sec "rs3/security"
	"sync"
	"time"
)

var db *database

func init() {
	rand.Seed(time.Now().UnixNano())
	db = newDatabase()
}

type User struct {
	Uid      []byte
	Pswrd    []byte
	Salt     *sec.Salt
	Nick     string
	Cookies  CookieJar
	Feeds    []*rss.Feed
	FeedUrls []string
	mutex    *sync.RWMutex
}

func newUser(uid, pwd []byte, salt *sec.Salt, nick string) *User {
	user := User{
		uid,
		pwd,
		salt,
		nick,
		make(CookieJar, 0),
		make([]*rss.Feed, 0),
		make([]string, 0),
		new(sync.RWMutex),
	}
	return &user
}

//256 rand number
type Cookie struct {
	exp     time.Time
	replace time.Time
	cookie  string
}

type CookieJar []Cookie

func newCookie() Cookie {
	var buf bytes.Buffer
	for i := 0; i < 5; i++ {
		buf.WriteString(fmt.Sprintf("%x", rand.Int63()))
	}
	cookie := Cookie{
		time.Now().Add(7 * 24 * time.Hour),
		time.Now().Add(14 * 24 * time.Hour),
		buf.String()[:256]}
	return cookie
}

type UserAlreadyExists struct{}

func (err UserAlreadyExists) Error() string {
	return "User ID Already Exists"
}

type UserDoesNotExist struct{}

func (err UserDoesNotExist) Error() string {
	return "User ID Does Not Exist"
}

type EmailAlreadyExists struct{}

func (err EmailAlreadyExists) Error() string {
	return "Email Already Exists"
}

type AuthenticationError struct{}

func (err AuthenticationError) Error() string {
	return "Authentication Failure, User ID or Password Incorrect"
}

type BackupFailure struct{}

func (err BackupFailure) Error() string {
	return "Failed to Backup Database"
}

type RestoreFailure struct{}

func (err RestoreFailure) Error() string {
	return "Failed to Restore Database"
}

type database struct {
	users  map[string]*User     //uid -> User
	salts  map[string]*sec.Salt //email -> Salt
	emails map[string]struct{}  //email -> null (for email existence check)
	mutex  *sync.RWMutex
}

type Database struct{}

// func NewDatabase() *Database
func newDatabase() *database {
	db := database{
		make(map[string]*User),
		make(map[string]*sec.Salt),
		make(map[string]struct{}),
		new(sync.RWMutex),
	}
	return &db
}

func Salt(email string) *sec.Salt {
	return db.salts[email]
}

//AddUser creates a new user and adds it to the database. It establishes that both the user
//does not exist and that their email is not in use
func AddUser(uid, pwd []byte, salt *sec.Salt, nick, email string) error {
	db.mutex.RLock()
	if _, ok := db.users[string(uid)]; ok {
		db.mutex.RUnlock()
		return new(UserAlreadyExists)
	}
	if _, ok := db.emails[string(uid)]; ok {
		db.mutex.RUnlock()
		return new(EmailAlreadyExists)
	}
	db.mutex.RUnlock()
	db.mutex.Lock()
	defer db.mutex.Unlock()
	user := newUser(uid, pwd, salt, nick)
	db.users[string(uid)] = user
	db.emails[email] = *new(struct{})
	return nil
}

//Delete user removes a user from the database provided they exist in the system
func DeleteUser(uid []byte) error {
	db.mutex.Lock()
	defer db.mutex.Unlock()
	if _, ok := db.users[string(uid)]; !ok {
		return new(UserDoesNotExist)
	}
	delete(db.users, string(uid))
	return nil
}

//Exists confirms whether or not a user exists in the system
func Exists(uid []byte) bool {
	db.mutex.RLock()
	defer db.mutex.RUnlock()
	_, ok := db.users[string(uid)]
	return ok
}

//Authenticate checks that the userID and password match.
func Authenticate(uid, pswd []byte) bool {
	db.mutex.RLock()
	defer db.mutex.RUnlock()
	user, ok := db.users[string(uid)]
	if !ok {
		return false
	} else {
		user.mutex.RLock()
		defer user.mutex.RUnlock()
		return (bytes.Compare(user.Pswrd, pswd) == 0)
	}
}

//Login logs a user into the system, returning the cookie string
//Authenticates the user first
//if user already has a valid cookie, returns that cookie as opposed to creating one
func Login(uid, pswd []byte) (string, time.Time, error) {
	db.mutex.RLock()
	defer db.mutex.RUnlock()
	if !Authenticate(uid, pswd) {
		return "", time.Now(), new(AuthenticationError)
	}
	user, ok := db.users[string(uid)]
	if !ok {
		return "", time.Now(), new(UserDoesNotExist)
	}
	if len(user.Cookies) != 0 {
		for i := 0; i < len(user.Cookies); i++ {
			if user.Cookies[i].exp.After(time.Now()) {
				return user.Cookies[i].cookie, user.Cookies[i].exp, nil
			}
		}
		c := newCookie()
		user.Cookies = append(user.Cookies, c)
		return c.cookie, c.exp, nil
	} else {
		user.Cookies = append(user.Cookies, newCookie())
		return user.Cookies[0].cookie, user.Cookies[0].exp, nil
	}
}

//Validate checks the cookie.
func Validate(cookie string, uid []byte) bool {
	db.mutex.RLock()
	defer db.mutex.RUnlock()
	user, ok := db.users[string(uid)]
	if !ok { //user does not exist
		return false
	}
	for _, uCookie := range user.Cookies {
		if uCookie.cookie == cookie {
			return true
		}
	}
	return false
}

//Nickname validates the cookie and returns the user's nickname
func Nickname(uid []byte, cookie string) (string, error) {
	if !Validate(cookie, uid) {
		return "", new(AuthenticationError)
	}
	db.mutex.RLock()
	defer db.mutex.RUnlock()
	user, ok := db.users[string(uid)]
	if !ok {
		return "", new(UserDoesNotExist)
	}
	return user.Nick, nil
}

//UpdatePassword changes the password of a given user
func UpdatePassword(uid, pwd, nPwd []byte) error {
	db.mutex.RLock()
	user, ok := db.users[string(uid)]
	if !ok {
		db.mutex.RUnlock()
		return new(UserDoesNotExist)
	}
	if !Authenticate(uid, pwd) {
		db.mutex.RUnlock()
		return new(AuthenticationError)
	}
	db.mutex.RUnlock()
	db.mutex.Lock()
	defer db.mutex.Unlock()
	user.Pswrd = nPwd
	return nil
}

//UpdateNickname updates a users nickname having first established the existence
//of a user and validated the cookie
func UpdateNickname(uid []byte, cookie string, nickname string) error {
	db.mutex.RLock()
	user, ok := db.users[string(uid)]
	if !ok {
		db.mutex.RUnlock()
		return new(UserDoesNotExist)
	}
	if !Validate(cookie, uid) {
		db.mutex.RUnlock()
		return new(AuthenticationError)
	}
	db.mutex.RUnlock()
	db.mutex.Lock()
	defer db.mutex.Unlock()
	user.Nick = nickname
	return nil
}

// removes all feeds from user’s account.
func ResetUserFeeds(uid []byte) error {
	db.mutex.RLock()
	user, ok := db.users[string(uid)]
	db.mutex.Unlock()
	if !ok {
		return new(UserDoesNotExist)
	}
	db.mutex.Lock()
	defer db.mutex.Unlock()
	user.Feeds = make([]*rss.Feed, 0)
	user.FeedUrls = make([]string, 0)
	return nil
}

// retrieves feed info.
func Feeds(uid []byte) ([]*rss.Feed, error) {
	if !Exists(uid) {
		return nil, new(UserDoesNotExist)
	}
	db.mutex.RLock()
	defer db.mutex.RUnlock()
	user, _ := db.users[string(uid)]
	return user.Feeds, nil
}

// pushes update to user’s account.
// func Update(userID []byte, delta *Delta) error {
// 	return nil
// }

func AddFeeds(uid []byte, cookie string, urls ...string) error {
	if !Exists(uid) {
		return new(UserDoesNotExist)
	}
	db.mutex.Lock()
	defer db.mutex.Unlock()
	user, _ := db.users[string(uid)]
	for _, url := range urls {
		resp, err := http.Get(url)
		if err != nil {
			return err
		}
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return err
		}
		feed, err := rss.Parse(body)
		if err != nil {
			return nil
		}
		user.Feeds = append(user.Feeds, feed)
		user.FeedUrls = append(user.FeedUrls, feed.Link)
	}
	return nil
}

func Debug() []byte {
	return nil
}

func (d *Database) Write([]byte) (int, error) {
	// restore
	return 0, nil
}

func (d *Database) Read([]byte) (int, error) {
	// backup
	return 0, nil
}

func Backup(path string) error {
	_, err := os.Create(path)
	if err != nil {
		return err
	}
	return nil
}

func Restore(path string) error {
	return nil
}
<|endoftext|>


<commit_before>// Package reference provides a general type to represent any way of referencing images within the registry.
// Its main purpose is to abstract tags and digests (content-addressable hash).
//
// Grammar
//
// 	reference                       := name [ ":" tag ] [ "@" digest ]
//	name                            := [domain '/'] path-component ['/' path-component]*
//	domain                          := domain-component ['.' domain-component]* [':' port-number]
//	domain-component                := /([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])/
//	port-number                     := /[0-9]+/
//	path-component                  := alpha-numeric [separator alpha-numeric]*
// 	alpha-numeric                   := /[a-z0-9]+/
//	separator                       := /[_.]|__|[-]*/
//
//	tag                             := /[\w][\w.-]{0,127}/
//
//	digest                          := digest-algorithm ":" digest-hex
//	digest-algorithm                := digest-algorithm-component [ digest-algorithm-separator digest-algorithm-component ]
//	digest-algorithm-separator      := /[+.-_]/
//	digest-algorithm-component      := /[A-Za-z][A-Za-z0-9]*/
//	digest-hex                      := /[0-9a-fA-F]{32,}/ ; At least 128 bit digest value
//
//      identifier                      := /[a-f0-9]{64}/
//      short-identifier                := /[a-f0-9]{6,64}/
package reference

import (
	"errors"
	"fmt"
	"strings"

	"github.com/opencontainers/go-digest"
)

const (
	// NameTotalLengthMax is the maximum total number of characters in a repository name.
	NameTotalLengthMax = 255
)

var (
	// ErrReferenceInvalidFormat represents an error while trying to parse a string as a reference.
	ErrReferenceInvalidFormat = errors.New("invalid reference format")

	// ErrTagInvalidFormat represents an error while trying to parse a string as a tag.
	ErrTagInvalidFormat = errors.New("invalid tag format")

	// ErrDigestInvalidFormat represents an error while trying to parse a string as a tag.
	ErrDigestInvalidFormat = errors.New("invalid digest format")

	// ErrNameContainsUppercase is returned for invalid repository names that contain uppercase characters.
	ErrNameContainsUppercase = errors.New("repository name must be lowercase")

	// ErrNameEmpty is returned for empty, invalid repository names.
	ErrNameEmpty = errors.New("repository name must have at least one component")

	// ErrNameTooLong is returned when a repository name is longer than NameTotalLengthMax.
	ErrNameTooLong = fmt.Errorf("repository name must not be more than %v characters", NameTotalLengthMax)
)

// Reference is an opaque object reference identifier that may include
// modifiers such as a hostname, name, tag, and digest.
type Reference interface {
	// String returns the full reference
	String() string
}

// Field provides a wrapper type for resolving correct reference types when
// working with encoding.
type Field struct {
	reference Reference
}

// AsField wraps a reference in a Field for encoding.
func AsField(reference Reference) Field {
	return Field{reference}
}

// Reference unwraps the reference type from the field to
// return the Reference object. This object should be
// of the appropriate type to further check for different
// reference types.
func (f Field) Reference() Reference {
	return f.reference
}

// MarshalText serializes the field to byte text which
// is the string of the reference.
func (f Field) MarshalText() (p []byte, err error) {
	return []byte(f.reference.String()), nil
}

// UnmarshalText parses text bytes by invoking the
// reference parser to ensure the appropriately
// typed reference object is wrapped by field.
func (f *Field) UnmarshalText(p []byte) error {
	r, err := Parse(string(p))
	if err != nil {
		return err
	}

	f.reference = r
	return nil
}

// Named is an object with a full name
type Named interface {
	Reference
	Name() string
}

// Tagged is an object which has a tag
type Tagged interface {
	Reference
	Tag() string
}

// NamedTagged is an object including a name and tag.
type NamedTagged interface {
	Named
	Tag() string
}

// Digested is an object which has a digest
// in which it can be referenced by
type Digested interface {
	Reference
	Digest() digest.Digest
}

// Canonical reference is an object with a fully unique
// name including a name with domain and digest
type Canonical interface {
	Named
	Digest() digest.Digest
}

// namedRepository is a reference to a repository with a name.
// A namedRepository has both domain and path components.
type namedRepository interface {
	Named
	Domain() string
	Path() string
}

// Domain returns the domain part of the Named reference
func Domain(named Named) string {
	if r, ok := named.(namedRepository); ok {
		return r.Domain()
	}
	domain, _ := splitDomain(named.Name())
	return domain
}

// Path returns the name without the domain part of the Named reference
func Path(named Named) (name string) {
	if r, ok := named.(namedRepository); ok {
		return r.Path()
	}
	_, path := splitDomain(named.Name())
	return path
}

func splitDomain(name string) (string, string) {
	match := anchoredNameRegexp.FindStringSubmatch(name)
	if len(match) != 3 {
		return "", name
	}
	return match[1], match[2]
}

// SplitHostname splits a named reference into a
// hostname and name string. If no valid hostname is
// found, the hostname is empty and the full value
// is returned as name
// DEPRECATED: Use Domain or Path
func SplitHostname(named Named) (string, string) {
	if r, ok := named.(namedRepository); ok {
		return r.Domain(), r.Path()
	}
	return splitDomain(named.Name())
}

// Parse parses s and returns a syntactically valid Reference.
// If an error was encountered it is returned, along with a nil Reference.
// NOTE: Parse will not handle short digests.
func Parse(s string) (Reference, error) {
	matches := ReferenceRegexp.FindStringSubmatch(s)
	if matches == nil {
		if s == "" {
			return nil, ErrNameEmpty
		}
		if ReferenceRegexp.FindStringSubmatch(strings.ToLower(s)) != nil {
			return nil, ErrNameContainsUppercase
		}
		return nil, ErrReferenceInvalidFormat
	}

	if len(matches[1]) > NameTotalLengthMax {
		return nil, ErrNameTooLong
	}

	var repo repository

	nameMatch := anchoredNameRegexp.FindStringSubmatch(matches[1])
	if nameMatch != nil && len(nameMatch) == 3 {
		repo.domain = nameMatch[1]
		repo.path = nameMatch[2]
	} else {
		repo.domain = ""
		repo.path = matches[1]
	}

	ref := reference{
		namedRepository: repo,
		tag:             matches[2],
	}
	if matches[3] != "" {
		var err error
		ref.digest, err = digest.Parse(matches[3])
		if err != nil {
			return nil, err
		}
	}

	r := getBestReferenceType(ref)
	if r == nil {
		return nil, ErrNameEmpty
	}

	return r, nil
}

// ParseNamed parses s and returns a syntactically valid reference implementing
// the Named interface. The reference must have a name, otherwise an error is
// returned.
// If an error was encountered it is returned, along with a nil Reference.
// NOTE: ParseNamed will not handle short digests.
func ParseNamed(s string) (Named, error) {
	ref, err := Parse(s)
	if err != nil {
		return nil, err
	}
	named, isNamed := ref.(Named)
	if !isNamed {
		return nil, fmt.Errorf("reference %s has no name", ref.String())
	}
	return named, nil
}

// WithName returns a named object representing the given string. If the input
// is invalid ErrReferenceInvalidFormat will be returned.
func WithName(name string) (Named, error) {
	if len(name) > NameTotalLengthMax {
		return nil, ErrNameTooLong
	}

	match := anchoredNameRegexp.FindStringSubmatch(name)
	if match == nil || len(match) != 3 {
		return nil, ErrReferenceInvalidFormat
	}
	return repository{
		domain: match[1],
		path:   match[2],
	}, nil
}

// WithTag combines the name from "name" and the tag from "tag" to form a
// reference incorporating both the name and the tag.
func WithTag(name Named, tag string) (NamedTagged, error) {
	if !anchoredTagRegexp.MatchString(tag) {
		return nil, ErrTagInvalidFormat
	}
	var repo repository
	if r, ok := name.(namedRepository); ok {
		repo.domain = r.Domain()
		repo.path = r.Path()
	} else {
		repo.path = name.Name()
	}
	if canonical, ok := name.(Canonical); ok {
		return reference{
			namedRepository: repo,
			tag:             tag,
			digest:          canonical.Digest(),
		}, nil
	}
	return taggedReference{
		namedRepository: repo,
		tag:             tag,
	}, nil
}

// WithDigest combines the name from "name" and the digest from "digest" to form
// a reference incorporating both the name and the digest.
func WithDigest(name Named, digest digest.Digest) (Canonical, error) {
	if !anchoredDigestRegexp.MatchString(digest.String()) {
		return nil, ErrDigestInvalidFormat
	}
	var repo repository
	if r, ok := name.(namedRepository); ok {
		repo.domain = r.Domain()
		repo.path = r.Path()
	} else {
		repo.path = name.Name()
	}
	if tagged, ok := name.(Tagged); ok {
		return reference{
			namedRepository: repo,
			tag:             tagged.Tag(),
			digest:          digest,
		}, nil
	}
	return canonicalReference{
		namedRepository: repo,
		digest:          digest,
	}, nil
}

// TrimNamed removes any tag or digest from the named reference.
func TrimNamed(ref Named) Named {
	domain, path := SplitHostname(ref)
	return repository{
		domain: domain,
		path:   path,
	}
}

func getBestReferenceType(ref reference) Reference {
	if ref.Name() == "" {
		// Allow digest only references
		if ref.digest != "" {
			return digestReference(ref.digest)
		}
		return nil
	}
	if ref.tag == "" {
		if ref.digest != "" {
			return canonicalReference{
				namedRepository: ref.namedRepository,
				digest:          ref.digest,
			}
		}
		return ref.namedRepository
	}
	if ref.digest == "" {
		return taggedReference{
			namedRepository: ref.namedRepository,
			tag:             ref.tag,
		}
	}

	return ref
}

type reference struct {
	namedRepository
	tag    string
	digest digest.Digest
}

func (r reference) String() string {
	return r.Name() + ":" + r.tag + "@" + r.digest.String()
}

func (r reference) Tag() string {
	return r.tag
}

func (r reference) Digest() digest.Digest {
	return r.digest
}

type repository struct {
	domain string
	path   string
}

func (r repository) String() string {
	return r.Name()
}

func (r repository) Name() string {
	if r.domain == "" {
		return r.path
	}
	return r.domain + "/" + r.path
}

func (r repository) Domain() string {
	return r.domain
}

func (r repository) Path() string {
	return r.path
}

type digestReference digest.Digest

func (d digestReference) String() string {
	return d.String()
}

func (d digestReference) Digest() digest.Digest {
	return digest.Digest(d)
}

type taggedReference struct {
	namedRepository
	tag string
}

func (t taggedReference) String() string {
	return t.Name() + ":" + t.tag
}

func (t taggedReference) Tag() string {
	return t.tag
}

type canonicalReference struct {
	namedRepository
	digest digest.Digest
}

func (c canonicalReference) String() string {
	return c.Name() + "@" + c.digest.String()
}

func (c canonicalReference) Digest() digest.Digest {
	return c.digest
}
<commit_msg>Fix inconsistent spacing in reference grammar<commit_after>// Package reference provides a general type to represent any way of referencing images within the registry.
// Its main purpose is to abstract tags and digests (content-addressable hash).
//
// Grammar
//
// 	reference                       := name [ ":" tag ] [ "@" digest ]
//	name                            := [domain '/'] path-component ['/' path-component]*
//	domain                          := domain-component ['.' domain-component]* [':' port-number]
//	domain-component                := /([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])/
//	port-number                     := /[0-9]+/
//	path-component                  := alpha-numeric [separator alpha-numeric]*
// 	alpha-numeric                   := /[a-z0-9]+/
//	separator                       := /[_.]|__|[-]*/
//
//	tag                             := /[\w][\w.-]{0,127}/
//
//	digest                          := digest-algorithm ":" digest-hex
//	digest-algorithm                := digest-algorithm-component [ digest-algorithm-separator digest-algorithm-component ]
//	digest-algorithm-separator      := /[+.-_]/
//	digest-algorithm-component      := /[A-Za-z][A-Za-z0-9]*/
//	digest-hex                      := /[0-9a-fA-F]{32,}/ ; At least 128 bit digest value
//
//	identifier                      := /[a-f0-9]{64}/
//	short-identifier                := /[a-f0-9]{6,64}/
package reference

import (
	"errors"
	"fmt"
	"strings"

	"github.com/opencontainers/go-digest"
)

const (
	// NameTotalLengthMax is the maximum total number of characters in a repository name.
	NameTotalLengthMax = 255
)

var (
	// ErrReferenceInvalidFormat represents an error while trying to parse a string as a reference.
	ErrReferenceInvalidFormat = errors.New("invalid reference format")

	// ErrTagInvalidFormat represents an error while trying to parse a string as a tag.
	ErrTagInvalidFormat = errors.New("invalid tag format")

	// ErrDigestInvalidFormat represents an error while trying to parse a string as a tag.
	ErrDigestInvalidFormat = errors.New("invalid digest format")

	// ErrNameContainsUppercase is returned for invalid repository names that contain uppercase characters.
	ErrNameContainsUppercase = errors.New("repository name must be lowercase")

	// ErrNameEmpty is returned for empty, invalid repository names.
	ErrNameEmpty = errors.New("repository name must have at least one component")

	// ErrNameTooLong is returned when a repository name is longer than NameTotalLengthMax.
	ErrNameTooLong = fmt.Errorf("repository name must not be more than %v characters", NameTotalLengthMax)
)

// Reference is an opaque object reference identifier that may include
// modifiers such as a hostname, name, tag, and digest.
type Reference interface {
	// String returns the full reference
	String() string
}

// Field provides a wrapper type for resolving correct reference types when
// working with encoding.
type Field struct {
	reference Reference
}

// AsField wraps a reference in a Field for encoding.
func AsField(reference Reference) Field {
	return Field{reference}
}

// Reference unwraps the reference type from the field to
// return the Reference object. This object should be
// of the appropriate type to further check for different
// reference types.
func (f Field) Reference() Reference {
	return f.reference
}

// MarshalText serializes the field to byte text which
// is the string of the reference.
func (f Field) MarshalText() (p []byte, err error) {
	return []byte(f.reference.String()), nil
}

// UnmarshalText parses text bytes by invoking the
// reference parser to ensure the appropriately
// typed reference object is wrapped by field.
func (f *Field) UnmarshalText(p []byte) error {
	r, err := Parse(string(p))
	if err != nil {
		return err
	}

	f.reference = r
	return nil
}

// Named is an object with a full name
type Named interface {
	Reference
	Name() string
}

// Tagged is an object which has a tag
type Tagged interface {
	Reference
	Tag() string
}

// NamedTagged is an object including a name and tag.
type NamedTagged interface {
	Named
	Tag() string
}

// Digested is an object which has a digest
// in which it can be referenced by
type Digested interface {
	Reference
	Digest() digest.Digest
}

// Canonical reference is an object with a fully unique
// name including a name with domain and digest
type Canonical interface {
	Named
	Digest() digest.Digest
}

// namedRepository is a reference to a repository with a name.
// A namedRepository has both domain and path components.
type namedRepository interface {
	Named
	Domain() string
	Path() string
}

// Domain returns the domain part of the Named reference
func Domain(named Named) string {
	if r, ok := named.(namedRepository); ok {
		return r.Domain()
	}
	domain, _ := splitDomain(named.Name())
	return domain
}

// Path returns the name without the domain part of the Named reference
func Path(named Named) (name string) {
	if r, ok := named.(namedRepository); ok {
		return r.Path()
	}
	_, path := splitDomain(named.Name())
	return path
}

func splitDomain(name string) (string, string) {
	match := anchoredNameRegexp.FindStringSubmatch(name)
	if len(match) != 3 {
		return "", name
	}
	return match[1], match[2]
}

// SplitHostname splits a named reference into a
// hostname and name string. If no valid hostname is
// found, the hostname is empty and the full value
// is returned as name
// DEPRECATED: Use Domain or Path
func SplitHostname(named Named) (string, string) {
	if r, ok := named.(namedRepository); ok {
		return r.Domain(), r.Path()
	}
	return splitDomain(named.Name())
}

// Parse parses s and returns a syntactically valid Reference.
// If an error was encountered it is returned, along with a nil Reference.
// NOTE: Parse will not handle short digests.
func Parse(s string) (Reference, error) {
	matches := ReferenceRegexp.FindStringSubmatch(s)
	if matches == nil {
		if s == "" {
			return nil, ErrNameEmpty
		}
		if ReferenceRegexp.FindStringSubmatch(strings.ToLower(s)) != nil {
			return nil, ErrNameContainsUppercase
		}
		return nil, ErrReferenceInvalidFormat
	}

	if len(matches[1]) > NameTotalLengthMax {
		return nil, ErrNameTooLong
	}

	var repo repository

	nameMatch := anchoredNameRegexp.FindStringSubmatch(matches[1])
	if nameMatch != nil && len(nameMatch) == 3 {
		repo.domain = nameMatch[1]
		repo.path = nameMatch[2]
	} else {
		repo.domain = ""
		repo.path = matches[1]
	}

	ref := reference{
		namedRepository: repo,
		tag:             matches[2],
	}
	if matches[3] != "" {
		var err error
		ref.digest, err = digest.Parse(matches[3])
		if err != nil {
			return nil, err
		}
	}

	r := getBestReferenceType(ref)
	if r == nil {
		return nil, ErrNameEmpty
	}

	return r, nil
}

// ParseNamed parses s and returns a syntactically valid reference implementing
// the Named interface. The reference must have a name, otherwise an error is
// returned.
// If an error was encountered it is returned, along with a nil Reference.
// NOTE: ParseNamed will not handle short digests.
func ParseNamed(s string) (Named, error) {
	ref, err := Parse(s)
	if err != nil {
		return nil, err
	}
	named, isNamed := ref.(Named)
	if !isNamed {
		return nil, fmt.Errorf("reference %s has no name", ref.String())
	}
	return named, nil
}

// WithName returns a named object representing the given string. If the input
// is invalid ErrReferenceInvalidFormat will be returned.
func WithName(name string) (Named, error) {
	if len(name) > NameTotalLengthMax {
		return nil, ErrNameTooLong
	}

	match := anchoredNameRegexp.FindStringSubmatch(name)
	if match == nil || len(match) != 3 {
		return nil, ErrReferenceInvalidFormat
	}
	return repository{
		domain: match[1],
		path:   match[2],
	}, nil
}

// WithTag combines the name from "name" and the tag from "tag" to form a
// reference incorporating both the name and the tag.
func WithTag(name Named, tag string) (NamedTagged, error) {
	if !anchoredTagRegexp.MatchString(tag) {
		return nil, ErrTagInvalidFormat
	}
	var repo repository
	if r, ok := name.(namedRepository); ok {
		repo.domain = r.Domain()
		repo.path = r.Path()
	} else {
		repo.path = name.Name()
	}
	if canonical, ok := name.(Canonical); ok {
		return reference{
			namedRepository: repo,
			tag:             tag,
			digest:          canonical.Digest(),
		}, nil
	}
	return taggedReference{
		namedRepository: repo,
		tag:             tag,
	}, nil
}

// WithDigest combines the name from "name" and the digest from "digest" to form
// a reference incorporating both the name and the digest.
func WithDigest(name Named, digest digest.Digest) (Canonical, error) {
	if !anchoredDigestRegexp.MatchString(digest.String()) {
		return nil, ErrDigestInvalidFormat
	}
	var repo repository
	if r, ok := name.(namedRepository); ok {
		repo.domain = r.Domain()
		repo.path = r.Path()
	} else {
		repo.path = name.Name()
	}
	if tagged, ok := name.(Tagged); ok {
		return reference{
			namedRepository: repo,
			tag:             tagged.Tag(),
			digest:          digest,
		}, nil
	}
	return canonicalReference{
		namedRepository: repo,
		digest:          digest,
	}, nil
}

// TrimNamed removes any tag or digest from the named reference.
func TrimNamed(ref Named) Named {
	domain, path := SplitHostname(ref)
	return repository{
		domain: domain,
		path:   path,
	}
}

func getBestReferenceType(ref reference) Reference {
	if ref.Name() == "" {
		// Allow digest only references
		if ref.digest != "" {
			return digestReference(ref.digest)
		}
		return nil
	}
	if ref.tag == "" {
		if ref.digest != "" {
			return canonicalReference{
				namedRepository: ref.namedRepository,
				digest:          ref.digest,
			}
		}
		return ref.namedRepository
	}
	if ref.digest == "" {
		return taggedReference{
			namedRepository: ref.namedRepository,
			tag:             ref.tag,
		}
	}

	return ref
}

type reference struct {
	namedRepository
	tag    string
	digest digest.Digest
}

func (r reference) String() string {
	return r.Name() + ":" + r.tag + "@" + r.digest.String()
}

func (r reference) Tag() string {
	return r.tag
}

func (r reference) Digest() digest.Digest {
	return r.digest
}

type repository struct {
	domain string
	path   string
}

func (r repository) String() string {
	return r.Name()
}

func (r repository) Name() string {
	if r.domain == "" {
		return r.path
	}
	return r.domain + "/" + r.path
}

func (r repository) Domain() string {
	return r.domain
}

func (r repository) Path() string {
	return r.path
}

type digestReference digest.Digest

func (d digestReference) String() string {
	return d.String()
}

func (d digestReference) Digest() digest.Digest {
	return digest.Digest(d)
}

type taggedReference struct {
	namedRepository
	tag string
}

func (t taggedReference) String() string {
	return t.Name() + ":" + t.tag
}

func (t taggedReference) Tag() string {
	return t.tag
}

type canonicalReference struct {
	namedRepository
	digest digest.Digest
}

func (c canonicalReference) String() string {
	return c.Name() + "@" + c.digest.String()
}

func (c canonicalReference) Digest() digest.Digest {
	return c.digest
}
<|endoftext|>


<commit_before>package service

import (
	"log"
	"net/http"
	"strings"

	"github.com/zyfdegh/hiupdate/server/entity"
	"github.com/zyfdegh/hiupdate/server/orm"
	"github.com/zyfdegh/hiupdate/server/util"
)

// GetRecords returns all records of a day
func GetRecords(date string) (records []entity.Record, err error) {
	records = make([]entity.Record, 20)
	persons, err := GetAllPersons()
	if err != nil {
		log.Printf("service get all persons error: %v", err)
		return
	}
	for _, person := range persons {
		id := util.GenerateID(person.Name, date)
		record, e := orm.QueryRecord(id)
		if e != nil {
			log.Printf("service query record error: %v", e)
			continue
		}
		records = append(records, *record)
	}
	return records, nil
}

func GetYesterdayRecord(name string) (resp *entity.RespGetUpdate, err error) {
	return GetUpdate(name, util.GetYesterday())
}

func checkReqGetUpdate(name, date string) (errmsg string) {
	if len(strings.TrimSpace(name)) == 0 {
		return "name not set"
	}
	if len(strings.TrimSpace(date)) == 0 {
		return "name not set"
	}
	return ""
}

func GetUpdate(name, date string) (resp *entity.RespGetUpdate, err error) {
	resp = &entity.RespGetUpdate{}
	errmsg := checkReqGetUpdate(name, date)
	if errmsg != "" {
		resp.Success = false
		resp.ErrNo = http.StatusBadRequest
		resp.Errmsg = errmsg
		return
	}
	id := util.GenerateID(name, date)
	record, err := orm.QueryRecord(id)
	if err != nil {
		log.Printf("service query record error: %v", err)
		resp.Success = false
		resp.ErrNo = http.StatusInternalServerError
		resp.Errmsg = "service query record error"
		return
	}
	resp.Success = true
	resp.Data = *record
	return
}

func checkReqPutUpdate(req *entity.ReqUpdate) string {
	if len(strings.TrimSpace(req.Name)) == 0 {
		return "name not set"
	}
	if len(strings.TrimSpace(req.Todo)) == 0 {
		return "todo not set"
	}
	if len(strings.TrimSpace(req.Issue)) == 0 {
		return "issue not set"
	}
	return ""
}

func PutUpdate(req *entity.ReqUpdate) (resp *entity.RespPutUpdate, err error) {
	resp = &entity.RespPutUpdate{}

	errmsg := checkReqPutUpdate(req)
	if errmsg != "" {
		resp.Success = false
		resp.ErrNo = http.StatusBadRequest
		resp.Errmsg = errmsg
		return
	}

	record := &entity.Record{}
	record.Person.Name = req.Name
	record.Content.Done = req.Done
	record.Content.Todo = req.Todo
	record.Content.Issue = req.Issue
	date := util.GetToday()
	record.Date = date
	record.ID = util.GenerateID(req.Name, date)

	err = orm.UpdateRecord(record)
	if err != nil {
		log.Printf("service record update error: %v", err)
		resp.Success = false
		resp.ErrNo = http.StatusInternalServerError
		resp.Errmsg = "service record update error"
		return
	}

	resp.Success = true
	resp.Data = *record
	return
}
<commit_msg>no longer check issue<commit_after>package service

import (
	"log"
	"net/http"
	"strings"

	"github.com/zyfdegh/hiupdate/server/entity"
	"github.com/zyfdegh/hiupdate/server/orm"
	"github.com/zyfdegh/hiupdate/server/util"
)

// GetRecords returns all records of a day
func GetRecords(date string) (records []entity.Record, err error) {
	records = make([]entity.Record, 20)
	persons, err := GetAllPersons()
	if err != nil {
		log.Printf("service get all persons error: %v", err)
		return
	}
	for _, person := range persons {
		id := util.GenerateID(person.Name, date)
		record, e := orm.QueryRecord(id)
		if e != nil {
			log.Printf("service query record error: %v", e)
			continue
		}
		records = append(records, *record)
	}
	return records, nil
}

func GetYesterdayRecord(name string) (resp *entity.RespGetUpdate, err error) {
	return GetUpdate(name, util.GetYesterday())
}

func checkReqGetUpdate(name, date string) (errmsg string) {
	if len(strings.TrimSpace(name)) == 0 {
		return "name not set"
	}
	if len(strings.TrimSpace(date)) == 0 {
		return "name not set"
	}
	return ""
}

func GetUpdate(name, date string) (resp *entity.RespGetUpdate, err error) {
	resp = &entity.RespGetUpdate{}
	errmsg := checkReqGetUpdate(name, date)
	if errmsg != "" {
		resp.Success = false
		resp.ErrNo = http.StatusBadRequest
		resp.Errmsg = errmsg
		return
	}
	id := util.GenerateID(name, date)
	record, err := orm.QueryRecord(id)
	if err != nil {
		log.Printf("service query record error: %v", err)
		resp.Success = false
		resp.ErrNo = http.StatusInternalServerError
		resp.Errmsg = "service query record error"
		return
	}
	resp.Success = true
	resp.Data = *record
	return
}

func checkReqPutUpdate(req *entity.ReqUpdate) string {
	if len(strings.TrimSpace(req.Name)) == 0 {
		return "name not set"
	}
	if len(strings.TrimSpace(req.Todo)) == 0 {
		return "todo not set"
	}
	return ""
}

func PutUpdate(req *entity.ReqUpdate) (resp *entity.RespPutUpdate, err error) {
	resp = &entity.RespPutUpdate{}

	errmsg := checkReqPutUpdate(req)
	if errmsg != "" {
		resp.Success = false
		resp.ErrNo = http.StatusBadRequest
		resp.Errmsg = errmsg
		return
	}

	record := &entity.Record{}
	record.Person.Name = req.Name
	record.Content.Done = req.Done
	record.Content.Todo = req.Todo
	record.Content.Issue = req.Issue
	date := util.GetToday()
	record.Date = date
	record.ID = util.GenerateID(req.Name, date)

	err = orm.UpdateRecord(record)
	if err != nil {
		log.Printf("service record update error: %v", err)
		resp.Success = false
		resp.ErrNo = http.StatusInternalServerError
		resp.Errmsg = "service record update error"
		return
	}

	resp.Success = true
	resp.Data = *record
	return
}
<|endoftext|>


<commit_before>package server

import (
	"bytes"
	"fmt"
	"log"
	"net/http"
	"net/url"

	"github.com/fsouza/go-dockerclient"
)

type TasksResource struct {
	Docker            *docker.Client
	DockerHubUsername string
}

type TaskRequest struct {
	Task Task `json:"task"`
}

type Task struct {
	Version string `json:"version"`
	Command string `json:"command"`
}

func (tr *TasksResource) Create(u *url.URL, h http.Header, req *TaskRequest) (int, http.Header, interface{}, error) {
	serviceName := u.Query().Get("name")
	taskName := fmt.Sprintf("%s-%s-task", serviceName, req.Task.Version)
	imageName := fmt.Sprintf("%s/%s:%s", tr.DockerHubUsername, serviceName, req.Task.Version)

	container, err := tr.Docker.CreateContainer(docker.CreateContainerOptions{
		Name: taskName,
		Config: &docker.Config{
			Image:        imageName,
			Cmd:          []string{req.Task.Command},
			AttachStdout: true,
			AttachStderr: true,
		},
	})
	if err != nil {
		return http.StatusInternalServerError, nil, nil, err
	}

	log.Printf("%#v", container)
	tr.Docker.StartContainer(container.ID, &docker.HostConfig{})

	var buf bytes.Buffer
	err = tr.Docker.AttachToContainer(docker.AttachToContainerOptions{
		Container:    container.ID,
		OutputStream: &buf,
		Logs:         true,
		Stdout:       true,
		Stderr:       true,
		Stream:       true,
	})
	if err != nil {
		return http.StatusInternalServerError, nil, nil, err
	}
	log.Println(buf.String())

	err = tr.Docker.RemoveContainer(docker.RemoveContainerOptions{ID: container.ID})
	if err != nil {
		return http.StatusInternalServerError, nil, nil, err
	}

	return http.StatusCreated, nil, nil, nil
}
<commit_msg>Reorganize some code into helper functions.  Move output from stdout to HTTP response and return the potentially large multi-line string in a JSON wrapper for now.<commit_after>package server

import (
	"bytes"
	"fmt"
	"log"
	"net/http"
	"net/url"

	"github.com/fsouza/go-dockerclient"
)

type TasksResource struct {
	Docker            *docker.Client
	DockerHubUsername string
}

type TaskRequest struct {
	Task Task `json:"task"`
}

type TaskResponse struct {
	Output string `json:"output"`
}

type Task struct {
	Version string `json:"version"`
	Command string `json:"command"`
}

func (tr *TasksResource) Create(u *url.URL, h http.Header, req *TaskRequest) (int, http.Header, *TaskResponse, error) {
	serviceName := u.Query().Get("name")
	taskName := fmt.Sprintf("%s-%s-task", serviceName, req.Task.Version)
	imageName := fmt.Sprintf("%s/%s:%s", tr.DockerHubUsername, serviceName, req.Task.Version)

	container, err := tr.runContainer(taskName, imageName, req.Task.Command)
	if err != nil {
		return http.StatusInternalServerError, nil, &TaskResponse{}, err
	}

	output, err := tr.readContainerOutput(container.ID)
	if err != nil {
		return http.StatusInternalServerError, nil, &TaskResponse{}, err
	}

	err = tr.Docker.RemoveContainer(docker.RemoveContainerOptions{ID: container.ID})
	if err != nil {
		log.Printf("WARNING: Container could not be cleaned up (%s)", err)
	}

	return http.StatusCreated, nil, &TaskResponse{output}, nil
}

func (tr *TasksResource) runContainer(taskName string, imageName string, command string) (*docker.Container, error) {
	container, err := tr.Docker.CreateContainer(docker.CreateContainerOptions{
		Name: taskName,
		Config: &docker.Config{
			Image:        imageName,
			Cmd:          []string{command},
			AttachStdout: true,
			AttachStderr: true,
		},
	})
	if err != nil {
		return &docker.Container{}, err
	}

	err = tr.Docker.StartContainer(container.ID, &docker.HostConfig{})
	if err != nil {
		return &docker.Container{}, err
	}

	return container, nil
}

func (tr *TasksResource) readContainerOutput(containerID string) (string, error) {
	var buf bytes.Buffer
	err := tr.Docker.AttachToContainer(docker.AttachToContainerOptions{
		Container:    containerID,
		OutputStream: &buf,
		Logs:         true,
		Stdout:       true,
		Stderr:       true,
		Stream:       true,
	})

	if err != nil {
		return "", err
	}

	return buf.String(), nil
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"math"

	"buildblast/physics"
	"buildblast/coords"
)

type ControlState struct {
	Forward         bool
	Left            bool
	Right           bool
	Back            bool
	Jump            bool
	ActivateBlaster bool
	Lat             float64
	Lon             float64

	Timestamp float64 // In ms
}

var PLAYER_EYE_HEIGHT = 1.6;
var PLAYER_HEIGHT = 1.75;
var PLAYER_BODY_HEIGHT = 1.3;
var PLAYER_DIST_CENTER_EYE = PLAYER_EYE_HEIGHT - PLAYER_BODY_HEIGHT/2;
var PLAYER_HALF_EXTENTS = coords.Vec3{
	0.2,
	PLAYER_HEIGHT / 2,
	0.2,
};
var PLAYER_CENTER_OFFSET = coords.Vec3{
	0,
	-PLAYER_DIST_CENTER_EYE,
	0,
};

// Gameplay state defaults
var PLAYER_MAX_HP = 100;

type Player struct {
	pos       coords.World
	look      coords.Vec3
	vy        float64
	box       physics.Box
	controls  *ControlState
	history   *PlayerHistory

	// Gameplay state
	hp        int
}

func NewPlayer() *Player {
	return &Player{
		pos: coords.World{
			X: 0,
			Y: 27,
			Z: 0,
		},
		controls: &ControlState{},
		history: NewPlayerHistory(),
		hp: PLAYER_MAX_HP,
	}
}

func (p *Player) simulateStep(world *World, controls *ControlState) (*MsgPlayerState, *MsgDebugRay) {
	dt := (controls.Timestamp - p.controls.Timestamp) / 1000

	if dt > 1.0 {
		log.Println("WARN: Attempt to simulate step with dt of ", dt, " which is too large. Clipping to 1.0s")
		dt = 1.0
	}
	if dt < 0.0 {
		log.Println("WARN: Attempting to simulate step with negative dt of ", dt, " this is probably wrong.")
	}

	p.updateLook(controls)

	msgDebugRay := p.simulateBlaster(dt, world, controls)
	p.simulateMovement(dt, world, controls)

	p.controls = controls
	p.history.Add(controls.Timestamp, p.pos)

	return &MsgPlayerState{
		Pos: p.pos,
		VelocityY: p.vy,
		Timestamp: controls.Timestamp,
		Hp: p.hp,
	}, msgDebugRay
}

func (p *Player) simulateMovement(dt float64, world *World, controls *ControlState) {
	p.vy += dt * -9.81

	fw := 0.0
	if controls.Forward {
		fw = 1 * dt * 10
	} else if controls.Back {
		fw = -1 * dt * 10
	}

	rt := 0.0
	if controls.Right {
		rt = 1 * dt * 10
	} else if controls.Left {
		rt = -1 * dt * 10
	}

	cos := math.Cos
	sin := math.Sin

	move := coords.Vec3{
		X: -cos(controls.Lon) * fw + sin(controls.Lon) * rt,
		Y: p.vy * dt,
		Z: -sin(controls.Lon) * fw - cos(controls.Lon) * rt,
	}

	box := p.Box()

	move = box.AttemptMove(world, move)

	if (move.Y == 0) {
		if (controls.Jump) {
			p.vy = 6
		} else {
			p.vy = 0
		}
	}

	p.pos.X += move.X
	p.pos.Y += move.Y
	p.pos.Z += move.Z
}

func (p *Player) updateLook(controls *ControlState) {
	cos := math.Cos
	sin := math.Sin

	lat := controls.Lat
	lon := controls.Lon

	p.look.X = sin(lat) * cos(lon)
	p.look.Y = cos(lat)
	p.look.Z = sin(lat) * sin(lon)
}

func (p *Player) simulateBlaster(dt float64, world *World, controls *ControlState) *MsgDebugRay {
	if !controls.ActivateBlaster {
		return nil
	}

	// Compile a list of player bounding boxes, based on this shooters time
	var players []*physics.Box
	for _, v := range world.players {
		if v == p {
			players = append(players, nil)
			continue
		}
		players = append(players, v.BoxAt(controls.Timestamp))
	}

	ray := physics.NewRay(p.pos, p.look)
	target, index := ray.FindAnyIntersect(world, players)
	if index >= 0 {
		world.players[index].hurt(10)
	}

	if target == nil {
		return nil
	}

	return &MsgDebugRay{
		Pos: *target,
	}
}

func (p *Player) Box() *physics.Box {
	return physics.NewBoxOffset(
		p.pos,
		PLAYER_HALF_EXTENTS,
		PLAYER_CENTER_OFFSET)
}

func (p *Player) BoxAt(t float64) *physics.Box {
	return physics.NewBoxOffset(
		p.history.PositionAt(t),
		PLAYER_HALF_EXTENTS,
		PLAYER_CENTER_OFFSET)
}

func (p *Player) hurt(dmg int) bool {
	p.hp -= dmg
	return p.dead()
}

func (p *Player) heal(hps int) {
	p.hp += hps
}

func (p *Player) dead() bool {
	return p.hp <= 0
}
<commit_msg>Basic respawning.<commit_after>package main

import (
	"log"
	"math"

	"buildblast/physics"
	"buildblast/coords"
)

type ControlState struct {
	Forward         bool
	Left            bool
	Right           bool
	Back            bool
	Jump            bool
	ActivateBlaster bool
	Lat             float64
	Lon             float64

	Timestamp float64 // In ms
}

var PLAYER_EYE_HEIGHT = 1.6;
var PLAYER_HEIGHT = 1.75;
var PLAYER_BODY_HEIGHT = 1.3;
var PLAYER_DIST_CENTER_EYE = PLAYER_EYE_HEIGHT - PLAYER_BODY_HEIGHT/2;
var PLAYER_HALF_EXTENTS = coords.Vec3{
	0.2,
	PLAYER_HEIGHT / 2,
	0.2,
};
var PLAYER_CENTER_OFFSET = coords.Vec3{
	0,
	-PLAYER_DIST_CENTER_EYE,
	0,
};
var PLAYER_SPAWN = coords.World{
	X: 0,
	Y: 27,
	Z: 0,
}

// Gameplay state defaults
var PLAYER_MAX_HP = 100;

type Player struct {
	pos       coords.World
	look      coords.Vec3
	vy        float64
	box       physics.Box
	controls  *ControlState
	history   *PlayerHistory

	// Gameplay state
	hp        int
}

func NewPlayer() *Player {
	return &Player{
		pos: PLAYER_SPAWN,
		controls: &ControlState{},
		history: NewPlayerHistory(),
		hp: PLAYER_MAX_HP,
	}
}

func (p *Player) simulateStep(world *World, controls *ControlState) (*MsgPlayerState, *MsgDebugRay) {
	dt := (controls.Timestamp - p.controls.Timestamp) / 1000

	if dt > 1.0 {
		log.Println("WARN: Attempt to simulate step with dt of ", dt, " which is too large. Clipping to 1.0s")
		dt = 1.0
	}
	if dt < 0.0 {
		log.Println("WARN: Attempting to simulate step with negative dt of ", dt, " this is probably wrong.")
	}

	p.updateLook(controls)

	msgDebugRay := p.simulateBlaster(dt, world, controls)
	p.simulateMovement(dt, world, controls)

	p.controls = controls
	p.history.Add(controls.Timestamp, p.pos)

	return &MsgPlayerState{
		Pos: p.pos,
		VelocityY: p.vy,
		Timestamp: controls.Timestamp,
		Hp: p.hp,
	}, msgDebugRay
}

func (p *Player) simulateMovement(dt float64, world *World, controls *ControlState) {
	p.vy += dt * -9.81

	fw := 0.0
	if controls.Forward {
		fw = 1 * dt * 10
	} else if controls.Back {
		fw = -1 * dt * 10
	}

	rt := 0.0
	if controls.Right {
		rt = 1 * dt * 10
	} else if controls.Left {
		rt = -1 * dt * 10
	}

	cos := math.Cos
	sin := math.Sin

	move := coords.Vec3{
		X: -cos(controls.Lon) * fw + sin(controls.Lon) * rt,
		Y: p.vy * dt,
		Z: -sin(controls.Lon) * fw - cos(controls.Lon) * rt,
	}

	box := p.Box()

	move = box.AttemptMove(world, move)

	if (move.Y == 0) {
		if (controls.Jump) {
			p.vy = 6
		} else {
			p.vy = 0
		}
	}

	p.pos.X += move.X
	p.pos.Y += move.Y
	p.pos.Z += move.Z
}

func (p *Player) updateLook(controls *ControlState) {
	cos := math.Cos
	sin := math.Sin

	lat := controls.Lat
	lon := controls.Lon

	p.look.X = sin(lat) * cos(lon)
	p.look.Y = cos(lat)
	p.look.Z = sin(lat) * sin(lon)
}

func (p *Player) simulateBlaster(dt float64, world *World, controls *ControlState) *MsgDebugRay {
	if !controls.ActivateBlaster {
		return nil
	}

	// Compile a list of player bounding boxes, based on this shooters time
	var players []*physics.Box
	for _, v := range world.players {
		if v == p {
			players = append(players, nil)
			continue
		}
		players = append(players, v.BoxAt(controls.Timestamp))
	}

	ray := physics.NewRay(p.pos, p.look)
	target, index := ray.FindAnyIntersect(world, players)
	if index >= 0 {
		world.players[index].Hurt(10)
	}

	if target == nil {
		return nil
	}

	return &MsgDebugRay{
		Pos: *target,
	}
}

func (p *Player) Box() *physics.Box {
	return physics.NewBoxOffset(
		p.pos,
		PLAYER_HALF_EXTENTS,
		PLAYER_CENTER_OFFSET)
}

func (p *Player) BoxAt(t float64) *physics.Box {
	return physics.NewBoxOffset(
		p.history.PositionAt(t),
		PLAYER_HALF_EXTENTS,
		PLAYER_CENTER_OFFSET)
}

func (p *Player) Hurt(dmg int) {
	p.hp -= dmg
	if p.hp <= 0 {
		p.Respawn()
	}
}

func (p *Player) Respawn() {
	p.pos = PLAYER_SPAWN
	p.hp = PLAYER_MAX_HP
}
<|endoftext|>