Update all dependencies

This commit is contained in:
Jakob Borg 2015-07-22 12:09:36 +02:00
parent e205f8afbb
commit 319abebd70
19 changed files with 3717 additions and 3515 deletions

20
Godeps/Godeps.json generated
View File

@ -1,6 +1,6 @@
{ {
"ImportPath": "github.com/syncthing/syncthing", "ImportPath": "github.com/syncthing/syncthing",
"GoVersion": "go1.4", "GoVersion": "devel",
"Packages": [ "Packages": [
"./cmd/..." "./cmd/..."
], ],
@ -22,8 +22,8 @@
"Rev": "5f7208e86762911861c94f1849eddbfc0a60cbf0" "Rev": "5f7208e86762911861c94f1849eddbfc0a60cbf0"
}, },
{ {
"ImportPath": "github.com/google/go-snappy/snappy", "ImportPath": "github.com/golang/snappy",
"Rev": "eaa750b9bf4dcb7cb20454be850613b66cda3273" "Rev": "0c7f8a7704bfec561913f4df52c832f094ef56f0"
}, },
{ {
"ImportPath": "github.com/juju/ratelimit", "ImportPath": "github.com/juju/ratelimit",
@ -35,15 +35,15 @@
}, },
{ {
"ImportPath": "github.com/syncthing/protocol", "ImportPath": "github.com/syncthing/protocol",
"Rev": "fcbd12b42176237d48985c1bfafbc43b2107aa31" "Rev": "22e24fc3879b1665077389f96862e222b2cdd8d3"
}, },
{ {
"ImportPath": "github.com/syndtr/goleveldb/leveldb", "ImportPath": "github.com/syndtr/goleveldb/leveldb",
"Rev": "a06509502ca32565bdf74afc1e573050023f261c" "Rev": "183614d6b32571e867df4cf086f5480ceefbdfac"
}, },
{ {
"ImportPath": "github.com/thejerf/suture", "ImportPath": "github.com/thejerf/suture",
"Rev": "ff19fb384c3fe30f42717967eaa69da91e5f317c" "Rev": "fc7aaeabdc43fe41c5328efa1479ffea0b820978"
}, },
{ {
"ImportPath": "github.com/vitrun/qart/coding", "ImportPath": "github.com/vitrun/qart/coding",
@ -59,19 +59,19 @@
}, },
{ {
"ImportPath": "golang.org/x/crypto/bcrypt", "ImportPath": "golang.org/x/crypto/bcrypt",
"Rev": "1e856cbfdf9bc25eefca75f83f25d55e35ae72e0" "Rev": "7d5b0be716b9d6d4269afdaae10032bb296d3cdf"
}, },
{ {
"ImportPath": "golang.org/x/crypto/blowfish", "ImportPath": "golang.org/x/crypto/blowfish",
"Rev": "1e856cbfdf9bc25eefca75f83f25d55e35ae72e0" "Rev": "7d5b0be716b9d6d4269afdaae10032bb296d3cdf"
}, },
{ {
"ImportPath": "golang.org/x/text/transform", "ImportPath": "golang.org/x/text/transform",
"Rev": "df923bbb63f8ea3a26bb743e2a497abd0ab585f7" "Rev": "3eb7007b740b66a77f3c85f2660a0240b284115a"
}, },
{ {
"ImportPath": "golang.org/x/text/unicode/norm", "ImportPath": "golang.org/x/text/unicode/norm",
"Rev": "df923bbb63f8ea3a26bb743e2a497abd0ab585f7" "Rev": "3eb7007b740b66a77f3c85f2660a0240b284115a"
} }
] ]
} }

14
Godeps/_workspace/src/github.com/golang/snappy/AUTHORS generated vendored Normal file
View File

@ -0,0 +1,14 @@
# This is the official list of Snappy-Go authors for copyright purposes.
# This file is distinct from the CONTRIBUTORS files.
# See the latter for an explanation.
# Names should be added to this file as
# Name or Organization <email address>
# The email address is not required for organizations.
# Please keep the list sorted.
Damian Gryski <dgryski@gmail.com>
Google Inc.
Jan Mercl <0xjnml@gmail.com>
Sebastien Binet <seb.binet@gmail.com>

View File

