<commit_before>package main

import (
	"bufio"
	"flag"
	"fmt"
	"log"
	"os"
	"runtime"
	"time"

	"github.com/dataence/bloom"
	"github.com/dataence/bloom/scalable"
	"github.com/jasonmoo/wc"
)

var (
	intersection = flag.Bool("i", false, "calculate the intersection")
	diff         = flag.Bool("d", false, "calculate the difference")
	union        = flag.Bool("u", false, "calculate the union")

	count = flag.Bool("c", false, "output counts of each token on non-large unions")

	// bloom processing
	large           = flag.Bool("large", false, "use bloom filters for large data size (may be lossy)")
	estimated_lines = flag.Uint64("estimated_lines", 0, "estimate used to size bloom filters (set this to avoid prescan)")

	// options
	trim          = flag.Bool("trim", false, "trim each line")
	match_regex   = flag.String("match", "", "only process matching lines")
	capture_regex = flag.String("capture", "", "only process captured data")

	// for fs opts
	devnull     = flag.Bool("devnull", false, "do not output tokens, just counts")
	buffer_size = flag.Int("buffer_size", 1<<20, "buffered io chunk size")

	// totals
	total_tokens_emitted  uint64
	total_bytes_processed uint64
	total_lines_scanned   uint64
	total_lines_matched   uint64
)

func init() {
	runtime.GOMAXPROCS(runtime.NumCPU())
}

func main() {

	flag.Parse()

	if !*intersection && !*diff && !*union {
		fmt.Println(`Usage: tt -[i,d,u] [-c] [-trim] [-match "regex"] [-capture "regex"] [-large [-estimated_lines N]] file1 file2[ file3..]`)
		flag.PrintDefaults()
		os.Exit(1)
	}

	start := time.Now()

	var stdout WriteFlusher

	if *devnull {
		stdout = new(DevNullWriter)
	} else {
		// buffered io
		stdout = bufio.NewWriterSize(os.Stdout, *buffer_size)
	}

	defer func() {
		stdout.Flush()
		fmt.Fprintln(os.Stderr, "** Token Report **")
		fmt.Fprintln(os.Stderr, "Lines scanned: ", total_lines_scanned)
		if *match_regex != "" {
			fmt.Fprintln(os.Stderr, "Lines matched: ", total_lines_matched)
		}
		fmt.Fprintln(os.Stderr, "Tokens emitted: ", total_tokens_emitted)
		fmt.Fprintln(os.Stderr, "Time: ", time.Since(start))
	}()

	file_paths := flag.Args()

	fmt.Fprintln(os.Stderr, "tt starting up")

	// if no estimate supplied, count lines
	if *large && *estimated_lines == 0 {

		var bytes_to_process uint64

		for _, file_path := range file_paths {

			file, err := os.Open(file_path)
			if err != nil {
				log.Fatal(err)
			}

			counter := wc.NewCounter(file)
			err = counter.Count(false, true, true, false)
			if err != nil {
				log.Fatal(err)
			}

			*estimated_lines += counter.Lines
			bytes_to_process += counter.Bytes

			file.Close()
		}

		fmt.Fprintln(os.Stderr, "Bytes to process: ", bytes_to_process)
		fmt.Fprintln(os.Stderr, "Lines to process: ", *estimated_lines)
	}

	if *large {

		if *union {

			unique_set := NewScalableBloom(*estimated_lines)

			for _, file_path := range file_paths {

				e, err := NewEmitter(file_path, *match_regex, *capture_regex, *buffer_size)
				if err != nil {
					log.Fatal(err)
				}

				for e.Scan() {
					token := e.Bytes()
					if !unique_set.Check(token) {
						total_tokens_emitted++
						stdout.Write(token)
						stdout.WriteByte('\n')
						unique_set.Add(token)
					}
				}

				e.Close()

				total_lines_scanned += e.LinesScanned

			}

			return
		}

		// multi file handling below
		sets := make([]bloom.Bloom, len(file_paths))

		// may require throttling due to disk thrashing
		// initial scan to fill the bloom filters
		for i, file_path := range file_paths {

			set := NewScalableBloom(*estimated_lines)

			e, err := NewEmitter(file_path, *match_regex, *capture_regex, *buffer_size)
			if err != nil {
				log.Fatal(err)
			}

			for e.Scan() {
				set.Add(e.Bytes())
			}

			e.Close()

			sets[i] = set

		}

		// do the work
		switch {

		// unique set of tokens that exist in all files
		case *intersection:

			echoed_set := NewScalableBloom(*estimated_lines)

			for _, file_path := range file_paths {

				e, err := NewEmitter(file_path, *match_regex, *capture_regex, *buffer_size)
				if err != nil {
					log.Fatal(err)
				}

			NEXT_TOKEN:
				for e.Scan() {

					token := e.Bytes()

					if echoed_set.Check(token) {
						goto NEXT_TOKEN
					}

					for _, set := range sets {
						if !set.Check(token) {
							goto NEXT_TOKEN
						}
					}

					total_tokens_emitted++
					stdout.Write(token)
					stdout.WriteByte('\n')
					echoed_set.Add(token)

				}

				total_lines_scanned += e.LinesScanned

				e.Close()

			}

		// unique set of tokens not in the intersection
		case *diff:

			echoed_set := NewScalableBloom(*estimated_lines)

			for _, file_path := range file_paths {

				e, err := NewEmitter(file_path, *match_regex, *capture_regex, *buffer_size)
				if err != nil {
					log.Fatal(err)
				}

				for e.Scan() {

					token := e.Bytes()

					if echoed_set.Check(token) {
						continue
					}

					for _, set := range sets {
						if !set.Check(token) {
							total_tokens_emitted++
							stdout.Write(token)
							stdout.WriteByte('\n')
							echoed_set.Add(token)
						}
					}

				}

				total_lines_scanned += e.LinesScanned

				e.Close()

			}
		}

		// defaults to map solution
	} else {

		if *union {

			unique_set := make(map[string]int)

			for _, file_path := range file_paths {

				e, err := NewEmitter(file_path, *match_regex, *capture_regex, *buffer_size)
				if err != nil {
					log.Fatal(err)
				}

				for e.Scan() {
					unique_set[e.Text()]++
				}

				total_lines_scanned += e.LinesScanned

				e.Close()

			}

			if *count {
				for token, ct := range unique_set {
					total_tokens_emitted++
					fmt.Fprintf(stdout, "%d: %s\n", ct, token)
				}
			} else {
				for token, _ := range unique_set {
					total_tokens_emitted++
					stdout.WriteString(token)
					stdout.WriteByte('\n')
				}
			}

			return
		}

		// multi file handling below
		sets := make([]map[string]bool, len(file_paths))

		// may require throttling due to disk thrashing
		// initial scan to fill the bloom filters
		for i, file_path := range file_paths {

			set := make(map[string]bool)

			e, err := NewEmitter(file_path, *match_regex, *capture_regex, *buffer_size)
			if err != nil {
				log.Fatal(err)
			}

			for e.Scan() {
				set[e.Text()] = true
			}

			e.Close()

			sets[i] = set

		}

		// do the work
		switch {

		// unique set of tokens that exist in all files
		case *intersection:

			echoed_set := make(map[string]bool)

			for _, file_path := range file_paths {

				e, err := NewEmitter(file_path, *match_regex, *capture_regex, *buffer_size)
				if err != nil {
					log.Fatal(err)
				}

			NEXT_TOKEN2:
				for e.Scan() {

					token := e.Text()

					if _, echoed := echoed_set[token]; echoed {
						goto NEXT_TOKEN2
					}

					for _, set := range sets {
						if _, in_this_set := set[token]; !in_this_set {
							goto NEXT_TOKEN2
						}
					}

					total_tokens_emitted++
					stdout.WriteString(token)
					stdout.WriteByte('\n')

					echoed_set[token] = true

				}

				total_lines_scanned += e.LinesScanned

				e.Close()

			}

		// unique set of tokens not in the intersection
		case *diff:

			echoed_set := make(map[string]bool)

			for _, file_path := range file_paths {

				e, err := NewEmitter(file_path, *match_regex, *capture_regex, *buffer_size)
				if err != nil {
					log.Fatal(err)
				}

				for e.Scan() {

					token := e.Text()

					if _, echoed := echoed_set[token]; echoed {
						continue
					}

					for _, set := range sets {
						if _, in_this_set := set[token]; !in_this_set {
							total_tokens_emitted++
							stdout.WriteString(token)
							stdout.WriteByte('\n')

							echoed_set[token] = true
							break
						}
					}

				}

				total_lines_scanned += e.LinesScanned

				e.Close()

			}
		}

	}

}

func NewScalableBloom(size uint64) bloom.Bloom {
	return scalable.New(uint(size))
}
<commit_msg>updating package location<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	"log"
	"os"
	"runtime"
	"time"

	"github.com/jasonmoo/wc"
	"github.com/zhenjl/bloom"
	"github.com/zhenjl/bloom/scalable"
)

var (
	intersection = flag.Bool("i", false, "calculate the intersection")
	diff         = flag.Bool("d", false, "calculate the difference")
	union        = flag.Bool("u", false, "calculate the union")

	count = flag.Bool("c", false, "output counts of each token on non-large unions")

	// bloom processing
	large           = flag.Bool("large", false, "use bloom filters for large data size (may be lossy)")
	estimated_lines = flag.Uint64("estimated_lines", 0, "estimate used to size bloom filters (set this to avoid prescan)")

	// options
	trim          = flag.Bool("trim", false, "trim each line")
	match_regex   = flag.String("match", "", "only process matching lines")
	capture_regex = flag.String("capture", "", "only process captured data")

	// for fs opts
	devnull     = flag.Bool("devnull", false, "do not output tokens, just counts")
	buffer_size = flag.Int("buffer_size", 1<<20, "buffered io chunk size")

	// totals
	total_tokens_emitted  uint64
	total_bytes_processed uint64
	total_lines_scanned   uint64
	total_lines_matched   uint64
)

func init() {
	runtime.GOMAXPROCS(runtime.NumCPU())
}

func main() {

	flag.Parse()

	if !*intersection && !*diff && !*union {
		fmt.Println(`Usage: tt -[i,d,u] [-c] [-trim] [-match "regex"] [-capture "regex"] [-large [-estimated_lines N]] file1 file2[ file3..]`)
		flag.PrintDefaults()
		os.Exit(1)
	}

	start := time.Now()

	var stdout WriteFlusher

	if *devnull {
		stdout = new(DevNullWriter)
	} else {
		// buffered io
		stdout = bufio.NewWriterSize(os.Stdout, *buffer_size)
	}

	defer func() {
		stdout.Flush()
		fmt.Fprintln(os.Stderr, "** Token Report **")
		fmt.Fprintln(os.Stderr, "Lines scanned: ", total_lines_scanned)
		if *match_regex != "" {
			fmt.Fprintln(os.Stderr, "Lines matched: ", total_lines_matched)
		}
		fmt.Fprintln(os.Stderr, "Tokens emitted: ", total_tokens_emitted)
		fmt.Fprintln(os.Stderr, "Time: ", time.Since(start))
	}()

	file_paths := flag.Args()

	fmt.Fprintln(os.Stderr, "tt starting up")

	// if no estimate supplied, count lines
	if *large && *estimated_lines == 0 {

		var bytes_to_process uint64

		for _, file_path := range file_paths {

			file, err := os.Open(file_path)
			if err != nil {
				log.Fatal(err)
			}

			counter := wc.NewCounter(file)
			err = counter.Count(false, true, true, false)
			if err != nil {
				log.Fatal(err)
			}

			*estimated_lines += counter.Lines
			bytes_to_process += counter.Bytes

			file.Close()
		}

		fmt.Fprintln(os.Stderr, "Bytes to process: ", bytes_to_process)
		fmt.Fprintln(os.Stderr, "Lines to process: ", *estimated_lines)
	}

	if *large {

		if *union {

			unique_set := NewScalableBloom(*estimated_lines)

			for _, file_path := range file_paths {

				e, err := NewEmitter(file_path, *match_regex, *capture_regex, *buffer_size)
				if err != nil {
					log.Fatal(err)
				}

				for e.Scan() {
					token := e.Bytes()
					if !unique_set.Check(token) {
						total_tokens_emitted++
						stdout.Write(token)
						stdout.WriteByte('\n')
						unique_set.Add(token)
					}
				}

				e.Close()

				total_lines_scanned += e.LinesScanned

			}

			return
		}

		// multi file handling below
		sets := make([]bloom.Bloom, len(file_paths))

		// may require throttling due to disk thrashing
		// initial scan to fill the bloom filters
		for i, file_path := range file_paths {

			set := NewScalableBloom(*estimated_lines)

			e, err := NewEmitter(file_path, *match_regex, *capture_regex, *buffer_size)
			if err != nil {
				log.Fatal(err)
			}

			for e.Scan() {
				set.Add(e.Bytes())
			}

			e.Close()

			sets[i] = set

		}

		// do the work
		switch {

		// unique set of tokens that exist in all files
		case *intersection:

			echoed_set := NewScalableBloom(*estimated_lines)

			for _, file_path := range file_paths {

				e, err := NewEmitter(file_path, *match_regex, *capture_regex, *buffer_size)
				if err != nil {
					log.Fatal(err)
				}

			NEXT_TOKEN:
				for e.Scan() {

					token := e.Bytes()

					if echoed_set.Check(token) {
						goto NEXT_TOKEN
					}

					for _, set := range sets {
						if !set.Check(token) {
							goto NEXT_TOKEN
						}
					}

					total_tokens_emitted++
					stdout.Write(token)
					stdout.WriteByte('\n')
					echoed_set.Add(token)

				}

				total_lines_scanned += e.LinesScanned

				e.Close()

			}

		// unique set of tokens not in the intersection
		case *diff:

			echoed_set := NewScalableBloom(*estimated_lines)

			for _, file_path := range file_paths {

				e, err := NewEmitter(file_path, *match_regex, *capture_regex, *buffer_size)
				if err != nil {
					log.Fatal(err)
				}

				for e.Scan() {

					token := e.Bytes()

					if echoed_set.Check(token) {
						continue
					}

					for _, set := range sets {
						if !set.Check(token) {
							total_tokens_emitted++
							stdout.Write(token)
							stdout.WriteByte('\n')
							echoed_set.Add(token)
						}
					}

				}

				total_lines_scanned += e.LinesScanned

				e.Close()

			}
		}

		// defaults to map solution
	} else {

		if *union {

			unique_set := make(map[string]int)

			for _, file_path := range file_paths {

				e, err := NewEmitter(file_path, *match_regex, *capture_regex, *buffer_size)
				if err != nil {
					log.Fatal(err)
				}

				for e.Scan() {
					unique_set[e.Text()]++
				}

				total_lines_scanned += e.LinesScanned

				e.Close()

			}

			if *count {
				for token, ct := range unique_set {
					total_tokens_emitted++
					fmt.Fprintf(stdout, "%d: %s\n", ct, token)
				}
			} else {
				for token, _ := range unique_set {
					total_tokens_emitted++
					stdout.WriteString(token)
					stdout.WriteByte('\n')
				}
			}

			return
		}

		// multi file handling below
		sets := make([]map[string]bool, len(file_paths))

		// may require throttling due to disk thrashing
		// initial scan to fill the bloom filters
		for i, file_path := range file_paths {

			set := make(map[string]bool)

			e, err := NewEmitter(file_path, *match_regex, *capture_regex, *buffer_size)
			if err != nil {
				log.Fatal(err)
			}

			for e.Scan() {
				set[e.Text()] = true
			}

			e.Close()

			sets[i] = set

		}

		// do the work
		switch {

		// unique set of tokens that exist in all files
		case *intersection:

			echoed_set := make(map[string]bool)

			for _, file_path := range file_paths {

				e, err := NewEmitter(file_path, *match_regex, *capture_regex, *buffer_size)
				if err != nil {
					log.Fatal(err)
				}

			NEXT_TOKEN2:
				for e.Scan() {

					token := e.Text()

					if _, echoed := echoed_set[token]; echoed {
						goto NEXT_TOKEN2
					}

					for _, set := range sets {
						if _, in_this_set := set[token]; !in_this_set {
							goto NEXT_TOKEN2
						}
					}

					total_tokens_emitted++
					stdout.WriteString(token)
					stdout.WriteByte('\n')

					echoed_set[token] = true

				}

				total_lines_scanned += e.LinesScanned

				e.Close()

			}

		// unique set of tokens not in the intersection
		case *diff:

			echoed_set := make(map[string]bool)

			for _, file_path := range file_paths {

				e, err := NewEmitter(file_path, *match_regex, *capture_regex, *buffer_size)
				if err != nil {
					log.Fatal(err)
				}

				for e.Scan() {

					token := e.Text()

					if _, echoed := echoed_set[token]; echoed {
						continue
					}

					for _, set := range sets {
						if _, in_this_set := set[token]; !in_this_set {
							total_tokens_emitted++
							stdout.WriteString(token)
							stdout.WriteByte('\n')

							echoed_set[token] = true
							break
						}
					}

				}

				total_lines_scanned += e.LinesScanned

				e.Close()

			}
		}

	}

}

