func (e *Encoder) EncodeObject(db uint32, key []byte, expireat uint64, obj interface{}) error { o, ok := obj.(objectEncoder) if !ok { return errors.Errorf("unsupported object type") } if e.db == -1 || uint32(e.db) != db { e.db = int64(db) if err := e.enc.EncodeDatabase(int(db)); err != nil { return errors.Trace(err) } } if expireat != 0 { if err := e.enc.EncodeExpiry(expireat); err != nil { return errors.Trace(err) } } if err := o.encodeType(e.enc); err != nil { return err } if err := e.enc.EncodeString(key); err != nil { return errors.Trace(err) } if err := o.encodeValue(e.enc); err != nil { return err } return nil }
func (e *encoder) encodeText(s string) error { if _, err := e.w.WriteString(s); err != nil { return errors.Trace(err) } if _, err := e.w.WriteString("\r\n"); err != nil { return errors.Trace(err) } return nil }
func (d *decoder) decodeText() (string, error) { b, err := d.r.ReadBytes('\n') if err != nil { return "", errors.Trace(err) } if n := len(b) - 2; n < 0 || b[n] != '\r' { return "", errors.Trace(ErrBadRespCRLFEnd) } else { return string(b[:n]), nil } }
func (o Set) encodeValue(enc *rdb.Encoder) error { if err := enc.EncodeLength(uint32(len(o))); err != nil { return errors.Trace(err) } for _, e := range o { if err := enc.EncodeString(e); err != nil { return errors.Trace(err) } } return nil }
func (p *fileBuffer) writeSome(b []byte) (int, error) { if p.f == nil { return 0, errors.Trace(io.ErrClosedPipe) } maxlen, offset := woffset(len(b), p.size, p.rpos, p.wpos) if maxlen == 0 { return 0, nil } n, err := p.f.WriteAt(b[:maxlen], int64(offset)) p.wpos += uint64(n) return n, errors.Trace(err) }
func (d *decoder) decodeType() (respType, error) { if b, err := d.r.ReadByte(); err != nil { return 0, errors.Trace(err) } else { return respType(b), nil } }
func DecodeDump(p []byte) (interface{}, error) { d := &decoder{} if err := rdb.DecodeDump(p, 0, nil, 0, d); err != nil { return nil, errors.Trace(err) } return d.obj, d.err }
func authPassword(c net.Conn, passwd string) { if passwd == "" { return } _, err := c.Write(redis.MustEncodeToBytes(redis.NewCommand("auth", passwd))) if err != nil { log.PanicError(errors.Trace(err), "write auth command failed") } var b = make([]byte, 5) if _, err := io.ReadFull(c, b); err != nil { log.PanicError(errors.Trace(err), "read auth response failed") } if strings.ToUpper(string(b)) != "+OK\r\n" { log.Panic("auth failed") } }
func openSyncConn(target string, passwd string) (net.Conn, <-chan int64) { c := openNetConn(target, passwd) if _, err := c.Write(redis.MustEncodeToBytes(redis.NewCommand("sync"))); err != nil { log.PanicError(errors.Trace(err), "write sync command failed") } return c, waitRdbDump(c) }
func (e *encoder) encodeBulkBytes(b []byte) error { if b == nil { return e.encodeInt(-1) } else { if err := e.encodeInt(int64(len(b))); err != nil { return err } if _, err := e.w.Write(b); err != nil { return errors.Trace(err) } if _, err := e.w.WriteString("\r\n"); err != nil { return errors.Trace(err) } return nil } }
func (p *fileBuffer) rclose() error { if f := p.f; f != nil { p.f = nil defer f.Close() return errors.Trace(f.Truncate(0)) } return nil }
func Parse(s string) (int64, error) { if !BytesizeRegexp.MatchString(s) { return 0, errors.Trace(ErrBadBytesize) } subs := BytesizeRegexp.FindStringSubmatch(s) if len(subs) != 3 { return 0, errors.Trace(ErrBadBytesize) } size := int64(0) switch strings.ToUpper(string(subs[2])) { case "B", "": size = 1 case "KB", "K": size = KB case "MB", "M": size = MB case "GB", "G": size = GB case "TB", "T": size = TB case "PB", "P": size = PB default: return 0, errors.Trace(ErrBadBytesizeUnit) } text := subs[1] if digitsRegexp.MatchString(text) { n, err := strconv.ParseInt(text, 10, 64) if err != nil { return 0, errors.Trace(ErrBadBytesize) } size *= n } else { n, err := strconv.ParseFloat(text, 64) if err != nil { return 0, errors.Trace(ErrBadBytesize) } size = int64(float64(size) * n) } return size, nil }
func Encode(w *bufio.Writer, r Resp, flush bool) error { e := &encoder{w} if err := e.encodeResp(r); err != nil { return err } if !flush { return nil } return errors.Trace(w.Flush()) }
func (d *decoder) decodeBulkBytes() ([]byte, error) { n, err := d.decodeInt() if err != nil { return nil, err } if n < -1 { return nil, errors.Trace(ErrBadRespBytesLen) } else if n == -1 { return nil, nil } b := make([]byte, n+2) if _, err := io.ReadFull(d.r, b); err != nil { return nil, errors.Trace(err) } if b[n] != '\r' || b[n+1] != '\n' { return nil, errors.Trace(ErrBadRespCRLFEnd) } return b[:n], nil }
func (p *fileBuffer) readSome(b []byte) (int, error) { if p.f == nil { return 0, errors.Trace(io.ErrClosedPipe) } maxlen, offset := roffset(len(b), p.size, p.rpos, p.wpos) if maxlen == 0 { return 0, nil } n, err := p.f.ReadAt(b[:maxlen], int64(offset)) p.rpos += uint64(n) if p.rpos == p.wpos { p.rpos = 0 p.wpos = 0 if err == nil { err = p.f.Truncate(0) } } return n, errors.Trace(err) }
func (d *decoder) decodeSingleLineBulkBytesArray() (Resp, error) { b, err := d.r.ReadBytes('\n') if err != nil { return nil, errors.Trace(err) } if n := len(b) - 2; n < 0 || b[n] != '\r' { return nil, errors.Trace(ErrBadRespCRLFEnd) } else { resp := &Array{} for l, r := 0, 0; r <= n; r++ { if r == n || b[r] == ' ' { if l < r { resp.Value = append(resp.Value, &BulkBytes{b[l:r]}) } l = r + 1 } } return resp, nil } }
func (d *decoder) decodeInt() (int64, error) { b, err := d.decodeText() if err != nil { return 0, err } if n, err := strconv.ParseInt(string(b), 10, 64); err != nil { return 0, errors.Trace(err) } else { return n, nil } }
func (p *memBuffer) writeSome(b []byte) (int, error) { if p.b == nil { return 0, errors.Trace(io.ErrClosedPipe) } maxlen, offset := woffset(len(b), p.size, p.rpos, p.wpos) if maxlen == 0 { return 0, nil } n := copy(p.b[offset:offset+maxlen], b) p.wpos += uint64(n) return n, nil }
func (p *pipe) WClose(err error) error { if err == nil { err = errors.Trace(io.EOF) } p.mu.Lock() defer p.mu.Unlock() if p.werr == nil { p.werr = err } p.rwait.Signal() p.wwait.Signal() return p.store.wclose() }
func (l *Loader) Header() error { header := make([]byte, 9) if err := l.readFull(header); err != nil { return err } if !bytes.Equal(header[:5], []byte("REDIS")) { return errors.Errorf("verify magic string, invalid file format") } if version, err := strconv.ParseInt(string(header[5:]), 10, 64); err != nil { return errors.Trace(err) } else if version <= 0 || version > Version { return errors.Errorf("verify version, invalid RDB version number %d", version) } return nil }
func (p *memBuffer) readSome(b []byte) (int, error) { if p.b == nil { return 0, errors.Trace(io.ErrClosedPipe) } maxlen, offset := roffset(len(b), p.size, p.rpos, p.wpos) if maxlen == 0 { return 0, nil } n := copy(b, p.b[offset:offset+maxlen]) p.rpos += uint64(n) if p.rpos == p.wpos { p.rpos = 0 p.wpos = 0 } return n, nil }
func EncodeDump(obj interface{}) ([]byte, error) { o, ok := obj.(objectEncoder) if !ok { return nil, errors.Errorf("unsupported object type") } var b bytes.Buffer enc := rdb.NewEncoder(&b) if err := o.encodeType(enc); err != nil { return nil, err } if err := o.encodeValue(enc); err != nil { return nil, err } if err := enc.EncodeDumpFooter(); err != nil { return nil, errors.Trace(err) } return b.Bytes(), nil }
func (d *decoder) decodeArray(depth int) ([]Resp, error) { n, err := d.decodeInt() if err != nil { return nil, err } if n < -1 { return nil, errors.Trace(ErrBadRespArrayLen) } else if n == -1 { return nil, nil } a := make([]Resp, n) for i := 0; i < len(a); i++ { if a[i], err = d.decodeResp(depth + 1); err != nil { return nil, err } } return a, nil }
func (p *pipe) writeSome(b []byte) (int, error) { p.mu.Lock() defer p.mu.Unlock() if p.werr != nil { return 0, errors.Trace(io.ErrClosedPipe) } if p.rerr != nil { return 0, p.rerr } if len(b) == 0 { return 0, nil } n, err := p.store.writeSome(b) if err != nil || n != 0 { p.rwait.Signal() return n, err } p.wwait.Wait() return 0, nil }
func (r *rdbReader) readFloat() (float64, error) { u, err := r.readUint8() if err != nil { return 0, err } switch u { case 253: return math.NaN(), nil case 254: return math.Inf(0), nil case 255: return math.Inf(-1), nil default: if b, err := r.readBytes(int(u)); err != nil { return 0, err } else { v, err := strconv.ParseFloat(string(b), 64) return v, errors.Trace(err) } } }
func (d *decoder) decodeResp(depth int) (Resp, error) { t, err := d.decodeType() if err != nil { return nil, err } switch t { case typeString: resp := &String{} resp.Value, err = d.decodeText() return resp, err case typeError: resp := &Error{} resp.Value, err = d.decodeText() return resp, err case typeInt: resp := &Int{} resp.Value, err = d.decodeInt() return resp, err case typeBulkBytes: resp := &BulkBytes{} resp.Value, err = d.decodeBulkBytes() return resp, err case typeArray: resp := &Array{} resp.Value, err = d.decodeArray(depth) return resp, err default: if depth != 0 { return nil, errors.Errorf("bad resp type %s", t) } if err := d.r.UnreadByte(); err != nil { return nil, errors.Trace(err) } return d.decodeSingleLineBulkBytesArray() } }
func (r *rdbReader) readByte() (byte, error) { b := r.buf[:1] _, err := io.ReadFull(r, b) return b[0], errors.Trace(err) }
func (r *rdbReader) Read(p []byte) (int, error) { n, err := r.raw.Read(p) r.nread += int64(n) return n, errors.Trace(err) }
func (r *rdbReader) readFull(p []byte) error { _, err := io.ReadFull(r, p) return errors.Trace(err) }
func OpenFile(path string) (*os.File, error) { f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0666) return f, errors.Trace(err) }