func openSyncConn(target string, authCode string) (net.Conn, chan int64) { c := openNetConn(target) // send auth to master if len(authCode) > 0 { cmd := fmt.Sprintf("*2\r\n$4\r\nauth\r\n$%d\r\n%s\r\n", len(authCode), authCode) if _, err := ioutils.WriteFull(c, []byte(cmd)); err != nil { log.PanicError(err, "write auth command failed") } resp := make([]byte, 5) if _, err := io.ReadFull(c, resp); err != nil { log.PanicError(err, "read auth response failed") } if string(resp) != "+OK\r\n" { log.Panic("auth failed") } } if _, err := ioutils.WriteFull(c, []byte("*1\r\n$4\r\nsync\r\n")); err != nil { log.PanicError(err, "write sync command failed") } size := make(chan int64) go func() { var rsp string for { b := []byte{0} if _, err := c.Read(b); err != nil { log.PanicErrorf(err, "read sync response = '%s'", rsp) } if len(rsp) == 0 && b[0] == '\n' { size <- 0 continue } rsp += string(b) if strings.HasSuffix(rsp, "\r\n") { break } } if rsp[0] != '$' { log.Panicf("invalid sync response, rsp = '%s'", rsp) } n, err := strconv.Atoi(rsp[1 : len(rsp)-2]) if err != nil || n <= 0 { log.PanicErrorf(err, "invalid sync response = '%s', n = %d", rsp, n) } size <- int64(n) }() return c, size }
func (w *BufWriter) WriteFloat64(f float64) error { p := make([]byte, 8) bits := float64ToUint64(f) binary.BigEndian.PutUint64(p, bits) _, err := ioutils.WriteFull(w.w, p) return errors.Trace(err) }
func (s *testIoPipeSuite) testPipe2(c *C, fileName string) { r, w := s.openPipe(c, fileName) cc := 1024 * 128 ss := "Hello world!!" go func() { for i := 0; i < cc; i++ { m := fmt.Sprintf("[%d]%s ", i, ss) _, err := ioutils.WriteFull(w, []byte(m)) c.Assert(err, IsNil) } c.Assert(w.Close(), IsNil) }() time.Sleep(time.Millisecond * 100) buf := make([]byte, len(ss)*cc*2) n, err := ioutils.ReadFull(r, buf) c.Assert(errors2.ErrorEqual(err, io.EOF), Equals, true) buf = buf[:n] for i := 0; i < cc; i++ { m := fmt.Sprintf("[%d]%s ", i, ss) c.Assert(len(buf) >= len(m), Equals, true) c.Assert(string(buf[:len(m)]), Equals, m) buf = buf[len(m):] } c.Assert(len(buf), Equals, 0) c.Assert(r.Close(), IsNil) }
func testPipe2(t *testing.T, fileName string) { r, w := openPipe(t, fileName) c := 1024 * 128 s := "Hello world!!" go func() { for i := 0; i < c; i++ { m := fmt.Sprintf("[%d]%s ", i, s) _, err := ioutils.WriteFull(w, []byte(m)) assert.ErrorIsNil(t, err) } assert.ErrorIsNil(t, w.Close()) }() time.Sleep(time.Millisecond * 100) buf := make([]byte, len(s)*c*2) n, err := ioutils.ReadFull(r, buf) assert.Must(t, errors.Equal(err, io.EOF)) buf = buf[:n] for i := 0; i < c; i++ { m := fmt.Sprintf("[%d]%s ", i, s) assert.Must(t, len(buf) >= len(m)) assert.Must(t, string(buf[:len(m)]) == m) buf = buf[len(m):] } assert.Must(t, len(buf) == 0) assert.ErrorIsNil(t, r.Close()) }
func (s *testIoPipeSuite) TestWriteAfterWriterClose(c *C) { r, w := Pipe() ss := "hello" errs := make(chan error) go func() { _, err := ioutils.WriteFull(w, []byte(ss)) c.Assert(err, IsNil) c.Assert(w.Close(), IsNil) _, err = w.Write([]byte("world")) errs <- err }() buf := make([]byte, 4096) n, err := ioutils.ReadFull(r, buf) c.Assert(errors2.ErrorEqual(err, io.EOF), Equals, true) c.Assert(string(buf[:n]), Equals, ss) err = <-errs c.Assert(errors2.ErrorEqual(err, io.ErrClosedPipe), Equals, true) c.Assert(r.Close(), IsNil) }
func (w *BufWriter) WriteVarbytes(p []byte) error { if n := uint64(len(p)); n > maxVarbytesLen { return errors.Trace(ErrVarbytesLen) } else if err := w.WriteUvarint(n); err != nil { return errors.Trace(err) } _, err := ioutils.WriteFull(w.w, p) return errors.Trace(err) }
func (s *testIoPipeSuite) testPipe3(c *C, fileName string) { r, w := s.openPipe(c, fileName) ch := make(chan int) size := 4096 go func() { buf := make([]byte, size) for { n, err := r.Read(buf) if errors2.ErrorEqual(err, io.EOF) { break } c.Assert(err, IsNil) ch <- n } c.Assert(r.Close(), IsNil) ch <- 0 }() go func() { buf := make([]byte, size) for i := 1; i < size; i++ { n, err := ioutils.WriteFull(w, buf[:i]) c.Assert(err, IsNil) c.Assert(n, Equals, i) } c.Assert(w.Close(), IsNil) }() sum := 0 for i := 1; i < size; i++ { sum += i } for { n := <-ch if n == 0 { break } sum -= n } c.Assert(sum, Equals, 0) }
func (s *testIoPipeSuite) testPipe4(c *C, fileName string) { r, w := s.openPipe(c, fileName) key := []byte("spinlock aes-128") block := aes.BlockSize count := 1024 * 1024 * 128 / block go func() { buf := make([]byte, count*block) m, err := aes.NewCipher(key) c.Assert(err, IsNil) for i := 0; i < len(buf); i++ { buf[i] = byte(i) } e := cipher.NewCBCEncrypter(m, make([]byte, block)) e.CryptBlocks(buf, buf) n, err := ioutils.WriteFull(w, buf) c.Assert(err, IsNil) c.Assert(w.Close(), IsNil) c.Assert(n, Equals, len(buf)) }() buf := make([]byte, count*block) m, err := aes.NewCipher(key) c.Assert(err, IsNil) _, err = ioutils.ReadFull(r, buf) c.Assert(err, IsNil) e := cipher.NewCBCDecrypter(m, make([]byte, block)) e.CryptBlocks(buf, buf) for i := 0; i < len(buf); i++ { // make gocheck faster if buf[i] != byte(i) { c.Assert(buf[i], Equals, byte(i)) } } _, err = ioutils.ReadFull(r, buf) c.Assert(errors2.ErrorEqual(err, io.EOF), Equals, true) c.Assert(r.Close(), IsNil) }
func iocopy(r io.Reader, w io.Writer, p []byte, max int) int { if max <= 0 || len(p) == 0 { log.Panicf("invalid max = %d, len(p) = %d", max, len(p)) } if len(p) > max { p = p[:max] } if n, err := r.Read(p); err != nil { log.PanicError(err, "read error") } else { p = p[:n] } if _, err := ioutils.WriteFull(w, p); err != nil { log.PanicError(err, "write full error") } return len(p) }
func testPipe1(t *testing.T, fileName string) { r, w := openPipe(t, fileName) s := "Hello world!!" go func(data []byte) { _, err := ioutils.WriteFull(w, data) assert.ErrorIsNil(t, err) assert.ErrorIsNil(t, w.Close()) }([]byte(s)) buf := make([]byte, 64) n, err := ioutils.ReadFull(r, buf) assert.Must(t, errors.Equal(err, io.EOF)) assert.Must(t, n == len(s)) assert.Must(t, string(buf[:n]) == s) assert.ErrorIsNil(t, r.Close()) }
func (s *testIoPipeSuite) testPipe1(c *C, fileName string) { r, w := s.openPipe(c, fileName) ss := "Hello world!!" go func(data []byte) { _, err := ioutils.WriteFull(w, data) c.Assert(err, IsNil) c.Assert(w.Close(), IsNil) }([]byte(ss)) buf := make([]byte, 64) n, err := ioutils.ReadFull(r, buf) c.Assert(errors2.ErrorEqual(err, io.EOF), Equals, true) c.Assert(n, Equals, len(ss)) c.Assert(string(buf[:n]), Equals, ss) c.Assert(r.Close(), IsNil) }
func testPipe3(t *testing.T, fileName string) { r, w := openPipe(t, fileName) c := make(chan int) size := 4096 go func() { buf := make([]byte, size) for { n, err := r.Read(buf) if errors.Equal(err, io.EOF) { break } assert.ErrorIsNil(t, err) c <- n } assert.ErrorIsNil(t, r.Close()) c <- 0 }() go func() { buf := make([]byte, size) for i := 1; i < size; i++ { n, err := ioutils.WriteFull(w, buf[:i]) assert.ErrorIsNil(t, err) assert.Must(t, n == i) } assert.ErrorIsNil(t, w.Close()) }() sum := 0 for i := 1; i < size; i++ { sum += i } for { n := <-c if n == 0 { break } sum -= n } assert.Must(t, sum == 0) }
func testPipe4(t *testing.T, fileName string) { r, w := openPipe(t, fileName) key := []byte("spinlock aes-128") block := aes.BlockSize count := 1024 * 1024 * 128 / block go func() { buf := make([]byte, count*block) m, err := aes.NewCipher(key) assert.ErrorIsNil(t, err) for i := 0; i < len(buf); i++ { buf[i] = byte(i) } e := cipher.NewCBCEncrypter(m, make([]byte, block)) e.CryptBlocks(buf, buf) n, err := ioutils.WriteFull(w, buf) assert.ErrorIsNil(t, err) assert.ErrorIsNil(t, w.Close()) assert.Must(t, n == len(buf)) }() buf := make([]byte, count*block) m, err := aes.NewCipher(key) assert.ErrorIsNil(t, err) _, err = ioutils.ReadFull(r, buf) assert.ErrorIsNil(t, err) e := cipher.NewCBCDecrypter(m, make([]byte, block)) e.CryptBlocks(buf, buf) for i := 0; i < len(buf); i++ { assert.Must(t, buf[i] == byte(i)) } _, err = ioutils.ReadFull(r, buf) assert.Must(t, errors.Equal(err, io.EOF)) assert.ErrorIsNil(t, r.Close()) }
func TestPipeWriteClose(t *testing.T) { for _, u := range pipeTests { r, w := Pipe() c := make(chan int, 1) if u.async { go delayClose(t, r, c, u) } else { delayClose(t, r, c, u) } <-c n, err := ioutils.WriteFull(w, []byte("hello, world")) expect := u.err if expect == nil { expect = io.ErrClosedPipe } assert.Must(t, errors.Equal(err, expect)) assert.Must(t, n == 0) assert.ErrorIsNil(t, w.Close()) } }
func (s *testIoPipeSuite) TestPipeWriteClose(c *C) { for _, u := range pipeTests { r, w := Pipe() ch := make(chan int, 1) if u.async { go s.delayClose(c, r, ch, u) } else { s.delayClose(c, r, ch, u) } <-ch n, err := ioutils.WriteFull(w, []byte("hello, world")) expect := u.err if expect == nil { expect = io.ErrClosedPipe } c.Assert(errors2.ErrorEqual(err, expect), Equals, true) c.Assert(n, Equals, 0) c.Assert(w.Close(), IsNil) } }
func TestWriteAfterWriterClose(t *testing.T) { r, w := Pipe() s := "hello" errs := make(chan error) go func() { _, err := ioutils.WriteFull(w, []byte(s)) assert.ErrorIsNil(t, err) assert.ErrorIsNil(t, w.Close()) _, err = w.Write([]byte("world")) errs <- err }() buf := make([]byte, 4096) n, err := ioutils.ReadFull(r, buf) assert.Must(t, errors.Equal(err, io.EOF)) assert.Must(t, string(buf[:n]) == s) err = <-errs assert.Must(t, errors.Equal(err, io.ErrClosedPipe)) assert.ErrorIsNil(t, r.Close()) }
func (w *BufWriter) WriteBytes(p []byte) error { _, err := ioutils.WriteFull(w.w, p) return errors.Trace(err) }
func (w *BufWriter) WriteUint64(s uint64) error { p := make([]byte, 8) binary.BigEndian.PutUint64(p, uint64(s)) _, err := ioutils.WriteFull(w.w, p) return errors.Trace(err) }
func (w *BufWriter) WriteUvarint(v uint64) error { p := make([]byte, binary.MaxVarintLen64) n := binary.PutUvarint(p, v) _, err := ioutils.WriteFull(w.w, p[:n]) return errors.Trace(err) }