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