diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index e6096fcde..1c0334993 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -41,14 +41,6 @@ "ImportPath": "github.com/ipfs/go-datastore", "Rev": "e63957b6da369d986ef3e7a3f249779ba3f56c7e" }, - { - "ImportPath": "github.com/jbenet/go-context/frac", - "Rev": "d14ea06fba99483203c19d92cfcd13ebe73135f4" - }, - { - "ImportPath": "github.com/jbenet/go-context/io", - "Rev": "d14ea06fba99483203c19d92cfcd13ebe73135f4" - }, { "ImportPath": "github.com/jbenet/go-detect-race", "Rev": "3463798d9574bd0b7eca275dccc530804ff5216f" diff --git a/Godeps/_workspace/src/github.com/jbenet/go-context/frac/fracctx.go b/Godeps/_workspace/src/github.com/jbenet/go-context/frac/fracctx.go deleted file mode 100644 index c92daa9c9..000000000 --- a/Godeps/_workspace/src/github.com/jbenet/go-context/frac/fracctx.go +++ /dev/null @@ -1,62 +0,0 @@ -// Package ctxext provides multiple useful context constructors. -package ctxext - -import ( - "time" - - context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context" -) - -// WithDeadlineFraction returns a Context with a fraction of the -// original context's timeout. This is useful in sequential pipelines -// of work, where one might try options and fall back to others -// depending on the time available, or failure to respond. For example: -// -// // getPicture returns a picture from our encrypted database -// // we have a pipeline of multiple steps. we need to: -// // - get the data from a database -// // - decrypt it -// // - apply many transforms -// // -// // we **know** that each step takes increasingly more time. -// // The transforms are much more expensive than decryption, and -// // decryption is more expensive than the database lookup. -// // If our database takes too long (i.e. >0.2 of available time), -// // there's no use in continuing. -// func getPicture(ctx context.Context, key string) ([]byte, error) { -// // fractional timeout contexts to the rescue! -// -// // try the database with 0.2 of remaining time. -// ctx1, _ := ctxext.WithDeadlineFraction(ctx, 0.2) -// val, err := db.Get(ctx1, key) -// if err != nil { -// return nil, err -// } -// -// // try decryption with 0.3 of remaining time. -// ctx2, _ := ctxext.WithDeadlineFraction(ctx, 0.3) -// if val, err = decryptor.Decrypt(ctx2, val); err != nil { -// return nil, err -// } -// -// // try transforms with all remaining time. hopefully it's enough! -// return transformer.Transform(ctx, val) -// } -// -// -func WithDeadlineFraction(ctx context.Context, fraction float64) ( - context.Context, context.CancelFunc) { - - d, found := ctx.Deadline() - if !found { // no deadline - return context.WithCancel(ctx) - } - - left := d.Sub(time.Now()) - if left < 0 { // already passed... - return context.WithCancel(ctx) - } - - left = time.Duration(float64(left) * fraction) - return context.WithTimeout(ctx, left) -} diff --git a/Godeps/_workspace/src/github.com/jbenet/go-context/frac/fracctx_test.go b/Godeps/_workspace/src/github.com/jbenet/go-context/frac/fracctx_test.go deleted file mode 100644 index 975b7696d..000000000 --- a/Godeps/_workspace/src/github.com/jbenet/go-context/frac/fracctx_test.go +++ /dev/null @@ -1,145 +0,0 @@ -package ctxext - -import ( - "os" - "testing" - "time" - - context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context" -) - -// this test is on the context tool itself, not our stuff. it's for sanity on ours. -func TestDeadline(t *testing.T) { - if os.Getenv("TRAVIS") == "true" { - t.Skip("timeouts don't work reliably on travis") - } - - ctx, _ := context.WithTimeout(context.Background(), 5*time.Millisecond) - - select { - case <-ctx.Done(): - t.Fatal("ended too early") - default: - } - - <-time.After(6 * time.Millisecond) - - select { - case <-ctx.Done(): - default: - t.Fatal("ended too late") - } -} - -func TestDeadlineFractionForever(t *testing.T) { - - ctx, _ := WithDeadlineFraction(context.Background(), 0.5) - - _, found := ctx.Deadline() - if found { - t.Fatal("should last forever") - } -} - -func TestDeadlineFractionHalf(t *testing.T) { - if os.Getenv("TRAVIS") == "true" { - t.Skip("timeouts don't work reliably on travis") - } - - ctx1, _ := context.WithTimeout(context.Background(), 10*time.Millisecond) - ctx2, _ := WithDeadlineFraction(ctx1, 0.5) - - select { - case <-ctx1.Done(): - t.Fatal("ctx1 ended too early") - case <-ctx2.Done(): - t.Fatal("ctx2 ended too early") - default: - } - - <-time.After(2 * time.Millisecond) - - select { - case <-ctx1.Done(): - t.Fatal("ctx1 ended too early") - case <-ctx2.Done(): - t.Fatal("ctx2 ended too early") - default: - } - - <-time.After(4 * time.Millisecond) - - select { - case <-ctx1.Done(): - t.Fatal("ctx1 ended too early") - case <-ctx2.Done(): - default: - t.Fatal("ctx2 ended too late") - } - - <-time.After(6 * time.Millisecond) - - select { - case <-ctx1.Done(): - default: - t.Fatal("ctx1 ended too late") - } - -} - -func TestDeadlineFractionCancel(t *testing.T) { - - ctx1, cancel1 := context.WithTimeout(context.Background(), 10*time.Millisecond) - ctx2, cancel2 := WithDeadlineFraction(ctx1, 0.5) - - select { - case <-ctx1.Done(): - t.Fatal("ctx1 ended too early") - case <-ctx2.Done(): - t.Fatal("ctx2 ended too early") - default: - } - - cancel2() - - select { - case <-ctx1.Done(): - t.Fatal("ctx1 should NOT be cancelled") - case <-ctx2.Done(): - default: - t.Fatal("ctx2 should be cancelled") - } - - cancel1() - - select { - case <-ctx1.Done(): - case <-ctx2.Done(): - default: - t.Fatal("ctx1 should be cancelled") - } - -} - -func TestDeadlineFractionObeysParent(t *testing.T) { - - ctx1, cancel1 := context.WithTimeout(context.Background(), 10*time.Millisecond) - ctx2, _ := WithDeadlineFraction(ctx1, 0.5) - - select { - case <-ctx1.Done(): - t.Fatal("ctx1 ended too early") - case <-ctx2.Done(): - t.Fatal("ctx2 ended too early") - default: - } - - cancel1() - - select { - case <-ctx2.Done(): - default: - t.Fatal("ctx2 should be cancelled") - } - -} diff --git a/Godeps/_workspace/src/github.com/jbenet/go-context/io/ctxio.go b/Godeps/_workspace/src/github.com/jbenet/go-context/io/ctxio.go deleted file mode 100644 index 411eea892..000000000 --- a/Godeps/_workspace/src/github.com/jbenet/go-context/io/ctxio.go +++ /dev/null @@ -1,120 +0,0 @@ -// Package ctxio provides io.Reader and io.Writer wrappers that -// respect context.Contexts. Use these at the interface between -// your context code and your io. -// -// WARNING: read the code. see how writes and reads will continue -// until you cancel the io. Maybe this package should provide -// versions of io.ReadCloser and io.WriteCloser that automatically -// call .Close when the context expires. But for now -- since in my -// use cases I have long-lived connections with ephemeral io wrappers -// -- this has yet to be a need. -package ctxio - -import ( - "io" - - context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context" -) - -type ioret struct { - n int - err error -} - -type Writer interface { - io.Writer -} - -type ctxWriter struct { - w io.Writer - ctx context.Context -} - -// NewWriter wraps a writer to make it respect given Context. -// If there is a blocking write, the returned Writer will return -// whenever the context is cancelled (the return values are n=0 -// and err=ctx.Err().) -// -// Note well: this wrapper DOES NOT ACTUALLY cancel the underlying -// write-- there is no way to do that with the standard go io -// interface. So the read and write _will_ happen or hang. So, use -// this sparingly, make sure to cancel the read or write as necesary -// (e.g. closing a connection whose context is up, etc.) -// -// Furthermore, in order to protect your memory from being read -// _after_ you've cancelled the context, this io.Writer will -// first make a **copy** of the buffer. -func NewWriter(ctx context.Context, w io.Writer) *ctxWriter { - if ctx == nil { - ctx = context.Background() - } - return &ctxWriter{ctx: ctx, w: w} -} - -func (w *ctxWriter) Write(buf []byte) (int, error) { - buf2 := make([]byte, len(buf)) - copy(buf2, buf) - - c := make(chan ioret, 1) - - go func() { - n, err := w.w.Write(buf2) - c <- ioret{n, err} - close(c) - }() - - select { - case r := <-c: - return r.n, r.err - case <-w.ctx.Done(): - return 0, w.ctx.Err() - } -} - -type Reader interface { - io.Reader -} - -type ctxReader struct { - r io.Reader - ctx context.Context -} - -// NewReader wraps a reader to make it respect given Context. -// If there is a blocking read, the returned Reader will return -// whenever the context is cancelled (the return values are n=0 -// and err=ctx.Err().) -// -// Note well: this wrapper DOES NOT ACTUALLY cancel the underlying -// write-- there is no way to do that with the standard go io -// interface. So the read and write _will_ happen or hang. So, use -// this sparingly, make sure to cancel the read or write as necesary -// (e.g. closing a connection whose context is up, etc.) -// -// Furthermore, in order to protect your memory from being read -// _before_ you've cancelled the context, this io.Reader will -// allocate a buffer of the same size, and **copy** into the client's -// if the read succeeds in time. -func NewReader(ctx context.Context, r io.Reader) *ctxReader { - return &ctxReader{ctx: ctx, r: r} -} - -func (r *ctxReader) Read(buf []byte) (int, error) { - buf2 := make([]byte, len(buf)) - - c := make(chan ioret, 1) - - go func() { - n, err := r.r.Read(buf2) - c <- ioret{n, err} - close(c) - }() - - select { - case ret := <-c: - copy(buf, buf2) - return ret.n, ret.err - case <-r.ctx.Done(): - return 0, r.ctx.Err() - } -} diff --git a/Godeps/_workspace/src/github.com/jbenet/go-context/io/ctxio_test.go b/Godeps/_workspace/src/github.com/jbenet/go-context/io/ctxio_test.go deleted file mode 100644 index a9de8694c..000000000 --- a/Godeps/_workspace/src/github.com/jbenet/go-context/io/ctxio_test.go +++ /dev/null @@ -1,273 +0,0 @@ -package ctxio - -import ( - "bytes" - "io" - "testing" - "time" - - context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context" -) - -func TestReader(t *testing.T) { - buf := []byte("abcdef") - buf2 := make([]byte, 3) - r := NewReader(context.Background(), bytes.NewReader(buf)) - - // read first half - n, err := r.Read(buf2) - if n != 3 { - t.Error("n should be 3") - } - if err != nil { - t.Error("should have no error") - } - if string(buf2) != string(buf[:3]) { - t.Error("incorrect contents") - } - - // read second half - n, err = r.Read(buf2) - if n != 3 { - t.Error("n should be 3") - } - if err != nil { - t.Error("should have no error") - } - if string(buf2) != string(buf[3:6]) { - t.Error("incorrect contents") - } - - // read more. - n, err = r.Read(buf2) - if n != 0 { - t.Error("n should be 0", n) - } - if err != io.EOF { - t.Error("should be EOF", err) - } -} - -func TestWriter(t *testing.T) { - var buf bytes.Buffer - w := NewWriter(context.Background(), &buf) - - // write three - n, err := w.Write([]byte("abc")) - if n != 3 { - t.Error("n should be 3") - } - if err != nil { - t.Error("should have no error") - } - if string(buf.Bytes()) != string("abc") { - t.Error("incorrect contents") - } - - // write three more - n, err = w.Write([]byte("def")) - if n != 3 { - t.Error("n should be 3") - } - if err != nil { - t.Error("should have no error") - } - if string(buf.Bytes()) != string("abcdef") { - t.Error("incorrect contents") - } -} - -func TestReaderCancel(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - piper, pipew := io.Pipe() - r := NewReader(ctx, piper) - - buf := make([]byte, 10) - done := make(chan ioret) - - go func() { - n, err := r.Read(buf) - done <- ioret{n, err} - }() - - pipew.Write([]byte("abcdefghij")) - - select { - case ret := <-done: - if ret.n != 10 { - t.Error("ret.n should be 10", ret.n) - } - if ret.err != nil { - t.Error("ret.err should be nil", ret.err) - } - if string(buf) != "abcdefghij" { - t.Error("read contents differ") - } - case <-time.After(20 * time.Millisecond): - t.Fatal("failed to read") - } - - go func() { - n, err := r.Read(buf) - done <- ioret{n, err} - }() - - cancel() - - select { - case ret := <-done: - if ret.n != 0 { - t.Error("ret.n should be 0", ret.n) - } - if ret.err == nil { - t.Error("ret.err should be ctx error", ret.err) - } - case <-time.After(20 * time.Millisecond): - t.Fatal("failed to stop reading after cancel") - } -} - -func TestWriterCancel(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - piper, pipew := io.Pipe() - w := NewWriter(ctx, pipew) - - buf := make([]byte, 10) - done := make(chan ioret) - - go func() { - n, err := w.Write([]byte("abcdefghij")) - done <- ioret{n, err} - }() - - piper.Read(buf) - - select { - case ret := <-done: - if ret.n != 10 { - t.Error("ret.n should be 10", ret.n) - } - if ret.err != nil { - t.Error("ret.err should be nil", ret.err) - } - if string(buf) != "abcdefghij" { - t.Error("write contents differ") - } - case <-time.After(20 * time.Millisecond): - t.Fatal("failed to write") - } - - go func() { - n, err := w.Write([]byte("abcdefghij")) - done <- ioret{n, err} - }() - - cancel() - - select { - case ret := <-done: - if ret.n != 0 { - t.Error("ret.n should be 0", ret.n) - } - if ret.err == nil { - t.Error("ret.err should be ctx error", ret.err) - } - case <-time.After(20 * time.Millisecond): - t.Fatal("failed to stop writing after cancel") - } -} - -func TestReadPostCancel(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - piper, pipew := io.Pipe() - r := NewReader(ctx, piper) - - buf := make([]byte, 10) - done := make(chan ioret) - - go func() { - n, err := r.Read(buf) - done <- ioret{n, err} - }() - - cancel() - - select { - case ret := <-done: - if ret.n != 0 { - t.Error("ret.n should be 0", ret.n) - } - if ret.err == nil { - t.Error("ret.err should be ctx error", ret.err) - } - case <-time.After(20 * time.Millisecond): - t.Fatal("failed to stop reading after cancel") - } - - pipew.Write([]byte("abcdefghij")) - - if !bytes.Equal(buf, make([]byte, len(buf))) { - t.Fatal("buffer should have not been written to") - } -} - -func TestWritePostCancel(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - piper, pipew := io.Pipe() - w := NewWriter(ctx, pipew) - - buf := []byte("abcdefghij") - buf2 := make([]byte, 10) - done := make(chan ioret) - - go func() { - n, err := w.Write(buf) - done <- ioret{n, err} - }() - - piper.Read(buf2) - - select { - case ret := <-done: - if ret.n != 10 { - t.Error("ret.n should be 10", ret.n) - } - if ret.err != nil { - t.Error("ret.err should be nil", ret.err) - } - if string(buf2) != "abcdefghij" { - t.Error("write contents differ") - } - case <-time.After(20 * time.Millisecond): - t.Fatal("failed to write") - } - - go func() { - n, err := w.Write(buf) - done <- ioret{n, err} - }() - - cancel() - - select { - case ret := <-done: - if ret.n != 0 { - t.Error("ret.n should be 0", ret.n) - } - if ret.err == nil { - t.Error("ret.err should be ctx error", ret.err) - } - case <-time.After(20 * time.Millisecond): - t.Fatal("failed to stop writing after cancel") - } - - copy(buf, []byte("aaaaaaaaaa")) - - piper.Read(buf2) - - if string(buf2) == "aaaaaaaaaa" { - t.Error("buffer was read from after ctx cancel") - } else if string(buf2) != "abcdefghij" { - t.Error("write contents differ from expected") - } -} diff --git a/diagnostics/diag.go b/diagnostics/diag.go index 74a31bb86..8b4a09994 100644 --- a/diagnostics/diag.go +++ b/diagnostics/diag.go @@ -11,11 +11,11 @@ import ( "sync" "time" - ctxio "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-context/io" pb "github.com/ipfs/go-ipfs/diagnostics/pb" host "gx/ipfs/QmRW2xiYTpDLWTHb822ZYbPBoh3dGLJwaXLGS9tnPyWZpq/go-libp2p/p2p/host" inet "gx/ipfs/QmRW2xiYTpDLWTHb822ZYbPBoh3dGLJwaXLGS9tnPyWZpq/go-libp2p/p2p/net" protocol "gx/ipfs/QmRW2xiYTpDLWTHb822ZYbPBoh3dGLJwaXLGS9tnPyWZpq/go-libp2p/p2p/protocol" + ctxio "gx/ipfs/QmX6DhWrpBB5NtadXmPSXYNdVvuLfJXoFNMvUMoVvP5UJa/go-context/io" ggio "gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/io" proto "gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/proto" context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context" diff --git a/package.json b/package.json index bf19f69f8..96b17c620 100644 --- a/package.json +++ b/package.json @@ -99,6 +99,12 @@ "hash": "QmeWjRodbcZFKe5tMN7poEx3izym6osrLSnTLf9UjJZBbs", "name": "pb", "version": "1.0.3" + }, + { + "author": "jbenet", + "hash": "QmX6DhWrpBB5NtadXmPSXYNdVvuLfJXoFNMvUMoVvP5UJa", + "name": "go-context", + "version": "0.0.0" } ], "gxVersion": "0.4.0", diff --git a/routing/dht/dht_net.go b/routing/dht/dht_net.go index ded60c18b..221c60dc1 100644 --- a/routing/dht/dht_net.go +++ b/routing/dht/dht_net.go @@ -4,9 +4,9 @@ import ( "errors" "time" - ctxio "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-context/io" pb "github.com/ipfs/go-ipfs/routing/dht/pb" inet "gx/ipfs/QmRW2xiYTpDLWTHb822ZYbPBoh3dGLJwaXLGS9tnPyWZpq/go-libp2p/p2p/net" + ctxio "gx/ipfs/QmX6DhWrpBB5NtadXmPSXYNdVvuLfJXoFNMvUMoVvP5UJa/go-context/io" ggio "gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/io" context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context" peer "gx/ipfs/QmbyvM8zRFDkbFdYyt1MnevUMJ62SiSGbfDFZ3Z8nkrzr4/go-libp2p-peer" diff --git a/routing/dht/records.go b/routing/dht/records.go index 23b01410b..9d2eab248 100644 --- a/routing/dht/records.go +++ b/routing/dht/records.go @@ -4,11 +4,11 @@ import ( "fmt" "time" - ctxfrac "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-context/frac" routing "github.com/ipfs/go-ipfs/routing" pb "github.com/ipfs/go-ipfs/routing/dht/pb" record "github.com/ipfs/go-ipfs/routing/record" ci "gx/ipfs/QmUEUu1CM8bxBJxc3ZLojAi8evhTr4byQogWstABet79oY/go-libp2p-crypto" + ctxfrac "gx/ipfs/QmX6DhWrpBB5NtadXmPSXYNdVvuLfJXoFNMvUMoVvP5UJa/go-context/frac" "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context" peer "gx/ipfs/QmbyvM8zRFDkbFdYyt1MnevUMJ62SiSGbfDFZ3Z8nkrzr4/go-libp2p-peer" )