func NewScalableBloom(size uint64) bloom.Bloom {
	return scalable.New(uint(size))
}
<|endoftext|>


<commit_before>package newrelic

import (
	"net/http"

	"golang.org/x/net/context"
)

// Tx represents a transaction.
type Tx interface {
	Start() error
	End() error
	StartGeneric(name string) error
	StartDatastore(table, operation, sql, rollupName string) error
	StartExternal(host, name string) error
	EndSegment() error
	ReportError(exceptionType, errorMessage, stackTrace, stackFrameDelim string) error
}

// tx implements the Tx interface.
type tx struct {
	Tracer   TxTracer
	Reporter TxReporter

	id   int64
	name string
	url  string
	ss   *SegmentStack
}

// NewTx returns a new transaction.
func NewTx(name string) *tx {
	return &tx{
		Tracer:   &NRTxTracer{},
		Reporter: &NRTxReporter{},
		name:     name,
		ss:       NewSegmentStack(),
	}
}

// NewRequestTx returns a new transaction with a request url.
func NewRequestTx(name string, url string) *tx {
	t := NewTx(name)
	t.url = url
	return t
}

// Start starts a transaction, setting the id.
func (t *tx) Start() error {
	var err error

	if t.id != 0 {
		return ErrTxAlreadyStarted
	}
	if t.id, err = t.Tracer.BeginTransaction(); err != nil {
		return err
	}
	if err = t.Tracer.SetTransactionName(t.id, t.name); err != nil {
		return err
	}
	if t.url != "" {
		return t.Tracer.SetTransactionRequestURL(t.id, t.url)
	}
	return nil
}

// End ends a transaction.
func (t *tx) End() error {
	for t.ss.Peek() != rootSegment {
		t.EndSegment()
	}
	return t.Tracer.EndTransaction(t.id)
}

// StartGeneric starts a generic segment.
func (t *tx) StartGeneric(name string) error {
	id, err := t.Tracer.BeginGenericSegment(t.id, t.ss.Peek(), name)
	if err != nil {
		return err
	}
	t.ss.Push(id)
	return nil
}

// StartDatastore starts a datastore segment.
func (t *tx) StartDatastore(table, operation, sql, rollupName string) error {
	id, err := t.Tracer.BeginDatastoreSegment(t.id, t.ss.Peek(), table, operation, sql, rollupName)
	if err != nil {
		return err
	}
	t.ss.Push(id)
	return nil
}

// StartExternal starts an external segment.
func (t *tx) StartExternal(host, name string) error {
	id, err := t.Tracer.BeginExternalSegment(t.id, t.ss.Peek(), host, name)
	if err != nil {
		return err
	}
	t.ss.Push(id)
	return nil
}

// EndSegment ends the segment at the top of the stack.
func (t *tx) EndSegment() error {
	if id, ok := t.ss.Pop(); ok {
		return t.Tracer.EndSegment(t.id, id)
	}
	return nil
}

// ReportError reports an error that occured during the transaction.
func (t *tx) ReportError(exceptionType, errorMessage, stackTrace, stackFrameDelim string) error {
	_, err := t.Reporter.ReportError(t.id, exceptionType, errorMessage, stackTrace, stackFrameDelim)
	return err
}

// WithTx inserts a newrelic.Tx into the provided context.
func WithTx(ctx context.Context, t Tx) context.Context {
	return context.WithValue(ctx, txKey, t)
}

// FromContext returns a newrelic.Tx from the context.
func FromContext(ctx context.Context) (Tx, bool) {
	t, ok := ctx.Value(txKey).(Tx)
	return t, ok
}

type Trace struct {
	err  error
	done func() error
}

func (t *Trace) Err() error {
	return t.err
}

func (t *Trace) Done() {
	if t.err == nil {
		t.err = t.done()
	}
}

// TraceReq traces an http request. It returns a new context with the transaction
// included in it, and a trace object.
//
// Usage:
//
//     ctx, t := TraceRequest(ctx, name, req)
//     defer t.Done()
func TraceRequest(ctx context.Context, name string, req *http.Request) (context.Context, *Trace) {
	tx := NewRequestTx(name, req.URL.String())
	ctx = WithTx(ctx, tx)
	err := tx.Start()

	return ctx, &Trace{
		err: err,
		done: func() error {
			return tx.End()
		},
	}
}

// TraceExternal adds an external segment to the newrelic transaction, if one exists in the context.
func TraceExternal(ctx context.Context, host, name string) *Trace {
	return trace(ctx, name, func(tx Tx) error {
		return tx.StartExternal(host, name)
	})
}

// TraceGeneric adds a generic segment to the newrelic transaction, if one exists in the context.
func TraceGeneric(ctx context.Context, name string) *Trace {
	return trace(ctx, name, func(tx Tx) error {
		return tx.StartGeneric(name)
	})
}

// trace is a helper function for TraceExternal and TraceGeneric, you probably don't want
// to use it directly.
func trace(ctx context.Context, name string, fn func(Tx) error) *Trace {
	if tx, ok := FromContext(ctx); ok {
		err := fn(tx)
		return &Trace{
			err: err,
			done: func() error {
				return tx.EndSegment()
			},
		}
	}
	return &Trace{nil, func() error { return nil }}
}

type key int

const (
	txKey key = iota
)
<commit_msg>Add TraceFunc<commit_after>package newrelic

import (
	"net/http"
	"path/filepath"
	"runtime"

	"golang.org/x/net/context"
)

// Tx represents a transaction.
type Tx interface {
	Start() error
	End() error
	StartGeneric(name string) error
	StartDatastore(table, operation, sql, rollupName string) error
	StartExternal(host, name string) error
	EndSegment() error
	ReportError(exceptionType, errorMessage, stackTrace, stackFrameDelim string) error
}

// tx implements the Tx interface.
type tx struct {
	Tracer   TxTracer
	Reporter TxReporter

	id   int64
	name string
	url  string
	ss   *SegmentStack
}

// NewTx returns a new transaction.
func NewTx(name string) *tx {
	return &tx{
		Tracer:   &NRTxTracer{},
		Reporter: &NRTxReporter{},
		name:     name,
		ss:       NewSegmentStack(),
	}
}

// NewRequestTx returns a new transaction with a request url.
func NewRequestTx(name string, url string) *tx {
	t := NewTx(name)
	t.url = url
	return t
}

// Start starts a transaction, setting the id.
func (t *tx) Start() error {
	var err error

	if t.id != 0 {
		return ErrTxAlreadyStarted
	}
	if t.id, err = t.Tracer.BeginTransaction(); err != nil {
		return err
	}
	if err = t.Tracer.SetTransactionName(t.id, t.name); err != nil {
		return err
	}
	if t.url != "" {
		return t.Tracer.SetTransactionRequestURL(t.id, t.url)
	}
	return nil
}

// End ends a transaction.
func (t *tx) End() error {
	for t.ss.Peek() != rootSegment {
		t.EndSegment()
	}
	return t.Tracer.EndTransaction(t.id)
}

// StartGeneric starts a generic segment.
func (t *tx) StartGeneric(name string) error {
	id, err := t.Tracer.BeginGenericSegment(t.id, t.ss.Peek(), name)
	if err != nil {
		return err
	}
	t.ss.Push(id)
	return nil
}

// StartDatastore starts a datastore segment.
func (t *tx) StartDatastore(table, operation, sql, rollupName string) error {
	id, err := t.Tracer.BeginDatastoreSegment(t.id, t.ss.Peek(), table, operation, sql, rollupName)
	if err != nil {
		return err
	}
	t.ss.Push(id)
	return nil
}

// StartExternal starts an external segment.
func (t *tx) StartExternal(host, name string) error {
	id, err := t.Tracer.BeginExternalSegment(t.id, t.ss.Peek(), host, name)
	if err != nil {
		return err
	}
	t.ss.Push(id)
	return nil
}

// EndSegment ends the segment at the top of the stack.
func (t *tx) EndSegment() error {
	if id, ok := t.ss.Pop(); ok {
		return t.Tracer.EndSegment(t.id, id)
	}
	return nil
}

// ReportError reports an error that occured during the transaction.
func (t *tx) ReportError(exceptionType, errorMessage, stackTrace, stackFrameDelim string) error {
	_, err := t.Reporter.ReportError(t.id, exceptionType, errorMessage, stackTrace, stackFrameDelim)
	return err
}

// WithTx inserts a newrelic.Tx into the provided context.
func WithTx(ctx context.Context, t Tx) context.Context {
	return context.WithValue(ctx, txKey, t)
}

// FromContext returns a newrelic.Tx from the context.
func FromContext(ctx context.Context) (Tx, bool) {
	t, ok := ctx.Value(txKey).(Tx)
	return t, ok
}

type Trace struct {
	err  error
	done func() error
}

func (t *Trace) Err() error {
	return t.err
}

func (t *Trace) Done() {
	if t.err == nil {
		t.err = t.done()
	}
}

// TraceReqest traces an http request. It returns a new context with the transaction
// included in it, and a trace object.
//
// Usage:
//
//     ctx, t := TraceRequest(ctx, name, req)
//     defer t.Done()
func TraceRequest(ctx context.Context, name string, req *http.Request) (context.Context, *Trace) {
	tx := NewRequestTx(name, req.URL.String())
	ctx = WithTx(ctx, tx)
	err := tx.Start()

	return ctx, &Trace{
		err: err,
		done: func() error {
			return tx.End()
		},
	}
}

// TraceExternal adds an external segment to the newrelic transaction, if one exists in the context.
func TraceExternal(ctx context.Context, host, name string) *Trace {
	return trace(ctx, name, func(tx Tx) error {
		return tx.StartExternal(host, name)
	})
}

// TraceGeneric adds a generic segment to the newrelic transaction, if one exists in the context.
func TraceGeneric(ctx context.Context, name string) *Trace {
	return trace(ctx, name, func(tx Tx) error {
		return tx.StartGeneric(name)
	})
}

// TraceDatastore adds a datastore segment to the newrelic transaction, if one exists in the context.
func TraceDatastore(ctx context.Context, table, operation, sql, rollupName string) *Trace {
	return trace(ctx, rollupName, func(tx Tx) error {
		return tx.StartDatastore(table, operation, sql, rollupName)
	})
}

// TraceFunc adds a generic segment, autodetecting the function name with runtime.Caller().
func TraceFunc(ctx context.Context) *Trace {
	name := caller(2) // Get the caller that called TraceFunc.
	return trace(ctx, name, func(tx Tx) error {
		return tx.StartGeneric(name)
	})
}

