func (cmd *cmdSync) PSyncPipeCopy(c net.Conn, br *bufio.Reader, bw *bufio.Writer, offset int64, copyto io.Writer) (int64, error) { defer c.Close() var nread atomic2.Int64 go func() { defer c.Close() for { time.Sleep(time.Second * 5) if err := sendPSyncAck(bw, offset+nread.Get()); err != nil { return } } }() var p = make([]byte, 8192) for { n, err := br.Read(p) if err != nil { return nread.Get(), nil } if _, err := copyto.Write(p[:n]); err != nil { return nread.Get(), err } nread.Add(int64(n)) } }
func (cmd *cmdDump) DumpRDBFile(reader *bufio.Reader, writer *bufio.Writer, nsize int64) { var nread atomic2.Int64 wait := make(chan struct{}) go func() { defer close(wait) p := make([]byte, WriterBufferSize) for nsize != nread.Get() { nstep := int(nsize - nread.Get()) ncopy := int64(iocopy(reader, writer, p, nstep)) nread.Add(ncopy) flushWriter(writer) } }() for done := false; !done; { select { case <-wait: done = true case <-time.After(time.Second): } n := nread.Get() p := 100 * n / nsize log.Infof("total = %d - %12d [%3d%%]\n", nsize, n, p) } log.Info("dump: rdb done") }
func (cmd *cmdDump) DumpCommand(reader *bufio.Reader, writer *bufio.Writer, nsize int64) { var nread atomic2.Int64 go func() { p := make([]byte, ReaderBufferSize) for { ncopy := int64(iocopy(reader, writer, p, len(p))) nread.Add(ncopy) flushWriter(writer) } }() for { time.Sleep(time.Second) log.Infof("dump: total = %d\n", nsize+nread.Get()) } }
func TestEncodeRdb(t *testing.T) { objs := make([]struct { db uint32 expireat uint64 key []byte obj interface{} typ string }, 128) var b bytes.Buffer enc := NewEncoder(&b) assert.MustNoError(enc.EncodeHeader()) for i := 0; i < len(objs); i++ { db := uint32(i + 32) expireat := uint64(i) key := []byte(strconv.Itoa(i)) var obj interface{} var typ string switch i % 5 { case 0: s := strconv.Itoa(i) obj = s typ = "string" assert.MustNoError(enc.EncodeObject(db, key, expireat, toString(s))) case 1: list := []string{} for j := 0; j < 32; j++ { list = append(list, fmt.Sprintf("l%d_%d", i, rand.Int())) } obj = list typ = "list" assert.MustNoError(enc.EncodeObject(db, key, expireat, toList(list...))) case 2: hash := make(map[string]string) for j := 0; j < 32; j++ { hash[strconv.Itoa(j)] = fmt.Sprintf("h%d_%d", i, rand.Int()) } obj = hash typ = "hash" assert.MustNoError(enc.EncodeObject(db, key, expireat, toHash(hash))) case 3: zset := make(map[string]float64) for j := 0; j < 32; j++ { zset[strconv.Itoa(j)] = rand.Float64() } obj = zset typ = "zset" assert.MustNoError(enc.EncodeObject(db, key, expireat, toZSet(zset))) case 4: set := []string{} for j := 0; j < 32; j++ { set = append(set, fmt.Sprintf("s%d_%d", i, rand.Int())) } obj = set typ = "set" assert.MustNoError(enc.EncodeObject(db, key, expireat, toSet(set...))) } objs[i].db = db objs[i].expireat = expireat objs[i].key = key objs[i].obj = obj objs[i].typ = typ } assert.MustNoError(enc.EncodeFooter()) rdb := b.Bytes() var c atomic2.Int64 l := NewLoader(stats.NewCountReader(bytes.NewReader(rdb), &c)) assert.MustNoError(l.Header()) var i int = 0 for { e, err := l.NextBinEntry() assert.MustNoError(err) if e == nil { break } assert.Must(objs[i].db == e.DB) assert.Must(objs[i].expireat == e.ExpireAt) assert.Must(bytes.Equal(objs[i].key, e.Key)) o, err := DecodeDump(e.Value) assert.MustNoError(err) switch objs[i].typ { case "string": checkString(t, o, objs[i].obj.(string)) case "list": checkList(t, o, objs[i].obj.([]string)) case "hash": checkHash(t, o, objs[i].obj.(map[string]string)) case "zset": checkZSet(t, o, objs[i].obj.(map[string]float64)) case "set": checkSet(t, o, objs[i].obj.([]string)) } i++ } assert.Must(i == len(objs)) assert.MustNoError(l.Footer()) assert.Must(c.Get() == int64(len(rdb))) }