View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.apache.hadoop.hbase.codec.prefixtree.row;
20  
21  import java.io.ByteArrayInputStream;
22  import java.io.ByteArrayOutputStream;
23  import java.io.IOException;
24  import java.nio.ByteBuffer;
25  import java.util.Collection;
26  import java.util.List;
27  
28  import org.apache.hadoop.hbase.Cell;
29  import org.apache.hadoop.hbase.KeyValue;
30  import org.apache.hadoop.hbase.KeyValueUtil;
31  import org.apache.hadoop.hbase.codec.prefixtree.PrefixTreeBlockMeta;
32  import org.apache.hadoop.hbase.codec.prefixtree.decode.PrefixTreeArraySearcher;
33  import org.apache.hadoop.hbase.codec.prefixtree.encode.PrefixTreeEncoder;
34  import org.apache.hadoop.hbase.util.Bytes;
35  import org.junit.Assert;
36  import org.junit.Before;
37  import org.junit.Test;
38  import org.junit.runner.RunWith;
39  import org.junit.runners.Parameterized;
40  import org.junit.runners.Parameterized.Parameters;
41  
42  import com.google.common.collect.Lists;
43  
44  @RunWith(Parameterized.class)
45  public class TestRowEncoder {
46  
47    protected static int BLOCK_START = 7;
48  
49    @Parameters
50    public static Collection<Object[]> parameters() {
51      List<Object[]> parameters = Lists.newArrayList();
52      for (TestRowData testRows : TestRowData.InMemory.getAll()) {
53        parameters.add(new Object[] { testRows });
54      }
55      return parameters;
56    }
57  
58    protected TestRowData rows;
59    protected List<KeyValue> inputKvs;
60    protected boolean includeMemstoreTS = true;
61    protected ByteArrayOutputStream os;
62    protected PrefixTreeEncoder encoder;
63    protected int totalBytes;
64    protected PrefixTreeBlockMeta blockMetaWriter;
65    protected byte[] outputBytes;
66    protected ByteBuffer buffer;
67    protected ByteArrayInputStream is;
68    protected PrefixTreeBlockMeta blockMetaReader;
69    protected byte[] inputBytes;
70    protected PrefixTreeArraySearcher searcher;
71  
72    public TestRowEncoder(TestRowData testRows) {
73      this.rows = testRows;
74    }
75  
76  	@Before
77    public void compile() throws IOException {
78      // Always run with tags. But should also ensure that KVs without tags work fine
79      os = new ByteArrayOutputStream(1 << 20);
80      encoder = new PrefixTreeEncoder(os, includeMemstoreTS);
81  
82      inputKvs = rows.getInputs();
83      for (KeyValue kv : inputKvs) {
84        encoder.write(kv);
85      }
86      encoder.flush();
87      totalBytes = encoder.getTotalBytes();
88      blockMetaWriter = encoder.getBlockMeta();
89      outputBytes = os.toByteArray();
90  
91      // start reading, but save the assertions for @Test methods
92      buffer = ByteBuffer.wrap(outputBytes);
93      blockMetaReader = new PrefixTreeBlockMeta(buffer);
94  
95      searcher = new PrefixTreeArraySearcher(blockMetaReader, blockMetaReader.getRowTreeDepth(),
96          blockMetaReader.getMaxRowLength(), blockMetaReader.getMaxQualifierLength(),
97          blockMetaReader.getMaxTagsLength());
98      searcher.initOnBlock(blockMetaReader, outputBytes, includeMemstoreTS);
99    }
100 
101   @Test
102   public void testEncoderOutput() throws IOException {
103     Assert.assertEquals(totalBytes, outputBytes.length);
104     Assert.assertEquals(blockMetaWriter, blockMetaReader);
105   }
106 
107   @Test
108   public void testForwardScanner() {
109     int counter = -1;
110     while (searcher.advance()) {
111       ++counter;
112       KeyValue inputKv = rows.getInputs().get(counter);
113       KeyValue outputKv = KeyValueUtil.copyToNewKeyValue(searcher.current());
114       assertKeyAndValueEqual(inputKv, outputKv);
115     }
116     // assert same number of cells
117     Assert.assertEquals(rows.getInputs().size(), counter + 1);
118   }
119 
120 
121   /**
122    * probably not needed since testReverseScannerWithJitter() below is more thorough
123    */
124   @Test
125   public void testReverseScanner() {
126     searcher.positionAfterLastCell();
127     int counter = -1;
128     while (searcher.previous()) {
129       ++counter;
130       int oppositeIndex = rows.getInputs().size() - counter - 1;
131       KeyValue inputKv = rows.getInputs().get(oppositeIndex);
132       KeyValue outputKv = KeyValueUtil.copyToNewKeyValue(searcher.current());
133       assertKeyAndValueEqual(inputKv, outputKv);
134     }
135     Assert.assertEquals(rows.getInputs().size(), counter + 1);
136   }
137 
138 
139   /**
140    * Exercise the nubCellsRemain variable by calling next+previous.  NubCellsRemain is basically
141    * a special fan index.
142    */
143   @Test
144   public void testReverseScannerWithJitter() {
145     searcher.positionAfterLastCell();
146     int counter = -1;
147     while (true) {
148       boolean foundCell = searcher.previous();
149       if (!foundCell) {
150         break;
151       }
152       ++counter;
153 
154       // a next+previous should cancel out
155       if (!searcher.isAfterLast()) {
156         searcher.advance();
157         searcher.previous();
158       }
159 
160       int oppositeIndex = rows.getInputs().size() - counter - 1;
161       KeyValue inputKv = rows.getInputs().get(oppositeIndex);
162       KeyValue outputKv = KeyValueUtil.copyToNewKeyValue(searcher.current());
163       assertKeyAndValueEqual(inputKv, outputKv);
164     }
165     Assert.assertEquals(rows.getInputs().size(), counter + 1);
166   }
167 
168   @Test
169   public void testIndividualBlockMetaAssertions() {
170     rows.individualBlockMetaAssertions(blockMetaReader);
171   }
172 
173 
174 	/**************** helper **************************/
175 
176   protected void assertKeyAndValueEqual(Cell expected, Cell actual) {
177     // assert keys are equal (doesn't compare values)
178     Assert.assertEquals(expected, actual);
179     if (includeMemstoreTS) {
180       Assert.assertEquals(expected.getMvccVersion(), actual.getMvccVersion());
181     }
182     // assert values equal
183     Assert.assertTrue(Bytes.equals(expected.getValueArray(), expected.getValueOffset(),
184       expected.getValueLength(), actual.getValueArray(), actual.getValueOffset(),
185       actual.getValueLength()));
186   }
187 
188 }