@ -0,0 +1,36 @@
# This is the official list of people who can contribute
# (and typically have contributed) code to the Snappy-Go repository.
# The AUTHORS file lists the copyright holders; this file
# lists people. For example, Google employees are listed here
# but not in AUTHORS, because Google holds the copyright.
#
# The submission process automatically checks to make sure
# that people submitting code are listed in this file (by email address).
#
# Names should be added to this file only after verifying that
# the individual or the individual's organization has agreed to
# the appropriate Contributor License Agreement, found here:
#
# http://code.google.com/legal/individual-cla-v1.0.html
# http://code.google.com/legal/corporate-cla-v1.0.html
#
# The agreement for individuals can be filled out on the web.
#
# When adding J Random Contributor's name to this file,
# either J's name or J's organization's name should be
# added to the AUTHORS file, depending on whether the
# individual or corporate CLA was used.
# Names should be added to this file like so:
# Name <email address>
# Please keep the list sorted.
Damian Gryski <dgryski@gmail.com>
Jan Mercl <0xjnml@gmail.com>
Kai Backman <kaib@golang.org>
Marc-Antoine Ruel <maruel@chromium.org>
Nigel Tao <nigeltao@golang.org>
Rob Pike <r@golang.org>
Russ Cox <rsc@golang.org>
Sebastien Binet <seb.binet@gmail.com>

27
Godeps/_workspace/src/github.com/golang/snappy/LICENSE generated vendored Normal file
View File

@ -0,0 +1,27 @@
Copyright (c) 2011 The Snappy-Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,7 @@
The Snappy compression format in the Go programming language.
To download and install from source:
$ go get github.com/golang/snappy
Unless otherwise noted, the Snappy-Go source files are distributed
under the BSD-style license found in the LICENSE file.

View File