// trace is a helper function for TraceExternal and TraceGeneric, you probably don't want
// to use it directly.
func trace(ctx context.Context, name string, fn func(Tx) error) *Trace {
	if tx, ok := FromContext(ctx); ok {
		err := fn(tx)
		return &Trace{
			err: err,
			done: func() error {
				return tx.EndSegment()
			},
		}
	}
	return &Trace{nil, func() error { return nil }}
}

// caller returns the name of the function that called the function this function was called from.
// n = 1 => caller of caller()
// n = 2 => caller of caller of call()
// etc.
func caller(n int) string {
	name := "unknown"
	if pc, _, _, ok := runtime.Caller(n); ok {
		name = filepath.Base(runtime.FuncForPC(pc).Name())
	}
	return name
}

type key int

const (
	txKey key = iota
)
<|endoftext|>


<commit_before>// Copyright (c) 2013-2016 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package btcutil

import (
	"bytes"
	"io"

	"github.com/btcsuite/btcd/chaincfg/chainhash"
	"github.com/btcsuite/btcd/wire"
)

// TxIndexUnknown is the value returned for a transaction index that is unknown.
// This is typically because the transaction has not been inserted into a block
// yet.
const TxIndexUnknown = -1

// Tx defines a bitcoin transaction that provides easier and more efficient
// manipulation of raw transactions.  It also memoizes the hash for the
// transaction on its first access so subsequent accesses don't have to repeat
// the relatively expensive hashing operations.
type Tx struct {
	msgTx         *wire.MsgTx     // Underlying MsgTx
	txHash        *chainhash.Hash // Cached transaction hash
	txHashWitness *chainhash.Hash // Cached transaction witness hash
	txIndex       int             // Position within a block or TxIndexUnknown
}

// MsgTx returns the underlying wire.MsgTx for the transaction.
func (t *Tx) MsgTx() *wire.MsgTx {
	// Return the cached transaction.
	return t.msgTx
}

// Hash returns the hash of the transaction.  This is equivalent to
// calling TxHash on the underlying wire.MsgTx, however it caches the
// result so subsequent calls are more efficient.
func (t *Tx) Hash() *chainhash.Hash {
	// Return the cached hash if it has already been generated.
	if t.txHash != nil {
		return t.txHash
	}

	// Cache the hash and return it.
	hash := t.msgTx.TxHash()
	t.txHash = &hash
	return &hash
}

// WitnessHash returns the witness hash (wtxid) of the transaction.  This is
// equivalent to calling WitnessHash on the underlying wire.MsgTx, however it
// caches the result so subsequent calls are more efficient.
func (t *Tx) WitnessHash() *chainhash.Hash {
	// Return the cached hash if it has already been generated.
	if t.txHashWitness != nil {
		return t.txHashWitness
	}

	// Cache the hash and return it.
	hash := t.msgTx.WitnessHash()
	t.txHashWitness = &hash
	return &hash
}

// Index returns the saved index of the transaction within a block.  This value
// will be TxIndexUnknown if it hasn't already explicitly been set.
func (t *Tx) Index() int {
	return t.txIndex
}

// SetIndex sets the index of the transaction in within a block.
func (t *Tx) SetIndex(index int) {
	t.txIndex = index
}

// NewTx returns a new instance of a bitcoin transaction given an underlying
// wire.MsgTx.  See Tx.
func NewTx(msgTx *wire.MsgTx) *Tx {
	return &Tx{
		msgTx:   msgTx,
		txIndex: TxIndexUnknown,
	}
}

// NewTxFromBytes returns a new instance of a bitcoin transaction given the
// serialized bytes.  See Tx.
func NewTxFromBytes(serializedTx []byte) (*Tx, error) {
	br := bytes.NewReader(serializedTx)
	return NewTxFromReader(br)
}

// NewTxFromReader returns a new instance of a bitcoin transaction given a
// Reader to deserialize the transaction.  See Tx.
func NewTxFromReader(r io.Reader) (*Tx, error) {
	// Deserialize the bytes into a MsgTx.
	var msgTx wire.MsgTx
	err := msgTx.Deserialize(r)
	if err != nil {
		return nil, err
	}

	t := Tx{
		msgTx:   &msgTx,
		txIndex: TxIndexUnknown,
	}
	return &t, nil
}
<commit_msg>add cached version of HasWitness<commit_after>// Copyright (c) 2013-2016 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package btcutil

import (
	"bytes"
	"io"

	"github.com/btcsuite/btcd/chaincfg/chainhash"
	"github.com/btcsuite/btcd/wire"
)

// TxIndexUnknown is the value returned for a transaction index that is unknown.
// This is typically because the transaction has not been inserted into a block
// yet.
const TxIndexUnknown = -1

// Tx defines a bitcoin transaction that provides easier and more efficient
// manipulation of raw transactions.  It also memoizes the hash for the
// transaction on its first access so subsequent accesses don't have to repeat
// the relatively expensive hashing operations.
type Tx struct {
	msgTx         *wire.MsgTx     // Underlying MsgTx
	txHash        *chainhash.Hash // Cached transaction hash
	txHashWitness *chainhash.Hash // Cached transaction witness hash
	txHasWitness  *bool           // If the transaction has witness data
	txIndex       int             // Position within a block or TxIndexUnknown
}

// MsgTx returns the underlying wire.MsgTx for the transaction.
func (t *Tx) MsgTx() *wire.MsgTx {
	// Return the cached transaction.
	return t.msgTx
}

// Hash returns the hash of the transaction.  This is equivalent to
// calling TxHash on the underlying wire.MsgTx, however it caches the
// result so subsequent calls are more efficient.
func (t *Tx) Hash() *chainhash.Hash {
	// Return the cached hash if it has already been generated.
	if t.txHash != nil {
		return t.txHash
	}

	// Cache the hash and return it.
	hash := t.msgTx.TxHash()
	t.txHash = &hash
	return &hash
}

// WitnessHash returns the witness hash (wtxid) of the transaction.  This is
// equivalent to calling WitnessHash on the underlying wire.MsgTx, however it
// caches the result so subsequent calls are more efficient.
func (t *Tx) WitnessHash() *chainhash.Hash {
	// Return the cached hash if it has already been generated.
	if t.txHashWitness != nil {
		return t.txHashWitness
	}

	// Cache the hash and return it.
	hash := t.msgTx.WitnessHash()
	t.txHashWitness = &hash
	return &hash
}

// HasWitness returns false if none of the inputs within the transaction
// contain witness data, true false otherwise. This equivalent to calling
// HasWitness on the underlying wire.MsgTx, however it caches the result so
// subsequent calls are more efficient.
func (t *Tx) HasWitness() bool {
	if t.txHashWitness != nil {
		return *t.txHasWitness
	}

	hasWitness := t.msgTx.HasWitness()
	t.txHasWitness = &hasWitness
	return hasWitness
}

// Index returns the saved index of the transaction within a block.  This value
// will be TxIndexUnknown if it hasn't already explicitly been set.
func (t *Tx) Index() int {
	return t.txIndex
}

// SetIndex sets the index of the transaction in within a block.
func (t *Tx) SetIndex(index int) {
	t.txIndex = index
}

// NewTx returns a new instance of a bitcoin transaction given an underlying
// wire.MsgTx.  See Tx.
func NewTx(msgTx *wire.MsgTx) *Tx {
	return &Tx{
		msgTx:   msgTx,
		txIndex: TxIndexUnknown,
	}
}

// NewTxFromBytes returns a new instance of a bitcoin transaction given the
// serialized bytes.  See Tx.
func NewTxFromBytes(serializedTx []byte) (*Tx, error) {
	br := bytes.NewReader(serializedTx)
	return NewTxFromReader(br)
}

// NewTxFromReader returns a new instance of a bitcoin transaction given a
// Reader to deserialize the transaction.  See Tx.
func NewTxFromReader(r io.Reader) (*Tx, error) {
	// Deserialize the bytes into a MsgTx.
	var msgTx wire.MsgTx
	err := msgTx.Deserialize(r)
	if err != nil {
		return nil, err
	}

	t := Tx{
		msgTx:   &msgTx,
		txIndex: TxIndexUnknown,
	}
	return &t, nil
}
<|endoftext|>


<commit_before>package pgx

import (
	"bytes"
	"context"
	"fmt"
	"strconv"

	"github.com/jackc/pgconn"
	errors "golang.org/x/xerrors"
)

type TxIsoLevel string

// Transaction isolation levels
const (
	Serializable    = TxIsoLevel("serializable")
	RepeatableRead  = TxIsoLevel("repeatable read")
	ReadCommitted   = TxIsoLevel("read committed")
	ReadUncommitted = TxIsoLevel("read uncommitted")
)

type TxAccessMode string

// Transaction access modes
const (
	ReadWrite = TxAccessMode("read write")
	ReadOnly  = TxAccessMode("read only")
)

type TxDeferrableMode string

// Transaction deferrable modes
const (
	Deferrable    = TxDeferrableMode("deferrable")
	NotDeferrable = TxDeferrableMode("not deferrable")
)

type TxOptions struct {
	IsoLevel       TxIsoLevel
	AccessMode     TxAccessMode
	DeferrableMode TxDeferrableMode
}

func (txOptions TxOptions) beginSQL() string {
	buf := &bytes.Buffer{}
	buf.WriteString("begin")
	if txOptions.IsoLevel != "" {
		fmt.Fprintf(buf, " isolation level %s", txOptions.IsoLevel)
	}
	if txOptions.AccessMode != "" {
		fmt.Fprintf(buf, " %s", txOptions.AccessMode)
	}
	if txOptions.DeferrableMode != "" {
		fmt.Fprintf(buf, " %s", txOptions.DeferrableMode)
	}

	return buf.String()
}

var ErrTxClosed = errors.New("tx is closed")

// ErrTxCommitRollback occurs when an error has occurred in a transaction and
// Commit() is called. PostgreSQL accepts COMMIT on aborted transactions, but
// it is treated as ROLLBACK.
var ErrTxCommitRollback = errors.New("commit unexpectedly resulted in rollback")

// Begin starts a transaction. Unlike database/sql, the context only affects the begin command. i.e. there is no
// auto-rollback on context cancellation.
func (c *Conn) Begin(ctx context.Context) (*dbTx, error) {
	return c.BeginTx(ctx, TxOptions{})
}

// BeginTx starts a transaction with txOptions determining the transaction mode. Unlike database/sql, the context only
// affects the begin command. i.e. there is no auto-rollback on context cancellation.
func (c *Conn) BeginTx(ctx context.Context, txOptions TxOptions) (*dbTx, error) {
	_, err := c.Exec(ctx, txOptions.beginSQL())
	if err != nil {
		// begin should never fail unless there is an underlying connection issue or
		// a context timeout. In either case, the connection is possibly broken.
		c.die(errors.New("failed to begin transaction"))
		return nil, err
	}

	return &dbTx{conn: c}, nil
}

type Tx interface {
	// Begin starts a pseudo nested transaction
	Begin(ctx context.Context) (Tx, error)
	Commit(ctx context.Context) error
	Rollback(ctx context.Context) error

	CopyFrom(ctx context.Context, tableName Identifier, columnNames []string, rowSrc CopyFromSource) (int64, error)
	SendBatch(ctx context.Context, b *Batch) BatchResults
	LargeObjects() LargeObjects

	Prepare(ctx context.Context, name, sql string) (*pgconn.StatementDescription, error)

	Exec(ctx context.Context, sql string, arguments ...interface{}) (commandTag pgconn.CommandTag, err error)
	Query(ctx context.Context, sql string, args ...interface{}) (Rows, error)
	QueryRow(ctx context.Context, sql string, args ...interface{}) Row
}

// dbTx represents a database transaction.
//
// All dbTx methods return ErrTxClosed if Commit or Rollback has already been
// called on the dbTx.
type dbTx struct {
	conn         *Conn
	err          error
	savepointNum int64
	closed       bool
}

// Begin starts a pseudo nested transaction implemented with a savepoint.
func (tx *dbTx) Begin(ctx context.Context) (Tx, error) {
	if tx.closed {
		return nil, ErrTxClosed
	}

	tx.savepointNum += 1
	_, err := tx.conn.Exec(ctx, "savepoint sp_"+strconv.FormatInt(tx.savepointNum, 10))
	if err != nil {
		return nil, err
	}

	return &dbSavepoint{tx: tx, savepointNum: tx.savepointNum}, nil
}

// Commit commits the transaction.
func (tx *dbTx) Commit(ctx context.Context) error {
	if tx.closed {
		return ErrTxClosed
	}

	commandTag, err := tx.conn.Exec(ctx, "commit")
	tx.closed = true
	if err != nil {
		// A commit failure leaves the connection in an undefined state so kill the connection (though any error that could
		// cause this to fail should have already killed the connection)
		tx.conn.die(errors.Errorf("commit failed: %w", err))
		return err
	}
	if string(commandTag) == "ROLLBACK" {
		return ErrTxCommitRollback
	}

	return nil
}

// Rollback rolls back the transaction. Rollback will return ErrTxClosed if the
// Tx is already closed, but is otherwise safe to call multiple times. Hence, a
// defer tx.Rollback() is safe even if tx.Commit() will be called first in a
// non-error condition.
func (tx *dbTx) Rollback(ctx context.Context) error {
	if tx.closed {
		return ErrTxClosed
	}

	_, err := tx.conn.Exec(ctx, "rollback")
	tx.closed = true
	if err != nil {
		// A rollback failure leaves the connection in an undefined state
		tx.conn.die(errors.Errorf("rollback failed: %w", err))
		return err
	}

	return nil
}

