2 * Copyright The Apache Software Foundation
4 * Licensed to the Apache Software Foundation (ASF) under one or more
5 * contributor license agreements. See the NOTICE file distributed with this
6 * work for additional information regarding copyright ownership. The ASF
7 * licenses this file to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16 * License for the specific language governing permissions and limitations
19 package org
.apache
.hadoop
.hbase
.regionserver
;
21 import java
.io
.IOException
;
22 import java
.util
.List
;
24 import org
.apache
.commons
.lang3
.NotImplementedException
;
25 import org
.apache
.hadoop
.hbase
.HConstants
;
26 import org
.apache
.yetus
.audience
.InterfaceAudience
;
27 import org
.apache
.hadoop
.hbase
.Cell
;
28 import org
.apache
.hadoop
.hbase
.CellComparator
;
29 import org
.apache
.hadoop
.hbase
.CellUtil
;
32 * ReversedKeyValueHeap is used for supporting reversed scanning. Compared with
33 * KeyValueHeap, its scanner comparator is a little different (see
34 * ReversedKVScannerComparator), all seek is backward seek(see
35 * {@link KeyValueScanner#backwardSeek}), and it will jump to the previous row
36 * if it is already at the end of one row when calling next().
38 @InterfaceAudience.Private
39 public class ReversedKeyValueHeap
extends KeyValueHeap
{
46 public ReversedKeyValueHeap(List
<?
extends KeyValueScanner
> scanners
,
47 CellComparator comparator
) throws IOException
{
48 super(scanners
, new ReversedKVScannerComparator(comparator
));
52 public boolean seek(Cell seekKey
) throws IOException
{
53 throw new IllegalStateException(
54 "seek cannot be called on ReversedKeyValueHeap");
58 public boolean reseek(Cell seekKey
) throws IOException
{
59 throw new IllegalStateException(
60 "reseek cannot be called on ReversedKeyValueHeap");
64 public boolean requestSeek(Cell key
, boolean forward
, boolean useBloom
)
66 throw new IllegalStateException(
67 "requestSeek cannot be called on ReversedKeyValueHeap");
71 public boolean seekToPreviousRow(Cell seekKey
) throws IOException
{
72 if (current
== null) {
78 KeyValueScanner scanner
;
79 while ((scanner
= heap
.poll()) != null) {
80 Cell topKey
= scanner
.peek();
81 if (comparator
.getComparator().compareRows(topKey
, seekKey
) < 0) {
82 // Row of Top KeyValue is before Seek row.
84 current
= pollRealKV();
85 return current
!= null;
88 if (!scanner
.seekToPreviousRow(seekKey
)) {
89 this.scannersForDelayedClose
.add(scanner
);
95 // Heap is returning empty, scanner is done
100 public boolean backwardSeek(Cell seekKey
) throws IOException
{
101 if (current
== null) {
107 KeyValueScanner scanner
;
108 while ((scanner
= heap
.poll()) != null) {
109 Cell topKey
= scanner
.peek();
110 if ((CellUtil
.matchingRows(seekKey
, topKey
) && comparator
111 .getComparator().compare(seekKey
, topKey
) <= 0)
112 || comparator
.getComparator().compareRows(seekKey
, topKey
) > 0) {
114 current
= pollRealKV();
115 return current
!= null;
117 if (!scanner
.backwardSeek(seekKey
)) {
118 this.scannersForDelayedClose
.add(scanner
);
127 public Cell
next() throws IOException
{
128 if (this.current
== null) {
131 Cell kvReturn
= this.current
.next();
132 Cell kvNext
= this.current
.peek();
134 || this.comparator
.kvComparator
.compareRows(kvNext
, kvReturn
) > 0) {
135 if (this.current
.seekToPreviousRow(kvReturn
)) {
136 this.heap
.add(this.current
);
138 this.scannersForDelayedClose
.add(this.current
);
141 this.current
= pollRealKV();
143 KeyValueScanner topScanner
= this.heap
.peek();
144 if (topScanner
!= null
145 && this.comparator
.compare(this.current
, topScanner
) > 0) {
146 this.heap
.add(this.current
);
148 this.current
= pollRealKV();
155 * In ReversedKVScannerComparator, we compare the row of scanners' peek values
156 * first, sort bigger one before the smaller one. Then compare the KeyValue if
157 * they have the equal row, sort smaller one before the bigger one
159 private static class ReversedKVScannerComparator
extends
160 KVScannerComparator
{
164 * @param kvComparator
166 public ReversedKVScannerComparator(CellComparator kvComparator
) {
171 public int compare(KeyValueScanner left
, KeyValueScanner right
) {
172 int rowComparison
= compareRows(left
.peek(), right
.peek());
173 if (rowComparison
!= 0) {
174 return -rowComparison
;
176 return super.compare(left
, right
);
180 * Compares rows of two KeyValue
183 * @return less than 0 if left is smaller, 0 if equal etc..
185 public int compareRows(Cell left
, Cell right
) {
186 return super.kvComparator
.compareRows(left
, right
);
191 public boolean seekToLastRow() throws IOException
{
192 throw new NotImplementedException(HConstants
.NOT_IMPLEMENTED
);