@@ -35,9 +35,13 @@ type Scanner struct {
3535 nextStartKey []byte
3636 endKey []byte
3737 eof bool
38+
39+ // Use for reverse scan.
40+ reverse bool
41+ nextEndKey []byte
3842}
3943
40- func newScanner (snapshot * tikvSnapshot , startKey []byte , endKey []byte , batchSize int ) (* Scanner , error ) {
44+ func newScanner (snapshot * tikvSnapshot , startKey []byte , endKey []byte , batchSize int , reverse bool ) (* Scanner , error ) {
4145 // It must be > 1. Otherwise scanner won't skipFirst.
4246 if batchSize <= 1 {
4347 batchSize = scanBatchSize
@@ -48,6 +52,8 @@ func newScanner(snapshot *tikvSnapshot, startKey []byte, endKey []byte, batchSiz
4852 valid : true ,
4953 nextStartKey : startKey ,
5054 endKey : endKey ,
55+ reverse : reverse ,
56+ nextEndKey : endKey ,
5157 }
5258 err := scanner .Next ()
5359 if kv .IsErrNotFound (err ) {
@@ -83,14 +89,15 @@ func (s *Scanner) Next() error {
8389 if ! s .valid {
8490 return errors .New ("scanner iterator is invalid" )
8591 }
92+ var err error
8693 for {
8794 s .idx ++
8895 if s .idx >= len (s .cache ) {
8996 if s .eof {
9097 s .Close ()
9198 return nil
9299 }
93- err : = s .getData (bo )
100+ err = s .getData (bo )
94101 if err != nil {
95102 s .Close ()
96103 return errors .Trace (err )
@@ -101,7 +108,8 @@ func (s *Scanner) Next() error {
101108 }
102109
103110 current := s .cache [s .idx ]
104- if len (s .endKey ) > 0 && kv .Key (current .Key ).Cmp (kv .Key (s .endKey )) >= 0 {
111+ if (! s .reverse && (len (s .endKey ) > 0 && kv .Key (current .Key ).Cmp (kv .Key (s .endKey )) >= 0 )) ||
112+ (s .reverse && len (s .nextStartKey ) > 0 && kv .Key (current .Key ).Cmp (kv .Key (s .nextStartKey )) < 0 ) {
105113 s .eof = true
106114 s .Close ()
107115 return nil
@@ -147,18 +155,34 @@ func (s *Scanner) resolveCurrentLock(bo *Backoffer, current *pb.KvPair) error {
147155func (s * Scanner ) getData (bo * Backoffer ) error {
148156 logutil .Logger (context .Background ()).Debug ("txn getData" ,
149157 zap .Binary ("nextStartKey" , s .nextStartKey ),
158+ zap .Binary ("nextEndKey" , s .nextEndKey ),
159+ zap .Bool ("reverse" , s .reverse ),
150160 zap .Uint64 ("txnStartTS" , s .startTS ()))
151161 sender := NewRegionRequestSender (s .snapshot .store .regionCache , s .snapshot .store .client )
152-
162+ var reqEndKey , reqStartKey []byte
163+ var loc * KeyLocation
164+ var err error
153165 for {
154- loc , err := s .snapshot .store .regionCache .LocateKey (bo , s .nextStartKey )
166+ if ! s .reverse {
167+ loc , err = s .snapshot .store .regionCache .LocateKey (bo , s .nextStartKey )
168+ } else {
169+ loc , err = s .snapshot .store .regionCache .LocateEndKey (bo , s .nextEndKey )
170+ }
155171 if err != nil {
156172 return errors .Trace (err )
157173 }
158174
159- reqEndKey := s .endKey
160- if len (reqEndKey ) > 0 && len (loc .EndKey ) > 0 && bytes .Compare (loc .EndKey , reqEndKey ) < 0 {
161- reqEndKey = loc .EndKey
175+ if ! s .reverse {
176+ reqEndKey = s .endKey
177+ if len (reqEndKey ) > 0 && len (loc .EndKey ) > 0 && bytes .Compare (loc .EndKey , reqEndKey ) < 0 {
178+ reqEndKey = loc .EndKey
179+ }
180+ } else {
181+ reqStartKey = s .nextStartKey
182+ if len (reqStartKey ) == 0 ||
183+ (len (loc .StartKey ) > 0 && bytes .Compare (loc .StartKey , reqStartKey ) > 0 ) {
184+ reqStartKey = loc .StartKey
185+ }
162186 }
163187
164188 req := & tikvrpc.Request {
@@ -175,6 +199,11 @@ func (s *Scanner) getData(bo *Backoffer) error {
175199 NotFillCache : s .snapshot .notFillCache ,
176200 },
177201 }
202+ if s .reverse {
203+ req .Scan .StartKey = s .nextEndKey
204+ req .Scan .EndKey = reqStartKey
205+ req .Scan .Reverse = true
206+ }
178207 resp , err := sender .SendReq (bo , req , loc .Region , ReadTimeoutMedium )
179208 if err != nil {
180209 return errors .Trace (err )
@@ -218,8 +247,13 @@ func (s *Scanner) getData(bo *Backoffer) error {
218247 if len (kvPairs ) < s .batchSize {
219248 // No more data in current Region. Next getData() starts
220249 // from current Region's endKey.
221- s .nextStartKey = loc .EndKey
222- if len (loc .EndKey ) == 0 || (len (s .endKey ) > 0 && kv .Key (s .nextStartKey ).Cmp (kv .Key (s .endKey )) >= 0 ) {
250+ if ! s .reverse {
251+ s .nextStartKey = loc .EndKey
252+ } else {
253+ s .nextEndKey = reqStartKey
254+ }
255+ if (! s .reverse && (len (loc .EndKey ) == 0 || (len (s .endKey ) > 0 && kv .Key (s .nextStartKey ).Cmp (kv .Key (s .endKey )) >= 0 ))) ||
256+ (s .reverse && (len (loc .StartKey ) == 0 || (len (s .nextStartKey ) > 0 && kv .Key (s .nextStartKey ).Cmp (kv .Key (s .nextEndKey )) >= 0 ))) {
223257 // Current Region is the last one.
224258 s .eof = true
225259 }
@@ -230,7 +264,11 @@ func (s *Scanner) getData(bo *Backoffer) error {
230264 // may get an empty response if the Region in fact does not have
231265 // more data.
232266 lastKey := kvPairs [len (kvPairs )- 1 ].GetKey ()
233- s .nextStartKey = kv .Key (lastKey ).Next ()
267+ if ! s .reverse {
268+ s .nextStartKey = kv .Key (lastKey ).Next ()
269+ } else {
270+ s .nextEndKey = kv .Key (lastKey )
271+ }
234272 return nil
235273 }
236274}
0 commit comments