// Exec delegates to the underlying *Conn
func (tx *dbTx) Exec(ctx context.Context, sql string, arguments ...interface{}) (commandTag pgconn.CommandTag, err error) {
	return tx.conn.Exec(ctx, sql, arguments...)
}

// Prepare delegates to the underlying *Conn
func (tx *dbTx) Prepare(ctx context.Context, name, sql string) (*pgconn.StatementDescription, error) {
	if tx.closed {
		return nil, ErrTxClosed
	}

	return tx.conn.Prepare(ctx, name, sql)
}

// Query delegates to the underlying *Conn
func (tx *dbTx) Query(ctx context.Context, sql string, args ...interface{}) (Rows, error) {
	if tx.closed {
		// Because checking for errors can be deferred to the *Rows, build one with the error
		err := ErrTxClosed
		return &connRows{closed: true, err: err}, err
	}

	return tx.conn.Query(ctx, sql, args...)
}

// QueryRow delegates to the underlying *Conn
func (tx *dbTx) QueryRow(ctx context.Context, sql string, args ...interface{}) Row {
	rows, _ := tx.Query(ctx, sql, args...)
	return (*connRow)(rows.(*connRows))
}

// CopyFrom delegates to the underlying *Conn
func (tx *dbTx) CopyFrom(ctx context.Context, tableName Identifier, columnNames []string, rowSrc CopyFromSource) (int64, error) {
	if tx.closed {
		return 0, ErrTxClosed
	}

	return tx.conn.CopyFrom(ctx, tableName, columnNames, rowSrc)
}

// SendBatch delegates to the underlying *Conn
func (tx *dbTx) SendBatch(ctx context.Context, b *Batch) BatchResults {
	if tx.closed {
		return &batchResults{err: ErrTxClosed}
	}

	return tx.conn.SendBatch(ctx, b)
}

// LargeObjects returns a LargeObjects instance for the transaction.
func (tx *dbTx) LargeObjects() LargeObjects {
	return LargeObjects{tx: tx}
}

// dbSavepoint represents a nested transaction implemented by a savepoint.
type dbSavepoint struct {
	tx           Tx
	savepointNum int64
	closed       bool
}

// Begin starts a pseudo nested transaction implemented with a savepoint.
func (sp *dbSavepoint) Begin(ctx context.Context) (Tx, error) {
	if sp.closed {
		return nil, ErrTxClosed
	}

	return sp.Begin(ctx)
}

// Commit releases the savepoint essentially committing the pseudo nested transaction.
func (sp *dbSavepoint) Commit(ctx context.Context) error {
	_, err := sp.Exec(ctx, "release savepoint sp_"+strconv.FormatInt(sp.savepointNum, 10))
	sp.closed = true
	return err
}

// Rollback rolls back to the savepoint essentially rolling back the pseudo nested transaction. Rollback will return
// ErrTxClosed if the dbSavepoint is already closed, but is otherwise safe to call multiple times. Hence, a defer sp.Rollback()
// is safe even if sp.Commit() will be called first in a non-error condition.
func (sp *dbSavepoint) Rollback(ctx context.Context) error {
	_, err := sp.Exec(ctx, "rollback to savepoint sp_"+strconv.FormatInt(sp.savepointNum, 10))
	sp.closed = true
	return err
}

// Exec delegates to the underlying Tx
func (sp *dbSavepoint) Exec(ctx context.Context, sql string, arguments ...interface{}) (commandTag pgconn.CommandTag, err error) {
	if sp.closed {
		return nil, ErrTxClosed
	}

	return sp.tx.Exec(ctx, sql, arguments...)
}

// Prepare delegates to the underlying Tx
func (sp *dbSavepoint) Prepare(ctx context.Context, name, sql string) (*pgconn.StatementDescription, error) {
	if sp.closed {
		return nil, ErrTxClosed
	}

	return sp.tx.Prepare(ctx, name, sql)
}

// Query delegates to the underlying Tx
func (sp *dbSavepoint) Query(ctx context.Context, sql string, args ...interface{}) (Rows, error) {
	if sp.closed {
		// Because checking for errors can be deferred to the *Rows, build one with the error
		err := ErrTxClosed
		return &connRows{closed: true, err: err}, err
	}

	return sp.tx.Query(ctx, sql, args...)
}

// QueryRow delegates to the underlying Tx
func (sp *dbSavepoint) QueryRow(ctx context.Context, sql string, args ...interface{}) Row {
	rows, _ := sp.Query(ctx, sql, args...)
	return (*connRow)(rows.(*connRows))
}

// CopyFrom delegates to the underlying *Conn
func (sp *dbSavepoint) CopyFrom(ctx context.Context, tableName Identifier, columnNames []string, rowSrc CopyFromSource) (int64, error) {
	if sp.closed {
		return 0, ErrTxClosed
	}

	return sp.tx.CopyFrom(ctx, tableName, columnNames, rowSrc)
}

// SendBatch delegates to the underlying *Conn
func (sp *dbSavepoint) SendBatch(ctx context.Context, b *Batch) BatchResults {
	if sp.closed {
		return &batchResults{err: ErrTxClosed}
	}

	return sp.tx.SendBatch(ctx, b)
}

func (sp *dbSavepoint) LargeObjects() LargeObjects {
	return LargeObjects{tx: sp}
}
<commit_msg>Check if dbSavepoint is already closed<commit_after>package pgx

import (
	"bytes"
	"context"
	"fmt"
	"strconv"

	"github.com/jackc/pgconn"
	errors "golang.org/x/xerrors"
)

type TxIsoLevel string

// Transaction isolation levels
const (
	Serializable    = TxIsoLevel("serializable")
	RepeatableRead  = TxIsoLevel("repeatable read")
	ReadCommitted   = TxIsoLevel("read committed")
	ReadUncommitted = TxIsoLevel("read uncommitted")
)

type TxAccessMode string

// Transaction access modes
const (
	ReadWrite = TxAccessMode("read write")
	ReadOnly  = TxAccessMode("read only")
)

type TxDeferrableMode string

// Transaction deferrable modes
const (
	Deferrable    = TxDeferrableMode("deferrable")
	NotDeferrable = TxDeferrableMode("not deferrable")
)

type TxOptions struct {
	IsoLevel       TxIsoLevel
	AccessMode     TxAccessMode
	DeferrableMode TxDeferrableMode
}

func (txOptions TxOptions) beginSQL() string {
	buf := &bytes.Buffer{}
	buf.WriteString("begin")
	if txOptions.IsoLevel != "" {
		fmt.Fprintf(buf, " isolation level %s", txOptions.IsoLevel)
	}
	if txOptions.AccessMode != "" {
		fmt.Fprintf(buf, " %s", txOptions.AccessMode)
	}
	if txOptions.DeferrableMode != "" {
		fmt.Fprintf(buf, " %s", txOptions.DeferrableMode)
	}

	return buf.String()
}

var ErrTxClosed = errors.New("tx is closed")

// ErrTxCommitRollback occurs when an error has occurred in a transaction and
// Commit() is called. PostgreSQL accepts COMMIT on aborted transactions, but
// it is treated as ROLLBACK.
var ErrTxCommitRollback = errors.New("commit unexpectedly resulted in rollback")

// Begin starts a transaction. Unlike database/sql, the context only affects the begin command. i.e. there is no
// auto-rollback on context cancellation.
func (c *Conn) Begin(ctx context.Context) (*dbTx, error) {
	return c.BeginTx(ctx, TxOptions{})
}

// BeginTx starts a transaction with txOptions determining the transaction mode. Unlike database/sql, the context only
// affects the begin command. i.e. there is no auto-rollback on context cancellation.
func (c *Conn) BeginTx(ctx context.Context, txOptions TxOptions) (*dbTx, error) {
	_, err := c.Exec(ctx, txOptions.beginSQL())
	if err != nil {
		// begin should never fail unless there is an underlying connection issue or
		// a context timeout. In either case, the connection is possibly broken.
		c.die(errors.New("failed to begin transaction"))
		return nil, err
	}

	return &dbTx{conn: c}, nil
}

type Tx interface {
	// Begin starts a pseudo nested transaction
	Begin(ctx context.Context) (Tx, error)
	Commit(ctx context.Context) error
	Rollback(ctx context.Context) error

	CopyFrom(ctx context.Context, tableName Identifier, columnNames []string, rowSrc CopyFromSource) (int64, error)
	SendBatch(ctx context.Context, b *Batch) BatchResults
	LargeObjects() LargeObjects

	Prepare(ctx context.Context, name, sql string) (*pgconn.StatementDescription, error)

	Exec(ctx context.Context, sql string, arguments ...interface{}) (commandTag pgconn.CommandTag, err error)
	Query(ctx context.Context, sql string, args ...interface{}) (Rows, error)
	QueryRow(ctx context.Context, sql string, args ...interface{}) Row
}

// dbTx represents a database transaction.
//
// All dbTx methods return ErrTxClosed if Commit or Rollback has already been
// called on the dbTx.
type dbTx struct {
	conn         *Conn
	err          error
	savepointNum int64
	closed       bool
}

// Begin starts a pseudo nested transaction implemented with a savepoint.
func (tx *dbTx) Begin(ctx context.Context) (Tx, error) {
	if tx.closed {
		return nil, ErrTxClosed
	}

	tx.savepointNum += 1
	_, err := tx.conn.Exec(ctx, "savepoint sp_"+strconv.FormatInt(tx.savepointNum, 10))
	if err != nil {
		return nil, err
	}

	return &dbSavepoint{tx: tx, savepointNum: tx.savepointNum}, nil
}

// Commit commits the transaction.
func (tx *dbTx) Commit(ctx context.Context) error {
	if tx.closed {
		return ErrTxClosed
	}

	commandTag, err := tx.conn.Exec(ctx, "commit")
	tx.closed = true
	if err != nil {
		// A commit failure leaves the connection in an undefined state so kill the connection (though any error that could
		// cause this to fail should have already killed the connection)
		tx.conn.die(errors.Errorf("commit failed: %w", err))
		return err
	}
	if string(commandTag) == "ROLLBACK" {
		return ErrTxCommitRollback
	}

	return nil
}

// Rollback rolls back the transaction. Rollback will return ErrTxClosed if the
// Tx is already closed, but is otherwise safe to call multiple times. Hence, a
// defer tx.Rollback() is safe even if tx.Commit() will be called first in a
// non-error condition.
func (tx *dbTx) Rollback(ctx context.Context) error {
	if tx.closed {
		return ErrTxClosed
	}

	_, err := tx.conn.Exec(ctx, "rollback")
	tx.closed = true
	if err != nil {
		// A rollback failure leaves the connection in an undefined state
		tx.conn.die(errors.Errorf("rollback failed: %w", err))
		return err
	}

	return nil
}

// Exec delegates to the underlying *Conn
func (tx *dbTx) Exec(ctx context.Context, sql string, arguments ...interface{}) (commandTag pgconn.CommandTag, err error) {
	return tx.conn.Exec(ctx, sql, arguments...)
}

// Prepare delegates to the underlying *Conn
func (tx *dbTx) Prepare(ctx context.Context, name, sql string) (*pgconn.StatementDescription, error) {
	if tx.closed {
		return nil, ErrTxClosed
	}

	return tx.conn.Prepare(ctx, name, sql)
}

// Query delegates to the underlying *Conn
func (tx *dbTx) Query(ctx context.Context, sql string, args ...interface{}) (Rows, error) {
	if tx.closed {
		// Because checking for errors can be deferred to the *Rows, build one with the error
		err := ErrTxClosed
		return &connRows{closed: true, err: err}, err
	}

	return tx.conn.Query(ctx, sql, args...)
}

// QueryRow delegates to the underlying *Conn
func (tx *dbTx) QueryRow(ctx context.Context, sql string, args ...interface{}) Row {
	rows, _ := tx.Query(ctx, sql, args...)
	return (*connRow)(rows.(*connRows))
}

// CopyFrom delegates to the underlying *Conn
func (tx *dbTx) CopyFrom(ctx context.Context, tableName Identifier, columnNames []string, rowSrc CopyFromSource) (int64, error) {
	if tx.closed {
		return 0, ErrTxClosed
	}

	return tx.conn.CopyFrom(ctx, tableName, columnNames, rowSrc)
}

// SendBatch delegates to the underlying *Conn
func (tx *dbTx) SendBatch(ctx context.Context, b *Batch) BatchResults {
	if tx.closed {
		return &batchResults{err: ErrTxClosed}
	}

	return tx.conn.SendBatch(ctx, b)
}

// LargeObjects returns a LargeObjects instance for the transaction.
func (tx *dbTx) LargeObjects() LargeObjects {
	return LargeObjects{tx: tx}
}

// dbSavepoint represents a nested transaction implemented by a savepoint.
type dbSavepoint struct {
	tx           Tx
	savepointNum int64
	closed       bool
}

// Begin starts a pseudo nested transaction implemented with a savepoint.
func (sp *dbSavepoint) Begin(ctx context.Context) (Tx, error) {
	if sp.closed {
		return nil, ErrTxClosed
	}

	return sp.Begin(ctx)
}

// Commit releases the savepoint essentially committing the pseudo nested transaction.
func (sp *dbSavepoint) Commit(ctx context.Context) error {
	if sp.closed {
		return ErrTxClosed
	}

	_, err := sp.Exec(ctx, "release savepoint sp_"+strconv.FormatInt(sp.savepointNum, 10))
	sp.closed = true
	return err
}

// Rollback rolls back to the savepoint essentially rolling back the pseudo nested transaction. Rollback will return
// ErrTxClosed if the dbSavepoint is already closed, but is otherwise safe to call multiple times. Hence, a defer sp.Rollback()
// is safe even if sp.Commit() will be called first in a non-error condition.
func (sp *dbSavepoint) Rollback(ctx context.Context) error {
	if sp.closed {
		return ErrTxClosed
	}

	_, err := sp.Exec(ctx, "rollback to savepoint sp_"+strconv.FormatInt(sp.savepointNum, 10))
	sp.closed = true
	return err
}

