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