示例#1
0
func myScan(in proto.PkgScanReq, au Authorize, t *testing.T) proto.PkgScanResp {
	var pkg = make([]byte, in.Length())
	_, err := in.Encode(pkg)
	if err != nil {
		t.Fatalf("Encode failed: ", err)
	}

	pkg = testTbl.Scan(&PkgArgs{in.Cmd, in.DbId, in.Seq, pkg}, au)

	var out proto.PkgScanResp
	_, 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
}
示例#2
0
文件: table.go 项目: tradia/gotable
func (tbl *Table) Scan(req *PkgArgs, au Authorize) []byte {
	var out proto.PkgScanResp
	out.Cmd = req.Cmd
	out.DbId = req.DbId
	out.Seq = req.Seq

	var in proto.PkgScanReq
	n, err := in.Decode(req.Pkg)
	if err != nil || n != len(req.Pkg) {
		return errorHandle(&out, table.EcDecodeFail)
	}

	out.PkgFlag = in.PkgFlag

	if in.DbId == proto.AdminDbId {
		return errorHandle(&out, table.EcInvDbId)
	}

	if !au.IsAuth(in.DbId) {
		return errorHandle(&out, table.EcNoPrivilege)
	}

	if in.ColSpace == proto.ColSpaceScore1 {
		tbl.zScanSortScore(&in, &out)
		return replyHandle(&out)
	}

	var scanColSpace uint8 = proto.ColSpaceDefault
	if in.ColSpace == proto.ColSpaceScore2 {
		scanColSpace = proto.ColSpaceScore2
	}
	var it = tbl.db.NewIterator(nil)
	defer it.Destroy()

	var scanAsc = (in.PkgFlag&proto.FlagScanAsc != 0)
	var startSeek = (in.PkgFlag&proto.FlagScanKeyStart != 0)
	if scanAsc {
		if startSeek {
			// Seek to the first element
			it.Seek(getRawKey(in.DbId, in.TableId, scanColSpace, in.RowKey, nil))
		} else {
			it.Seek(getRawKey(in.DbId, in.TableId, scanColSpace,
				in.RowKey, in.ColKey))
		}
	} else {
		if startSeek {
			// Seek to the last element
			it.Seek(getRawKey(in.DbId, in.TableId, scanColSpace+1, in.RowKey, nil))
		} else {
			it.Seek(getRawKey(in.DbId, in.TableId, scanColSpace,
				in.RowKey, in.ColKey))
		}
		if !it.Valid() {
			it.SeekToLast()
		}
	}

	out.PkgFlag |= proto.FlagScanEnd
	var first = true
	var scanNum = int(in.Num)
	var pkgLen = proto.HeadSize + 1000
	for i := 0; it.Valid() && i < scanNum+1; iterMove(it, scanAsc) {
		_, dbId, tableId, colSpace, rowKey, colKey := parseRawKey(it.Key())
		if dbId != in.DbId || tableId != in.TableId ||
			colSpace != scanColSpace || bytes.Compare(rowKey, in.RowKey) != 0 {
			if first {
				first = false
				continue
			} else {
				break
			}
		}

		if first {
			first = false
		}

		if !startSeek {
			if scanAsc {
				if bytes.Compare(colKey, in.ColKey) <= 0 {
					continue
				}
			} else {
				if bytes.Compare(colKey, in.ColKey) >= 0 {
					continue
				}
			}
		}

		if i < scanNum {
			var kv proto.KeyValue
			kv.TableId = in.TableId
			kv.RowKey = in.RowKey
			kv.ColKey = colKey
			kv.Value, kv.Score = parseRawValue(it.Value())
			if len(kv.Value) > 0 {
				kv.CtrlFlag |= proto.CtrlValue
			}
			if kv.Score != 0 {
				kv.CtrlFlag |= proto.CtrlScore
			}

			out.Kvs = append(out.Kvs, kv)

			pkgLen += kv.Length()
			if pkgLen > proto.MaxPkgLen/2 {
				out.PkgFlag &^= proto.FlagScanEnd
				break
			}
		} else {
			out.PkgFlag &^= proto.FlagScanEnd
			break
		}
		i++
	}

	return replyHandle(&out)
}
示例#3
0
文件: table.go 项目: tradia/gotable
func (tbl *Table) zScanSortScore(in *proto.PkgScanReq, out *proto.PkgScanResp) {
	var it = tbl.db.NewIterator(nil)
	defer it.Destroy()

	var scanAsc = (in.PkgFlag&proto.FlagScanAsc != 0)
	var startSeek = (in.PkgFlag&proto.FlagScanKeyStart != 0)
	var scanColSpace uint8 = proto.ColSpaceScore1
	if scanAsc {
		if startSeek {
			// Seek to the first element
			it.Seek(getRawKey(in.DbId, in.TableId, scanColSpace,
				in.RowKey, nil))
		} else {
			it.Seek(getRawKey(in.DbId, in.TableId, scanColSpace,
				in.RowKey, newScoreColKey(in.Score, in.ColKey)))
		}
	} else {
		if startSeek {
			// Seek to the last element
			it.Seek(getRawKey(in.DbId, in.TableId, scanColSpace+1,
				in.RowKey, nil))
		} else {
			it.Seek(getRawKey(in.DbId, in.TableId, scanColSpace,
				in.RowKey, newScoreColKey(in.Score, in.ColKey)))
		}
		if !it.Valid() {
			it.SeekToLast()
		}
	}

	out.PkgFlag |= proto.FlagScanEnd
	var first = true
	var scanNum = int(in.Num)
	var pkgLen = proto.HeadSize + 1000
	for i := 0; it.Valid() && i < scanNum+1; iterMove(it, scanAsc) {
		_, dbId, tableId, colSpace, rowKey, colKey := parseRawKey(it.Key())
		if dbId != in.DbId || tableId != in.TableId ||
			colSpace != scanColSpace || bytes.Compare(rowKey, in.RowKey) != 0 {
			if first {
				first = false
				continue
			} else {
				break
			}
		}

		if first {
			first = false
		}

		if len(colKey) < 8 {
			continue //  skip invalid record
		}
		zColKey, zScore := parseZColKey(colKey)
		if !startSeek {
			if scanAsc {
				if zScore < in.Score {
					continue
				}
				if zScore == in.Score && bytes.Compare(zColKey, in.ColKey) <= 0 {
					continue
				}
			} else {
				if zScore > in.Score {
					continue
				}
				if zScore == in.Score && bytes.Compare(zColKey, in.ColKey) >= 0 {
					continue
				}
			}
		}

		if i < scanNum {
			var kv proto.KeyValue
			kv.TableId = in.TableId
			kv.RowKey = in.RowKey
			kv.ColKey = zColKey
			kv.Value, _ = parseRawValue(it.Value())
			kv.Score = zScore
			if len(kv.Value) > 0 {
				kv.CtrlFlag |= proto.CtrlValue
			}
			if kv.Score != 0 {
				kv.CtrlFlag |= proto.CtrlScore
			}
			out.Kvs = append(out.Kvs, kv)

			pkgLen += kv.Length()
			if pkgLen > proto.MaxPkgLen/2 {
				out.PkgFlag &^= proto.FlagScanEnd
				break
			}
		} else {
			out.PkgFlag &^= proto.FlagScanEnd
			break
		}
		i++
	}
}
示例#4
0
文件: context.go 项目: tradia/gotable
// Get call reply. The real reply types are:
// Auth/Ping/(Z)Set/(Z)Del: nil;
// (Z)Get: GetReply;
// (Z)Incr: IncrReply;
// (Z)MGet: []GetReply;
// (Z)MSet: []SetReply;
// (Z)MDel: []DelReply;
// (Z)MIncr: []IncrReply;
// (Z)Scan: ScanReply;
// Dump: DumpReply;
func (call *Call) Reply() (interface{}, error) {
	if call.err != nil {
		return nil, call.err
	}

	if !call.ready {
		return nil, ErrCallNotReady
	}

	if proto.CmdAuth == call.cmd ||
		proto.CmdPing == call.cmd ||
		proto.CmdIncr == call.cmd ||
		proto.CmdDel == call.cmd ||
		proto.CmdSet == call.cmd ||
		proto.CmdGet == call.cmd {
		var p proto.PkgOneOp
		_, err := p.Decode(call.pkg)
		if err != nil {
			call.err = err
			return nil, call.err
		}
		if p.ErrCode < 0 {
			return nil, getErr(p.ErrCode)
		}
		switch call.cmd {
		case proto.CmdAuth:
			return nil, nil
		case proto.CmdPing:
			return nil, nil
		case proto.CmdIncr:
			return IncrReply{p.ErrCode, p.TableId, copyBytes(p.RowKey),
				copyBytes(p.ColKey), copyBytes(p.Value), p.Score}, nil
		case proto.CmdDel:
			return nil, nil
		case proto.CmdSet:
			return nil, nil
		case proto.CmdGet:
			return GetReply{p.ErrCode, p.TableId, copyBytes(p.RowKey),
				copyBytes(p.ColKey), copyBytes(p.Value), p.Score, p.Cas}, nil
		}
	}

	if proto.CmdMIncr == call.cmd ||
		proto.CmdMDel == call.cmd ||
		proto.CmdMSet == call.cmd ||
		proto.CmdMGet == call.cmd {
		var p proto.PkgMultiOp
		_, err := p.Decode(call.pkg)
		if err != nil {
			call.err = err
			return nil, call.err
		}

		if p.ErrCode < 0 {
			return nil, getErr(p.ErrCode)
		}

		switch call.cmd {
		case proto.CmdMIncr:
			var r = make([]IncrReply, len(p.Kvs))
			for i := 0; i < len(r); i++ {
				r[i] = IncrReply{p.Kvs[i].ErrCode, p.Kvs[i].TableId,
					copyBytes(p.Kvs[i].RowKey), copyBytes(p.Kvs[i].ColKey),
					copyBytes(p.Kvs[i].Value), p.Kvs[i].Score}
			}
			return r, nil
		case proto.CmdMDel:
			var r = make([]DelReply, len(p.Kvs))
			for i := 0; i < len(r); i++ {
				r[i] = DelReply{p.Kvs[i].ErrCode, p.Kvs[i].TableId,
					copyBytes(p.Kvs[i].RowKey), copyBytes(p.Kvs[i].ColKey)}
			}
			return r, nil
		case proto.CmdMSet:
			var r = make([]SetReply, len(p.Kvs))
			for i := 0; i < len(r); i++ {
				r[i] = SetReply{p.Kvs[i].ErrCode, p.Kvs[i].TableId,
					copyBytes(p.Kvs[i].RowKey), copyBytes(p.Kvs[i].ColKey)}
			}
			return r, nil
		case proto.CmdMGet:
			var r = make([]GetReply, len(p.Kvs))
			for i := 0; i < len(r); i++ {
				r[i] = GetReply{p.Kvs[i].ErrCode, p.Kvs[i].TableId,
					copyBytes(p.Kvs[i].RowKey), copyBytes(p.Kvs[i].ColKey),
					copyBytes(p.Kvs[i].Value), p.Kvs[i].Score, p.Kvs[i].Cas}
			}
			return r, nil
		}
	}

	switch call.cmd {
	case proto.CmdScan:
		var p proto.PkgScanResp
		_, err := p.Decode(call.pkg)
		if err != nil {
			call.err = err
			return nil, call.err
		}

		if p.ErrCode < 0 {
			return nil, getErr(p.ErrCode)
		}

		var r ScanReply
		r.ctx = call.ctx.(scanContext)
		r.TableId = r.ctx.tableId
		r.RowKey = r.ctx.rowKey
		r.End = (p.PkgFlag&proto.FlagScanEnd != 0)
		r.Kvs = make([]ScanKV, len(p.Kvs))
		for i := 0; i < len(p.Kvs); i++ {
			r.Kvs[i] = ScanKV{copyBytes(p.Kvs[i].ColKey),
				copyBytes(p.Kvs[i].Value), p.Kvs[i].Score}
		}
		return r, nil

	case proto.CmdDump:
		var p proto.PkgDumpResp
		_, err := p.Decode(call.pkg)
		if err != nil {
			call.err = err
			return nil, call.err
		}

		if p.ErrCode < 0 {
			return nil, getErr(p.ErrCode)
		}

		var r DumpReply
		r.ctx = call.ctx.(dumpContext)
		r.ctx.lastSlotId = p.LastSlotId
		r.ctx.slotStart = (p.PkgFlag&proto.FlagDumpSlotStart != 0)
		r.End = (p.PkgFlag&proto.FlagDumpEnd != 0)
		r.Kvs = make([]DumpKV, len(p.Kvs))
		for i := 0; i < len(p.Kvs); i++ {
			r.Kvs[i] = DumpKV{p.Kvs[i].TableId, p.Kvs[i].ColSpace,
				copyBytes(p.Kvs[i].RowKey), copyBytes(p.Kvs[i].ColKey),
				copyBytes(p.Kvs[i].Value), p.Kvs[i].Score}
		}
		return r, nil
	}

	switch call.cmd {
	case proto.CmdSlaveOf:
		return call.replyInnerCtrl(&ctrl.PkgSlaveOf{})
	case proto.CmdMigrate:
		return call.replyInnerCtrl(&ctrl.PkgMigrate{})
	case proto.CmdSlaveSt:
		return call.replyInnerCtrl(&ctrl.PkgSlaveStatus{})
	case proto.CmdDelSlot:
		return call.replyInnerCtrl(&ctrl.PkgDelSlot{})
	}

	return nil, ErrUnknownCmd
}