func TestTableDump(t *testing.T) { // Dump var in proto.PkgDumpReq in.Cmd = proto.CmdDump in.DbId = 2 in.Seq = 20 in.TableId = 2 in.PkgFlag |= proto.FlagDumpSlotStart in.StartSlotId = 0 in.EndSlotId = 65535 out := myDump(in, testAuth, t) if len(out.Kvs) != 10 { t.Fatalf("Invalid KV number: %d", len(out.Kvs)) } if out.PkgFlag&proto.FlagDumpEnd == 0 { t.Fatalf("Dump should end") } for i := 0; i < len(out.Kvs); i++ { j := i idx := 4 - i if i >= 5 { j = i - 5 idx = 9 - i } if out.Kvs[i].ErrCode != 0 { t.Fatalf("ErrCode is 0") } if out.Kvs[i].TableId != 2 { t.Fatalf("TableId mismatch") } if bytes.Compare(out.Kvs[i].RowKey, []byte("row2")) == 0 { if bytes.Compare(out.Kvs[i].ColKey, []byte(fmt.Sprintf("col%d", idx))) != 0 { t.Fatalf("ColKey mismatch") } if out.Kvs[i].Score != int64(j*10) { t.Fatalf("Score mismatch") } if bytes.Compare(out.Kvs[i].Value, []byte(fmt.Sprintf("v%d", idx))) != 0 { t.Fatalf("Value mismatch") } } else { if bytes.Compare(out.Kvs[i].RowKey, []byte("row1")) != 0 { t.Fatalf("RowKey mismatch") } if bytes.Compare(out.Kvs[i].ColKey, []byte(fmt.Sprintf("col%d", j))) != 0 { t.Fatalf("ColKey mismatch") } if out.Kvs[i].Score != int64(j*10+10) { t.Fatalf("Score mismatch") } if bytes.Compare(out.Kvs[i].Value, []byte(fmt.Sprintf("v%d", j))) != 0 { t.Fatalf("Value mismatch") } } } }
func myDump(in proto.PkgDumpReq, au Authorize, t *testing.T) proto.PkgDumpResp { var pkg = make([]byte, in.Length()) _, err := in.Encode(pkg) if err != nil { t.Fatalf("Encode failed: ", err) } pkg = testTbl.Dump(&PkgArgs{in.Cmd, in.DbId, in.Seq, pkg}, au) var out proto.PkgDumpResp _, err = out.Decode(pkg) if err != nil { t.Fatalf("Decode failed: ", err) } if out.ErrCode != 0 { t.Fatalf("Failed with ErrCode %d", out.ErrCode) } if out.DbId != in.DbId || out.Seq != in.Seq { t.Fatalf("DbId/Seq mismatch") } return out }
func (tbl *Table) Dump(req *PkgArgs, au Authorize) []byte { var out proto.PkgDumpResp out.Cmd = req.Cmd out.DbId = req.DbId out.Seq = req.Seq var in proto.PkgDumpReq n, err := in.Decode(req.Pkg) if err != nil || n != len(req.Pkg) { return errorHandle(&out, table.EcDecodeFail) } out.StartSlotId = in.StartSlotId out.EndSlotId = in.EndSlotId out.LastSlotId = in.StartSlotId out.PkgFlag = in.PkgFlag out.PkgFlag &^= (proto.FlagDumpSlotStart | proto.FlagDumpEnd) if in.DbId == proto.AdminDbId { return errorHandle(&out, table.EcInvDbId) } if !au.IsAuth(in.DbId) { return errorHandle(&out, table.EcNoPrivilege) } var onlyOneTable = (out.PkgFlag&proto.FlagDumpTable != 0) var rOpt = tbl.db.NewReadOptions(false) rOpt.SetFillCache(false) defer rOpt.Destroy() var it = tbl.db.NewIterator(rOpt) defer it.Destroy() if len(in.RowKey) == 0 { it.Seek(getRawSlotKey(in.StartSlotId, in.DbId, in.TableId)) } else { var rawColKey = in.ColKey if in.ColSpace == proto.ColSpaceScore1 { rawColKey = newScoreColKey(in.Score, in.ColKey) } it.Seek(getRawKey(in.DbId, in.TableId, in.ColSpace, in.RowKey, rawColKey)) if it.Valid() { _, dbId, tableId, colSpace, rowKey, colKey := parseRawKey(it.Key()) if dbId == in.DbId && tableId == in.TableId && bytes.Compare(rowKey, in.RowKey) == 0 && colSpace == in.ColSpace && bytes.Compare(colKey, rawColKey) == 0 { it.Next() } } } const maxScanNum = 1000 const maxTrySlotNum = 10 var triedSlotNum = 0 var pkgLen = proto.HeadSize + 1000 for it.Valid() && len(out.Kvs) < maxScanNum { slotId, dbId, tableId, colSpace, rowKey, colKey := parseRawKey(it.Key()) if slotId < in.StartSlotId || slotId > in.EndSlotId { out.PkgFlag |= proto.FlagDumpEnd break } var misMatch bool var nextSlotTableId uint8 // Dump only the selected TableId? if onlyOneTable { if dbId != in.DbId || tableId != in.TableId { misMatch = true nextSlotTableId = in.TableId } } else { if dbId != in.DbId { misMatch = true } } if misMatch { if triedSlotNum >= maxTrySlotNum { break } var nextSlotId = out.LastSlotId + 1 if nextSlotId < slotId && slotId <= in.EndSlotId { nextSlotId = slotId } if nextSlotId <= in.EndSlotId { triedSlotNum++ out.LastSlotId = nextSlotId out.PkgFlag |= proto.FlagDumpSlotStart seekToSlot(it, nextSlotId, in.DbId, nextSlotTableId) continue } else { out.PkgFlag |= proto.FlagDumpEnd break } } if colSpace == proto.ColSpaceScore2 { it.Seek(getRawKey(dbId, tableId, colSpace+1, rowKey, nil)) continue // No need to dup dump } var kv proto.KeyValue if colSpace != proto.ColSpaceScore1 { kv.ColKey = colKey kv.Value, kv.Score = parseRawValue(it.Value()) } else { if len(colKey) < 8 { it.Next() continue // Skip invalid record } kv.Score = int64(binary.BigEndian.Uint64(colKey) - zopScoreUp) kv.ColKey = colKey[8:] kv.Value, _ = parseRawValue(it.Value()) } kv.TableId = tableId kv.RowKey = rowKey kv.SetColSpace(colSpace) if len(kv.Value) > 0 { kv.CtrlFlag |= proto.CtrlValue } if kv.Score != 0 { kv.CtrlFlag |= proto.CtrlScore } out.Kvs = append(out.Kvs, kv) out.LastSlotId = slotId out.PkgFlag &^= proto.FlagDumpSlotStart pkgLen += kv.Length() if pkgLen > proto.MaxPkgLen/2 { out.PkgFlag &^= proto.FlagDumpEnd break } it.Next() } if !it.Valid() { out.PkgFlag |= proto.FlagDumpEnd } var pkg = make([]byte, out.Length()) _, err = out.Encode(pkg) if err != nil { log.Fatalf("Encode failed: %s\n", err) } return pkg }
func (c *Context) goDump(oneTable bool, tableId, colSpace uint8, rowKey, colKey []byte, score int64, startSlotId, endSlotId uint16, done chan *Call) (*Call, error) { call := c.cli.newCall(proto.CmdDump, done) if call.err != nil { return call, call.err } var p proto.PkgDumpReq p.Seq = call.seq p.DbId = c.dbId p.Cmd = call.cmd if oneTable { p.PkgFlag |= proto.FlagDumpTable } p.StartSlotId = startSlotId p.EndSlotId = endSlotId p.TableId = tableId p.RowKey = rowKey p.ColKey = colKey p.SetColSpace(colSpace) p.SetScore(score) var pkgLen = p.Length() if pkgLen > proto.MaxPkgLen { c.cli.errCall(call, ErrInvPkgLen) return call, call.err } call.pkg = make([]byte, pkgLen) _, err := p.Encode(call.pkg) if err != nil { c.cli.errCall(call, err) return call, err } call.ctx = dumpContext{oneTable, tableId, startSlotId, endSlotId, startSlotId, false} c.cli.sending <- call return call, nil }