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

/*
	Package fmt implements formatted I/O with functions analogous
	to C's printf and scanf.  The format 'verbs' are derived from C's but
	are simpler.

	Printing:

	The verbs:

	General:
		%v	the value in a default format.
			when printing structs, the plus flag (%+v) adds field names
		%#v	a Go-syntax representation of the value
		%T	a Go-syntax representation of the type of the value
		%%	a literal percent sign; consumes no value

	Boolean:
		%t	the word true or false
	Integer:
		%b	base 2
		%c	the character represented by the corresponding Unicode code point
		%d	base 10
		%o	base 8
		%q	a single-quoted character literal safely escaped with Go syntax.
		%x	base 16, with lower-case letters for a-f
		%X	base 16, with upper-case letters for A-F
		%U	Unicode format: U+1234; same as "U+%04X"
	Floating-point and complex constituents:
		%b	decimalless scientific notation with exponent a power
			of two, in the manner of strconv.Ftoa32, e.g. -123456p-78
		%e	scientific notation, e.g. -1234.456e+78
		%E	scientific notation, e.g. -1234.456E+78
		%f	decimal point but no exponent, e.g. 123.456
		%g	whichever of %e or %f produces more compact output
		%G	whichever of %E or %f produces more compact output
	String and slice of bytes:
		%s	the uninterpreted bytes of the string or slice
		%q	a double-quoted string safely escaped with Go syntax
		%x	base 16, lower-case, two characters per byte
		%X	base 16, upper-case, two characters per byte
	Pointer:
		%p	base 16 notation, with leading 0x

	There is no 'u' flag.  Integers are printed unsigned if they have unsigned type.
	Similarly, there is no need to specify the size of the operand (int8, int64).

	The width and precision control formatting and are in units of Unicode
	code points.  (This differs from C's printf where the units are numbers
	of bytes.) Either or both of the flags may be replaced with the
	character '*', causing their values to be obtained from the next
	operand, which must be of type int.

	For numeric values, width sets the width of the field and precision
	sets the number of places after the decimal, if appropriate.  For
	example, the format %6.2f prints 123.45.

	For strings, width is the minimum number of characters to output,
	padding with spaces if necessary, and precision is the maximum
	number of characters to output, truncating if necessary.

	Other flags:
		+	always print a sign for numeric values;
			guarantee ASCII-only output for %q (%+q)
		-	pad with spaces on the right rather than the left (left-justify the field)
		#	alternate format: add leading 0 for octal (%#o), 0x for hex (%#x);
			0X for hex (%#X); suppress 0x for %p (%#p);
			print a raw (backquoted) string if possible for %q (%#q);
			write e.g. U+0078 'x' if the character is printable for %U (%#U).
		' '	(space) leave a space for elided sign in numbers (% d);
			put spaces between bytes printing strings or slices in hex (% x, % X)
		0	pad with leading zeros rather than spaces

	For each Printf-like function, there is also a Print function
	that takes no format and is equivalent to saying %v for every
	operand.  Another variant Println inserts blanks between
	operands and appends a newline.

	Regardless of the verb, if an operand is an interface value,
	the internal concrete value is used, not the interface itself.
	Thus:
		var i interface{} = 23
		fmt.Printf("%v\n", i)
	will print 23.

	If an operand implements interface Formatter, that interface
	can be used for fine control of formatting.

	If an operand implements method String() string that method
	will be used to convert the object to a string, which will then
	be formatted as required by the verb (if any). To avoid
	recursion in cases such as
		type X int
		func (x X) String() string { return Sprintf("%d", x) }
	cast the value before recurring:
		func (x X) String() string { return Sprintf("%d", int(x)) }

	Format errors:

	If an invalid argument is given for a verb, such as providing
	a string to %d, the generated string will contain a
	description of the problem, as in these examples:

		Wrong type or unknown verb: %!verb(type=value)
			Printf("%d", hi):          %!d(string=hi)
		Too many arguments: %!(EXTRA type=value)
			Printf("hi", "guys"):      hi%!(EXTRA string=guys)
		Too few arguments: %!verb(MISSING)
			Printf("hi%d"):            hi %!d(MISSING)
		Non-int for width or precision: %!(BADWIDTH) or %!(BADPREC)
			Printf("%*s", 4.5, "hi"):  %!(BADWIDTH)hi
			Printf("%.*s", 4.5, "hi"): %!(BADPREC)hi

	All errors begin with the string "%!" followed sometimes
	by a single character (the verb) and end with a parenthesized
	description.

	Scanning:

	An analogous set of functions scans formatted text to yield
	values.  Scan, Scanf and Scanln read from os.Stdin; Fscan,
	Fscanf and Fscanln read from a specified os.Reader; Sscan,
	Sscanf and Sscanln read from an argument string.  Scanln,
	Fscanln and Sscanln stop scanning at a newline and require that
	the items be followed by one; Sscanf, Fscanf and Sscanf require
	newlines in the input to match newlines in the format; the other
	routines treat newlines as spaces.

	Scanf, Fscanf, and Sscanf parse the arguments according to a
	format string, analogous to that of Printf.  For example, %x
	will scan an integer as a hexadecimal number, and %v will scan
	the default representation format for the value.

	The formats behave analogously to those of Printf with the
	following exceptions:

		%p is not implemented
		%T is not implemented
		%e %E %f %F %g %G are all equivalent and scan any floating point or complex value
		%s and %v on strings scan a space-delimited token

	The familiar base-setting prefixes 0 (octal) and 0x
	(hexadecimal) are accepted when scanning integers without a
	format or with the %v verb.

	Width is interpreted in the input text (%5s means at most
	five runes of input will be read to scan a string) but there
	is no syntax for scanning with a precision (no %5.2f, just
	%5f).

	When scanning with a format, all non-empty runs of space
	characters (except newline) are equivalent to a single
	space in both the format and the input.  With that proviso,
	text in the format string must match the input text; scanning
	stops if it does not, with the return value of the function
	indicating the number of arguments scanned.

	In all the scanning functions, if an operand implements method
	Scan (that is, it implements the Scanner interface) that
	method will be used to scan the text for that operand.  Also,
	if the number of arguments scanned is less than the number of
	arguments provided, an error is returned.

	All arguments to be scanned must be either pointers to basic
	types or implementations of the Scanner interface.

	Note: Fscan etc. can read one character (rune) past the input
	they return, which means that a loop calling a scan routine
	may skip some of the input.  This is usually a problem only
	when there is no space between input values.  If the reader
	provided to Fscan implements ReadRune, that method will be used
	to read characters.  If the reader also implements UnreadRune,
	that method will be used to save the character and successive
	calls will not lose data.  To attach ReadRune and UnreadRune
	methods to a reader without that capability, use
	bufio.NewReader.
*/
package fmt
<commit_msg>fmt: fix doc typo<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
	Package fmt implements formatted I/O with functions analogous
	to C's printf and scanf.  The format 'verbs' are derived from C's but
	are simpler.

	Printing:

	The verbs:

	General:
		%v	the value in a default format.
			when printing structs, the plus flag (%+v) adds field names
		%#v	a Go-syntax representation of the value
		%T	a Go-syntax representation of the type of the value
		%%	a literal percent sign; consumes no value

	Boolean:
		%t	the word true or false
	Integer:
		%b	base 2
		%c	the character represented by the corresponding Unicode code point
		%d	base 10
		%o	base 8
		%q	a single-quoted character literal safely escaped with Go syntax.
		%x	base 16, with lower-case letters for a-f
		%X	base 16, with upper-case letters for A-F
		%U	Unicode format: U+1234; same as "U+%04X"
	Floating-point and complex constituents:
		%b	decimalless scientific notation with exponent a power
			of two, in the manner of strconv.Ftoa32, e.g. -123456p-78
		%e	scientific notation, e.g. -1234.456e+78
		%E	scientific notation, e.g. -1234.456E+78
		%f	decimal point but no exponent, e.g. 123.456
		%g	whichever of %e or %f produces more compact output
		%G	whichever of %E or %f produces more compact output
	String and slice of bytes:
		%s	the uninterpreted bytes of the string or slice
		%q	a double-quoted string safely escaped with Go syntax
		%x	base 16, lower-case, two characters per byte
		%X	base 16, upper-case, two characters per byte
	Pointer:
		%p	base 16 notation, with leading 0x

	There is no 'u' flag.  Integers are printed unsigned if they have unsigned type.
	Similarly, there is no need to specify the size of the operand (int8, int64).

	The width and precision control formatting and are in units of Unicode
	code points.  (This differs from C's printf where the units are numbers
	of bytes.) Either or both of the flags may be replaced with the
	character '*', causing their values to be obtained from the next
	operand, which must be of type int.

	For numeric values, width sets the width of the field and precision
	sets the number of places after the decimal, if appropriate.  For
	example, the format %6.2f prints 123.45.

	For strings, width is the minimum number of characters to output,
	padding with spaces if necessary, and precision is the maximum
	number of characters to output, truncating if necessary.

	Other flags:
		+	always print a sign for numeric values;
			guarantee ASCII-only output for %q (%+q)
		-	pad with spaces on the right rather than the left (left-justify the field)
		#	alternate format: add leading 0 for octal (%#o), 0x for hex (%#x);
			0X for hex (%#X); suppress 0x for %p (%#p);
			print a raw (backquoted) string if possible for %q (%#q);
			write e.g. U+0078 'x' if the character is printable for %U (%#U).
		' '	(space) leave a space for elided sign in numbers (% d);
			put spaces between bytes printing strings or slices in hex (% x, % X)
		0	pad with leading zeros rather than spaces

	For each Printf-like function, there is also a Print function
	that takes no format and is equivalent to saying %v for every
	operand.  Another variant Println inserts blanks between
	operands and appends a newline.

	Regardless of the verb, if an operand is an interface value,
	the internal concrete value is used, not the interface itself.
	Thus:
		var i interface{} = 23
		fmt.Printf("%v\n", i)
	will print 23.

	If an operand implements interface Formatter, that interface
	can be used for fine control of formatting.

	If an operand implements method String() string that method
	will be used to convert the object to a string, which will then
	be formatted as required by the verb (if any). To avoid
	recursion in cases such as
		type X int
		func (x X) String() string { return Sprintf("%d", x) }
	cast the value before recurring:
		func (x X) String() string { return Sprintf("%d", int(x)) }

	Format errors:

	If an invalid argument is given for a verb, such as providing
	a string to %d, the generated string will contain a
	description of the problem, as in these examples:

		Wrong type or unknown verb: %!verb(type=value)
			Printf("%d", hi):          %!d(string=hi)
		Too many arguments: %!(EXTRA type=value)
			Printf("hi", "guys"):      hi%!(EXTRA string=guys)
		Too few arguments: %!verb(MISSING)
			Printf("hi%d"):            hi %!d(MISSING)
		Non-int for width or precision: %!(BADWIDTH) or %!(BADPREC)
			Printf("%*s", 4.5, "hi"):  %!(BADWIDTH)hi
			Printf("%.*s", 4.5, "hi"): %!(BADPREC)hi

	All errors begin with the string "%!" followed sometimes
	by a single character (the verb) and end with a parenthesized
	description.

	Scanning:

	An analogous set of functions scans formatted text to yield
	values.  Scan, Scanf and Scanln read from os.Stdin; Fscan,
	Fscanf and Fscanln read from a specified io.Reader; Sscan,
	Sscanf and Sscanln read from an argument string.  Scanln,
	Fscanln and Sscanln stop scanning at a newline and require that
	the items be followed by one; Sscanf, Fscanf and Sscanf require
	newlines in the input to match newlines in the format; the other
	routines treat newlines as spaces.

	Scanf, Fscanf, and Sscanf parse the arguments according to a
	format string, analogous to that of Printf.  For example, %x
	will scan an integer as a hexadecimal number, and %v will scan
	the default representation format for the value.

	The formats behave analogously to those of Printf with the
	following exceptions:

		%p is not implemented
		%T is not implemented
		%e %E %f %F %g %G are all equivalent and scan any floating point or complex value
		%s and %v on strings scan a space-delimited token

	The familiar base-setting prefixes 0 (octal) and 0x
	(hexadecimal) are accepted when scanning integers without a
	format or with the %v verb.

	Width is interpreted in the input text (%5s means at most
	five runes of input will be read to scan a string) but there
	is no syntax for scanning with a precision (no %5.2f, just
	%5f).

	When scanning with a format, all non-empty runs of space
	characters (except newline) are equivalent to a single
	space in both the format and the input.  With that proviso,
	text in the format string must match the input text; scanning
	stops if it does not, with the return value of the function
	indicating the number of arguments scanned.

	In all the scanning functions, if an operand implements method
	Scan (that is, it implements the Scanner interface) that
	method will be used to scan the text for that operand.  Also,
	if the number of arguments scanned is less than the number of
	arguments provided, an error is returned.

	All arguments to be scanned must be either pointers to basic
	types or implementations of the Scanner interface.

	Note: Fscan etc. can read one character (rune) past the input
	they return, which means that a loop calling a scan routine
	may skip some of the input.  This is usually a problem only
	when there is no space between input values.  If the reader
	provided to Fscan implements ReadRune, that method will be used
	to read characters.  If the reader also implements UnreadRune,
	that method will be used to save the character and successive
	calls will not lose data.  To attach ReadRune and UnreadRune
	methods to a reader without that capability, use
	bufio.NewReader.
*/
package fmt
<|endoftext|>


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

// Package os provides a platform-independent interface to operating system
// functionality. The design is Unix-like, although the error handling is
// Go-like; failing calls return values of type error rather than error numbers.
// Often, more information is available within the error. For example,
// if a call that takes a file name fails, such as Open or Stat, the error
// will include the failing file name when printed and will be of type
// *PathError, which may be unpacked for more information.
//
// The os interface is intended to be uniform across all operating systems.
// Features not generally available appear in the system-specific package syscall.
//
// Here is a simple example, opening a file and reading some of it.
//
//	file, err := os.Open("file.go") // For read access.
//	if err != nil {
//		log.Fatal(err)
//	}
//
// If the open fails, the error string will be self-explanatory, like
//
//	open file.go: no such file or directory
//
// The file's data can then be read into a slice of bytes. Read and
// Write take their byte counts from the length of the argument slice.
//
//	data := make([]byte, 100)
//	count, err := file.Read(data)
//	if err != nil {
//		log.Fatal(err)
//	}
//	fmt.Printf("read %d bytes: %q\n", count, data[:count])
//
package os

import (
	"io"
	"syscall"
)

// Name returns the name of the file as presented to Open.
func (f *File) Name() string { return f.name }

// Stdin, Stdout, and Stderr are open Files pointing to the standard input,
// standard output, and standard error file descriptors.
var (
	Stdin  = NewFile(uintptr(syscall.Stdin), "/dev/stdin")
	Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")
	Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr")
)

// Flags to Open wrapping those of the underlying system. Not all flags
// may be implemented on a given system.
const (
	O_RDONLY int = syscall.O_RDONLY // open the file read-only.
	O_WRONLY int = syscall.O_WRONLY // open the file write-only.
	O_RDWR   int = syscall.O_RDWR   // open the file read-write.
	O_APPEND int = syscall.O_APPEND // append data to the file when writing.
	O_CREATE int = syscall.O_CREAT  // create a new file if none exists.
	O_EXCL   int = syscall.O_EXCL   // used with O_CREATE, file must not exist
	O_SYNC   int = syscall.O_SYNC   // open for synchronous I/O.
	O_TRUNC  int = syscall.O_TRUNC  // if possible, truncate file when opened.
)

// Seek whence values.
const (
	SEEK_SET int = 0 // seek relative to the origin of the file
	SEEK_CUR int = 1 // seek relative to the current offset
	SEEK_END int = 2 // seek relative to the end
)

// LinkError records an error during a link or symlink or rename
// system call and the paths that caused it.
type LinkError struct {
	Op  string
	Old string
	New string
	Err error
}

func (e *LinkError) Error() string {
	return e.Op + " " + e.Old + " " + e.New + ": " + e.Err.Error()
}

// Read reads up to len(b) bytes from the File.
// It returns the number of bytes read and an error, if any.
// EOF is signaled by a zero count with err set to io.EOF.
func (f *File) Read(b []byte) (n int, err error) {
	if f == nil {
		return 0, ErrInvalid
	}
	n, e := f.read(b)
	if n < 0 {
		n = 0
	}
	if n == 0 && len(b) > 0 && e == nil {
		return 0, io.EOF
	}
	if e != nil {
		err = &PathError{"read", f.name, e}
	}
	return n, err
}

// ReadAt reads len(b) bytes from the File starting at byte offset off.
// It returns the number of bytes read and the error, if any.
// ReadAt always returns a non-nil error when n < len(b).
// At end of file, that error is io.EOF.
func (f *File) ReadAt(b []byte, off int64) (n int, err error) {
	if f == nil {
		return 0, ErrInvalid
	}
	for len(b) > 0 {
		m, e := f.pread(b, off)
		if m == 0 && e == nil {
			return n, io.EOF
		}
		if e != nil {
			err = &PathError{"read", f.name, e}
			break
		}
		n += m
		b = b[m:]
		off += int64(m)
	}
	return
}

// Write writes len(b) bytes to the File.
// It returns the number of bytes written and an error, if any.
// Write returns a non-nil error when n != len(b).
func (f *File) Write(b []byte) (n int, err error) {
	if f == nil {
		return 0, ErrInvalid
	}
	n, e := f.write(b)
	if n < 0 {
		n = 0
	}
	if n != len(b) {
		err = io.ErrShortWrite
	}

	epipecheck(f, e)

	if e != nil {
		err = &PathError{"write", f.name, e}
	}
	return n, err
}

// WriteAt writes len(b) bytes to the File starting at byte offset off.
// It returns the number of bytes written and an error, if any.
// WriteAt returns a non-nil error when n != len(b).
func (f *File) WriteAt(b []byte, off int64) (n int, err error) {
	if f == nil {
		return 0, ErrInvalid
	}
	for len(b) > 0 {
		m, e := f.pwrite(b, off)
		if e != nil {
			err = &PathError{"write", f.name, e}
			break
		}
		n += m
		b = b[m:]
		off += int64(m)
	}
	return
}

// Seek sets the offset for the next Read or Write on file to offset, interpreted
// according to whence: 0 means relative to the origin of the file, 1 means
// relative to the current offset, and 2 means relative to the end.
// It returns the new offset and an error, if any.
func (f *File) Seek(offset int64, whence int) (ret int64, err error) {
	if f == nil {
		return 0, ErrInvalid
	}
	r, e := f.seek(offset, whence)
	if e == nil && f.dirinfo != nil && r != 0 {
		e = syscall.EISDIR
	}
	if e != nil {
		return 0, &PathError{"seek", f.name, e}
	}
	return r, nil
}

// WriteString is like Write, but writes the contents of string s rather than
// a slice of bytes.
func (f *File) WriteString(s string) (ret int, err error) {
	if f == nil {
		return 0, ErrInvalid
	}
	return f.Write([]byte(s))
}

// Mkdir creates a new directory with the specified name and permission bits.
// If there is an error, it will be of type *PathError.
func Mkdir(name string, perm FileMode) error {
	e := syscall.Mkdir(name, syscallMode(perm))
	if e != nil {
		return &PathError{"mkdir", name, e}
	}
	return nil
}

// Chdir changes the current working directory to the named directory.
// If there is an error, it will be of type *PathError.
func Chdir(dir string) error {
	if e := syscall.Chdir(dir); e != nil {
		return &PathError{"chdir", dir, e}
	}
	return nil
}

// Chdir changes the current working directory to the file,
// which must be a directory.
// If there is an error, it will be of type *PathError.
func (f *File) Chdir() error {
	if f == nil {
		return ErrInvalid
	}
	if e := syscall.Fchdir(f.fd); e != nil {
		return &PathError{"chdir", f.name, e}
	}
	return nil
}

// Open opens the named file for reading.  If successful, methods on
// the returned file can be used for reading; the associated file
// descriptor has mode O_RDONLY.
// If there is an error, it will be of type *PathError.
func Open(name string) (file *File, err error) {
	return OpenFile(name, O_RDONLY, 0)
}

// Create creates the named file mode 0666 (before umask), truncating
// it if it already exists.  If successful, methods on the returned
// File can be used for I/O; the associated file descriptor has mode
// O_RDWR.
// If there is an error, it will be of type *PathError.
func Create(name string) (file *File, err error) {
	return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
}

// lstat is overridden in tests.
var lstat = Lstat
<commit_msg>os: fix build. CL 36800043 and CL 36930044 have a merge conflict that I overlooked.<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package os provides a platform-independent interface to operating system
// functionality. The design is Unix-like, although the error handling is
// Go-like; failing calls return values of type error rather than error numbers.
// Often, more information is available within the error. For example,
// if a call that takes a file name fails, such as Open or Stat, the error
// will include the failing file name when printed and will be of type
// *PathError, which may be unpacked for more information.
//
// The os interface is intended to be uniform across all operating systems.
// Features not generally available appear in the system-specific package syscall.
//
// Here is a simple example, opening a file and reading some of it.
//
//	file, err := os.Open("file.go") // For read access.
//	if err != nil {
//		log.Fatal(err)
//	}
//
// If the open fails, the error string will be self-explanatory, like
//
//	open file.go: no such file or directory
//
// The file's data can then be read into a slice of bytes. Read and
// Write take their byte counts from the length of the argument slice.
//
//	data := make([]byte, 100)
//	count, err := file.Read(data)
//	if err != nil {
//		log.Fatal(err)
//	}
//	fmt.Printf("read %d bytes: %q\n", count, data[:count])
//
package os

import (
	"io"
	"syscall"
)

// Name returns the name of the file as presented to Open.
func (f *File) Name() string { return f.name }

// Stdin, Stdout, and Stderr are open Files pointing to the standard input,
// standard output, and standard error file descriptors.
var (
	Stdin  = NewFile(uintptr(syscall.Stdin), "/dev/stdin")
	Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")
	Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr")
)

// Flags to Open wrapping those of the underlying system. Not all flags
// may be implemented on a given system.
const (
	O_RDONLY int = syscall.O_RDONLY // open the file read-only.
	O_WRONLY int = syscall.O_WRONLY // open the file write-only.
	O_RDWR   int = syscall.O_RDWR   // open the file read-write.
	O_APPEND int = syscall.O_APPEND // append data to the file when writing.
	O_CREATE int = syscall.O_CREAT  // create a new file if none exists.
	O_EXCL   int = syscall.O_EXCL   // used with O_CREATE, file must not exist
	O_SYNC   int = syscall.O_SYNC   // open for synchronous I/O.
	O_TRUNC  int = syscall.O_TRUNC  // if possible, truncate file when opened.
)

// Seek whence values.
const (
	SEEK_SET int = 0 // seek relative to the origin of the file
	SEEK_CUR int = 1 // seek relative to the current offset
	SEEK_END int = 2 // seek relative to the end
)

// LinkError records an error during a link or symlink or rename
// system call and the paths that caused it.
type LinkError struct {
	Op  string
	Old string
	New string
	Err error
}

func (e *LinkError) Error() string {
	return e.Op + " " + e.Old + " " + e.New + ": " + e.Err.Error()
}

// Read reads up to len(b) bytes from the File.
// It returns the number of bytes read and an error, if any.
// EOF is signaled by a zero count with err set to io.EOF.
func (f *File) Read(b []byte) (n int, err error) {
	if f == nil {
		return 0, ErrInvalid
	}
	n, e := f.read(b)
	if n < 0 {
		n = 0
	}
	if n == 0 && len(b) > 0 && e == nil {
		return 0, io.EOF
	}
	if e != nil {
		err = &PathError{"read", f.name, e}
	}
	return n, err
}

// ReadAt reads len(b) bytes from the File starting at byte offset off.
// It returns the number of bytes read and the error, if any.
// ReadAt always returns a non-nil error when n < len(b).
// At end of file, that error is io.EOF.
func (f *File) ReadAt(b []byte, off int64) (n int, err error) {
	if f == nil {
		return 0, ErrInvalid
	}
	for len(b) > 0 {
		m, e := f.pread(b, off)
		if m == 0 && e == nil {
			return n, io.EOF
		}
		if e != nil {
			err = &PathError{"read", f.name, e}
			break
		}
		n += m
		b = b[m:]
		off += int64(m)
	}
	return
}

// Write writes len(b) bytes to the File.
// It returns the number of bytes written and an error, if any.
// Write returns a non-nil error when n != len(b).
func (f *File) Write(b []byte) (n int, err error) {
	if f == nil {
		return 0, ErrInvalid
	}
	n, e := f.write(b)
	if n < 0 {
		n = 0
	}
	if n != len(b) {
		err = io.ErrShortWrite
	}

	epipecheck(f, e)

	if e != nil {
		err = &PathError{"write", f.name, e}
	}
	return n, err
}

// WriteAt writes len(b) bytes to the File starting at byte offset off.
// It returns the number of bytes written and an error, if any.
// WriteAt returns a non-nil error when n != len(b).
func (f *File) WriteAt(b []byte, off int64) (n int, err error) {
	if f == nil {
		return 0, ErrInvalid
	}
	for len(b) > 0 {
		m, e := f.pwrite(b, off)
		if e != nil {
			err = &PathError{"write", f.name, e}
			break
		}
		n += m
		b = b[m:]
		off += int64(m)
	}
	return
}

// Seek sets the offset for the next Read or Write on file to offset, interpreted
// according to whence: 0 means relative to the origin of the file, 1 means
// relative to the current offset, and 2 means relative to the end.
// It returns the new offset and an error, if any.
func (f *File) Seek(offset int64, whence int) (ret int64, err error) {
	if f == nil {
		return 0, ErrInvalid
	}
	r, e := f.seek(offset, whence)
	if e == nil && f.dirinfo != nil && r != 0 {
		e = syscall.EISDIR
	}
	if e != nil {
		return 0, &PathError{"seek", f.name, e}
	}
	return r, nil
}

// WriteString is like Write, but writes the contents of string s rather than
// a slice of bytes.
func (f *File) WriteString(s string) (ret int, err error) {
	if f == nil {
		return 0, ErrInvalid
	}
	return f.Write([]byte(s))
}

// Mkdir creates a new directory with the specified name and permission bits.
// If there is an error, it will be of type *PathError.
func Mkdir(name string, perm FileMode) error {
	e := syscall.Mkdir(name, syscallMode(perm))
	if e != nil {
		return &PathError{"mkdir", name, e}
	}
	return nil
}

// Chdir changes the current working directory to the named directory.
// If there is an error, it will be of type *PathError.
func Chdir(dir string) error {
	if e := syscall.Chdir(dir); e != nil {
		return &PathError{"chdir", dir, e}
	}
	return nil
}

// Chdir changes the current working directory to the file,
// which must be a directory.
// If there is an error, it will be of type *PathError.
func (f *File) Chdir() error {
	if f == nil {
		return ErrInvalid
	}
	if e := syscall.Fchdir(f.fd); e != nil {
		return &PathError{"chdir", f.name, e}
	}
	return nil
}

// Open opens the named file for reading.  If successful, methods on
// the returned file can be used for reading; the associated file
// descriptor has mode O_RDONLY.
// If there is an error, it will be of type *PathError.
func Open(name string) (file *File, err error) {
	return OpenFile(name, O_RDONLY, 0)
}

// Create creates the named file mode 0666 (before umask), truncating
// it if it already exists.  If successful, methods on the returned
// File can be used for I/O; the associated file descriptor has mode
// O_RDWR.
// If there is an error, it will be of type *PathError.
func Create(name string) (file *File, err error) {
	return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
}

// lstat is overridden in tests.
var lstat = Lstat

// Rename renames (moves) a file. OS-specific restrictions might apply.
func Rename(oldpath, newpath string) error {
	return rename(oldpath, newpath)
}
<|endoftext|>


<commit_before>package web

import (
	"doozer/store"
	"doozer/util"
	"http"
	"io"
	"json"
	"log"
	"net"
	"runtime"
	"strings"
	"template"
	"websocket"
)

var Store *store.Store
var ClusterName, evPrefix string

var (
	mainTpl  = template.MustParse(main_html, nil)
	statsTpl = template.MustParse(stats_html, nil)
)

type info struct {
	Path string
}

type stringHandler struct {
	contentType string
	body        string
}

func (sh stringHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	w.SetHeader("content-type", sh.contentType)
	io.WriteString(w, sh.body)
}

func Serve(listener net.Listener) {
	prefix := "/d/" + ClusterName
	evPrefix = "/events" + prefix

	http.Handle("/", http.RedirectHandler("/view/d/"+ClusterName+"/", 307))
	http.HandleFunc("/stats.html", statsHtml)
	http.HandleFunc("/view/", viewHtml)
	http.Handle("/main.js", stringHandler{"application/javascript", main_js})
	http.Handle("/main.css", stringHandler{"text/css", main_css})
	http.HandleFunc(evPrefix+"/", evServer)

	http.Serve(listener, nil)
}

func send(ws *websocket.Conn, path string, evs <-chan store.Event, logger *log.Logger) {
	defer close(evs)
	l := len(path) - 1
	for ev := range evs {
		ev.Getter = nil // don't marshal the entire snapshot
		ev.Path = ev.Path[l:]
		logger.Println("sending", ev)
		b, err := json.Marshal(ev)
		if err != nil {
			logger.Println(err)
			return
		}
		_, err = ws.Write(b)
		if err != nil {
			logger.Println(err)
			return
		}
	}
}

func evServer(w http.ResponseWriter, r *http.Request) {
	wevs := make(chan store.Event)
	logger := util.NewLogger(w.RemoteAddr())
	path := r.URL.Path[len(evPrefix):]
	logger.Println("new", path)

	glob, err := store.CompileGlob(path + "**")
	if err != nil {
		w.WriteHeader(400)
		return
	}

	wt := store.NewWatch(Store, glob)

	// TODO convert store.Snapshot to json and use that
	go func() {
		walk(path, Store, wevs)
		close(wevs)
	}()

	websocket.Handler(func(ws *websocket.Conn) {
		send(ws, path, wevs, logger)
		send(ws, path, wt.C, logger)
		wt.Stop()
		ws.Close()
	}).ServeHTTP(w, r)
}

func viewHtml(w http.ResponseWriter, r *http.Request) {
	if !strings.HasSuffix(r.URL.Path, "/") {
		w.WriteHeader(404)
		return
	}
	var x info
	x.Path = r.URL.Path[len("/view"):]
	w.SetHeader("content-type", "text/html")
	mainTpl.Execute(x, w)
}

func statsHtml(w http.ResponseWriter, r *http.Request) {
	w.SetHeader("content-type", "text/html")
	statsTpl.Execute(runtime.MemStats, w)
}

func walk(path string, st *store.Store, ch chan store.Event) {
	for path != "/" && strings.HasSuffix(path, "/") {
		// TODO generalize and factor this into pkg store.
		path = path[0 : len(path)-1]
	}
	v, cas := st.Get(path)
	if cas != store.Dir {
		ch <- store.Event{0, path, v[0], cas, "", nil, nil}
		return
	}
	if path == "/" {
		path = ""
	}
	for _, ent := range v {
		walk(path+"/"+ent, st, ch)
	}
}
<commit_msg>update for go release 2011-02-15<commit_after>package web

import (
	"doozer/store"
	"doozer/util"
	"http"
	"io"
	"json"
	"log"
	"net"
	"runtime"
	"strings"
	"template"
	"websocket"
)

var Store *store.Store
var ClusterName, evPrefix string

var (
	mainTpl  = template.MustParse(main_html, nil)
	statsTpl = template.MustParse(stats_html, nil)
)

type info struct {
	Path string
}

type stringHandler struct {
	contentType string
	body        string
}

func (sh stringHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	w.SetHeader("content-type", sh.contentType)
	io.WriteString(w, sh.body)
}

func Serve(listener net.Listener) {
	prefix := "/d/" + ClusterName
	evPrefix = "/events" + prefix

	http.Handle("/", http.RedirectHandler("/view/d/"+ClusterName+"/", 307))
	http.HandleFunc("/stats.html", statsHtml)
	http.HandleFunc("/view/", viewHtml)
	http.Handle("/main.js", stringHandler{"application/javascript", main_js})
	http.Handle("/main.css", stringHandler{"text/css", main_css})
	http.HandleFunc(evPrefix+"/", evServer)

	http.Serve(listener, nil)
}

func send(ws *websocket.Conn, path string, evs <-chan store.Event, logger *log.Logger) {
	defer close(evs)
	l := len(path) - 1
	for ev := range evs {
		ev.Getter = nil // don't marshal the entire snapshot
		ev.Path = ev.Path[l:]
		logger.Println("sending", ev)
		b, err := json.Marshal(ev)
		if err != nil {
			logger.Println(err)
			return
		}
		_, err = ws.Write(b)
		if err != nil {
			logger.Println(err)
			return
		}
	}
}

func evServer(w http.ResponseWriter, r *http.Request) {
	wevs := make(chan store.Event)
	logger := util.NewLogger(w.RemoteAddr())
	path := r.URL.Path[len(evPrefix):]
	logger.Println("new", path)

	glob, err := store.CompileGlob(path + "**")
	if err != nil {
		w.WriteHeader(400)
		return
	}

	wt := store.NewWatch(Store, glob)

	// TODO convert store.Snapshot to json and use that
	go func() {
		walk(path, Store, wevs)
		close(wevs)
	}()

	websocket.Handler(func(ws *websocket.Conn) {
		send(ws, path, wevs, logger)
		send(ws, path, wt.C, logger)
		wt.Stop()
		ws.Close()
	}).ServeHTTP(w, r)
}

func viewHtml(w http.ResponseWriter, r *http.Request) {
	if !strings.HasSuffix(r.URL.Path, "/") {
		w.WriteHeader(404)
		return
	}
	var x info
	x.Path = r.URL.Path[len("/view"):]
	w.SetHeader("content-type", "text/html")
	mainTpl.Execute(w, x)
}

func statsHtml(w http.ResponseWriter, r *http.Request) {
	w.SetHeader("content-type", "text/html")
	statsTpl.Execute(w, runtime.MemStats)
}

func walk(path string, st *store.Store, ch chan store.Event) {
	for path != "/" && strings.HasSuffix(path, "/") {
		// TODO generalize and factor this into pkg store.
		path = path[0 : len(path)-1]
	}
	v, cas := st.Get(path)
	if cas != store.Dir {
		ch <- store.Event{0, path, v[0], cas, "", nil, nil}
		return
	}
	if path == "/" {
		path = ""
	}
	for _, ent := range v {
		walk(path+"/"+ent, st, ch)
	}
}
<|endoftext|>


<commit_before>package server

import (
	"../bitset"
	"../hashtree"
	"../network"
)

type Source interface {
	RequestableSize() hashtree.Bytes
	AddRequest(file *network.File)
	RemoveRequest(file *network.File)
	Reset()
}

type DownloadTask struct {
	id            network.StaticId
	sources       []Source
	hashCompleted bool
	complete      bool
	hashesSet     bitset.BitSet
	dataSet       bitset.BitSet
}

func newDownlaodTask(d Database, id network.StaticId, sources []Source) *DownloadTask {

	t := &DownloadTask{
		id:      id,
		sources: sources,
	}

	state := d.GetState(id)

	switch state {
	case FILE_UNKNOW:
		err := d.StartPart(id)
		if err != nil {
			log.Printf("starting new DownloadTask err:%v", err)
		}
		t.hashCompleted = false
		t.hashesSet = d.InnerHashesSet(id)
	case FILE_PART:
		if !HaveAllInnerHashes(d, id) {
			t.hashCompleted = false
			t.hashesSet = d.InnerHashesSet(id)
		} else {
			t.hashCompleted = true
			t.dataSet = d.DataPartsSet(id)
		}
	case FILE_COMPLETE:
		t.complete = true
	}

	return t
}

type TaskManager struct {
	tasks map[string]DownloadTask
}
<commit_msg>working on create requests<commit_after>package server

import (
	"../bitset"
	"../hashtree"
	"../network"
)

type Source interface {
	RequestableSize() hashtree.Bytes
	AddRequest(file *network.File)
	RemoveRequest(file *network.File)
	Reset()
}

type DownloadTask struct {
	id            network.StaticId
	sources       []Source
	hashCompleted bool
	complete      bool
	hashesSet     bitset.BitSet
	dataSet       bitset.BitSet
}

func newDownlaodTask(d Database, id network.StaticId, sources []Source) *DownloadTask {

	t := &DownloadTask{
		id:      id,
		sources: sources,
	}

	state := d.GetState(id)

	switch state {
	case FILE_UNKNOW:
		err := d.StartPart(id)
		if err != nil {
			log.Printf("starting new DownloadTask err:%v", err)
		}
		t.hashCompleted = false
		t.hashesSet = d.InnerHashesSet(id)
	case FILE_PART:
		if !HaveAllInnerHashes(d, id) {
			t.hashCompleted = false
			t.hashesSet = d.InnerHashesSet(id)
		} else {
			t.hashCompleted = true
			t.dataSet = d.DataPartsSet(id)
		}
	case FILE_COMPLETE:
		t.complete = true
	}

	return t
}

type TaskManager struct {
	tasks map[string]*DownloadTask
	d     Database
}

func (tm *TaskManager) AddDownload(id network.StaticId, sources []Source) {
	t, ok := tm.tasks[id.CompactId()]
	if !ok {
		t = newDownlaodTask(tm.d, id, sources)
		tm.tasks[id.CompactId()] = t
	} else {
		//todo just add sources to t
	}
}

// Request the amount of data up to maxAmount now (expected to be used per tic)
// Only data and inner-hashes are counted, other overhead aren't,
// In the future, there maybe more than one maxAmount (ie, one for local, one for world)
// Returns the actual amount request, which should be the same as maxAmount unless:
// - sourcesFull: all sourcess have there own bandwidth/request queue satuated
// - allRequested: all parts of all downloading files are requested
// - maxAmount - requested < the smallest size requestable (1024)
func (tm *TaskManager) doRequest(maxAmount hashtree.Bytes) (requested hashtree.Bytes, sourcesFull bool, allRequested bool) {
	reqLeft := maxAmount
	allRequested = true
	sourcesFull = true
	for _, t := range tm.tasks {
		if reqLeft <= 1024 {
			sourcesFull = false
			allRequested = false
			break
		}
		r, s, a := t.doRequest(reqLeft)
		reqLeft -= r
		sourcesFull = sourcesFull && s
		allRequested = allRequested && a
	}
	requested = maxAmount - reqLeft
	return
}

func (t *DownloadTask) doRequest(maxAmount hashtree.Bytes) (requested hashtree.Bytes, sourcesFull bool, allRequested bool) {
	//todo
	return 0, true, false
}
<|endoftext|>


<commit_before>// TODO - hmac

package sloth

import (
  "fmt"
  "bytes"
  "net/http"
  "net/url"
  "database/sql"
  _ "github.com/go-sql-driver/mysql"
)

// Hooks

var _ RestfulHook = (*RestHook)(nil)

type RestfulHook interface {
  Mesg(interface{}) (*http.Response, error)
  Kill()
}

type RestHook struct {
  subscriberUrl    string
  subscriberMethod string
}

func (hook *RestHook) Url() string {
  return hook.subscriberUrl
}

func (hook *RestHook) Method() string {
  return hook.subscriberMethod
}

func (hook *RestHook) Mesg(data interface{}) (*http.Response, error) {
  hookCaller   := &http.Client{}
  dataBytes, _ := AsBytes(data)

  req, err := http.NewRequest(hook.subscriberMethod, hook.subscriberUrl, bytes.NewBuffer(dataBytes))

  if err != nil {
    panic(err)
  }

  req.Header.Add("X-Sloth-Hook-Id",        `W/"something"`)
  req.Header.Add("X-Sloth-Hook-Signature", `W/"abc123"`) // TODO - HMAC

  resp, err := hookCaller.Do(req)

  defer resp.Body.Close()

  return resp, err
}

func (hook *RestHook) Kill() {

}

// Hook resource

var _ HookableResource = (*HookResource)(nil)

type HookableResource interface {
  RestfulResource

  Subscribe(subUrl string, subMethod string)
  Broadcast(data interface{})
}

type HookResource struct {
  UrlSlug string
  RestResource
  Hooks []RestHook
}

func (resource *HookResource) Slug() string {
  return resource.UrlSlug
}

func (resource *HookResource) Put(values url.Values) (int, interface{}) {
  resource.Subscribe(values["subscriber_url"][0], values["subscriber_method"][0])
  return 200, "FIXME"
}

func (resource *HookResource) Subscribe(subUrl string, subMethod string) {
  newHook := RestHook {
    subscriberUrl    : subUrl,
    subscriberMethod : subMethod,
  }

  resource.Hooks = append(resource.Hooks, newHook)

  fmt.Println("Successful subscription!", subUrl, subMethod)
}

func (resource *HookResource) Broadcast(data interface{}) {
  // TODO - make this async / concurrent
  for _, hook := range resource.Hooks {
    hook.Mesg(data)
  }
}

// Hook repository

type HookRepo struct { }

func (repo *HookRepo) Db() *sql.DB {
  db, err := sql.Open("mysql", "user:password@/hooks") // FIXME - integrate with config

  if err != nil {
    fmt.Println("improve this error")
  }

  return db
}

func (repo *HookRepo) All() (*sql.Rows, error) {
  return repo.Db().Query("select id, subscriber_url, subscriber_method from hooks")
}

func (repo *HookRepo) Add(hook *RestHook) (sql.Result, error) {
  return repo.Db().Exec("insert into hooks (subscriber_url, subscriber_method) values (?, ?)", hook.subscriberUrl, hook.subscriberMethod)
}

func (repo *HookRepo) Delete(hook *RestHook) (sql.Result, error) {
  return repo.Db().Exec("delete from hooks where subscriber_url = ? and subscriber_method = ?", hook.subscriberUrl, hook.subscriberMethod)
}

func (repo *HookRepo) Close() {
  repo.Db().Close()
}
<commit_msg>made broadcast a go routine<commit_after>// TODO - hmac

package sloth

import (
  "fmt"
  "bytes"
  "net/http"
  "net/url"
  "database/sql"
  _ "github.com/go-sql-driver/mysql"
)

// Hooks

var _ RestfulHook = (*RestHook)(nil)

type RestfulHook interface {
  Mesg(interface{}) (*http.Response, error)
  Kill()
}

type RestHook struct {
  subscriberUrl    string
  subscriberMethod string
}

func (hook *RestHook) Url() string {
  return hook.subscriberUrl
}

func (hook *RestHook) Method() string {
  return hook.subscriberMethod
}

func (hook *RestHook) Mesg(data interface{}) (*http.Response, error) {
  hookCaller   := &http.Client{}
  dataBytes, _ := AsBytes(data)

  req, err := http.NewRequest(hook.subscriberMethod, hook.subscriberUrl, bytes.NewBuffer(dataBytes))

  if err != nil {
    panic(err)
  }

  req.Header.Add("X-Sloth-Hook-Id",        `W/"something"`)
  req.Header.Add("X-Sloth-Hook-Signature", `W/"abc123"`) // TODO - HMAC

  resp, err := hookCaller.Do(req)

  defer resp.Body.Close()

  return resp, err
}

func (hook *RestHook) Kill() {

}

// Hook resource

var _ HookableResource = (*HookResource)(nil)

type HookableResource interface {
  RestfulResource

  Subscribe(subUrl string, subMethod string)
  Broadcast(data interface{})
}

type HookResource struct {
  UrlSlug string
  RestResource
  Hooks []RestHook
}

func (resource *HookResource) Slug() string {
  return resource.UrlSlug
}

func (resource *HookResource) Put(values url.Values) (int, interface{}) {
  resource.Subscribe(values["subscriber_url"][0], values["subscriber_method"][0])
  return 200, "FIXME"
}

func (resource *HookResource) Subscribe(subUrl string, subMethod string) {
  newHook := RestHook {
    subscriberUrl    : subUrl,
    subscriberMethod : subMethod,
  }

  resource.Hooks = append(resource.Hooks, newHook)

  fmt.Println("Successful subscription!", subUrl, subMethod)
}

func (resource *HookResource) Broadcast(data interface{}) {
  go func() {
    for _, hook := range resource.Hooks {
      hook.Mesg(data)
    }
  }()
}

// Hook repository

type HookRepo struct { }

func (repo *HookRepo) Db() *sql.DB {
  db, err := sql.Open("mysql", "user:password@/hooks") // FIXME - integrate with config

  if err != nil {
    fmt.Println("improve this error")
  }

  return db
}

func (repo *HookRepo) All() (*sql.Rows, error) {
  return repo.Db().Query("select id, subscriber_url, subscriber_method from hooks")
}

func (repo *HookRepo) Add(hook *RestHook) (sql.Result, error) {
  return repo.Db().Exec("insert into hooks (subscriber_url, subscriber_method) values (?, ?)", hook.subscriberUrl, hook.subscriberMethod)
}

func (repo *HookRepo) Delete(hook *RestHook) (sql.Result, error) {
  return repo.Db().Exec("delete from hooks where subscriber_url = ? and subscriber_method = ?", hook.subscriberUrl, hook.subscriberMethod)
}

func (repo *HookRepo) Close() {
  repo.Db().Close()
}
<|endoftext|>


<commit_before>package worker

import (
	"log"
	"os"
	"sync"

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

const (
	DefaultWorkersCount = 10
)

// Pool represents a pool of workers connected to a queue.
type Pool struct {
	count int   // workers count
	queue Queue // input queue

	middleware middleware
	handlers   []Handler
	mux        map[string]Factory
	logger     *log.Logger
}

// SetQueue assigns a custom queue to worker pool.
func SetQueue(q Queue) func(*Pool) {
	return func(p *Pool) {
		p.queue = q
	}
}

// SetWorkers configures the pool concurrency.
func SetWorkers(n int) func(*Pool) {
	return func(p *Pool) {
		p.count = n
	}
}

// NewPool returns a new Pool instance.
func NewPool(opts ...func(*Pool)) *Pool {
	pool := &Pool{
		count:    DefaultWorkersCount,
		queue:    NewMemoryQueue(),
		mux:      map[string]Factory{},
		logger:   log.New(os.Stdout, "[worker] ", 0),
		handlers: CommonStack(),
	}

	// Apply options.
	for _, opt := range opts {
		opt(pool)
	}

	// Init middleware stack.
	pool.middleware = pool.build(pool.handlers)

	return pool
}

// Add registers a new job factory.
func (p *Pool) Add(f Factory) error {
	typ, err := StructType(f)
	if err != nil {
		return err
	}

	if _, ok := p.mux[typ]; ok {
		return NewErrorFmt("factory %q exists already", typ)
	}
	p.mux[typ] = f
	return nil
}

// Use appends a new middleware to current stack.
func (p *Pool) Use(h Handler) {
	p.handlers = append(p.handlers, h)
	p.middleware = p.build(p.handlers)
}

// build iterates over the handlers, it returns a
// list of middlewares with each item linked to
// the next one.
func (p *Pool) build(hs []Handler) middleware {
	if len(hs) == 0 {
		return p.last()
	}
	next := p.build(hs[1:])
	return middleware{hs[0], &next}
}

// last builds and returns the last middleware, which will
// execute the job without calling next middleware.
func (p *Pool) last() middleware {
	return middleware{
		HandlerFunc(func(sw StatusWriter, fact string, args *Args, next JobRunner) {
			err := p.execute(fact, args)
			sw.Set(err)
		}),
		&middleware{},
	}
}

// Run starts processing jobs from the queue.
func (p *Pool) Run(ctx context.Context) error {
	var wg sync.WaitGroup

	// Fan-out channel.
	c := make(chan *Message)
	defer close(c)

	// Start workers.
	wg.Add(p.count)
	for i := 0; i < p.count; i++ {
		go func() {
			defer wg.Done()
			p.worker(ctx, c)
		}()
	}

	// Start producer.
	for {
		msg, err := p.queue.Get(ctx)
		if err != nil {
			if wkerr, ok := err.(*Error); ok && wkerr.Timeout() {
				continue
			}
			return err
		}

		select {
		case <-ctx.Done():
			wg.Wait()
			return ctx.Err()
		case c <- msg:
		}
	}
}

// worker executes jobs from the in channel in a separate goroutine.
func (p *Pool) worker(ctx context.Context, in chan *Message) {
	for msg := range in {
		status := NewStatusWriter()
		done := make(chan struct{}, 1)

		// Start the job in a separate goroutine.
		go func() {
			p.Exec(status, msg.Type(), msg.Args())
			done <- struct{}{}
		}()

		// Wait job completion.
		select {
		case <-ctx.Done():
			return
		case <-done:
			if status.OK() {
				if err := p.queue.Delete(ctx, msg); err != nil {
					p.logger.Println("delete:", msg, err)
				}
			} else {
				if err := p.queue.Reject(ctx, msg); err != nil {
					p.logger.Println("reject:", msg, err)
				}
			}
		}
	}
}

// Exec runs the job passing it through the middleware stack.
func (p *Pool) Exec(sw StatusWriter, fact string, args *Args) {
	p.middleware.Exec(sw, fact, args)
}

// execute runs the job without passing it through the
// middleware stack.
func (p *Pool) execute(fact string, args *Args) error {
	f, ok := p.mux[fact]
	if !ok {
		return NewErrorFmt("bad type: %v", fact)
	}

	j, err := f.Make(args)
	if err != nil {
		return NewErrorFmt("make: %v", err)
	}

	if err := j.Run(); err != nil {
		return NewErrorFmt("run: %v", err)
	}

	return nil
}
<commit_msg>Add trap method<commit_after>package worker

import (
	"log"
	"os"
	"os/signal"
	"sync"
	"syscall"

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

const (
	DefaultWorkersCount = 10
)

// Pool represents a pool of workers connected to a queue.
type Pool struct {
	count int   // workers count
	queue Queue // input queue

	middleware middleware
	handlers   []Handler
	mux        map[string]Factory
	logger     *log.Logger
}

// SetQueue assigns a custom queue to worker pool.
func SetQueue(q Queue) func(*Pool) {
	return func(p *Pool) {
		p.queue = q
	}
}

// SetWorkers configures the pool concurrency.
func SetWorkers(n int) func(*Pool) {
	return func(p *Pool) {
		p.count = n
	}
}

// NewPool returns a new Pool instance.
func NewPool(opts ...func(*Pool)) *Pool {
	pool := &Pool{
		count:    DefaultWorkersCount,
		queue:    NewMemoryQueue(),
		mux:      map[string]Factory{},
		logger:   log.New(os.Stdout, "[worker] ", 0),
		handlers: CommonStack(),
	}

	// Apply options.
	for _, opt := range opts {
		opt(pool)
	}

	// Init middleware stack.
	pool.middleware = pool.build(pool.handlers)

	return pool
}

// Add registers a new job factory.
func (p *Pool) Add(f Factory) error {
	typ, err := StructType(f)
	if err != nil {
		return err
	}

	if _, ok := p.mux[typ]; ok {
		return NewErrorFmt("factory %q exists already", typ)
	}
	p.mux[typ] = f
	return nil
}

// Use appends a new middleware to current stack.
func (p *Pool) Use(h Handler) {
	p.handlers = append(p.handlers, h)
	p.middleware = p.build(p.handlers)
}

// build iterates over the handlers, it returns a
// list of middlewares with each item linked to
// the next one.
func (p *Pool) build(hs []Handler) middleware {
	if len(hs) == 0 {
		return p.last()
	}
	next := p.build(hs[1:])
	return middleware{hs[0], &next}
}

// last builds and returns the last middleware, which will
// execute the job without calling next middleware.
func (p *Pool) last() middleware {
	return middleware{
		HandlerFunc(func(sw StatusWriter, fact string, args *Args, next JobRunner) {
			err := p.execute(fact, args)
			sw.Set(err)
		}),
		&middleware{},
	}
}

// Run starts processing jobs from the queue.
func (p *Pool) Run(ctx context.Context) error {
	var wg sync.WaitGroup

	// Fan-out channel.
	c := make(chan *Message)
	defer close(c)

	// Start workers.
	wg.Add(p.count)
	for i := 0; i < p.count; i++ {
		go func() {
			defer wg.Done()
			p.worker(ctx, c)
		}()
	}

	// Start producer.
	for {
		msg, err := p.queue.Get(ctx)
		if err != nil {
			if wkerr, ok := err.(*Error); ok && wkerr.Timeout() {
				continue
			}
			return err
		}

		select {
		case <-ctx.Done():
			wg.Wait()
			return ctx.Err()
		case c <- msg:
		}
	}
}

// worker executes jobs from the in channel in a separate goroutine.
func (p *Pool) worker(ctx context.Context, in chan *Message) {
	for msg := range in {
		status := NewStatusWriter()
		done := make(chan struct{}, 1)

		// Start the job in a separate goroutine.
		go func() {
			p.Exec(status, msg.Type(), msg.Args())
			done <- struct{}{}
		}()

		// Wait job completion.
		select {
		case <-ctx.Done():
			return
		case <-done:
			if status.OK() {
				if err := p.queue.Delete(ctx, msg); err != nil {
					p.logger.Println("delete:", msg, err)
				}
			} else {
				if err := p.queue.Reject(ctx, msg); err != nil {
					p.logger.Println("reject:", msg, err)
				}
			}
		}
	}
}

// Exec runs the job passing it through the middleware stack.
func (p *Pool) Exec(sw StatusWriter, fact string, args *Args) {
	p.middleware.Exec(sw, fact, args)
}

// execute runs the job without passing it through the
// middleware stack.
func (p *Pool) execute(fact string, args *Args) error {
	f, ok := p.mux[fact]
	if !ok {
		return NewErrorFmt("bad type: %v", fact)
	}

	j, err := f.Make(args)
	if err != nil {
		return NewErrorFmt("make: %v", err)
	}

	if err := j.Run(); err != nil {
		return NewErrorFmt("run: %v", err)
	}

	return nil
}

func (p *Pool) trap() <-chan struct{} {
	out := make(chan struct{}, 1)
	signals := make(chan os.Signal, 1)
	signal.Notify(signals, syscall.SIGUSR1, syscall.SIGINT, syscall.SIGTERM)

	go func() {
		defer close(out)
		for s := range signals {
			switch s {
			case syscall.SIGINT, syscall.SIGUSR1, syscall.SIGTERM:
				p.logger.Println("Quit signal received!")
				out <- struct{}{}
				return
			}
		}
	}()

	return out
}
<|endoftext|>


<commit_before>// MIT License
//
// Copyright (c) 2017 Ryan Fowler
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

package red

import (
	"errors"
	"sync"
	"time"
)

var errPoolClosed = errors.New("red: pool closed")

type idleConn struct {
	conn      Conn
	idleSince time.Time
}

// Pool represents a pool of zero or more Redis Conns. All methods on a Pool are
// save to use concurrently.
type Pool struct {
	// Addr represents the address of the Redis server to connect to; Required.
	Addr string
	// Dial is an optional function to create a Conn. The default dial
	// attempts to create a TCP connection to the Redis server with a 30 -
	// second connection timeout.
	Dial func(string) (Conn, error)
	// MaxActiveConns represents the maximum total active connections at a
	// given time. A value <= 0 is no active limit.
	MaxActiveConns int
	// MaxIdleConns represents the maximum number of idle connections at a
	// given time. The default value is 10.
	MaxIdleConns int
	// MaxIdleDuration represents the timeout for an idle connection. By
	// default, there is no idle timeout.
	MaxIdleDuration time.Duration
	// OnReuse is an optional function to intercept an idle Conn before use.
	// If OnReuse returns false, the Conn will be closed and another will be
	// retrieved/created.
	OnReuse func(Conn) bool

	mu           sync.Mutex
	cond         *sync.Cond
	numWaiting   int
	numActive    int
	closed       bool
	chMaxIdleDur chan struct{}
	idleConns    []*idleConn
}

// Status represents the status of a Pool.
type Status struct {
	// Closed is true of the Pool has been closed.
	Closed bool
	// NumActive is the total number of active connections.
	NumActive int
	// NumIdle is the number of idle connections.
	NumIdle int
	// NumWaiting is the total number of connections waiting for an idle
	// connection.
	NumWaiting int
}

// Status returns the current status of the Pool.
func (p *Pool) Status() Status {
	p.mu.Lock()
	s := Status{
		Closed:     p.closed,
		NumActive:  p.numActive,
		NumIdle:    len(p.idleConns),
		NumWaiting: p.numWaiting,
	}
	p.mu.Unlock()
	return s
}

// Close closes the Pool and any of its idle connections. After being closed, a
// pool cannot be used and any attempt to use it will return an error.
func (p *Pool) Close() error {
	p.mu.Lock()
	if p.closed {
		p.mu.Unlock()
		return nil
	}
	p.closed = true

	toClose := make([]Conn, len(p.idleConns))
	for i, c := range p.idleConns {
		toClose[i] = c.conn
		p.idleConns[i] = nil
	}
	p.idleConns = nil

	if p.chMaxIdleDur != nil {
		select {
		case p.chMaxIdleDur <- struct{}{}:
		default:
		}
	}
	p.numActive -= len(toClose)
	if p.cond != nil && p.numWaiting > 0 {
		p.cond.Broadcast()
	}
	p.mu.Unlock()

	for _, c := range toClose {
		c.Close()
	}

	return nil
}

// Conn allows for direct access to a Conn using the provided function. The
// Conn is only valid during the lifetime of the function. Conn will return any
// error returned by fn.
func (p *Pool) Conn(fn func(c Conn) error) error {
	c, err := p.getConn()
	if err != nil {
		return err
	}
	defer p.putConn(c)
	return fn(c)
}

func (p *Pool) getConn() (Conn, error) {
	p.mu.Lock()
	for {
		// Return if pool is closed.
		if p.closed {
			p.mu.Unlock()
			return nil, errPoolClosed
		}

		// Attempt to get an idle conn.
		if len(p.idleConns) > 0 {
			c := p.popIdle()
			p.mu.Unlock()
			if p.OnReuse != nil && !p.OnReuse(c) {
				c.Close()
				p.mu.Lock()
				p.decrActiveLocked(1)
				continue
			}
			return c, nil
		}

		// Check number of active conns.
		if p.MaxActiveConns <= 0 || p.numActive < p.MaxActiveConns {
			break
		}
		if p.cond == nil {
			p.cond = sync.NewCond(&p.mu)
		}

		p.numWaiting++
		p.cond.Wait()
		p.numWaiting--
	}
	p.numActive++
	p.mu.Unlock()

	// Create and return a new connection.
	c, err := p.dialConn()
	if err != nil {
		p.mu.Lock()
		p.decrActiveLocked(1)
		p.mu.Unlock()
		return nil, err
	}
	return c, nil
}

func (p *Pool) dialConn() (Conn, error) {
	if p.Dial == nil {
		return Dial(p.Addr, defaultDialTimeout)
	}
	return p.Dial(p.Addr)
}

func (p *Pool) popIdle() Conn {
	// TODO (ryanfowler): optimize?
	c := p.idleConns[0]
	copy(p.idleConns, p.idleConns[1:])
	p.idleConns[len(p.idleConns)-1] = nil
	p.idleConns = p.idleConns[:len(p.idleConns)-1]
	return c.conn
}

func (p *Pool) putConn(c Conn) {
	if c == nil {
		return
	}

	p.mu.Lock()

	// Return if the pool is closed or the connection has a fatal error.
	if p.closed || c.Err() != nil {
		p.decrActiveLocked(1)
		p.mu.Unlock()
		c.Close()
		return
	}

	// Check number of idle conns.
	maxIdle := p.MaxIdleConns
	if maxIdle < 1 {
		maxIdle = 10
	}
	if len(p.idleConns) >= maxIdle {
		p.decrActiveLocked(1)
		p.mu.Unlock()
		c.Close()
		return
	}

	// Add to idle conns and optionally start the idle conn worker.
	p.idleConns = append(p.idleConns, &idleConn{conn: c, idleSince: time.Now()})
	p.startMaxIdleWorker()
	p.decrActiveLocked(0)
	p.mu.Unlock()
}

func (p *Pool) decrActiveLocked(n int) {
	p.numActive -= n
	if p.cond != nil && p.numWaiting > 0 {
		p.cond.Signal()
	}
}

func (p *Pool) ExecArray(cmd string, args []interface{}, fn func(*ArrayRes) error) error {
	return p.Conn(func(c Conn) error {
		return p.execArray(c, cmd, args, fn)
	})
}

func (p *Pool) execArray(c Conn, cmd string, args []interface{}, fn func(*ArrayRes) error) error {
	c.Cmd(cmd, args...)
	err := c.Send()
	if err != nil {
		return err
	}
	ar, err := c.ReadArray()
	if err != nil {
		return err
	}
	defer ar.Close()
	return fn(ar)
}

func (p *Pool) ExecStringArr(cmd string, args ...interface{}) ([]string, error) {
	var ss []string
	err := p.Conn(func(c Conn) error {
		var err error
		ss, err = p.execStringArr(c, cmd, args...)
		return err
	})
	return ss, err
}

func (p *Pool) execStringArr(c Conn, cmd string, args ...interface{}) ([]string, error) {
	c.Cmd(cmd, args...)
	err := c.Send()
	if err != nil {
		return nil, err
	}
	return c.ReadStringArr()
}

func (p *Pool) ExecString(cmd string, args ...interface{}) (string, error) {
	var s string
	err := p.Conn(func(c Conn) error {
		var err error
		s, err = p.execString(c, cmd, args...)
		return err
	})
	return s, err
}

func (p *Pool) execString(c Conn, cmd string, args ...interface{}) (string, error) {
	c.Cmd(cmd, args...)
	err := c.Send()
	if err != nil {
		return "", err
	}
	return c.ReadString()
}

func (p *Pool) ExecBytes(cmd string, args ...interface{}) ([]byte, error) {
	var b []byte
	err := p.Conn(func(c Conn) error {
		var err error
		b, err = p.execBytes(c, cmd, args...)
		return err
	})
	return b, err
}

func (p *Pool) execBytes(c Conn, cmd string, args ...interface{}) ([]byte, error) {
	c.Cmd(cmd, args...)
	err := c.Send()
	if err != nil {
		return nil, err
	}
	return c.ReadBytes()
}

func (p *Pool) ExecNullString(cmd string, args ...interface{}) (NullString, error) {
	var ns NullString
	err := p.Conn(func(c Conn) error {
		var err error
		ns, err = p.execNullString(c, cmd, args...)
		return err
	})
	return ns, err
}

func (p *Pool) execNullString(c Conn, cmd string, args ...interface{}) (NullString, error) {
	c.Cmd(cmd, args...)
	err := c.Send()
	if err != nil {
		return NullString{}, err
	}
	return c.ReadNullString()
}

func (p *Pool) ExecInteger(cmd string, args ...interface{}) (int64, error) {
	var i int64
	err := p.Conn(func(c Conn) error {
		var err error
		i, err = p.execInteger(c, cmd, args...)
		return err
	})
	return i, err
}

func (p *Pool) execInteger(c Conn, cmd string, args ...interface{}) (int64, error) {
	c.Cmd(cmd, args...)
	err := c.Send()
	if err != nil {
		return 0, err
	}
	return c.ReadInteger()
}

func (p *Pool) startMaxIdleWorker() {
	if p.MaxIdleDuration > 0 && p.chMaxIdleDur == nil && len(p.idleConns) > 0 {
		p.chMaxIdleDur = make(chan struct{}, 1)
		go p.maxIdleWorker()
	}
}

func (p *Pool) maxIdleWorker() {
	dur := maxDuration(p.MaxIdleDuration, time.Second)
	t := time.NewTimer(dur)
	for {
		select {
		case <-t.C:
		case <-p.chMaxIdleDur:
		}

		p.mu.Lock()

		if p.closed || len(p.idleConns) == 0 {
			p.chMaxIdleDur = nil
			p.mu.Unlock()
			t.Stop()
			return
		}

		var toClose []Conn
		expiry := time.Now().Add(-dur)
		for len(p.idleConns) > 0 {
			c := p.idleConns[0]
			if c.idleSince.After(expiry) {
				break
			}
			toClose = append(toClose, c.conn)
			copy(p.idleConns, p.idleConns[1:])
			p.idleConns[len(p.idleConns)-1] = nil
			p.idleConns = p.idleConns[:len(p.idleConns)-1]

		}
		p.numActive -= len(toClose)
		if p.cond != nil {
			for i := 0; i < len(toClose) && i < p.numWaiting; i++ {
				p.cond.Signal()
			}
		}
		p.mu.Unlock()

		for _, c := range toClose {
			c.Close()
		}

		t.Reset(dur)
	}
}

func maxDuration(a, b time.Duration) time.Duration {
	if a > b {
		return a
	}
	return b
}
<commit_msg>Add MaxWaiting field to Pool<commit_after>// MIT License
//
// Copyright (c) 2017 Ryan Fowler
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

package red

import (
	"errors"
	"sync"
	"time"
)

var (
	// ErrTooManyActive represents the error on a Pool when the
	// MaxActiveConns and MaxWaiting limits have been reached.
	ErrTooManyActive = errors.New("red: too many active connections")
	errPoolClosed    = errors.New("red: pool closed")
)

type idleConn struct {
	conn      Conn
	idleSince time.Time
}

// Pool represents a pool of zero or more Redis Conns. All methods on a Pool are
// save to use concurrently.
type Pool struct {
	// Addr represents the address of the Redis server to connect to; Required.
	Addr string
	// Dial is an optional function to create a Conn. The default dial
	// attempts to create a TCP connection to the Redis server with a 30 -
	// second connection timeout.
	Dial func(string) (Conn, error)
	// MaxActiveConns represents the maximum total active connections at a
	// given time. A value <= 0 is no active limit.
	MaxActiveConns int
	// MaxIdleConns represents the maximum number of idle connections at a
	// given time. The default value is 10.
	MaxIdleConns int
	// MaxIdleDuration represents the timeout for an idle connection. By
	// default, there is no idle timeout.
	MaxIdleDuration time.Duration
	// MaxWaiting represents the maximum number of goroutines waiting for a
	// Conn because they are blocked by MaxActiveConns. The default value is
	// no limit. With a value < 0, ErrTooManyActive will be returned whenever
	// MaxActiveConns is reached.
	MaxWaiting int
	// OnReuse is an optional function to intercept an idle Conn before use.
	// If OnReuse returns false, the Conn will be closed and another will be
	// retrieved/created.
	OnReuse func(Conn) bool

	mu           sync.Mutex
	cond         *sync.Cond
	numWaiting   int
	numActive    int
	closed       bool
	chMaxIdleDur chan struct{}
	idleConns    []*idleConn
}

// Status represents the status of a Pool.
type Status struct {
	// Closed is true if the Pool has been closed.
	Closed bool
	// NumActive is the total number of active connections.
	NumActive int
	// NumIdle is the number of idle connections.
	NumIdle int
	// NumWaiting is the total number of connections waiting for an idle
	// connection.
	NumWaiting int
}

// Status returns the current status of the Pool.
func (p *Pool) Status() Status {
	p.mu.Lock()
	s := Status{
		Closed:     p.closed,
		NumActive:  p.numActive,
		NumIdle:    len(p.idleConns),
		NumWaiting: p.numWaiting,
	}
	p.mu.Unlock()
	return s
}

// Close closes the Pool and any of its idle connections. After being closed, a
// pool cannot be used and any attempt to use it will return an error.
func (p *Pool) Close() error {
	p.mu.Lock()
	if p.closed {
		p.mu.Unlock()
		return nil
	}
	p.closed = true

	toClose := make([]Conn, len(p.idleConns))
	for i, c := range p.idleConns {
		toClose[i] = c.conn
		p.idleConns[i] = nil
	}
	p.idleConns = nil

	if p.chMaxIdleDur != nil {
		select {
		case p.chMaxIdleDur <- struct{}{}:
		default:
		}
	}
	p.numActive -= len(toClose)
	if p.cond != nil && p.numWaiting > 0 {
		p.cond.Broadcast()
	}
	p.mu.Unlock()

	for _, c := range toClose {
		c.Close()
	}

	return nil
}

// Conn allows for direct access to a Conn using the provided function. The
// Conn is only valid during the lifetime of the function. Conn will return any
// error returned by fn.
func (p *Pool) Conn(fn func(c Conn) error) error {
	c, err := p.getConn()
	if err != nil {
		return err
	}
	defer p.putConn(c)
	return fn(c)
}

func (p *Pool) getConn() (Conn, error) {
	p.mu.Lock()
	for {
		// Return if pool is closed.
		if p.closed {
			p.mu.Unlock()
			return nil, errPoolClosed
		}

		// Attempt to get an idle conn.
		if len(p.idleConns) > 0 {
			c := p.popIdle()
			p.mu.Unlock()
			if p.OnReuse != nil && !p.OnReuse(c) {
				c.Close()
				p.mu.Lock()
				p.decrActiveLocked(1)
				continue
			}
			return c, nil
		}

		// Check number of active conns.
		if p.MaxActiveConns <= 0 || p.numActive < p.MaxActiveConns {
			break
		}
		if p.cond == nil {
			p.cond = sync.NewCond(&p.mu)
		}

		// Check wait limits.
		if !p.waitOK() {
			p.mu.Unlock()
			return nil, ErrTooManyActive
		}

		p.numWaiting++
		p.cond.Wait()
		p.numWaiting--
	}
	p.numActive++
	p.mu.Unlock()

	// Create and return a new connection.
	c, err := p.dialConn()
	if err != nil {
		p.mu.Lock()
		p.decrActiveLocked(1)
		p.mu.Unlock()
		return nil, err
	}
	return c, nil
}

func (p *Pool) dialConn() (Conn, error) {
	if p.Dial == nil {
		return Dial(p.Addr, defaultDialTimeout)
	}
	return p.Dial(p.Addr)
}

func (p *Pool) popIdle() Conn {
	// TODO (ryanfowler): optimize?
	c := p.idleConns[0]
	copy(p.idleConns, p.idleConns[1:])
	p.idleConns[len(p.idleConns)-1] = nil
	p.idleConns = p.idleConns[:len(p.idleConns)-1]
	return c.conn
}

func (p *Pool) waitOK() bool {
	if p.MaxWaiting < 0 {
		return false
	}
	if p.MaxWaiting > 0 && p.numWaiting >= p.MaxWaiting {
		return false
	}
	return true
}

func (p *Pool) putConn(c Conn) {
	if c == nil {
		return
	}

	p.mu.Lock()

	// Return if the pool is closed or the connection has a fatal error.
	if p.closed || c.Err() != nil {
		p.decrActiveLocked(1)
		p.mu.Unlock()
		c.Close()
		return
	}

	// Check number of idle conns.
	maxIdle := p.MaxIdleConns
	if maxIdle < 1 {
		maxIdle = 10
	}
	if len(p.idleConns) >= maxIdle {
		p.decrActiveLocked(1)
		p.mu.Unlock()
		c.Close()
		return
	}

	// Add to idle conns and optionally start the idle conn worker.
	p.idleConns = append(p.idleConns, &idleConn{conn: c, idleSince: time.Now()})
	p.startMaxIdleWorker()
	p.decrActiveLocked(0)
	p.mu.Unlock()
}

func (p *Pool) decrActiveLocked(n int) {
	p.numActive -= n
	if p.cond != nil && p.numWaiting > 0 {
		p.cond.Signal()
	}
}

func (p *Pool) ExecArray(cmd string, args []interface{}, fn func(*ArrayRes) error) error {
	return p.Conn(func(c Conn) error {
		return p.execArray(c, cmd, args, fn)
	})
}

func (p *Pool) execArray(c Conn, cmd string, args []interface{}, fn func(*ArrayRes) error) error {
	c.Cmd(cmd, args...)
	err := c.Send()
	if err != nil {
		return err
	}
	ar, err := c.ReadArray()
	if err != nil {
		return err
	}
	defer ar.Close()
	return fn(ar)
}

func (p *Pool) ExecStringArr(cmd string, args ...interface{}) ([]string, error) {
	var ss []string
	err := p.Conn(func(c Conn) error {
		var err error
		ss, err = p.execStringArr(c, cmd, args...)
		return err
	})
	return ss, err
}

func (p *Pool) execStringArr(c Conn, cmd string, args ...interface{}) ([]string, error) {
	c.Cmd(cmd, args...)
	err := c.Send()
	if err != nil {
		return nil, err
	}
	return c.ReadStringArr()
}

func (p *Pool) ExecString(cmd string, args ...interface{}) (string, error) {
	var s string
	err := p.Conn(func(c Conn) error {
		var err error
		s, err = p.execString(c, cmd, args...)
		return err
	})
	return s, err
}

func (p *Pool) execString(c Conn, cmd string, args ...interface{}) (string, error) {
	c.Cmd(cmd, args...)
	err := c.Send()
	if err != nil {
		return "", err
	}
	return c.ReadString()
}

func (p *Pool) ExecBytes(cmd string, args ...interface{}) ([]byte, error) {
	var b []byte
	err := p.Conn(func(c Conn) error {
		var err error
		b, err = p.execBytes(c, cmd, args...)
		return err
	})
	return b, err
}

func (p *Pool) execBytes(c Conn, cmd string, args ...interface{}) ([]byte, error) {
	c.Cmd(cmd, args...)
	err := c.Send()
	if err != nil {
		return nil, err
	}
	return c.ReadBytes()
}

func (p *Pool) ExecNullString(cmd string, args ...interface{}) (NullString, error) {
	var ns NullString
	err := p.Conn(func(c Conn) error {
		var err error
		ns, err = p.execNullString(c, cmd, args...)
		return err
	})
	return ns, err
}

func (p *Pool) execNullString(c Conn, cmd string, args ...interface{}) (NullString, error) {
	c.Cmd(cmd, args...)
	err := c.Send()
	if err != nil {
		return NullString{}, err
	}
	return c.ReadNullString()
}

func (p *Pool) ExecInteger(cmd string, args ...interface{}) (int64, error) {
	var i int64
	err := p.Conn(func(c Conn) error {
		var err error
		i, err = p.execInteger(c, cmd, args...)
		return err
	})
	return i, err
}

func (p *Pool) execInteger(c Conn, cmd string, args ...interface{}) (int64, error) {
	c.Cmd(cmd, args...)
	err := c.Send()
	if err != nil {
		return 0, err
	}
	return c.ReadInteger()
}

func (p *Pool) startMaxIdleWorker() {
	if p.MaxIdleDuration > 0 && p.chMaxIdleDur == nil && len(p.idleConns) > 0 {
		p.chMaxIdleDur = make(chan struct{}, 1)
		go p.maxIdleWorker()
	}
}

func (p *Pool) maxIdleWorker() {
	dur := maxDuration(p.MaxIdleDuration, time.Second)
	t := time.NewTimer(dur)
	for {
		select {
		case <-t.C:
		case <-p.chMaxIdleDur:
		}

		p.mu.Lock()

		if p.closed || len(p.idleConns) == 0 {
			p.chMaxIdleDur = nil
			p.mu.Unlock()
			t.Stop()
			return
		}

		var toClose []Conn
		expiry := time.Now().Add(-dur)
		for len(p.idleConns) > 0 {
			c := p.idleConns[0]
			if c.idleSince.After(expiry) {
				break
			}
			toClose = append(toClose, c.conn)
			copy(p.idleConns, p.idleConns[1:])
			p.idleConns[len(p.idleConns)-1] = nil
			p.idleConns = p.idleConns[:len(p.idleConns)-1]

		}
		p.numActive -= len(toClose)
		if p.cond != nil {
			for i := 0; i < len(toClose) && i < p.numWaiting; i++ {
				p.cond.Signal()
			}
		}
		p.mu.Unlock()

		for _, c := range toClose {
			c.Close()
		}

		t.Reset(dur)
	}
}

func maxDuration(a, b time.Duration) time.Duration {
	if a > b {
		return a
	}
	return b
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/codegangsta/cli"
	"github.com/go-xiaohei/pugo-static/builder"
	"github.com/go-xiaohei/pugo-static/command"
	"github.com/go-xiaohei/pugo-static/server"
	"gopkg.in/inconshreveable/log15.v2"
	"gopkg.in/inconshreveable/log15.v2/ext"
)

//go:generate go-bindata -o=asset/asset.go -pkg=asset source/... template/...

const (
	VERSION  = "0.7.0"
	VER_DATE = "2015-11-14"

	SRC_DIR    = "source"   // source contents dir
	TPL_DIR    = "template" // template dir
	UPLOAD_DIR = "upload"   // upload dir
	DST_DIR    = "dest"     // destination dir
)

var (
	app = cli.NewApp()
)

func init() {
	app.Name = "pugo"
	app.Usage = "a beautiful site generator"
	app.Author = "https://github.com/fuxiaohei"
	app.Email = "fuxiaohei@vip.qq.com"
	app.Version = VERSION + "(" + VER_DATE + ")"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "addr",
			Value: "0.0.0.0:9899",
			Usage: "pugo's http server address",
		},
		cli.StringFlag{
			Name:  "theme",
			Value: "default",
			Usage: "pugo's theme to display",
		},
		cli.BoolFlag{
			Name:  "debug",
			Usage: "debug mode flag",
		},
		cli.BoolFlag{
			Name:  "build",
			Usage: "only build site, but don't serve http",
		},
	}
	log15.Root().SetHandler(log15.LvlFilterHandler(log15.LvlDebug, ext.FatalHandler(log15.StderrHandler)))
}

func action(ctx *cli.Context) {
	if !ctx.Bool("debug") {
		log15.Root().SetHandler(log15.LvlFilterHandler(log15.LvlInfo, ext.FatalHandler(log15.StderrHandler)))
	}

	log15.Debug("Dir.Source./" + SRC_DIR)
	log15.Debug("Dir.Template./" + TPL_DIR)
	log15.Debug("Dir.Destination./" + DST_DIR)

	// builder
	b := builder.New(SRC_DIR, TPL_DIR, ctx.String("theme"), ctx.Bool("debug"))
	if b.Error != nil {
		panic(b.Error)
	}
	b.Version.Num = VERSION
	b.Version.Date = VER_DATE

	b.Build(DST_DIR)
	if ctx.Bool("debug") {
		b.Watch(DST_DIR, TPL_DIR)
	} else {
		b.Watch(DST_DIR, "")
	}

	if ctx.Bool("build") {
		return
	}

	// server
	staticDir := b.Renders().Current().StaticDir()
	static := server.NewStatic()
	static.RootPath = staticDir

	upload := server.NewStatic()
	upload.RootPath = UPLOAD_DIR
	upload.Prefix = "/upload"
	upload.IndexFiles = []string{}

	s := server.NewServer(ctx.String("addr"))
	s.Static = []*server.Static{static, upload}
	s.Helper = server.NewHelper(b, DST_DIR)
	s.ErrorHandler = server.Errors(DST_DIR)
	s.Run()
}

func main() {
	app.Action = action
	app.Commands = []cli.Command{command.New(SRC_DIR, TPL_DIR)}
	app.RunAndExitOnError()
}
<commit_msg>update version -> 0.7.2<commit_after>package main

import (
	"github.com/codegangsta/cli"
	"github.com/go-xiaohei/pugo-static/builder"
	"github.com/go-xiaohei/pugo-static/command"
	"github.com/go-xiaohei/pugo-static/server"
	"gopkg.in/inconshreveable/log15.v2"
	"gopkg.in/inconshreveable/log15.v2/ext"
)

//go:generate go-bindata -o=asset/asset.go -pkg=asset source/... template/...

const (
	VERSION  = "0.7.2"
	VER_DATE = "2015-11-15"

	SRC_DIR    = "source"   // source contents dir
	TPL_DIR    = "template" // template dir
	UPLOAD_DIR = "upload"   // upload dir
	DST_DIR    = "dest"     // destination dir
)

var (
	app = cli.NewApp()
)

func init() {
	app.Name = "pugo"
	app.Usage = "a beautiful site generator"
	app.Author = "https://github.com/fuxiaohei"
	app.Email = "fuxiaohei@vip.qq.com"
	app.Version = VERSION + "(" + VER_DATE + ")"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "addr",
			Value: "0.0.0.0:9899",
			Usage: "pugo's http server address",
		},
		cli.StringFlag{
			Name:  "theme",
			Value: "default",
			Usage: "pugo's theme to display",
		},
		cli.BoolFlag{
			Name:  "debug",
			Usage: "debug mode flag",
		},
		cli.BoolFlag{
			Name:  "build",
			Usage: "only build site, but don't serve http",
		},
	}
	log15.Root().SetHandler(log15.LvlFilterHandler(log15.LvlDebug, ext.FatalHandler(log15.StderrHandler)))
}

func action(ctx *cli.Context) {
	if !ctx.Bool("debug") {
		log15.Root().SetHandler(log15.LvlFilterHandler(log15.LvlInfo, ext.FatalHandler(log15.StderrHandler)))
	}

	log15.Debug("Dir.Source./" + SRC_DIR)
	log15.Debug("Dir.Template./" + TPL_DIR)
	log15.Debug("Dir.Destination./" + DST_DIR)

	// builder
	b := builder.New(SRC_DIR, TPL_DIR, ctx.String("theme"), ctx.Bool("debug"))
	if b.Error != nil {
		panic(b.Error)
	}
	b.Version.Num = VERSION
	b.Version.Date = VER_DATE

	b.Build(DST_DIR)
	if ctx.Bool("debug") {
		b.Watch(DST_DIR, TPL_DIR)
	} else {
		b.Watch(DST_DIR, "")
	}

	if ctx.Bool("build") {
		return
	}

	// server
	staticDir := b.Renders().Current().StaticDir()
	static := server.NewStatic()
	static.RootPath = staticDir

	upload := server.NewStatic()
	upload.RootPath = UPLOAD_DIR
	upload.Prefix = "/upload"
	upload.IndexFiles = []string{}

	s := server.NewServer(ctx.String("addr"))
	s.Static = []*server.Static{static, upload}
	s.Helper = server.NewHelper(b, DST_DIR)
	s.ErrorHandler = server.Errors(DST_DIR)
	s.Run()
}

func main() {
	app.Action = action
	app.Commands = []cli.Command{command.New(SRC_DIR, TPL_DIR)}
	app.RunAndExitOnError()
}
<|endoftext|>


<commit_before>package pb

import (
	"fmt"
	"io"
	"math"
	"strings"
	"sync/atomic"
	"time"
)

const (
	// Default refresh rate - 200ms
	DEFAULT_REFRESH_RATE = time.Millisecond * 200
	FORMAT               = "[=>-]"
)

// DEPRECATED
// variables for backward compatibility, from now do not work
// use pb.Format and pb.SetRefreshRate
var (
	DefaultRefreshRate                         = DEFAULT_REFRESH_RATE
	BarStart, BarEnd, Empty, Current, CurrentN string
)

// Create new progress bar object
func New(total int) (pb *ProgressBar) {
	return New64(int64(total))
}

// Create new progress bar object uding int64 as total
func New64(total int64) (pb *ProgressBar) {
	pb = &ProgressBar{
		Total:         total,
		RefreshRate:   DEFAULT_REFRESH_RATE,
		ShowPercent:   true,
		ShowCounters:  true,
		ShowBar:       true,
		ShowTimeLeft:  true,
		ShowFinalTime: true,
	}
	pb.Format(FORMAT)
	return
}

// Create new object and start
func StartNew(total int) (pb *ProgressBar) {
	pb = New(total)
	pb.Start()
	return
}

// Callback for custom output
// For example:
// bar.Callback = func(s string) {
//     mySuperPrint(s)
// }
//
type Callback func(out string)

type ProgressBar struct {
	current int64 // current must be first member of struct (https://code.google.com/p/go/issues/detail?id=5278)

	Total                            int64
	RefreshRate                      time.Duration
	ShowPercent, ShowCounters        bool
	ShowSpeed, ShowTimeLeft, ShowBar bool
	ShowFinalTime                    bool
	Output                           io.Writer
	Callback                         Callback
	NotPrint                         bool
	Units                            int
	Width                            int
	ForceWidth                       bool

	isFinish  bool
	startTime time.Time

	prefix, postfix string

	BarStart string
	BarEnd   string
	Empty    string
	Current  string
	CurrentN string
}

// Start print
func (pb *ProgressBar) Start() {
	pb.startTime = time.Now()
	if pb.Total == 0 {
		pb.ShowBar = false
		pb.ShowTimeLeft = false
		pb.ShowPercent = false
	}
	go pb.writer()
}

// Increment current value
func (pb *ProgressBar) Increment() int {
	return pb.Add(1)
}

// Set current value
func (pb *ProgressBar) Set(current int) {
	atomic.StoreInt64(&pb.current, int64(current))
}

// Add to current value
func (pb *ProgressBar) Add(add int) int {
	return int(atomic.AddInt64(&pb.current, int64(add)))
}

// Set prefix string
func (pb *ProgressBar) Prefix(prefix string) (bar *ProgressBar) {
	pb.prefix = prefix
	return pb
}

// Set postfix string
func (pb *ProgressBar) Postfix(postfix string) (bar *ProgressBar) {
	pb.postfix = postfix
	return pb
}

// Set custom format for bar
// Example: bar.Format("[=>_]")
func (pb *ProgressBar) Format(format string) (bar *ProgressBar) {
	bar = pb
	formatEntries := strings.Split(format, "")
	if len(formatEntries) != 5 {
		return
	}
	pb.BarStart = formatEntries[0]
	pb.BarEnd = formatEntries[4]
	pb.Empty = formatEntries[3]
	pb.Current = formatEntries[1]
	pb.CurrentN = formatEntries[2]
	return
}

// Set bar refresh rate
func (pb *ProgressBar) SetRefreshRate(rate time.Duration) (bar *ProgressBar) {
	bar = pb
	pb.RefreshRate = rate
	return
}

// Set units
// bar.SetUnits(U_NO) - by default
// bar.SetUnits(U_BYTES) - for Mb, Kb, etc
func (pb *ProgressBar) SetUnits(units int) (bar *ProgressBar) {
	bar = pb
	switch units {
	case U_NO, U_BYTES:
		pb.Units = units
	}
	return
}

// Set max width, if width is bigger than terminal width, will be ignored
func (pb *ProgressBar) SetMaxWidth(width int) (bar *ProgressBar) {
	bar = pb
	pb.Width = width
	pb.ForceWidth = false
	return
}

// Set bar width
func (pb *ProgressBar) SetWidth(width int) (bar *ProgressBar) {
	bar = pb
	pb.Width = width
	pb.ForceWidth = true
	return
}

// End print
func (pb *ProgressBar) Finish() {
	pb.isFinish = true
	pb.write(atomic.LoadInt64(&pb.current))
	if !pb.NotPrint {
		fmt.Println()
	}
}

// End print and write string 'str'
func (pb *ProgressBar) FinishPrint(str string) {
	pb.Finish()
	fmt.Println(str)
}

// implement io.Writer
func (pb *ProgressBar) Write(p []byte) (n int, err error) {
	n = len(p)
	pb.Add(n)
	return
}

// implement io.Reader
func (pb *ProgressBar) Read(p []byte) (n int, err error) {
	n = len(p)
	pb.Add(n)
	return
}

// Create new proxy reader over bar
func (pb *ProgressBar) NewProxyReader(r io.Reader) *Reader {
	return &Reader{r, pb}
}

func (pb *ProgressBar) write(current int64) {
	width := pb.getWidth()

	var percentBox, countersBox, timeLeftBox, speedBox, barBox, end, out string

	// percents
	if pb.ShowPercent {
		percent := float64(current) / (float64(pb.Total) / float64(100))
		percentBox = fmt.Sprintf(" %#.02f %% ", percent)
	}

	// counters
	if pb.ShowCounters {
		if pb.Total > 0 {
			countersBox = fmt.Sprintf("%s / %s ", Format(current, pb.Units), Format(pb.Total, pb.Units))
		} else {
			countersBox = Format(current, pb.Units) + " "
		}
	}

	// time left
	fromStart := time.Now().Sub(pb.startTime)
	if pb.isFinish {
		if pb.ShowFinalTime {
			left := (fromStart / time.Second) * time.Second
			timeLeftBox = left.String()
		}
	} else if pb.ShowTimeLeft && current > 0 {
		perEntry := fromStart / time.Duration(current)
		left := time.Duration(pb.Total-current) * perEntry
		left = (left / time.Second) * time.Second
		timeLeftBox = left.String()
	}

	// speed
	if pb.ShowSpeed && current > 0 {
		fromStart := time.Now().Sub(pb.startTime)
		speed := float64(current) / (float64(fromStart) / float64(time.Second))
		speedBox = Format(int64(speed), pb.Units) + "/s "
	}

	// bar
	if pb.ShowBar {
		size := width - len(countersBox+pb.BarStart+pb.BarEnd+percentBox+timeLeftBox+speedBox+pb.prefix+pb.postfix)
		if size > 0 {
			curCount := int(math.Ceil((float64(current) / float64(pb.Total)) * float64(size)))
			emptCount := size - curCount
			barBox = pb.BarStart
			if emptCount < 0 {
				emptCount = 0
			}
			if curCount > size {
				curCount = size
			}
			if emptCount <= 0 {
				barBox += strings.Repeat(pb.Current, curCount)
			} else if curCount > 0 {
				barBox += strings.Repeat(pb.Current, curCount-1) + pb.CurrentN
			}

			barBox += strings.Repeat(pb.Empty, emptCount) + pb.BarEnd
		}
	}

	// check len
	out = pb.prefix + countersBox + barBox + percentBox + speedBox + timeLeftBox + pb.postfix
	if len(out) < width {
		end = strings.Repeat(" ", width-len(out))
	}

	// and print!
	switch {
	case pb.Output != nil:
		fmt.Fprint(pb.Output, "\r"+out+end)
	case pb.Callback != nil:
		pb.Callback(out + end)
	case !pb.NotPrint:
		fmt.Print("\r" + out + end)
	}
}

func (pb *ProgressBar) getWidth() int {
	if pb.ForceWidth {
		return pb.Width
	}

	width := pb.Width
	termWidth, _ := terminalWidth()
	if width == 0 || termWidth <= width {
		width = termWidth
	}

	return width
}

func (pb *ProgressBar) writer() {
	var c, oc int64
	oc = -1
	for {
		if pb.isFinish {
			break
		}
		c = atomic.LoadInt64(&pb.current)
		if c != oc {
			pb.write(c)
			oc = c
		}
		time.Sleep(pb.RefreshRate)
	}
}

type window struct {
	Row    uint16
	Col    uint16
	Xpixel uint16
	Ypixel uint16
}
<commit_msg>This commit adds an "Add64" method on the progress bar<commit_after>package pb

import (
	"fmt"
	"io"
	"math"
	"strings"
	"sync/atomic"
	"time"
)

const (
	// Default refresh rate - 200ms
	DEFAULT_REFRESH_RATE = time.Millisecond * 200
	FORMAT               = "[=>-]"
)

// DEPRECATED
// variables for backward compatibility, from now do not work
// use pb.Format and pb.SetRefreshRate
var (
	DefaultRefreshRate                         = DEFAULT_REFRESH_RATE
	BarStart, BarEnd, Empty, Current, CurrentN string
)

// Create new progress bar object
func New(total int) (pb *ProgressBar) {
	return New64(int64(total))
}

// Create new progress bar object uding int64 as total
func New64(total int64) (pb *ProgressBar) {
	pb = &ProgressBar{
		Total:         total,
		RefreshRate:   DEFAULT_REFRESH_RATE,
		ShowPercent:   true,
		ShowCounters:  true,
		ShowBar:       true,
		ShowTimeLeft:  true,
		ShowFinalTime: true,
	}
	pb.Format(FORMAT)
	return
}

// Create new object and start
func StartNew(total int) (pb *ProgressBar) {
	pb = New(total)
	pb.Start()
	return
}

// Callback for custom output
// For example:
// bar.Callback = func(s string) {
//     mySuperPrint(s)
// }
//
type Callback func(out string)

type ProgressBar struct {
	current int64 // current must be first member of struct (https://code.google.com/p/go/issues/detail?id=5278)

	Total                            int64
	RefreshRate                      time.Duration
	ShowPercent, ShowCounters        bool
	ShowSpeed, ShowTimeLeft, ShowBar bool
	ShowFinalTime                    bool
	Output                           io.Writer
	Callback                         Callback
	NotPrint                         bool
	Units                            int
	Width                            int
	ForceWidth                       bool

	isFinish  bool
	startTime time.Time

	prefix, postfix string

	BarStart string
	BarEnd   string
	Empty    string
	Current  string
	CurrentN string
}

// Start print
func (pb *ProgressBar) Start() {
	pb.startTime = time.Now()
	if pb.Total == 0 {
		pb.ShowBar = false
		pb.ShowTimeLeft = false
		pb.ShowPercent = false
	}
	go pb.writer()
}

// Increment current value
func (pb *ProgressBar) Increment() int {
	return pb.Add(1)
}

// Set current value
func (pb *ProgressBar) Set(current int) {
	atomic.StoreInt64(&pb.current, int64(current))
}

// Add to current value
func (pb *ProgressBar) Add(add int) int {
	return int(atomic.AddInt64(&pb.current, int64(add)))
}

func (pb *ProgressBar) Add64(add int64) int64 {
	return atomic.AddInt64(&pb.current, add)
}

// Set prefix string
func (pb *ProgressBar) Prefix(prefix string) (bar *ProgressBar) {
	pb.prefix = prefix
	return pb
}

// Set postfix string
func (pb *ProgressBar) Postfix(postfix string) (bar *ProgressBar) {
	pb.postfix = postfix
	return pb
}

// Set custom format for bar
// Example: bar.Format("[=>_]")
func (pb *ProgressBar) Format(format string) (bar *ProgressBar) {
	bar = pb
	formatEntries := strings.Split(format, "")
	if len(formatEntries) != 5 {
		return
	}
	pb.BarStart = formatEntries[0]
	pb.BarEnd = formatEntries[4]
	pb.Empty = formatEntries[3]
	pb.Current = formatEntries[1]
	pb.CurrentN = formatEntries[2]
	return
}

// Set bar refresh rate
func (pb *ProgressBar) SetRefreshRate(rate time.Duration) (bar *ProgressBar) {
	bar = pb
	pb.RefreshRate = rate
	return
}

// Set units
// bar.SetUnits(U_NO) - by default
// bar.SetUnits(U_BYTES) - for Mb, Kb, etc
func (pb *ProgressBar) SetUnits(units int) (bar *ProgressBar) {
	bar = pb
	switch units {
	case U_NO, U_BYTES:
		pb.Units = units
	}
	return
}

// Set max width, if width is bigger than terminal width, will be ignored
func (pb *ProgressBar) SetMaxWidth(width int) (bar *ProgressBar) {
	bar = pb
	pb.Width = width
	pb.ForceWidth = false
	return
}

// Set bar width
func (pb *ProgressBar) SetWidth(width int) (bar *ProgressBar) {
	bar = pb
	pb.Width = width
	pb.ForceWidth = true
	return
}

// End print
func (pb *ProgressBar) Finish() {
	pb.isFinish = true
	pb.write(atomic.LoadInt64(&pb.current))
	if !pb.NotPrint {
		fmt.Println()
	}
}

// End print and write string 'str'
func (pb *ProgressBar) FinishPrint(str string) {
	pb.Finish()
	fmt.Println(str)
}

// implement io.Writer
func (pb *ProgressBar) Write(p []byte) (n int, err error) {
	n = len(p)
	pb.Add(n)
	return
}

// implement io.Reader
func (pb *ProgressBar) Read(p []byte) (n int, err error) {
	n = len(p)
	pb.Add(n)
	return
}

// Create new proxy reader over bar
func (pb *ProgressBar) NewProxyReader(r io.Reader) *Reader {
	return &Reader{r, pb}
}

func (pb *ProgressBar) write(current int64) {
	width := pb.getWidth()

	var percentBox, countersBox, timeLeftBox, speedBox, barBox, end, out string

	// percents
	if pb.ShowPercent {
		percent := float64(current) / (float64(pb.Total) / float64(100))
		percentBox = fmt.Sprintf(" %#.02f %% ", percent)
	}

	// counters
	if pb.ShowCounters {
		if pb.Total > 0 {
			countersBox = fmt.Sprintf("%s / %s ", Format(current, pb.Units), Format(pb.Total, pb.Units))
		} else {
			countersBox = Format(current, pb.Units) + " "
		}
	}

	// time left
	fromStart := time.Now().Sub(pb.startTime)
	if pb.isFinish {
		if pb.ShowFinalTime {
			left := (fromStart / time.Second) * time.Second
			timeLeftBox = left.String()
		}
	} else if pb.ShowTimeLeft && current > 0 {
		perEntry := fromStart / time.Duration(current)
		left := time.Duration(pb.Total-current) * perEntry
		left = (left / time.Second) * time.Second
		timeLeftBox = left.String()
	}

	// speed
	if pb.ShowSpeed && current > 0 {
		fromStart := time.Now().Sub(pb.startTime)
		speed := float64(current) / (float64(fromStart) / float64(time.Second))
		speedBox = Format(int64(speed), pb.Units) + "/s "
	}

	// bar
	if pb.ShowBar {
		size := width - len(countersBox+pb.BarStart+pb.BarEnd+percentBox+timeLeftBox+speedBox+pb.prefix+pb.postfix)
		if size > 0 {
			curCount := int(math.Ceil((float64(current) / float64(pb.Total)) * float64(size)))
			emptCount := size - curCount
			barBox = pb.BarStart
			if emptCount < 0 {
				emptCount = 0
			}
			if curCount > size {
				curCount = size
			}
			if emptCount <= 0 {
				barBox += strings.Repeat(pb.Current, curCount)
			} else if curCount > 0 {
				barBox += strings.Repeat(pb.Current, curCount-1) + pb.CurrentN
			}

			barBox += strings.Repeat(pb.Empty, emptCount) + pb.BarEnd
		}
	}

	// check len
	out = pb.prefix + countersBox + barBox + percentBox + speedBox + timeLeftBox + pb.postfix
	if len(out) < width {
		end = strings.Repeat(" ", width-len(out))
	}

	// and print!
	switch {
	case pb.Output != nil:
		fmt.Fprint(pb.Output, "\r"+out+end)
	case pb.Callback != nil:
		pb.Callback(out + end)
	case !pb.NotPrint:
		fmt.Print("\r" + out + end)
	}
}

func (pb *ProgressBar) getWidth() int {
	if pb.ForceWidth {
		return pb.Width
	}

	width := pb.Width
	termWidth, _ := terminalWidth()
	if width == 0 || termWidth <= width {
		width = termWidth
	}

	return width
}

func (pb *ProgressBar) writer() {
	var c, oc int64
	oc = -1
	for {
		if pb.isFinish {
			break
		}
		c = atomic.LoadInt64(&pb.current)
		if c != oc {
			pb.write(c)
			oc = c
		}
		time.Sleep(pb.RefreshRate)
	}
}

type window struct {
	Row    uint16
	Col    uint16
	Xpixel uint16
	Ypixel uint16
}
<|endoftext|>