1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.regionserver;
21
22 import java.io.IOException;
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.List;
26
27 import org.apache.hadoop.hbase.Cell;
28 import org.apache.hadoop.hbase.HBaseTestCase;
29 import org.apache.hadoop.hbase.KeyValue;
30 import org.apache.hadoop.hbase.testclassification.SmallTests;
31 import org.apache.hadoop.hbase.util.Bytes;
32 import org.apache.hadoop.hbase.util.CollectionBackedScanner;
33 import org.junit.Test;
34 import org.junit.experimental.categories.Category;
35
36 @Category(SmallTests.class)
37 public class TestKeyValueHeap extends HBaseTestCase {
38 private byte[] row1 = Bytes.toBytes("row1");
39 private byte[] fam1 = Bytes.toBytes("fam1");
40 private byte[] col1 = Bytes.toBytes("col1");
41 private byte[] data = Bytes.toBytes("data");
42
43 private byte[] row2 = Bytes.toBytes("row2");
44 private byte[] fam2 = Bytes.toBytes("fam2");
45 private byte[] col2 = Bytes.toBytes("col2");
46
47 private byte[] col3 = Bytes.toBytes("col3");
48 private byte[] col4 = Bytes.toBytes("col4");
49 private byte[] col5 = Bytes.toBytes("col5");
50
51
52 Cell kv111 = new KeyValue(row1, fam1, col1, data);
53 Cell kv112 = new KeyValue(row1, fam1, col2, data);
54 Cell kv113 = new KeyValue(row1, fam1, col3, data);
55 Cell kv114 = new KeyValue(row1, fam1, col4, data);
56 Cell kv115 = new KeyValue(row1, fam1, col5, data);
57 Cell kv121 = new KeyValue(row1, fam2, col1, data);
58 Cell kv122 = new KeyValue(row1, fam2, col2, data);
59 Cell kv211 = new KeyValue(row2, fam1, col1, data);
60 Cell kv212 = new KeyValue(row2, fam1, col2, data);
61 Cell kv213 = new KeyValue(row2, fam1, col3, data);
62
63 TestScanner s1 = new TestScanner(Arrays.asList(kv115, kv211, kv212));
64 TestScanner s2 = new TestScanner(Arrays.asList(kv111, kv112));
65 TestScanner s3 = new TestScanner(Arrays.asList(kv113, kv114, kv121, kv122, kv213));
66
67 List<KeyValueScanner> scanners = new ArrayList<KeyValueScanner>(Arrays.asList(s1, s2, s3));
68
69
70
71
72
73
74 public List<Cell> assertCells(List<Cell> expected, List<KeyValueScanner> scanners)
75 throws IOException {
76
77 KeyValueHeap kvh = new KeyValueHeap(scanners, KeyValue.COMPARATOR);
78
79 List<Cell> actual = new ArrayList<>();
80 while(kvh.peek() != null){
81 actual.add(kvh.next());
82 }
83
84 assertEquals(expected, actual);
85 return actual;
86 }
87
88 public void setUp() throws Exception {
89 super.setUp();
90 }
91
92 public void testSorted() throws IOException{
93
94
95
96
97 List<Cell> expected = Arrays.asList(
98 kv111, kv112, kv113, kv114, kv115, kv121, kv122, kv211, kv212, kv213);
99
100 List<Cell> actual = assertCells(expected, scanners);
101
102
103 for(int i=0; i<actual.size()-1; i++){
104 int ret = KeyValue.COMPARATOR.compare(actual.get(i), actual.get(i+1));
105 assertTrue(ret < 0);
106 }
107 }
108
109 public void testSeek() throws IOException {
110
111
112
113
114 List<Cell> expected = Arrays.asList(kv211);
115
116
117 KeyValueHeap kvh =
118 new KeyValueHeap(scanners, KeyValue.COMPARATOR);
119
120 Cell seekKv = new KeyValue(row2, fam1, null, null);
121 kvh.seek(seekKv);
122
123 List<Cell> actual = Arrays.asList(kvh.peek());
124
125 assertEquals("Expected = " + Arrays.toString(expected.toArray())
126 + "\n Actual = " + Arrays.toString(actual.toArray()), expected, actual);
127 }
128
129 public void testScannerLeak() throws IOException {
130
131
132 TestScanner s4 = new TestScanner(new ArrayList<Cell>());
133 scanners.add(s4);
134
135
136 KeyValueHeap kvh = new KeyValueHeap(scanners, KeyValue.COMPARATOR);
137
138 while(kvh.next() != null);
139
140 for(KeyValueScanner scanner : scanners) {
141 assertTrue(((TestScanner)scanner).isClosed());
142 }
143 }
144
145 public void testScannerException() throws IOException {
146
147
148 TestScanner s1 = new SeekTestScanner(Arrays.asList(kv115, kv211, kv212));
149 TestScanner s2 = new SeekTestScanner(Arrays.asList(kv111, kv112));
150 TestScanner s3 = new SeekTestScanner(Arrays.asList(kv113, kv114, kv121, kv122, kv213));
151 TestScanner s4 = new SeekTestScanner(new ArrayList<Cell>());
152
153 List<KeyValueScanner> scanners = new ArrayList<KeyValueScanner>(Arrays.asList(s1, s2, s3, s4));
154
155
156 KeyValueHeap kvh = new KeyValueHeap(scanners, KeyValue.COMPARATOR);
157
158 try {
159 for (KeyValueScanner scanner : scanners) {
160 ((SeekTestScanner) scanner).setRealSeekDone(false);
161 }
162 while (kvh.next() != null);
163
164 assertTrue(false);
165 } catch (IOException ioe) {
166 kvh.close();
167 }
168
169
170 for (KeyValueScanner scanner : scanners) {
171
172 assertTrue(((SeekTestScanner) scanner).isClosed());
173 assertEquals(((SeekTestScanner) scanner).getClosedNum(), 1);
174 }
175 }
176
177 @Test
178 public void testPriorityId() throws IOException {
179 Cell kv113A = new KeyValue(row1, fam1, col3, Bytes.toBytes("aaa"));
180 Cell kv113B = new KeyValue(row1, fam1, col3, Bytes.toBytes("bbb"));
181 {
182 TestScanner scan1 = new TestScanner(Arrays.asList(kv111, kv112, kv113A), 1);
183 TestScanner scan2 = new TestScanner(Arrays.asList(kv113B), 2);
184 List<Cell> expected = Arrays.asList(kv111, kv112, kv113B, kv113A);
185 assertCells(expected, new ArrayList<KeyValueScanner>(Arrays.asList(scan1, scan2)));
186 }
187 {
188 TestScanner scan1 = new TestScanner(Arrays.asList(kv111, kv112, kv113A), 2);
189 TestScanner scan2 = new TestScanner(Arrays.asList(kv113B), 1);
190 List<Cell> expected = Arrays.asList(kv111, kv112, kv113A, kv113B);
191 assertCells(expected, new ArrayList<KeyValueScanner>(Arrays.asList(scan1, scan2)));
192 }
193 }
194
195 private static class TestScanner extends CollectionBackedScanner {
196 private boolean closed = false;
197 private long scannerOrder = 0;
198
199 public TestScanner(List<Cell> list) {
200 super(list);
201 }
202
203 public TestScanner(List<Cell> list, long scannerOrder) {
204 this(list);
205 this.scannerOrder = scannerOrder;
206 }
207
208 @Override
209 public long getScannerOrder() {
210 return scannerOrder;
211 }
212
213 @Override
214 public void close(){
215 closed = true;
216 }
217
218 public boolean isClosed() {
219 return closed;
220 }
221 }
222
223 private static class SeekTestScanner extends TestScanner {
224 private int closedNum = 0;
225 private boolean realSeekDone = true;
226
227 public SeekTestScanner(List<Cell> list) {
228 super(list);
229 }
230
231 @Override
232 public void close() {
233 super.close();
234 closedNum++;
235 }
236
237 public int getClosedNum() {
238 return closedNum;
239 }
240
241 @Override
242 public boolean realSeekDone() {
243 return realSeekDone;
244 }
245
246 public void setRealSeekDone(boolean done) {
247 realSeekDone = done;
248 }
249
250 @Override
251 public void enforceSeek() throws IOException {
252 throw new IOException("enforceSeek must not be called on a " + "non-lazy scanner");
253 }
254 }
255 }