// Exec delegates to the underlying Tx
func (sp *dbSavepoint) Exec(ctx context.Context, sql string, arguments ...interface{}) (commandTag pgconn.CommandTag, err error) {
	if sp.closed {
		return nil, ErrTxClosed
	}

	return sp.tx.Exec(ctx, sql, arguments...)
}

// Prepare delegates to the underlying Tx
func (sp *dbSavepoint) Prepare(ctx context.Context, name, sql string) (*pgconn.StatementDescription, error) {
	if sp.closed {
		return nil, ErrTxClosed
	}

	return sp.tx.Prepare(ctx, name, sql)
}

// Query delegates to the underlying Tx
func (sp *dbSavepoint) Query(ctx context.Context, sql string, args ...interface{}) (Rows, error) {
	if sp.closed {
		// Because checking for errors can be deferred to the *Rows, build one with the error
		err := ErrTxClosed
		return &connRows{closed: true, err: err}, err
	}

	return sp.tx.Query(ctx, sql, args...)
}

// QueryRow delegates to the underlying Tx
func (sp *dbSavepoint) QueryRow(ctx context.Context, sql string, args ...interface{}) Row {
	rows, _ := sp.Query(ctx, sql, args...)
	return (*connRow)(rows.(*connRows))
}

// CopyFrom delegates to the underlying *Conn
func (sp *dbSavepoint) CopyFrom(ctx context.Context, tableName Identifier, columnNames []string, rowSrc CopyFromSource) (int64, error) {
	if sp.closed {
		return 0, ErrTxClosed
	}

	return sp.tx.CopyFrom(ctx, tableName, columnNames, rowSrc)
}

// SendBatch delegates to the underlying *Conn
func (sp *dbSavepoint) SendBatch(ctx context.Context, b *Batch) BatchResults {
	if sp.closed {
		return &batchResults{err: ErrTxClosed}
	}

	return sp.tx.SendBatch(ctx, b)
}

func (sp *dbSavepoint) LargeObjects() LargeObjects {
	return LargeObjects{tx: sp}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"strconv"
	"os"
	stfl "github.com/akrennmair/go-stfl"
)

type UserInterface struct {
	form                  *stfl.Form
	actionchan            chan UserInterfaceAction
	tweetchan             chan []*Tweet
	cmdchan               chan TwitterCommand
	lookupchan            chan TweetRequest
	in_reply_to_status_id int64
}

type ActionId int

const (
	RESET_LAST_LINE ActionId = iota
	RAW_INPUT
	UPDATE_RATELIMIT
)

type UserInterfaceAction struct {
	Action ActionId
	Args   []string
}

func NewUserInterface(cc chan TwitterCommand, tc chan []*Tweet, lc chan TweetRequest, uac chan UserInterfaceAction) *UserInterface {
	stfl.Init()
	ui := &UserInterface{
		form:                  stfl.Create("<ui.stfl>"),
		actionchan:            uac,
		tweetchan:             tc,
		cmdchan:               cc,
		in_reply_to_status_id: 0,
		lookupchan:            lc,
	}
	return ui
}

func (ui *UserInterface) GetActionChannel() chan UserInterfaceAction {
	return ui.actionchan
}

func (ui *UserInterface) Run() {
	for {
		select {
		case newtweets := <-ui.tweetchan:
			str := formatTweets(newtweets)
			ui.form.Modify("tweets", "insert_inner", str)
			ui.form.Run(-1)
		case action := <-ui.actionchan:
			ui.HandleAction(action)
		}
	}
}

func (ui *UserInterface) HandleAction(action UserInterfaceAction) {
	switch action.Action {
	case RESET_LAST_LINE:
		ui.ResetLastLine()
	case RAW_INPUT:
		input := action.Args[0]
		ui.HandleRawInput(input)
	case UPDATE_RATELIMIT:
		rem, _ := strconv.Atoui(action.Args[0])
		limit, _ := strconv.Atoui(action.Args[1])
		reset, _ := strconv.Atoi64(action.Args[2])
		newtext := fmt.Sprintf("Next reset: %d min %d/%d", reset/60, rem, limit)
		ui.form.Set("rateinfo", newtext)
		ui.form.Run(-1)
	}
}

func (ui *UserInterface) ResetLastLine() {
	ui.form.Modify("lastline", "replace", "{hbox[lastline] .expand:0 {label text[msg]:\"\" .expand:h}}")
}

func (ui *UserInterface) HandleRawInput(input string) {
	switch input {
	case "ENTER":
		ui.SetInputField("Tweet: ", "", "end-input")
	case "r":
		var err os.Error
		ui.in_reply_to_status_id, err = strconv.Atoi64(ui.form.Get("status_id"))
		if err != nil {
			// TODO: show error
			break
		}
		tweet := ui.LookupTweet(ui.in_reply_to_status_id)
		if tweet != nil {
			ui.SetInputField("Reply: ", "@"+*tweet.User.Screen_name+" ","end-input")
		} else {
			//TODO: show error
		}
	case "^R":
		status_id, err := strconv.Atoi64(ui.form.Get("status_id"))
		if err != nil {
			// TODO: show error
			break
		}
		status_id_ptr := new(int64)
		*status_id_ptr = status_id
		ui.cmdchan <- TwitterCommand{Cmd: RETWEET, Data: Tweet{Id: status_id_ptr}}
	case "end-input":
		tweet_text := new(string)
		*tweet_text = ui.form.Get("inputfield")
		if len(*tweet_text) > 0 {
			t := Tweet{Text: tweet_text}
			if ui.in_reply_to_status_id != 0 {
				t.In_reply_to_status_id = new(int64)
				*t.In_reply_to_status_id = ui.in_reply_to_status_id
				ui.in_reply_to_status_id = int64(0)
			}
			ui.cmdchan <- TwitterCommand{Cmd: UPDATE, Data: t}
		}
		ui.ResetLastLine()
	case "cancel-input":
		ui.ResetLastLine()
	}
	ui.form.Run(-1)
}

func (ui *UserInterface) LookupTweet(status_id int64) *Tweet {
	reply := make(chan *Tweet)
	req := TweetRequest{Status_id: status_id, Reply: reply}
	ui.lookupchan <- req
	return <-reply
}

func (ui *UserInterface) InputLoop() {
	event := ""
	for event != "q" {
		event = ui.form.Run(0)
		if event != "" {
			if event == "^L" {
				stfl.Reset()
			} else {
				ui.actionchan <- UserInterfaceAction{RAW_INPUT, []string{event}}
			}
		}
	}
	stfl.Reset()
}

func (ui *UserInterface) SetInputField(prompt, deftext, endevent string) {
	last_line_text := "{hbox[lastline] .expand:0 {label .expand:0 text[prompt]:" + stfl.Quote(prompt) + "}{input[tweetinput] on_ESC:cancel-input on_ENTER:" + endevent + " modal:1 .expand:h text[inputfield]:" + stfl.Quote(deftext) + "}}"

	ui.form.Modify("lastline", "replace", last_line_text)
	ui.form.SetFocus("tweetinput")
}

func formatTweets(tweets []*Tweet) string {
	buf := bytes.NewBufferString("{list")

	for _, t := range tweets {
		tweetline := fmt.Sprintf("[%16s] %s", "@"+*t.User.Screen_name, *t.Text)
		buf.WriteString(fmt.Sprintf("{listitem[%v] text:%v}", *t.Id, stfl.Quote(tweetline)))
	}

	buf.WriteString("}")
	return string(buf.Bytes())
}
<commit_msg>show program name and version.<commit_after>package main

import (
	"bytes"
	"fmt"
	"strconv"
	"os"
	stfl "github.com/akrennmair/go-stfl"
)

type UserInterface struct {
	form                  *stfl.Form
	actionchan            chan UserInterfaceAction
	tweetchan             chan []*Tweet
	cmdchan               chan TwitterCommand
	lookupchan            chan TweetRequest
	in_reply_to_status_id int64
}

type ActionId int

const (
	RESET_LAST_LINE ActionId = iota
	RAW_INPUT
	UPDATE_RATELIMIT
)

type UserInterfaceAction struct {
	Action ActionId
	Args   []string
}

func NewUserInterface(cc chan TwitterCommand, tc chan []*Tweet, lc chan TweetRequest, uac chan UserInterfaceAction) *UserInterface {
	stfl.Init()
	ui := &UserInterface{
		form:                  stfl.Create("<ui.stfl>"),
		actionchan:            uac,
		tweetchan:             tc,
		cmdchan:               cc,
		in_reply_to_status_id: 0,
		lookupchan:            lc,
	}
	ui.form.Set("program", "gockel 0.0")
	return ui
}

func (ui *UserInterface) GetActionChannel() chan UserInterfaceAction {
	return ui.actionchan
}

func (ui *UserInterface) Run() {
	for {
		select {
		case newtweets := <-ui.tweetchan:
			str := formatTweets(newtweets)
			ui.form.Modify("tweets", "insert_inner", str)
			ui.form.Run(-1)
		case action := <-ui.actionchan:
			ui.HandleAction(action)
		}
	}
}

func (ui *UserInterface) HandleAction(action UserInterfaceAction) {
	switch action.Action {
	case RESET_LAST_LINE:
		ui.ResetLastLine()
	case RAW_INPUT:
		input := action.Args[0]
		ui.HandleRawInput(input)
	case UPDATE_RATELIMIT:
		rem, _ := strconv.Atoui(action.Args[0])
		limit, _ := strconv.Atoui(action.Args[1])
		reset, _ := strconv.Atoi64(action.Args[2])
		newtext := fmt.Sprintf("Next reset: %d min %d/%d", reset/60, rem, limit)
		ui.form.Set("rateinfo", newtext)
		ui.form.Run(-1)
	}
}

func (ui *UserInterface) ResetLastLine() {
	ui.form.Modify("lastline", "replace", "{hbox[lastline] .expand:0 {label text[msg]:\"\" .expand:h}}")
}

func (ui *UserInterface) HandleRawInput(input string) {
	switch input {
	case "ENTER":
		ui.SetInputField("Tweet: ", "", "end-input")
	case "r":
		var err os.Error
		ui.in_reply_to_status_id, err = strconv.Atoi64(ui.form.Get("status_id"))
		if err != nil {
			// TODO: show error
			break
		}
		tweet := ui.LookupTweet(ui.in_reply_to_status_id)
		if tweet != nil {
			ui.SetInputField("Reply: ", "@"+*tweet.User.Screen_name+" ","end-input")
		} else {
			//TODO: show error
		}
	case "^R":
		status_id, err := strconv.Atoi64(ui.form.Get("status_id"))
		if err != nil {
			// TODO: show error
			break
		}
		status_id_ptr := new(int64)
		*status_id_ptr = status_id
		ui.cmdchan <- TwitterCommand{Cmd: RETWEET, Data: Tweet{Id: status_id_ptr}}
	case "end-input":
		tweet_text := new(string)
		*tweet_text = ui.form.Get("inputfield")
		if len(*tweet_text) > 0 {
			t := Tweet{Text: tweet_text}
			if ui.in_reply_to_status_id != 0 {
				t.In_reply_to_status_id = new(int64)
				*t.In_reply_to_status_id = ui.in_reply_to_status_id
				ui.in_reply_to_status_id = int64(0)
			}
			ui.cmdchan <- TwitterCommand{Cmd: UPDATE, Data: t}
		}
		ui.ResetLastLine()
	case "cancel-input":
		ui.ResetLastLine()
	}
	ui.form.Run(-1)
}

func (ui *UserInterface) LookupTweet(status_id int64) *Tweet {
	reply := make(chan *Tweet)
	req := TweetRequest{Status_id: status_id, Reply: reply}
	ui.lookupchan <- req
	return <-reply
}

func (ui *UserInterface) InputLoop() {
	event := ""
	for event != "q" {
		event = ui.form.Run(0)
		if event != "" {
			if event == "^L" {
				stfl.Reset()
			} else {
				ui.actionchan <- UserInterfaceAction{RAW_INPUT, []string{event}}
			}
		}
	}
	stfl.Reset()
}

func (ui *UserInterface) SetInputField(prompt, deftext, endevent string) {
	last_line_text := "{hbox[lastline] .expand:0 {label .expand:0 text[prompt]:" + stfl.Quote(prompt) + "}{input[tweetinput] on_ESC:cancel-input on_ENTER:" + endevent + " modal:1 .expand:h text[inputfield]:" + stfl.Quote(deftext) + "}}"

	ui.form.Modify("lastline", "replace", last_line_text)
	ui.form.SetFocus("tweetinput")
}

func formatTweets(tweets []*Tweet) string {
	buf := bytes.NewBufferString("{list")

	for _, t := range tweets {
		tweetline := fmt.Sprintf("[%16s] %s", "@"+*t.User.Screen_name, *t.Text)
		buf.WriteString(fmt.Sprintf("{listitem[%v] text:%v}", *t.Id, stfl.Quote(tweetline)))
	}

	buf.WriteString("}")
	return string(buf.Bytes())
}
<|endoftext|>


<commit_before>package gamehack

import (
	"fmt"
	"html/template"
	"net/http"

	"appengine"
	"appengine/datastore"
	"appengine/user"
)

const homePage = `
<!doctype html>

    <title>Game+Hack</title>
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>

    <form action="/login" method="post">

<input type="submit" value="Sign In">

    </form>

`

func root(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, homePage)
}

