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.client;
20  
21  import static org.junit.Assert.assertArrayEquals;
22  import static org.junit.Assert.assertEquals;
23  import static org.junit.Assert.assertFalse;
24  import static org.junit.Assert.assertNotNull;
25  import static org.junit.Assert.assertNull;
26  import static org.junit.Assert.assertSame;
27  import static org.junit.Assert.assertTrue;
28  import static org.junit.Assert.fail;
29  
30  import java.io.IOException;
31  import java.lang.reflect.Method;
32  import java.util.ArrayList;
33  import java.util.Arrays;
34  import java.util.Collections;
35  import java.util.HashSet;
36  import java.util.Iterator;
37  import java.util.List;
38  import java.util.Map;
39  import java.util.NavigableMap;
40  import java.util.UUID;
41  import java.util.concurrent.Callable;
42  import java.util.concurrent.ExecutorService;
43  import java.util.concurrent.Executors;
44  import java.util.concurrent.atomic.AtomicReference;
45  
46  import org.apache.log4j.Level;
47  import org.apache.commons.lang.ArrayUtils;
48  import org.apache.commons.logging.Log;
49  import org.apache.commons.logging.LogFactory;
50  import org.apache.hadoop.conf.Configuration;
51  import org.apache.hadoop.hbase.Abortable;
52  import org.apache.hadoop.hbase.Cell;
53  import org.apache.hadoop.hbase.CellUtil;
54  import org.apache.hadoop.hbase.HBaseTestingUtility;
55  import org.apache.hadoop.hbase.HColumnDescriptor;
56  import org.apache.hadoop.hbase.HConstants;
57  import org.apache.hadoop.hbase.HRegionInfo;
58  import org.apache.hadoop.hbase.HRegionLocation;
59  import org.apache.hadoop.hbase.HTableDescriptor;
60  import org.apache.hadoop.hbase.KeyValue;
61  import org.apache.hadoop.hbase.MiniHBaseCluster;
62  import org.apache.hadoop.hbase.RegionLocations;
63  import org.apache.hadoop.hbase.ServerName;
64  import org.apache.hadoop.hbase.TableName;
65  import org.apache.hadoop.hbase.Waiter;
66  import org.apache.hadoop.hbase.client.metrics.ScanMetrics;
67  import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
68  import org.apache.hadoop.hbase.coprocessor.MultiRowMutationEndpoint;
69  import org.apache.hadoop.hbase.filter.BinaryComparator;
70  import org.apache.hadoop.hbase.filter.CompareFilter;
71  import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
72  import org.apache.hadoop.hbase.filter.Filter;
73  import org.apache.hadoop.hbase.filter.FilterList;
74  import org.apache.hadoop.hbase.filter.FirstKeyOnlyFilter;
75  import org.apache.hadoop.hbase.filter.InclusiveStopFilter;
76  import org.apache.hadoop.hbase.filter.KeyOnlyFilter;
77  import org.apache.hadoop.hbase.filter.LongComparator;
78  import org.apache.hadoop.hbase.filter.PrefixFilter;
79  import org.apache.hadoop.hbase.filter.QualifierFilter;
80  import org.apache.hadoop.hbase.filter.RegexStringComparator;
81  import org.apache.hadoop.hbase.filter.RowFilter;
82  import org.apache.hadoop.hbase.filter.SingleColumnValueFilter;
83  import org.apache.hadoop.hbase.filter.WhileMatchFilter;
84  import org.apache.hadoop.hbase.io.hfile.BlockCache;
85  import org.apache.hadoop.hbase.io.hfile.CacheConfig;
86  import org.apache.hadoop.hbase.ipc.CoprocessorRpcChannel;
87  import org.apache.hadoop.hbase.master.HMaster;
88  import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
89  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos;
90  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutationProto;
91  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutationProto.MutationType;
92  import org.apache.hadoop.hbase.protobuf.generated.MultiRowMutationProtos.MultiRowMutationService;
93  import org.apache.hadoop.hbase.protobuf.generated.MultiRowMutationProtos.MutateRowsRequest;
94  import org.apache.hadoop.hbase.regionserver.HRegion;
95  import org.apache.hadoop.hbase.regionserver.HRegionServer;
96  import org.apache.hadoop.hbase.regionserver.NoSuchColumnFamilyException;
97  import org.apache.hadoop.hbase.regionserver.Region;
98  import org.apache.hadoop.hbase.regionserver.Store;
99  import org.apache.hadoop.hbase.testclassification.LargeTests;
100 import org.apache.hadoop.hbase.util.Bytes;
101 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
102 import org.apache.hadoop.hbase.util.Pair;
103 import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
104 import org.apache.log4j.AppenderSkeleton;
105 import org.apache.log4j.Logger;
106 import org.apache.log4j.spi.LoggingEvent;
107 import org.junit.After;
108 import org.junit.AfterClass;
109 import org.junit.Before;
110 import org.junit.BeforeClass;
111 import org.junit.Ignore;
112 import org.junit.Test;
113 import org.junit.experimental.categories.Category;
114 /**
115  * Run tests that use the HBase clients; {@link HTable}.
116  * Sets up the HBase mini cluster once at start and runs through all client tests.
117  * Each creates a table named for the method and does its stuff against that.
118  */
119 @Category(LargeTests.class)
120 @SuppressWarnings ("deprecation")
121 public class TestFromClientSide {
122   private static final Log LOG = LogFactory.getLog(TestFromClientSide.class);
123   protected final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
124   private static byte [] ROW = Bytes.toBytes("testRow");
125   private static byte [] FAMILY = Bytes.toBytes("testFamily");
126   private static byte [] QUALIFIER = Bytes.toBytes("testQualifier");
127   private static byte [] VALUE = Bytes.toBytes("testValue");
128   protected static int SLAVES = 3;
129 
130   /**
131    * @throws java.lang.Exception
132    */
133   @BeforeClass
134   public static void setUpBeforeClass() throws Exception {
135     // Uncomment the following lines if more verbosity is needed for
136     // debugging (see HBASE-12285 for details).
137     //((Log4JLogger)RpcServer.LOG).getLogger().setLevel(Level.ALL);
138     //((Log4JLogger)RpcClient.LOG).getLogger().setLevel(Level.ALL);
139     //((Log4JLogger)ScannerCallable.LOG).getLogger().setLevel(Level.ALL);
140     Configuration conf = TEST_UTIL.getConfiguration();
141     conf.setStrings(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY,
142         MultiRowMutationEndpoint.class.getName());
143     conf.setBoolean("hbase.table.sanity.checks", true); // enable for below tests
144     // We need more than one region server in this test
145     TEST_UTIL.startMiniCluster(SLAVES);
146   }
147 
148   /**
149    * @throws java.lang.Exception
150    */
151   @AfterClass
152   public static void tearDownAfterClass() throws Exception {
153     TEST_UTIL.shutdownMiniCluster();
154   }
155 
156   /**
157    * @throws java.lang.Exception
158    */
159   @Before
160   public void setUp() throws Exception {
161     // Nothing to do.
162   }
163 
164   /**
165    * @throws java.lang.Exception
166    */
167   @After
168   public void tearDown() throws Exception {
169     // Nothing to do.
170   }
171 
172   /**
173    * Basic client side validation of HBASE-4536
174    */
175    @Test
176    public void testKeepDeletedCells() throws Exception {
177      final TableName TABLENAME = TableName.valueOf("testKeepDeletesCells");
178      final byte[] FAMILY = Bytes.toBytes("family");
179      final byte[] C0 = Bytes.toBytes("c0");
180 
181      final byte[] T1 = Bytes.toBytes("T1");
182      final byte[] T2 = Bytes.toBytes("T2");
183      final byte[] T3 = Bytes.toBytes("T3");
184      HColumnDescriptor hcd = new HColumnDescriptor(FAMILY)
185          .setKeepDeletedCells(true).setMaxVersions(3);
186 
187      HTableDescriptor desc = new HTableDescriptor(TABLENAME);
188      desc.addFamily(hcd);
189      TEST_UTIL.getHBaseAdmin().createTable(desc);
190      Configuration c = TEST_UTIL.getConfiguration();
191      Table h = new HTable(c, TABLENAME);
192 
193      long ts = System.currentTimeMillis();
194      Put p = new Put(T1, ts);
195      p.add(FAMILY, C0, T1);
196      h.put(p);
197      p = new Put(T1, ts+2);
198      p.add(FAMILY, C0, T2);
199      h.put(p);
200      p = new Put(T1, ts+4);
201      p.add(FAMILY, C0, T3);
202      h.put(p);
203 
204      Delete d = new Delete(T1, ts+3);
205      h.delete(d);
206 
207      d = new Delete(T1, ts+3);
208      d.deleteColumns(FAMILY, C0, ts+3);
209      h.delete(d);
210 
211      Get g = new Get(T1);
212      // does *not* include the delete
213      g.setTimeRange(0, ts+3);
214      Result r = h.get(g);
215      assertArrayEquals(T2, r.getValue(FAMILY, C0));
216 
217      Scan s = new Scan(T1);
218      s.setTimeRange(0, ts+3);
219      s.setMaxVersions();
220      ResultScanner scanner = h.getScanner(s);
221      Cell[] kvs = scanner.next().rawCells();
222      assertArrayEquals(T2, CellUtil.cloneValue(kvs[0]));
223      assertArrayEquals(T1, CellUtil.cloneValue(kvs[1]));
224      scanner.close();
225 
226      s = new Scan(T1);
227      s.setRaw(true);
228      s.setMaxVersions();
229      scanner = h.getScanner(s);
230      kvs = scanner.next().rawCells();
231      assertTrue(CellUtil.isDeleteFamily(kvs[0]));
232      assertArrayEquals(T3, CellUtil.cloneValue(kvs[1]));
233      assertTrue(CellUtil.isDelete(kvs[2]));
234      assertArrayEquals(T2, CellUtil.cloneValue(kvs[3]));
235      assertArrayEquals(T1, CellUtil.cloneValue(kvs[4]));
236      scanner.close();
237      h.close();
238    }
239 
240     /**
241     * Basic client side validation of HBASE-10118
242     */
243    @Test
244    public void testPurgeFutureDeletes() throws Exception {
245      final TableName TABLENAME = TableName.valueOf("testPurgeFutureDeletes");
246      final byte[] ROW = Bytes.toBytes("row");
247      final byte[] FAMILY = Bytes.toBytes("family");
248      final byte[] COLUMN = Bytes.toBytes("column");
249      final byte[] VALUE = Bytes.toBytes("value");
250 
251      Table table = TEST_UTIL.createTable(TABLENAME, FAMILY);
252 
253      // future timestamp
254      long ts = System.currentTimeMillis() * 2;
255      Put put = new Put(ROW, ts);
256      put.add(FAMILY, COLUMN, VALUE);
257      table.put(put);
258 
259      Get get = new Get(ROW);
260      Result result = table.get(get);
261      assertArrayEquals(VALUE, result.getValue(FAMILY, COLUMN));
262 
263      Delete del = new Delete(ROW);
264      del.deleteColumn(FAMILY, COLUMN, ts);
265      table.delete(del);
266 
267      get = new Get(ROW);
268      result = table.get(get);
269      assertNull(result.getValue(FAMILY, COLUMN));
270 
271      // major compaction, purged future deletes
272      TEST_UTIL.getHBaseAdmin().flush(TABLENAME);
273      TEST_UTIL.getHBaseAdmin().majorCompact(TABLENAME);
274 
275      // waiting for the major compaction to complete
276      TEST_UTIL.waitFor(6000, new Waiter.Predicate<IOException>() {
277        @Override
278        public boolean evaluate() throws IOException {
279          return TEST_UTIL.getHBaseAdmin().getCompactionState(TABLENAME) ==
280              AdminProtos.GetRegionInfoResponse.CompactionState.NONE;
281        }
282      });
283 
284      put = new Put(ROW, ts);
285      put.add(FAMILY, COLUMN, VALUE);
286      table.put(put);
287 
288      get = new Get(ROW);
289      result = table.get(get);
290      assertArrayEquals(VALUE, result.getValue(FAMILY, COLUMN));
291 
292      table.close();
293    }
294 
295    /**
296     * @deprecated Tests deprecated functionality. Remove when we are past 1.0.
297     * @throws Exception
298     */
299    @Deprecated
300    @Test
301    public void testSharedZooKeeper() throws Exception {
302      Configuration newConfig = new Configuration(TEST_UTIL.getConfiguration());
303      newConfig.set(HConstants.HBASE_CLIENT_INSTANCE_ID, "12345");
304 
305      // First with a simple ZKW
306      ZooKeeperWatcher z0 = new ZooKeeperWatcher(
307        newConfig, "hconnection", new Abortable() {
308        @Override public void abort(String why, Throwable e) {}
309        @Override public boolean isAborted() {return false;}
310      });
311      z0.getRecoverableZooKeeper().getZooKeeper().exists("/oldZooKeeperWatcher", false);
312      z0.close();
313 
314      // Then a ZooKeeperKeepAliveConnection
315      ConnectionManager.HConnectionImplementation connection1 =
316        (ConnectionManager.HConnectionImplementation)
317          HConnectionManager.getConnection(newConfig);
318 
319      ZooKeeperKeepAliveConnection z1 = connection1.getKeepAliveZooKeeperWatcher();
320      z1.getRecoverableZooKeeper().getZooKeeper().exists("/z1", false);
321 
322      z1.close();
323 
324      // will still work, because the real connection is not closed yet
325      // Not do be done in real code
326      z1.getRecoverableZooKeeper().getZooKeeper().exists("/z1afterclose", false);
327 
328 
329      ZooKeeperKeepAliveConnection z2 = connection1.getKeepAliveZooKeeperWatcher();
330      assertTrue(
331        "ZooKeeperKeepAliveConnection equals on same connection", z1 == z2);
332 
333 
334 
335      Configuration newConfig2 = new Configuration(TEST_UTIL.getConfiguration());
336      newConfig2.set(HConstants.HBASE_CLIENT_INSTANCE_ID, "6789");
337      ConnectionManager.HConnectionImplementation connection2 =
338        (ConnectionManager.HConnectionImplementation)
339          HConnectionManager.getConnection(newConfig2);
340 
341      assertTrue("connections should be different ", connection1 != connection2);
342 
343      ZooKeeperKeepAliveConnection z3 = connection2.getKeepAliveZooKeeperWatcher();
344      assertTrue(
345        "ZooKeeperKeepAliveConnection should be different" +
346          " on different connections", z1 != z3);
347 
348      // Bypass the private access
349      Method m = ConnectionManager.HConnectionImplementation.class.
350        getDeclaredMethod("closeZooKeeperWatcher");
351      m.setAccessible(true);
352      m.invoke(connection2);
353 
354      ZooKeeperKeepAliveConnection z4 = connection2.getKeepAliveZooKeeperWatcher();
355      assertTrue(
356        "ZooKeeperKeepAliveConnection should be recreated" +
357          " when previous connections was closed"
358        , z3 != z4);
359 
360 
361      z2.getRecoverableZooKeeper().getZooKeeper().exists("/z2", false);
362      z4.getRecoverableZooKeeper().getZooKeeper().exists("/z4", false);
363 
364 
365      HConnectionManager.deleteConnection(newConfig);
366      try {
367        z2.getRecoverableZooKeeper().getZooKeeper().exists("/z2", false);
368        assertTrue("We should not have a valid connection for z2", false);
369      } catch (Exception e){
370      }
371 
372      z4.getRecoverableZooKeeper().getZooKeeper().exists("/z4", false);
373      // We expect success here.
374 
375 
376      HConnectionManager.deleteConnection(newConfig2);
377      try {
378        z4.getRecoverableZooKeeper().getZooKeeper().exists("/z4", false);
379        assertTrue("We should not have a valid connection for z4", false);
380      } catch (Exception e){
381      }
382    }
383 
384 
385   /**
386    * Verifies that getConfiguration returns the same Configuration object used
387    * to create the HTable instance.
388    */
389   @Test
390   public void testGetConfiguration() throws Exception {
391     TableName TABLE = TableName.valueOf("testGetConfiguration");
392     byte[][] FAMILIES = new byte[][] { Bytes.toBytes("foo") };
393     Configuration conf = TEST_UTIL.getConfiguration();
394     Table table = TEST_UTIL.createTable(TABLE, FAMILIES, conf);
395     assertSame(conf, table.getConfiguration());
396   }
397 
398   /**
399    * Test from client side of an involved filter against a multi family that
400    * involves deletes.
401    *
402    * @throws Exception
403    */
404   @Test
405   public void testWeirdCacheBehaviour() throws Exception {
406     TableName TABLE = TableName.valueOf("testWeirdCacheBehaviour");
407     byte [][] FAMILIES = new byte[][] { Bytes.toBytes("trans-blob"),
408         Bytes.toBytes("trans-type"), Bytes.toBytes("trans-date"),
409         Bytes.toBytes("trans-tags"), Bytes.toBytes("trans-group") };
410     HTable ht = TEST_UTIL.createTable(TABLE, FAMILIES);
411     String value = "this is the value";
412     String value2 = "this is some other value";
413     String keyPrefix1 = UUID.randomUUID().toString();
414     String keyPrefix2 = UUID.randomUUID().toString();
415     String keyPrefix3 = UUID.randomUUID().toString();
416     putRows(ht, 3, value, keyPrefix1);
417     putRows(ht, 3, value, keyPrefix2);
418     putRows(ht, 3, value, keyPrefix3);
419     ht.flushCommits();
420     putRows(ht, 3, value2, keyPrefix1);
421     putRows(ht, 3, value2, keyPrefix2);
422     putRows(ht, 3, value2, keyPrefix3);
423     Table table = new HTable(TEST_UTIL.getConfiguration(), TABLE);
424     System.out.println("Checking values for key: " + keyPrefix1);
425     assertEquals("Got back incorrect number of rows from scan", 3,
426         getNumberOfRows(keyPrefix1, value2, table));
427     System.out.println("Checking values for key: " + keyPrefix2);
428     assertEquals("Got back incorrect number of rows from scan", 3,
429         getNumberOfRows(keyPrefix2, value2, table));
430     System.out.println("Checking values for key: " + keyPrefix3);
431     assertEquals("Got back incorrect number of rows from scan", 3,
432         getNumberOfRows(keyPrefix3, value2, table));
433     deleteColumns(ht, value2, keyPrefix1);
434     deleteColumns(ht, value2, keyPrefix2);
435     deleteColumns(ht, value2, keyPrefix3);
436     System.out.println("Starting important checks.....");
437     assertEquals("Got back incorrect number of rows from scan: " + keyPrefix1,
438       0, getNumberOfRows(keyPrefix1, value2, table));
439     assertEquals("Got back incorrect number of rows from scan: " + keyPrefix2,
440       0, getNumberOfRows(keyPrefix2, value2, table));
441     assertEquals("Got back incorrect number of rows from scan: " + keyPrefix3,
442       0, getNumberOfRows(keyPrefix3, value2, table));
443     ht.setScannerCaching(0);
444     assertEquals("Got back incorrect number of rows from scan", 0,
445       getNumberOfRows(keyPrefix1, value2, table)); ht.setScannerCaching(100);
446     assertEquals("Got back incorrect number of rows from scan", 0,
447       getNumberOfRows(keyPrefix2, value2, table));
448   }
449 
450   private void deleteColumns(Table ht, String value, String keyPrefix)
451   throws IOException {
452     ResultScanner scanner = buildScanner(keyPrefix, value, ht);
453     Iterator<Result> it = scanner.iterator();
454     int count = 0;
455     while (it.hasNext()) {
456       Result result = it.next();
457       Delete delete = new Delete(result.getRow());
458       delete.deleteColumn(Bytes.toBytes("trans-tags"), Bytes.toBytes("qual2"));
459       ht.delete(delete);
460       count++;
461     }
462     assertEquals("Did not perform correct number of deletes", 3, count);
463   }
464 
465   private int getNumberOfRows(String keyPrefix, String value, Table ht)
466       throws Exception {
467     ResultScanner resultScanner = buildScanner(keyPrefix, value, ht);
468     Iterator<Result> scanner = resultScanner.iterator();
469     int numberOfResults = 0;
470     while (scanner.hasNext()) {
471       Result result = scanner.next();
472       System.out.println("Got back key: " + Bytes.toString(result.getRow()));
473       for (Cell kv : result.rawCells()) {
474         System.out.println("kv=" + kv.toString() + ", "
475             + Bytes.toString(CellUtil.cloneValue(kv)));
476       }
477       numberOfResults++;
478     }
479     return numberOfResults;
480   }
481 
482   private ResultScanner buildScanner(String keyPrefix, String value, Table ht)
483       throws IOException {
484     // OurFilterList allFilters = new OurFilterList();
485     FilterList allFilters = new FilterList(/* FilterList.Operator.MUST_PASS_ALL */);
486     allFilters.addFilter(new PrefixFilter(Bytes.toBytes(keyPrefix)));
487     SingleColumnValueFilter filter = new SingleColumnValueFilter(Bytes
488         .toBytes("trans-tags"), Bytes.toBytes("qual2"), CompareOp.EQUAL, Bytes
489         .toBytes(value));
490     filter.setFilterIfMissing(true);
491     allFilters.addFilter(filter);
492 
493     // allFilters.addFilter(new
494     // RowExcludingSingleColumnValueFilter(Bytes.toBytes("trans-tags"),
495     // Bytes.toBytes("qual2"), CompareOp.EQUAL, Bytes.toBytes(value)));
496 
497     Scan scan = new Scan();
498     scan.addFamily(Bytes.toBytes("trans-blob"));
499     scan.addFamily(Bytes.toBytes("trans-type"));
500     scan.addFamily(Bytes.toBytes("trans-date"));
501     scan.addFamily(Bytes.toBytes("trans-tags"));
502     scan.addFamily(Bytes.toBytes("trans-group"));
503     scan.setFilter(allFilters);
504 
505     return ht.getScanner(scan);
506   }
507 
508   private void putRows(Table ht, int numRows, String value, String key)
509       throws IOException {
510     for (int i = 0; i < numRows; i++) {
511       String row = key + "_" + UUID.randomUUID().toString();
512       System.out.println(String.format("Saving row: %s, with value %s", row,
513           value));
514       Put put = new Put(Bytes.toBytes(row));
515       put.setDurability(Durability.SKIP_WAL);
516       put.add(Bytes.toBytes("trans-blob"), null, Bytes
517           .toBytes("value for blob"));
518       put.add(Bytes.toBytes("trans-type"), null, Bytes.toBytes("statement"));
519       put.add(Bytes.toBytes("trans-date"), null, Bytes
520           .toBytes("20090921010101999"));
521       put.add(Bytes.toBytes("trans-tags"), Bytes.toBytes("qual2"), Bytes
522           .toBytes(value));
523       put.add(Bytes.toBytes("trans-group"), null, Bytes
524           .toBytes("adhocTransactionGroupId"));
525       ht.put(put);
526     }
527   }
528 
529   /**
530    * Test filters when multiple regions.  It does counts.  Needs eye-balling of
531    * logs to ensure that we're not scanning more regions that we're supposed to.
532    * Related to the TestFilterAcrossRegions over in the o.a.h.h.filter package.
533    * @throws IOException
534    * @throws InterruptedException
535    */
536   @Test
537   public void testFilterAcrossMultipleRegions()
538   throws IOException, InterruptedException {
539     TableName name = TableName.valueOf("testFilterAcrossMutlipleRegions");
540     HTable t = TEST_UTIL.createTable(name, FAMILY);
541     int rowCount = TEST_UTIL.loadTable(t, FAMILY, false);
542     assertRowCount(t, rowCount);
543     // Split the table.  Should split on a reasonable key; 'lqj'
544     Map<HRegionInfo, ServerName> regions  = splitTable(t);
545     assertRowCount(t, rowCount);
546     // Get end key of first region.
547     byte [] endKey = regions.keySet().iterator().next().getEndKey();
548     // Count rows with a filter that stops us before passed 'endKey'.
549     // Should be count of rows in first region.
550     int endKeyCount = countRows(t, createScanWithRowFilter(endKey));
551     assertTrue(endKeyCount < rowCount);
552 
553     // How do I know I did not got to second region?  Thats tough.  Can't really
554     // do that in client-side region test.  I verified by tracing in debugger.
555     // I changed the messages that come out when set to DEBUG so should see
556     // when scanner is done. Says "Finished with scanning..." with region name.
557     // Check that its finished in right region.
558 
559     // New test.  Make it so scan goes into next region by one and then two.
560     // Make sure count comes out right.
561     byte [] key = new byte [] {endKey[0], endKey[1], (byte)(endKey[2] + 1)};
562     int plusOneCount = countRows(t, createScanWithRowFilter(key));
563     assertEquals(endKeyCount + 1, plusOneCount);
564     key = new byte [] {endKey[0], endKey[1], (byte)(endKey[2] + 2)};
565     int plusTwoCount = countRows(t, createScanWithRowFilter(key));
566     assertEquals(endKeyCount + 2, plusTwoCount);
567 
568     // New test.  Make it so I scan one less than endkey.
569     key = new byte [] {endKey[0], endKey[1], (byte)(endKey[2] - 1)};
570     int minusOneCount = countRows(t, createScanWithRowFilter(key));
571     assertEquals(endKeyCount - 1, minusOneCount);
572     // For above test... study logs.  Make sure we do "Finished with scanning.."
573     // in first region and that we do not fall into the next region.
574 
575     key = new byte [] {'a', 'a', 'a'};
576     int countBBB = countRows(t,
577       createScanWithRowFilter(key, null, CompareFilter.CompareOp.EQUAL));
578     assertEquals(1, countBBB);
579 
580     int countGreater = countRows(t, createScanWithRowFilter(endKey, null,
581       CompareFilter.CompareOp.GREATER_OR_EQUAL));
582     // Because started at start of table.
583     assertEquals(0, countGreater);
584     countGreater = countRows(t, createScanWithRowFilter(endKey, endKey,
585       CompareFilter.CompareOp.GREATER_OR_EQUAL));
586     assertEquals(rowCount - endKeyCount, countGreater);
587   }
588 
589   /*
590    * @param key
591    * @return Scan with RowFilter that does LESS than passed key.
592    */
593   private Scan createScanWithRowFilter(final byte [] key) {
594     return createScanWithRowFilter(key, null, CompareFilter.CompareOp.LESS);
595   }
596 
597   /*
598    * @param key
599    * @param op
600    * @param startRow
601    * @return Scan with RowFilter that does CompareOp op on passed key.
602    */
603   private Scan createScanWithRowFilter(final byte [] key,
604       final byte [] startRow, CompareFilter.CompareOp op) {
605     // Make sure key is of some substance... non-null and > than first key.
606     assertTrue(key != null && key.length > 0 &&
607       Bytes.BYTES_COMPARATOR.compare(key, new byte [] {'a', 'a', 'a'}) >= 0);
608     LOG.info("Key=" + Bytes.toString(key));
609     Scan s = startRow == null? new Scan(): new Scan(startRow);
610     Filter f = new RowFilter(op, new BinaryComparator(key));
611     f = new WhileMatchFilter(f);
612     s.setFilter(f);
613     return s;
614   }
615 
616   /*
617    * @param t
618    * @param s
619    * @return Count of rows in table.
620    * @throws IOException
621    */
622   private int countRows(final Table t, final Scan s)
623   throws IOException {
624     // Assert all rows in table.
625     ResultScanner scanner = t.getScanner(s);
626     int count = 0;
627     for (Result result: scanner) {
628       count++;
629       assertTrue(result.size() > 0);
630       // LOG.info("Count=" + count + ", row=" + Bytes.toString(result.getRow()));
631     }
632     return count;
633   }
634 
635   private void assertRowCount(final Table t, final int expected)
636   throws IOException {
637     assertEquals(expected, countRows(t, new Scan()));
638   }
639 
640   /*
641    * Split table into multiple regions.
642    * @param t Table to split.
643    * @return Map of regions to servers.
644    * @throws IOException
645    */
646   private Map<HRegionInfo, ServerName> splitTable(final HTable t)
647   throws IOException, InterruptedException {
648     // Split this table in two.
649     HBaseAdmin admin = new HBaseAdmin(TEST_UTIL.getConfiguration());
650     admin.split(t.getTableName());
651     admin.close();
652     Map<HRegionInfo, ServerName> regions = waitOnSplit(t);
653     assertTrue(regions.size() > 1);
654     return regions;
655   }
656 
657   /*
658    * Wait on table split.  May return because we waited long enough on the split
659    * and it didn't happen.  Caller should check.
660    * @param t
661    * @return Map of table regions; caller needs to check table actually split.
662    */
663   private Map<HRegionInfo, ServerName> waitOnSplit(final HTable t)
664   throws IOException {
665     Map<HRegionInfo, ServerName> regions = t.getRegionLocations();
666     int originalCount = regions.size();
667     for (int i = 0; i < TEST_UTIL.getConfiguration().getInt("hbase.test.retries", 30); i++) {
668       Thread.currentThread();
669       try {
670         Thread.sleep(1000);
671       } catch (InterruptedException e) {
672         e.printStackTrace();
673       }
674       regions = t.getRegionLocations();
675       if (regions.size() > originalCount) break;
676     }
677     return regions;
678   }
679 
680   @Test
681   public void testSuperSimple() throws Exception {
682     byte [] TABLE = Bytes.toBytes("testSuperSimple");
683     Table ht = TEST_UTIL.createTable(TABLE, FAMILY);
684     Put put = new Put(ROW);
685     put.add(FAMILY, QUALIFIER, VALUE);
686     ht.put(put);
687     Scan scan = new Scan();
688     scan.addColumn(FAMILY, TABLE);
689     ResultScanner scanner = ht.getScanner(scan);
690     Result result = scanner.next();
691     assertTrue("Expected null result", result == null);
692     scanner.close();
693   }
694 
695   @Test
696   public void testMaxKeyValueSize() throws Exception {
697     byte [] TABLE = Bytes.toBytes("testMaxKeyValueSize");
698     Configuration conf = TEST_UTIL.getConfiguration();
699     String oldMaxSize = conf.get(ConnectionConfiguration.MAX_KEYVALUE_SIZE_KEY);
700     Table ht = TEST_UTIL.createTable(TABLE, FAMILY);
701     byte[] value = new byte[4 * 1024 * 1024];
702     Put put = new Put(ROW);
703     put.add(FAMILY, QUALIFIER, value);
704     ht.put(put);
705     try {
706       TEST_UTIL.getConfiguration().setInt(
707           ConnectionConfiguration.MAX_KEYVALUE_SIZE_KEY, 2 * 1024 * 1024);
708       // Create new table so we pick up the change in Configuration.
709       try (Connection connection =
710           ConnectionFactory.createConnection(TEST_UTIL.getConfiguration())) {
711         try (Table t = connection.getTable(TableName.valueOf(FAMILY))) {
712           put = new Put(ROW);
713           put.add(FAMILY, QUALIFIER, value);
714           t.put(put);
715         }
716       }
717       fail("Inserting a too large KeyValue worked, should throw exception");
718     } catch(Exception e) {}
719     conf.set(ConnectionConfiguration.MAX_KEYVALUE_SIZE_KEY, oldMaxSize);
720   }
721 
722   @Test
723   public void testFilters() throws Exception {
724     byte [] TABLE = Bytes.toBytes("testFilters");
725     Table ht = TEST_UTIL.createTable(TABLE, FAMILY);
726     byte [][] ROWS = makeN(ROW, 10);
727     byte [][] QUALIFIERS = {
728         Bytes.toBytes("col0-<d2v1>-<d3v2>"), Bytes.toBytes("col1-<d2v1>-<d3v2>"),
729         Bytes.toBytes("col2-<d2v1>-<d3v2>"), Bytes.toBytes("col3-<d2v1>-<d3v2>"),
730         Bytes.toBytes("col4-<d2v1>-<d3v2>"), Bytes.toBytes("col5-<d2v1>-<d3v2>"),
731         Bytes.toBytes("col6-<d2v1>-<d3v2>"), Bytes.toBytes("col7-<d2v1>-<d3v2>"),
732         Bytes.toBytes("col8-<d2v1>-<d3v2>"), Bytes.toBytes("col9-<d2v1>-<d3v2>")
733     };
734     for(int i=0;i<10;i++) {
735       Put put = new Put(ROWS[i]);
736       put.setDurability(Durability.SKIP_WAL);
737       put.add(FAMILY, QUALIFIERS[i], VALUE);
738       ht.put(put);
739     }
740     Scan scan = new Scan();
741     scan.addFamily(FAMILY);
742     Filter filter = new QualifierFilter(CompareOp.EQUAL,
743       new RegexStringComparator("col[1-5]"));
744     scan.setFilter(filter);
745     ResultScanner scanner = ht.getScanner(scan);
746     int expectedIndex = 1;
747     for(Result result : ht.getScanner(scan)) {
748       assertEquals(result.size(), 1);
749       assertTrue(Bytes.equals(CellUtil.cloneRow(result.rawCells()[0]), ROWS[expectedIndex]));
750       assertTrue(Bytes.equals(CellUtil.cloneQualifier(result.rawCells()[0]),
751           QUALIFIERS[expectedIndex]));
752       expectedIndex++;
753     }
754     assertEquals(expectedIndex, 6);
755     scanner.close();
756   }
757 
758   @Test
759   public void testFilterWithLongCompartor() throws Exception {
760     byte [] TABLE = Bytes.toBytes("testFilterWithLongCompartor");
761     Table ht = TEST_UTIL.createTable(TABLE, FAMILY);
762     byte [][] ROWS = makeN(ROW, 10);
763     byte [][] values = new byte[10][];
764     for (int i = 0; i < 10; i ++) {
765         values[i] = Bytes.toBytes(100L * i);
766     }
767     for(int i = 0; i < 10; i ++) {
768       Put put = new Put(ROWS[i]);
769       put.setDurability(Durability.SKIP_WAL);
770       put.add(FAMILY, QUALIFIER, values[i]);
771       ht.put(put);
772     }
773     Scan scan = new Scan();
774     scan.addFamily(FAMILY);
775     Filter filter = new SingleColumnValueFilter(FAMILY, QUALIFIER, CompareOp.GREATER,
776       new LongComparator(500));
777     scan.setFilter(filter);
778     ResultScanner scanner = ht.getScanner(scan);
779     int expectedIndex = 0;
780     for(Result result : ht.getScanner(scan)) {
781       assertEquals(result.size(), 1);
782       assertTrue(Bytes.toLong(result.getValue(FAMILY, QUALIFIER)) > 500);
783       expectedIndex++;
784     }
785     assertEquals(expectedIndex, 4);
786     scanner.close();
787 }
788 
789   @Test
790   public void testKeyOnlyFilter() throws Exception {
791     byte [] TABLE = Bytes.toBytes("testKeyOnlyFilter");
792     Table ht = TEST_UTIL.createTable(TABLE, FAMILY);
793     byte [][] ROWS = makeN(ROW, 10);
794     byte [][] QUALIFIERS = {
795         Bytes.toBytes("col0-<d2v1>-<d3v2>"), Bytes.toBytes("col1-<d2v1>-<d3v2>"),
796         Bytes.toBytes("col2-<d2v1>-<d3v2>"), Bytes.toBytes("col3-<d2v1>-<d3v2>"),
797         Bytes.toBytes("col4-<d2v1>-<d3v2>"), Bytes.toBytes("col5-<d2v1>-<d3v2>"),
798         Bytes.toBytes("col6-<d2v1>-<d3v2>"), Bytes.toBytes("col7-<d2v1>-<d3v2>"),
799         Bytes.toBytes("col8-<d2v1>-<d3v2>"), Bytes.toBytes("col9-<d2v1>-<d3v2>")
800     };
801     for(int i=0;i<10;i++) {
802       Put put = new Put(ROWS[i]);
803       put.setDurability(Durability.SKIP_WAL);
804       put.add(FAMILY, QUALIFIERS[i], VALUE);
805       ht.put(put);
806     }
807     Scan scan = new Scan();
808     scan.addFamily(FAMILY);
809     Filter filter = new KeyOnlyFilter(true);
810     scan.setFilter(filter);
811     ResultScanner scanner = ht.getScanner(scan);
812     int count = 0;
813     for(Result result : ht.getScanner(scan)) {
814       assertEquals(result.size(), 1);
815       assertEquals(result.rawCells()[0].getValueLength(), Bytes.SIZEOF_INT);
816       assertEquals(Bytes.toInt(CellUtil.cloneValue(result.rawCells()[0])), VALUE.length);
817       count++;
818     }
819     assertEquals(count, 10);
820     scanner.close();
821   }
822 
823   /**
824    * Test simple table and non-existent row cases.
825    */
826   @Test
827   public void testSimpleMissing() throws Exception {
828     byte [] TABLE = Bytes.toBytes("testSimpleMissing");
829     Table ht = TEST_UTIL.createTable(TABLE, FAMILY);
830     byte [][] ROWS = makeN(ROW, 4);
831 
832     // Try to get a row on an empty table
833     Get get = new Get(ROWS[0]);
834     Result result = ht.get(get);
835     assertEmptyResult(result);
836 
837     get = new Get(ROWS[0]);
838     get.addFamily(FAMILY);
839     result = ht.get(get);
840     assertEmptyResult(result);
841 
842     get = new Get(ROWS[0]);
843     get.addColumn(FAMILY, QUALIFIER);
844     result = ht.get(get);
845     assertEmptyResult(result);
846 
847     Scan scan = new Scan();
848     result = getSingleScanResult(ht, scan);
849     assertNullResult(result);
850 
851 
852     scan = new Scan(ROWS[0]);
853     result = getSingleScanResult(ht, scan);
854     assertNullResult(result);
855 
856     scan = new Scan(ROWS[0],ROWS[1]);
857     result = getSingleScanResult(ht, scan);
858     assertNullResult(result);
859 
860     scan = new Scan();
861     scan.addFamily(FAMILY);
862     result = getSingleScanResult(ht, scan);
863     assertNullResult(result);
864 
865     scan = new Scan();
866     scan.addColumn(FAMILY, QUALIFIER);
867     result = getSingleScanResult(ht, scan);
868     assertNullResult(result);
869 
870     // Insert a row
871 
872     Put put = new Put(ROWS[2]);
873     put.add(FAMILY, QUALIFIER, VALUE);
874     ht.put(put);
875 
876     // Try to get empty rows around it
877 
878     get = new Get(ROWS[1]);
879     result = ht.get(get);
880     assertEmptyResult(result);
881 
882     get = new Get(ROWS[0]);
883     get.addFamily(FAMILY);
884     result = ht.get(get);
885     assertEmptyResult(result);
886 
887     get = new Get(ROWS[3]);
888     get.addColumn(FAMILY, QUALIFIER);
889     result = ht.get(get);
890     assertEmptyResult(result);
891 
892     // Try to scan empty rows around it
893 
894     scan = new Scan(ROWS[3]);
895     result = getSingleScanResult(ht, scan);
896     assertNullResult(result);
897 
898     scan = new Scan(ROWS[0],ROWS[2]);
899     result = getSingleScanResult(ht, scan);
900     assertNullResult(result);
901 
902     // Make sure we can actually get the row
903 
904     get = new Get(ROWS[2]);
905     result = ht.get(get);
906     assertSingleResult(result, ROWS[2], FAMILY, QUALIFIER, VALUE);
907 
908     get = new Get(ROWS[2]);
909     get.addFamily(FAMILY);
910     result = ht.get(get);
911     assertSingleResult(result, ROWS[2], FAMILY, QUALIFIER, VALUE);
912 
913     get = new Get(ROWS[2]);
914     get.addColumn(FAMILY, QUALIFIER);
915     result = ht.get(get);
916     assertSingleResult(result, ROWS[2], FAMILY, QUALIFIER, VALUE);
917 
918     // Make sure we can scan the row
919 
920     scan = new Scan();
921     result = getSingleScanResult(ht, scan);
922     assertSingleResult(result, ROWS[2], FAMILY, QUALIFIER, VALUE);
923 
924     scan = new Scan(ROWS[0],ROWS[3]);
925     result = getSingleScanResult(ht, scan);
926     assertSingleResult(result, ROWS[2], FAMILY, QUALIFIER, VALUE);
927 
928     scan = new Scan(ROWS[2],ROWS[3]);
929     result = getSingleScanResult(ht, scan);
930     assertSingleResult(result, ROWS[2], FAMILY, QUALIFIER, VALUE);
931   }
932 
933   /**
934    * Test basic puts, gets, scans, and deletes for a single row
935    * in a multiple family table.
936    */
937   @Test
938   public void testSingleRowMultipleFamily() throws Exception {
939     byte [] TABLE = Bytes.toBytes("testSingleRowMultipleFamily");
940     byte [][] ROWS = makeN(ROW, 3);
941     byte [][] FAMILIES = makeNAscii(FAMILY, 10);
942     byte [][] QUALIFIERS = makeN(QUALIFIER, 10);
943     byte [][] VALUES = makeN(VALUE, 10);
944 
945     Table ht = TEST_UTIL.createTable(TABLE, FAMILIES);
946 
947     Get get;
948     Scan scan;
949     Delete delete;
950     Put put;
951     Result result;
952 
953     ////////////////////////////////////////////////////////////////////////////
954     // Insert one column to one family
955     ////////////////////////////////////////////////////////////////////////////
956 
957     put = new Put(ROWS[0]);
958     put.add(FAMILIES[4], QUALIFIERS[0], VALUES[0]);
959     ht.put(put);
960 
961     // Get the single column
962     getVerifySingleColumn(ht, ROWS, 0, FAMILIES, 4, QUALIFIERS, 0, VALUES, 0);
963 
964     // Scan the single column
965     scanVerifySingleColumn(ht, ROWS, 0, FAMILIES, 4, QUALIFIERS, 0, VALUES, 0);
966 
967     // Get empty results around inserted column
968     getVerifySingleEmpty(ht, ROWS, 0, FAMILIES, 4, QUALIFIERS, 0);
969 
970     // Scan empty results around inserted column
971     scanVerifySingleEmpty(ht, ROWS, 0, FAMILIES, 4, QUALIFIERS, 0);
972 
973     ////////////////////////////////////////////////////////////////////////////
974     // Flush memstore and run same tests from storefiles
975     ////////////////////////////////////////////////////////////////////////////
976 
977     TEST_UTIL.flush();
978 
979     // Redo get and scan tests from storefile
980     getVerifySingleColumn(ht, ROWS, 0, FAMILIES, 4, QUALIFIERS, 0, VALUES, 0);
981     scanVerifySingleColumn(ht, ROWS, 0, FAMILIES, 4, QUALIFIERS, 0, VALUES, 0);
982     getVerifySingleEmpty(ht, ROWS, 0, FAMILIES, 4, QUALIFIERS, 0);
983     scanVerifySingleEmpty(ht, ROWS, 0, FAMILIES, 4, QUALIFIERS, 0);
984 
985     ////////////////////////////////////////////////////////////////////////////
986     // Now, Test reading from memstore and storefiles at once
987     ////////////////////////////////////////////////////////////////////////////
988 
989     // Insert multiple columns to two other families
990     put = new Put(ROWS[0]);
991     put.add(FAMILIES[2], QUALIFIERS[2], VALUES[2]);
992     put.add(FAMILIES[2], QUALIFIERS[4], VALUES[4]);
993     put.add(FAMILIES[4], QUALIFIERS[4], VALUES[4]);
994     put.add(FAMILIES[6], QUALIFIERS[6], VALUES[6]);
995     put.add(FAMILIES[6], QUALIFIERS[7], VALUES[7]);
996     put.add(FAMILIES[7], QUALIFIERS[7], VALUES[7]);
997     put.add(FAMILIES[9], QUALIFIERS[0], VALUES[0]);
998     ht.put(put);
999 
1000     // Get multiple columns across multiple families and get empties around it
1001     singleRowGetTest(ht, ROWS, FAMILIES, QUALIFIERS, VALUES);
1002 
1003     // Scan multiple columns across multiple families and scan empties around it
1004     singleRowScanTest(ht, ROWS, FAMILIES, QUALIFIERS, VALUES);
1005 
1006     ////////////////////////////////////////////////////////////////////////////
1007     // Flush the table again
1008     ////////////////////////////////////////////////////////////////////////////
1009 
1010     TEST_UTIL.flush();
1011 
1012     // Redo tests again
1013     singleRowGetTest(ht, ROWS, FAMILIES, QUALIFIERS, VALUES);
1014     singleRowScanTest(ht, ROWS, FAMILIES, QUALIFIERS, VALUES);
1015 
1016     // Insert more data to memstore
1017     put = new Put(ROWS[0]);
1018     put.add(FAMILIES[6], QUALIFIERS[5], VALUES[5]);
1019     put.add(FAMILIES[6], QUALIFIERS[8], VALUES[8]);
1020     put.add(FAMILIES[6], QUALIFIERS[9], VALUES[9]);
1021     put.add(FAMILIES[4], QUALIFIERS[3], VALUES[3]);
1022     ht.put(put);
1023 
1024     ////////////////////////////////////////////////////////////////////////////
1025     // Delete a storefile column
1026     ////////////////////////////////////////////////////////////////////////////
1027     delete = new Delete(ROWS[0]);
1028     delete.deleteColumns(FAMILIES[6], QUALIFIERS[7]);
1029     ht.delete(delete);
1030 
1031     // Try to get deleted column
1032     get = new Get(ROWS[0]);
1033     get.addColumn(FAMILIES[6], QUALIFIERS[7]);
1034     result = ht.get(get);
1035     assertEmptyResult(result);
1036 
1037     // Try to scan deleted column
1038     scan = new Scan();
1039     scan.addColumn(FAMILIES[6], QUALIFIERS[7]);
1040     result = getSingleScanResult(ht, scan);
1041     assertNullResult(result);
1042 
1043     // Make sure we can still get a column before it and after it
1044     get = new Get(ROWS[0]);
1045     get.addColumn(FAMILIES[6], QUALIFIERS[6]);
1046     result = ht.get(get);
1047     assertSingleResult(result, ROWS[0], FAMILIES[6], QUALIFIERS[6], VALUES[6]);
1048 
1049     get = new Get(ROWS[0]);
1050     get.addColumn(FAMILIES[6], QUALIFIERS[8]);
1051     result = ht.get(get);
1052     assertSingleResult(result, ROWS[0], FAMILIES[6], QUALIFIERS[8], VALUES[8]);
1053 
1054     // Make sure we can still scan a column before it and after it
1055     scan = new Scan();
1056     scan.addColumn(FAMILIES[6], QUALIFIERS[6]);
1057     result = getSingleScanResult(ht, scan);
1058     assertSingleResult(result, ROWS[0], FAMILIES[6], QUALIFIERS[6], VALUES[6]);
1059 
1060     scan = new Scan();
1061     scan.addColumn(FAMILIES[6], QUALIFIERS[8]);
1062     result = getSingleScanResult(ht, scan);
1063     assertSingleResult(result, ROWS[0], FAMILIES[6], QUALIFIERS[8], VALUES[8]);
1064 
1065     ////////////////////////////////////////////////////////////////////////////
1066     // Delete a memstore column
1067     ////////////////////////////////////////////////////////////////////////////
1068     delete = new Delete(ROWS[0]);
1069     delete.deleteColumns(FAMILIES[6], QUALIFIERS[8]);
1070     ht.delete(delete);
1071 
1072     // Try to get deleted column
1073     get = new Get(ROWS[0]);
1074     get.addColumn(FAMILIES[6], QUALIFIERS[8]);
1075     result = ht.get(get);
1076     assertEmptyResult(result);
1077 
1078     // Try to scan deleted column
1079     scan = new Scan();
1080     scan.addColumn(FAMILIES[6], QUALIFIERS[8]);
1081     result = getSingleScanResult(ht, scan);
1082     assertNullResult(result);
1083 
1084     // Make sure we can still get a column before it and after it
1085     get = new Get(ROWS[0]);
1086     get.addColumn(FAMILIES[6], QUALIFIERS[6]);
1087     result = ht.get(get);
1088     assertSingleResult(result, ROWS[0], FAMILIES[6], QUALIFIERS[6], VALUES[6]);
1089 
1090     get = new Get(ROWS[0]);
1091     get.addColumn(FAMILIES[6], QUALIFIERS[9]);
1092     result = ht.get(get);
1093     assertSingleResult(result, ROWS[0], FAMILIES[6], QUALIFIERS[9], VALUES[9]);
1094 
1095     // Make sure we can still scan a column before it and after it
1096     scan = new Scan();
1097     scan.addColumn(FAMILIES[6], QUALIFIERS[6]);
1098     result = getSingleScanResult(ht, scan);
1099     assertSingleResult(result, ROWS[0], FAMILIES[6], QUALIFIERS[6], VALUES[6]);
1100 
1101     scan = new Scan();
1102     scan.addColumn(FAMILIES[6], QUALIFIERS[9]);
1103     result = getSingleScanResult(ht, scan);
1104     assertSingleResult(result, ROWS[0], FAMILIES[6], QUALIFIERS[9], VALUES[9]);
1105 
1106     ////////////////////////////////////////////////////////////////////////////
1107     // Delete joint storefile/memstore family
1108     ////////////////////////////////////////////////////////////////////////////
1109 
1110     delete = new Delete(ROWS[0]);
1111     delete.deleteFamily(FAMILIES[4]);
1112     ht.delete(delete);
1113 
1114     // Try to get storefile column in deleted family
1115     get = new Get(ROWS[0]);
1116     get.addColumn(FAMILIES[4], QUALIFIERS[4]);
1117     result = ht.get(get);
1118     assertEmptyResult(result);
1119 
1120     // Try to get memstore column in deleted family
1121     get = new Get(ROWS[0]);
1122     get.addColumn(FAMILIES[4], QUALIFIERS[3]);
1123     result = ht.get(get);
1124     assertEmptyResult(result);
1125 
1126     // Try to get deleted family
1127     get = new Get(ROWS[0]);
1128     get.addFamily(FAMILIES[4]);
1129     result = ht.get(get);
1130     assertEmptyResult(result);
1131 
1132     // Try to scan storefile column in deleted family
1133     scan = new Scan();
1134     scan.addColumn(FAMILIES[4], QUALIFIERS[4]);
1135     result = getSingleScanResult(ht, scan);
1136     assertNullResult(result);
1137 
1138     // Try to scan memstore column in deleted family
1139     scan = new Scan();
1140     scan.addColumn(FAMILIES[4], QUALIFIERS[3]);
1141     result = getSingleScanResult(ht, scan);
1142     assertNullResult(result);
1143 
1144     // Try to scan deleted family
1145     scan = new Scan();
1146     scan.addFamily(FAMILIES[4]);
1147     result = getSingleScanResult(ht, scan);
1148     assertNullResult(result);
1149 
1150     // Make sure we can still get another family
1151     get = new Get(ROWS[0]);
1152     get.addColumn(FAMILIES[2], QUALIFIERS[2]);
1153     result = ht.get(get);
1154     assertSingleResult(result, ROWS[0], FAMILIES[2], QUALIFIERS[2], VALUES[2]);
1155 
1156     get = new Get(ROWS[0]);
1157     get.addColumn(FAMILIES[6], QUALIFIERS[9]);
1158     result = ht.get(get);
1159     assertSingleResult(result, ROWS[0], FAMILIES[6], QUALIFIERS[9], VALUES[9]);
1160 
1161     // Make sure we can still scan another family
1162     scan = new Scan();
1163     scan.addColumn(FAMILIES[6], QUALIFIERS[6]);
1164     result = getSingleScanResult(ht, scan);
1165     assertSingleResult(result, ROWS[0], FAMILIES[6], QUALIFIERS[6], VALUES[6]);
1166 
1167     scan = new Scan();
1168     scan.addColumn(FAMILIES[6], QUALIFIERS[9]);
1169     result = getSingleScanResult(ht, scan);
1170     assertSingleResult(result, ROWS[0], FAMILIES[6], QUALIFIERS[9], VALUES[9]);
1171 
1172     ////////////////////////////////////////////////////////////////////////////
1173     // Flush everything and rerun delete tests
1174     ////////////////////////////////////////////////////////////////////////////
1175 
1176     TEST_UTIL.flush();
1177 
1178     // Try to get storefile column in deleted family
1179     get = new Get(ROWS[0]);
1180     get.addColumn(FAMILIES[4], QUALIFIERS[4]);
1181     result = ht.get(get);
1182     assertEmptyResult(result);
1183 
1184     // Try to get memstore column in deleted family
1185     get = new Get(ROWS[0]);
1186     get.addColumn(FAMILIES[4], QUALIFIERS[3]);
1187     result = ht.get(get);
1188     assertEmptyResult(result);
1189 
1190     // Try to get deleted family
1191     get = new Get(ROWS[0]);
1192     get.addFamily(FAMILIES[4]);
1193     result = ht.get(get);
1194     assertEmptyResult(result);
1195 
1196     // Try to scan storefile column in deleted family
1197     scan = new Scan();
1198     scan.addColumn(FAMILIES[4], QUALIFIERS[4]);
1199     result = getSingleScanResult(ht, scan);
1200     assertNullResult(result);
1201 
1202     // Try to scan memstore column in deleted family
1203     scan = new Scan();
1204     scan.addColumn(FAMILIES[4], QUALIFIERS[3]);
1205     result = getSingleScanResult(ht, scan);
1206     assertNullResult(result);
1207 
1208     // Try to scan deleted family
1209     scan = new Scan();
1210     scan.addFamily(FAMILIES[4]);
1211     result = getSingleScanResult(ht, scan);
1212     assertNullResult(result);
1213 
1214     // Make sure we can still get another family
1215     get = new Get(ROWS[0]);
1216     get.addColumn(FAMILIES[2], QUALIFIERS[2]);
1217     result = ht.get(get);
1218     assertSingleResult(result, ROWS[0], FAMILIES[2], QUALIFIERS[2], VALUES[2]);
1219 
1220     get = new Get(ROWS[0]);
1221     get.addColumn(FAMILIES[6], QUALIFIERS[9]);
1222     result = ht.get(get);
1223     assertSingleResult(result, ROWS[0], FAMILIES[6], QUALIFIERS[9], VALUES[9]);
1224 
1225     // Make sure we can still scan another family
1226     scan = new Scan();
1227     scan.addColumn(FAMILIES[6], QUALIFIERS[6]);
1228     result = getSingleScanResult(ht, scan);
1229     assertSingleResult(result, ROWS[0], FAMILIES[6], QUALIFIERS[6], VALUES[6]);
1230 
1231     scan = new Scan();
1232     scan.addColumn(FAMILIES[6], QUALIFIERS[9]);
1233     result = getSingleScanResult(ht, scan);
1234     assertSingleResult(result, ROWS[0], FAMILIES[6], QUALIFIERS[9], VALUES[9]);
1235 
1236   }
1237 
1238   @Test
1239   public void testNull() throws Exception {
1240     byte [] TABLE = Bytes.toBytes("testNull");
1241 
1242     // Null table name (should NOT work)
1243     try {
1244       TEST_UTIL.createTable((TableName)null, FAMILY);
1245       fail("Creating a table with null name passed, should have failed");
1246     } catch(Exception e) {}
1247 
1248     // Null family (should NOT work)
1249     try {
1250       TEST_UTIL.createTable(TABLE, new byte[][]{(byte[])null});
1251       fail("Creating a table with a null family passed, should fail");
1252     } catch(Exception e) {}
1253 
1254     Table ht = TEST_UTIL.createTable(TABLE, FAMILY);
1255 
1256     // Null row (should NOT work)
1257     try {
1258       Put put = new Put((byte[])null);
1259       put.add(FAMILY, QUALIFIER, VALUE);
1260       ht.put(put);
1261       fail("Inserting a null row worked, should throw exception");
1262     } catch(Exception e) {}
1263 
1264     // Null qualifier (should work)
1265     {
1266       Put put = new Put(ROW);
1267       put.add(FAMILY, null, VALUE);
1268       ht.put(put);
1269 
1270       getTestNull(ht, ROW, FAMILY, VALUE);
1271 
1272       scanTestNull(ht, ROW, FAMILY, VALUE);
1273 
1274       Delete delete = new Delete(ROW);
1275       delete.deleteColumns(FAMILY, null);
1276       ht.delete(delete);
1277 
1278       Get get = new Get(ROW);
1279       Result result = ht.get(get);
1280       assertEmptyResult(result);
1281     }
1282 
1283     // Use a new table
1284     byte [] TABLE2 = Bytes.toBytes("testNull2");
1285     ht = TEST_UTIL.createTable(TableName.valueOf(TABLE2), FAMILY);
1286 
1287     // Empty qualifier, byte[0] instead of null (should work)
1288     try {
1289       Put put = new Put(ROW);
1290       put.add(FAMILY, HConstants.EMPTY_BYTE_ARRAY, VALUE);
1291       ht.put(put);
1292 
1293       getTestNull(ht, ROW, FAMILY, VALUE);
1294 
1295       scanTestNull(ht, ROW, FAMILY, VALUE);
1296 
1297       // Flush and try again
1298 
1299       TEST_UTIL.flush();
1300 
1301       getTestNull(ht, ROW, FAMILY, VALUE);
1302 
1303       scanTestNull(ht, ROW, FAMILY, VALUE);
1304 
1305       Delete delete = new Delete(ROW);
1306       delete.deleteColumns(FAMILY, HConstants.EMPTY_BYTE_ARRAY);
1307       ht.delete(delete);
1308 
1309       Get get = new Get(ROW);
1310       Result result = ht.get(get);
1311       assertEmptyResult(result);
1312 
1313     } catch(Exception e) {
1314       throw new IOException("Using a row with null qualifier threw exception, should ");
1315     }
1316 
1317     // Null value
1318     try {
1319       Put put = new Put(ROW);
1320       put.add(FAMILY, QUALIFIER, null);
1321       ht.put(put);
1322 
1323       Get get = new Get(ROW);
1324       get.addColumn(FAMILY, QUALIFIER);
1325       Result result = ht.get(get);
1326       assertSingleResult(result, ROW, FAMILY, QUALIFIER, null);
1327 
1328       Scan scan = new Scan();
1329       scan.addColumn(FAMILY, QUALIFIER);
1330       result = getSingleScanResult(ht, scan);
1331       assertSingleResult(result, ROW, FAMILY, QUALIFIER, null);
1332 
1333       Delete delete = new Delete(ROW);
1334       delete.deleteColumns(FAMILY, QUALIFIER);
1335       ht.delete(delete);
1336 
1337       get = new Get(ROW);
1338       result = ht.get(get);
1339       assertEmptyResult(result);
1340 
1341     } catch(Exception e) {
1342       throw new IOException("Null values should be allowed, but threw exception");
1343     }
1344   }
1345 
1346   @Test
1347   public void testVersions() throws Exception {
1348     byte [] TABLE = Bytes.toBytes("testVersions");
1349 
1350     long [] STAMPS = makeStamps(20);
1351     byte [][] VALUES = makeNAscii(VALUE, 20);
1352 
1353     Table ht = TEST_UTIL.createTable(TABLE, FAMILY, 10);
1354 
1355     // Insert 4 versions of same column
1356     Put put = new Put(ROW);
1357     put.add(FAMILY, QUALIFIER, STAMPS[1], VALUES[1]);
1358     put.add(FAMILY, QUALIFIER, STAMPS[2], VALUES[2]);
1359     put.add(FAMILY, QUALIFIER, STAMPS[4], VALUES[4]);
1360     put.add(FAMILY, QUALIFIER, STAMPS[5], VALUES[5]);
1361     ht.put(put);
1362 
1363     // Verify we can get each one properly
1364     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[1], VALUES[1]);
1365     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[2], VALUES[2]);
1366     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[4], VALUES[4]);
1367     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[5], VALUES[5]);
1368     scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[1], VALUES[1]);
1369     scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[2], VALUES[2]);
1370     scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[4], VALUES[4]);
1371     scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[5], VALUES[5]);
1372 
1373     // Verify we don't accidentally get others
1374     getVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[0]);
1375     getVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[3]);
1376     getVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[6]);
1377     scanVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[0]);
1378     scanVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[3]);
1379     scanVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[6]);
1380 
1381     // Ensure maxVersions in query is respected
1382     Get get = new Get(ROW);
1383     get.addColumn(FAMILY, QUALIFIER);
1384     get.setMaxVersions(2);
1385     Result result = ht.get(get);
1386     assertNResult(result, ROW, FAMILY, QUALIFIER,
1387         new long [] {STAMPS[4], STAMPS[5]},
1388         new byte[][] {VALUES[4], VALUES[5]},
1389         0, 1);
1390 
1391     Scan scan = new Scan(ROW);
1392     scan.addColumn(FAMILY, QUALIFIER);
1393     scan.setMaxVersions(2);
1394     result = getSingleScanResult(ht, scan);
1395     assertNResult(result, ROW, FAMILY, QUALIFIER,
1396         new long [] {STAMPS[4], STAMPS[5]},
1397         new byte[][] {VALUES[4], VALUES[5]},
1398         0, 1);
1399 
1400     // Flush and redo
1401 
1402     TEST_UTIL.flush();
1403 
1404     // Verify we can get each one properly
1405     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[1], VALUES[1]);
1406     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[2], VALUES[2]);
1407     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[4], VALUES[4]);
1408     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[5], VALUES[5]);
1409     scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[1], VALUES[1]);
1410     scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[2], VALUES[2]);
1411     scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[4], VALUES[4]);
1412     scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[5], VALUES[5]);
1413 
1414     // Verify we don't accidentally get others
1415     getVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[0]);
1416     getVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[3]);
1417     getVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[6]);
1418     scanVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[0]);
1419     scanVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[3]);
1420     scanVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[6]);
1421 
1422     // Ensure maxVersions in query is respected
1423     get = new Get(ROW);
1424     get.addColumn(FAMILY, QUALIFIER);
1425     get.setMaxVersions(2);
1426     result = ht.get(get);
1427     assertNResult(result, ROW, FAMILY, QUALIFIER,
1428         new long [] {STAMPS[4], STAMPS[5]},
1429         new byte[][] {VALUES[4], VALUES[5]},
1430         0, 1);
1431 
1432     scan = new Scan(ROW);
1433     scan.addColumn(FAMILY, QUALIFIER);
1434     scan.setMaxVersions(2);
1435     result = getSingleScanResult(ht, scan);
1436     assertNResult(result, ROW, FAMILY, QUALIFIER,
1437         new long [] {STAMPS[4], STAMPS[5]},
1438         new byte[][] {VALUES[4], VALUES[5]},
1439         0, 1);
1440 
1441 
1442     // Add some memstore and retest
1443 
1444     // Insert 4 more versions of same column and a dupe
1445     put = new Put(ROW);
1446     put.add(FAMILY, QUALIFIER, STAMPS[3], VALUES[3]);
1447     put.add(FAMILY, QUALIFIER, STAMPS[6], VALUES[6]);
1448     put.add(FAMILY, QUALIFIER, STAMPS[7], VALUES[7]);
1449     put.add(FAMILY, QUALIFIER, STAMPS[8], VALUES[8]);
1450     ht.put(put);
1451 
1452     // Ensure maxVersions in query is respected
1453     get = new Get(ROW);
1454     get.addColumn(FAMILY, QUALIFIER);
1455     get.setMaxVersions();
1456     result = ht.get(get);
1457     assertNResult(result, ROW, FAMILY, QUALIFIER,
1458         new long [] {STAMPS[1], STAMPS[2], STAMPS[3], STAMPS[4], STAMPS[5], STAMPS[6], STAMPS[7], STAMPS[8]},
1459         new byte[][] {VALUES[1], VALUES[2], VALUES[3], VALUES[4], VALUES[5], VALUES[6], VALUES[7], VALUES[8]},
1460         0, 7);
1461 
1462     scan = new Scan(ROW);
1463     scan.addColumn(FAMILY, QUALIFIER);
1464     scan.setMaxVersions();
1465     result = getSingleScanResult(ht, scan);
1466     assertNResult(result, ROW, FAMILY, QUALIFIER,
1467         new long [] {STAMPS[1], STAMPS[2], STAMPS[3], STAMPS[4], STAMPS[5], STAMPS[6], STAMPS[7], STAMPS[8]},
1468         new byte[][] {VALUES[1], VALUES[2], VALUES[3], VALUES[4], VALUES[5], VALUES[6], VALUES[7], VALUES[8]},
1469         0, 7);
1470 
1471     get = new Get(ROW);
1472     get.setMaxVersions();
1473     result = ht.get(get);
1474     assertNResult(result, ROW, FAMILY, QUALIFIER,
1475         new long [] {STAMPS[1], STAMPS[2], STAMPS[3], STAMPS[4], STAMPS[5], STAMPS[6], STAMPS[7], STAMPS[8]},
1476         new byte[][] {VALUES[1], VALUES[2], VALUES[3], VALUES[4], VALUES[5], VALUES[6], VALUES[7], VALUES[8]},
1477         0, 7);
1478 
1479     scan = new Scan(ROW);
1480     scan.setMaxVersions();
1481     result = getSingleScanResult(ht, scan);
1482     assertNResult(result, ROW, FAMILY, QUALIFIER,
1483         new long [] {STAMPS[1], STAMPS[2], STAMPS[3], STAMPS[4], STAMPS[5], STAMPS[6], STAMPS[7], STAMPS[8]},
1484         new byte[][] {VALUES[1], VALUES[2], VALUES[3], VALUES[4], VALUES[5], VALUES[6], VALUES[7], VALUES[8]},
1485         0, 7);
1486 
1487     // Verify we can get each one properly
1488     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[1], VALUES[1]);
1489     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[2], VALUES[2]);
1490     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[4], VALUES[4]);
1491     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[7], VALUES[7]);
1492     scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[1], VALUES[1]);
1493     scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[2], VALUES[2]);
1494     scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[4], VALUES[4]);
1495     scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[7], VALUES[7]);
1496 
1497     // Verify we don't accidentally get others
1498     getVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[0]);
1499     getVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[9]);
1500     scanVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[0]);
1501     scanVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[9]);
1502 
1503     // Ensure maxVersions of table is respected
1504 
1505     TEST_UTIL.flush();
1506 
1507     // Insert 4 more versions of same column and a dupe
1508     put = new Put(ROW);
1509     put.add(FAMILY, QUALIFIER, STAMPS[9], VALUES[9]);
1510     put.add(FAMILY, QUALIFIER, STAMPS[11], VALUES[11]);
1511     put.add(FAMILY, QUALIFIER, STAMPS[13], VALUES[13]);
1512     put.add(FAMILY, QUALIFIER, STAMPS[15], VALUES[15]);
1513     ht.put(put);
1514 
1515     get = new Get(ROW);
1516     get.addColumn(FAMILY, QUALIFIER);
1517     get.setMaxVersions(Integer.MAX_VALUE);
1518     result = ht.get(get);
1519     assertNResult(result, ROW, FAMILY, QUALIFIER,
1520         new long [] {STAMPS[3], STAMPS[4], STAMPS[5], STAMPS[6], STAMPS[7], STAMPS[8], STAMPS[9], STAMPS[11], STAMPS[13], STAMPS[15]},
1521         new byte[][] {VALUES[3], VALUES[4], VALUES[5], VALUES[6], VALUES[7], VALUES[8], VALUES[9], VALUES[11], VALUES[13], VALUES[15]},
1522         0, 9);
1523 
1524     scan = new Scan(ROW);
1525     scan.addColumn(FAMILY, QUALIFIER);
1526     scan.setMaxVersions(Integer.MAX_VALUE);
1527     result = getSingleScanResult(ht, scan);
1528     assertNResult(result, ROW, FAMILY, QUALIFIER,
1529         new long [] {STAMPS[3], STAMPS[4], STAMPS[5], STAMPS[6], STAMPS[7], STAMPS[8], STAMPS[9], STAMPS[11], STAMPS[13], STAMPS[15]},
1530         new byte[][] {VALUES[3], VALUES[4], VALUES[5], VALUES[6], VALUES[7], VALUES[8], VALUES[9], VALUES[11], VALUES[13], VALUES[15]},
1531         0, 9);
1532 
1533     // Delete a version in the memstore and a version in a storefile
1534     Delete delete = new Delete(ROW);
1535     delete.deleteColumn(FAMILY, QUALIFIER, STAMPS[11]);
1536     delete.deleteColumn(FAMILY, QUALIFIER, STAMPS[7]);
1537     ht.delete(delete);
1538 
1539     // Test that it's gone
1540     get = new Get(ROW);
1541     get.addColumn(FAMILY, QUALIFIER);
1542     get.setMaxVersions(Integer.MAX_VALUE);
1543     result = ht.get(get);
1544     assertNResult(result, ROW, FAMILY, QUALIFIER,
1545         new long [] {STAMPS[1], STAMPS[2], STAMPS[3], STAMPS[4], STAMPS[5], STAMPS[6], STAMPS[8], STAMPS[9], STAMPS[13], STAMPS[15]},
1546         new byte[][] {VALUES[1], VALUES[2], VALUES[3], VALUES[4], VALUES[5], VALUES[6], VALUES[8], VALUES[9], VALUES[13], VALUES[15]},
1547         0, 9);
1548 
1549     scan = new Scan(ROW);
1550     scan.addColumn(FAMILY, QUALIFIER);
1551     scan.setMaxVersions(Integer.MAX_VALUE);
1552     result = getSingleScanResult(ht, scan);
1553     assertNResult(result, ROW, FAMILY, QUALIFIER,
1554         new long [] {STAMPS[1], STAMPS[2], STAMPS[3], STAMPS[4], STAMPS[5], STAMPS[6], STAMPS[8], STAMPS[9], STAMPS[13], STAMPS[15]},
1555         new byte[][] {VALUES[1], VALUES[2], VALUES[3], VALUES[4], VALUES[5], VALUES[6], VALUES[8], VALUES[9], VALUES[13], VALUES[15]},
1556         0, 9);
1557 
1558   }
1559 
1560   @Test
1561   public void testVersionLimits() throws Exception {
1562     byte [] TABLE = Bytes.toBytes("testVersionLimits");
1563     byte [][] FAMILIES = makeNAscii(FAMILY, 3);
1564     int [] LIMITS = {1,3,5};
1565     long [] STAMPS = makeStamps(10);
1566     byte [][] VALUES = makeNAscii(VALUE, 10);
1567     Table ht = TEST_UTIL.createTable(TABLE, FAMILIES, LIMITS);
1568 
1569     // Insert limit + 1 on each family
1570     Put put = new Put(ROW);
1571     put.add(FAMILIES[0], QUALIFIER, STAMPS[0], VALUES[0]);
1572     put.add(FAMILIES[0], QUALIFIER, STAMPS[1], VALUES[1]);
1573     put.add(FAMILIES[1], QUALIFIER, STAMPS[0], VALUES[0]);
1574     put.add(FAMILIES[1], QUALIFIER, STAMPS[1], VALUES[1]);
1575     put.add(FAMILIES[1], QUALIFIER, STAMPS[2], VALUES[2]);
1576     put.add(FAMILIES[1], QUALIFIER, STAMPS[3], VALUES[3]);
1577     put.add(FAMILIES[2], QUALIFIER, STAMPS[0], VALUES[0]);
1578     put.add(FAMILIES[2], QUALIFIER, STAMPS[1], VALUES[1]);
1579     put.add(FAMILIES[2], QUALIFIER, STAMPS[2], VALUES[2]);
1580     put.add(FAMILIES[2], QUALIFIER, STAMPS[3], VALUES[3]);
1581     put.add(FAMILIES[2], QUALIFIER, STAMPS[4], VALUES[4]);
1582     put.add(FAMILIES[2], QUALIFIER, STAMPS[5], VALUES[5]);
1583     put.add(FAMILIES[2], QUALIFIER, STAMPS[6], VALUES[6]);
1584     ht.put(put);
1585 
1586     // Verify we only get the right number out of each
1587 
1588     // Family0
1589 
1590     Get get = new Get(ROW);
1591     get.addColumn(FAMILIES[0], QUALIFIER);
1592     get.setMaxVersions(Integer.MAX_VALUE);
1593     Result result = ht.get(get);
1594     assertNResult(result, ROW, FAMILIES[0], QUALIFIER,
1595         new long [] {STAMPS[1]},
1596         new byte[][] {VALUES[1]},
1597         0, 0);
1598 
1599     get = new Get(ROW);
1600     get.addFamily(FAMILIES[0]);
1601     get.setMaxVersions(Integer.MAX_VALUE);
1602     result = ht.get(get);
1603     assertNResult(result, ROW, FAMILIES[0], QUALIFIER,
1604         new long [] {STAMPS[1]},
1605         new byte[][] {VALUES[1]},
1606         0, 0);
1607 
1608     Scan scan = new Scan(ROW);
1609     scan.addColumn(FAMILIES[0], QUALIFIER);
1610     scan.setMaxVersions(Integer.MAX_VALUE);
1611     result = getSingleScanResult(ht, scan);
1612     assertNResult(result, ROW, FAMILIES[0], QUALIFIER,
1613         new long [] {STAMPS[1]},
1614         new byte[][] {VALUES[1]},
1615         0, 0);
1616 
1617     scan = new Scan(ROW);
1618     scan.addFamily(FAMILIES[0]);
1619     scan.setMaxVersions(Integer.MAX_VALUE);
1620     result = getSingleScanResult(ht, scan);
1621     assertNResult(result, ROW, FAMILIES[0], QUALIFIER,
1622         new long [] {STAMPS[1]},
1623         new byte[][] {VALUES[1]},
1624         0, 0);
1625 
1626     // Family1
1627 
1628     get = new Get(ROW);
1629     get.addColumn(FAMILIES[1], QUALIFIER);
1630     get.setMaxVersions(Integer.MAX_VALUE);
1631     result = ht.get(get);
1632     assertNResult(result, ROW, FAMILIES[1], QUALIFIER,
1633         new long [] {STAMPS[1], STAMPS[2], STAMPS[3]},
1634         new byte[][] {VALUES[1], VALUES[2], VALUES[3]},
1635         0, 2);
1636 
1637     get = new Get(ROW);
1638     get.addFamily(FAMILIES[1]);
1639     get.setMaxVersions(Integer.MAX_VALUE);
1640     result = ht.get(get);
1641     assertNResult(result, ROW, FAMILIES[1], QUALIFIER,
1642         new long [] {STAMPS[1], STAMPS[2], STAMPS[3]},
1643         new byte[][] {VALUES[1], VALUES[2], VALUES[3]},
1644         0, 2);
1645 
1646     scan = new Scan(ROW);
1647     scan.addColumn(FAMILIES[1], QUALIFIER);
1648     scan.setMaxVersions(Integer.MAX_VALUE);
1649     result = getSingleScanResult(ht, scan);
1650     assertNResult(result, ROW, FAMILIES[1], QUALIFIER,
1651         new long [] {STAMPS[1], STAMPS[2], STAMPS[3]},
1652         new byte[][] {VALUES[1], VALUES[2], VALUES[3]},
1653         0, 2);
1654 
1655     scan = new Scan(ROW);
1656     scan.addFamily(FAMILIES[1]);
1657     scan.setMaxVersions(Integer.MAX_VALUE);
1658     result = getSingleScanResult(ht, scan);
1659     assertNResult(result, ROW, FAMILIES[1], QUALIFIER,
1660         new long [] {STAMPS[1], STAMPS[2], STAMPS[3]},
1661         new byte[][] {VALUES[1], VALUES[2], VALUES[3]},
1662         0, 2);
1663 
1664     // Family2
1665 
1666     get = new Get(ROW);
1667     get.addColumn(FAMILIES[2], QUALIFIER);
1668     get.setMaxVersions(Integer.MAX_VALUE);
1669     result = ht.get(get);
1670     assertNResult(result, ROW, FAMILIES[2], QUALIFIER,
1671         new long [] {STAMPS[2], STAMPS[3], STAMPS[4], STAMPS[5], STAMPS[6]},
1672         new byte[][] {VALUES[2], VALUES[3], VALUES[4], VALUES[5], VALUES[6]},
1673         0, 4);
1674 
1675     get = new Get(ROW);
1676     get.addFamily(FAMILIES[2]);
1677     get.setMaxVersions(Integer.MAX_VALUE);
1678     result = ht.get(get);
1679     assertNResult(result, ROW, FAMILIES[2], QUALIFIER,
1680         new long [] {STAMPS[2], STAMPS[3], STAMPS[4], STAMPS[5], STAMPS[6]},
1681         new byte[][] {VALUES[2], VALUES[3], VALUES[4], VALUES[5], VALUES[6]},
1682         0, 4);
1683 
1684     scan = new Scan(ROW);
1685     scan.addColumn(FAMILIES[2], QUALIFIER);
1686     scan.setMaxVersions(Integer.MAX_VALUE);
1687     result = getSingleScanResult(ht, scan);
1688     assertNResult(result, ROW, FAMILIES[2], QUALIFIER,
1689         new long [] {STAMPS[2], STAMPS[3], STAMPS[4], STAMPS[5], STAMPS[6]},
1690         new byte[][] {VALUES[2], VALUES[3], VALUES[4], VALUES[5], VALUES[6]},
1691         0, 4);
1692 
1693     scan = new Scan(ROW);
1694     scan.addFamily(FAMILIES[2]);
1695     scan.setMaxVersions(Integer.MAX_VALUE);
1696     result = getSingleScanResult(ht, scan);
1697     assertNResult(result, ROW, FAMILIES[2], QUALIFIER,
1698         new long [] {STAMPS[2], STAMPS[3], STAMPS[4], STAMPS[5], STAMPS[6]},
1699         new byte[][] {VALUES[2], VALUES[3], VALUES[4], VALUES[5], VALUES[6]},
1700         0, 4);
1701 
1702     // Try all families
1703 
1704     get = new Get(ROW);
1705     get.setMaxVersions(Integer.MAX_VALUE);
1706     result = ht.get(get);
1707     assertTrue("Expected 9 keys but received " + result.size(),
1708         result.size() == 9);
1709 
1710     get = new Get(ROW);
1711     get.addFamily(FAMILIES[0]);
1712     get.addFamily(FAMILIES[1]);
1713     get.addFamily(FAMILIES[2]);
1714     get.setMaxVersions(Integer.MAX_VALUE);
1715     result = ht.get(get);
1716     assertTrue("Expected 9 keys but received " + result.size(),
1717         result.size() == 9);
1718 
1719     get = new Get(ROW);
1720     get.addColumn(FAMILIES[0], QUALIFIER);
1721     get.addColumn(FAMILIES[1], QUALIFIER);
1722     get.addColumn(FAMILIES[2], QUALIFIER);
1723     get.setMaxVersions(Integer.MAX_VALUE);
1724     result = ht.get(get);
1725     assertTrue("Expected 9 keys but received " + result.size(),
1726         result.size() == 9);
1727 
1728     scan = new Scan(ROW);
1729     scan.setMaxVersions(Integer.MAX_VALUE);
1730     result = getSingleScanResult(ht, scan);
1731     assertTrue("Expected 9 keys but received " + result.size(),
1732         result.size() == 9);
1733 
1734     scan = new Scan(ROW);
1735     scan.setMaxVersions(Integer.MAX_VALUE);
1736     scan.addFamily(FAMILIES[0]);
1737     scan.addFamily(FAMILIES[1]);
1738     scan.addFamily(FAMILIES[2]);
1739     result = getSingleScanResult(ht, scan);
1740     assertTrue("Expected 9 keys but received " + result.size(),
1741         result.size() == 9);
1742 
1743     scan = new Scan(ROW);
1744     scan.setMaxVersions(Integer.MAX_VALUE);
1745     scan.addColumn(FAMILIES[0], QUALIFIER);
1746     scan.addColumn(FAMILIES[1], QUALIFIER);
1747     scan.addColumn(FAMILIES[2], QUALIFIER);
1748     result = getSingleScanResult(ht, scan);
1749     assertTrue("Expected 9 keys but received " + result.size(),
1750         result.size() == 9);
1751 
1752   }
1753 
1754   @Test
1755   public void testDeleteFamilyVersion() throws Exception {
1756     HBaseAdmin admin = new HBaseAdmin(TEST_UTIL.getConfiguration());
1757     byte [] TABLE = Bytes.toBytes("testDeleteFamilyVersion");
1758 
1759     byte [][] QUALIFIERS = makeNAscii(QUALIFIER, 1);
1760     byte [][] VALUES = makeN(VALUE, 5);
1761     long [] ts = {1000, 2000, 3000, 4000, 5000};
1762 
1763     Table ht = TEST_UTIL.createTable(TABLE, FAMILY, 5);
1764 
1765     Put put = new Put(ROW);
1766     for (int q = 0; q < 1; q++)
1767       for (int t = 0; t < 5; t++)
1768         put.add(FAMILY, QUALIFIERS[q], ts[t], VALUES[t]);
1769     ht.put(put);
1770     admin.flush(TABLE);
1771 
1772     Delete delete = new Delete(ROW);
1773     delete.deleteFamilyVersion(FAMILY, ts[1]);  // delete version '2000'
1774     delete.deleteFamilyVersion(FAMILY, ts[3]);  // delete version '4000'
1775     ht.delete(delete);
1776     admin.flush(TABLE);
1777 
1778     for (int i = 0; i < 1; i++) {
1779       Get get = new Get(ROW);
1780       get.addColumn(FAMILY, QUALIFIERS[i]);
1781       get.setMaxVersions(Integer.MAX_VALUE);
1782       Result result = ht.get(get);
1783       // verify version '1000'/'3000'/'5000' remains for all columns
1784       assertNResult(result, ROW, FAMILY, QUALIFIERS[i],
1785           new long [] {ts[0], ts[2], ts[4]},
1786           new byte[][] {VALUES[0], VALUES[2], VALUES[4]},
1787           0, 2);
1788     }
1789     ht.close();
1790     admin.close();
1791   }
1792 
1793   @Test
1794   public void testDeleteFamilyVersionWithOtherDeletes() throws Exception {
1795     byte [] TABLE = Bytes.toBytes("testDeleteFamilyVersionWithOtherDeletes");
1796 
1797     byte [][] QUALIFIERS = makeNAscii(QUALIFIER, 5);
1798     byte [][] VALUES = makeN(VALUE, 5);
1799     long [] ts = {1000, 2000, 3000, 4000, 5000};
1800 
1801     HBaseAdmin admin = new HBaseAdmin(TEST_UTIL.getConfiguration());
1802     Table ht = TEST_UTIL.createTable(TABLE, FAMILY, 5);
1803     Put put = null;
1804     Result result = null;
1805     Get get = null;
1806     Delete delete = null;
1807 
1808     // 1. put on ROW
1809     put = new Put(ROW);
1810     for (int q = 0; q < 5; q++)
1811       for (int t = 0; t < 5; t++)
1812         put.add(FAMILY, QUALIFIERS[q], ts[t], VALUES[t]);
1813     ht.put(put);
1814     admin.flush(TABLE);
1815 
1816     // 2. put on ROWS[0]
1817     byte [] ROW2 = Bytes.toBytes("myRowForTest");
1818     put = new Put(ROW2);
1819     for (int q = 0; q < 5; q++)
1820       for (int t = 0; t < 5; t++)
1821         put.add(FAMILY, QUALIFIERS[q], ts[t], VALUES[t]);
1822     ht.put(put);
1823     admin.flush(TABLE);
1824 
1825     // 3. delete on ROW
1826     delete = new Delete(ROW);
1827     // delete version <= 2000 of all columns
1828     // note: deleteFamily must be the first since it will mask
1829     // the subsequent other type deletes!
1830     delete.deleteFamily(FAMILY, ts[1]);
1831     // delete version '4000' of all columns
1832     delete.deleteFamilyVersion(FAMILY, ts[3]);
1833    // delete version <= 3000 of column 0
1834     delete.deleteColumns(FAMILY, QUALIFIERS[0], ts[2]);
1835     // delete version <= 5000 of column 2
1836     delete.deleteColumns(FAMILY, QUALIFIERS[2], ts[4]);
1837     // delete version 5000 of column 4
1838     delete.deleteColumn(FAMILY, QUALIFIERS[4], ts[4]);
1839     ht.delete(delete);
1840     admin.flush(TABLE);
1841 
1842      // 4. delete on ROWS[0]
1843     delete = new Delete(ROW2);
1844     delete.deleteFamilyVersion(FAMILY, ts[1]);  // delete version '2000'
1845     delete.deleteFamilyVersion(FAMILY, ts[3]);  // delete version '4000'
1846     ht.delete(delete);
1847     admin.flush(TABLE);
1848 
1849     // 5. check ROW
1850     get = new Get(ROW);
1851     get.addColumn(FAMILY, QUALIFIERS[0]);
1852     get.setMaxVersions(Integer.MAX_VALUE);
1853     result = ht.get(get);
1854     assertNResult(result, ROW, FAMILY, QUALIFIERS[0],
1855         new long [] {ts[4]},
1856         new byte[][] {VALUES[4]},
1857         0, 0);
1858 
1859     get = new Get(ROW);
1860     get.addColumn(FAMILY, QUALIFIERS[1]);
1861     get.setMaxVersions(Integer.MAX_VALUE);
1862     result = ht.get(get);
1863     assertNResult(result, ROW, FAMILY, QUALIFIERS[1],
1864         new long [] {ts[2], ts[4]},
1865         new byte[][] {VALUES[2], VALUES[4]},
1866         0, 1);
1867 
1868     get = new Get(ROW);
1869     get.addColumn(FAMILY, QUALIFIERS[2]);
1870     get.setMaxVersions(Integer.MAX_VALUE);
1871     result = ht.get(get);
1872     assertEquals(0, result.size());
1873 
1874     get = new Get(ROW);
1875     get.addColumn(FAMILY, QUALIFIERS[3]);
1876     get.setMaxVersions(Integer.MAX_VALUE);
1877     result = ht.get(get);
1878     assertNResult(result, ROW, FAMILY, QUALIFIERS[3],
1879         new long [] {ts[2], ts[4]},
1880         new byte[][] {VALUES[2], VALUES[4]},
1881         0, 1);
1882 
1883     get = new Get(ROW);
1884     get.addColumn(FAMILY, QUALIFIERS[4]);
1885     get.setMaxVersions(Integer.MAX_VALUE);
1886     result = ht.get(get);
1887     assertNResult(result, ROW, FAMILY, QUALIFIERS[4],
1888         new long [] {ts[2]},
1889         new byte[][] {VALUES[2]},
1890         0, 0);
1891 
1892     // 6. check ROWS[0]
1893     for (int i = 0; i < 5; i++) {
1894       get = new Get(ROW2);
1895       get.addColumn(FAMILY, QUALIFIERS[i]);
1896       get.setMaxVersions(Integer.MAX_VALUE);
1897       result = ht.get(get);
1898       // verify version '1000'/'3000'/'5000' remains for all columns
1899       assertNResult(result, ROW2, FAMILY, QUALIFIERS[i],
1900           new long [] {ts[0], ts[2], ts[4]},
1901           new byte[][] {VALUES[0], VALUES[2], VALUES[4]},
1902           0, 2);
1903     }
1904     ht.close();
1905     admin.close();
1906   }
1907 
1908   @Test
1909   public void testDeletes() throws Exception {
1910     byte [] TABLE = Bytes.toBytes("testDeletes");
1911 
1912     byte [][] ROWS = makeNAscii(ROW, 6);
1913     byte [][] FAMILIES = makeNAscii(FAMILY, 3);
1914     byte [][] VALUES = makeN(VALUE, 5);
1915     long [] ts = {1000, 2000, 3000, 4000, 5000};
1916 
1917     Table ht = TEST_UTIL.createTable(TABLE, FAMILIES, 3);
1918 
1919     Put put = new Put(ROW);
1920     put.add(FAMILIES[0], QUALIFIER, ts[0], VALUES[0]);
1921     put.add(FAMILIES[0], QUALIFIER, ts[1], VALUES[1]);
1922     ht.put(put);
1923 
1924     Delete delete = new Delete(ROW);
1925     delete.deleteFamily(FAMILIES[0], ts[0]);
1926     ht.delete(delete);
1927 
1928     Get get = new Get(ROW);
1929     get.addFamily(FAMILIES[0]);
1930     get.setMaxVersions(Integer.MAX_VALUE);
1931     Result result = ht.get(get);
1932     assertNResult(result, ROW, FAMILIES[0], QUALIFIER,
1933         new long [] {ts[1]},
1934         new byte[][] {VALUES[1]},
1935         0, 0);
1936 
1937     Scan scan = new Scan(ROW);
1938     scan.addFamily(FAMILIES[0]);
1939     scan.setMaxVersions(Integer.MAX_VALUE);
1940     result = getSingleScanResult(ht, scan);
1941     assertNResult(result, ROW, FAMILIES[0], QUALIFIER,
1942         new long [] {ts[1]},
1943         new byte[][] {VALUES[1]},
1944         0, 0);
1945 
1946     // Test delete latest version
1947     put = new Put(ROW);
1948     put.add(FAMILIES[0], QUALIFIER, ts[4], VALUES[4]);
1949     put.add(FAMILIES[0], QUALIFIER, ts[2], VALUES[2]);
1950     put.add(FAMILIES[0], QUALIFIER, ts[3], VALUES[3]);
1951     put.add(FAMILIES[0], null, ts[4], VALUES[4]);
1952     put.add(FAMILIES[0], null, ts[2], VALUES[2]);
1953     put.add(FAMILIES[0], null, ts[3], VALUES[3]);
1954     ht.put(put);
1955 
1956     delete = new Delete(ROW);
1957     delete.deleteColumn(FAMILIES[0], QUALIFIER); // ts[4]
1958     ht.delete(delete);
1959 
1960     get = new Get(ROW);
1961     get.addColumn(FAMILIES[0], QUALIFIER);
1962     get.setMaxVersions(Integer.MAX_VALUE);
1963     result = ht.get(get);
1964     assertNResult(result, ROW, FAMILIES[0], QUALIFIER,
1965         new long [] {ts[1], ts[2], ts[3]},
1966         new byte[][] {VALUES[1], VALUES[2], VALUES[3]},
1967         0, 2);
1968 
1969     scan = new Scan(ROW);
1970     scan.addColumn(FAMILIES[0], QUALIFIER);
1971     scan.setMaxVersions(Integer.MAX_VALUE);
1972     result = getSingleScanResult(ht, scan);
1973     assertNResult(result, ROW, FAMILIES[0], QUALIFIER,
1974         new long [] {ts[1], ts[2], ts[3]},
1975         new byte[][] {VALUES[1], VALUES[2], VALUES[3]},
1976         0, 2);
1977 
1978     // Test for HBASE-1847
1979     delete = new Delete(ROW);
1980     delete.deleteColumn(FAMILIES[0], null);
1981     ht.delete(delete);
1982 
1983     // Cleanup null qualifier
1984     delete = new Delete(ROW);
1985     delete.deleteColumns(FAMILIES[0], null);
1986     ht.delete(delete);
1987 
1988     // Expected client behavior might be that you can re-put deleted values
1989     // But alas, this is not to be.  We can't put them back in either case.
1990 
1991     put = new Put(ROW);
1992     put.add(FAMILIES[0], QUALIFIER, ts[0], VALUES[0]); // 1000
1993     put.add(FAMILIES[0], QUALIFIER, ts[4], VALUES[4]); // 5000
1994     ht.put(put);
1995 
1996 
1997     // It used to be due to the internal implementation of Get, that
1998     // the Get() call would return ts[4] UNLIKE the Scan below. With
1999     // the switch to using Scan for Get this is no longer the case.
2000     get = new Get(ROW);
2001     get.addFamily(FAMILIES[0]);
2002     get.setMaxVersions(Integer.MAX_VALUE);
2003     result = ht.get(get);
2004     assertNResult(result, ROW, FAMILIES[0], QUALIFIER,
2005         new long [] {ts[1], ts[2], ts[3]},
2006         new byte[][] {VALUES[1], VALUES[2], VALUES[3]},
2007         0, 2);
2008 
2009     // The Scanner returns the previous values, the expected-naive-unexpected behavior
2010 
2011     scan = new Scan(ROW);
2012     scan.addFamily(FAMILIES[0]);
2013     scan.setMaxVersions(Integer.MAX_VALUE);
2014     result = getSingleScanResult(ht, scan);
2015     assertNResult(result, ROW, FAMILIES[0], QUALIFIER,
2016         new long [] {ts[1], ts[2], ts[3]},
2017         new byte[][] {VALUES[1], VALUES[2], VALUES[3]},
2018         0, 2);
2019 
2020     // Test deleting an entire family from one row but not the other various ways
2021 
2022     put = new Put(ROWS[0]);
2023     put.add(FAMILIES[1], QUALIFIER, ts[0], VALUES[0]);
2024     put.add(FAMILIES[1], QUALIFIER, ts[1], VALUES[1]);
2025     put.add(FAMILIES[2], QUALIFIER, ts[2], VALUES[2]);
2026     put.add(FAMILIES[2], QUALIFIER, ts[3], VALUES[3]);
2027     ht.put(put);
2028 
2029     put = new Put(ROWS[1]);
2030     put.add(FAMILIES[1], QUALIFIER, ts[0], VALUES[0]);
2031     put.add(FAMILIES[1], QUALIFIER, ts[1], VALUES[1]);
2032     put.add(FAMILIES[2], QUALIFIER, ts[2], VALUES[2]);
2033     put.add(FAMILIES[2], QUALIFIER, ts[3], VALUES[3]);
2034     ht.put(put);
2035 
2036     put = new Put(ROWS[2]);
2037     put.add(FAMILIES[1], QUALIFIER, ts[0], VALUES[0]);
2038     put.add(FAMILIES[1], QUALIFIER, ts[1], VALUES[1]);
2039     put.add(FAMILIES[2], QUALIFIER, ts[2], VALUES[2]);
2040     put.add(FAMILIES[2], QUALIFIER, ts[3], VALUES[3]);
2041     ht.put(put);
2042 
2043     // Assert that above went in.
2044     get = new Get(ROWS[2]);
2045     get.addFamily(FAMILIES[1]);
2046     get.addFamily(FAMILIES[2]);
2047     get.setMaxVersions(Integer.MAX_VALUE);
2048     result = ht.get(get);
2049     assertTrue("Expected 4 key but received " + result.size() + ": " + result,
2050         result.size() == 4);
2051 
2052     delete = new Delete(ROWS[0]);
2053     delete.deleteFamily(FAMILIES[2]);
2054     ht.delete(delete);
2055 
2056     delete = new Delete(ROWS[1]);
2057     delete.deleteColumns(FAMILIES[1], QUALIFIER);
2058     ht.delete(delete);
2059 
2060     delete = new Delete(ROWS[2]);
2061     delete.deleteColumn(FAMILIES[1], QUALIFIER);
2062     delete.deleteColumn(FAMILIES[1], QUALIFIER);
2063     delete.deleteColumn(FAMILIES[2], QUALIFIER);
2064     ht.delete(delete);
2065 
2066     get = new Get(ROWS[0]);
2067     get.addFamily(FAMILIES[1]);
2068     get.addFamily(FAMILIES[2]);
2069     get.setMaxVersions(Integer.MAX_VALUE);
2070     result = ht.get(get);
2071     assertTrue("Expected 2 keys but received " + result.size(),
2072         result.size() == 2);
2073     assertNResult(result, ROWS[0], FAMILIES[1], QUALIFIER,
2074         new long [] {ts[0], ts[1]},
2075         new byte[][] {VALUES[0], VALUES[1]},
2076         0, 1);
2077 
2078     scan = new Scan(ROWS[0]);
2079     scan.addFamily(FAMILIES[1]);
2080     scan.addFamily(FAMILIES[2]);
2081     scan.setMaxVersions(Integer.MAX_VALUE);
2082     result = getSingleScanResult(ht, scan);
2083     assertTrue("Expected 2 keys but received " + result.size(),
2084         result.size() == 2);
2085     assertNResult(result, ROWS[0], FAMILIES[1], QUALIFIER,
2086         new long [] {ts[0], ts[1]},
2087         new byte[][] {VALUES[0], VALUES[1]},
2088         0, 1);
2089 
2090     get = new Get(ROWS[1]);
2091     get.addFamily(FAMILIES[1]);
2092     get.addFamily(FAMILIES[2]);
2093     get.setMaxVersions(Integer.MAX_VALUE);
2094     result = ht.get(get);
2095     assertTrue("Expected 2 keys but received " + result.size(),
2096         result.size() == 2);
2097 
2098     scan = new Scan(ROWS[1]);
2099     scan.addFamily(FAMILIES[1]);
2100     scan.addFamily(FAMILIES[2]);
2101     scan.setMaxVersions(Integer.MAX_VALUE);
2102     result = getSingleScanResult(ht, scan);
2103     assertTrue("Expected 2 keys but received " + result.size(),
2104         result.size() == 2);
2105 
2106     get = new Get(ROWS[2]);
2107     get.addFamily(FAMILIES[1]);
2108     get.addFamily(FAMILIES[2]);
2109     get.setMaxVersions(Integer.MAX_VALUE);
2110     result = ht.get(get);
2111     assertEquals(1, result.size());
2112     assertNResult(result, ROWS[2], FAMILIES[2], QUALIFIER,
2113         new long [] {ts[2]},
2114         new byte[][] {VALUES[2]},
2115         0, 0);
2116 
2117     scan = new Scan(ROWS[2]);
2118     scan.addFamily(FAMILIES[1]);
2119     scan.addFamily(FAMILIES[2]);
2120     scan.setMaxVersions(Integer.MAX_VALUE);
2121     result = getSingleScanResult(ht, scan);
2122     assertEquals(1, result.size());
2123     assertNResult(result, ROWS[2], FAMILIES[2], QUALIFIER,
2124         new long [] {ts[2]},
2125         new byte[][] {VALUES[2]},
2126         0, 0);
2127 
2128     // Test if we delete the family first in one row (HBASE-1541)
2129 
2130     delete = new Delete(ROWS[3]);
2131     delete.deleteFamily(FAMILIES[1]);
2132     ht.delete(delete);
2133 
2134     put = new Put(ROWS[3]);
2135     put.add(FAMILIES[2], QUALIFIER, VALUES[0]);
2136     ht.put(put);
2137 
2138     put = new Put(ROWS[4]);
2139     put.add(FAMILIES[1], QUALIFIER, VALUES[1]);
2140     put.add(FAMILIES[2], QUALIFIER, VALUES[2]);
2141     ht.put(put);
2142 
2143     get = new Get(ROWS[3]);
2144     get.addFamily(FAMILIES[1]);
2145     get.addFamily(FAMILIES[2]);
2146     get.setMaxVersions(Integer.MAX_VALUE);
2147     result = ht.get(get);
2148     assertTrue("Expected 1 key but received " + result.size(),
2149         result.size() == 1);
2150 
2151     get = new Get(ROWS[4]);
2152     get.addFamily(FAMILIES[1]);
2153     get.addFamily(FAMILIES[2]);
2154     get.setMaxVersions(Integer.MAX_VALUE);
2155     result = ht.get(get);
2156     assertTrue("Expected 2 keys but received " + result.size(),
2157         result.size() == 2);
2158 
2159     scan = new Scan(ROWS[3]);
2160     scan.addFamily(FAMILIES[1]);
2161     scan.addFamily(FAMILIES[2]);
2162     scan.setMaxVersions(Integer.MAX_VALUE);
2163     ResultScanner scanner = ht.getScanner(scan);
2164     result = scanner.next();
2165     assertTrue("Expected 1 key but received " + result.size(),
2166         result.size() == 1);
2167     assertTrue(Bytes.equals(CellUtil.cloneRow(result.rawCells()[0]), ROWS[3]));
2168     assertTrue(Bytes.equals(CellUtil.cloneValue(result.rawCells()[0]), VALUES[0]));
2169     result = scanner.next();
2170     assertTrue("Expected 2 keys but received " + result.size(),
2171         result.size() == 2);
2172     assertTrue(Bytes.equals(CellUtil.cloneRow(result.rawCells()[0]), ROWS[4]));
2173     assertTrue(Bytes.equals(CellUtil.cloneRow(result.rawCells()[1]), ROWS[4]));
2174     assertTrue(Bytes.equals(CellUtil.cloneValue(result.rawCells()[0]), VALUES[1]));
2175     assertTrue(Bytes.equals(CellUtil.cloneValue(result.rawCells()[1]), VALUES[2]));
2176     scanner.close();
2177 
2178     // Add test of bulk deleting.
2179     for (int i = 0; i < 10; i++) {
2180       byte [] bytes = Bytes.toBytes(i);
2181       put = new Put(bytes);
2182       put.setDurability(Durability.SKIP_WAL);
2183       put.add(FAMILIES[0], QUALIFIER, bytes);
2184       ht.put(put);
2185     }
2186     for (int i = 0; i < 10; i++) {
2187       byte [] bytes = Bytes.toBytes(i);
2188       get = new Get(bytes);
2189       get.addFamily(FAMILIES[0]);
2190       result = ht.get(get);
2191       assertTrue(result.size() == 1);
2192     }
2193     ArrayList<Delete> deletes = new ArrayList<Delete>();
2194     for (int i = 0; i < 10; i++) {
2195       byte [] bytes = Bytes.toBytes(i);
2196       delete = new Delete(bytes);
2197       delete.deleteFamily(FAMILIES[0]);
2198       deletes.add(delete);
2199     }
2200     ht.delete(deletes);
2201     for (int i = 0; i < 10; i++) {
2202       byte [] bytes = Bytes.toBytes(i);
2203       get = new Get(bytes);
2204       get.addFamily(FAMILIES[0]);
2205       result = ht.get(get);
2206       assertTrue(result.size() == 0);
2207     }
2208   }
2209 
2210   /*
2211    * Baseline "scalability" test.
2212    *
2213    * Tests one hundred families, one million columns, one million versions
2214    */
2215   @Ignore @Test
2216   public void testMillions() throws Exception {
2217 
2218     // 100 families
2219 
2220     // millions of columns
2221 
2222     // millions of versions
2223 
2224   }
2225 
2226   @Ignore @Test
2227   public void testMultipleRegionsAndBatchPuts() throws Exception {
2228     // Two family table
2229 
2230     // Insert lots of rows
2231 
2232     // Insert to the same row with batched puts
2233 
2234     // Insert to multiple rows with batched puts
2235 
2236     // Split the table
2237 
2238     // Get row from first region
2239 
2240     // Get row from second region
2241 
2242     // Scan all rows
2243 
2244     // Insert to multiple regions with batched puts
2245 
2246     // Get row from first region
2247 
2248     // Get row from second region
2249 
2250     // Scan all rows
2251 
2252 
2253   }
2254 
2255   @Ignore @Test
2256   public void testMultipleRowMultipleFamily() throws Exception {
2257 
2258   }
2259 
2260   //
2261   // JIRA Testers
2262   //
2263 
2264   /**
2265    * HBASE-867
2266    *    If millions of columns in a column family, hbase scanner won't come up
2267    *
2268    *    Test will create numRows rows, each with numColsPerRow columns
2269    *    (1 version each), and attempt to scan them all.
2270    *
2271    *    To test at scale, up numColsPerRow to the millions
2272    *    (have not gotten that to work running as junit though)
2273    */
2274   @Test
2275   public void testJiraTest867() throws Exception {
2276     int numRows = 10;
2277     int numColsPerRow = 2000;
2278 
2279     byte [] TABLE = Bytes.toBytes("testJiraTest867");
2280 
2281     byte [][] ROWS = makeN(ROW, numRows);
2282     byte [][] QUALIFIERS = makeN(QUALIFIER, numColsPerRow);
2283 
2284     Table ht = TEST_UTIL.createTable(TABLE, FAMILY);
2285 
2286     // Insert rows
2287 
2288     for(int i=0;i<numRows;i++) {
2289       Put put = new Put(ROWS[i]);
2290       put.setDurability(Durability.SKIP_WAL);
2291       for(int j=0;j<numColsPerRow;j++) {
2292         put.add(FAMILY, QUALIFIERS[j], QUALIFIERS[j]);
2293       }
2294       assertTrue("Put expected to contain " + numColsPerRow + " columns but " +
2295           "only contains " + put.size(), put.size() == numColsPerRow);
2296       ht.put(put);
2297     }
2298 
2299     // Get a row
2300     Get get = new Get(ROWS[numRows-1]);
2301     Result result = ht.get(get);
2302     assertNumKeys(result, numColsPerRow);
2303     Cell [] keys = result.rawCells();
2304     for(int i=0;i<result.size();i++) {
2305       assertKey(keys[i], ROWS[numRows-1], FAMILY, QUALIFIERS[i], QUALIFIERS[i]);
2306     }
2307 
2308     // Scan the rows
2309     Scan scan = new Scan();
2310     ResultScanner scanner = ht.getScanner(scan);
2311     int rowCount = 0;
2312     while((result = scanner.next()) != null) {
2313       assertNumKeys(result, numColsPerRow);
2314       Cell [] kvs = result.rawCells();
2315       for(int i=0;i<numColsPerRow;i++) {
2316         assertKey(kvs[i], ROWS[rowCount], FAMILY, QUALIFIERS[i], QUALIFIERS[i]);
2317       }
2318       rowCount++;
2319     }
2320     scanner.close();
2321     assertTrue("Expected to scan " + numRows + " rows but actually scanned "
2322         + rowCount + " rows", rowCount == numRows);
2323 
2324     // flush and try again
2325 
2326     TEST_UTIL.flush();
2327 
2328     // Get a row
2329     get = new Get(ROWS[numRows-1]);
2330     result = ht.get(get);
2331     assertNumKeys(result, numColsPerRow);
2332     keys = result.rawCells();
2333     for(int i=0;i<result.size();i++) {
2334       assertKey(keys[i], ROWS[numRows-1], FAMILY, QUALIFIERS[i], QUALIFIERS[i]);
2335     }
2336 
2337     // Scan the rows
2338     scan = new Scan();
2339     scanner = ht.getScanner(scan);
2340     rowCount = 0;
2341     while((result = scanner.next()) != null) {
2342       assertNumKeys(result, numColsPerRow);
2343       Cell [] kvs = result.rawCells();
2344       for(int i=0;i<numColsPerRow;i++) {
2345         assertKey(kvs[i], ROWS[rowCount], FAMILY, QUALIFIERS[i], QUALIFIERS[i]);
2346       }
2347       rowCount++;
2348     }
2349     scanner.close();
2350     assertTrue("Expected to scan " + numRows + " rows but actually scanned "
2351         + rowCount + " rows", rowCount == numRows);
2352 
2353   }
2354 
2355   /**
2356    * HBASE-861
2357    *    get with timestamp will return a value if there is a version with an
2358    *    earlier timestamp
2359    */
2360   @Test
2361   public void testJiraTest861() throws Exception {
2362 
2363     byte [] TABLE = Bytes.toBytes("testJiraTest861");
2364     byte [][] VALUES = makeNAscii(VALUE, 7);
2365     long [] STAMPS = makeStamps(7);
2366 
2367     Table ht = TEST_UTIL.createTable(TABLE, FAMILY, 10);
2368 
2369     // Insert three versions
2370 
2371     Put put = new Put(ROW);
2372     put.add(FAMILY, QUALIFIER, STAMPS[3], VALUES[3]);
2373     put.add(FAMILY, QUALIFIER, STAMPS[2], VALUES[2]);
2374     put.add(FAMILY, QUALIFIER, STAMPS[4], VALUES[4]);
2375     ht.put(put);
2376 
2377     // Get the middle value
2378     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[2], VALUES[2]);
2379 
2380     // Try to get one version before (expect fail)
2381     getVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[1]);
2382 
2383     // Try to get one version after (expect fail)
2384     getVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[5]);
2385 
2386     // Try same from storefile
2387     TEST_UTIL.flush();
2388     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[2], VALUES[2]);
2389     getVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[1]);
2390     getVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[5]);
2391 
2392     // Insert two more versions surrounding others, into memstore
2393     put = new Put(ROW);
2394     put.add(FAMILY, QUALIFIER, STAMPS[0], VALUES[0]);
2395     put.add(FAMILY, QUALIFIER, STAMPS[6], VALUES[6]);
2396     ht.put(put);
2397 
2398     // Check we can get everything we should and can't get what we shouldn't
2399     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[0], VALUES[0]);
2400     getVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[1]);
2401     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[2], VALUES[2]);
2402     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[3], VALUES[3]);
2403     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[4], VALUES[4]);
2404     getVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[5]);
2405     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[6], VALUES[6]);
2406 
2407     // Try same from two storefiles
2408     TEST_UTIL.flush();
2409     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[0], VALUES[0]);
2410     getVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[1]);
2411     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[2], VALUES[2]);
2412     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[3], VALUES[3]);
2413     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[4], VALUES[4]);
2414     getVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[5]);
2415     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[6], VALUES[6]);
2416 
2417   }
2418 
2419   /**
2420    * HBASE-33
2421    *    Add a HTable get/obtainScanner method that retrieves all versions of a
2422    *    particular column and row between two timestamps
2423    */
2424   @Test
2425   public void testJiraTest33() throws Exception {
2426 
2427     byte [] TABLE = Bytes.toBytes("testJiraTest33");
2428     byte [][] VALUES = makeNAscii(VALUE, 7);
2429     long [] STAMPS = makeStamps(7);
2430 
2431     Table ht = TEST_UTIL.createTable(TABLE, FAMILY, 10);
2432 
2433     // Insert lots versions
2434 
2435     Put put = new Put(ROW);
2436     put.add(FAMILY, QUALIFIER, STAMPS[0], VALUES[0]);
2437     put.add(FAMILY, QUALIFIER, STAMPS[1], VALUES[1]);
2438     put.add(FAMILY, QUALIFIER, STAMPS[2], VALUES[2]);
2439     put.add(FAMILY, QUALIFIER, STAMPS[3], VALUES[3]);
2440     put.add(FAMILY, QUALIFIER, STAMPS[4], VALUES[4]);
2441     put.add(FAMILY, QUALIFIER, STAMPS[5], VALUES[5]);
2442     ht.put(put);
2443 
2444     getVersionRangeAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS, VALUES, 0, 5);
2445     getVersionRangeAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS, VALUES, 0, 2);
2446     getVersionRangeAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS, VALUES, 4, 5);
2447     getVersionRangeAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS, VALUES, 2, 3);
2448 
2449     scanVersionRangeAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS, VALUES, 0, 5);
2450     scanVersionRangeAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS, VALUES, 0, 2);
2451     scanVersionRangeAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS, VALUES, 4, 5);
2452     scanVersionRangeAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS, VALUES, 2, 3);
2453 
2454     // Try same from storefile
2455     TEST_UTIL.flush();
2456 
2457     getVersionRangeAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS, VALUES, 0, 5);
2458     getVersionRangeAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS, VALUES, 0, 2);
2459     getVersionRangeAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS, VALUES, 4, 5);
2460     getVersionRangeAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS, VALUES, 2, 3);
2461 
2462     scanVersionRangeAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS, VALUES, 0, 5);
2463     scanVersionRangeAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS, VALUES, 0, 2);
2464     scanVersionRangeAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS, VALUES, 4, 5);
2465     scanVersionRangeAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS, VALUES, 2, 3);
2466 
2467   }
2468 
2469   /**
2470    * HBASE-1014
2471    *    commit(BatchUpdate) method should return timestamp
2472    */
2473   @Test
2474   public void testJiraTest1014() throws Exception {
2475 
2476     byte [] TABLE = Bytes.toBytes("testJiraTest1014");
2477 
2478     Table ht = TEST_UTIL.createTable(TABLE, FAMILY, 10);
2479 
2480     long manualStamp = 12345;
2481 
2482     // Insert lots versions
2483 
2484     Put put = new Put(ROW);
2485     put.add(FAMILY, QUALIFIER, manualStamp, VALUE);
2486     ht.put(put);
2487 
2488     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, manualStamp, VALUE);
2489     getVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, manualStamp-1);
2490     getVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, manualStamp+1);
2491 
2492   }
2493 
2494   /**
2495    * HBASE-1182
2496    *    Scan for columns > some timestamp
2497    */
2498   @Test
2499   public void testJiraTest1182() throws Exception {
2500 
2501     byte [] TABLE = Bytes.toBytes("testJiraTest1182");
2502     byte [][] VALUES = makeNAscii(VALUE, 7);
2503     long [] STAMPS = makeStamps(7);
2504 
2505     Table ht = TEST_UTIL.createTable(TABLE, FAMILY, 10);
2506 
2507     // Insert lots versions
2508 
2509     Put put = new Put(ROW);
2510     put.add(FAMILY, QUALIFIER, STAMPS[0], VALUES[0]);
2511     put.add(FAMILY, QUALIFIER, STAMPS[1], VALUES[1]);
2512     put.add(FAMILY, QUALIFIER, STAMPS[2], VALUES[2]);
2513     put.add(FAMILY, QUALIFIER, STAMPS[3], VALUES[3]);
2514     put.add(FAMILY, QUALIFIER, STAMPS[4], VALUES[4]);
2515     put.add(FAMILY, QUALIFIER, STAMPS[5], VALUES[5]);
2516     ht.put(put);
2517 
2518     getVersionRangeAndVerifyGreaterThan(ht, ROW, FAMILY, QUALIFIER, STAMPS, VALUES, 0, 5);
2519     getVersionRangeAndVerifyGreaterThan(ht, ROW, FAMILY, QUALIFIER, STAMPS, VALUES, 2, 5);
2520     getVersionRangeAndVerifyGreaterThan(ht, ROW, FAMILY, QUALIFIER, STAMPS, VALUES, 4, 5);
2521 
2522     scanVersionRangeAndVerifyGreaterThan(ht, ROW, FAMILY, QUALIFIER, STAMPS, VALUES, 0, 5);
2523     scanVersionRangeAndVerifyGreaterThan(ht, ROW, FAMILY, QUALIFIER, STAMPS, VALUES, 2, 5);
2524     scanVersionRangeAndVerifyGreaterThan(ht, ROW, FAMILY, QUALIFIER, STAMPS, VALUES, 4, 5);
2525 
2526     // Try same from storefile
2527     TEST_UTIL.flush();
2528 
2529     getVersionRangeAndVerifyGreaterThan(ht, ROW, FAMILY, QUALIFIER, STAMPS, VALUES, 0, 5);
2530     getVersionRangeAndVerifyGreaterThan(ht, ROW, FAMILY, QUALIFIER, STAMPS, VALUES, 2, 5);
2531     getVersionRangeAndVerifyGreaterThan(ht, ROW, FAMILY, QUALIFIER, STAMPS, VALUES, 4, 5);
2532 
2533     scanVersionRangeAndVerifyGreaterThan(ht, ROW, FAMILY, QUALIFIER, STAMPS, VALUES, 0, 5);
2534     scanVersionRangeAndVerifyGreaterThan(ht, ROW, FAMILY, QUALIFIER, STAMPS, VALUES, 2, 5);
2535     scanVersionRangeAndVerifyGreaterThan(ht, ROW, FAMILY, QUALIFIER, STAMPS, VALUES, 4, 5);
2536   }
2537 
2538   /**
2539    * HBASE-52
2540    *    Add a means of scanning over all versions
2541    */
2542   @Test
2543   public void testJiraTest52() throws Exception {
2544     byte [] TABLE = Bytes.toBytes("testJiraTest52");
2545     byte [][] VALUES = makeNAscii(VALUE, 7);
2546     long [] STAMPS = makeStamps(7);
2547 
2548     Table ht = TEST_UTIL.createTable(TABLE, FAMILY, 10);
2549 
2550     // Insert lots versions
2551 
2552     Put put = new Put(ROW);
2553     put.add(FAMILY, QUALIFIER, STAMPS[0], VALUES[0]);
2554     put.add(FAMILY, QUALIFIER, STAMPS[1], VALUES[1]);
2555     put.add(FAMILY, QUALIFIER, STAMPS[2], VALUES[2]);
2556     put.add(FAMILY, QUALIFIER, STAMPS[3], VALUES[3]);
2557     put.add(FAMILY, QUALIFIER, STAMPS[4], VALUES[4]);
2558     put.add(FAMILY, QUALIFIER, STAMPS[5], VALUES[5]);
2559     ht.put(put);
2560 
2561     getAllVersionsAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS, VALUES, 0, 5);
2562 
2563     scanAllVersionsAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS, VALUES, 0, 5);
2564 
2565     // Try same from storefile
2566     TEST_UTIL.flush();
2567 
2568     getAllVersionsAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS, VALUES, 0, 5);
2569 
2570     scanAllVersionsAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS, VALUES, 0, 5);
2571   }
2572 
2573   //
2574   // Bulk Testers
2575   //
2576 
2577   private void getVersionRangeAndVerifyGreaterThan(Table ht, byte [] row,
2578       byte [] family, byte [] qualifier, long [] stamps, byte [][] values,
2579       int start, int end)
2580   throws IOException {
2581     Get get = new Get(row);
2582     get.addColumn(family, qualifier);
2583     get.setMaxVersions(Integer.MAX_VALUE);
2584     get.setTimeRange(stamps[start+1], Long.MAX_VALUE);
2585     Result result = ht.get(get);
2586     assertNResult(result, row, family, qualifier, stamps, values, start+1, end);
2587   }
2588 
2589   private void getVersionRangeAndVerify(Table ht, byte [] row, byte [] family,
2590       byte [] qualifier, long [] stamps, byte [][] values, int start, int end)
2591   throws IOException {
2592     Get get = new Get(row);
2593     get.addColumn(family, qualifier);
2594     get.setMaxVersions(Integer.MAX_VALUE);
2595     get.setTimeRange(stamps[start], stamps[end]+1);
2596     Result result = ht.get(get);
2597     assertNResult(result, row, family, qualifier, stamps, values, start, end);
2598   }
2599 
2600   private void getAllVersionsAndVerify(Table ht, byte [] row, byte [] family,
2601       byte [] qualifier, long [] stamps, byte [][] values, int start, int end)
2602   throws IOException {
2603     Get get = new Get(row);
2604     get.addColumn(family, qualifier);
2605     get.setMaxVersions(Integer.MAX_VALUE);
2606     Result result = ht.get(get);
2607     assertNResult(result, row, family, qualifier, stamps, values, start, end);
2608   }
2609 
2610   private void scanVersionRangeAndVerifyGreaterThan(Table ht, byte [] row,
2611       byte [] family, byte [] qualifier, long [] stamps, byte [][] values,
2612       int start, int end)
2613   throws IOException {
2614     Scan scan = new Scan(row);
2615     scan.addColumn(family, qualifier);
2616     scan.setMaxVersions(Integer.MAX_VALUE);
2617     scan.setTimeRange(stamps[start+1], Long.MAX_VALUE);
2618     Result result = getSingleScanResult(ht, scan);
2619     assertNResult(result, row, family, qualifier, stamps, values, start+1, end);
2620   }
2621 
2622   private void scanVersionRangeAndVerify(Table ht, byte [] row, byte [] family,
2623       byte [] qualifier, long [] stamps, byte [][] values, int start, int end)
2624   throws IOException {
2625     Scan scan = new Scan(row);
2626     scan.addColumn(family, qualifier);
2627     scan.setMaxVersions(Integer.MAX_VALUE);
2628     scan.setTimeRange(stamps[start], stamps[end]+1);
2629     Result result = getSingleScanResult(ht, scan);
2630     assertNResult(result, row, family, qualifier, stamps, values, start, end);
2631   }
2632 
2633   private void scanAllVersionsAndVerify(Table ht, byte [] row, byte [] family,
2634       byte [] qualifier, long [] stamps, byte [][] values, int start, int end)
2635   throws IOException {
2636     Scan scan = new Scan(row);
2637     scan.addColumn(family, qualifier);
2638     scan.setMaxVersions(Integer.MAX_VALUE);
2639     Result result = getSingleScanResult(ht, scan);
2640     assertNResult(result, row, family, qualifier, stamps, values, start, end);
2641   }
2642 
2643   private void getVersionAndVerify(Table ht, byte [] row, byte [] family,
2644       byte [] qualifier, long stamp, byte [] value)
2645   throws Exception {
2646     Get get = new Get(row);
2647     get.addColumn(family, qualifier);
2648     get.setTimeStamp(stamp);
2649     get.setMaxVersions(Integer.MAX_VALUE);
2650     Result result = ht.get(get);
2651     assertSingleResult(result, row, family, qualifier, stamp, value);
2652   }
2653 
2654   private void getVersionAndVerifyMissing(Table ht, byte [] row, byte [] family,
2655       byte [] qualifier, long stamp)
2656   throws Exception {
2657     Get get = new Get(row);
2658     get.addColumn(family, qualifier);
2659     get.setTimeStamp(stamp);
2660     get.setMaxVersions(Integer.MAX_VALUE);
2661     Result result = ht.get(get);
2662     assertEmptyResult(result);
2663   }
2664 
2665   private void scanVersionAndVerify(Table ht, byte [] row, byte [] family,
2666       byte [] qualifier, long stamp, byte [] value)
2667   throws Exception {
2668     Scan scan = new Scan(row);
2669     scan.addColumn(family, qualifier);
2670     scan.setTimeStamp(stamp);
2671     scan.setMaxVersions(Integer.MAX_VALUE);
2672     Result result = getSingleScanResult(ht, scan);
2673     assertSingleResult(result, row, family, qualifier, stamp, value);
2674   }
2675 
2676   private void scanVersionAndVerifyMissing(Table ht, byte [] row,
2677       byte [] family, byte [] qualifier, long stamp)
2678   throws Exception {
2679     Scan scan = new Scan(row);
2680     scan.addColumn(family, qualifier);
2681     scan.setTimeStamp(stamp);
2682     scan.setMaxVersions(Integer.MAX_VALUE);
2683     Result result = getSingleScanResult(ht, scan);
2684     assertNullResult(result);
2685   }
2686 
2687   private void getTestNull(Table ht, byte [] row, byte [] family,
2688       byte [] value)
2689   throws Exception {
2690 
2691     Get get = new Get(row);
2692     get.addColumn(family, null);
2693     Result result = ht.get(get);
2694     assertSingleResult(result, row, family, null, value);
2695 
2696     get = new Get(row);
2697     get.addColumn(family, HConstants.EMPTY_BYTE_ARRAY);
2698     result = ht.get(get);
2699     assertSingleResult(result, row, family, HConstants.EMPTY_BYTE_ARRAY, value);
2700 
2701     get = new Get(row);
2702     get.addFamily(family);
2703     result = ht.get(get);
2704     assertSingleResult(result, row, family, HConstants.EMPTY_BYTE_ARRAY, value);
2705 
2706     get = new Get(row);
2707     result = ht.get(get);
2708     assertSingleResult(result, row, family, HConstants.EMPTY_BYTE_ARRAY, value);
2709 
2710   }
2711 
2712   private void scanTestNull(Table ht, byte[] row, byte[] family, byte[] value)
2713       throws Exception {
2714     scanTestNull(ht, row, family, value, false);
2715   }
2716 
2717   private void scanTestNull(Table ht, byte[] row, byte[] family, byte[] value,
2718       boolean isReversedScan) throws Exception {
2719 
2720     Scan scan = new Scan();
2721     scan.setReversed(isReversedScan);
2722     scan.addColumn(family, null);
2723     Result result = getSingleScanResult(ht, scan);
2724     assertSingleResult(result, row, family, HConstants.EMPTY_BYTE_ARRAY, value);
2725 
2726     scan = new Scan();
2727     scan.setReversed(isReversedScan);
2728     scan.addColumn(family, HConstants.EMPTY_BYTE_ARRAY);
2729     result = getSingleScanResult(ht, scan);
2730     assertSingleResult(result, row, family, HConstants.EMPTY_BYTE_ARRAY, value);
2731 
2732     scan = new Scan();
2733     scan.setReversed(isReversedScan);
2734     scan.addFamily(family);
2735     result = getSingleScanResult(ht, scan);
2736     assertSingleResult(result, row, family, HConstants.EMPTY_BYTE_ARRAY, value);
2737 
2738     scan = new Scan();
2739     scan.setReversed(isReversedScan);
2740     result = getSingleScanResult(ht, scan);
2741     assertSingleResult(result, row, family, HConstants.EMPTY_BYTE_ARRAY, value);
2742 
2743   }
2744 
2745   private void singleRowGetTest(Table ht, byte [][] ROWS, byte [][] FAMILIES,
2746       byte [][] QUALIFIERS, byte [][] VALUES)
2747   throws Exception {
2748 
2749     // Single column from memstore
2750     Get get = new Get(ROWS[0]);
2751     get.addColumn(FAMILIES[4], QUALIFIERS[0]);
2752     Result result = ht.get(get);
2753     assertSingleResult(result, ROWS[0], FAMILIES[4], QUALIFIERS[0], VALUES[0]);
2754 
2755     // Single column from storefile
2756     get = new Get(ROWS[0]);
2757     get.addColumn(FAMILIES[2], QUALIFIERS[2]);
2758     result = ht.get(get);
2759     assertSingleResult(result, ROWS[0], FAMILIES[2], QUALIFIERS[2], VALUES[2]);
2760 
2761     // Single column from storefile, family match
2762     get = new Get(ROWS[0]);
2763     get.addFamily(FAMILIES[7]);
2764     result = ht.get(get);
2765     assertSingleResult(result, ROWS[0], FAMILIES[7], QUALIFIERS[7], VALUES[7]);
2766 
2767     // Two columns, one from memstore one from storefile, same family,
2768     // wildcard match
2769     get = new Get(ROWS[0]);
2770     get.addFamily(FAMILIES[4]);
2771     result = ht.get(get);
2772     assertDoubleResult(result, ROWS[0], FAMILIES[4], QUALIFIERS[0], VALUES[0],
2773         FAMILIES[4], QUALIFIERS[4], VALUES[4]);
2774 
2775     // Two columns, one from memstore one from storefile, same family,
2776     // explicit match
2777     get = new Get(ROWS[0]);
2778     get.addColumn(FAMILIES[4], QUALIFIERS[0]);
2779     get.addColumn(FAMILIES[4], QUALIFIERS[4]);
2780     result = ht.get(get);
2781     assertDoubleResult(result, ROWS[0], FAMILIES[4], QUALIFIERS[0], VALUES[0],
2782         FAMILIES[4], QUALIFIERS[4], VALUES[4]);
2783 
2784     // Three column, one from memstore two from storefile, different families,
2785     // wildcard match
2786     get = new Get(ROWS[0]);
2787     get.addFamily(FAMILIES[4]);
2788     get.addFamily(FAMILIES[7]);
2789     result = ht.get(get);
2790     assertNResult(result, ROWS[0], FAMILIES, QUALIFIERS, VALUES,
2791         new int [][] { {4, 0, 0}, {4, 4, 4}, {7, 7, 7} });
2792 
2793     // Multiple columns from everywhere storefile, many family, wildcard
2794     get = new Get(ROWS[0]);
2795     get.addFamily(FAMILIES[2]);
2796     get.addFamily(FAMILIES[4]);
2797     get.addFamily(FAMILIES[6]);
2798     get.addFamily(FAMILIES[7]);
2799     result = ht.get(get);
2800     assertNResult(result, ROWS[0], FAMILIES, QUALIFIERS, VALUES,
2801         new int [][] {
2802           {2, 2, 2}, {2, 4, 4}, {4, 0, 0}, {4, 4, 4}, {6, 6, 6}, {6, 7, 7}, {7, 7, 7}
2803     });
2804 
2805     // Multiple columns from everywhere storefile, many family, wildcard
2806     get = new Get(ROWS[0]);
2807     get.addColumn(FAMILIES[2], QUALIFIERS[2]);
2808     get.addColumn(FAMILIES[2], QUALIFIERS[4]);
2809     get.addColumn(FAMILIES[4], QUALIFIERS[0]);
2810     get.addColumn(FAMILIES[4], QUALIFIERS[4]);
2811     get.addColumn(FAMILIES[6], QUALIFIERS[6]);
2812     get.addColumn(FAMILIES[6], QUALIFIERS[7]);
2813     get.addColumn(FAMILIES[7], QUALIFIERS[7]);
2814     get.addColumn(FAMILIES[7], QUALIFIERS[8]);
2815     result = ht.get(get);
2816     assertNResult(result, ROWS[0], FAMILIES, QUALIFIERS, VALUES,
2817         new int [][] {
2818           {2, 2, 2}, {2, 4, 4}, {4, 0, 0}, {4, 4, 4}, {6, 6, 6}, {6, 7, 7}, {7, 7, 7}
2819     });
2820 
2821     // Everything
2822     get = new Get(ROWS[0]);
2823     result = ht.get(get);
2824     assertNResult(result, ROWS[0], FAMILIES, QUALIFIERS, VALUES,
2825         new int [][] {
2826           {2, 2, 2}, {2, 4, 4}, {4, 0, 0}, {4, 4, 4}, {6, 6, 6}, {6, 7, 7}, {7, 7, 7}, {9, 0, 0}
2827     });
2828 
2829     // Get around inserted columns
2830 
2831     get = new Get(ROWS[1]);
2832     result = ht.get(get);
2833     assertEmptyResult(result);
2834 
2835     get = new Get(ROWS[0]);
2836     get.addColumn(FAMILIES[4], QUALIFIERS[3]);
2837     get.addColumn(FAMILIES[2], QUALIFIERS[3]);
2838     result = ht.get(get);
2839     assertEmptyResult(result);
2840 
2841   }
2842 
2843   private void singleRowScanTest(Table ht, byte [][] ROWS, byte [][] FAMILIES,
2844       byte [][] QUALIFIERS, byte [][] VALUES)
2845   throws Exception {
2846 
2847     // Single column from memstore
2848     Scan scan = new Scan();
2849     scan.addColumn(FAMILIES[4], QUALIFIERS[0]);
2850     Result result = getSingleScanResult(ht, scan);
2851     assertSingleResult(result, ROWS[0], FAMILIES[4], QUALIFIERS[0], VALUES[0]);
2852 
2853     // Single column from storefile
2854     scan = new Scan();
2855     scan.addColumn(FAMILIES[2], QUALIFIERS[2]);
2856     result = getSingleScanResult(ht, scan);
2857     assertSingleResult(result, ROWS[0], FAMILIES[2], QUALIFIERS[2], VALUES[2]);
2858 
2859     // Single column from storefile, family match
2860     scan = new Scan();
2861     scan.addFamily(FAMILIES[7]);
2862     result = getSingleScanResult(ht, scan);
2863     assertSingleResult(result, ROWS[0], FAMILIES[7], QUALIFIERS[7], VALUES[7]);
2864 
2865     // Two columns, one from memstore one from storefile, same family,
2866     // wildcard match
2867     scan = new Scan();
2868     scan.addFamily(FAMILIES[4]);
2869     result = getSingleScanResult(ht, scan);
2870     assertDoubleResult(result, ROWS[0], FAMILIES[4], QUALIFIERS[0], VALUES[0],
2871         FAMILIES[4], QUALIFIERS[4], VALUES[4]);
2872 
2873     // Two columns, one from memstore one from storefile, same family,
2874     // explicit match
2875     scan = new Scan();
2876     scan.addColumn(FAMILIES[4], QUALIFIERS[0]);
2877     scan.addColumn(FAMILIES[4], QUALIFIERS[4]);
2878     result = getSingleScanResult(ht, scan);
2879     assertDoubleResult(result, ROWS[0], FAMILIES[4], QUALIFIERS[0], VALUES[0],
2880         FAMILIES[4], QUALIFIERS[4], VALUES[4]);
2881 
2882     // Three column, one from memstore two from storefile, different families,
2883     // wildcard match
2884     scan = new Scan();
2885     scan.addFamily(FAMILIES[4]);
2886     scan.addFamily(FAMILIES[7]);
2887     result = getSingleScanResult(ht, scan);
2888     assertNResult(result, ROWS[0], FAMILIES, QUALIFIERS, VALUES,
2889         new int [][] { {4, 0, 0}, {4, 4, 4}, {7, 7, 7} });
2890 
2891     // Multiple columns from everywhere storefile, many family, wildcard
2892     scan = new Scan();
2893     scan.addFamily(FAMILIES[2]);
2894     scan.addFamily(FAMILIES[4]);
2895     scan.addFamily(FAMILIES[6]);
2896     scan.addFamily(FAMILIES[7]);
2897     result = getSingleScanResult(ht, scan);
2898     assertNResult(result, ROWS[0], FAMILIES, QUALIFIERS, VALUES,
2899         new int [][] {
2900           {2, 2, 2}, {2, 4, 4}, {4, 0, 0}, {4, 4, 4}, {6, 6, 6}, {6, 7, 7}, {7, 7, 7}
2901     });
2902 
2903     // Multiple columns from everywhere storefile, many family, wildcard
2904     scan = new Scan();
2905     scan.addColumn(FAMILIES[2], QUALIFIERS[2]);
2906     scan.addColumn(FAMILIES[2], QUALIFIERS[4]);
2907     scan.addColumn(FAMILIES[4], QUALIFIERS[0]);
2908     scan.addColumn(FAMILIES[4], QUALIFIERS[4]);
2909     scan.addColumn(FAMILIES[6], QUALIFIERS[6]);
2910     scan.addColumn(FAMILIES[6], QUALIFIERS[7]);
2911     scan.addColumn(FAMILIES[7], QUALIFIERS[7]);
2912     scan.addColumn(FAMILIES[7], QUALIFIERS[8]);
2913     result = getSingleScanResult(ht, scan);
2914     assertNResult(result, ROWS[0], FAMILIES, QUALIFIERS, VALUES,
2915         new int [][] {
2916           {2, 2, 2}, {2, 4, 4}, {4, 0, 0}, {4, 4, 4}, {6, 6, 6}, {6, 7, 7}, {7, 7, 7}
2917     });
2918 
2919     // Everything
2920     scan = new Scan();
2921     result = getSingleScanResult(ht, scan);
2922     assertNResult(result, ROWS[0], FAMILIES, QUALIFIERS, VALUES,
2923         new int [][] {
2924           {2, 2, 2}, {2, 4, 4}, {4, 0, 0}, {4, 4, 4}, {6, 6, 6}, {6, 7, 7}, {7, 7, 7}, {9, 0, 0}
2925     });
2926 
2927     // Scan around inserted columns
2928 
2929     scan = new Scan(ROWS[1]);
2930     result = getSingleScanResult(ht, scan);
2931     assertNullResult(result);
2932 
2933     scan = new Scan();
2934     scan.addColumn(FAMILIES[4], QUALIFIERS[3]);
2935     scan.addColumn(FAMILIES[2], QUALIFIERS[3]);
2936     result = getSingleScanResult(ht, scan);
2937     assertNullResult(result);
2938   }
2939 
2940   /**
2941    * Verify a single column using gets.
2942    * Expects family and qualifier arrays to be valid for at least
2943    * the range:  idx-2 < idx < idx+2
2944    */
2945   private void getVerifySingleColumn(Table ht,
2946       byte [][] ROWS, int ROWIDX,
2947       byte [][] FAMILIES, int FAMILYIDX,
2948       byte [][] QUALIFIERS, int QUALIFIERIDX,
2949       byte [][] VALUES, int VALUEIDX)
2950   throws Exception {
2951 
2952     Get get = new Get(ROWS[ROWIDX]);
2953     Result result = ht.get(get);
2954     assertSingleResult(result, ROWS[ROWIDX], FAMILIES[FAMILYIDX],
2955         QUALIFIERS[QUALIFIERIDX], VALUES[VALUEIDX]);
2956 
2957     get = new Get(ROWS[ROWIDX]);
2958     get.addFamily(FAMILIES[FAMILYIDX]);
2959     result = ht.get(get);
2960     assertSingleResult(result, ROWS[ROWIDX], FAMILIES[FAMILYIDX],
2961         QUALIFIERS[QUALIFIERIDX], VALUES[VALUEIDX]);
2962 
2963     get = new Get(ROWS[ROWIDX]);
2964     get.addFamily(FAMILIES[FAMILYIDX-2]);
2965     get.addFamily(FAMILIES[FAMILYIDX]);
2966     get.addFamily(FAMILIES[FAMILYIDX+2]);
2967     result = ht.get(get);
2968     assertSingleResult(result, ROWS[ROWIDX], FAMILIES[FAMILYIDX],
2969         QUALIFIERS[QUALIFIERIDX], VALUES[VALUEIDX]);
2970 
2971     get = new Get(ROWS[ROWIDX]);
2972     get.addColumn(FAMILIES[FAMILYIDX], QUALIFIERS[0]);
2973     result = ht.get(get);
2974     assertSingleResult(result, ROWS[ROWIDX], FAMILIES[FAMILYIDX],
2975         QUALIFIERS[QUALIFIERIDX], VALUES[VALUEIDX]);
2976 
2977     get = new Get(ROWS[ROWIDX]);
2978     get.addColumn(FAMILIES[FAMILYIDX], QUALIFIERS[1]);
2979     get.addFamily(FAMILIES[FAMILYIDX]);
2980     result = ht.get(get);
2981     assertSingleResult(result, ROWS[ROWIDX], FAMILIES[FAMILYIDX],
2982         QUALIFIERS[QUALIFIERIDX], VALUES[VALUEIDX]);
2983 
2984     get = new Get(ROWS[ROWIDX]);
2985     get.addFamily(FAMILIES[FAMILYIDX]);
2986     get.addColumn(FAMILIES[FAMILYIDX+1], QUALIFIERS[1]);
2987     get.addColumn(FAMILIES[FAMILYIDX-2], QUALIFIERS[1]);
2988     get.addFamily(FAMILIES[FAMILYIDX-1]);
2989     get.addFamily(FAMILIES[FAMILYIDX+2]);
2990     result = ht.get(get);
2991     assertSingleResult(result, ROWS[ROWIDX], FAMILIES[FAMILYIDX],
2992         QUALIFIERS[QUALIFIERIDX], VALUES[VALUEIDX]);
2993 
2994   }
2995 
2996 
2997   /**
2998    * Verify a single column using scanners.
2999    * Expects family and qualifier arrays to be valid for at least
3000    * the range:  idx-2 to idx+2
3001    * Expects row array to be valid for at least idx to idx+2
3002    */
3003   private void scanVerifySingleColumn(Table ht,
3004       byte [][] ROWS, int ROWIDX,
3005       byte [][] FAMILIES, int FAMILYIDX,
3006       byte [][] QUALIFIERS, int QUALIFIERIDX,
3007       byte [][] VALUES, int VALUEIDX)
3008   throws Exception {
3009 
3010     Scan scan = new Scan();
3011     Result result = getSingleScanResult(ht, scan);
3012     assertSingleResult(result, ROWS[ROWIDX], FAMILIES[FAMILYIDX],
3013         QUALIFIERS[QUALIFIERIDX], VALUES[VALUEIDX]);
3014 
3015     scan = new Scan(ROWS[ROWIDX]);
3016     result = getSingleScanResult(ht, scan);
3017     assertSingleResult(result, ROWS[ROWIDX], FAMILIES[FAMILYIDX],
3018         QUALIFIERS[QUALIFIERIDX], VALUES[VALUEIDX]);
3019 
3020     scan = new Scan(ROWS[ROWIDX], ROWS[ROWIDX+1]);
3021     result = getSingleScanResult(ht, scan);
3022     assertSingleResult(result, ROWS[ROWIDX], FAMILIES[FAMILYIDX],
3023         QUALIFIERS[QUALIFIERIDX], VALUES[VALUEIDX]);
3024 
3025     scan = new Scan(HConstants.EMPTY_START_ROW, ROWS[ROWIDX+1]);
3026     result = getSingleScanResult(ht, scan);
3027     assertSingleResult(result, ROWS[ROWIDX], FAMILIES[FAMILYIDX],
3028         QUALIFIERS[QUALIFIERIDX], VALUES[VALUEIDX]);
3029 
3030     scan = new Scan();
3031     scan.addFamily(FAMILIES[FAMILYIDX]);
3032     result = getSingleScanResult(ht, scan);
3033     assertSingleResult(result, ROWS[ROWIDX], FAMILIES[FAMILYIDX],
3034         QUALIFIERS[QUALIFIERIDX], VALUES[VALUEIDX]);
3035 
3036     scan = new Scan();
3037     scan.addColumn(FAMILIES[FAMILYIDX], QUALIFIERS[QUALIFIERIDX]);
3038     result = getSingleScanResult(ht, scan);
3039     assertSingleResult(result, ROWS[ROWIDX], FAMILIES[FAMILYIDX],
3040         QUALIFIERS[QUALIFIERIDX], VALUES[VALUEIDX]);
3041 
3042     scan = new Scan();
3043     scan.addColumn(FAMILIES[FAMILYIDX], QUALIFIERS[QUALIFIERIDX+1]);
3044     scan.addFamily(FAMILIES[FAMILYIDX]);
3045     result = getSingleScanResult(ht, scan);
3046     assertSingleResult(result, ROWS[ROWIDX], FAMILIES[FAMILYIDX],
3047         QUALIFIERS[QUALIFIERIDX], VALUES[VALUEIDX]);
3048 
3049     scan = new Scan();
3050     scan.addColumn(FAMILIES[FAMILYIDX-1], QUALIFIERS[QUALIFIERIDX+1]);
3051     scan.addColumn(FAMILIES[FAMILYIDX], QUALIFIERS[QUALIFIERIDX]);
3052     scan.addFamily(FAMILIES[FAMILYIDX+1]);
3053     result = getSingleScanResult(ht, scan);
3054     assertSingleResult(result, ROWS[ROWIDX], FAMILIES[FAMILYIDX],
3055         QUALIFIERS[QUALIFIERIDX], VALUES[VALUEIDX]);
3056 
3057   }
3058 
3059   /**
3060    * Verify we do not read any values by accident around a single column
3061    * Same requirements as getVerifySingleColumn
3062    */
3063   private void getVerifySingleEmpty(Table ht,
3064       byte [][] ROWS, int ROWIDX,
3065       byte [][] FAMILIES, int FAMILYIDX,
3066       byte [][] QUALIFIERS, int QUALIFIERIDX)
3067   throws Exception {
3068 
3069     Get get = new Get(ROWS[ROWIDX]);
3070     get.addFamily(FAMILIES[4]);
3071     get.addColumn(FAMILIES[4], QUALIFIERS[1]);
3072     Result result = ht.get(get);
3073     assertEmptyResult(result);
3074 
3075     get = new Get(ROWS[ROWIDX]);
3076     get.addFamily(FAMILIES[4]);
3077     get.addColumn(FAMILIES[4], QUALIFIERS[2]);
3078     result = ht.get(get);
3079     assertEmptyResult(result);
3080 
3081     get = new Get(ROWS[ROWIDX]);
3082     get.addFamily(FAMILIES[3]);
3083     get.addColumn(FAMILIES[4], QUALIFIERS[2]);
3084     get.addFamily(FAMILIES[5]);
3085     result = ht.get(get);
3086     assertEmptyResult(result);
3087 
3088     get = new Get(ROWS[ROWIDX+1]);
3089     result = ht.get(get);
3090     assertEmptyResult(result);
3091 
3092   }
3093 
3094   private void scanVerifySingleEmpty(Table ht,
3095       byte [][] ROWS, int ROWIDX,
3096       byte [][] FAMILIES, int FAMILYIDX,
3097       byte [][] QUALIFIERS, int QUALIFIERIDX)
3098   throws Exception {
3099 
3100     Scan scan = new Scan(ROWS[ROWIDX+1]);
3101     Result result = getSingleScanResult(ht, scan);
3102     assertNullResult(result);
3103 
3104     scan = new Scan(ROWS[ROWIDX+1],ROWS[ROWIDX+2]);
3105     result = getSingleScanResult(ht, scan);
3106     assertNullResult(result);
3107 
3108     scan = new Scan(HConstants.EMPTY_START_ROW, ROWS[ROWIDX]);
3109     result = getSingleScanResult(ht, scan);
3110     assertNullResult(result);
3111 
3112     scan = new Scan();
3113     scan.addColumn(FAMILIES[FAMILYIDX], QUALIFIERS[QUALIFIERIDX+1]);
3114     scan.addFamily(FAMILIES[FAMILYIDX-1]);
3115     result = getSingleScanResult(ht, scan);
3116     assertNullResult(result);
3117 
3118   }
3119 
3120   //
3121   // Verifiers
3122   //
3123 
3124   private void assertKey(Cell key, byte [] row, byte [] family,
3125       byte [] qualifier, byte [] value)
3126   throws Exception {
3127     assertTrue("Expected row [" + Bytes.toString(row) + "] " +
3128         "Got row [" + Bytes.toString(CellUtil.cloneRow(key)) +"]",
3129         equals(row, CellUtil.cloneRow(key)));
3130     assertTrue("Expected family [" + Bytes.toString(family) + "] " +
3131         "Got family [" + Bytes.toString(CellUtil.cloneFamily(key)) + "]",
3132         equals(family, CellUtil.cloneFamily(key)));
3133     assertTrue("Expected qualifier [" + Bytes.toString(qualifier) + "] " +
3134         "Got qualifier [" + Bytes.toString(CellUtil.cloneQualifier(key)) + "]",
3135         equals(qualifier, CellUtil.cloneQualifier(key)));
3136     assertTrue("Expected value [" + Bytes.toString(value) + "] " +
3137         "Got value [" + Bytes.toString(CellUtil.cloneValue(key)) + "]",
3138         equals(value, CellUtil.cloneValue(key)));
3139   }
3140 
3141   static void assertIncrementKey(Cell key, byte [] row, byte [] family,
3142       byte [] qualifier, long value)
3143   throws Exception {
3144     assertTrue("Expected row [" + Bytes.toString(row) + "] " +
3145         "Got row [" + Bytes.toString(CellUtil.cloneRow(key)) +"]",
3146         equals(row, CellUtil.cloneRow(key)));
3147     assertTrue("Expected family [" + Bytes.toString(family) + "] " +
3148         "Got family [" + Bytes.toString(CellUtil.cloneFamily(key)) + "]",
3149         equals(family, CellUtil.cloneFamily(key)));
3150     assertTrue("Expected qualifier [" + Bytes.toString(qualifier) + "] " +
3151         "Got qualifier [" + Bytes.toString(CellUtil.cloneQualifier(key)) + "]",
3152         equals(qualifier, CellUtil.cloneQualifier(key)));
3153     assertTrue("Expected value [" + value + "] " +
3154         "Got value [" + Bytes.toLong(CellUtil.cloneValue(key)) + "]",
3155         Bytes.toLong(CellUtil.cloneValue(key)) == value);
3156   }
3157 
3158   private void assertNumKeys(Result result, int n) throws Exception {
3159     assertTrue("Expected " + n + " keys but got " + result.size(),
3160         result.size() == n);
3161   }
3162 
3163   private void assertNResult(Result result, byte [] row,
3164       byte [][] families, byte [][] qualifiers, byte [][] values,
3165       int [][] idxs)
3166   throws Exception {
3167     assertTrue("Expected row [" + Bytes.toString(row) + "] " +
3168         "Got row [" + Bytes.toString(result.getRow()) +"]",
3169         equals(row, result.getRow()));
3170     assertTrue("Expected " + idxs.length + " keys but result contains "
3171         + result.size(), result.size() == idxs.length);
3172 
3173     Cell [] keys = result.rawCells();
3174 
3175     for(int i=0;i<keys.length;i++) {
3176       byte [] family = families[idxs[i][0]];
3177       byte [] qualifier = qualifiers[idxs[i][1]];
3178       byte [] value = values[idxs[i][2]];
3179       Cell key = keys[i];
3180 
3181       byte[] famb = CellUtil.cloneFamily(key);
3182       byte[] qualb = CellUtil.cloneQualifier(key);
3183       byte[] valb = CellUtil.cloneValue(key);
3184       assertTrue("(" + i + ") Expected family [" + Bytes.toString(family)
3185           + "] " + "Got family [" + Bytes.toString(famb) + "]",
3186           equals(family, famb));
3187       assertTrue("(" + i + ") Expected qualifier [" + Bytes.toString(qualifier)
3188           + "] " + "Got qualifier [" + Bytes.toString(qualb) + "]",
3189           equals(qualifier, qualb));
3190       assertTrue("(" + i + ") Expected value [" + Bytes.toString(value) + "] "
3191           + "Got value [" + Bytes.toString(valb) + "]",
3192           equals(value, valb));
3193     }
3194   }
3195 
3196   private void assertNResult(Result result, byte [] row,
3197       byte [] family, byte [] qualifier, long [] stamps, byte [][] values,
3198       int start, int end)
3199   throws IOException {
3200     assertTrue("Expected row [" + Bytes.toString(row) + "] " +
3201         "Got row [" + Bytes.toString(result.getRow()) +"]",
3202         equals(row, result.getRow()));
3203     int expectedResults = end - start + 1;
3204     assertEquals(expectedResults, result.size());
3205 
3206     Cell[] keys = result.rawCells();
3207 
3208     for (int i=0; i<keys.length; i++) {
3209       byte [] value = values[end-i];
3210       long ts = stamps[end-i];
3211       Cell key = keys[i];
3212 
3213       assertTrue("(" + i + ") Expected family [" + Bytes.toString(family)
3214           + "] " + "Got family [" + Bytes.toString(CellUtil.cloneFamily(key)) + "]",
3215           CellUtil.matchingFamily(key, family));
3216       assertTrue("(" + i + ") Expected qualifier [" + Bytes.toString(qualifier)
3217           + "] " + "Got qualifier [" + Bytes.toString(CellUtil.cloneQualifier(key))+ "]",
3218           CellUtil.matchingQualifier(key, qualifier));
3219       assertTrue("Expected ts [" + ts + "] " +
3220           "Got ts [" + key.getTimestamp() + "]", ts == key.getTimestamp());
3221       assertTrue("(" + i + ") Expected value [" + Bytes.toString(value) + "] "
3222           + "Got value [" + Bytes.toString(CellUtil.cloneValue(key)) + "]",
3223           CellUtil.matchingValue(key,  value));
3224     }
3225   }
3226 
3227   /**
3228    * Validate that result contains two specified keys, exactly.
3229    * It is assumed key A sorts before key B.
3230    */
3231   private void assertDoubleResult(Result result, byte [] row,
3232       byte [] familyA, byte [] qualifierA, byte [] valueA,
3233       byte [] familyB, byte [] qualifierB, byte [] valueB)
3234   throws Exception {
3235     assertTrue("Expected row [" + Bytes.toString(row) + "] " +
3236         "Got row [" + Bytes.toString(result.getRow()) +"]",
3237         equals(row, result.getRow()));
3238     assertTrue("Expected two keys but result contains " + result.size(),
3239         result.size() == 2);
3240     Cell [] kv = result.rawCells();
3241     Cell kvA = kv[0];
3242     assertTrue("(A) Expected family [" + Bytes.toString(familyA) + "] " +
3243         "Got family [" + Bytes.toString(CellUtil.cloneFamily(kvA)) + "]",
3244         equals(familyA, CellUtil.cloneFamily(kvA)));
3245     assertTrue("(A) Expected qualifier [" + Bytes.toString(qualifierA) + "] " +
3246         "Got qualifier [" + Bytes.toString(CellUtil.cloneQualifier(kvA)) + "]",
3247         equals(qualifierA, CellUtil.cloneQualifier(kvA)));
3248     assertTrue("(A) Expected value [" + Bytes.toString(valueA) + "] " +
3249         "Got value [" + Bytes.toString(CellUtil.cloneValue(kvA)) + "]",
3250         equals(valueA, CellUtil.cloneValue(kvA)));
3251     Cell kvB = kv[1];
3252     assertTrue("(B) Expected family [" + Bytes.toString(familyB) + "] " +
3253         "Got family [" + Bytes.toString(CellUtil.cloneFamily(kvB)) + "]",
3254         equals(familyB, CellUtil.cloneFamily(kvB)));
3255     assertTrue("(B) Expected qualifier [" + Bytes.toString(qualifierB) + "] " +
3256         "Got qualifier [" + Bytes.toString(CellUtil.cloneQualifier(kvB)) + "]",
3257         equals(qualifierB, CellUtil.cloneQualifier(kvB)));
3258     assertTrue("(B) Expected value [" + Bytes.toString(valueB) + "] " +
3259         "Got value [" + Bytes.toString(CellUtil.cloneValue(kvB)) + "]",
3260         equals(valueB, CellUtil.cloneValue(kvB)));
3261   }
3262 
3263   private void assertSingleResult(Result result, byte [] row, byte [] family,
3264       byte [] qualifier, byte [] value)
3265   throws Exception {
3266     assertTrue("Expected row [" + Bytes.toString(row) + "] " +
3267         "Got row [" + Bytes.toString(result.getRow()) +"]",
3268         equals(row, result.getRow()));
3269     assertTrue("Expected a single key but result contains " + result.size(),
3270         result.size() == 1);
3271     Cell kv = result.rawCells()[0];
3272     assertTrue("Expected family [" + Bytes.toString(family) + "] " +
3273         "Got family [" + Bytes.toString(CellUtil.cloneFamily(kv)) + "]",
3274         equals(family, CellUtil.cloneFamily(kv)));
3275     assertTrue("Expected qualifier [" + Bytes.toString(qualifier) + "] " +
3276         "Got qualifier [" + Bytes.toString(CellUtil.cloneQualifier(kv)) + "]",
3277         equals(qualifier, CellUtil.cloneQualifier(kv)));
3278     assertTrue("Expected value [" + Bytes.toString(value) + "] " +
3279         "Got value [" + Bytes.toString(CellUtil.cloneValue(kv)) + "]",
3280         equals(value, CellUtil.cloneValue(kv)));
3281   }
3282 
3283   private void assertSingleResult(Result result, byte [] row, byte [] family,
3284       byte [] qualifier, long ts, byte [] value)
3285   throws Exception {
3286     assertTrue("Expected row [" + Bytes.toString(row) + "] " +
3287         "Got row [" + Bytes.toString(result.getRow()) +"]",
3288         equals(row, result.getRow()));
3289     assertTrue("Expected a single key but result contains " + result.size(),
3290         result.size() == 1);
3291     Cell kv = result.rawCells()[0];
3292     assertTrue("Expected family [" + Bytes.toString(family) + "] " +
3293         "Got family [" + Bytes.toString(CellUtil.cloneFamily(kv)) + "]",
3294         equals(family, CellUtil.cloneFamily(kv)));
3295     assertTrue("Expected qualifier [" + Bytes.toString(qualifier) + "] " +
3296         "Got qualifier [" + Bytes.toString(CellUtil.cloneQualifier(kv)) + "]",
3297         equals(qualifier, CellUtil.cloneQualifier(kv)));
3298     assertTrue("Expected ts [" + ts + "] " +
3299         "Got ts [" + kv.getTimestamp() + "]", ts == kv.getTimestamp());
3300     assertTrue("Expected value [" + Bytes.toString(value) + "] " +
3301         "Got value [" + Bytes.toString(CellUtil.cloneValue(kv)) + "]",
3302         equals(value, CellUtil.cloneValue(kv)));
3303   }
3304 
3305   private void assertEmptyResult(Result result) throws Exception {
3306     assertTrue("expected an empty result but result contains " +
3307         result.size() + " keys", result.isEmpty());
3308   }
3309 
3310   private void assertNullResult(Result result) throws Exception {
3311     assertTrue("expected null result but received a non-null result",
3312         result == null);
3313   }
3314 
3315   //
3316   // Helpers
3317   //
3318 
3319   private Result getSingleScanResult(Table ht, Scan scan) throws IOException {
3320     ResultScanner scanner = ht.getScanner(scan);
3321     Result result = scanner.next();
3322     scanner.close();
3323     return result;
3324   }
3325 
3326   private byte [][] makeNAscii(byte [] base, int n) {
3327     if(n > 256) {
3328       return makeNBig(base, n);
3329     }
3330     byte [][] ret = new byte[n][];
3331     for(int i=0;i<n;i++) {
3332       byte [] tail = Bytes.toBytes(Integer.toString(i));
3333       ret[i] = Bytes.add(base, tail);
3334     }
3335     return ret;
3336   }
3337 
3338   private byte [][] makeN(byte [] base, int n) {
3339     if (n > 256) {
3340       return makeNBig(base, n);
3341     }
3342     byte [][] ret = new byte[n][];
3343     for(int i=0;i<n;i++) {
3344       ret[i] = Bytes.add(base, new byte[]{(byte)i});
3345     }
3346     return ret;
3347   }
3348 
3349   private byte [][] makeNBig(byte [] base, int n) {
3350     byte [][] ret = new byte[n][];
3351     for(int i=0;i<n;i++) {
3352       int byteA = (i % 256);
3353       int byteB = (i >> 8);
3354       ret[i] = Bytes.add(base, new byte[]{(byte)byteB,(byte)byteA});
3355     }
3356     return ret;
3357   }
3358 
3359   private long [] makeStamps(int n) {
3360     long [] stamps = new long[n];
3361     for(int i=0;i<n;i++) stamps[i] = i+1;
3362     return stamps;
3363   }
3364 
3365   static boolean equals(byte [] left, byte [] right) {
3366     if (left == null && right == null) return true;
3367     if (left == null && right.length == 0) return true;
3368     if (right == null && left.length == 0) return true;
3369     return Bytes.equals(left, right);
3370   }
3371 
3372   @Test
3373   public void testDuplicateVersions() throws Exception {
3374     byte [] TABLE = Bytes.toBytes("testDuplicateVersions");
3375 
3376     long [] STAMPS = makeStamps(20);
3377     byte [][] VALUES = makeNAscii(VALUE, 20);
3378 
3379     Table ht = TEST_UTIL.createTable(TABLE, FAMILY, 10);
3380 
3381     // Insert 4 versions of same column
3382     Put put = new Put(ROW);
3383     put.add(FAMILY, QUALIFIER, STAMPS[1], VALUES[1]);
3384     put.add(FAMILY, QUALIFIER, STAMPS[2], VALUES[2]);
3385     put.add(FAMILY, QUALIFIER, STAMPS[4], VALUES[4]);
3386     put.add(FAMILY, QUALIFIER, STAMPS[5], VALUES[5]);
3387     ht.put(put);
3388 
3389     // Verify we can get each one properly
3390     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[1], VALUES[1]);
3391     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[2], VALUES[2]);
3392     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[4], VALUES[4]);
3393     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[5], VALUES[5]);
3394     scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[1], VALUES[1]);
3395     scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[2], VALUES[2]);
3396     scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[4], VALUES[4]);
3397     scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[5], VALUES[5]);
3398 
3399     // Verify we don't accidentally get others
3400     getVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[0]);
3401     getVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[3]);
3402     getVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[6]);
3403     scanVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[0]);
3404     scanVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[3]);
3405     scanVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[6]);
3406 
3407     // Ensure maxVersions in query is respected
3408     Get get = new Get(ROW);
3409     get.addColumn(FAMILY, QUALIFIER);
3410     get.setMaxVersions(2);
3411     Result result = ht.get(get);
3412     assertNResult(result, ROW, FAMILY, QUALIFIER,
3413         new long [] {STAMPS[4], STAMPS[5]},
3414         new byte[][] {VALUES[4], VALUES[5]},
3415         0, 1);
3416 
3417     Scan scan = new Scan(ROW);
3418     scan.addColumn(FAMILY, QUALIFIER);
3419     scan.setMaxVersions(2);
3420     result = getSingleScanResult(ht, scan);
3421     assertNResult(result, ROW, FAMILY, QUALIFIER,
3422         new long [] {STAMPS[4], STAMPS[5]},
3423         new byte[][] {VALUES[4], VALUES[5]},
3424         0, 1);
3425 
3426     // Flush and redo
3427 
3428     TEST_UTIL.flush();
3429 
3430     // Verify we can get each one properly
3431     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[1], VALUES[1]);
3432     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[2], VALUES[2]);
3433     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[4], VALUES[4]);
3434     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[5], VALUES[5]);
3435     scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[1], VALUES[1]);
3436     scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[2], VALUES[2]);
3437     scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[4], VALUES[4]);
3438     scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[5], VALUES[5]);
3439 
3440     // Verify we don't accidentally get others
3441     getVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[0]);
3442     getVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[3]);
3443     getVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[6]);
3444     scanVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[0]);
3445     scanVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[3]);
3446     scanVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[6]);
3447 
3448     // Ensure maxVersions in query is respected
3449     get = new Get(ROW);
3450     get.addColumn(FAMILY, QUALIFIER);
3451     get.setMaxVersions(2);
3452     result = ht.get(get);
3453     assertNResult(result, ROW, FAMILY, QUALIFIER,
3454         new long [] {STAMPS[4], STAMPS[5]},
3455         new byte[][] {VALUES[4], VALUES[5]},
3456         0, 1);
3457 
3458     scan = new Scan(ROW);
3459     scan.addColumn(FAMILY, QUALIFIER);
3460     scan.setMaxVersions(2);
3461     result = getSingleScanResult(ht, scan);
3462     assertNResult(result, ROW, FAMILY, QUALIFIER,
3463         new long [] {STAMPS[4], STAMPS[5]},
3464         new byte[][] {VALUES[4], VALUES[5]},
3465         0, 1);
3466 
3467 
3468     // Add some memstore and retest
3469 
3470     // Insert 4 more versions of same column and a dupe
3471     put = new Put(ROW);
3472     put.add(FAMILY, QUALIFIER, STAMPS[3], VALUES[3]);
3473     put.add(FAMILY, QUALIFIER, STAMPS[4], VALUES[14]);
3474     put.add(FAMILY, QUALIFIER, STAMPS[6], VALUES[6]);
3475     put.add(FAMILY, QUALIFIER, STAMPS[7], VALUES[7]);
3476     put.add(FAMILY, QUALIFIER, STAMPS[8], VALUES[8]);
3477     ht.put(put);
3478 
3479     // Ensure maxVersions in query is respected
3480     get = new Get(ROW);
3481     get.addColumn(FAMILY, QUALIFIER);
3482     get.setMaxVersions(7);
3483     result = ht.get(get);
3484     assertNResult(result, ROW, FAMILY, QUALIFIER,
3485         new long [] {STAMPS[2], STAMPS[3], STAMPS[4], STAMPS[5], STAMPS[6], STAMPS[7], STAMPS[8]},
3486         new byte[][] {VALUES[2], VALUES[3], VALUES[14], VALUES[5], VALUES[6], VALUES[7], VALUES[8]},
3487         0, 6);
3488 
3489     scan = new Scan(ROW);
3490     scan.addColumn(FAMILY, QUALIFIER);
3491     scan.setMaxVersions(7);
3492     result = getSingleScanResult(ht, scan);
3493     assertNResult(result, ROW, FAMILY, QUALIFIER,
3494         new long [] {STAMPS[2], STAMPS[3], STAMPS[4], STAMPS[5], STAMPS[6], STAMPS[7], STAMPS[8]},
3495         new byte[][] {VALUES[2], VALUES[3], VALUES[14], VALUES[5], VALUES[6], VALUES[7], VALUES[8]},
3496         0, 6);
3497 
3498     get = new Get(ROW);
3499     get.setMaxVersions(7);
3500     result = ht.get(get);
3501     assertNResult(result, ROW, FAMILY, QUALIFIER,
3502         new long [] {STAMPS[2], STAMPS[3], STAMPS[4], STAMPS[5], STAMPS[6], STAMPS[7], STAMPS[8]},
3503         new byte[][] {VALUES[2], VALUES[3], VALUES[14], VALUES[5], VALUES[6], VALUES[7], VALUES[8]},
3504         0, 6);
3505 
3506     scan = new Scan(ROW);
3507     scan.setMaxVersions(7);
3508     result = getSingleScanResult(ht, scan);
3509     assertNResult(result, ROW, FAMILY, QUALIFIER,
3510         new long [] {STAMPS[2], STAMPS[3], STAMPS[4], STAMPS[5], STAMPS[6], STAMPS[7], STAMPS[8]},
3511         new byte[][] {VALUES[2], VALUES[3], VALUES[14], VALUES[5], VALUES[6], VALUES[7], VALUES[8]},
3512         0, 6);
3513 
3514     // Verify we can get each one properly
3515     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[1], VALUES[1]);
3516     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[2], VALUES[2]);
3517     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[4], VALUES[14]);
3518     getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[7], VALUES[7]);
3519     scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[1], VALUES[1]);
3520     scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[2], VALUES[2]);
3521     scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[4], VALUES[14]);
3522     scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[7], VALUES[7]);
3523 
3524     // Verify we don't accidentally get others
3525     getVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[0]);
3526     getVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[9]);
3527     scanVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[0]);
3528     scanVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[9]);
3529 
3530     // Ensure maxVersions of table is respected
3531 
3532     TEST_UTIL.flush();
3533 
3534     // Insert 4 more versions of same column and a dupe
3535     put = new Put(ROW);
3536     put.add(FAMILY, QUALIFIER, STAMPS[9], VALUES[9]);
3537     put.add(FAMILY, QUALIFIER, STAMPS[11], VALUES[11]);
3538     put.add(FAMILY, QUALIFIER, STAMPS[13], VALUES[13]);
3539     put.add(FAMILY, QUALIFIER, STAMPS[15], VALUES[15]);
3540     ht.put(put);
3541 
3542     get = new Get(ROW);
3543     get.addColumn(FAMILY, QUALIFIER);
3544     get.setMaxVersions(Integer.MAX_VALUE);
3545     result = ht.get(get);
3546     assertNResult(result, ROW, FAMILY, QUALIFIER,
3547         new long [] {STAMPS[3], STAMPS[4], STAMPS[5], STAMPS[6], STAMPS[7], STAMPS[8], STAMPS[9], STAMPS[11], STAMPS[13], STAMPS[15]},
3548         new byte[][] {VALUES[3], VALUES[14], VALUES[5], VALUES[6], VALUES[7], VALUES[8], VALUES[9], VALUES[11], VALUES[13], VALUES[15]},
3549         0, 9);
3550 
3551     scan = new Scan(ROW);
3552     scan.addColumn(FAMILY, QUALIFIER);
3553     scan.setMaxVersions(Integer.MAX_VALUE);
3554     result = getSingleScanResult(ht, scan);
3555     assertNResult(result, ROW, FAMILY, QUALIFIER,
3556         new long [] {STAMPS[3], STAMPS[4], STAMPS[5], STAMPS[6], STAMPS[7], STAMPS[8], STAMPS[9], STAMPS[11], STAMPS[13], STAMPS[15]},
3557         new byte[][] {VALUES[3], VALUES[14], VALUES[5], VALUES[6], VALUES[7], VALUES[8], VALUES[9], VALUES[11], VALUES[13], VALUES[15]},
3558         0, 9);
3559 
3560     // Delete a version in the memstore and a version in a storefile
3561     Delete delete = new Delete(ROW);
3562     delete.deleteColumn(FAMILY, QUALIFIER, STAMPS[11]);
3563     delete.deleteColumn(FAMILY, QUALIFIER, STAMPS[7]);
3564     ht.delete(delete);
3565 
3566     // Test that it's gone
3567     get = new Get(ROW);
3568     get.addColumn(FAMILY, QUALIFIER);
3569     get.setMaxVersions(Integer.MAX_VALUE);
3570     result = ht.get(get);
3571     assertNResult(result, ROW, FAMILY, QUALIFIER,
3572         new long [] {STAMPS[1], STAMPS[2], STAMPS[3], STAMPS[4], STAMPS[5], STAMPS[6], STAMPS[8], STAMPS[9], STAMPS[13], STAMPS[15]},
3573         new byte[][] {VALUES[1], VALUES[2], VALUES[3], VALUES[14], VALUES[5], VALUES[6], VALUES[8], VALUES[9], VALUES[13], VALUES[15]},
3574         0, 9);
3575 
3576     scan = new Scan(ROW);
3577     scan.addColumn(FAMILY, QUALIFIER);
3578     scan.setMaxVersions(Integer.MAX_VALUE);
3579     result = getSingleScanResult(ht, scan);
3580     assertNResult(result, ROW, FAMILY, QUALIFIER,
3581         new long [] {STAMPS[1], STAMPS[2], STAMPS[3], STAMPS[4], STAMPS[5], STAMPS[6], STAMPS[8], STAMPS[9], STAMPS[13], STAMPS[15]},
3582         new byte[][] {VALUES[1], VALUES[2], VALUES[3], VALUES[14], VALUES[5], VALUES[6], VALUES[8], VALUES[9], VALUES[13], VALUES[15]},
3583         0, 9);
3584   }
3585 
3586   @Test
3587   public void testUpdates() throws Exception {
3588 
3589     byte [] TABLE = Bytes.toBytes("testUpdates");
3590     Table hTable = TEST_UTIL.createTable(TABLE, FAMILY, 10);
3591 
3592     // Write a column with values at timestamp 1, 2 and 3
3593     byte[] row = Bytes.toBytes("row1");
3594     byte[] qualifier = Bytes.toBytes("myCol");
3595     Put put = new Put(row);
3596     put.add(FAMILY, qualifier, 1L, Bytes.toBytes("AAA"));
3597     hTable.put(put);
3598 
3599     put = new Put(row);
3600     put.add(FAMILY, qualifier, 2L, Bytes.toBytes("BBB"));
3601     hTable.put(put);
3602 
3603     put = new Put(row);
3604     put.add(FAMILY, qualifier, 3L, Bytes.toBytes("EEE"));
3605     hTable.put(put);
3606 
3607     Get get = new Get(row);
3608     get.addColumn(FAMILY, qualifier);
3609     get.setMaxVersions();
3610 
3611     // Check that the column indeed has the right values at timestamps 1 and
3612     // 2
3613     Result result = hTable.get(get);
3614     NavigableMap<Long, byte[]> navigableMap =
3615         result.getMap().get(FAMILY).get(qualifier);
3616     assertEquals("AAA", Bytes.toString(navigableMap.get(1L)));
3617     assertEquals("BBB", Bytes.toString(navigableMap.get(2L)));
3618 
3619     // Update the value at timestamp 1
3620     put = new Put(row);
3621     put.add(FAMILY, qualifier, 1L, Bytes.toBytes("CCC"));
3622     hTable.put(put);
3623 
3624     // Update the value at timestamp 2
3625     put = new Put(row);
3626     put.add(FAMILY, qualifier, 2L, Bytes.toBytes("DDD"));
3627     hTable.put(put);
3628 
3629     // Check that the values at timestamp 2 and 1 got updated
3630     result = hTable.get(get);
3631     navigableMap = result.getMap().get(FAMILY).get(qualifier);
3632     assertEquals("CCC", Bytes.toString(navigableMap.get(1L)));
3633     assertEquals("DDD", Bytes.toString(navigableMap.get(2L)));
3634   }
3635 
3636   @Test
3637   public void testUpdatesWithMajorCompaction() throws Exception {
3638 
3639     TableName TABLE = TableName.valueOf("testUpdatesWithMajorCompaction");
3640     Table hTable = TEST_UTIL.createTable(TABLE, FAMILY, 10);
3641     HBaseAdmin admin = new HBaseAdmin(TEST_UTIL.getConfiguration());
3642 
3643     // Write a column with values at timestamp 1, 2 and 3
3644     byte[] row = Bytes.toBytes("row2");
3645     byte[] qualifier = Bytes.toBytes("myCol");
3646     Put put = new Put(row);
3647     put.add(FAMILY, qualifier, 1L, Bytes.toBytes("AAA"));
3648     hTable.put(put);
3649 
3650     put = new Put(row);
3651     put.add(FAMILY, qualifier, 2L, Bytes.toBytes("BBB"));
3652     hTable.put(put);
3653 
3654     put = new Put(row);
3655     put.add(FAMILY, qualifier, 3L, Bytes.toBytes("EEE"));
3656     hTable.put(put);
3657 
3658     Get get = new Get(row);
3659     get.addColumn(FAMILY, qualifier);
3660     get.setMaxVersions();
3661 
3662     // Check that the column indeed has the right values at timestamps 1 and
3663     // 2
3664     Result result = hTable.get(get);
3665     NavigableMap<Long, byte[]> navigableMap =
3666         result.getMap().get(FAMILY).get(qualifier);
3667     assertEquals("AAA", Bytes.toString(navigableMap.get(1L)));
3668     assertEquals("BBB", Bytes.toString(navigableMap.get(2L)));
3669 
3670     // Trigger a major compaction
3671     admin.flush(TABLE);
3672     admin.majorCompact(TABLE);
3673     Thread.sleep(6000);
3674 
3675     // Update the value at timestamp 1
3676     put = new Put(row);
3677     put.add(FAMILY, qualifier, 1L, Bytes.toBytes("CCC"));
3678     hTable.put(put);
3679 
3680     // Update the value at timestamp 2
3681     put = new Put(row);
3682     put.add(FAMILY, qualifier, 2L, Bytes.toBytes("DDD"));
3683     hTable.put(put);
3684 
3685     // Trigger a major compaction
3686     admin.flush(TABLE);
3687     admin.majorCompact(TABLE);
3688     Thread.sleep(6000);
3689 
3690     // Check that the values at timestamp 2 and 1 got updated
3691     result = hTable.get(get);
3692     navigableMap = result.getMap().get(FAMILY).get(qualifier);
3693     assertEquals("CCC", Bytes.toString(navigableMap.get(1L)));
3694     assertEquals("DDD", Bytes.toString(navigableMap.get(2L)));
3695   }
3696 
3697   @Test
3698   public void testMajorCompactionBetweenTwoUpdates() throws Exception {
3699 
3700     String tableName = "testMajorCompactionBetweenTwoUpdates";
3701     byte [] TABLE = Bytes.toBytes(tableName);
3702     Table hTable = TEST_UTIL.createTable(TABLE, FAMILY, 10);
3703     HBaseAdmin admin = new HBaseAdmin(TEST_UTIL.getConfiguration());
3704 
3705     // Write a column with values at timestamp 1, 2 and 3
3706     byte[] row = Bytes.toBytes("row3");
3707     byte[] qualifier = Bytes.toBytes("myCol");
3708     Put put = new Put(row);
3709     put.add(FAMILY, qualifier, 1L, Bytes.toBytes("AAA"));
3710     hTable.put(put);
3711 
3712     put = new Put(row);
3713     put.add(FAMILY, qualifier, 2L, Bytes.toBytes("BBB"));
3714     hTable.put(put);
3715 
3716     put = new Put(row);
3717     put.add(FAMILY, qualifier, 3L, Bytes.toBytes("EEE"));
3718     hTable.put(put);
3719 
3720     Get get = new Get(row);
3721     get.addColumn(FAMILY, qualifier);
3722     get.setMaxVersions();
3723 
3724     // Check that the column indeed has the right values at timestamps 1 and
3725     // 2
3726     Result result = hTable.get(get);
3727     NavigableMap<Long, byte[]> navigableMap =
3728         result.getMap().get(FAMILY).get(qualifier);
3729     assertEquals("AAA", Bytes.toString(navigableMap.get(1L)));
3730     assertEquals("BBB", Bytes.toString(navigableMap.get(2L)));
3731 
3732     // Trigger a major compaction
3733     admin.flush(tableName);
3734     admin.majorCompact(tableName);
3735     Thread.sleep(6000);
3736 
3737     // Update the value at timestamp 1
3738     put = new Put(row);
3739     put.add(FAMILY, qualifier, 1L, Bytes.toBytes("CCC"));
3740     hTable.put(put);
3741 
3742     // Trigger a major compaction
3743     admin.flush(tableName);
3744     admin.majorCompact(tableName);
3745     Thread.sleep(6000);
3746 
3747     // Update the value at timestamp 2
3748     put = new Put(row);
3749     put.add(FAMILY, qualifier, 2L, Bytes.toBytes("DDD"));
3750     hTable.put(put);
3751 
3752     // Trigger a major compaction
3753     admin.flush(tableName);
3754     admin.majorCompact(tableName);
3755     Thread.sleep(6000);
3756 
3757     // Check that the values at timestamp 2 and 1 got updated
3758     result = hTable.get(get);
3759     navigableMap = result.getMap().get(FAMILY).get(qualifier);
3760 
3761     assertEquals("CCC", Bytes.toString(navigableMap.get(1L)));
3762     assertEquals("DDD", Bytes.toString(navigableMap.get(2L)));
3763   }
3764 
3765   @Test
3766   public void testGet_EmptyTable() throws IOException {
3767     Table table = TEST_UTIL.createTable(TableName.valueOf("testGet_EmptyTable"), FAMILY);
3768     Get get = new Get(ROW);
3769     get.addFamily(FAMILY);
3770     Result r = table.get(get);
3771     assertTrue(r.isEmpty());
3772   }
3773 
3774   @Test
3775   public void testGet_NullQualifier() throws IOException {
3776     Table table = TEST_UTIL.createTable(TableName.valueOf("testGet_NullQualifier"), FAMILY);
3777     Put put = new Put(ROW);
3778     put.add(FAMILY, QUALIFIER, VALUE);
3779     table.put(put);
3780 
3781     put = new Put(ROW);
3782     put.add(FAMILY, null, VALUE);
3783     table.put(put);
3784     LOG.info("Row put");
3785 
3786     Get get = new Get(ROW);
3787     get.addColumn(FAMILY, null);
3788     Result r = table.get(get);
3789     assertEquals(1, r.size());
3790 
3791     get = new Get(ROW);
3792     get.addFamily(FAMILY);
3793     r = table.get(get);
3794     assertEquals(2, r.size());
3795   }
3796 
3797   @Test
3798   public void testGet_NonExistentRow() throws IOException {
3799     Table table = TEST_UTIL.createTable(TableName.valueOf("testGet_NonExistentRow"), FAMILY);
3800     Put put = new Put(ROW);
3801     put.add(FAMILY, QUALIFIER, VALUE);
3802     table.put(put);
3803     LOG.info("Row put");
3804 
3805     Get get = new Get(ROW);
3806     get.addFamily(FAMILY);
3807     Result r = table.get(get);
3808     assertFalse(r.isEmpty());
3809     System.out.println("Row retrieved successfully");
3810 
3811     byte [] missingrow = Bytes.toBytes("missingrow");
3812     get = new Get(missingrow);
3813     get.addFamily(FAMILY);
3814     r = table.get(get);
3815     assertTrue(r.isEmpty());
3816     LOG.info("Row missing as it should be");
3817   }
3818 
3819   @Test
3820   public void testPut() throws IOException {
3821     final byte [] CONTENTS_FAMILY = Bytes.toBytes("contents");
3822     final byte [] SMALL_FAMILY = Bytes.toBytes("smallfam");
3823     final byte [] row1 = Bytes.toBytes("row1");
3824     final byte [] row2 = Bytes.toBytes("row2");
3825     final byte [] value = Bytes.toBytes("abcd");
3826     Table table = TEST_UTIL.createTable(Bytes.toBytes("testPut"),
3827       new byte [][] {CONTENTS_FAMILY, SMALL_FAMILY});
3828     Put put = new Put(row1);
3829     put.add(CONTENTS_FAMILY, null, value);
3830     table.put(put);
3831 
3832     put = new Put(row2);
3833     put.add(CONTENTS_FAMILY, null, value);
3834 
3835     assertEquals(put.size(), 1);
3836     assertEquals(put.getFamilyCellMap().get(CONTENTS_FAMILY).size(), 1);
3837 
3838     // KeyValue v1 expectation.  Cast for now until we go all Cell all the time. TODO
3839     KeyValue kv = (KeyValue)put.getFamilyCellMap().get(CONTENTS_FAMILY).get(0);
3840 
3841     assertTrue(Bytes.equals(kv.getFamily(), CONTENTS_FAMILY));
3842     // will it return null or an empty byte array?
3843     assertTrue(Bytes.equals(kv.getQualifier(), new byte[0]));
3844 
3845     assertTrue(Bytes.equals(kv.getValue(), value));
3846 
3847     table.put(put);
3848 
3849     Scan scan = new Scan();
3850     scan.addColumn(CONTENTS_FAMILY, null);
3851     ResultScanner scanner = table.getScanner(scan);
3852     for (Result r : scanner) {
3853       for(Cell key : r.rawCells()) {
3854         System.out.println(Bytes.toString(r.getRow()) + ": " + key.toString());
3855       }
3856     }
3857   }
3858 
3859   @Test
3860   public void testPutNoCF() throws IOException {
3861     final byte[] BAD_FAM = Bytes.toBytes("BAD_CF");
3862     final byte[] VAL = Bytes.toBytes(100);
3863     Table table = TEST_UTIL.createTable(Bytes.toBytes("testPutNoCF"), FAMILY);
3864 
3865     boolean caughtNSCFE = false;
3866 
3867     try {
3868       Put p = new Put(ROW);
3869       p.add(BAD_FAM, QUALIFIER, VAL);
3870       table.put(p);
3871     } catch (RetriesExhaustedWithDetailsException e) {
3872       caughtNSCFE = e.getCause(0) instanceof NoSuchColumnFamilyException;
3873     }
3874     assertTrue("Should throw NoSuchColumnFamilyException", caughtNSCFE);
3875 
3876   }
3877 
3878   @Test
3879   public void testRowsPut() throws IOException {
3880     final byte[] CONTENTS_FAMILY = Bytes.toBytes("contents");
3881     final byte[] SMALL_FAMILY = Bytes.toBytes("smallfam");
3882     final int NB_BATCH_ROWS = 10;
3883     final byte[] value = Bytes.toBytes("abcd");
3884     Table table = TEST_UTIL.createTable(Bytes.toBytes("testRowsPut"),
3885       new byte[][] {CONTENTS_FAMILY, SMALL_FAMILY });
3886     ArrayList<Put> rowsUpdate = new ArrayList<Put>();
3887     for (int i = 0; i < NB_BATCH_ROWS; i++) {
3888       byte[] row = Bytes.toBytes("row" + i);
3889       Put put = new Put(row);
3890       put.setDurability(Durability.SKIP_WAL);
3891       put.add(CONTENTS_FAMILY, null, value);
3892       rowsUpdate.add(put);
3893     }
3894     table.put(rowsUpdate);
3895     Scan scan = new Scan();
3896     scan.addFamily(CONTENTS_FAMILY);
3897     ResultScanner scanner = table.getScanner(scan);
3898     int nbRows = 0;
3899     for (@SuppressWarnings("unused")
3900     Result row : scanner)
3901       nbRows++;
3902     assertEquals(NB_BATCH_ROWS, nbRows);
3903   }
3904 
3905   @Test
3906   public void testRowsPutBufferedOneFlush() throws IOException {
3907     final byte [] CONTENTS_FAMILY = Bytes.toBytes("contents");
3908     final byte [] SMALL_FAMILY = Bytes.toBytes("smallfam");
3909     final byte [] value = Bytes.toBytes("abcd");
3910     final int NB_BATCH_ROWS = 10;
3911     HTable table = TEST_UTIL.createTable(Bytes.toBytes("testRowsPutBufferedOneFlush"),
3912       new byte [][] {CONTENTS_FAMILY, SMALL_FAMILY});
3913     table.setAutoFlush(false);
3914     ArrayList<Put> rowsUpdate = new ArrayList<Put>();
3915     for (int i = 0; i < NB_BATCH_ROWS * 10; i++) {
3916       byte[] row = Bytes.toBytes("row" + i);
3917       Put put = new Put(row);
3918       put.setDurability(Durability.SKIP_WAL);
3919       put.add(CONTENTS_FAMILY, null, value);
3920       rowsUpdate.add(put);
3921     }
3922     table.put(rowsUpdate);
3923 
3924     Scan scan = new Scan();
3925     scan.addFamily(CONTENTS_FAMILY);
3926     ResultScanner scanner = table.getScanner(scan);
3927     int nbRows = 0;
3928     for (@SuppressWarnings("unused")
3929     Result row : scanner)
3930       nbRows++;
3931     assertEquals(0, nbRows);
3932     scanner.close();
3933 
3934     table.flushCommits();
3935 
3936     scan = new Scan();
3937     scan.addFamily(CONTENTS_FAMILY);
3938     scanner = table.getScanner(scan);
3939     nbRows = 0;
3940     for (@SuppressWarnings("unused")
3941     Result row : scanner)
3942       nbRows++;
3943     assertEquals(NB_BATCH_ROWS * 10, nbRows);
3944     table.close();
3945   }
3946 
3947   @Test
3948   public void testRowsPutBufferedManyManyFlushes() throws IOException {
3949     final byte[] CONTENTS_FAMILY = Bytes.toBytes("contents");
3950     final byte[] SMALL_FAMILY = Bytes.toBytes("smallfam");
3951     final byte[] value = Bytes.toBytes("abcd");
3952     final int NB_BATCH_ROWS = 10;
3953     HTable table = TEST_UTIL.createTable(Bytes.toBytes("testRowsPutBufferedManyManyFlushes"),
3954       new byte[][] {CONTENTS_FAMILY, SMALL_FAMILY });
3955     table.setWriteBufferSize(10);
3956     ArrayList<Put> rowsUpdate = new ArrayList<Put>();
3957     for (int i = 0; i < NB_BATCH_ROWS * 10; i++) {
3958       byte[] row = Bytes.toBytes("row" + i);
3959       Put put = new Put(row);
3960       put.setDurability(Durability.SKIP_WAL);
3961       put.add(CONTENTS_FAMILY, null, value);
3962       rowsUpdate.add(put);
3963     }
3964     table.put(rowsUpdate);
3965 
3966     Scan scan = new Scan();
3967     scan.addFamily(CONTENTS_FAMILY);
3968     ResultScanner scanner = table.getScanner(scan);
3969     int nbRows = 0;
3970     for (@SuppressWarnings("unused")
3971     Result row : scanner)
3972       nbRows++;
3973     assertEquals(NB_BATCH_ROWS * 10, nbRows);
3974   }
3975 
3976   @Test
3977   public void testAddKeyValue() throws IOException {
3978     final byte[] CONTENTS_FAMILY = Bytes.toBytes("contents");
3979     final byte[] value = Bytes.toBytes("abcd");
3980     final byte[] row1 = Bytes.toBytes("row1");
3981     final byte[] row2 = Bytes.toBytes("row2");
3982     byte[] qualifier = Bytes.toBytes("qf1");
3983     Put put = new Put(row1);
3984 
3985     // Adding KeyValue with the same row
3986     KeyValue kv = new KeyValue(row1, CONTENTS_FAMILY, qualifier, value);
3987     boolean ok = true;
3988     try {
3989       put.add(kv);
3990     } catch (IOException e) {
3991       ok = false;
3992     }
3993     assertEquals(true, ok);
3994 
3995     // Adding KeyValue with the different row
3996     kv = new KeyValue(row2, CONTENTS_FAMILY, qualifier, value);
3997     ok = false;
3998     try {
3999       put.add(kv);
4000     } catch (IOException e) {
4001       ok = true;
4002     }
4003     assertEquals(true, ok);
4004   }
4005 
4006   /**
4007    * test for HBASE-737
4008    * @throws IOException
4009    */
4010   @Test
4011   public void testHBase737 () throws IOException {
4012     final byte [] FAM1 = Bytes.toBytes("fam1");
4013     final byte [] FAM2 = Bytes.toBytes("fam2");
4014     // Open table
4015     Table table = TEST_UTIL.createTable(Bytes.toBytes("testHBase737"),
4016       new byte [][] {FAM1, FAM2});
4017     // Insert some values
4018     Put put = new Put(ROW);
4019     put.add(FAM1, Bytes.toBytes("letters"), Bytes.toBytes("abcdefg"));
4020     table.put(put);
4021     try {
4022       Thread.sleep(1000);
4023     } catch (InterruptedException i) {
4024       //ignore
4025     }
4026 
4027     put = new Put(ROW);
4028     put.add(FAM1, Bytes.toBytes("numbers"), Bytes.toBytes("123456"));
4029     table.put(put);
4030 
4031     try {
4032       Thread.sleep(1000);
4033     } catch (InterruptedException i) {
4034       //ignore
4035     }
4036 
4037     put = new Put(ROW);
4038     put.add(FAM2, Bytes.toBytes("letters"), Bytes.toBytes("hijklmnop"));
4039     table.put(put);
4040 
4041     long times[] = new long[3];
4042 
4043     // First scan the memstore
4044 
4045     Scan scan = new Scan();
4046     scan.addFamily(FAM1);
4047     scan.addFamily(FAM2);
4048     ResultScanner s = table.getScanner(scan);
4049     try {
4050       int index = 0;
4051       Result r = null;
4052       while ((r = s.next()) != null) {
4053         for(Cell key : r.rawCells()) {
4054           times[index++] = key.getTimestamp();
4055         }
4056       }
4057     } finally {
4058       s.close();
4059     }
4060     for (int i = 0; i < times.length - 1; i++) {
4061       for (int j = i + 1; j < times.length; j++) {
4062         assertTrue(times[j] > times[i]);
4063       }
4064     }
4065 
4066     // Flush data to disk and try again
4067     TEST_UTIL.flush();
4068 
4069     // Reset times
4070     for(int i=0;i<times.length;i++) {
4071       times[i] = 0;
4072     }
4073 
4074     try {
4075       Thread.sleep(1000);
4076     } catch (InterruptedException i) {
4077       //ignore
4078     }
4079     scan = new Scan();
4080     scan.addFamily(FAM1);
4081     scan.addFamily(FAM2);
4082     s = table.getScanner(scan);
4083     try {
4084       int index = 0;
4085       Result r = null;
4086       while ((r = s.next()) != null) {
4087         for(Cell key : r.rawCells()) {
4088           times[index++] = key.getTimestamp();
4089         }
4090       }
4091     } finally {
4092       s.close();
4093     }
4094     for (int i = 0; i < times.length - 1; i++) {
4095       for (int j = i + 1; j < times.length; j++) {
4096         assertTrue(times[j] > times[i]);
4097       }
4098     }
4099   }
4100 
4101   @Test
4102   public void testListTables() throws IOException, InterruptedException {
4103     TableName t1 = TableName.valueOf("testListTables1");
4104     TableName t2 = TableName.valueOf("testListTables2");
4105     TableName t3 = TableName.valueOf("testListTables3");
4106     TableName [] tables = new TableName[] { t1, t2, t3 };
4107     for (int i = 0; i < tables.length; i++) {
4108       TEST_UTIL.createTable(tables[i], FAMILY);
4109     }
4110     Admin admin = new HBaseAdmin(TEST_UTIL.getConfiguration());
4111     HTableDescriptor[] ts = admin.listTables();
4112     HashSet<HTableDescriptor> result = new HashSet<HTableDescriptor>(ts.length);
4113     Collections.addAll(result, ts);
4114     int size = result.size();
4115     assertTrue(size >= tables.length);
4116     for (int i = 0; i < tables.length && i < size; i++) {
4117       boolean found = false;
4118       for (int j = 0; j < ts.length; j++) {
4119         if (ts[j].getTableName().equals(tables[i])) {
4120           found = true;
4121           break;
4122         }
4123       }
4124       assertTrue("Not found: " + tables[i], found);
4125     }
4126   }
4127 
4128   /**
4129    * creates an HTable for tableName using an unmanaged HConnection.
4130    *
4131    * @param tableName - table to create
4132    * @return the created HTable object
4133    * @throws IOException
4134    */
4135   HTable createUnmangedHConnectionHTable(final TableName tableName) throws IOException {
4136     TEST_UTIL.createTable(tableName, HConstants.CATALOG_FAMILY);
4137     HConnection conn = HConnectionManager.createConnection(TEST_UTIL.getConfiguration());
4138     return (HTable)conn.getTable(tableName);
4139   }
4140 
4141   /**
4142    * simple test that just executes parts of the client
4143    * API that accept a pre-created HConnection instance
4144    *
4145    * @throws IOException
4146    */
4147   @Test
4148   public void testUnmanagedHConnection() throws IOException {
4149     final TableName tableName = TableName.valueOf("testUnmanagedHConnection");
4150     HTable t = createUnmangedHConnectionHTable(tableName);
4151     HBaseAdmin ha = new HBaseAdmin(t.getConnection());
4152     assertTrue(ha.tableExists(tableName));
4153     assertTrue(t.get(new Get(ROW)).isEmpty());
4154     ha.close();
4155   }
4156 
4157   /**
4158    * test of that unmanaged HConnections are able to reconnect
4159    * properly (see HBASE-5058)
4160    *
4161    * @throws Exception
4162    */
4163   @Test
4164   public void testUnmanagedHConnectionReconnect() throws Exception {
4165     final TableName tableName = TableName.valueOf("testUnmanagedHConnectionReconnect");
4166     HTable t = createUnmangedHConnectionHTable(tableName);
4167     Connection conn = t.getConnection();
4168     try (HBaseAdmin ha = new HBaseAdmin(conn)) {
4169       assertTrue(ha.tableExists(tableName));
4170       assertTrue(t.get(new Get(ROW)).isEmpty());
4171     }
4172 
4173     // stop the master
4174     MiniHBaseCluster cluster = TEST_UTIL.getHBaseCluster();
4175     cluster.stopMaster(0, false);
4176     cluster.waitOnMaster(0);
4177 
4178     // start up a new master
4179     cluster.startMaster();
4180     assertTrue(cluster.waitForActiveAndReadyMaster());
4181 
4182     // test that the same unmanaged connection works with a new
4183     // HBaseAdmin and can connect to the new master;
4184     try (HBaseAdmin newAdmin = new HBaseAdmin(conn)) {
4185       assertTrue(newAdmin.tableExists(tableName));
4186       assertTrue(newAdmin.getClusterStatus().getServersSize() == SLAVES);
4187     }
4188   }
4189 
4190   @Test
4191   public void testMiscHTableStuff() throws IOException {
4192     final TableName tableAname = TableName.valueOf("testMiscHTableStuffA");
4193     final TableName tableBname = TableName.valueOf("testMiscHTableStuffB");
4194     final byte[] attrName = Bytes.toBytes("TESTATTR");
4195     final byte[] attrValue = Bytes.toBytes("somevalue");
4196     byte[] value = Bytes.toBytes("value");
4197 
4198     Table a = TEST_UTIL.createTable(tableAname, HConstants.CATALOG_FAMILY);
4199     Table b = TEST_UTIL.createTable(tableBname, HConstants.CATALOG_FAMILY);
4200     Put put = new Put(ROW);
4201     put.add(HConstants.CATALOG_FAMILY, null, value);
4202     a.put(put);
4203 
4204     // open a new connection to A and a connection to b
4205     Table newA = new HTable(TEST_UTIL.getConfiguration(), tableAname);
4206 
4207     // copy data from A to B
4208     Scan scan = new Scan();
4209     scan.addFamily(HConstants.CATALOG_FAMILY);
4210     ResultScanner s = newA.getScanner(scan);
4211     try {
4212       for (Result r : s) {
4213         put = new Put(r.getRow());
4214         put.setDurability(Durability.SKIP_WAL);
4215         for (Cell kv : r.rawCells()) {
4216           put.add(kv);
4217         }
4218         b.put(put);
4219       }
4220     } finally {
4221       s.close();
4222     }
4223 
4224     // Opening a new connection to A will cause the tables to be reloaded
4225     Table anotherA = new HTable(TEST_UTIL.getConfiguration(), tableAname);
4226     Get get = new Get(ROW);
4227     get.addFamily(HConstants.CATALOG_FAMILY);
4228     anotherA.get(get);
4229 
4230     // We can still access A through newA because it has the table information
4231     // cached. And if it needs to recalibrate, that will cause the information
4232     // to be reloaded.
4233 
4234     // Test user metadata
4235     Admin admin = new HBaseAdmin(TEST_UTIL.getConfiguration());
4236     // make a modifiable descriptor
4237     HTableDescriptor desc = new HTableDescriptor(a.getTableDescriptor());
4238     // offline the table
4239     admin.disableTable(tableAname);
4240     // add a user attribute to HTD
4241     desc.setValue(attrName, attrValue);
4242     // add a user attribute to HCD
4243     for (HColumnDescriptor c : desc.getFamilies())
4244       c.setValue(attrName, attrValue);
4245     // update metadata for all regions of this table
4246     admin.modifyTable(tableAname, desc);
4247     // enable the table
4248     admin.enableTable(tableAname);
4249 
4250     // Test that attribute changes were applied
4251     desc = a.getTableDescriptor();
4252     assertEquals("wrong table descriptor returned", desc.getTableName(), tableAname);
4253     // check HTD attribute
4254     value = desc.getValue(attrName);
4255     assertFalse("missing HTD attribute value", value == null);
4256     assertFalse("HTD attribute value is incorrect",
4257       Bytes.compareTo(value, attrValue) != 0);
4258     // check HCD attribute
4259     for (HColumnDescriptor c : desc.getFamilies()) {
4260       value = c.getValue(attrName);
4261       assertFalse("missing HCD attribute value", value == null);
4262       assertFalse("HCD attribute value is incorrect",
4263         Bytes.compareTo(value, attrValue) != 0);
4264     }
4265   }
4266 
4267   @Test
4268   public void testGetClosestRowBefore() throws IOException, InterruptedException {
4269     final TableName tableAname = TableName.valueOf("testGetClosestRowBefore");
4270     final byte[] firstRow = Bytes.toBytes("row111");
4271     final byte[] secondRow = Bytes.toBytes("row222");
4272     final byte[] thirdRow = Bytes.toBytes("row333");
4273     final byte[] forthRow = Bytes.toBytes("row444");
4274     final byte[] beforeFirstRow = Bytes.toBytes("row");
4275     final byte[] beforeSecondRow = Bytes.toBytes("row22");
4276     final byte[] beforeThirdRow = Bytes.toBytes("row33");
4277     final byte[] beforeForthRow = Bytes.toBytes("row44");
4278 
4279     HTable table =
4280         TEST_UTIL.createTable(tableAname,
4281           new byte[][] { HConstants.CATALOG_FAMILY, Bytes.toBytes("info2") }, 1, 1024);
4282     // set block size to 64 to making 2 kvs into one block, bypassing the walkForwardInSingleRow
4283     // in Store.rowAtOrBeforeFromStoreFile
4284     String regionName = table.getRegionLocations().firstKey().getEncodedName();
4285     Region region =
4286         TEST_UTIL.getRSForFirstRegionInTable(tableAname).getFromOnlineRegions(regionName);
4287     Put put1 = new Put(firstRow);
4288     Put put2 = new Put(secondRow);
4289     Put put3 = new Put(thirdRow);
4290     Put put4 = new Put(forthRow);
4291     byte[] one = new byte[] { 1 };
4292     byte[] two = new byte[] { 2 };
4293     byte[] three = new byte[] { 3 };
4294     byte[] four = new byte[] { 4 };
4295 
4296     put1.add(HConstants.CATALOG_FAMILY, null, one);
4297     put2.add(HConstants.CATALOG_FAMILY, null, two);
4298     put3.add(HConstants.CATALOG_FAMILY, null, three);
4299     put4.add(HConstants.CATALOG_FAMILY, null, four);
4300     table.put(put1);
4301     table.put(put2);
4302     table.put(put3);
4303     table.put(put4);
4304     region.flush(true);
4305     Result result = null;
4306 
4307     // Test before first that null is returned
4308     result = table.getRowOrBefore(beforeFirstRow, HConstants.CATALOG_FAMILY);
4309     assertTrue(result == null);
4310 
4311     // Test at first that first is returned
4312     result = table.getRowOrBefore(firstRow, HConstants.CATALOG_FAMILY);
4313     assertTrue(result.containsColumn(HConstants.CATALOG_FAMILY, null));
4314     assertTrue(Bytes.equals(result.getRow(), firstRow));
4315     assertTrue(Bytes.equals(result.getValue(HConstants.CATALOG_FAMILY, null), one));
4316 
4317     // Test in between first and second that first is returned
4318     result = table.getRowOrBefore(beforeSecondRow, HConstants.CATALOG_FAMILY);
4319     assertTrue(result.containsColumn(HConstants.CATALOG_FAMILY, null));
4320     assertTrue(Bytes.equals(result.getRow(), firstRow));
4321     assertTrue(Bytes.equals(result.getValue(HConstants.CATALOG_FAMILY, null), one));
4322 
4323     // Test at second make sure second is returned
4324     result = table.getRowOrBefore(secondRow, HConstants.CATALOG_FAMILY);
4325     assertTrue(result.containsColumn(HConstants.CATALOG_FAMILY, null));
4326     assertTrue(Bytes.equals(result.getRow(), secondRow));
4327     assertTrue(Bytes.equals(result.getValue(HConstants.CATALOG_FAMILY, null), two));
4328 
4329     // Test in second and third, make sure second is returned
4330     result = table.getRowOrBefore(beforeThirdRow, HConstants.CATALOG_FAMILY);
4331     assertTrue(result.containsColumn(HConstants.CATALOG_FAMILY, null));
4332     assertTrue(Bytes.equals(result.getRow(), secondRow));
4333     assertTrue(Bytes.equals(result.getValue(HConstants.CATALOG_FAMILY, null), two));
4334 
4335     // Test at third make sure third is returned
4336     result = table.getRowOrBefore(thirdRow, HConstants.CATALOG_FAMILY);
4337     assertTrue(result.containsColumn(HConstants.CATALOG_FAMILY, null));
4338     assertTrue(Bytes.equals(result.getRow(), thirdRow));
4339     assertTrue(Bytes.equals(result.getValue(HConstants.CATALOG_FAMILY, null), three));
4340 
4341     // Test in third and forth, make sure third is returned
4342     result = table.getRowOrBefore(beforeForthRow, HConstants.CATALOG_FAMILY);
4343     assertTrue(result.containsColumn(HConstants.CATALOG_FAMILY, null));
4344     assertTrue(Bytes.equals(result.getRow(), thirdRow));
4345     assertTrue(Bytes.equals(result.getValue(HConstants.CATALOG_FAMILY, null), three));
4346 
4347     // Test at forth make sure forth is returned
4348     result = table.getRowOrBefore(forthRow, HConstants.CATALOG_FAMILY);
4349     assertTrue(result.containsColumn(HConstants.CATALOG_FAMILY, null));
4350     assertTrue(Bytes.equals(result.getRow(), forthRow));
4351     assertTrue(Bytes.equals(result.getValue(HConstants.CATALOG_FAMILY, null), four));
4352 
4353     // Test after forth make sure forth is returned
4354     result = table.getRowOrBefore(Bytes.add(forthRow, one), HConstants.CATALOG_FAMILY);
4355     assertTrue(result.containsColumn(HConstants.CATALOG_FAMILY, null));
4356     assertTrue(Bytes.equals(result.getRow(), forthRow));
4357     assertTrue(Bytes.equals(result.getValue(HConstants.CATALOG_FAMILY, null), four));
4358 
4359     table.close();
4360   }
4361 
4362   /**
4363    * For HBASE-2156
4364    * @throws Exception
4365    */
4366   @Test
4367   public void testScanVariableReuse() throws Exception {
4368     Scan scan = new Scan();
4369     scan.addFamily(FAMILY);
4370     scan.addColumn(FAMILY, ROW);
4371 
4372     assertTrue(scan.getFamilyMap().get(FAMILY).size() == 1);
4373 
4374     scan = new Scan();
4375     scan.addFamily(FAMILY);
4376 
4377     assertTrue(scan.getFamilyMap().get(FAMILY) == null);
4378     assertTrue(scan.getFamilyMap().containsKey(FAMILY));
4379   }
4380 
4381   @Test
4382   public void testMultiRowMutation() throws Exception {
4383     LOG.info("Starting testMultiRowMutation");
4384     final TableName TABLENAME = TableName.valueOf("testMultiRowMutation");
4385     final byte [] ROW1 = Bytes.toBytes("testRow1");
4386 
4387     Table t = TEST_UTIL.createTable(TABLENAME, FAMILY);
4388     Put p = new Put(ROW);
4389     p.add(FAMILY, QUALIFIER, VALUE);
4390     MutationProto m1 = ProtobufUtil.toMutation(MutationType.PUT, p);
4391 
4392     p = new Put(ROW1);
4393     p.add(FAMILY, QUALIFIER, VALUE);
4394     MutationProto m2 = ProtobufUtil.toMutation(MutationType.PUT, p);
4395 
4396     MutateRowsRequest.Builder mrmBuilder = MutateRowsRequest.newBuilder();
4397     mrmBuilder.addMutationRequest(m1);
4398     mrmBuilder.addMutationRequest(m2);
4399     MutateRowsRequest mrm = mrmBuilder.build();
4400     CoprocessorRpcChannel channel = t.coprocessorService(ROW);
4401     MultiRowMutationService.BlockingInterface service =
4402        MultiRowMutationService.newBlockingStub(channel);
4403     service.mutateRows(null, mrm);
4404     Get g = new Get(ROW);
4405     Result r = t.get(g);
4406     assertEquals(0, Bytes.compareTo(VALUE, r.getValue(FAMILY, QUALIFIER)));
4407     g = new Get(ROW1);
4408     r = t.get(g);
4409     assertEquals(0, Bytes.compareTo(VALUE, r.getValue(FAMILY, QUALIFIER)));
4410   }
4411 
4412   @Test
4413   public void testRowMutation() throws Exception {
4414     LOG.info("Starting testRowMutation");
4415     final TableName TABLENAME = TableName.valueOf("testRowMutation");
4416     Table t = TEST_UTIL.createTable(TABLENAME, FAMILY);
4417     byte [][] QUALIFIERS = new byte [][] {
4418         Bytes.toBytes("a"), Bytes.toBytes("b")
4419     };
4420     RowMutations arm = new RowMutations(ROW);
4421     Put p = new Put(ROW);
4422     p.add(FAMILY, QUALIFIERS[0], VALUE);
4423     arm.add(p);
4424     t.mutateRow(arm);
4425 
4426     Get g = new Get(ROW);
4427     Result r = t.get(g);
4428     assertEquals(0, Bytes.compareTo(VALUE, r.getValue(FAMILY, QUALIFIERS[0])));
4429 
4430     arm = new RowMutations(ROW);
4431     p = new Put(ROW);
4432     p.add(FAMILY, QUALIFIERS[1], VALUE);
4433     arm.add(p);
4434     Delete d = new Delete(ROW);
4435     d.deleteColumns(FAMILY, QUALIFIERS[0]);
4436     arm.add(d);
4437     // TODO: Trying mutateRow again.  The batch was failing with a one try only.
4438     t.mutateRow(arm);
4439     r = t.get(g);
4440     assertEquals(0, Bytes.compareTo(VALUE, r.getValue(FAMILY, QUALIFIERS[1])));
4441     assertNull(r.getValue(FAMILY, QUALIFIERS[0]));
4442 
4443     //Test that we get a region level exception
4444     try {
4445       arm = new RowMutations(ROW);
4446       p = new Put(ROW);
4447       p.add(new byte[]{'b', 'o', 'g', 'u', 's'}, QUALIFIERS[0], VALUE);
4448       arm.add(p);
4449       t.mutateRow(arm);
4450       fail("Expected NoSuchColumnFamilyException");
4451     } catch(NoSuchColumnFamilyException e) {
4452     }
4453   }
4454 
4455   @Test
4456   public void testAppend() throws Exception {
4457     LOG.info("Starting testAppend");
4458     final TableName TABLENAME = TableName.valueOf("testAppend");
4459     Table t = TEST_UTIL.createTable(TABLENAME, FAMILY);
4460     byte[] v1 = Bytes.toBytes("42");
4461     byte[] v2 = Bytes.toBytes("23");
4462     byte [][] QUALIFIERS = new byte [][] {
4463         Bytes.toBytes("b"), Bytes.toBytes("a"), Bytes.toBytes("c")
4464     };
4465     Append a = new Append(ROW);
4466     a.add(FAMILY, QUALIFIERS[0], v1);
4467     a.add(FAMILY, QUALIFIERS[1], v2);
4468     a.setReturnResults(false);
4469     assertNullResult(t.append(a));
4470 
4471     a = new Append(ROW);
4472     a.add(FAMILY, QUALIFIERS[0], v2);
4473     a.add(FAMILY, QUALIFIERS[1], v1);
4474     a.add(FAMILY, QUALIFIERS[2], v2);
4475     Result r = t.append(a);
4476     assertEquals(0, Bytes.compareTo(Bytes.add(v1,v2), r.getValue(FAMILY, QUALIFIERS[0])));
4477     assertEquals(0, Bytes.compareTo(Bytes.add(v2,v1), r.getValue(FAMILY, QUALIFIERS[1])));
4478     // QUALIFIERS[2] previously not exist, verify both value and timestamp are correct
4479     assertEquals(0, Bytes.compareTo(v2, r.getValue(FAMILY, QUALIFIERS[2])));
4480     assertEquals(r.getColumnLatest(FAMILY, QUALIFIERS[0]).getTimestamp(),
4481         r.getColumnLatest(FAMILY, QUALIFIERS[2]).getTimestamp());
4482   }
4483 
4484   @Test
4485   public void testClientPoolRoundRobin() throws IOException {
4486     final TableName tableName = TableName.valueOf("testClientPoolRoundRobin");
4487 
4488     int poolSize = 3;
4489     int numVersions = poolSize * 2;
4490     Configuration conf = TEST_UTIL.getConfiguration();
4491     conf.set(HConstants.HBASE_CLIENT_IPC_POOL_TYPE, "round-robin");
4492     conf.setInt(HConstants.HBASE_CLIENT_IPC_POOL_SIZE, poolSize);
4493 
4494     Table table = TEST_UTIL.createTable(tableName, new byte[][] { FAMILY }, conf, Integer.MAX_VALUE);
4495 
4496     final long ts = EnvironmentEdgeManager.currentTime();
4497     Get get = new Get(ROW);
4498     get.addColumn(FAMILY, QUALIFIER);
4499     get.setMaxVersions();
4500 
4501     for (int versions = 1; versions <= numVersions; versions++) {
4502       Put put = new Put(ROW);
4503       put.add(FAMILY, QUALIFIER, ts + versions, VALUE);
4504       table.put(put);
4505 
4506       Result result = table.get(get);
4507       NavigableMap<Long, byte[]> navigableMap = result.getMap().get(FAMILY)
4508           .get(QUALIFIER);
4509 
4510       assertEquals("The number of versions of '" + FAMILY + ":" + QUALIFIER
4511           + " did not match " + versions, versions, navigableMap.size());
4512       for (Map.Entry<Long, byte[]> entry : navigableMap.entrySet()) {
4513         assertTrue("The value at time " + entry.getKey()
4514             + " did not match what was put",
4515             Bytes.equals(VALUE, entry.getValue()));
4516       }
4517     }
4518   }
4519 
4520   @Ignore ("Flakey: HBASE-8989") @Test
4521   public void testClientPoolThreadLocal() throws IOException {
4522     final TableName tableName = TableName.valueOf("testClientPoolThreadLocal");
4523 
4524     int poolSize = Integer.MAX_VALUE;
4525     int numVersions = 3;
4526     Configuration conf = TEST_UTIL.getConfiguration();
4527     conf.set(HConstants.HBASE_CLIENT_IPC_POOL_TYPE, "thread-local");
4528     conf.setInt(HConstants.HBASE_CLIENT_IPC_POOL_SIZE, poolSize);
4529 
4530     final Table table = TEST_UTIL.createTable(tableName,
4531         new byte[][] { FAMILY }, conf, 3);
4532 
4533     final long ts = EnvironmentEdgeManager.currentTime();
4534     final Get get = new Get(ROW);
4535     get.addColumn(FAMILY, QUALIFIER);
4536     get.setMaxVersions();
4537 
4538     for (int versions = 1; versions <= numVersions; versions++) {
4539       Put put = new Put(ROW);
4540       put.add(FAMILY, QUALIFIER, ts + versions, VALUE);
4541       table.put(put);
4542 
4543       Result result = table.get(get);
4544       NavigableMap<Long, byte[]> navigableMap = result.getMap().get(FAMILY)
4545           .get(QUALIFIER);
4546 
4547       assertEquals("The number of versions of '" + FAMILY + ":" + QUALIFIER + " did not match " +
4548         versions + "; " + put.toString() + ", " + get.toString(), versions, navigableMap.size());
4549       for (Map.Entry<Long, byte[]> entry : navigableMap.entrySet()) {
4550         assertTrue("The value at time " + entry.getKey()
4551             + " did not match what was put",
4552             Bytes.equals(VALUE, entry.getValue()));
4553       }
4554     }
4555 
4556     final Object waitLock = new Object();
4557     ExecutorService executorService = Executors.newFixedThreadPool(numVersions);
4558     final AtomicReference<AssertionError> error = new AtomicReference<AssertionError>(null);
4559     for (int versions = numVersions; versions < numVersions * 2; versions++) {
4560       final int versionsCopy = versions;
4561       executorService.submit(new Callable<Void>() {
4562         @Override
4563         public Void call() {
4564           try {
4565             Put put = new Put(ROW);
4566             put.add(FAMILY, QUALIFIER, ts + versionsCopy, VALUE);
4567             table.put(put);
4568 
4569             Result result = table.get(get);
4570             NavigableMap<Long, byte[]> navigableMap = result.getMap()
4571                 .get(FAMILY).get(QUALIFIER);
4572 
4573             assertEquals("The number of versions of '" + Bytes.toString(FAMILY) + ":"
4574                 + Bytes.toString(QUALIFIER) + " did not match " + versionsCopy, versionsCopy,
4575                 navigableMap.size());
4576             for (Map.Entry<Long, byte[]> entry : navigableMap.entrySet()) {
4577               assertTrue("The value at time " + entry.getKey()
4578                   + " did not match what was put",
4579                   Bytes.equals(VALUE, entry.getValue()));
4580             }
4581             synchronized (waitLock) {
4582               waitLock.wait();
4583             }
4584           } catch (Exception e) {
4585           } catch (AssertionError e) {
4586             // the error happens in a thread, it won't fail the test,
4587             // need to pass it to the caller for proper handling.
4588             error.set(e);
4589             LOG.error(e);
4590           }
4591 
4592           return null;
4593         }
4594       });
4595     }
4596     synchronized (waitLock) {
4597       waitLock.notifyAll();
4598     }
4599     executorService.shutdownNow();
4600     assertNull(error.get());
4601   }
4602 
4603   @Test
4604   public void testCheckAndPut() throws IOException {
4605     final byte [] anotherrow = Bytes.toBytes("anotherrow");
4606     final byte [] value2 = Bytes.toBytes("abcd");
4607 
4608     Table table = TEST_UTIL.createTable(TableName.valueOf("testCheckAndPut"), FAMILY);
4609     Put put1 = new Put(ROW);
4610     put1.add(FAMILY, QUALIFIER, VALUE);
4611 
4612     // row doesn't exist, so using non-null value should be considered "not match".
4613     boolean ok = table.checkAndPut(ROW, FAMILY, QUALIFIER, VALUE, put1);
4614     assertEquals(ok, false);
4615 
4616     // row doesn't exist, so using "null" to check for existence should be considered "match".
4617     ok = table.checkAndPut(ROW, FAMILY, QUALIFIER, null, put1);
4618     assertEquals(ok, true);
4619 
4620     // row now exists, so using "null" to check for existence should be considered "not match".
4621     ok = table.checkAndPut(ROW, FAMILY, QUALIFIER, null, put1);
4622     assertEquals(ok, false);
4623 
4624     Put put2 = new Put(ROW);
4625     put2.add(FAMILY, QUALIFIER, value2);
4626 
4627     // row now exists, use the matching value to check
4628     ok = table.checkAndPut(ROW, FAMILY, QUALIFIER, VALUE, put2);
4629     assertEquals(ok, true);
4630 
4631     Put put3 = new Put(anotherrow);
4632     put3.add(FAMILY, QUALIFIER, VALUE);
4633 
4634     // try to do CheckAndPut on different rows
4635     try {
4636         ok = table.checkAndPut(ROW, FAMILY, QUALIFIER, value2, put3);
4637         fail("trying to check and modify different rows should have failed.");
4638     } catch(Exception e) {}
4639 
4640   }
4641 
4642   @Test
4643   public void testCheckAndPutWithCompareOp() throws IOException {
4644     final byte [] value1 = Bytes.toBytes("aaaa");
4645     final byte [] value2 = Bytes.toBytes("bbbb");
4646     final byte [] value3 = Bytes.toBytes("cccc");
4647     final byte [] value4 = Bytes.toBytes("dddd");
4648 
4649     Table table = TEST_UTIL.createTable(TableName.valueOf("testCheckAndPutWithCompareOp"), FAMILY);
4650 
4651     Put put2 = new Put(ROW);
4652     put2.add(FAMILY, QUALIFIER, value2);
4653 
4654     Put put3 = new Put(ROW);
4655     put3.add(FAMILY, QUALIFIER, value3);
4656 
4657     // row doesn't exist, so using "null" to check for existence should be considered "match".
4658     boolean ok = table.checkAndPut(ROW, FAMILY, QUALIFIER, null, put2);
4659     assertEquals(ok, true);
4660 
4661     // cell = "bbbb", using "aaaa" to compare only LESS/LESS_OR_EQUAL/NOT_EQUAL
4662     // turns out "match"
4663     ok = table.checkAndPut(ROW, FAMILY, QUALIFIER, CompareOp.GREATER, value1, put2);
4664     assertEquals(ok, false);
4665     ok = table.checkAndPut(ROW, FAMILY, QUALIFIER, CompareOp.EQUAL, value1, put2);
4666     assertEquals(ok, false);
4667     ok = table.checkAndPut(ROW, FAMILY, QUALIFIER, CompareOp.GREATER_OR_EQUAL, value1, put2);
4668     assertEquals(ok, false);
4669     ok = table.checkAndPut(ROW, FAMILY, QUALIFIER, CompareOp.LESS, value1, put2);
4670     assertEquals(ok, true);
4671     ok = table.checkAndPut(ROW, FAMILY, QUALIFIER, CompareOp.LESS_OR_EQUAL, value1, put2);
4672     assertEquals(ok, true);
4673     ok = table.checkAndPut(ROW, FAMILY, QUALIFIER, CompareOp.NOT_EQUAL, value1, put3);
4674     assertEquals(ok, true);
4675 
4676     // cell = "cccc", using "dddd" to compare only LARGER/LARGER_OR_EQUAL/NOT_EQUAL
4677     // turns out "match"
4678     ok = table.checkAndPut(ROW, FAMILY, QUALIFIER, CompareOp.LESS, value4, put3);
4679     assertEquals(ok, false);
4680     ok = table.checkAndPut(ROW, FAMILY, QUALIFIER, CompareOp.LESS_OR_EQUAL, value4, put3);
4681     assertEquals(ok, false);
4682     ok = table.checkAndPut(ROW, FAMILY, QUALIFIER, CompareOp.EQUAL, value4, put3);
4683     assertEquals(ok, false);
4684     ok = table.checkAndPut(ROW, FAMILY, QUALIFIER, CompareOp.GREATER, value4, put3);
4685     assertEquals(ok, true);
4686     ok = table.checkAndPut(ROW, FAMILY, QUALIFIER, CompareOp.GREATER_OR_EQUAL, value4, put3);
4687     assertEquals(ok, true);
4688     ok = table.checkAndPut(ROW, FAMILY, QUALIFIER, CompareOp.NOT_EQUAL, value4, put2);
4689     assertEquals(ok, true);
4690 
4691     // cell = "bbbb", using "bbbb" to compare only GREATER_OR_EQUAL/LESS_OR_EQUAL/EQUAL
4692     // turns out "match"
4693     ok = table.checkAndPut(ROW, FAMILY, QUALIFIER, CompareOp.GREATER, value2, put2);
4694     assertEquals(ok, false);
4695     ok = table.checkAndPut(ROW, FAMILY, QUALIFIER, CompareOp.NOT_EQUAL, value2, put2);
4696     assertEquals(ok, false);
4697     ok = table.checkAndPut(ROW, FAMILY, QUALIFIER, CompareOp.LESS, value2, put2);
4698     assertEquals(ok, false);
4699     ok = table.checkAndPut(ROW, FAMILY, QUALIFIER, CompareOp.GREATER_OR_EQUAL, value2, put2);
4700     assertEquals(ok, true);
4701     ok = table.checkAndPut(ROW, FAMILY, QUALIFIER, CompareOp.LESS_OR_EQUAL, value2, put2);
4702     assertEquals(ok, true);
4703     ok = table.checkAndPut(ROW, FAMILY, QUALIFIER, CompareOp.EQUAL, value2, put3);
4704     assertEquals(ok, true);
4705   }
4706 
4707   @Test
4708   public void testCheckAndDeleteWithCompareOp() throws IOException {
4709     final byte [] value1 = Bytes.toBytes("aaaa");
4710     final byte [] value2 = Bytes.toBytes("bbbb");
4711     final byte [] value3 = Bytes.toBytes("cccc");
4712     final byte [] value4 = Bytes.toBytes("dddd");
4713 
4714     Table table = TEST_UTIL.createTable(TableName.valueOf("testCheckAndDeleteWithCompareOp"),
4715         FAMILY);
4716 
4717     Put put2 = new Put(ROW);
4718     put2.add(FAMILY, QUALIFIER, value2);
4719     table.put(put2);
4720 
4721     Put put3 = new Put(ROW);
4722     put3.add(FAMILY, QUALIFIER, value3);
4723 
4724     Delete delete = new Delete(ROW);
4725     delete.deleteColumns(FAMILY, QUALIFIER);
4726 
4727     // cell = "bbbb", using "aaaa" to compare only LESS/LESS_OR_EQUAL/NOT_EQUAL
4728     // turns out "match"
4729     boolean ok = table.checkAndDelete(ROW, FAMILY, QUALIFIER, CompareOp.GREATER, value1, delete);
4730     assertEquals(ok, false);
4731     ok = table.checkAndDelete(ROW, FAMILY, QUALIFIER, CompareOp.EQUAL, value1, delete);
4732     assertEquals(ok, false);
4733     ok = table.checkAndDelete(ROW, FAMILY, QUALIFIER, CompareOp.GREATER_OR_EQUAL, value1, delete);
4734     assertEquals(ok, false);
4735     ok = table.checkAndDelete(ROW, FAMILY, QUALIFIER, CompareOp.LESS, value1, delete);
4736     assertEquals(ok, true);
4737     table.put(put2);
4738     ok = table.checkAndDelete(ROW, FAMILY, QUALIFIER, CompareOp.LESS_OR_EQUAL, value1, delete);
4739     assertEquals(ok, true);
4740     table.put(put2);
4741     ok = table.checkAndDelete(ROW, FAMILY, QUALIFIER, CompareOp.NOT_EQUAL, value1, delete);
4742     assertEquals(ok, true);
4743 
4744     // cell = "cccc", using "dddd" to compare only LARGER/LARGER_OR_EQUAL/NOT_EQUAL
4745     // turns out "match"
4746     table.put(put3);
4747     ok = table.checkAndDelete(ROW, FAMILY, QUALIFIER, CompareOp.LESS, value4, delete);
4748     assertEquals(ok, false);
4749     ok = table.checkAndDelete(ROW, FAMILY, QUALIFIER, CompareOp.LESS_OR_EQUAL, value4, delete);
4750     assertEquals(ok, false);
4751     ok = table.checkAndDelete(ROW, FAMILY, QUALIFIER, CompareOp.EQUAL, value4, delete);
4752     assertEquals(ok, false);
4753     ok = table.checkAndDelete(ROW, FAMILY, QUALIFIER, CompareOp.GREATER, value4, delete);
4754     assertEquals(ok, true);
4755     table.put(put3);
4756     ok = table.checkAndDelete(ROW, FAMILY, QUALIFIER, CompareOp.GREATER_OR_EQUAL, value4, delete);
4757     assertEquals(ok, true);
4758     table.put(put3);
4759     ok = table.checkAndDelete(ROW, FAMILY, QUALIFIER, CompareOp.NOT_EQUAL, value4, delete);
4760     assertEquals(ok, true);
4761 
4762     // cell = "bbbb", using "bbbb" to compare only GREATER_OR_EQUAL/LESS_OR_EQUAL/EQUAL
4763     // turns out "match"
4764     table.put(put2);
4765     ok = table.checkAndDelete(ROW, FAMILY, QUALIFIER, CompareOp.GREATER, value2, delete);
4766     assertEquals(ok, false);
4767     ok = table.checkAndDelete(ROW, FAMILY, QUALIFIER, CompareOp.NOT_EQUAL, value2, delete);
4768     assertEquals(ok, false);
4769     ok = table.checkAndDelete(ROW, FAMILY, QUALIFIER, CompareOp.LESS, value2, delete);
4770     assertEquals(ok, false);
4771     ok = table.checkAndDelete(ROW, FAMILY, QUALIFIER, CompareOp.GREATER_OR_EQUAL, value2, delete);
4772     assertEquals(ok, true);
4773     table.put(put2);
4774     ok = table.checkAndDelete(ROW, FAMILY, QUALIFIER, CompareOp.LESS_OR_EQUAL, value2, delete);
4775     assertEquals(ok, true);
4776     table.put(put2);
4777     ok = table.checkAndDelete(ROW, FAMILY, QUALIFIER, CompareOp.EQUAL, value2, delete);
4778     assertEquals(ok, true);
4779   }
4780 
4781   /**
4782   * Test ScanMetrics
4783   * @throws Exception
4784   */
4785   @Test
4786   @SuppressWarnings ("unused")
4787   public void testScanMetrics() throws Exception {
4788     TableName TABLENAME = TableName.valueOf("testScanMetrics");
4789 
4790     Configuration conf = TEST_UTIL.getConfiguration();
4791 
4792     // Set up test table:
4793     // Create table:
4794     HTable ht = TEST_UTIL.createMultiRegionTable(TABLENAME, FAMILY);
4795     int numOfRegions = -1;
4796     try (RegionLocator r = ht.getRegionLocator()) {
4797       numOfRegions = r.getStartKeys().length;
4798     }
4799     // Create 3 rows in the table, with rowkeys starting with "zzz*" so that
4800     // scan are forced to hit all the regions.
4801     Put put1 = new Put(Bytes.toBytes("zzz1"));
4802     put1.add(FAMILY, QUALIFIER, VALUE);
4803     Put put2 = new Put(Bytes.toBytes("zzz2"));
4804     put2.add(FAMILY, QUALIFIER, VALUE);
4805     Put put3 = new Put(Bytes.toBytes("zzz3"));
4806     put3.add(FAMILY, QUALIFIER, VALUE);
4807     ht.put(Arrays.asList(put1, put2, put3));
4808 
4809     Scan scan1 = new Scan();
4810     int numRecords = 0;
4811     ResultScanner scanner = ht.getScanner(scan1);
4812     for(Result result : scanner) {
4813       numRecords++;
4814     }
4815     scanner.close();
4816     LOG.info("test data has " + numRecords + " records.");
4817 
4818     // by default, scan metrics collection is turned off
4819     assertEquals(null, scan1.getScanMetrics());
4820 
4821     // turn on scan metrics
4822     Scan scan2 = new Scan();
4823     scan2.setScanMetricsEnabled(true);
4824     scan2.setCaching(numRecords+1);
4825     scanner = ht.getScanner(scan2);
4826     for (Result result : scanner.next(numRecords - 1)) {
4827     }
4828     scanner.close();
4829     // closing the scanner will set the metrics.
4830     assertNotNull(scan2.getScanMetrics());
4831 
4832     // set caching to 1, because metrics are collected in each roundtrip only
4833     scan2 = new Scan();
4834     scan2.setScanMetricsEnabled(true);
4835     scan2.setCaching(1);
4836     scanner = ht.getScanner(scan2);
4837     // per HBASE-5717, this should still collect even if you don't run all the way to
4838     // the end of the scanner. So this is asking for 2 of the 3 rows we inserted.
4839     for (Result result : scanner.next(numRecords - 1)) {
4840     }
4841     scanner.close();
4842 
4843     ScanMetrics scanMetrics = scan2.getScanMetrics();
4844     assertEquals("Did not access all the regions in the table", numOfRegions,
4845         scanMetrics.countOfRegions.get());
4846 
4847     // check byte counters
4848     scan2 = new Scan();
4849     scan2.setScanMetricsEnabled(true);
4850     scan2.setCaching(1);
4851     scanner = ht.getScanner(scan2);
4852     int numBytes = 0;
4853     for (Result result : scanner.next(1)) {
4854       for (Cell cell: result.listCells()) {
4855         numBytes += CellUtil.estimatedSerializedSizeOf(cell);
4856       }
4857     }
4858     scanner.close();
4859     scanMetrics = scan2.getScanMetrics();
4860     assertEquals("Did not count the result bytes", numBytes,
4861       scanMetrics.countOfBytesInResults.get());
4862 
4863     // check byte counters on a small scan
4864     scan2 = new Scan();
4865     scan2.setScanMetricsEnabled(true);
4866     scan2.setCaching(1);
4867     scan2.setSmall(true);
4868     scanner = ht.getScanner(scan2);
4869     numBytes = 0;
4870     for (Result result : scanner.next(1)) {
4871       for (Cell cell: result.listCells()) {
4872         numBytes += CellUtil.estimatedSerializedSizeOf(cell);
4873       }
4874     }
4875     scanner.close();
4876     scanMetrics = scan2.getScanMetrics();
4877     assertEquals("Did not count the result bytes", numBytes,
4878       scanMetrics.countOfBytesInResults.get());
4879 
4880     // now, test that the metrics are still collected even if you don't call close, but do
4881     // run past the end of all the records
4882     /** There seems to be a timing issue here.  Comment out for now. Fix when time.
4883     Scan scanWithoutClose = new Scan();
4884     scanWithoutClose.setCaching(1);
4885     scanWithoutClose.setScanMetricsEnabled(true);
4886     ResultScanner scannerWithoutClose = ht.getScanner(scanWithoutClose);
4887     for (Result result : scannerWithoutClose.next(numRecords + 1)) {
4888     }
4889     ScanMetrics scanMetricsWithoutClose = getScanMetrics(scanWithoutClose);
4890     assertEquals("Did not access all the regions in the table", numOfRegions,
4891         scanMetricsWithoutClose.countOfRegions.get());
4892     */
4893 
4894     // finally, test that the metrics are collected correctly if you both run past all the records,
4895     // AND close the scanner
4896     Scan scanWithClose = new Scan();
4897     // make sure we can set caching up to the number of a scanned values
4898     scanWithClose.setCaching(numRecords);
4899     scanWithClose.setScanMetricsEnabled(true);
4900     ResultScanner scannerWithClose = ht.getScanner(scanWithClose);
4901     for (Result result : scannerWithClose.next(numRecords + 1)) {
4902     }
4903     scannerWithClose.close();
4904     ScanMetrics scanMetricsWithClose = getScanMetrics(scanWithClose);
4905     assertEquals("Did not access all the regions in the table", numOfRegions,
4906         scanMetricsWithClose.countOfRegions.get());
4907   }
4908 
4909   private ScanMetrics getScanMetrics(Scan scan) throws Exception {
4910     byte[] serializedMetrics = scan.getAttribute(Scan.SCAN_ATTRIBUTES_METRICS_DATA);
4911     assertTrue("Serialized metrics were not found.", serializedMetrics != null);
4912 
4913     ScanMetrics scanMetrics = ProtobufUtil.toScanMetrics(serializedMetrics);
4914 
4915     return scanMetrics;
4916   }
4917 
4918   /**
4919    * Tests that cache on write works all the way up from the client-side.
4920    *
4921    * Performs inserts, flushes, and compactions, verifying changes in the block
4922    * cache along the way.
4923    *
4924    * @throws Exception
4925    */
4926   @Test
4927   public void testCacheOnWriteEvictOnClose() throws Exception {
4928     TableName tableName = TableName.valueOf("testCOWEOCfromClient");
4929     byte [] data = Bytes.toBytes("data");
4930     HTable table = TEST_UTIL.createTable(tableName, FAMILY);
4931     // get the block cache and region
4932     String regionName = table.getRegionLocations().firstKey().getEncodedName();
4933     Region region = TEST_UTIL.getRSForFirstRegionInTable(tableName)
4934       .getFromOnlineRegions(regionName);
4935     Store store = region.getStores().iterator().next();
4936     CacheConfig cacheConf = store.getCacheConfig();
4937     cacheConf.setCacheDataOnWrite(true);
4938     cacheConf.setEvictOnClose(true);
4939     BlockCache cache = cacheConf.getBlockCache();
4940 
4941     // establish baseline stats
4942     long startBlockCount = cache.getBlockCount();
4943     long startBlockHits = cache.getStats().getHitCount();
4944     long startBlockMiss = cache.getStats().getMissCount();
4945 
4946     // wait till baseline is stable, (minimal 500 ms)
4947     for (int i = 0; i < 5; i++) {
4948       Thread.sleep(100);
4949       if (startBlockCount != cache.getBlockCount()
4950           || startBlockHits != cache.getStats().getHitCount()
4951           || startBlockMiss != cache.getStats().getMissCount()) {
4952         startBlockCount = cache.getBlockCount();
4953         startBlockHits = cache.getStats().getHitCount();
4954         startBlockMiss = cache.getStats().getMissCount();
4955         i = -1;
4956       }
4957     }
4958 
4959     // insert data
4960     Put put = new Put(ROW);
4961     put.add(FAMILY, QUALIFIER, data);
4962     table.put(put);
4963     assertTrue(Bytes.equals(table.get(new Get(ROW)).value(), data));
4964     // data was in memstore so don't expect any changes
4965     assertEquals(startBlockCount, cache.getBlockCount());
4966     assertEquals(startBlockHits, cache.getStats().getHitCount());
4967     assertEquals(startBlockMiss, cache.getStats().getMissCount());
4968     // flush the data
4969     System.out.println("Flushing cache");
4970     region.flush(true);
4971     // expect one more block in cache, no change in hits/misses
4972     long expectedBlockCount = startBlockCount + 1;
4973     long expectedBlockHits = startBlockHits;
4974     long expectedBlockMiss = startBlockMiss;
4975     assertEquals(expectedBlockCount, cache.getBlockCount());
4976     assertEquals(expectedBlockHits, cache.getStats().getHitCount());
4977     assertEquals(expectedBlockMiss, cache.getStats().getMissCount());
4978     // read the data and expect same blocks, one new hit, no misses
4979     assertTrue(Bytes.equals(table.get(new Get(ROW)).value(), data));
4980     assertEquals(expectedBlockCount, cache.getBlockCount());
4981     assertEquals(++expectedBlockHits, cache.getStats().getHitCount());
4982     assertEquals(expectedBlockMiss, cache.getStats().getMissCount());
4983     // insert a second column, read the row, no new blocks, one new hit
4984     byte [] QUALIFIER2 = Bytes.add(QUALIFIER, QUALIFIER);
4985     byte [] data2 = Bytes.add(data, data);
4986     put = new Put(ROW);
4987     put.add(FAMILY, QUALIFIER2, data2);
4988     table.put(put);
4989     Result r = table.get(new Get(ROW));
4990     assertTrue(Bytes.equals(r.getValue(FAMILY, QUALIFIER), data));
4991     assertTrue(Bytes.equals(r.getValue(FAMILY, QUALIFIER2), data2));
4992     assertEquals(expectedBlockCount, cache.getBlockCount());
4993     assertEquals(++expectedBlockHits, cache.getStats().getHitCount());
4994     assertEquals(expectedBlockMiss, cache.getStats().getMissCount());
4995     // flush, one new block
4996     System.out.println("Flushing cache");
4997     region.flush(true);
4998     assertEquals(++expectedBlockCount, cache.getBlockCount());
4999     assertEquals(expectedBlockHits, cache.getStats().getHitCount());
5000     assertEquals(expectedBlockMiss, cache.getStats().getMissCount());
5001     // compact, net minus two blocks, two hits, no misses
5002     System.out.println("Compacting");
5003     assertEquals(2, store.getStorefilesCount());
5004     store.triggerMajorCompaction();
5005     region.compact(true);
5006     waitForStoreFileCount(store, 1, 10000); // wait 10 seconds max
5007     assertEquals(1, store.getStorefilesCount());
5008     expectedBlockCount -= 2; // evicted two blocks, cached none
5009     assertEquals(expectedBlockCount, cache.getBlockCount());
5010     expectedBlockHits += 2;
5011     assertEquals(expectedBlockMiss, cache.getStats().getMissCount());
5012     assertEquals(expectedBlockHits, cache.getStats().getHitCount());
5013     // read the row, this should be a cache miss because we don't cache data
5014     // blocks on compaction
5015     r = table.get(new Get(ROW));
5016     assertTrue(Bytes.equals(r.getValue(FAMILY, QUALIFIER), data));
5017     assertTrue(Bytes.equals(r.getValue(FAMILY, QUALIFIER2), data2));
5018     expectedBlockCount += 1; // cached one data block
5019     assertEquals(expectedBlockCount, cache.getBlockCount());
5020     assertEquals(expectedBlockHits, cache.getStats().getHitCount());
5021     assertEquals(++expectedBlockMiss, cache.getStats().getMissCount());
5022   }
5023 
5024   private void waitForStoreFileCount(Store store, int count, int timeout)
5025   throws InterruptedException {
5026     long start = System.currentTimeMillis();
5027     while (start + timeout > System.currentTimeMillis() &&
5028         store.getStorefilesCount() != count) {
5029       Thread.sleep(100);
5030     }
5031     System.out.println("start=" + start + ", now=" +
5032         System.currentTimeMillis() + ", cur=" + store.getStorefilesCount());
5033     assertEquals(count, store.getStorefilesCount());
5034   }
5035 
5036   @Test
5037   /**
5038    * Tests the non cached version of getRegionLocator by moving a region.
5039    */
5040   public void testNonCachedGetRegionLocation() throws Exception {
5041     // Test Initialization.
5042     TableName TABLE = TableName.valueOf("testNonCachedGetRegionLocation");
5043     byte [] family1 = Bytes.toBytes("f1");
5044     byte [] family2 = Bytes.toBytes("f2");
5045     try (HTable table = TEST_UTIL.createTable(TABLE, new byte[][] {family1, family2}, 10);
5046         Admin admin = new HBaseAdmin(TEST_UTIL.getConfiguration())) {
5047       Map <HRegionInfo, ServerName> regionsMap = table.getRegionLocations();
5048       assertEquals(1, regionsMap.size());
5049       HRegionInfo regionInfo = regionsMap.keySet().iterator().next();
5050       ServerName addrBefore = regionsMap.get(regionInfo);
5051       // Verify region location before move.
5052       HRegionLocation addrCache = table.getRegionLocation(regionInfo.getStartKey(), false);
5053       HRegionLocation addrNoCache = table.getRegionLocation(regionInfo.getStartKey(),  true);
5054 
5055       assertEquals(addrBefore.getPort(), addrCache.getPort());
5056       assertEquals(addrBefore.getPort(), addrNoCache.getPort());
5057 
5058       ServerName addrAfter = null;
5059       // Now move the region to a different server.
5060       for (int i = 0; i < SLAVES; i++) {
5061         HRegionServer regionServer = TEST_UTIL.getHBaseCluster().getRegionServer(i);
5062         ServerName addr = regionServer.getServerName();
5063         if (addr.getPort() != addrBefore.getPort()) {
5064           admin.move(regionInfo.getEncodedNameAsBytes(),
5065               Bytes.toBytes(addr.toString()));
5066           // Wait for the region to move.
5067           Thread.sleep(5000);
5068           addrAfter = addr;
5069           break;
5070         }
5071       }
5072 
5073       // Verify the region was moved.
5074       addrCache = table.getRegionLocation(regionInfo.getStartKey(), false);
5075       addrNoCache = table.getRegionLocation(regionInfo.getStartKey(), true);
5076       assertNotNull(addrAfter);
5077       assertTrue(addrAfter.getPort() != addrCache.getPort());
5078       assertEquals(addrAfter.getPort(), addrNoCache.getPort());
5079     }
5080   }
5081 
5082   @Test
5083   /**
5084    * Tests getRegionsInRange by creating some regions over which a range of
5085    * keys spans; then changing the key range.
5086    */
5087   public void testGetRegionsInRange() throws Exception {
5088     // Test Initialization.
5089     byte [] startKey = Bytes.toBytes("ddc");
5090     byte [] endKey = Bytes.toBytes("mmm");
5091     TableName TABLE = TableName.valueOf("testGetRegionsInRange");
5092     HTable table = TEST_UTIL.createMultiRegionTable(TABLE, new byte[][] { FAMILY }, 10);
5093     int numOfRegions = -1;
5094     try (RegionLocator r = table.getRegionLocator()) {
5095       numOfRegions = r.getStartKeys().length;
5096     }
5097     assertEquals(26, numOfRegions);
5098 
5099     // Get the regions in this range
5100     List<HRegionLocation> regionsList = table.getRegionsInRange(startKey,
5101       endKey);
5102     assertEquals(10, regionsList.size());
5103 
5104     // Change the start key
5105     startKey = Bytes.toBytes("fff");
5106     regionsList = table.getRegionsInRange(startKey, endKey);
5107     assertEquals(7, regionsList.size());
5108 
5109     // Change the end key
5110     endKey = Bytes.toBytes("nnn");
5111     regionsList = table.getRegionsInRange(startKey, endKey);
5112     assertEquals(8, regionsList.size());
5113 
5114     // Empty start key
5115     regionsList = table.getRegionsInRange(HConstants.EMPTY_START_ROW, endKey);
5116     assertEquals(13, regionsList.size());
5117 
5118     // Empty end key
5119     regionsList = table.getRegionsInRange(startKey, HConstants.EMPTY_END_ROW);
5120     assertEquals(21, regionsList.size());
5121 
5122     // Both start and end keys empty
5123     regionsList = table.getRegionsInRange(HConstants.EMPTY_START_ROW,
5124       HConstants.EMPTY_END_ROW);
5125     assertEquals(26, regionsList.size());
5126 
5127     // Change the end key to somewhere in the last block
5128     endKey = Bytes.toBytes("zzz1");
5129     regionsList = table.getRegionsInRange(startKey, endKey);
5130     assertEquals(21, regionsList.size());
5131 
5132     // Change the start key to somewhere in the first block
5133     startKey = Bytes.toBytes("aac");
5134     regionsList = table.getRegionsInRange(startKey, endKey);
5135     assertEquals(26, regionsList.size());
5136 
5137     // Make start and end key the same
5138     startKey = endKey = Bytes.toBytes("ccc");
5139     regionsList = table.getRegionsInRange(startKey, endKey);
5140     assertEquals(1, regionsList.size());
5141   }
5142 
5143   @Test
5144   public void testJira6912() throws Exception {
5145     TableName TABLE = TableName.valueOf("testJira6912");
5146     Table foo = TEST_UTIL.createTable(TABLE, new byte[][] {FAMILY}, 10);
5147 
5148     List<Put> puts = new ArrayList<Put>();
5149     for (int i=0;i !=100; i++){
5150       Put put = new Put(Bytes.toBytes(i));
5151       put.add(FAMILY, FAMILY, Bytes.toBytes(i));
5152       puts.add(put);
5153     }
5154     foo.put(puts);
5155     // If i comment this out it works
5156     TEST_UTIL.flush();
5157 
5158     Scan scan = new Scan();
5159     scan.setStartRow(Bytes.toBytes(1));
5160     scan.setStopRow(Bytes.toBytes(3));
5161     scan.addColumn(FAMILY, FAMILY);
5162     scan.setFilter(new RowFilter(CompareFilter.CompareOp.NOT_EQUAL, new BinaryComparator(Bytes.toBytes(1))));
5163 
5164     ResultScanner scanner = foo.getScanner(scan);
5165     Result[] bar = scanner.next(100);
5166     assertEquals(1, bar.length);
5167   }
5168 
5169   @Test
5170   public void testScan_NullQualifier() throws IOException {
5171     Table table = TEST_UTIL.createTable(TableName.valueOf("testScan_NullQualifier"), FAMILY);
5172     Put put = new Put(ROW);
5173     put.add(FAMILY, QUALIFIER, VALUE);
5174     table.put(put);
5175 
5176     put = new Put(ROW);
5177     put.add(FAMILY, null, VALUE);
5178     table.put(put);
5179     LOG.info("Row put");
5180 
5181     Scan scan = new Scan();
5182     scan.addColumn(FAMILY, null);
5183 
5184     ResultScanner scanner = table.getScanner(scan);
5185     Result[] bar = scanner.next(100);
5186     assertEquals(1, bar.length);
5187     assertEquals(1, bar[0].size());
5188 
5189     scan = new Scan();
5190     scan.addFamily(FAMILY);
5191 
5192     scanner = table.getScanner(scan);
5193     bar = scanner.next(100);
5194     assertEquals(1, bar.length);
5195     assertEquals(2, bar[0].size());
5196   }
5197 
5198   @Test
5199   public void testNegativeTimestamp() throws IOException {
5200     Table table = TEST_UTIL.createTable(TableName.valueOf("testNegativeTimestamp"), FAMILY);
5201 
5202     try {
5203       Put put = new Put(ROW, -1);
5204       put.add(FAMILY, QUALIFIER, VALUE);
5205       table.put(put);
5206       fail("Negative timestamps should not have been allowed");
5207     } catch (IllegalArgumentException ex) {
5208       assertTrue(ex.getMessage().contains("negative"));
5209     }
5210 
5211     try {
5212       Put put = new Put(ROW);
5213       put.add(FAMILY, QUALIFIER, -1, VALUE);
5214       table.put(put);
5215       fail("Negative timestamps should not have been allowed");
5216     } catch (IllegalArgumentException ex) {
5217       assertTrue(ex.getMessage().contains("negative"));
5218     }
5219 
5220     try {
5221       Delete delete = new Delete(ROW, -1);
5222       table.delete(delete);
5223       fail("Negative timestamps should not have been allowed");
5224     } catch (IllegalArgumentException ex) {
5225       assertTrue(ex.getMessage().contains("negative"));
5226     }
5227 
5228     try {
5229       Delete delete = new Delete(ROW);
5230       delete.deleteFamily(FAMILY, -1);
5231       table.delete(delete);
5232       fail("Negative timestamps should not have been allowed");
5233     } catch (IllegalArgumentException ex) {
5234       assertTrue(ex.getMessage().contains("negative"));
5235     }
5236 
5237     try {
5238       Scan scan = new Scan();
5239       scan.setTimeRange(-1, 1);
5240       table.getScanner(scan);
5241       fail("Negative timestamps should not have been allowed");
5242     } catch (IllegalArgumentException ex) {
5243       assertTrue(ex.getMessage().contains("negative"));
5244     }
5245 
5246     // KeyValue should allow negative timestamps for backwards compat. Otherwise, if the user
5247     // already has negative timestamps in cluster data, HBase won't be able to handle that
5248     try {
5249       new KeyValue(Bytes.toBytes(42), Bytes.toBytes(42), Bytes.toBytes(42), -1, Bytes.toBytes(42));
5250     } catch (IllegalArgumentException ex) {
5251       fail("KeyValue SHOULD allow negative timestamps");
5252     }
5253 
5254     table.close();
5255   }
5256 
5257   @Test
5258   public void testIllegalTableDescriptor() throws Exception {
5259     HTableDescriptor htd = new HTableDescriptor(TableName.valueOf("testIllegalTableDescriptor"));
5260     HColumnDescriptor hcd = new HColumnDescriptor(FAMILY);
5261 
5262     // create table with 0 families
5263     checkTableIsIllegal(htd);
5264     htd.addFamily(hcd);
5265     checkTableIsLegal(htd);
5266 
5267     htd.setMaxFileSize(1024); // 1K
5268     checkTableIsIllegal(htd);
5269     htd.setMaxFileSize(0);
5270     checkTableIsIllegal(htd);
5271     htd.setMaxFileSize(1024 * 1024 * 1024); // 1G
5272     checkTableIsLegal(htd);
5273 
5274     htd.setMemStoreFlushSize(1024);
5275     checkTableIsIllegal(htd);
5276     htd.setMemStoreFlushSize(0);
5277     checkTableIsIllegal(htd);
5278     htd.setMemStoreFlushSize(128 * 1024 * 1024); // 128M
5279     checkTableIsLegal(htd);
5280 
5281     htd.setRegionSplitPolicyClassName("nonexisting.foo.class");
5282     checkTableIsIllegal(htd);
5283     htd.setRegionSplitPolicyClassName(null);
5284     checkTableIsLegal(htd);
5285 
5286     hcd.setBlocksize(0);
5287     checkTableIsIllegal(htd);
5288     hcd.setBlocksize(1024 * 1024 * 128); // 128M
5289     checkTableIsIllegal(htd);
5290     hcd.setBlocksize(1024);
5291     checkTableIsLegal(htd);
5292 
5293     hcd.setTimeToLive(0);
5294     checkTableIsIllegal(htd);
5295     hcd.setTimeToLive(-1);
5296     checkTableIsIllegal(htd);
5297     hcd.setTimeToLive(1);
5298     checkTableIsLegal(htd);
5299 
5300     hcd.setMinVersions(-1);
5301     checkTableIsIllegal(htd);
5302     hcd.setMinVersions(3);
5303     try {
5304       hcd.setMaxVersions(2);
5305       fail();
5306     } catch (IllegalArgumentException ex) {
5307       // expected
5308       hcd.setMaxVersions(10);
5309     }
5310     checkTableIsLegal(htd);
5311 
5312     // HBASE-13776 Setting illegal versions for HColumnDescriptor
5313     //  does not throw IllegalArgumentException
5314     // finally, minVersions must be less than or equal to maxVersions
5315     hcd.setMaxVersions(4);
5316     hcd.setMinVersions(5);
5317     checkTableIsIllegal(htd);
5318     hcd.setMinVersions(3);
5319 
5320     hcd.setScope(-1);
5321     checkTableIsIllegal(htd);
5322     hcd.setScope(0);
5323     checkTableIsLegal(htd);
5324 
5325     try {
5326       hcd.setDFSReplication((short) -1);
5327       fail("Illegal value for setDFSReplication did not throw");
5328     } catch (IllegalArgumentException e) {
5329       // pass
5330     }
5331     // set an illegal DFS replication value by hand
5332     hcd.setValue(HColumnDescriptor.DFS_REPLICATION, "-1");
5333     checkTableIsIllegal(htd);
5334     try {
5335       hcd.setDFSReplication((short) -1);
5336       fail("Should throw exception if an illegal value is explicitly being set");
5337     } catch (IllegalArgumentException e) {
5338       // pass
5339     }
5340 
5341     // check the conf settings to disable sanity checks
5342     htd.setMemStoreFlushSize(0);
5343 
5344     // Check that logs warn on invalid table but allow it.
5345     ListAppender listAppender = new ListAppender();
5346     Logger log = Logger.getLogger(HMaster.class);
5347     log.addAppender(listAppender);
5348     log.setLevel(Level.WARN);
5349 
5350     htd.setConfiguration("hbase.table.sanity.checks", Boolean.FALSE.toString());
5351     checkTableIsLegal(htd);
5352 
5353     assertFalse(listAppender.getMessages().isEmpty());
5354     assertTrue(listAppender.getMessages().get(0).startsWith("MEMSTORE_FLUSHSIZE for table "
5355         + "descriptor or \"hbase.hregion.memstore.flush.size\" (0) is too small, which might "
5356         + "cause very frequent flushing."));
5357 
5358     log.removeAppender(listAppender);
5359   }
5360 
5361   private static class ListAppender extends AppenderSkeleton {
5362     private final List<String> messages = new ArrayList<String>();
5363 
5364     @Override
5365     protected void append(LoggingEvent event) {
5366       messages.add(event.getMessage().toString());
5367     }
5368 
5369     @Override
5370     public void close() {
5371     }
5372 
5373     @Override
5374     public boolean requiresLayout() {
5375       return false;
5376     }
5377 
5378     public List<String> getMessages() {
5379       return messages;
5380     }
5381   }
5382 
5383   private void checkTableIsLegal(HTableDescriptor htd) throws IOException {
5384     Admin admin = TEST_UTIL.getHBaseAdmin();
5385     admin.createTable(htd);
5386     assertTrue(admin.tableExists(htd.getTableName()));
5387     admin.disableTable(htd.getTableName());
5388     admin.deleteTable(htd.getTableName());
5389   }
5390 
5391   private void checkTableIsIllegal(HTableDescriptor htd) throws IOException {
5392     Admin admin = TEST_UTIL.getHBaseAdmin();
5393     try {
5394       admin.createTable(htd);
5395       fail();
5396     } catch(Exception ex) {
5397       // should throw ex
5398     }
5399     assertFalse(admin.tableExists(htd.getTableName()));
5400   }
5401 
5402   @Test
5403   public void testRawScanRespectsVersions() throws Exception {
5404     TableName TABLE = TableName.valueOf("testRawScan");
5405     Table table = TEST_UTIL.createTable(TABLE, FAMILY);
5406     byte[] row = Bytes.toBytes("row");
5407 
5408     // put the same row 4 times, with different values
5409     Put p = new Put(row);
5410     p.add(FAMILY, QUALIFIER, 10, VALUE);
5411     table.put(p);
5412     p = new Put(row);
5413     p.add(FAMILY, QUALIFIER, 11, ArrayUtils.add(VALUE, (byte) 2));
5414     table.put(p);
5415 
5416     p = new Put(row);
5417     p.add(FAMILY, QUALIFIER, 12, ArrayUtils.add(VALUE, (byte) 3));
5418     table.put(p);
5419 
5420     p = new Put(row);
5421     p.add(FAMILY, QUALIFIER, 13, ArrayUtils.add(VALUE, (byte) 4));
5422     table.put(p);
5423 
5424     int versions = 4;
5425     Scan s = new Scan(row);
5426     // get all the possible versions
5427     s.setMaxVersions();
5428     s.setRaw(true);
5429 
5430     ResultScanner scanner = table.getScanner(s);
5431     int count = 0;
5432     for (Result r : scanner) {
5433       assertEquals("Found an unexpected number of results for the row!", versions, r.listCells().size());
5434       count++;
5435     }
5436     assertEquals("Found more than a single row when raw scanning the table with a single row!", 1,
5437       count);
5438     scanner.close();
5439 
5440     // then if we decrease the number of versions, but keep the scan raw, we should see exactly that
5441     // number of versions
5442     versions = 2;
5443     s.setMaxVersions(versions);
5444     scanner = table.getScanner(s);
5445     count = 0;
5446     for (Result r : scanner) {
5447       assertEquals("Found an unexpected number of results for the row!", versions, r.listCells().size());
5448       count++;
5449     }
5450     assertEquals("Found more than a single row when raw scanning the table with a single row!", 1,
5451       count);
5452     scanner.close();
5453 
5454     // finally, if we turn off raw scanning, but max out the number of versions, we should go back
5455     // to seeing just three
5456     versions = 3;
5457     s.setMaxVersions(versions);
5458     scanner = table.getScanner(s);
5459     count = 0;
5460     for (Result r : scanner) {
5461       assertEquals("Found an unexpected number of results for the row!", versions, r.listCells().size());
5462       count++;
5463     }
5464     assertEquals("Found more than a single row when raw scanning the table with a single row!", 1,
5465       count);
5466     scanner.close();
5467 
5468     table.close();
5469     TEST_UTIL.deleteTable(TABLE);
5470   }
5471 
5472   @Test
5473   public void testSmallScan() throws Exception {
5474     // Test Initialization.
5475     TableName TABLE = TableName.valueOf("testSmallScan");
5476     Table table = TEST_UTIL.createTable(TABLE, FAMILY);
5477 
5478     // Insert one row each region
5479     int insertNum = 10;
5480     for (int i = 0; i < 10; i++) {
5481       Put put = new Put(Bytes.toBytes("row" + String.format("%03d", i)));
5482       put.add(FAMILY, QUALIFIER, VALUE);
5483       table.put(put);
5484     }
5485 
5486     // nomal scan
5487     ResultScanner scanner = table.getScanner(new Scan());
5488     int count = 0;
5489     for (Result r : scanner) {
5490       assertTrue(!r.isEmpty());
5491       count++;
5492     }
5493     assertEquals(insertNum, count);
5494 
5495     // small scan
5496     Scan scan = new Scan(HConstants.EMPTY_START_ROW, HConstants.EMPTY_END_ROW);
5497     scan.setSmall(true);
5498     scan.setCaching(2);
5499     scanner = table.getScanner(scan);
5500     count = 0;
5501     for (Result r : scanner) {
5502       assertTrue(!r.isEmpty());
5503       count++;
5504     }
5505     assertEquals(insertNum, count);
5506 
5507   }
5508 
5509   @Test
5510   public void testSuperSimpleWithReverseScan() throws Exception {
5511     TableName TABLE = TableName.valueOf("testSuperSimpleWithReverseScan");
5512     Table ht = TEST_UTIL.createTable(TABLE, FAMILY);
5513     Put put = new Put(Bytes.toBytes("0-b11111-0000000000000000000"));
5514     put.add(FAMILY, QUALIFIER, VALUE);
5515     ht.put(put);
5516     put = new Put(Bytes.toBytes("0-b11111-0000000000000000002"));
5517     put.add(FAMILY, QUALIFIER, VALUE);
5518     ht.put(put);
5519     put = new Put(Bytes.toBytes("0-b11111-0000000000000000004"));
5520     put.add(FAMILY, QUALIFIER, VALUE);
5521     ht.put(put);
5522     put = new Put(Bytes.toBytes("0-b11111-0000000000000000006"));
5523     put.add(FAMILY, QUALIFIER, VALUE);
5524     ht.put(put);
5525     put = new Put(Bytes.toBytes("0-b11111-0000000000000000008"));
5526     put.add(FAMILY, QUALIFIER, VALUE);
5527     ht.put(put);
5528     put = new Put(Bytes.toBytes("0-b22222-0000000000000000001"));
5529     put.add(FAMILY, QUALIFIER, VALUE);
5530     ht.put(put);
5531     put = new Put(Bytes.toBytes("0-b22222-0000000000000000003"));
5532     put.add(FAMILY, QUALIFIER, VALUE);
5533     ht.put(put);
5534     put = new Put(Bytes.toBytes("0-b22222-0000000000000000005"));
5535     put.add(FAMILY, QUALIFIER, VALUE);
5536     ht.put(put);
5537     put = new Put(Bytes.toBytes("0-b22222-0000000000000000007"));
5538     put.add(FAMILY, QUALIFIER, VALUE);
5539     ht.put(put);
5540     put = new Put(Bytes.toBytes("0-b22222-0000000000000000009"));
5541     put.add(FAMILY, QUALIFIER, VALUE);
5542     ht.put(put);
5543     Scan scan = new Scan(Bytes.toBytes("0-b11111-9223372036854775807"),
5544         Bytes.toBytes("0-b11111-0000000000000000000"));
5545     scan.setReversed(true);
5546     ResultScanner scanner = ht.getScanner(scan);
5547     Result result = scanner.next();
5548     assertTrue(Bytes.equals(result.getRow(),
5549         Bytes.toBytes("0-b11111-0000000000000000008")));
5550     scanner.close();
5551     ht.close();
5552   }
5553 
5554   @Test
5555   public void testFiltersWithReverseScan() throws Exception {
5556     TableName TABLE = TableName.valueOf("testFiltersWithReverseScan");
5557     Table ht = TEST_UTIL.createTable(TABLE, FAMILY);
5558     byte[][] ROWS = makeN(ROW, 10);
5559     byte[][] QUALIFIERS = { Bytes.toBytes("col0-<d2v1>-<d3v2>"),
5560         Bytes.toBytes("col1-<d2v1>-<d3v2>"),
5561         Bytes.toBytes("col2-<d2v1>-<d3v2>"),
5562         Bytes.toBytes("col3-<d2v1>-<d3v2>"),
5563         Bytes.toBytes("col4-<d2v1>-<d3v2>"),
5564         Bytes.toBytes("col5-<d2v1>-<d3v2>"),
5565         Bytes.toBytes("col6-<d2v1>-<d3v2>"),
5566         Bytes.toBytes("col7-<d2v1>-<d3v2>"),
5567         Bytes.toBytes("col8-<d2v1>-<d3v2>"),
5568         Bytes.toBytes("col9-<d2v1>-<d3v2>") };
5569     for (int i = 0; i < 10; i++) {
5570       Put put = new Put(ROWS[i]);
5571       put.add(FAMILY, QUALIFIERS[i], VALUE);
5572       ht.put(put);
5573     }
5574     Scan scan = new Scan();
5575     scan.setReversed(true);
5576     scan.addFamily(FAMILY);
5577     Filter filter = new QualifierFilter(CompareOp.EQUAL,
5578         new RegexStringComparator("col[1-5]"));
5579     scan.setFilter(filter);
5580     ResultScanner scanner = ht.getScanner(scan);
5581     int expectedIndex = 5;
5582     for (Result result : scanner) {
5583       assertEquals(result.size(), 1);
5584       assertTrue(Bytes.equals(result.raw()[0].getRow(), ROWS[expectedIndex]));
5585       assertTrue(Bytes.equals(result.raw()[0].getQualifier(),
5586           QUALIFIERS[expectedIndex]));
5587       expectedIndex--;
5588     }
5589     assertEquals(expectedIndex, 0);
5590     scanner.close();
5591     ht.close();
5592   }
5593 
5594   @Test
5595   public void testKeyOnlyFilterWithReverseScan() throws Exception {
5596     TableName TABLE = TableName.valueOf("testKeyOnlyFilterWithReverseScan");
5597     Table ht = TEST_UTIL.createTable(TABLE, FAMILY);
5598     byte[][] ROWS = makeN(ROW, 10);
5599     byte[][] QUALIFIERS = { Bytes.toBytes("col0-<d2v1>-<d3v2>"),
5600         Bytes.toBytes("col1-<d2v1>-<d3v2>"),
5601         Bytes.toBytes("col2-<d2v1>-<d3v2>"),
5602         Bytes.toBytes("col3-<d2v1>-<d3v2>"),
5603         Bytes.toBytes("col4-<d2v1>-<d3v2>"),
5604         Bytes.toBytes("col5-<d2v1>-<d3v2>"),
5605         Bytes.toBytes("col6-<d2v1>-<d3v2>"),
5606         Bytes.toBytes("col7-<d2v1>-<d3v2>"),
5607         Bytes.toBytes("col8-<d2v1>-<d3v2>"),
5608         Bytes.toBytes("col9-<d2v1>-<d3v2>") };
5609     for (int i = 0; i < 10; i++) {
5610       Put put = new Put(ROWS[i]);
5611       put.add(FAMILY, QUALIFIERS[i], VALUE);
5612       ht.put(put);
5613     }
5614     Scan scan = new Scan();
5615     scan.setReversed(true);
5616     scan.addFamily(FAMILY);
5617     Filter filter = new KeyOnlyFilter(true);
5618     scan.setFilter(filter);
5619     ResultScanner scanner = ht.getScanner(scan);
5620     int count = 0;
5621     for (Result result : ht.getScanner(scan)) {
5622       assertEquals(result.size(), 1);
5623       assertEquals(result.raw()[0].getValueLength(), Bytes.SIZEOF_INT);
5624       assertEquals(Bytes.toInt(result.raw()[0].getValue()), VALUE.length);
5625       count++;
5626     }
5627     assertEquals(count, 10);
5628     scanner.close();
5629     ht.close();
5630   }
5631 
5632   /**
5633    * Test simple table and non-existent row cases.
5634    */
5635   @Test
5636   public void testSimpleMissingWithReverseScan() throws Exception {
5637     TableName TABLE = TableName.valueOf("testSimpleMissingWithReverseScan");
5638     Table ht = TEST_UTIL.createTable(TABLE, FAMILY);
5639     byte[][] ROWS = makeN(ROW, 4);
5640 
5641     // Try to get a row on an empty table
5642     Scan scan = new Scan();
5643     scan.setReversed(true);
5644     Result result = getSingleScanResult(ht, scan);
5645     assertNullResult(result);
5646 
5647     scan = new Scan(ROWS[0]);
5648     scan.setReversed(true);
5649     result = getSingleScanResult(ht, scan);
5650     assertNullResult(result);
5651 
5652     scan = new Scan(ROWS[0], ROWS[1]);
5653     scan.setReversed(true);
5654     result = getSingleScanResult(ht, scan);
5655     assertNullResult(result);
5656 
5657     scan = new Scan();
5658     scan.setReversed(true);
5659     scan.addFamily(FAMILY);
5660     result = getSingleScanResult(ht, scan);
5661     assertNullResult(result);
5662 
5663     scan = new Scan();
5664     scan.setReversed(true);
5665     scan.addColumn(FAMILY, QUALIFIER);
5666     result = getSingleScanResult(ht, scan);
5667     assertNullResult(result);
5668 
5669     // Insert a row
5670 
5671     Put put = new Put(ROWS[2]);
5672     put.add(FAMILY, QUALIFIER, VALUE);
5673     ht.put(put);
5674 
5675     // Make sure we can scan the row
5676     scan = new Scan();
5677     scan.setReversed(true);
5678     result = getSingleScanResult(ht, scan);
5679     assertSingleResult(result, ROWS[2], FAMILY, QUALIFIER, VALUE);
5680 
5681     scan = new Scan(ROWS[3], ROWS[0]);
5682     scan.setReversed(true);
5683     result = getSingleScanResult(ht, scan);
5684     assertSingleResult(result, ROWS[2], FAMILY, QUALIFIER, VALUE);
5685 
5686     scan = new Scan(ROWS[2], ROWS[1]);
5687     scan.setReversed(true);
5688     result = getSingleScanResult(ht, scan);
5689     assertSingleResult(result, ROWS[2], FAMILY, QUALIFIER, VALUE);
5690 
5691     // Try to scan empty rows around it
5692     // Introduced MemStore#shouldSeekForReverseScan to fix the following
5693     scan = new Scan(ROWS[1]);
5694     scan.setReversed(true);
5695     result = getSingleScanResult(ht, scan);
5696     assertNullResult(result);
5697     ht.close();
5698   }
5699 
5700   @Test
5701   public void testNullWithReverseScan() throws Exception {
5702     TableName TABLE = TableName.valueOf("testNullWithReverseScan");
5703     Table ht = TEST_UTIL.createTable(TABLE, FAMILY);
5704     // Null qualifier (should work)
5705     Put put = new Put(ROW);
5706     put.add(FAMILY, null, VALUE);
5707     ht.put(put);
5708     scanTestNull(ht, ROW, FAMILY, VALUE, true);
5709     Delete delete = new Delete(ROW);
5710     delete.deleteColumns(FAMILY, null);
5711     ht.delete(delete);
5712     // Use a new table
5713     byte[] TABLE2 = Bytes.toBytes("testNull2WithReverseScan");
5714     ht = TEST_UTIL.createTable(TableName.valueOf(TABLE2), FAMILY);
5715     // Empty qualifier, byte[0] instead of null (should work)
5716     put = new Put(ROW);
5717     put.add(FAMILY, HConstants.EMPTY_BYTE_ARRAY, VALUE);
5718     ht.put(put);
5719     scanTestNull(ht, ROW, FAMILY, VALUE, true);
5720     TEST_UTIL.flush();
5721     scanTestNull(ht, ROW, FAMILY, VALUE, true);
5722     delete = new Delete(ROW);
5723     delete.deleteColumns(FAMILY, HConstants.EMPTY_BYTE_ARRAY);
5724     ht.delete(delete);
5725     // Null value
5726     put = new Put(ROW);
5727     put.add(FAMILY, QUALIFIER, null);
5728     ht.put(put);
5729     Scan scan = new Scan();
5730     scan.setReversed(true);
5731     scan.addColumn(FAMILY, QUALIFIER);
5732     Result result = getSingleScanResult(ht, scan);
5733     assertSingleResult(result, ROW, FAMILY, QUALIFIER, null);
5734     ht.close();
5735   }
5736 
5737   @Test
5738   public void testDeletesWithReverseScan() throws Exception {
5739     TableName TABLE = TableName.valueOf("testDeletesWithReverseScan");
5740     byte[][] ROWS = makeNAscii(ROW, 6);
5741     byte[][] FAMILIES = makeNAscii(FAMILY, 3);
5742     byte[][] VALUES = makeN(VALUE, 5);
5743     long[] ts = { 1000, 2000, 3000, 4000, 5000 };
5744     Table ht = TEST_UTIL.createTable(TABLE, FAMILIES, TEST_UTIL.getConfiguration(), 3);
5745 
5746     Put put = new Put(ROW);
5747     put.add(FAMILIES[0], QUALIFIER, ts[0], VALUES[0]);
5748     put.add(FAMILIES[0], QUALIFIER, ts[1], VALUES[1]);
5749     ht.put(put);
5750 
5751     Delete delete = new Delete(ROW);
5752     delete.deleteFamily(FAMILIES[0], ts[0]);
5753     ht.delete(delete);
5754 
5755     Scan scan = new Scan(ROW);
5756     scan.setReversed(true);
5757     scan.addFamily(FAMILIES[0]);
5758     scan.setMaxVersions(Integer.MAX_VALUE);
5759     Result result = getSingleScanResult(ht, scan);
5760     assertNResult(result, ROW, FAMILIES[0], QUALIFIER, new long[] { ts[1] },
5761         new byte[][] { VALUES[1] }, 0, 0);
5762 
5763     // Test delete latest version
5764     put = new Put(ROW);
5765     put.add(FAMILIES[0], QUALIFIER, ts[4], VALUES[4]);
5766     put.add(FAMILIES[0], QUALIFIER, ts[2], VALUES[2]);
5767     put.add(FAMILIES[0], QUALIFIER, ts[3], VALUES[3]);
5768     put.add(FAMILIES[0], null, ts[4], VALUES[4]);
5769     put.add(FAMILIES[0], null, ts[2], VALUES[2]);
5770     put.add(FAMILIES[0], null, ts[3], VALUES[3]);
5771     ht.put(put);
5772 
5773     delete = new Delete(ROW);
5774     delete.deleteColumn(FAMILIES[0], QUALIFIER); // ts[4]
5775     ht.delete(delete);
5776 
5777     scan = new Scan(ROW);
5778     scan.setReversed(true);
5779     scan.addColumn(FAMILIES[0], QUALIFIER);
5780     scan.setMaxVersions(Integer.MAX_VALUE);
5781     result = getSingleScanResult(ht, scan);
5782     assertNResult(result, ROW, FAMILIES[0], QUALIFIER, new long[] { ts[1],
5783         ts[2], ts[3] }, new byte[][] { VALUES[1], VALUES[2], VALUES[3] }, 0, 2);
5784 
5785     // Test for HBASE-1847
5786     delete = new Delete(ROW);
5787     delete.deleteColumn(FAMILIES[0], null);
5788     ht.delete(delete);
5789 
5790     // Cleanup null qualifier
5791     delete = new Delete(ROW);
5792     delete.deleteColumns(FAMILIES[0], null);
5793     ht.delete(delete);
5794 
5795     // Expected client behavior might be that you can re-put deleted values
5796     // But alas, this is not to be. We can't put them back in either case.
5797 
5798     put = new Put(ROW);
5799     put.add(FAMILIES[0], QUALIFIER, ts[0], VALUES[0]); // 1000
5800     put.add(FAMILIES[0], QUALIFIER, ts[4], VALUES[4]); // 5000
5801     ht.put(put);
5802 
5803     // The Scanner returns the previous values, the expected-naive-unexpected
5804     // behavior
5805 
5806     scan = new Scan(ROW);
5807     scan.setReversed(true);
5808     scan.addFamily(FAMILIES[0]);
5809     scan.setMaxVersions(Integer.MAX_VALUE);
5810     result = getSingleScanResult(ht, scan);
5811     assertNResult(result, ROW, FAMILIES[0], QUALIFIER, new long[] { ts[1],
5812         ts[2], ts[3] }, new byte[][] { VALUES[1], VALUES[2], VALUES[3] }, 0, 2);
5813 
5814     // Test deleting an entire family from one row but not the other various
5815     // ways
5816 
5817     put = new Put(ROWS[0]);
5818     put.add(FAMILIES[1], QUALIFIER, ts[0], VALUES[0]);
5819     put.add(FAMILIES[1], QUALIFIER, ts[1], VALUES[1]);
5820     put.add(FAMILIES[2], QUALIFIER, ts[2], VALUES[2]);
5821     put.add(FAMILIES[2], QUALIFIER, ts[3], VALUES[3]);
5822     ht.put(put);
5823 
5824     put = new Put(ROWS[1]);
5825     put.add(FAMILIES[1], QUALIFIER, ts[0], VALUES[0]);
5826     put.add(FAMILIES[1], QUALIFIER, ts[1], VALUES[1]);
5827     put.add(FAMILIES[2], QUALIFIER, ts[2], VALUES[2]);
5828     put.add(FAMILIES[2], QUALIFIER, ts[3], VALUES[3]);
5829     ht.put(put);
5830 
5831     put = new Put(ROWS[2]);
5832     put.add(FAMILIES[1], QUALIFIER, ts[0], VALUES[0]);
5833     put.add(FAMILIES[1], QUALIFIER, ts[1], VALUES[1]);
5834     put.add(FAMILIES[2], QUALIFIER, ts[2], VALUES[2]);
5835     put.add(FAMILIES[2], QUALIFIER, ts[3], VALUES[3]);
5836     ht.put(put);
5837 
5838     delete = new Delete(ROWS[0]);
5839     delete.deleteFamily(FAMILIES[2]);
5840     ht.delete(delete);
5841 
5842     delete = new Delete(ROWS[1]);
5843     delete.deleteColumns(FAMILIES[1], QUALIFIER);
5844     ht.delete(delete);
5845 
5846     delete = new Delete(ROWS[2]);
5847     delete.deleteColumn(FAMILIES[1], QUALIFIER);
5848     delete.deleteColumn(FAMILIES[1], QUALIFIER);
5849     delete.deleteColumn(FAMILIES[2], QUALIFIER);
5850     ht.delete(delete);
5851 
5852     scan = new Scan(ROWS[0]);
5853     scan.setReversed(true);
5854     scan.addFamily(FAMILIES[1]);
5855     scan.addFamily(FAMILIES[2]);
5856     scan.setMaxVersions(Integer.MAX_VALUE);
5857     result = getSingleScanResult(ht, scan);
5858     assertTrue("Expected 2 keys but received " + result.size(),
5859         result.size() == 2);
5860     assertNResult(result, ROWS[0], FAMILIES[1], QUALIFIER, new long[] { ts[0],
5861         ts[1] }, new byte[][] { VALUES[0], VALUES[1] }, 0, 1);
5862 
5863     scan = new Scan(ROWS[1]);
5864     scan.setReversed(true);
5865     scan.addFamily(FAMILIES[1]);
5866     scan.addFamily(FAMILIES[2]);
5867     scan.setMaxVersions(Integer.MAX_VALUE);
5868     result = getSingleScanResult(ht, scan);
5869     assertTrue("Expected 2 keys but received " + result.size(),
5870         result.size() == 2);
5871 
5872     scan = new Scan(ROWS[2]);
5873     scan.setReversed(true);
5874     scan.addFamily(FAMILIES[1]);
5875     scan.addFamily(FAMILIES[2]);
5876     scan.setMaxVersions(Integer.MAX_VALUE);
5877     result = getSingleScanResult(ht, scan);
5878     assertEquals(1, result.size());
5879     assertNResult(result, ROWS[2], FAMILIES[2], QUALIFIER,
5880         new long[] { ts[2] }, new byte[][] { VALUES[2] }, 0, 0);
5881 
5882     // Test if we delete the family first in one row (HBASE-1541)
5883 
5884     delete = new Delete(ROWS[3]);
5885     delete.deleteFamily(FAMILIES[1]);
5886     ht.delete(delete);
5887 
5888     put = new Put(ROWS[3]);
5889     put.add(FAMILIES[2], QUALIFIER, VALUES[0]);
5890     ht.put(put);
5891 
5892     put = new Put(ROWS[4]);
5893     put.add(FAMILIES[1], QUALIFIER, VALUES[1]);
5894     put.add(FAMILIES[2], QUALIFIER, VALUES[2]);
5895     ht.put(put);
5896 
5897     scan = new Scan(ROWS[4]);
5898     scan.setReversed(true);
5899     scan.addFamily(FAMILIES[1]);
5900     scan.addFamily(FAMILIES[2]);
5901     scan.setMaxVersions(Integer.MAX_VALUE);
5902     ResultScanner scanner = ht.getScanner(scan);
5903     result = scanner.next();
5904     assertTrue("Expected 2 keys but received " + result.size(),
5905         result.size() == 2);
5906     assertTrue(Bytes.equals(result.raw()[0].getRow(), ROWS[4]));
5907     assertTrue(Bytes.equals(result.raw()[1].getRow(), ROWS[4]));
5908     assertTrue(Bytes.equals(result.raw()[0].getValue(), VALUES[1]));
5909     assertTrue(Bytes.equals(result.raw()[1].getValue(), VALUES[2]));
5910     result = scanner.next();
5911     assertTrue("Expected 1 key but received " + result.size(),
5912         result.size() == 1);
5913     assertTrue(Bytes.equals(result.raw()[0].getRow(), ROWS[3]));
5914     assertTrue(Bytes.equals(result.raw()[0].getValue(), VALUES[0]));
5915     scanner.close();
5916     ht.close();
5917   }
5918 
5919   /**
5920    * Tests reversed scan under multi regions
5921    */
5922   @Test
5923   public void testReversedScanUnderMultiRegions() throws Exception {
5924     // Test Initialization.
5925     TableName TABLE = TableName.valueOf("testReversedScanUnderMultiRegions");
5926     byte[] maxByteArray = ReversedClientScanner.MAX_BYTE_ARRAY;
5927     byte[][] splitRows = new byte[][] { Bytes.toBytes("005"),
5928         Bytes.add(Bytes.toBytes("005"), Bytes.multiple(maxByteArray, 16)),
5929         Bytes.toBytes("006"),
5930         Bytes.add(Bytes.toBytes("006"), Bytes.multiple(maxByteArray, 8)),
5931         Bytes.toBytes("007"),
5932         Bytes.add(Bytes.toBytes("007"), Bytes.multiple(maxByteArray, 4)),
5933         Bytes.toBytes("008"), Bytes.multiple(maxByteArray, 2) };
5934     HTable table = TEST_UTIL.createTable(TABLE, FAMILY, splitRows);
5935     TEST_UTIL.waitUntilAllRegionsAssigned(table.getName());
5936 
5937     assertEquals(splitRows.length + 1, table.getRegionLocations().size());
5938     // Insert one row each region
5939     int insertNum = splitRows.length;
5940     for (int i = 0; i < insertNum; i++) {
5941       Put put = new Put(splitRows[i]);
5942       put.add(FAMILY, QUALIFIER, VALUE);
5943       table.put(put);
5944     }
5945 
5946     // scan forward
5947     ResultScanner scanner = table.getScanner(new Scan());
5948     int count = 0;
5949     for (Result r : scanner) {
5950       assertTrue(!r.isEmpty());
5951       count++;
5952     }
5953     assertEquals(insertNum, count);
5954 
5955     // scan backward
5956     Scan scan = new Scan();
5957     scan.setReversed(true);
5958     scanner = table.getScanner(scan);
5959     count = 0;
5960     byte[] lastRow = null;
5961     for (Result r : scanner) {
5962       assertTrue(!r.isEmpty());
5963       count++;
5964       byte[] thisRow = r.getRow();
5965       if (lastRow != null) {
5966         assertTrue("Error scan order, last row= " + Bytes.toString(lastRow)
5967             + ",this row=" + Bytes.toString(thisRow),
5968             Bytes.compareTo(thisRow, lastRow) < 0);
5969       }
5970       lastRow = thisRow;
5971     }
5972     assertEquals(insertNum, count);
5973     table.close();
5974   }
5975 
5976   /**
5977    * Tests reversed scan under multi regions
5978    */
5979   @Test
5980   public void testSmallReversedScanUnderMultiRegions() throws Exception {
5981     // Test Initialization.
5982     TableName TABLE = TableName.valueOf("testSmallReversedScanUnderMultiRegions");
5983     byte[][] splitRows = new byte[][]{
5984         Bytes.toBytes("000"), Bytes.toBytes("002"), Bytes.toBytes("004"),
5985         Bytes.toBytes("006"), Bytes.toBytes("008"), Bytes.toBytes("010")};
5986     HTable table = TEST_UTIL.createTable(TABLE, FAMILY, splitRows);
5987     TEST_UTIL.waitUntilAllRegionsAssigned(table.getName());
5988 
5989     assertEquals(splitRows.length + 1, table.getRegionLocations().size());
5990     for (byte[] splitRow : splitRows) {
5991       Put put = new Put(splitRow);
5992       put.add(FAMILY, QUALIFIER, VALUE);
5993       table.put(put);
5994 
5995       byte[] nextRow = Bytes.copy(splitRow);
5996       nextRow[nextRow.length - 1]++;
5997 
5998       put = new Put(nextRow);
5999       put.add(FAMILY, QUALIFIER, VALUE);
6000       table.put(put);
6001     }
6002 
6003     // scan forward
6004     ResultScanner scanner = table.getScanner(new Scan());
6005     int count = 0;
6006     for (Result r : scanner) {
6007       assertTrue(!r.isEmpty());
6008       count++;
6009     }
6010     assertEquals(12, count);
6011 
6012     reverseScanTest(table, false);
6013     reverseScanTest(table, true);
6014 
6015     table.close();
6016   }
6017 
6018   private void reverseScanTest(Table table, boolean small) throws IOException {
6019     // scan backward
6020     Scan scan = new Scan();
6021     scan.setReversed(true);
6022     ResultScanner scanner = table.getScanner(scan);
6023     int count = 0;
6024     byte[] lastRow = null;
6025     for (Result r : scanner) {
6026       assertTrue(!r.isEmpty());
6027       count++;
6028       byte[] thisRow = r.getRow();
6029       if (lastRow != null) {
6030         assertTrue("Error scan order, last row= " + Bytes.toString(lastRow)
6031             + ",this row=" + Bytes.toString(thisRow),
6032             Bytes.compareTo(thisRow, lastRow) < 0);
6033       }
6034       lastRow = thisRow;
6035     }
6036     assertEquals(12, count);
6037 
6038     scan = new Scan();
6039     scan.setSmall(small);
6040     scan.setReversed(true);
6041     scan.setStartRow(Bytes.toBytes("002"));
6042     scanner = table.getScanner(scan);
6043     count = 0;
6044     lastRow = null;
6045     for (Result r : scanner) {
6046       assertTrue(!r.isEmpty());
6047       count++;
6048       byte[] thisRow = r.getRow();
6049       if (lastRow != null) {
6050         assertTrue("Error scan order, last row= " + Bytes.toString(lastRow)
6051             + ",this row=" + Bytes.toString(thisRow),
6052             Bytes.compareTo(thisRow, lastRow) < 0);
6053       }
6054       lastRow = thisRow;
6055     }
6056     assertEquals(3, count); // 000 001 002
6057 
6058     scan = new Scan();
6059     scan.setSmall(small);
6060     scan.setReversed(true);
6061     scan.setStartRow(Bytes.toBytes("002"));
6062     scan.setStopRow(Bytes.toBytes("000"));
6063     scanner = table.getScanner(scan);
6064     count = 0;
6065     lastRow = null;
6066     for (Result r : scanner) {
6067       assertTrue(!r.isEmpty());
6068       count++;
6069       byte[] thisRow = r.getRow();
6070       if (lastRow != null) {
6071         assertTrue("Error scan order, last row= " + Bytes.toString(lastRow)
6072             + ",this row=" + Bytes.toString(thisRow),
6073             Bytes.compareTo(thisRow, lastRow) < 0);
6074       }
6075       lastRow = thisRow;
6076     }
6077     assertEquals(2, count); // 001 002
6078 
6079     scan = new Scan();
6080     scan.setSmall(small);
6081     scan.setReversed(true);
6082     scan.setStartRow(Bytes.toBytes("001"));
6083     scanner = table.getScanner(scan);
6084     count = 0;
6085     lastRow = null;
6086     for (Result r : scanner) {
6087       assertTrue(!r.isEmpty());
6088       count++;
6089       byte[] thisRow = r.getRow();
6090       if (lastRow != null) {
6091         assertTrue("Error scan order, last row= " + Bytes.toString(lastRow)
6092             + ",this row=" + Bytes.toString(thisRow),
6093             Bytes.compareTo(thisRow, lastRow) < 0);
6094       }
6095       lastRow = thisRow;
6096     }
6097     assertEquals(2, count); // 000 001
6098 
6099     scan = new Scan();
6100     scan.setSmall(small);
6101     scan.setReversed(true);
6102     scan.setStartRow(Bytes.toBytes("000"));
6103     scanner = table.getScanner(scan);
6104     count = 0;
6105     lastRow = null;
6106     for (Result r : scanner) {
6107       assertTrue(!r.isEmpty());
6108       count++;
6109       byte[] thisRow = r.getRow();
6110       if (lastRow != null) {
6111         assertTrue("Error scan order, last row= " + Bytes.toString(lastRow)
6112             + ",this row=" + Bytes.toString(thisRow),
6113             Bytes.compareTo(thisRow, lastRow) < 0);
6114       }
6115       lastRow = thisRow;
6116     }
6117     assertEquals(1, count); // 000
6118 
6119     scan = new Scan();
6120     scan.setSmall(small);
6121     scan.setReversed(true);
6122     scan.setStartRow(Bytes.toBytes("006"));
6123     scan.setStopRow(Bytes.toBytes("002"));
6124     scanner = table.getScanner(scan);
6125     count = 0;
6126     lastRow = null;
6127     for (Result r : scanner) {
6128       assertTrue(!r.isEmpty());
6129       count++;
6130       byte[] thisRow = r.getRow();
6131       if (lastRow != null) {
6132         assertTrue("Error scan order, last row= " + Bytes.toString(lastRow)
6133             + ",this row=" + Bytes.toString(thisRow),
6134             Bytes.compareTo(thisRow, lastRow) < 0);
6135       }
6136       lastRow = thisRow;
6137     }
6138     assertEquals(4, count); // 003 004 005 006
6139   }
6140 
6141   @Test
6142   public void testGetStartEndKeysWithRegionReplicas() throws IOException {
6143     HTableDescriptor htd = new HTableDescriptor(TableName.valueOf("testGetStartEndKeys"));
6144     HColumnDescriptor fam = new HColumnDescriptor(FAMILY);
6145     htd.addFamily(fam);
6146     byte[][] KEYS = HBaseTestingUtility.KEYS_FOR_HBA_CREATE_TABLE;
6147     HBaseAdmin admin = TEST_UTIL.getHBaseAdmin();
6148     admin.createTable(htd, KEYS);
6149     List<HRegionInfo> regions = admin.getTableRegions(htd.getTableName());
6150 
6151     HRegionLocator locator =
6152         (HRegionLocator) admin.getConnection().getRegionLocator(htd.getTableName());
6153     for (int regionReplication = 1; regionReplication < 4; regionReplication++) {
6154       List<RegionLocations> regionLocations = new ArrayList<RegionLocations>();
6155 
6156       // mock region locations coming from meta with multiple replicas
6157       for (HRegionInfo region : regions) {
6158         HRegionLocation[] arr = new HRegionLocation[regionReplication];
6159         for (int i = 0; i < arr.length; i++) {
6160           arr[i] = new HRegionLocation(RegionReplicaUtil.getRegionInfoForReplica(region, i), null);
6161         }
6162         regionLocations.add(new RegionLocations(arr));
6163       }
6164 
6165       Pair<byte[][], byte[][]> startEndKeys = locator.getStartEndKeys(regionLocations);
6166 
6167       assertEquals(KEYS.length + 1, startEndKeys.getFirst().length);
6168 
6169       for (int i = 0; i < KEYS.length + 1; i++) {
6170         byte[] startKey = i == 0 ? HConstants.EMPTY_START_ROW : KEYS[i - 1];
6171         byte[] endKey = i == KEYS.length ? HConstants.EMPTY_END_ROW : KEYS[i];
6172         assertArrayEquals(startKey, startEndKeys.getFirst()[i]);
6173         assertArrayEquals(endKey, startEndKeys.getSecond()[i]);
6174       }
6175     }
6176   }
6177 
6178   @Test
6179   public void testFilterAllRecords() throws IOException {
6180     Scan scan = new Scan();
6181     scan.setBatch(1);
6182     scan.setCaching(1);
6183     // Filter out any records
6184     scan.setFilter(new FilterList(new FirstKeyOnlyFilter(), new InclusiveStopFilter(new byte[0])));
6185     Table table = TEST_UTIL.getConnection().getTable(TableName.NAMESPACE_TABLE_NAME);
6186     ResultScanner s = table.getScanner(scan);
6187     assertNull(s.next());
6188     table.close();
6189   }
6190 }