View Javadoc

1   /*
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  
20  package org.apache.hadoop.hbase.client;
21  
22  import static org.apache.hadoop.hbase.HBaseTestCase.assertByteEquals;
23  
24  import java.io.IOException;
25  import java.nio.ByteBuffer;
26  import java.util.Arrays;
27  import java.util.List;
28  
29  import junit.framework.TestCase;
30  
31  import org.apache.commons.logging.Log;
32  import org.apache.commons.logging.LogFactory;
33  import org.apache.hadoop.hbase.Cell;
34  import org.apache.hadoop.hbase.CellScanner;
35  import org.apache.hadoop.hbase.CellUtil;
36  import org.apache.hadoop.hbase.KeyValue;
37  import org.apache.hadoop.hbase.testclassification.SmallTests;
38  import org.apache.hadoop.hbase.util.Bytes;
39  import org.junit.experimental.categories.Category;
40  
41  @Category(SmallTests.class)
42  public class TestResult extends TestCase {
43  
44    private static final Log LOG = LogFactory.getLog(TestResult.class.getName());
45  
46    static KeyValue[] genKVs(final byte[] row, final byte[] family,
47                             final byte[] value,
48                      final long timestamp,
49                      final int cols) {
50      KeyValue [] kvs = new KeyValue[cols];
51  
52      for (int i = 0; i < cols ; i++) {
53        kvs[i] = new KeyValue(
54            row, family, Bytes.toBytes(i),
55            timestamp,
56            Bytes.add(value, Bytes.toBytes(i)));
57      }
58      return kvs;
59    }
60  
61    static final byte [] row = Bytes.toBytes("row");
62    static final byte [] family = Bytes.toBytes("family");
63    static final byte [] value = Bytes.toBytes("value");
64  
65    /**
66     * Run some tests to ensure Result acts like a proper CellScanner.
67     * @throws IOException
68     */
69    public void testResultAsCellScanner() throws IOException {
70      Cell [] cells = genKVs(row, family, value, 1, 10);
71      Arrays.sort(cells, KeyValue.COMPARATOR);
72      Result r = Result.create(cells);
73      assertSame(r, cells);
74      // Assert I run over same result multiple times.
75      assertSame(r.cellScanner(), cells);
76      assertSame(r.cellScanner(), cells);
77      // Assert we are not creating new object when doing cellscanner
78      assertTrue(r == r.cellScanner());
79    }
80  
81    private void assertSame(final CellScanner cellScanner, final Cell [] cells) throws IOException {
82      int count = 0;
83      while (cellScanner.advance()) {
84        assertTrue(cells[count].equals(cellScanner.current()));
85        count++;
86      }
87      assertEquals(cells.length, count);
88    }
89  
90    public void testBasicGetColumn() throws Exception {
91      KeyValue [] kvs = genKVs(row, family, value, 1, 100);
92  
93      Arrays.sort(kvs, KeyValue.COMPARATOR);
94  
95      Result r = Result.create(kvs);
96  
97      for (int i = 0; i < 100; ++i) {
98        final byte[] qf = Bytes.toBytes(i);
99  
100       List<Cell> ks = r.getColumnCells(family, qf);
101       assertEquals(1, ks.size());
102       assertTrue(CellUtil.matchingQualifier(ks.get(0), qf));
103       assertEquals(ks.get(0), r.getColumnLatestCell(family, qf));
104     }
105   }
106 
107   public void testMultiVersionGetColumn() throws Exception {
108     KeyValue [] kvs1 = genKVs(row, family, value, 1, 100);
109     KeyValue [] kvs2 = genKVs(row, family, value, 200, 100);
110 
111     KeyValue [] kvs = new KeyValue[kvs1.length+kvs2.length];
112     System.arraycopy(kvs1, 0, kvs, 0, kvs1.length);
113     System.arraycopy(kvs2, 0, kvs, kvs1.length, kvs2.length);
114 
115     Arrays.sort(kvs, KeyValue.COMPARATOR);
116 
117     Result r = Result.create(kvs);
118     for (int i = 0; i < 100; ++i) {
119       final byte[] qf = Bytes.toBytes(i);
120 
121       List<Cell> ks = r.getColumnCells(family, qf);
122       assertEquals(2, ks.size());
123       assertTrue(CellUtil.matchingQualifier(ks.get(0), qf));
124       assertEquals(200, ks.get(0).getTimestamp());
125       assertEquals(ks.get(0), r.getColumnLatestCell(family, qf));
126     }
127   }
128 
129   public void testBasicGetValue() throws Exception {
130     KeyValue [] kvs = genKVs(row, family, value, 1, 100);
131 
132     Arrays.sort(kvs, KeyValue.COMPARATOR);
133 
134     Result r = Result.create(kvs);
135 
136     for (int i = 0; i < 100; ++i) {
137       final byte[] qf = Bytes.toBytes(i);
138 
139       assertByteEquals(Bytes.add(value, Bytes.toBytes(i)), r.getValue(family, qf));
140       assertTrue(r.containsColumn(family, qf));
141     }
142   }
143 
144   public void testMultiVersionGetValue() throws Exception {
145     KeyValue [] kvs1 = genKVs(row, family, value, 1, 100);
146     KeyValue [] kvs2 = genKVs(row, family, value, 200, 100);
147 
148     KeyValue [] kvs = new KeyValue[kvs1.length+kvs2.length];
149     System.arraycopy(kvs1, 0, kvs, 0, kvs1.length);
150     System.arraycopy(kvs2, 0, kvs, kvs1.length, kvs2.length);
151 
152     Arrays.sort(kvs, KeyValue.COMPARATOR);
153 
154     Result r = Result.create(kvs);
155     for (int i = 0; i < 100; ++i) {
156       final byte[] qf = Bytes.toBytes(i);
157 
158       assertByteEquals(Bytes.add(value, Bytes.toBytes(i)), r.getValue(family, qf));
159       assertTrue(r.containsColumn(family, qf));
160     }
161   }
162 
163   public void testBasicLoadValue() throws Exception {
164     KeyValue [] kvs = genKVs(row, family, value, 1, 100);
165 
166     Arrays.sort(kvs, KeyValue.COMPARATOR);
167 
168     Result r = Result.create(kvs);
169     ByteBuffer loadValueBuffer = ByteBuffer.allocate(1024);
170 
171     for (int i = 0; i < 100; ++i) {
172       final byte[] qf = Bytes.toBytes(i);
173 
174       loadValueBuffer.clear();
175       r.loadValue(family, qf, loadValueBuffer);
176       loadValueBuffer.flip();
177       assertEquals(ByteBuffer.wrap(Bytes.add(value, Bytes.toBytes(i))), loadValueBuffer);
178       assertEquals(ByteBuffer.wrap(Bytes.add(value, Bytes.toBytes(i))),
179           r.getValueAsByteBuffer(family, qf));
180     }
181   }
182 
183   public void testMultiVersionLoadValue() throws Exception {
184     KeyValue [] kvs1 = genKVs(row, family, value, 1, 100);
185     KeyValue [] kvs2 = genKVs(row, family, value, 200, 100);
186 
187     KeyValue [] kvs = new KeyValue[kvs1.length+kvs2.length];
188     System.arraycopy(kvs1, 0, kvs, 0, kvs1.length);
189     System.arraycopy(kvs2, 0, kvs, kvs1.length, kvs2.length);
190 
191     Arrays.sort(kvs, KeyValue.COMPARATOR);
192 
193     ByteBuffer loadValueBuffer = ByteBuffer.allocate(1024);
194 
195     Result r = Result.create(kvs);
196     for (int i = 0; i < 100; ++i) {
197       final byte[] qf = Bytes.toBytes(i);
198 
199       loadValueBuffer.clear();
200       r.loadValue(family, qf, loadValueBuffer);
201       loadValueBuffer.flip();
202       assertEquals(ByteBuffer.wrap(Bytes.add(value, Bytes.toBytes(i))), loadValueBuffer);
203       assertEquals(ByteBuffer.wrap(Bytes.add(value, Bytes.toBytes(i))),
204           r.getValueAsByteBuffer(family, qf));
205     }
206   }
207 
208   /**
209    * Verify that Result.compareResults(...) behaves correctly.
210    */
211   public void testCompareResults() throws Exception {
212     byte [] value1 = Bytes.toBytes("value1");
213     byte [] qual = Bytes.toBytes("qual");
214 
215     KeyValue kv1 = new KeyValue(row, family, qual, value);
216     KeyValue kv2 = new KeyValue(row, family, qual, value1);
217 
218     Result r1 = Result.create(new KeyValue[] {kv1});
219     Result r2 = Result.create(new KeyValue[] {kv2});
220     // no exception thrown
221     Result.compareResults(r1, r1);
222     try {
223       // these are different (HBASE-4800)
224       Result.compareResults(r1, r2);
225       fail();
226     } catch (Exception x) {
227       assertTrue(x.getMessage().startsWith("This result was different:"));
228     }
229   }
230 
231 
232   /**
233    * Microbenchmark that compares {@link Result#getValue} and {@link Result#loadValue} performance.
234    *
235    * @throws Exception
236    */
237   public void doReadBenchmark() throws Exception {
238 
239     final int n = 5;
240     final int m = 100000000;
241 
242     StringBuilder valueSB = new StringBuilder();
243     for (int i = 0; i < 100; i++) {
244       valueSB.append((byte)(Math.random() * 10));
245     }
246 
247     StringBuilder rowSB = new StringBuilder();
248     for (int i = 0; i < 50; i++) {
249       rowSB.append((byte)(Math.random() * 10));
250     }
251 
252     KeyValue [] kvs = genKVs(Bytes.toBytes(rowSB.toString()), family,
253         Bytes.toBytes(valueSB.toString()), 1, n);
254     Arrays.sort(kvs, KeyValue.COMPARATOR);
255     ByteBuffer loadValueBuffer = ByteBuffer.allocate(1024);
256     Result r = Result.create(kvs);
257 
258     byte[][] qfs = new byte[n][Bytes.SIZEOF_INT];
259     for (int i = 0; i < n; ++i) {
260       System.arraycopy(qfs[i], 0, Bytes.toBytes(i), 0, Bytes.SIZEOF_INT);
261     }
262 
263     // warm up
264     for (int k = 0; k < 100000; k++) {
265       for (int i = 0; i < n; ++i) {
266         r.getValue(family, qfs[i]);
267         loadValueBuffer.clear();
268         r.loadValue(family, qfs[i], loadValueBuffer);
269         loadValueBuffer.flip();
270       }
271     }
272 
273     System.gc();
274     long start = System.nanoTime();
275     for (int k = 0; k < m; k++) {
276       for (int i = 0; i < n; ++i) {
277         loadValueBuffer.clear();
278         r.loadValue(family, qfs[i], loadValueBuffer);
279         loadValueBuffer.flip();
280       }
281     }
282     long stop = System.nanoTime();
283     System.out.println("loadValue(): " + (stop - start));
284 
285     System.gc();
286     start = System.nanoTime();
287     for (int k = 0; k < m; k++) {
288       for (int i = 0; i < n; i++) {
289         r.getValue(family, qfs[i]);
290       }
291     }
292     stop = System.nanoTime();
293     System.out.println("getValue():  " + (stop - start));
294   }
295 
296   /**
297    * Calls non-functional test methods.
298    *
299    * @param args
300    */
301   public static void main(String[] args) {
302     TestResult testResult = new TestResult();
303     try {
304       testResult.doReadBenchmark();
305     } catch (Exception e) {
306       LOG.error("Unexpected exception", e);
307     }
308   }
309 }