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  package org.apache.hadoop.hbase.regionserver;
20  
21  import java.io.IOException;
22  import java.util.ArrayList;
23  import java.util.List;
24  
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  import org.apache.hadoop.fs.FileSystem;
28  import org.apache.hadoop.fs.Path;
29  import org.apache.hadoop.hbase.TableName;
30  import org.apache.hadoop.hbase.HBaseTestCase;
31  import org.apache.hadoop.hbase.HConstants;
32  import org.apache.hadoop.hbase.HRegionInfo;
33  import org.apache.hadoop.hbase.HTableDescriptor;
34  import org.apache.hadoop.hbase.KeyValue;
35  import org.apache.hadoop.hbase.MediumTests;
36  import org.apache.hadoop.hbase.catalog.MetaEditor;
37  import org.apache.hadoop.hbase.client.Delete;
38  import org.apache.hadoop.hbase.client.Put;
39  import org.apache.hadoop.hbase.client.Result;
40  import org.apache.hadoop.hbase.client.Scan;
41  import org.apache.hadoop.hbase.client.Durability;
42  import org.apache.hadoop.hbase.util.Bytes;
43  import org.junit.experimental.categories.Category;
44  
45  /**
46   * TestGet is a medley of tests of get all done up as a single test.
47   * This class
48   */
49  @Category(MediumTests.class)
50  public class TestGetClosestAtOrBefore extends HBaseTestCase {
51    private static final Log LOG = LogFactory.getLog(TestGetClosestAtOrBefore.class);
52  
53    private static final byte[] T00 = Bytes.toBytes("000");
54    private static final byte[] T10 = Bytes.toBytes("010");
55    private static final byte[] T11 = Bytes.toBytes("011");
56    private static final byte[] T12 = Bytes.toBytes("012");
57    private static final byte[] T20 = Bytes.toBytes("020");
58    private static final byte[] T30 = Bytes.toBytes("030");
59    private static final byte[] T31 = Bytes.toBytes("031");
60    private static final byte[] T35 = Bytes.toBytes("035");
61    private static final byte[] T40 = Bytes.toBytes("040");
62  
63  
64  
65    public void testUsingMetaAndBinary() throws IOException {
66      FileSystem filesystem = FileSystem.get(conf);
67      Path rootdir = testDir;
68      // Up flush size else we bind up when we use default catalog flush of 16k.
69      HTableDescriptor.META_TABLEDESC.setMemStoreFlushSize(64 * 1024 * 1024);
70  
71      HRegion mr = HRegion.createHRegion(HRegionInfo.FIRST_META_REGIONINFO,
72        rootdir, this.conf, HTableDescriptor.META_TABLEDESC);
73      try {
74      // Write rows for three tables 'A', 'B', and 'C'.
75      for (char c = 'A'; c < 'D'; c++) {
76        HTableDescriptor htd = new HTableDescriptor(TableName.valueOf("" + c));
77        final int last = 128;
78        final int interval = 2;
79        for (int i = 0; i <= last; i += interval) {
80          HRegionInfo hri = new HRegionInfo(htd.getTableName(),
81            i == 0? HConstants.EMPTY_BYTE_ARRAY: Bytes.toBytes((byte)i),
82            i == last? HConstants.EMPTY_BYTE_ARRAY: Bytes.toBytes((byte)i + interval));
83  
84          Put put = MetaEditor.makePutFromRegionInfo(hri);
85          put.setDurability(Durability.SKIP_WAL);
86          mr.put(put);
87        }
88      }
89      InternalScanner s = mr.getScanner(new Scan());
90      try {
91        List<KeyValue> keys = new ArrayList<KeyValue>();
92        while(s.next(keys)) {
93          LOG.info(keys);
94          keys.clear();
95        }
96      } finally {
97        s.close();
98      }
99      findRow(mr, 'C', 44, 44);
100     findRow(mr, 'C', 45, 44);
101     findRow(mr, 'C', 46, 46);
102     findRow(mr, 'C', 43, 42);
103     mr.flushcache();
104     findRow(mr, 'C', 44, 44);
105     findRow(mr, 'C', 45, 44);
106     findRow(mr, 'C', 46, 46);
107     findRow(mr, 'C', 43, 42);
108     // Now delete 'C' and make sure I don't get entries from 'B'.
109     byte [] firstRowInC = HRegionInfo.createRegionName(
110         TableName.valueOf("" + 'C'),
111         HConstants.EMPTY_BYTE_ARRAY, HConstants.ZEROES, false);
112     Scan scan = new Scan(firstRowInC);
113     s = mr.getScanner(scan);
114     try {
115       List<KeyValue> keys = new ArrayList<KeyValue>();
116       while (s.next(keys)) {
117         mr.delete(new Delete(keys.get(0).getRow()));
118         keys.clear();
119       }
120     } finally {
121       s.close();
122     }
123     // Assert we get null back (pass -1).
124     findRow(mr, 'C', 44, -1);
125     findRow(mr, 'C', 45, -1);
126     findRow(mr, 'C', 46, -1);
127     findRow(mr, 'C', 43, -1);
128     mr.flushcache();
129     findRow(mr, 'C', 44, -1);
130     findRow(mr, 'C', 45, -1);
131     findRow(mr, 'C', 46, -1);
132     findRow(mr, 'C', 43, -1);
133     } finally {
134       if (mr != null) {
135         try {
136           mr.close();
137         } catch (Exception e) {
138           e.printStackTrace();
139         }
140         mr.getLog().closeAndDelete();
141       }
142     }
143   }
144 
145   /*
146    * @param mr
147    * @param table
148    * @param rowToFind
149    * @param answer Pass -1 if we're not to find anything.
150    * @return Row found.
151    * @throws IOException
152    */
153   private byte [] findRow(final HRegion mr, final char table,
154     final int rowToFind, final int answer)
155   throws IOException {
156     TableName tableb = TableName.valueOf("" + table);
157     // Find the row.
158     byte [] tofindBytes = Bytes.toBytes((short)rowToFind);
159     byte [] metaKey = HRegionInfo.createRegionName(
160         tableb, tofindBytes,
161       HConstants.NINES, false);
162     LOG.info("find=" + new String(metaKey));
163     Result r = mr.getClosestRowBefore(metaKey);
164     if (answer == -1) {
165       assertNull(r);
166       return null;
167     }
168     assertTrue(Bytes.compareTo(Bytes.toBytes((short)answer),
169       extractRowFromMetaRow(r.getRow())) == 0);
170     return r.getRow();
171   }
172 
173   private byte [] extractRowFromMetaRow(final byte [] b) {
174     int firstDelimiter = KeyValue.getDelimiter(b, 0, b.length,
175       HConstants.DELIMITER);
176     int lastDelimiter = KeyValue.getDelimiterInReverse(b, 0, b.length,
177       HConstants.DELIMITER);
178     int length = lastDelimiter - firstDelimiter - 1;
179     byte [] row = new byte[length];
180     System.arraycopy(b, firstDelimiter + 1, row, 0, length);
181     return row;
182   }
183 
184   /**
185    * Test file of multiple deletes and with deletes as final key.
186    * @see <a href="https://issues.apache.org/jira/browse/HBASE-751">HBASE-751</a>
187    */
188   public void testGetClosestRowBefore3() throws IOException{
189     HRegion region = null;
190     byte [] c0 = COLUMNS[0];
191     byte [] c1 = COLUMNS[1];
192     try {
193       HTableDescriptor htd = createTableDescriptor(getName());
194       region = createNewHRegion(htd, null, null);
195 
196       Put p = new Put(T00);
197       p.add(c0, c0, T00);
198       region.put(p);
199 
200       p = new Put(T10);
201       p.add(c0, c0, T10);
202       region.put(p);
203 
204       p = new Put(T20);
205       p.add(c0, c0, T20);
206       region.put(p);
207 
208       Result r = region.getClosestRowBefore(T20, c0);
209       assertTrue(Bytes.equals(T20, r.getRow()));
210 
211       Delete d = new Delete(T20);
212       d.deleteColumn(c0, c0);
213       region.delete(d);
214 
215       r = region.getClosestRowBefore(T20, c0);
216       assertTrue(Bytes.equals(T10, r.getRow()));
217 
218       p = new Put(T30);
219       p.add(c0, c0, T30);
220       region.put(p);
221 
222       r = region.getClosestRowBefore(T30, c0);
223       assertTrue(Bytes.equals(T30, r.getRow()));
224 
225       d = new Delete(T30);
226       d.deleteColumn(c0, c0);
227       region.delete(d);
228 
229       r = region.getClosestRowBefore(T30, c0);
230       assertTrue(Bytes.equals(T10, r.getRow()));
231       r = region.getClosestRowBefore(T31, c0);
232       assertTrue(Bytes.equals(T10, r.getRow()));
233 
234       region.flushcache();
235 
236       // try finding "010" after flush
237       r = region.getClosestRowBefore(T30, c0);
238       assertTrue(Bytes.equals(T10, r.getRow()));
239       r = region.getClosestRowBefore(T31, c0);
240       assertTrue(Bytes.equals(T10, r.getRow()));
241 
242       // Put into a different column family.  Should make it so I still get t10
243       p = new Put(T20);
244       p.add(c1, c1, T20);
245       region.put(p);
246 
247       r = region.getClosestRowBefore(T30, c0);
248       assertTrue(Bytes.equals(T10, r.getRow()));
249       r = region.getClosestRowBefore(T31, c0);
250       assertTrue(Bytes.equals(T10, r.getRow()));
251 
252       region.flushcache();
253 
254       r = region.getClosestRowBefore(T30, c0);
255       assertTrue(Bytes.equals(T10, r.getRow()));
256       r = region.getClosestRowBefore(T31, c0);
257       assertTrue(Bytes.equals(T10, r.getRow()));
258 
259       // Now try combo of memcache and mapfiles.  Delete the t20 COLUMS[1]
260       // in memory; make sure we get back t10 again.
261       d = new Delete(T20);
262       d.deleteColumn(c1, c1);
263       region.delete(d);
264       r = region.getClosestRowBefore(T30, c0);
265       assertTrue(Bytes.equals(T10, r.getRow()));
266 
267       // Ask for a value off the end of the file.  Should return t10.
268       r = region.getClosestRowBefore(T31, c0);
269       assertTrue(Bytes.equals(T10, r.getRow()));
270       region.flushcache();
271       r = region.getClosestRowBefore(T31, c0);
272       assertTrue(Bytes.equals(T10, r.getRow()));
273 
274       // Ok.  Let the candidate come out of hfile but have delete of
275       // the candidate be in memory.
276       p = new Put(T11);
277       p.add(c0, c0, T11);
278       region.put(p);
279       d = new Delete(T10);
280       d.deleteColumn(c1, c1);
281       r = region.getClosestRowBefore(T12, c0);
282       assertTrue(Bytes.equals(T11, r.getRow()));
283     } finally {
284       if (region != null) {
285         try {
286           region.close();
287         } catch (Exception e) {
288           e.printStackTrace();
289         }
290         region.getLog().closeAndDelete();
291       }
292     }
293   }
294 
295   /** For HBASE-694 */
296   public void testGetClosestRowBefore2() throws IOException{
297     HRegion region = null;
298     byte [] c0 = COLUMNS[0];
299     try {
300       HTableDescriptor htd = createTableDescriptor(getName());
301       region = createNewHRegion(htd, null, null);
302 
303       Put p = new Put(T10);
304       p.add(c0, c0, T10);
305       region.put(p);
306 
307       p = new Put(T30);
308       p.add(c0, c0, T30);
309       region.put(p);
310 
311       p = new Put(T40);
312       p.add(c0, c0, T40);
313       region.put(p);
314 
315       // try finding "035"
316       Result r = region.getClosestRowBefore(T35, c0);
317       assertTrue(Bytes.equals(T30, r.getRow()));
318 
319       region.flushcache();
320 
321       // try finding "035"
322       r = region.getClosestRowBefore(T35, c0);
323       assertTrue(Bytes.equals(T30, r.getRow()));
324 
325       p = new Put(T20);
326       p.add(c0, c0, T20);
327       region.put(p);
328 
329       // try finding "035"
330       r = region.getClosestRowBefore(T35, c0);
331       assertTrue(Bytes.equals(T30, r.getRow()));
332 
333       region.flushcache();
334 
335       // try finding "035"
336       r = region.getClosestRowBefore(T35, c0);
337       assertTrue(Bytes.equals(T30, r.getRow()));
338     } finally {
339       if (region != null) {
340         try {
341           region.close();
342         } catch (Exception e) {
343           e.printStackTrace();
344         }
345         region.getLog().closeAndDelete();
346       }
347     }
348   }
349 
350 }
351