func (cmd *cmdDecode) decoderMain(ipipe <-chan *rdb.BinEntry, opipe chan<- string) { toText := func(p []byte) string { var b bytes.Buffer for _, c := range p { switch { case c >= '#' && c <= '~': b.WriteByte(c) default: b.WriteByte('.') } } return b.String() } toBase64 := func(p []byte) string { return base64.StdEncoding.EncodeToString(p) } toJson := func(o interface{}) string { b, err := json.Marshal(o) if err != nil { log.PanicError(err, "encode to json failed") } return string(b) } for e := range ipipe { o, err := rdb.DecodeDump(e.Value) if err != nil { log.PanicError(err, "decode failed") } var b bytes.Buffer switch obj := o.(type) { default: log.Panicf("unknown object %v", o) case rdb.String: o := &struct { DB uint32 `json:"db"` Type string `json:"type"` ExpireAt uint64 `json:"expireat"` Key string `json:"key"` Key64 string `json:"key64"` Value64 string `json:"value64"` }{ e.DB, "string", e.ExpireAt, toText(e.Key), toBase64(e.Key), toBase64(obj), } fmt.Fprintf(&b, "%s\n", toJson(o)) case rdb.List: for i, ele := range obj { o := &struct { DB uint32 `json:"db"` Type string `json:"type"` ExpireAt uint64 `json:"expireat"` Key string `json:"key"` Key64 string `json:"key64"` Index int `json:"index"` Value64 string `json:"value64"` }{ e.DB, "list", e.ExpireAt, toText(e.Key), toBase64(e.Key), i, toBase64(ele), } fmt.Fprintf(&b, "%s\n", toJson(o)) } case rdb.Hash: for _, ele := range obj { o := &struct { DB uint32 `json:"db"` Type string `json:"type"` ExpireAt uint64 `json:"expireat"` Key string `json:"key"` Key64 string `json:"key64"` Field string `json:"field"` Field64 string `json:"field64"` Value64 string `json:"value64"` }{ e.DB, "hash", e.ExpireAt, toText(e.Key), toBase64(e.Key), toText(ele.Field), toBase64(ele.Field), toBase64(ele.Value), } fmt.Fprintf(&b, "%s\n", toJson(o)) } case rdb.Set: for _, mem := range obj { o := &struct { DB uint32 `json:"db"` Type string `json:"type"` ExpireAt uint64 `json:"expireat"` Key string `json:"key"` Key64 string `json:"key64"` Member string `json:"member"` Member64 string `json:"member64"` }{ e.DB, "set", e.ExpireAt, toText(e.Key), toBase64(e.Key), toText(mem), toBase64(mem), } fmt.Fprintf(&b, "%s\n", toJson(o)) } case rdb.ZSet: for _, ele := range obj { o := &struct { DB uint32 `json:"db"` Type string `json:"type"` ExpireAt uint64 `json:"expireat"` Key string `json:"key"` Key64 string `json:"key64"` Member string `json:"member"` Member64 string `json:"member64"` Score float64 `json:"score"` }{ e.DB, "zset", e.ExpireAt, toText(e.Key), toBase64(e.Key), toText(ele.Member), toBase64(ele.Member), ele.Score, } fmt.Fprintf(&b, "%s\n", toJson(o)) } } cmd.nentry.Incr() opipe <- b.String() } }
func restoreRdbEntry(c redigo.Conn, e *rdb.BinEntry) { var ttlms uint64 if e.ExpireAt != 0 { now := uint64(time.Now().Add(args.shift).UnixNano()) now /= uint64(time.Millisecond) if now >= e.ExpireAt { ttlms = 1 } else { ttlms = e.ExpireAt - now } } toText := func(p []byte) string { var b bytes.Buffer for _, c := range p { switch { case c >= '#' && c <= '~': b.WriteByte(c) default: b.WriteByte('.') } } return b.String() } if aggregateKey(e.Key) { log.Infof("Aggregate key %s", e.Key) o, err := rdb.DecodeDump(e.Value) if err != nil { log.PanicError(err, "decode failed") } switch obj := o.(type) { default: log.Panicf("unknown object %v", o) case rdb.List: for _, ele := range obj { _, err := c.Do(aggregateCmd, aggregateTarget, toText(ele)) if err != nil { log.PanicError(err, "aggregate error") } } case rdb.Set: for _, ele := range obj { _, err := c.Do(aggregateCmd, aggregateTarget, toText(ele)) if err != nil { log.PanicError(err, "aggregate error") } } } } if set2sortedKey(e.Key) { o, err := rdb.DecodeDump(e.Value) if err != nil { log.PanicError(err, "decode failed") } switch obj := o.(type) { default: log.Panicf("set2sorted key %s type is not set err", e.Key) log.Panicf("unknown object %v", o) case rdb.Set: for _, ele := range obj { _, err := c.Do("zadd", e.Key, 1, toText(ele)) if err != nil { log.PanicErrorf(err, "set2sorted zadd %s 1 %s", e.Key, toText(ele)) } } } return } if sorted2setKey(e.Key) { o, err := rdb.DecodeDump(e.Value) if err != nil { log.PanicError(err, "decode failed") } switch obj := o.(type) { default: log.Panicf("sorted2set key %s type is not sorted set err", e.Key) case rdb.ZSet: for _, ele := range obj { _, err := c.Do("sadd", e.Key, toText(ele.Member)) if err != nil { log.PanicErrorf(err, "sorted2set sadd %s %s", e.Key, toText(ele.Member)) } } } return } if (restoreCmd == "del") || (restoreCmd == "DEL") { _, err := redigo.String(c.Do(restoreCmd, e.Key)) if err != nil { log.Warnf("delete key: '%s'", e.Key) } } else { s, err := redigo.String(c.Do(restoreCmd, e.Key, ttlms, e.Value)) if err != nil { log.Warnf("restore error, when '%s' '%s'", restoreCmd, e.Key) //log.PanicError(err, "restore command error") } if s != "OK" { //log.Panicf("restore command response = '%s', should be 'OK'", s) log.Warnf("restore command response = '%s', should be 'OK'", s) } } }