var phoneTemplate = template.Must(template.New("phone").Parse(`
<!doctype html>

    <title>Game+Hack</title>
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>

Hello, {{.Name}}! Sign Out

		{{if .AuthorizedWithMoves}}

Account is currently authorized with Moves.

		{{else}}

Authenticate With Moves

		{{end}}
    <form action="/addphone" method="POST">

Parent: <input type="text" name="parent"/>

Phone: <input type="text" name="phone"/>

<input type="submit" value="Add Phone Number">

    </form>
    <form action="/delphone" method="POST">
      <select name="parent">
        <option value=""></option>
        {{range .PhoneEntries}}
          <option value="{{.Parent}}">{{.Parent}}</option>
        {{end}}
      </select>

<input type="submit" value="Remove Phone Number">

    </form>
    {{range .PhoneEntries}}

{{.Parent}}: {{.Phone}}

    {{end}}

`))

func phone(w http.ResponseWriter, r *http.Request) {
	c := appengine.NewContext(r)
	u := user.Current(c)
	if u == nil {
		http.Redirect(w, r, "/", http.StatusUnauthorized)
		return
	}
	user := User{
		Name: u.String(),
	}

	userKey := datastore.NewKey(c, "User", u.ID, 0, nil)

	err := datastore.Get(c, userKey, &user)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	_, err = datastore.NewQuery("PhoneEntry").Ancestor(userKey).GetAll(c, &user.PhoneEntries)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	err = phoneTemplate.Execute(w, &user)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}
<commit_msg>CSS it up in here.<commit_after>package gamehack

import (
	"fmt"
	"html/template"
	"net/http"

	"appengine"
	"appengine/datastore"
	"appengine/user"
)

const homePage = `
<!doctype html>

    <title>Amelia</title>
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
		<link rel="stylesheet" href="http://bootswatch.com/amelia/bootstrap.min.css">

					<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar-collapse">
						Toggle navigation

					</button>
					Amelia

					<form class="navbar-form navbar-right" action="/login">
						<button type="submit" class="btn btn-default">Sign Up</button>
					</form>

Amelia

Amelia keeps track of your children when you aren't.

					<form action="/login">
						<button type="submit" style="font-size: 24px;" class="btn btn-primary btn-lg">Sign Up</button>
					</form>

`

func root(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, homePage)
}

var phoneTemplate = template.Must(template.New("phone").Parse(`
<!doctype html>

    <title>Amelia</title>
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
		<link rel="stylesheet" href="http://bootswatch.com/amelia/bootstrap.min.css">

					<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar-collapse">
						Toggle navigation

					</button>
					Amelia

Sign Out

Hello, {{.Name}}!

		{{if .AuthorizedWithMoves}}

Account is currently authorized with Moves.

		{{else}}

Authenticate With Moves

		{{end}}

Phones

    {{range .PhoneEntries}}

{{.Parent}}: {{.Phone}}

    {{end}}

Add Phone Number

    <form action="/addphone" method="POST" role="form">

				Parent
				<input type="text" class="form-control" id="parent" name="parent" placeholder="Enter parent name.">

				Phone
				<input type="text" class="form-control" id="phone" name="phone" placeholder="+15553332222">

			<button type="submit" class="btn btn-default">Add Phone Number</button>
    </form>

Remove Phone Number

    <form action="/delphone" method="POST">

				<select name="parent" class="form-control">
					<option value=""></option>
					{{range .PhoneEntries}}
						<option value="{{.Parent}}">{{.Parent}}</option>
					{{end}}
				</select>

			<button type="submit" class="btn btn-default">Remove Phone Number</button>
    </form>

`))

func phone(w http.ResponseWriter, r *http.Request) {
	c := appengine.NewContext(r)
	u := user.Current(c)
	if u == nil {
		http.Redirect(w, r, "/", http.StatusUnauthorized)
		return
	}
	user := User{
		Name: u.String(),
	}

	userKey := datastore.NewKey(c, "User", u.ID, 0, nil)

	err := datastore.Get(c, userKey, &user)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	_, err = datastore.NewQuery("PhoneEntry").Ancestor(userKey).GetAll(c, &user.PhoneEntries)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	err = phoneTemplate.Execute(w, &user)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}
<|endoftext|>


<commit_before>package someutils

import (
	"fmt"
	"io"
	"bufio"
	"github.com/laher/uggo"
	"os"
)

type WcOptions struct {
	IsBytes bool
	IsWords bool
	IsLines bool
}

func init() {
	Register(Util{
		"wc",
		Wc})
}

func Wc(call []string) error {
	options := WcOptions{}
	flagSet := uggo.NewFlagSetDefault("wc", "[options]", VERSION)
	flagSet.AliasedBoolVar(&options.IsLines, []string{"l", "lines"}, false, "Count lines")
	flagSet.AliasedBoolVar(&options.IsWords, []string{"w", "words"}, false, "Count words")
//	flagSet.AliasedBoolVar(&options.IsChars, []string{"m", "chars"}, false, "Count characters")
	flagSet.AliasedBoolVar(&options.IsBytes, []string{"c", "bytes"}, false, "Count bytes")
	err := flagSet.Parse(call[1:])

	if err != nil {
		return err
	}
	if flagSet.ProcessHelpOrVersion() {
		return nil
	}
	if len(flagSet.Args()) > 0 {
		//treat no args as all args
		if !options.IsWords && !options.IsLines && !options.IsBytes {
			options.IsWords = true
			options.IsLines = true
			options.IsBytes = true
		}
		for _, fileName := range flagSet.Args() {
			bytes := int64(-1)
			words := int64(-1)
			lines := int64(-1)
			//get byte count
			file, err := os.Open(fileName)
			if err != nil {
				return err
			}
			err = wc(file, options, &bytes, &words, &lines)
			if err != nil {
				file.Close()
				return err
			}
			err = file.Close()
			if err != nil {
				return err
			}
			if options.IsWords && !options.IsLines && !options.IsBytes {
				fmt.Printf("%d %s\n", words, fileName)
			} else if !options.IsWords && options.IsLines && !options.IsBytes {
				fmt.Printf("%d %s\n", lines, fileName)
			} else if !options.IsWords && !options.IsLines && options.IsBytes {
				fmt.Printf("%d %s\n", bytes, fileName)
			} else {
				fmt.Printf("%d %d %d %s\n", lines, words, bytes, fileName)
			}
		}
	} else {
		//stdin ..
		if !options.IsWords && !options.IsLines && !options.IsBytes {
			options.IsWords = true
		}
		bytes := int64(-1)
		words := int64(-1)
		lines := int64(-1)
		err = wc(os.Stdin, options, &bytes, &words, &lines)
		if err != nil {
			return err
		}
		if options.IsWords && !options.IsLines && !options.IsBytes {
			fmt.Printf("%d\n", words)
		} else if !options.IsWords && options.IsLines && !options.IsBytes {
			fmt.Printf("%d\n", lines)
		} else if !options.IsWords && !options.IsLines && options.IsBytes {
			fmt.Printf("%d\n", bytes)
		} else {
			fmt.Printf("%d %d %d\n", lines, words, bytes)
		}
	}
	if err != nil {
		return err
	}
	//println(wd)
	return nil
}

func isSpace(c byte) bool {
	return c == ' ' || c == '\t' || c == '\n' || c == '\r'
}

func wc(file io.Reader, options WcOptions, bytes *int64, words *int64, lines *int64) (err error) {
	lastWasSpace := false
	bio := bufio.NewReader(file)
	for err == nil {
		c, err := bio.ReadByte()
		if err != nil {
			if io.EOF == err {
				return nil
			}
			return err
		}
		*bytes += 1
		if isSpace(c) {
			if !lastWasSpace {
				*words += 1
			}
			lastWasSpace = true
		} else {
			lastWasSpace = false
		}
		if c == '\n' {
			*lines += 1
		}
/*
		scanner := bufio.NewScanner(file)
		// Count the lines
		count := int64(0)
		for scanner.Scan() {
			count++
		}
		if err := scanner.Err(); err != nil {
			fmt.Fprintln(os.Stderr, "reading input:", err)
			return err
		}
		fmt.Printf("lines: %d\n", count)
		*lines = count
	} else if options.IsWordsOnly {
		scanner := bufio.NewScanner(file)
		scanner.Split(bufio.ScanWords)
		// Count the words.
		count := int64(0)
		for scanner.Scan() {
			count++
		}
		if err := scanner.Err(); err != nil {
			fmt.Fprintln(os.Stderr, "reading input:", err)
			return err
		}
		*words = count
	}
*/
	}
	return err
}
<commit_msg>Corrected totals for wc<commit_after>package someutils

import (
	"fmt"
	"io"
	"bufio"
	"github.com/laher/uggo"
	"os"
)

type WcOptions struct {
	IsBytes bool
	IsWords bool
	IsLines bool
}

func init() {
	Register(Util{
		"wc",
		Wc})
}

func Wc(call []string) error {
	options := WcOptions{}
	flagSet := uggo.NewFlagSetDefault("wc", "[options]", VERSION)
	flagSet.AliasedBoolVar(&options.IsLines, []string{"l", "lines"}, false, "Count lines")
	flagSet.AliasedBoolVar(&options.IsWords, []string{"w", "words"}, false, "Count words")
//	flagSet.AliasedBoolVar(&options.IsChars, []string{"m", "chars"}, false, "Count characters")
	flagSet.AliasedBoolVar(&options.IsBytes, []string{"c", "bytes"}, false, "Count bytes")
	err := flagSet.Parse(call[1:])

	if err != nil {
		return err
	}
	if flagSet.ProcessHelpOrVersion() {
		return nil
	}
	if len(flagSet.Args()) > 0 {
		//treat no args as all args
		if !options.IsWords && !options.IsLines && !options.IsBytes {
			options.IsWords = true
			options.IsLines = true
			options.IsBytes = true
		}
		for _, fileName := range flagSet.Args() {
			bytes := int64(0)
			words := int64(0)
			lines := int64(0)
			//get byte count
			file, err := os.Open(fileName)
			if err != nil {
				return err
			}
			err = wc(file, options, &bytes, &words, &lines)
			if err != nil {
				file.Close()
				return err
			}
			err = file.Close()
			if err != nil {
				return err
			}
			if options.IsWords && !options.IsLines && !options.IsBytes {
				fmt.Printf("%d %s\n", words, fileName)
			} else if !options.IsWords && options.IsLines && !options.IsBytes {
				fmt.Printf("%d %s\n", lines, fileName)
			} else if !options.IsWords && !options.IsLines && options.IsBytes {
				fmt.Printf("%d %s\n", bytes, fileName)
			} else {
				fmt.Printf("%d %d %d %s\n", lines, words, bytes, fileName)
			}
		}
	} else {
		//stdin ..
		if !options.IsWords && !options.IsLines && !options.IsBytes {
			options.IsWords = true
		}
		bytes := int64(0)
		words := int64(0)
		lines := int64(0)
		err = wc(os.Stdin, options, &bytes, &words, &lines)
		if err != nil {
			return err
		}
		if options.IsWords && !options.IsLines && !options.IsBytes {
			fmt.Printf("%d\n", words)
		} else if !options.IsWords && options.IsLines && !options.IsBytes {
			fmt.Printf("%d\n", lines)
		} else if !options.IsWords && !options.IsLines && options.IsBytes {
			fmt.Printf("%d\n", bytes)
		} else {
			fmt.Printf("%d %d %d\n", lines, words, bytes)
		}
	}
	if err != nil {
		return err
	}
	//println(wd)
	return nil
}

func isSpace(c byte) bool {
	return c == ' ' || c == '\t' || c == '\n' || c == '\r'
}

func wc(file io.Reader, options WcOptions, bytes *int64, words *int64, lines *int64) (err error) {
	lastWasSpace := false
	bio := bufio.NewReader(file)
	for err == nil {
		c, err := bio.ReadByte()
		if err != nil {
			if io.EOF == err {
				return nil
			}
			return err
		}
		*bytes += 1
		if isSpace(c) {
			if !lastWasSpace {
				*words += 1
			}
			lastWasSpace = true
		} else {
			lastWasSpace = false
		}
		if c == '\n' {
			*lines += 1
		}

	}
	return err
}
<|endoftext|>


<commit_before>package undb

import (
	"github.com/gorilla/websocket"
	"encoding/json"
	"fmt"
	"log"
//	"time"
)

func (store *Store) ws_setup(ops *[]Op, opchan chan Op) {
	store.Lock()
	defer store.Unlock()

	store.Instruct(ops)
	store.Listen(opchan)
}

func (store *Store) ws_cleanup(opchan chan Op) {
	store.Lock()
	defer store.Unlock()

	store.Unlisten(opchan)
}

func (store* Store) ws_exec(ops []Op, source string) error {
	store.Lock()
	defer store.Unlock()

	for _, op := range ops {
		err := store.Exec(&op, source)
		if err != nil {
			return err
		}
	}

	return nil
}

func (store *Store) Websocket(ws *websocket.Conn, ws_id string) {
	fmt.Println("Store '" + store.Id + "': websocket opened (" + ws_id + ")")
	defer fmt.Println("Store '" + store.Id + "': websocket closing")

	var ops []Op
	opchan := make(chan Op, 8192)

	// this logic is tricky.  take care with these
	// locks and with defer.  lock/unlock is required for
	// store.Unlisten()
	store.ws_setup(&ops, opchan)
	defer store.ws_cleanup(opchan)

	j, err := json.Marshal(ops)
	if err != nil {
		panic(err)
	}
	ws.WriteMessage(websocket.TextMessage, j)

//	time.Sleep(time.Second)

	go func() {
		defer close(opchan)
		defer store.ws_cleanup(opchan) // double cleanup is ok

		for {
//			time.Sleep(time.Second)

			log.Println("receiving message")
			_, msgdata, err := ws.ReadMessage()
			if err != nil {
				fmt.Println(err.Error())
				return
			}

			log.Println("receiving message complete")

			var opslice []Op
			err = json.Unmarshal(msgdata, &opslice)
			if err != nil {
				panic(err)
			}

			err = store.ws_exec(opslice, ws_id)
			if err != nil {
				panic(err)
			}
		}
	}();

	for {
		op, ok := <-opchan
		if !ok {
			return
		}

		if op.changesource == ws_id {
			continue
		}

//		time.Sleep(time.Second)

		opslice := []Op{op}
		j, err := json.Marshal(&opslice)
		if err != nil {
			panic(err)
		}
		log.Println("writing message")
		err = ws.WriteMessage(websocket.TextMessage, j)
		log.Println("writing message complete")
		if err != nil {
			log.Println(err)
			return
		}
	}
}