@ -27,7 +27,7 @@ func DecodedLen(src []byte) (int, error) {
// that the length header occupied. // that the length header occupied.
func decodedLen(src []byte) (blockLen, headerLen int, err error) { func decodedLen(src []byte) (blockLen, headerLen int, err error) {
v, n := binary.Uvarint(src) v, n := binary.Uvarint(src)
if n == 0 { if n <= 0 {
return 0, 0, ErrCorrupt return 0, 0, ErrCorrupt
} }
if uint64(int(v)) != v { if uint64(int(v)) != v {
@ -56,7 +56,7 @@ func Decode(dst, src []byte) ([]byte, error) {
x := uint(src[s] >> 2) x := uint(src[s] >> 2)
switch { switch {
case x < 60: case x < 60:
s += 1 s++
case x == 60: case x == 60:
s += 2 s += 2
if s > len(src) { if s > len(src) {
@ -130,7 +130,7 @@ func Decode(dst, src []byte) ([]byte, error) {
// NewReader returns a new Reader that decompresses from r, using the framing // NewReader returns a new Reader that decompresses from r, using the framing
// format described at // format described at
// https://code.google.com/p/snappy/source/browse/trunk/framing_format.txt // https://github.com/google/snappy/blob/master/framing_format.txt
func NewReader(r io.Reader) *Reader { func NewReader(r io.Reader) *Reader {
return &Reader{ return &Reader{
r: r, r: r,
@ -200,7 +200,7 @@ func (r *Reader) Read(p []byte) (int, error) {
} }
// The chunk types are specified at // The chunk types are specified at
// https://code.google.com/p/snappy/source/browse/trunk/framing_format.txt // https://github.com/google/snappy/blob/master/framing_format.txt
switch chunkType { switch chunkType {
case chunkTypeCompressedData: case chunkTypeCompressedData:
// Section 4.2. Compressed data (chunk type 0x00). // Section 4.2. Compressed data (chunk type 0x00).
@ -280,13 +280,11 @@ func (r *Reader) Read(p []byte) (int, error) {
// Section 4.5. Reserved unskippable chunks (chunk types 0x02-0x7f). // Section 4.5. Reserved unskippable chunks (chunk types 0x02-0x7f).
r.err = ErrUnsupported r.err = ErrUnsupported
return 0, r.err return 0, r.err
}
} else { // Section 4.4 Padding (chunk type 0xfe).
// Section 4.4 Padding (chunk type 0xfe). // Section 4.6. Reserved skippable chunks (chunk types 0x80-0xfd).
// Section 4.6. Reserved skippable chunks (chunk types 0x80-0xfd). if !r.readFull(r.buf[:chunkLen]) {
if !r.readFull(r.buf[:chunkLen]) { return 0, r.err
return 0, r.err
}
} }
} }
} }

View File

@ -79,7 +79,7 @@ func emitCopy(dst []byte, offset, length int) int {
// slice of dst if dst was large enough to hold the entire encoded block. // slice of dst if dst was large enough to hold the entire encoded block.
// Otherwise, a newly allocated slice will be returned. // Otherwise, a newly allocated slice will be returned.
// It is valid to pass a nil dst. // It is valid to pass a nil dst.
func Encode(dst, src []byte) ([]byte, error) { func Encode(dst, src []byte) []byte {
if n := MaxEncodedLen(len(src)); len(dst) < n { if n := MaxEncodedLen(len(src)); len(dst) < n {
dst = make([]byte, n) dst = make([]byte, n)
} }
@ -92,7 +92,7 @@ func Encode(dst, src []byte) ([]byte, error) {
if len(src) != 0 { if len(src) != 0 {
d += emitLiteral(dst[d:], src) d += emitLiteral(dst[d:], src)
} }
return dst[:d], nil return dst[:d]
} }
// Initialize the hash table. Its size ranges from 1<<8 to 1<<14 inclusive. // Initialize the hash table. Its size ranges from 1<<8 to 1<<14 inclusive.
@ -145,7 +145,7 @@ func Encode(dst, src []byte) ([]byte, error) {
if lit != len(src) { if lit != len(src) {
d += emitLiteral(dst[d:], src[lit:]) d += emitLiteral(dst[d:], src[lit:])
} }
return dst[:d], nil return dst[:d]
} }
// MaxEncodedLen returns the maximum length of a snappy block, given its // MaxEncodedLen returns the maximum length of a snappy block, given its
@ -176,7 +176,7 @@ func MaxEncodedLen(srcLen int) int {
// NewWriter returns a new Writer that compresses to w, using the framing // NewWriter returns a new Writer that compresses to w, using the framing
// format described at // format described at
// https://code.google.com/p/snappy/source/browse/trunk/framing_format.txt // https://github.com/google/snappy/blob/master/framing_format.txt
func NewWriter(w io.Writer) *Writer { func NewWriter(w io.Writer) *Writer {
return &Writer{ return &Writer{
w: w, w: w,
@ -226,11 +226,7 @@ func (w *Writer) Write(p []byte) (n int, errRet error) {
// Compress the buffer, discarding the result if the improvement // Compress the buffer, discarding the result if the improvement
// isn't at least 12.5%. // isn't at least 12.5%.
chunkType := uint8(chunkTypeCompressedData) chunkType := uint8(chunkTypeCompressedData)
chunkBody, err := Encode(w.enc, uncompressed) chunkBody := Encode(w.enc, uncompressed)
if err != nil {
w.err = err
return n, err
}
if len(chunkBody) >= len(uncompressed)-len(uncompressed)/8 { if len(chunkBody) >= len(uncompressed)-len(uncompressed)/8 {
chunkType, chunkBody = chunkTypeUncompressedData, uncompressed chunkType, chunkBody = chunkTypeUncompressedData, uncompressed
} }
@ -244,11 +240,11 @@ func (w *Writer) Write(p []byte) (n int, errRet error) {
w.buf[5] = uint8(checksum >> 8) w.buf[5] = uint8(checksum >> 8)
w.buf[6] = uint8(checksum >> 16) w.buf[6] = uint8(checksum >> 16)
w.buf[7] = uint8(checksum >> 24) w.buf[7] = uint8(checksum >> 24)
if _, err = w.w.Write(w.buf[:]); err != nil { if _, err := w.w.Write(w.buf[:]); err != nil {
w.err = err w.err = err
return n, err return n, err
} }
if _, err = w.w.Write(chunkBody); err != nil { if _, err := w.w.Write(chunkBody); err != nil {
w.err = err w.err = err
return n, err return n, err
} }

View File

@ -5,7 +5,7 @@
// Package snappy implements the snappy block-based compression format. // Package snappy implements the snappy block-based compression format.
// It aims for very high speeds and reasonable compression. // It aims for very high speeds and reasonable compression.
// //
// The C++ snappy implementation is at http://code.google.com/p/snappy/ // The C++ snappy implementation is at https://github.com/google/snappy
package snappy package snappy
import ( import (
@ -46,7 +46,7 @@ const (
chunkHeaderSize = 4 chunkHeaderSize = 4
magicChunk = "\xff\x06\x00\x00" + magicBody magicChunk = "\xff\x06\x00\x00" + magicBody
magicBody = "sNaPpY" magicBody = "sNaPpY"
// https://code.google.com/p/snappy/source/browse/trunk/framing_format.txt says // https://github.com/google/snappy/blob/master/framing_format.txt says
// that "the uncompressed data in a chunk must be no longer than 65536 bytes". // that "the uncompressed data in a chunk must be no longer than 65536 bytes".
maxUncompressedChunkLen = 65536 maxUncompressedChunkLen = 65536
) )
@ -61,7 +61,7 @@ const (
var crcTable = crc32.MakeTable(crc32.Castagnoli) var crcTable = crc32.MakeTable(crc32.Castagnoli)
// crc implements the checksum specified in section 3 of // crc implements the checksum specified in section 3 of
// https://code.google.com/p/snappy/source/browse/trunk/framing_format.txt // https://github.com/google/snappy/blob/master/framing_format.txt
func crc(b []byte) uint32 { func crc(b []byte) uint32 {
c := crc32.Update(0, crcTable, b) c := crc32.Update(0, crcTable, b)
return uint32(c>>15|c<<17) + 0xa282ead8 return uint32(c>>15|c<<17) + 0xa282ead8

View File

@ -24,11 +24,7 @@ var (
) )
func roundtrip(b, ebuf, dbuf []byte) error { func roundtrip(b, ebuf, dbuf []byte) error {
e, err := Encode(ebuf, b) d, err := Decode(dbuf, Encode(ebuf, b))
if err != nil {
return fmt.Errorf("encoding error: %v", err)
}
d, err := Decode(dbuf, e)
if err != nil { if err != nil {
return fmt.Errorf("decoding error: %v", err) return fmt.Errorf("decoding error: %v", err)
} }
@ -82,6 +78,16 @@ func TestSmallRegular(t *testing.T) {
} }
} }
func TestInvalidVarint(t *testing.T) {
data := []byte("\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00")
if _, err := DecodedLen(data); err != ErrCorrupt {
t.Errorf("DecodedLen: got %v, want ErrCorrupt", err)
}
if _, err := Decode(nil, data); err != ErrCorrupt {
t.Errorf("Decode: got %v, want ErrCorrupt", err)
}
}
func cmp(a, b []byte) error { func cmp(a, b []byte) error {
if len(a) != len(b) { if len(a) != len(b) {
return fmt.Errorf("got %d bytes, want %d", len(a), len(b)) return fmt.Errorf("got %d bytes, want %d", len(a), len(b))
@ -197,10 +203,7 @@ func TestWriterReset(t *testing.T) {
} }
func benchDecode(b *testing.B, src []byte) { func benchDecode(b *testing.B, src []byte) {
encoded, err := Encode(nil, src) encoded := Encode(nil, src)
if err != nil {
b.Fatal(err)
}
// Bandwidth is in amount of uncompressed data. // Bandwidth is in amount of uncompressed data.
b.SetBytes(int64(len(src))) b.SetBytes(int64(len(src)))
b.ResetTimer() b.ResetTimer()
@ -222,7 +225,7 @@ func benchEncode(b *testing.B, src []byte) {
func readFile(b testing.TB, filename string) []byte { func readFile(b testing.TB, filename string) []byte {
src, err := ioutil.ReadFile(filename) src, err := ioutil.ReadFile(filename)
if err != nil { if err != nil {
b.Fatalf("failed reading %s: %s", filename, err) b.Skipf("skipping benchmark: %v", err)
} }
if len(src) == 0 { if len(src) == 0 {
b.Fatalf("%s has zero length", filename) b.Fatalf("%s has zero length", filename)
@ -284,14 +287,14 @@ var testFiles = []struct {
// The test data files are present at this canonical URL. // The test data files are present at this canonical URL.
const baseURL = "https://raw.githubusercontent.com/google/snappy/master/testdata/" const baseURL = "https://raw.githubusercontent.com/google/snappy/master/testdata/"
func downloadTestdata(basename string) (errRet error) { func downloadTestdata(b *testing.B, basename string) (errRet error) {
filename := filepath.Join(*testdata, basename) filename := filepath.Join(*testdata, basename)
if stat, err := os.Stat(filename); err == nil && stat.Size() != 0 { if stat, err := os.Stat(filename); err == nil && stat.Size() != 0 {
return nil return nil
} }
if !*download { if !*download {
return fmt.Errorf("test data not found; skipping benchmark without the -download flag") b.Skipf("test data not found; skipping benchmark without the -download flag")
} }
// Download the official snappy C++ implementation reference test data // Download the official snappy C++ implementation reference test data
// files for benchmarking. // files for benchmarking.
@ -326,7 +329,7 @@ func downloadTestdata(basename string) (errRet error) {
} }
func benchFile(b *testing.B, n int, decode bool) { func benchFile(b *testing.B, n int, decode bool) {
if err := downloadTestdata(testFiles[n].filename); err != nil { if err := downloadTestdata(b, testFiles[n].filename); err != nil {
b.Fatalf("failed to download testdata: %s", err) b.Fatalf("failed to download testdata: %s", err)
} }
data := readFile(b, filepath.Join(*testdata, testFiles[n].filename)) data := readFile(b, filepath.Join(*testdata, testFiles[n].filename))

View File

@ -20,7 +20,7 @@ token in the bucket represents one byte.
```go ```go
func Writer(w io.Writer, bucket *Bucket) io.Writer func Writer(w io.Writer, bucket *Bucket) io.Writer
``` ```
Writer returns a reader that is rate limited by the given token bucket. Each Writer returns a writer that is rate limited by the given token bucket. Each
token in the bucket represents one byte. token in the bucket represents one byte.
#### type Bucket #### type Bucket

View File

@ -2,15 +2,16 @@
// Licensed under the LGPLv3 with static-linking exception. // Licensed under the LGPLv3 with static-linking exception.
// See LICENCE file for details. // See LICENCE file for details.
// The ratelimit package provides an efficient token bucket implementation. // The ratelimit package provides an efficient token bucket implementation
// that can be used to limit the rate of arbitrary things.
// See http://en.wikipedia.org/wiki/Token_bucket. // See http://en.wikipedia.org/wiki/Token_bucket.
package ratelimit package ratelimit
import ( import (
"math"
"strconv" "strconv"
"sync" "sync"
"time" "time"
"math"
) )
// Bucket represents a token bucket that fills at a predetermined rate. // Bucket represents a token bucket that fills at a predetermined rate.

View File

@ -14,7 +14,7 @@ import (
"strings" "strings"
"sync" "sync"
"github.com/google/go-snappy/snappy" "github.com/golang/snappy"
"github.com/syndtr/goleveldb/leveldb/cache" "github.com/syndtr/goleveldb/leveldb/cache"
"github.com/syndtr/goleveldb/leveldb/comparer" "github.com/syndtr/goleveldb/leveldb/comparer"

View File

@ -12,7 +12,7 @@ import (
"fmt" "fmt"
"io" "io"
"github.com/google/go-snappy/snappy" "github.com/golang/snappy"
"github.com/syndtr/goleveldb/leveldb/comparer" "github.com/syndtr/goleveldb/leveldb/comparer"
"github.com/syndtr/goleveldb/leveldb/filter" "github.com/syndtr/goleveldb/leveldb/filter"
@ -167,11 +167,7 @@ func (w *Writer) writeBlock(buf *util.Buffer, compression opt.Compression) (bh b
if n := snappy.MaxEncodedLen(buf.Len()) + blockTrailerLen; len(w.compressionScratch) < n { if n := snappy.MaxEncodedLen(buf.Len()) + blockTrailerLen; len(w.compressionScratch) < n {
w.compressionScratch = make([]byte, n) w.compressionScratch = make([]byte, n)
} }
var compressed []byte compressed := snappy.Encode(w.compressionScratch, buf.Bytes())
compressed, err = snappy.Encode(w.compressionScratch, buf.Bytes())
if err != nil {
return
}
n := len(compressed) n := len(compressed)
b = compressed[:n+blockTrailerLen] b = compressed[:n+blockTrailerLen]
b[n] = blockTypeSnappyCompression b[n] = blockTypeSnappyCompression

View File

@ -1,4 +1,4 @@
Copyright (c) 2014 Barracuda Networks, Inc. Copyright (c) 2014-2015 Barracuda Networks, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@ -36,6 +36,13 @@ to your Supervisor. Supervisors are also services, so you can create a
tree structure here, depending on the exact combination of restarts tree structure here, depending on the exact combination of restarts
you want to create. you want to create.
As a special case, when adding Supervisors to Supervisors, the "sub"
supervisor will have the "super" supervisor's Log function copied.
This allows you to set one log function on the "top" supervisor, and
have it propagate down to all the sub-supervisors. This also allows
libraries or modules to provide Supervisors without having to commit
their users to a particular logging method.
Finally, as what is probably the last line of your main() function, call Finally, as what is probably the last line of your main() function, call
.Serve() on your top level supervisor. This will start all the services .Serve() on your top level supervisor. This will start all the services
you've defined. you've defined.
@ -126,8 +133,10 @@ type Supervisor struct {
// If you ever come up with some need to get into these, submit a pull // If you ever come up with some need to get into these, submit a pull
// request to make them public and some smidge of justification, and // request to make them public and some smidge of justification, and
// I'll happily do it. // I'll happily do it.
logBadStop func(Service) // But since I've now changed the signature on these once, I'm glad I
logFailure func(service Service, currentFailures float64, failureThreshold float64, restarting bool, error interface{}, stacktrace []byte) // didn't start with them public... :)
logBadStop func(*Supervisor, Service)
logFailure func(supervisor *Supervisor, service Service, currentFailures float64, failureThreshold float64, restarting bool, error interface{}, stacktrace []byte)
logBackoff func(*Supervisor, bool) logBackoff func(*Supervisor, bool)
// avoid a dependency on github.com/thejerf/abtime by just implementing // avoid a dependency on github.com/thejerf/abtime by just implementing
@ -233,10 +242,10 @@ func New(name string, spec Spec) (s *Supervisor) {
s.resumeTimer = make(chan time.Time) s.resumeTimer = make(chan time.Time)
// set up the default logging handlers // set up the default logging handlers
s.logBadStop = func(service Service) { s.logBadStop = func(supervisor *Supervisor, service Service) {
s.log(fmt.Sprintf("Service %s failed to terminate in a timely manner", serviceName(service))) s.log(fmt.Sprintf("%s: Service %s failed to terminate in a timely manner", serviceName(supervisor), serviceName(service)))
} }
s.logFailure = func(service Service, failures float64, threshold float64, restarting bool, err interface{}, st []byte) { s.logFailure = func(supervisor *Supervisor, service Service, failures float64, threshold float64, restarting bool, err interface{}, st []byte) {
var errString string var errString string
e, canError := err.(error) e, canError := err.(error)
@ -246,7 +255,7 @@ func New(name string, spec Spec) (s *Supervisor) {
errString = fmt.Sprintf("%#v", err) errString = fmt.Sprintf("%#v", err)
} }
s.log(fmt.Sprintf("Failed service '%s' (%f failures of %f), restarting: %#v, error: %s, stacktrace: %s", serviceName(service), failures, threshold, restarting, errString, string(st))) s.log(fmt.Sprintf("%s: Failed service '%s' (%f failures of %f), restarting: %#v, error: %s, stacktrace: %s", serviceName(supervisor), serviceName(service), failures, threshold, restarting, errString, string(st)))
} }
s.logBackoff = func(s *Supervisor, entering bool) { s.logBackoff = func(s *Supervisor, entering bool) {
if entering { if entering {
@ -346,12 +355,24 @@ will be started when the supervisor is.
The returned ServiceID may be passed to the Remove method of the Supervisor The returned ServiceID may be passed to the Remove method of the Supervisor
to terminate the service. to terminate the service.
As a special behavior, if the service added is itself a supervisor, the
supervisor being added will copy the Log function from the Supervisor it
is being added to. This allows factoring out providing a Supervisor
from its logging.
*/ */
func (s *Supervisor) Add(service Service) ServiceToken { func (s *Supervisor) Add(service Service) ServiceToken {
if s == nil { if s == nil {
panic("can't add service to nil *suture.Supervisor") panic("can't add service to nil *suture.Supervisor")
} }
if supervisor, isSupervisor := service.(*Supervisor); isSupervisor {
supervisor.logBadStop = s.logBadStop
supervisor.logFailure = s.logFailure
supervisor.logBackoff = s.logBackoff
}
if s.state == notRunning { if s.state == notRunning {
id := s.serviceCounter id := s.serviceCounter
s.serviceCounter++ s.serviceCounter++
@ -492,12 +513,12 @@ func (s *Supervisor) handleFailedService(id serviceID, err interface{}, stacktra
if monitored { if monitored {
if s.state == normal { if s.state == normal {
s.runService(failedService, id) s.runService(failedService, id)
s.logFailure(failedService, s.failures, s.failureThreshold, true, err, stacktrace) s.logFailure(s, failedService, s.failures, s.failureThreshold, true, err, stacktrace)
} else { } else {
// FIXME: When restarting, check that the service still // FIXME: When restarting, check that the service still
// exists (it may have been stopped in the meantime) // exists (it may have been stopped in the meantime)
s.restartQueue = append(s.restartQueue, id) s.restartQueue = append(s.restartQueue, id)
s.logFailure(failedService, s.failures, s.failureThreshold, false, err, stacktrace) s.logFailure(s, failedService, s.failures, s.failureThreshold, false, err, stacktrace)
} }
} }
} }
@ -536,7 +557,7 @@ func (s *Supervisor) removeService(id serviceID) {
case <-successChan: case <-successChan:
// Life is good! // Life is good!
case <-failChan: case <-failChan:
s.logBadStop(service) s.logBadStop(s, service)
} }
}() }()
} }

View File

@ -77,7 +77,7 @@ func TestFailures(t *testing.T) {
// to avoid deadlocks during shutdown, we have to not try to send // to avoid deadlocks during shutdown, we have to not try to send
// things out on channels while we're shutting down (this undoes the // things out on channels while we're shutting down (this undoes the
// logFailure overide about 25 lines down) // logFailure overide about 25 lines down)
s.logFailure = func(Service, float64, float64, bool, interface{}, []byte) {} s.logFailure = func(*Supervisor, Service, float64, float64, bool, interface{}, []byte) {}
s.Stop() s.Stop()
}() }()
s.sync() s.sync()
@ -102,7 +102,7 @@ func TestFailures(t *testing.T) {
failNotify := make(chan bool) failNotify := make(chan bool)
// use this to synchronize on here // use this to synchronize on here
s.logFailure = func(s Service, cf float64, ft float64, r bool, error interface{}, stacktrace []byte) { s.logFailure = func(supervisor *Supervisor, s Service, cf float64, ft float64, r bool, error interface{}, stacktrace []byte) {
failNotify <- r failNotify <- r
} }
@ -276,8 +276,8 @@ func TestDefaultLogging(t *testing.T) {
serviceName(&BarelyService{}) serviceName(&BarelyService{})
s.logBadStop(service) s.logBadStop(s, service)
s.logFailure(service, 1, 1, true, errors.New("test error"), []byte{}) s.logFailure(s, service, 1, 1, true, errors.New("test error"), []byte{})
s.Stop() s.Stop()
} }
@ -289,9 +289,17 @@ func TestNestedSupervisors(t *testing.T) {
super2 := NewSimple("Nested5") super2 := NewSimple("Nested5")
service := NewService("Service5") service := NewService("Service5")
super2.logBadStop = func(*Supervisor, Service) {
panic("Failed to copy logBadStop")
}
super1.Add(super2) super1.Add(super2)
super2.Add(service) super2.Add(service)
// test the functions got copied from super1; if this panics, it didn't
// get copied
super2.logBadStop(super2, service)
go super1.Serve() go super1.Serve()
super1.sync() super1.sync()
@ -340,7 +348,7 @@ func TestStoppingStillWorksWithHungServices(t *testing.T) {
return resumeChan return resumeChan
} }
failNotify := make(chan struct{}) failNotify := make(chan struct{})
s.logBadStop = func(s Service) { s.logBadStop = func(supervisor *Supervisor, s Service) {
failNotify <- struct{}{} failNotify <- struct{}{}
} }
@ -438,7 +446,7 @@ func TestFailingSupervisors(t *testing.T) {
} }
failNotify := make(chan string) failNotify := make(chan string)
// use this to synchronize on here // use this to synchronize on here
s1.logFailure = func(s Service, cf float64, ft float64, r bool, error interface{}, stacktrace []byte) { s1.logFailure = func(supervisor *Supervisor, s Service, cf float64, ft float64, r bool, error interface{}, stacktrace []byte) {
failNotify <- fmt.Sprintf("%s", s) failNotify <- fmt.Sprintf("%s", s)
} }

View File

@ -471,29 +471,22 @@ func computeNonStarterCounts() {
if exp := c.forms[FCompatibility].expandedDecomp; len(exp) > 0 { if exp := c.forms[FCompatibility].expandedDecomp; len(exp) > 0 {
runes = exp runes = exp
} }
// We consider runes that combine backwards to be non-starters for the
// purpose of Stream-Safe Text Processing.
for _, r := range runes { for _, r := range runes {
if chars[r].ccc == 0 { if cr := &chars[r]; cr.ccc == 0 && !cr.forms[FCompatibility].combinesBackward {
break break
} }
c.nLeadingNonStarters++ c.nLeadingNonStarters++
} }
for i := len(runes) - 1; i >= 0; i-- { for i := len(runes) - 1; i >= 0; i-- {
if chars[runes[i]].ccc == 0 { if cr := &chars[runes[i]]; cr.ccc == 0 && !cr.forms[FCompatibility].combinesBackward {
break break
} }
c.nTrailingNonStarters++ c.nTrailingNonStarters++
} }
if c.nTrailingNonStarters > 3 {
// We consider runes that combine backwards to be non-starters for the log.Fatalf("%U: Decomposition with more than 3 (%d) trailing modifiers (%U)", i, c.nTrailingNonStarters, runes)
// purpose of Stream-Safe Text Processing.
for _, f := range c.forms {
if c.ccc == 0 && f.combinesBackward {
if len(c.forms[FCompatibility].expandedDecomp) > 0 {
log.Fatalf("%U: CCC==0 modifier with an expansion is not supported.", i)
}
c.nTrailingNonStarters = 1
c.nLeadingNonStarters = 1
}
} }
if isHangul(rune(i)) { if isHangul(rune(i)) {
@ -839,10 +832,16 @@ func verifyComputed() {
continue continue
} }
if a, b := c.nLeadingNonStarters > 0, (c.ccc > 0 || f.combinesBackward); a != b { if a, b := c.nLeadingNonStarters > 0, (c.ccc > 0 || f.combinesBackward); a != b {
// We accept these two runes to be treated differently (it only affects // We accept these runes to be treated differently (it only affects
// segment breaking in iteration, most likely on inproper use), but // segment breaking in iteration, most likely on improper use), but
// reconsider if more characters are added. // reconsider if more characters are added.
if i != 0xFF9E && i != 0xFF9F { // U+FF9E HALFWIDTH KATAKANA VOICED SOUND MARK;Lm;0;L;<narrow> 3099;;;;N;;;;;
// U+FF9F HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK;Lm;0;L;<narrow> 309A;;;;N;;;;;
// U+3133 HANGUL LETTER KIYEOK-SIOS;Lo;0;L;<compat> 11AA;;;;N;HANGUL LETTER GIYEOG SIOS;;;;
// U+318E HANGUL LETTER ARAEAE;Lo;0;L;<compat> 11A1;;;;N;HANGUL LETTER ALAE AE;;;;
// U+FFA3 HALFWIDTH HANGUL LETTER KIYEOK-SIOS;Lo;0;L;<narrow> 3133;;;;N;HALFWIDTH HANGUL LETTER GIYEOG SIOS;;;;
// U+FFDC HALFWIDTH HANGUL LETTER I;Lo;0;L;<narrow> 3163;;;;N;;;;;
if i != 0xFF9E && i != 0xFF9F && !(0x3133 <= i && i <= 0x318E) && !(0xFFA3 <= i && i <= 0xFFDC) {
log.Fatalf("%U: nLead was %v; want %v", i, a, b) log.Fatalf("%U: nLead was %v; want %v", i, a, b)
} }
} }

View File

@ -113,7 +113,25 @@ var decomposeSegmentTests = []PositionTest{
{"\u00C0b", 2, "A\u0300"}, {"\u00C0b", 2, "A\u0300"},
// long // long
{grave(31), 60, grave(30) + cgj}, {grave(31), 60, grave(30) + cgj},
{"a" + grave(31), 61, "a" + grave(30) + cgj},
// Stability tests: see http://www.unicode.org/review/pr-29.html.
// U+0300 COMBINING GRAVE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING GRAVE;;;;
// U+0B47 ORIYA VOWEL SIGN E;Mc;0;L;;;;;N;;;;;
// U+0B3E ORIYA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
// U+1100 HANGUL CHOSEONG KIYEOK;Lo;0;L;;;;;N;;;;;
// U+1161 HANGUL JUNGSEONG A;Lo;0;L;;;;;N;;;;;
{"\u0B47\u0300\u0B3E", 8, "\u0B47\u0300\u0B3E"},
{"\u1100\u0300\u1161", 8, "\u1100\u0300\u1161"},
{"\u0B47\u0B3E", 6, "\u0B47\u0B3E"},
{"\u1100\u1161", 6, "\u1100\u1161"},
// U+04DA MALAYALAM VOWEL SIGN O;Mc;0;L;0D46 0D3E;;;;N;;;;;
// Sequence of decomposing characters that are starters and modifiers.
{"\u0d4a" + strings.Repeat("\u0d3e", 31), 90, "\u0d46" + strings.Repeat("\u0d3e", 30) + cgj},
{grave(30), 60, grave(30)}, {grave(30), 60, grave(30)},
// U+FF9E is a starter, but decomposes to U+3099, which is not.
{grave(30) + "\uff9e", 60, grave(30) + cgj}, {grave(30) + "\uff9e", 60, grave(30) + cgj},
// ends with incomplete UTF-8 encoding // ends with incomplete UTF-8 encoding
{"\xCC", 0, ""}, {"\xCC", 0, ""},
@ -552,6 +570,44 @@ var appendTestsNFC = []AppendTest{
"a" + rep(0x0305, maxNonStarters+4) + "\u0316", "a" + rep(0x0305, maxNonStarters+4) + "\u0316",
"a" + rep(0x0305, maxNonStarters) + cgj + "\u0316" + rep(0x305, 4), "a" + rep(0x0305, maxNonStarters) + cgj + "\u0316" + rep(0x305, 4),
}, },
{ // Combine across non-blocking non-starters.
// U+0327 COMBINING CEDILLA;Mn;202;NSM;;;;;N;NON-SPACING CEDILLA;;;;
// U+0325 COMBINING RING BELOW;Mn;220;NSM;;;;;N;NON-SPACING RING BELOW;;;;
"", "a\u0327\u0325", "\u1e01\u0327",
},
{ // Jamo V+T does not combine.
"",
"\u1161\u11a8",
"\u1161\u11a8",
},
// Stability tests: see http://www.unicode.org/review/pr-29.html.
{"", "\u0b47\u0300\u0b3e", "\u0b47\u0300\u0b3e"},
{"", "\u1100\u0300\u1161", "\u1100\u0300\u1161"},
{"", "\u0b47\u0b3e", "\u0b4b"},
{"", "\u1100\u1161", "\uac00"},
// U+04DA MALAYALAM VOWEL SIGN O;Mc;0;L;0D46 0D3E;;;;N;;;;;
{ // 0d4a starts a new segment.
"",
"\u0d4a" + strings.Repeat("\u0d3e", 15) + "\u0d4a" + strings.Repeat("\u0d3e", 15),
"\u0d4a" + strings.Repeat("\u0d3e", 15) + "\u0d4a" + strings.Repeat("\u0d3e", 15),
},
{ // Split combining characters.
// TODO: don't insert CGJ before starters.
"",
"\u0d46" + strings.Repeat("\u0d3e", 31),
"\u0d4a" + strings.Repeat("\u0d3e", 29) + cgj + "\u0d3e",
},
{ // Split combining characters.
"",
"\u0d4a" + strings.Repeat("\u0d3e", 30),
"\u0d4a" + strings.Repeat("\u0d3e", 29) + cgj + "\u0d3e",
},
} }
var appendTestsNFD = []AppendTest{ var appendTestsNFD = []AppendTest{

File diff suppressed because it is too large Load Diff