1   /**
2    * Copyright 2008 The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  
21  package org.apache.hadoop.hbase;
22  
23  import org.apache.hadoop.fs.Path;
24  import org.apache.hadoop.hbase.client.Get;
25  import org.apache.hadoop.hbase.client.HTable;
26  import org.apache.hadoop.hbase.client.Put;
27  import org.apache.hadoop.hbase.client.Result;
28  import org.apache.hadoop.hbase.client.Scan;
29  import org.apache.hadoop.hbase.client.ResultScanner;
30  import org.apache.hadoop.hbase.regionserver.HRegion;
31  import org.apache.hadoop.hbase.util.Bytes;
32  
33  /**
34   * Regression test for HBASE-613
35   */
36  public class TestScanMultipleVersions extends HBaseClusterTestCase {
37    private final byte[] TABLE_NAME = Bytes.toBytes("TestScanMultipleVersions");
38    private final HRegionInfo[] INFOS = new HRegionInfo[2];
39    private final HRegion[] REGIONS = new HRegion[2];
40    private final byte[][] ROWS = new byte[][] {
41        Bytes.toBytes("row_0200"),
42        Bytes.toBytes("row_0800")
43    };
44    private final long[] TIMESTAMPS = new long[] {
45        100L,
46        1000L
47    };
48    private HTableDescriptor desc = null;
49  
50    @Override
51    protected void preHBaseClusterSetup() throws Exception {
52      testDir = new Path(conf.get(HConstants.HBASE_DIR));
53  
54      // Create table description
55  
56      this.desc = new HTableDescriptor(TABLE_NAME);
57      this.desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
58  
59      // Region 0 will contain the key range [,row_0500)
60      INFOS[0] = new HRegionInfo(this.desc, HConstants.EMPTY_START_ROW,
61          Bytes.toBytes("row_0500"));
62      // Region 1 will contain the key range [row_0500,)
63      INFOS[1] = new HRegionInfo(this.desc, Bytes.toBytes("row_0500"),
64          HConstants.EMPTY_END_ROW);
65  
66      // Create root and meta regions
67      createRootAndMetaRegions();
68      // Create the regions
69      for (int i = 0; i < REGIONS.length; i++) {
70        REGIONS[i] =
71          HRegion.createHRegion(this.INFOS[i], this.testDir, this.conf);
72        // Insert data
73        for (int j = 0; j < TIMESTAMPS.length; j++) {
74          Put put = new Put(ROWS[i], TIMESTAMPS[j], null);
75          put.add(HConstants.CATALOG_FAMILY, null, TIMESTAMPS[j],
76              Bytes.toBytes(TIMESTAMPS[j]));
77          REGIONS[i].put(put);
78        }
79        // Insert the region we created into the meta
80        HRegion.addRegionToMETA(meta, REGIONS[i]);
81        // Close region
82        REGIONS[i].close();
83        REGIONS[i].getLog().closeAndDelete();
84      }
85      // Close root and meta regions
86      closeRootAndMeta();
87    }
88  
89    /**
90     * @throws Exception
91     */
92    public void testScanMultipleVersions() throws Exception {
93      // At this point we have created multiple regions and both HDFS and HBase
94      // are running. There are 5 cases we have to test. Each is described below.
95      HTable t = new HTable(conf, TABLE_NAME);
96      for (int i = 0; i < ROWS.length; i++) {
97        for (int j = 0; j < TIMESTAMPS.length; j++) {
98          Get get = new Get(ROWS[i]);
99          get.addFamily(HConstants.CATALOG_FAMILY);
100         get.setTimeStamp(TIMESTAMPS[j]);
101         Result result = t.get(get);
102         int cellCount = 0;
103         for(@SuppressWarnings("unused")KeyValue kv : result.sorted()) {
104           cellCount++;
105         }
106         assertTrue(cellCount == 1);
107       }
108     }
109 
110     // Case 1: scan with LATEST_TIMESTAMP. Should get two rows
111     int count = 0;
112     Scan scan = new Scan();
113     scan.addFamily(HConstants.CATALOG_FAMILY);
114     ResultScanner s = t.getScanner(scan);
115     try {
116       for (Result rr = null; (rr = s.next()) != null;) {
117         System.out.println(rr.toString());
118         count += 1;
119       }
120       assertEquals("Number of rows should be 2", 2, count);
121     } finally {
122       s.close();
123     }
124 
125     // Case 2: Scan with a timestamp greater than most recent timestamp
126     // (in this case > 1000 and < LATEST_TIMESTAMP. Should get 2 rows.
127 
128     count = 0;
129     scan = new Scan();
130     scan.setTimeRange(1000L, Long.MAX_VALUE);
131     scan.addFamily(HConstants.CATALOG_FAMILY);
132 
133     s = t.getScanner(scan);
134     try {
135       while (s.next() != null) {
136         count += 1;
137       }
138       assertEquals("Number of rows should be 2", 2, count);
139     } finally {
140       s.close();
141     }
142 
143     // Case 3: scan with timestamp equal to most recent timestamp
144     // (in this case == 1000. Should get 2 rows.
145 
146     count = 0;
147     scan = new Scan();
148     scan.setTimeStamp(1000L);
149     scan.addFamily(HConstants.CATALOG_FAMILY);
150 
151     s = t.getScanner(scan);
152     try {
153       while (s.next() != null) {
154         count += 1;
155       }
156       assertEquals("Number of rows should be 2", 2, count);
157     } finally {
158       s.close();
159     }
160 
161     // Case 4: scan with timestamp greater than first timestamp but less than
162     // second timestamp (100 < timestamp < 1000). Should get 2 rows.
163 
164     count = 0;
165     scan = new Scan();
166     scan.setTimeRange(100L, 1000L);
167     scan.addFamily(HConstants.CATALOG_FAMILY);
168 
169     s = t.getScanner(scan);
170     try {
171       while (s.next() != null) {
172         count += 1;
173       }
174       assertEquals("Number of rows should be 2", 2, count);
175     } finally {
176       s.close();
177     }
178 
179     // Case 5: scan with timestamp equal to first timestamp (100)
180     // Should get 2 rows.
181 
182     count = 0;
183     scan = new Scan();
184     scan.setTimeStamp(100L);
185     scan.addFamily(HConstants.CATALOG_FAMILY);
186 
187     s = t.getScanner(scan);
188     try {
189       while (s.next() != null) {
190         count += 1;
191       }
192       assertEquals("Number of rows should be 2", 2, count);
193     } finally {
194       s.close();
195     }
196   }
197 }