<commit_msg>Fix crash when we get incomplete json<commit_after>package undb

import (
	"github.com/gorilla/websocket"
	"encoding/json"
	"fmt"
	"log"
//	"time"
)

func (store *Store) ws_setup(ops *[]Op, opchan chan Op) {
	store.Lock()
	defer store.Unlock()

	store.Instruct(ops)
	store.Listen(opchan)
}

func (store *Store) ws_cleanup(opchan chan Op) {
	store.Lock()
	defer store.Unlock()

	store.Unlisten(opchan)
}

func (store* Store) ws_exec(ops []Op, source string) error {
	store.Lock()
	defer store.Unlock()

	for _, op := range ops {
		err := store.Exec(&op, source)
		if err != nil {
			return err
		}
	}

	return nil
}

func (store *Store) Websocket(ws *websocket.Conn, ws_id string) {
	fmt.Println("Store '" + store.Id + "': websocket opened (" + ws_id + ")")
	defer fmt.Println("Store '" + store.Id + "': websocket closing")

	var ops []Op
	opchan := make(chan Op, 8192)

	// this logic is tricky.  take care with these
	// locks and with defer.  lock/unlock is required for
	// store.Unlisten()
	store.ws_setup(&ops, opchan)
	defer store.ws_cleanup(opchan)

	j, err := json.Marshal(ops)
	if err != nil {
		panic(err)
	}
	ws.WriteMessage(websocket.TextMessage, j)

//	time.Sleep(time.Second)

	go func() {
		defer close(opchan)
		defer store.ws_cleanup(opchan) // double cleanup is ok

		for {
//			time.Sleep(time.Second)

			log.Println("receiving message")
			_, msgdata, err := ws.ReadMessage()
			if err != nil {
				fmt.Println(err.Error())
				return
			}

			log.Println("receiving message complete")

			var opslice []Op
			err = json.Unmarshal(msgdata, &opslice)
			if err != nil {
				log.Println("message unmarshal error", err)
				continue
			}

			err = store.ws_exec(opslice, ws_id)
			if err != nil {
				panic(err)
			}
		}
	}();

	for {
		op, ok := <-opchan
		if !ok {
			return
		}

		if op.changesource == ws_id {
			continue
		}

//		time.Sleep(time.Second)

		opslice := []Op{op}
		j, err := json.Marshal(&opslice)
		if err != nil {
			panic(err)
		}
		log.Println("writing message")
		err = ws.WriteMessage(websocket.TextMessage, j)
		log.Println("writing message complete")
		if err != nil {
			log.Println(err)
			return
		}
	}
}

<|endoftext|>


<commit_before>package sms

import (
	"bytes"
	"fmt"
	"time"
)

// VP is type of validity period
type VP interface {
	fmt.Stringer
	ExpireTime(t time.Time) time.Time
	Duration() time.Duration
	SingleAttempt() bool
}

// ValidityPeriodOf returns VP from deadend time
func ValidityPeriodOf(t time.Duration, s bool) VP {
	t = t.Truncate(time.Second)
	if t == 0 {
		vp := VPEnhanced{}
		if s {
			vp[0] = 0x40
		}
		return vp
	} else if t%(time.Hour*24*7) == 0 && t <= time.Hour*24*7*63 {
		return VPRelative(byte(t/(time.Hour*24*7)) + 192)
	} else if t%(time.Hour*24) == 0 && t <= time.Hour*24*30 {
		return VPRelative(byte(t/(time.Hour*24)) + 166)
	} else if t%(time.Minute*30) == 0 && t <= time.Hour*24 && t >= time.Hour*12+time.Minute*30 {
		return VPRelative(byte((t-time.Hour*12)/(time.Minute*30)) + 143)
	} else if t%(time.Minute*5) == 0 && t <= time.Hour*12 && t >= time.Minute*5 {
		return VPRelative(byte(t/(time.Minute*5)) - 1)
	} else if t <= time.Second*255 {
		vp := VPEnhanced{}
		vp[0] = 0x02
		if s {
			vp[0] |= 0x40
		}
		vp[1] = byte(t / time.Second)
		return vp
	} else if t <= time.Hour*99+time.Minute*59+time.Second*59 {
		vp := VPEnhanced{}
		vp[0] = 0x03
		if s {
			vp[0] |= 0x40
		}
		vp[1] = int2SemiOctet(int(t / time.Hour))
		vp[2] = int2SemiOctet(int(t / time.Minute))
		vp[3] = int2SemiOctet(int(t / time.Hour))
		return vp
	}
	vp := encodeSCTimeStamp(time.Now().Add(t))
	return VPAbsolute{vp[0], vp[1], vp[2], vp[3], vp[4], vp[5], vp[6]}
}

// VPRelative is relative format VP value
type VPRelative byte

func (f VPRelative) String() string {
	return "ralative, " + relativeFormatString(byte(f))
}
func relativeFormatString(b byte) string {
	if b < 144 {
		i := int(b+1) * 5
		return fmt.Sprintf("%d:%d", (i-i%60)/60, i%60)
	}
	if b < 168 {
		i := int(b-143) * 30
		return fmt.Sprintf("%d:%d", (i-i%60)/60+12, i%60)
	}
	if b < 197 {
		return fmt.Sprintf("%d days", b-166)
	}
	return fmt.Sprintf("%d weeks", b-192)
}

// ExpireTime return expire time
func (f VPRelative) ExpireTime(t time.Time) time.Time {
	return t.Add(relativeFormatDuration(byte(f)))
}

// Duration return duration to expire time
func (f VPRelative) Duration() time.Duration {
	return relativeFormatDuration(byte(f))
}

func relativeFormatDuration(b byte) time.Duration {
	if b < 144 {
		return time.Duration(b+1) * 5 * time.Minute
	}
	if b < 168 {
		return time.Duration(b-143) * 30 * time.Minute
	}
	if b < 197 {
		return time.Duration(b-166) * time.Hour * 24
	}
	return time.Duration(b-192) * time.Hour * 24 * 7
}

// SingleAttempt return single attempt is required or not
func (f VPRelative) SingleAttempt() bool {
	return false
}

// VPAbsolute is absolute format VP value
type VPAbsolute [7]byte

func (f VPAbsolute) String() string {
	return fmt.Sprintf("absolute, %s", decodeSCTimeStamp(f))
}

// ExpireTime return expire time
func (f VPAbsolute) ExpireTime(t time.Time) time.Time {
	return decodeSCTimeStamp(f)
}

// Duration return duration to expire time
func (f VPAbsolute) Duration() time.Duration {
	return time.Until(decodeSCTimeStamp(f))
}

// SingleAttempt return single attempt is required or not
func (f VPAbsolute) SingleAttempt() bool {
	return false
}

// VPEnhanced is enhanced format VP value
type VPEnhanced [7]byte

func (f VPEnhanced) String() string {
	var s bytes.Buffer
	s.WriteString("enhanced")
	if f[0]&0x40 == 0x40 {
		s.WriteString(", single-shot")
	}
	switch f[0] & 0x03 {
	case 0x00:
		s.WriteString(", no validity period")
	case 0x01:
		s.WriteString(", ")
		s.WriteString(relativeFormatString(f[1]))
	case 0x02:
		s.WriteString(fmt.Sprintf(", %d sec", f[1]))
	case 0x03:
		s.WriteString(fmt.Sprintf(", %d:%d:%d",
			semiOctet2Int(f[1]),
			semiOctet2Int(f[2]),
			semiOctet2Int(f[3])))
	default:
		s.WriteString(", invalid format")
	}
	return s.String()
}

// ExpireTime return expire time
func (f VPEnhanced) ExpireTime(t time.Time) time.Time {
	switch f[0] & 0x03 {
	case 0x00:
		return time.Time{}
	case 0x01:
		return t.Add(relativeFormatDuration(f[1]))
	case 0x02:
		return t.Add(time.Duration(f[1]) * time.Second)
	case 0x03:
		i := time.Duration(semiOctet2Int(f[1])) * time.Hour
		i += time.Duration(semiOctet2Int(f[2])) * time.Minute
		i += time.Duration(semiOctet2Int(f[3])) * time.Second
		return t.Add(i)
	}
	return time.Time{}
}

// Duration return duration to expire time
func (f VPEnhanced) Duration() time.Duration {
	switch f[0] & 0x03 {
	case 0x00:
		return time.Duration(0)
	case 0x01:
		return relativeFormatDuration(f[1])
	case 0x02:
		return time.Duration(f[1]) * time.Second
	case 0x03:
		i := time.Duration(semiOctet2Int(f[1])) * time.Hour
		i += time.Duration(semiOctet2Int(f[2])) * time.Minute
		i += time.Duration(semiOctet2Int(f[3])) * time.Second
		return i
	}
	return time.Duration(0)
}

// SingleAttempt return single attempt is required or not
func (f VPEnhanced) SingleAttempt() bool {
	if f[0]&0x40 == 0x40 {
		return true
	}
	return false
}
<commit_msg>modify TP-VP generation logic<commit_after>package sms

import (
	"bytes"
	"fmt"
	"time"
)

// VP is type of validity period
type VP interface {
	fmt.Stringer
	ExpireTime(t time.Time) time.Time
	Duration() time.Duration
	SingleAttempt() bool
}

// ValidityPeriodOf returns VP from deadend time and single-attempt flag
func ValidityPeriodOf(t time.Duration, s bool) VP {
	t = t.Truncate(time.Second)

	if s {
		vp := VPEnhanced{}
		vp[0] = 0x40
		if t == 0 {
		} else if t%(time.Hour*24*7) == 0 && t <= time.Hour*24*7*63 {
			vp[0] |= 0x01
			vp[1] = byte(t/(time.Hour*24*7)) + 192
		} else if t%(time.Hour*24) == 0 && t <= time.Hour*24*30 {
			vp[0] |= 0x01
			vp[1] = byte(t/(time.Hour*24)) + 166
		} else if t%(time.Minute*30) == 0 && t <= time.Hour*24 && t >= time.Hour*12+time.Minute*30 {
			vp[0] |= 0x01
			vp[1] = byte((t-time.Hour*12)/(time.Minute*30)) + 143
		} else if t%(time.Minute*5) == 0 && t <= time.Hour*12 && t >= time.Minute*5 {
			vp[0] |= 0x01
			vp[1] = byte(t/(time.Minute*5)) - 1
		} else if t <= time.Second*255 {
			vp[0] = 0x02
			vp[1] = byte(t / time.Second)
		} else if t <= time.Hour*99+time.Minute*59+time.Second*59 {
			vp[0] = 0x03
			vp[1] = int2SemiOctet(int(t / time.Hour))
			vp[2] = int2SemiOctet(int(t / time.Minute))
			vp[3] = int2SemiOctet(int(t / time.Hour))
		} else if t <= time.Hour*24*30 {
			vp[0] |= 0x01
			vp[1] = byte(t/(time.Hour*24)) + 166
		}
		return vp
	}
	if t == 0 {
		return VPEnhanced{}
	} else if t%(time.Hour*24*7) == 0 && t <= time.Hour*24*7*63 {
		return VPRelative(byte(t/(time.Hour*24*7)) + 192)
	} else if t%(time.Hour*24) == 0 && t <= time.Hour*24*30 {
		return VPRelative(byte(t/(time.Hour*24)) + 166)
	} else if t%(time.Minute*30) == 0 && t <= time.Hour*24 && t >= time.Hour*12+time.Minute*30 {
		return VPRelative(byte((t-time.Hour*12)/(time.Minute*30)) + 143)
	} else if t%(time.Minute*5) == 0 && t <= time.Hour*12 && t >= time.Minute*5 {
		return VPRelative(byte(t/(time.Minute*5)) - 1)
	} else if t <= time.Second*255 {
		vp := VPEnhanced{}
		vp[0] = 0x02
		vp[1] = byte(t / time.Second)
		return vp
	} else if t <= time.Hour*99+time.Minute*59+time.Second*59 {
		vp := VPEnhanced{}
		vp[0] = 0x03
		vp[1] = int2SemiOctet(int(t / time.Hour))
		vp[2] = int2SemiOctet(int(t / time.Minute))
		vp[3] = int2SemiOctet(int(t / time.Hour))
		return vp
	}
	vp := encodeSCTimeStamp(time.Now().Add(t))
	return VPAbsolute{vp[0], vp[1], vp[2], vp[3], vp[4], vp[5], vp[6]}
}

// VPRelative is relative format VP value
type VPRelative byte

func (f VPRelative) String() string {
	return "ralative, " + relativeFormatString(byte(f))
}
func relativeFormatString(b byte) string {
	if b < 144 {
		i := int(b+1) * 5
		return fmt.Sprintf("%d:%d", (i-i%60)/60, i%60)
	}
	if b < 168 {
		i := int(b-143) * 30
		return fmt.Sprintf("%d:%d", (i-i%60)/60+12, i%60)
	}
	if b < 197 {
		return fmt.Sprintf("%d days", b-166)
	}
	return fmt.Sprintf("%d weeks", b-192)
}

// ExpireTime return expire time
func (f VPRelative) ExpireTime(t time.Time) time.Time {
	return t.Add(relativeFormatDuration(byte(f)))
}

