func seekAndCopySyncKV(it *Iterator, p *proto.KeyValue) (uint8, uint16, bool) { p.CtrlFlag &^= 0xFF slotId, dbId, tableId, colSpace, rowKey, colKey := parseRawKey(it.Key()) switch colSpace { case proto.ColSpaceDefault: value, score := parseRawValue(it.Value()) p.SetValue(value) p.SetScore(score) case proto.ColSpaceScore1: it.Seek(getRawKey(dbId, tableId, colSpace+1, rowKey, nil)) if !it.Valid() { return dbId, slotId, false } return seekAndCopySyncKV(it, p) case proto.ColSpaceScore2: value, score := parseRawValue(it.Value()) p.SetValue(value) p.SetScore(score) } p.TableId = tableId p.SetColSpace(colSpace) p.RowKey = rowKey p.ColKey = colKey return dbId, slotId, true }
func (tbl *Table) getKV(rOpt *ReadOptions, zop bool, dbId uint8, kv *proto.KeyValue, wa *WriteAccess) error { kv.CtrlFlag &^= 0xFF // Clear all ctrl flags if kv.Cas > 0 && !wa.CheckKey(dbId, kv.TableId, kv.RowKey) { kv.SetErrCode(table.EcSlaveCas) return nil } var rawColSpace uint8 = proto.ColSpaceDefault if zop { rawColSpace = proto.ColSpaceScore2 } var rawKey = getRawKey(dbId, kv.TableId, rawColSpace, kv.RowKey, kv.ColKey) var err error kv.Value, err = tbl.db.Get(rOpt, rawKey) if err != nil { kv.SetErrCode(table.EcReadFail) return err } else if kv.Value == nil { // Key not exist kv.SetErrCode(table.EcNotExist) } else { // Key exists kv.Value, kv.Score = parseRawValue(kv.Value) if len(kv.Value) > 0 { kv.CtrlFlag |= proto.CtrlValue } if kv.Score != 0 { kv.CtrlFlag |= proto.CtrlScore } } if kv.Cas > 1 { var rawKey = getRawKey(dbId, kv.TableId, rawColSpace, kv.RowKey, kv.ColKey) var lck = tbl.tl.GetLock(rawKey) lck.Lock() kv.SetCas(lck.NewCas(rawKey)) lck.Unlock() } return nil }
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 (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) }
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++ } }
func (tbl *Table) incrKV(wb *WriteBatch, zop bool, dbId uint8, kv *proto.KeyValue, wa *WriteAccess) error { kv.CtrlFlag &^= 0xFF // Clear all ctrl flags if len(kv.RowKey) == 0 { kv.SetErrCode(table.EcInvRowKey) return nil } if !wa.CheckKey(dbId, kv.TableId, kv.RowKey) { kv.SetErrCode(table.EcWriteSlave) return nil } var rawColSpace uint8 = proto.ColSpaceDefault if zop { rawColSpace = proto.ColSpaceScore2 } var rawKey = getRawKey(dbId, kv.TableId, rawColSpace, kv.RowKey, kv.ColKey) var lck = tbl.tl.GetLock(rawKey) lck.Lock() defer lck.Unlock() if !wa.replication && kv.Cas != 0 { var cas = lck.GetCas(rawKey) if cas != kv.Cas { kv.SetErrCode(table.EcCasNotMatch) return nil } } lck.ClearCas(rawKey) var err error var newScore = kv.Score var oldVal []byte var oldScore int64 if zop { if wb == nil { wb = tbl.db.NewWriteBatch() defer wb.Destroy() } oldVal, err = tbl.db.Get(nil, rawKey) if err != nil { kv.SetErrCode(table.EcReadFail) return err } else if oldVal != nil { oldVal, oldScore = parseRawValue(oldVal) newScore += oldScore if newScore != oldScore { var scoreKey = getRawKey(dbId, kv.TableId, proto.ColSpaceScore1, kv.RowKey, newScoreColKey(oldScore, kv.ColKey)) tbl.db.Del(scoreKey, wb) } else { // nothing changed kv.SetValue(oldVal) kv.SetScore(newScore) return nil } } tbl.db.Put(rawKey, getRawValue(oldVal, newScore), wb) var scoreKey = getRawKey(dbId, kv.TableId, proto.ColSpaceScore1, kv.RowKey, newScoreColKey(newScore, kv.ColKey)) tbl.db.Put(scoreKey, getRawValue(oldVal, 0), wb) kv.SetValue(oldVal) kv.SetScore(newScore) err = tbl.db.Commit(wb) if err != nil { kv.SetErrCode(table.EcWriteFail) return err } } else { oldVal, err = tbl.db.Get(nil, rawKey) if err != nil { kv.SetErrCode(table.EcReadFail) return err } else if oldVal != nil { oldVal, oldScore = parseRawValue(oldVal) newScore += oldScore if newScore == oldScore { // nothing changed kv.SetValue(oldVal) kv.SetScore(newScore) return nil } } kv.SetValue(oldVal) kv.SetScore(newScore) err = tbl.db.Put(rawKey, getRawValue(oldVal, newScore), nil) if err != nil { kv.SetErrCode(table.EcWriteFail) return err } } return nil }