Example #1
0
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")
			}
		}
	}
}
Example #2
0
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
}
Example #3
0
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
}
Example #4
0
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
}