// Duration return duration to expire time
func (f VPRelative) Duration() time.Duration {
	return relativeFormatDuration(byte(f))
}

func relativeFormatDuration(b byte) time.Duration {
	if b < 144 {
		return time.Duration(b+1) * 5 * time.Minute
	}
	if b < 168 {
		return time.Duration(b-143) * 30 * time.Minute
	}
	if b < 197 {
		return time.Duration(b-166) * time.Hour * 24
	}
	return time.Duration(b-192) * time.Hour * 24 * 7
}

// SingleAttempt return single attempt is required or not
func (f VPRelative) SingleAttempt() bool {
	return false
}

// VPAbsolute is absolute format VP value
type VPAbsolute [7]byte

func (f VPAbsolute) String() string {
	return fmt.Sprintf("absolute, %s", decodeSCTimeStamp(f))
}

// ExpireTime return expire time
func (f VPAbsolute) ExpireTime(t time.Time) time.Time {
	return decodeSCTimeStamp(f)
}

// Duration return duration to expire time
func (f VPAbsolute) Duration() time.Duration {
	return time.Until(decodeSCTimeStamp(f))
}

// SingleAttempt return single attempt is required or not
func (f VPAbsolute) SingleAttempt() bool {
	return false
}

// VPEnhanced is enhanced format VP value
type VPEnhanced [7]byte

func (f VPEnhanced) String() string {
	var s bytes.Buffer
	s.WriteString("enhanced")
	if f[0]&0x40 == 0x40 {
		s.WriteString(", single-shot")
	}
	switch f[0] & 0x03 {
	case 0x00:
		s.WriteString(", no validity period")
	case 0x01:
		s.WriteString(", ")
		s.WriteString(relativeFormatString(f[1]))
	case 0x02:
		s.WriteString(fmt.Sprintf(", %d sec", f[1]))
	case 0x03:
		s.WriteString(fmt.Sprintf(", %d:%d:%d",
			semiOctet2Int(f[1]),
			semiOctet2Int(f[2]),
			semiOctet2Int(f[3])))
	default:
		s.WriteString(", invalid format")
	}
	return s.String()
}

// ExpireTime return expire time
func (f VPEnhanced) ExpireTime(t time.Time) time.Time {
	switch f[0] & 0x03 {
	case 0x00:
		return time.Time{}
	case 0x01:
		return t.Add(relativeFormatDuration(f[1]))
	case 0x02:
		return t.Add(time.Duration(f[1]) * time.Second)
	case 0x03:
		i := time.Duration(semiOctet2Int(f[1])) * time.Hour
		i += time.Duration(semiOctet2Int(f[2])) * time.Minute
		i += time.Duration(semiOctet2Int(f[3])) * time.Second
		return t.Add(i)
	}
	return time.Time{}
}

// Duration return duration to expire time
func (f VPEnhanced) Duration() time.Duration {
	switch f[0] & 0x03 {
	case 0x00:
		return time.Duration(0)
	case 0x01:
		return relativeFormatDuration(f[1])
	case 0x02:
		return time.Duration(f[1]) * time.Second
	case 0x03:
		i := time.Duration(semiOctet2Int(f[1])) * time.Hour
		i += time.Duration(semiOctet2Int(f[2])) * time.Minute
		i += time.Duration(semiOctet2Int(f[3])) * time.Second
		return i
	}
	return time.Duration(0)
}

// SingleAttempt return single attempt is required or not
func (f VPEnhanced) SingleAttempt() bool {
	if f[0]&0x40 == 0x40 {
		return true
	}
	return false
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"encoding/json"
	"flag"
	"fmt"
	"html/template"
	"net/http"
	"os"
	"regexp"
	"time"

	_ "github.com/mattn/go-sqlite3"
)

var settings struct {
	DailyTarget int
	Database    string
}

func init() {
	flag.IntVar(&settings.DailyTarget, "target", 900, "The number of words to write daily")
	flag.StringVar(&settings.Database, "db", "diary.db", "The name of the database file")
}

func main() {
	flag.Parse()

	db, err := sql.Open("sqlite3", settings.Database)
	if err != nil {
		panic(err)
	}

	_, err = db.Exec("CREATE TABLE IF NOT EXISTS entries (date TEXT PRIMARY KEY, text TEXT, words INTEGER)")
	if err != nil {
		panic(err)
	}

	http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
		now := time.Now()
		days := daysOfMonth(now)
		annotatedDays, err := annotateDays(db, days)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %s\n", err)
		}

		text := ""
		words := 0
		rows, err := db.Query("SELECT text, words FROM entries WHERE date = ?", now.Format("2006-01-02"))
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %s\n", err)
		}
		defer rows.Close()

		if rows.Next() {
			err = rows.Scan(&text, &words)
			if err != nil {
				fmt.Fprintf(os.Stderr, "Error: %s\n", err)
			}
		}

		err = indexTmpl.Execute(w, map[string]interface{}{
			"Title": fmt.Sprintf("%d words", settings.DailyTarget),

			"Now":  now,
			"Days": annotatedDays,

			"Text":  text,
			"Words": words,
		})
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %s\n", err)
		}
	})

	http.HandleFunc("/save", func(w http.ResponseWriter, req *http.Request) {
		var entry map[string]string
		dec := json.NewDecoder(req.Body)
		err := dec.Decode(&entry)
		if err != nil {
			respondWithError(w, http.StatusBadRequest, err)
			return
		}

		text, ok := entry["text"]
		if !ok {
			respondWithError(w, http.StatusBadRequest, fmt.Errorf("Missing field 'text'"))
			return
		}

		words := countWords(text)
		now := time.Now()
		_, err = db.Exec("INSERT OR REPLACE INTO entries VALUES (?, ?, ?)", now.Format("2006-01-02"), text, words)
		if err != nil {
			respondWithError(w, http.StatusInternalServerError, fmt.Errorf("%s", http.StatusText(http.StatusInternalServerError)))
			return
		}

		enc := json.NewEncoder(w)
		err = enc.Encode(map[string]string{"message": "saved post", "time": now.Format(time.RFC3339)})
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %s\n", err)
		}
	})

	http.ListenAndServe("localhost:12345", nil)
}

func respondWithError(w http.ResponseWriter, status int, err error) {
	res := map[string]string{"error": err.Error()}
	out, err := json.Marshal(res)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		fmt.Fprintf(w, "{\"error\": %q}", http.StatusText(http.StatusInternalServerError))
		return
	}
	w.WriteHeader(status)
	w.Write(out)
}

var indexTmpl = template.Must(template.New("index").Parse(`<!doctype html>

		<meta charset="utf-8" />
		<title>{{ .Title }}</title>

{{ .Title }}

			{{ $now := .Now }}
			{{ range $day := .Days -}}

{{ $day.Date.Day }}

			{{ end }}

{{ .Now.Format "Monday, January 2, 2006" }}

				<textarea id="editor">{{ .Text }}</textarea>

					0 words

				Made with <3 by strange adventures.  —  /about

`))

var wordSeperator = regexp.MustCompile(`\s+`)

func countWords(text string) int {
	ws := wordSeperator.Split(text, -1)
	c := 0
	for _, w := range ws {
		if w != "" {
			c += 1
		}
	}
	return c
}

func daysOfMonth(t time.Time) []time.Time {
	s := time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, t.Location())
	e := s.AddDate(0, 1, 0)
	ts := make([]time.Time, 0, 31)
	for s.Before(e) {
		ts = append(ts, s)
		s = s.AddDate(0, 0, 1)
	}
	return ts
}

type Day struct {
	Date  time.Time
	Words int
}

func (d Day) Classes(now time.Time) string {
	var classes string
	if d.Date.Before(now) {
		classes = "past"
	} else {
		classes = "future"
	}

	if d.Words >= 1 {
		classes += " written"
	}

	if d.Words >= settings.DailyTarget {
		classes += " yay"
	}

	return classes
}

func annotateDays(db *sql.DB, days []time.Time) ([]Day, error) {
	rows, err := db.Query("SELECT date, words FROM entries WHERE date >= ? AND date <= ?", days[0].Format("2006-01-02"), days[len(days)-1].Format("2006-01-02"))
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var day string
	var words int
	if rows.Next() {
		err = rows.Scan(&day, &words)
		if err != nil {
			return nil, err
		}
	}

	annotatedDays := make([]Day, len(days))
	for i, t := range days {
		d := Day{Date: t, Words: 0}

		if t.Format("2006-01-02") == day {
			d.Words = words

			if rows.Next() {
				err = rows.Scan(&day)
				if err != nil {
					return nil, err
				}
			}
		}

		annotatedDays[i] = d
	}

	return annotatedDays, nil
}
<commit_msg>Fix missing paramter to result scan<commit_after>package main

import (
	"database/sql"
	"encoding/json"
	"flag"
	"fmt"
	"html/template"
	"net/http"
	"os"
	"regexp"
	"time"

	_ "github.com/mattn/go-sqlite3"
)

var settings struct {
	DailyTarget int
	Database    string
}

func init() {
	flag.IntVar(&settings.DailyTarget, "target", 900, "The number of words to write daily")
	flag.StringVar(&settings.Database, "db", "diary.db", "The name of the database file")
}

func main() {
	flag.Parse()

	db, err := sql.Open("sqlite3", settings.Database)
	if err != nil {
		panic(err)
	}

	_, err = db.Exec("CREATE TABLE IF NOT EXISTS entries (date TEXT PRIMARY KEY, text TEXT, words INTEGER)")
	if err != nil {
		panic(err)
	}

	http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
		now := time.Now()
		days := daysOfMonth(now)
		annotatedDays, err := annotateDays(db, days)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %s\n", err)
		}

		text := ""
		words := 0
		rows, err := db.Query("SELECT text, words FROM entries WHERE date = ?", now.Format("2006-01-02"))
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %s\n", err)
		}
		defer rows.Close()

		if rows.Next() {
			err = rows.Scan(&text, &words)
			if err != nil {
				fmt.Fprintf(os.Stderr, "Error: %s\n", err)
			}
		}

		err = indexTmpl.Execute(w, map[string]interface{}{
			"Title": fmt.Sprintf("%d words", settings.DailyTarget),

			"Now":  now,
			"Days": annotatedDays,

			"Text":  text,
			"Words": words,
		})
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %s\n", err)
		}
	})

	http.HandleFunc("/save", func(w http.ResponseWriter, req *http.Request) {
		var entry map[string]string
		dec := json.NewDecoder(req.Body)
		err := dec.Decode(&entry)
		if err != nil {
			respondWithError(w, http.StatusBadRequest, err)
			return
		}

		text, ok := entry["text"]
		if !ok {
			respondWithError(w, http.StatusBadRequest, fmt.Errorf("Missing field 'text'"))
			return
		}

		words := countWords(text)
		now := time.Now()
		_, err = db.Exec("INSERT OR REPLACE INTO entries VALUES (?, ?, ?)", now.Format("2006-01-02"), text, words)
		if err != nil {
			respondWithError(w, http.StatusInternalServerError, fmt.Errorf("%s", http.StatusText(http.StatusInternalServerError)))
			return
		}

		enc := json.NewEncoder(w)
		err = enc.Encode(map[string]string{"message": "saved post", "time": now.Format(time.RFC3339)})
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %s\n", err)
		}
	})

	http.ListenAndServe("localhost:12345", nil)
}

func respondWithError(w http.ResponseWriter, status int, err error) {
	res := map[string]string{"error": err.Error()}
	out, err := json.Marshal(res)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		fmt.Fprintf(w, "{\"error\": %q}", http.StatusText(http.StatusInternalServerError))
		return
	}
	w.WriteHeader(status)
	w.Write(out)
}

var indexTmpl = template.Must(template.New("index").Parse(`<!doctype html>

		<meta charset="utf-8" />
		<title>{{ .Title }}</title>

{{ .Title }}

			{{ $now := .Now }}
			{{ range $day := .Days -}}

{{ $day.Date.Day }}

			{{ end }}

{{ .Now.Format "Monday, January 2, 2006" }}

				<textarea id="editor">{{ .Text }}</textarea>

					0 words

				Made with <3 by strange adventures.  —  /about

`))

var wordSeperator = regexp.MustCompile(`\s+`)

func countWords(text string) int {
	ws := wordSeperator.Split(text, -1)
	c := 0
	for _, w := range ws {
		if w != "" {
			c += 1
		}
	}
	return c
}

func daysOfMonth(t time.Time) []time.Time {
	s := time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, t.Location())
	e := s.AddDate(0, 1, 0)
	ts := make([]time.Time, 0, 31)
	for s.Before(e) {
		ts = append(ts, s)
		s = s.AddDate(0, 0, 1)
	}
	return ts
}

type Day struct {
	Date  time.Time
	Words int
}

func (d Day) Classes(now time.Time) string {
	var classes string
	if d.Date.Before(now) {
		classes = "past"
	} else {
		classes = "future"
	}

	if d.Words >= 1 {
		classes += " written"
	}

	if d.Words >= settings.DailyTarget {
		classes += " yay"
	}

	return classes
}

func annotateDays(db *sql.DB, days []time.Time) ([]Day, error) {
	rows, err := db.Query("SELECT date, words FROM entries WHERE date >= ? AND date <= ?", days[0].Format("2006-01-02"), days[len(days)-1].Format("2006-01-02"))
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var day string
	var words int
	if rows.Next() {
		err = rows.Scan(&day, &words)
		if err != nil {
			return nil, err
		}
	}

	annotatedDays := make([]Day, len(days))
	for i, t := range days {
		d := Day{Date: t, Words: 0}

		if t.Format("2006-01-02") == day {
			d.Words = words

			if rows.Next() {
				err = rows.Scan(&day, &words)
				if err != nil {
					return nil, err
				}
			}
		}

		annotatedDays[i] = d
	}

	return annotatedDays, nil
}
<|endoftext|>