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  
20  package org.apache.hadoop.hbase.coprocessor;
21  
22  import static org.junit.Assert.assertArrayEquals;
23  import static org.junit.Assert.assertFalse;
24  import static org.junit.Assert.assertNotNull;
25  import static org.junit.Assert.assertTrue;
26  
27  import java.io.IOException;
28  import java.lang.reflect.Method;
29  import java.util.ArrayList;
30  import java.util.List;
31  
32  import org.apache.commons.logging.Log;
33  import org.apache.commons.logging.LogFactory;
34  import org.apache.hadoop.conf.Configuration;
35  import org.apache.hadoop.fs.FileSystem;
36  import org.apache.hadoop.fs.Path;
37  import org.apache.hadoop.hbase.Cell;
38  import org.apache.hadoop.hbase.CellUtil;
39  import org.apache.hadoop.hbase.Coprocessor;
40  import org.apache.hadoop.hbase.HBaseTestingUtility;
41  import org.apache.hadoop.hbase.HColumnDescriptor;
42  import org.apache.hadoop.hbase.HRegionInfo;
43  import org.apache.hadoop.hbase.HTableDescriptor;
44  import org.apache.hadoop.hbase.KeyValue;
45  import org.apache.hadoop.hbase.MediumTests;
46  import org.apache.hadoop.hbase.MiniHBaseCluster;
47  import org.apache.hadoop.hbase.ServerName;
48  import org.apache.hadoop.hbase.TableName;
49  import org.apache.hadoop.hbase.client.Delete;
50  import org.apache.hadoop.hbase.client.Durability;
51  import org.apache.hadoop.hbase.client.Get;
52  import org.apache.hadoop.hbase.client.HBaseAdmin;
53  import org.apache.hadoop.hbase.client.HTable;
54  import org.apache.hadoop.hbase.client.Increment;
55  import org.apache.hadoop.hbase.client.Put;
56  import org.apache.hadoop.hbase.client.Result;
57  import org.apache.hadoop.hbase.client.ResultScanner;
58  import org.apache.hadoop.hbase.client.RowMutations;
59  import org.apache.hadoop.hbase.client.Scan;
60  import org.apache.hadoop.hbase.io.hfile.CacheConfig;
61  import org.apache.hadoop.hbase.io.hfile.HFile;
62  import org.apache.hadoop.hbase.io.hfile.HFileContext;
63  import org.apache.hadoop.hbase.io.hfile.HFileContextBuilder;
64  import org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles;
65  import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
66  import org.apache.hadoop.hbase.regionserver.HRegion;
67  import org.apache.hadoop.hbase.regionserver.InternalScanner;
68  import org.apache.hadoop.hbase.regionserver.RegionCoprocessorHost;
69  import org.apache.hadoop.hbase.regionserver.ScanType;
70  import org.apache.hadoop.hbase.regionserver.Store;
71  import org.apache.hadoop.hbase.regionserver.StoreFile;
72  import org.apache.hadoop.hbase.util.Bytes;
73  import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
74  import org.apache.hadoop.hbase.util.JVMClusterUtil;
75  import org.apache.hadoop.hbase.util.Threads;
76  import org.junit.AfterClass;
77  import org.junit.BeforeClass;
78  import org.junit.Test;
79  import org.junit.experimental.categories.Category;
80  
81  @Category(MediumTests.class)
82  public class TestRegionObserverInterface {
83    static final Log LOG = LogFactory.getLog(TestRegionObserverInterface.class);
84  
85    public static final TableName TEST_TABLE = TableName.valueOf("TestTable");
86    public final static byte[] A = Bytes.toBytes("a");
87    public final static byte[] B = Bytes.toBytes("b");
88    public final static byte[] C = Bytes.toBytes("c");
89    public final static byte[] ROW = Bytes.toBytes("testrow");
90  
91    private static HBaseTestingUtility util = new HBaseTestingUtility();
92    private static MiniHBaseCluster cluster = null;
93  
94    @BeforeClass
95    public static void setupBeforeClass() throws Exception {
96      // set configure to indicate which cp should be loaded
97      Configuration conf = util.getConfiguration();
98      conf.setBoolean("hbase.master.distributed.log.replay", true);
99      conf.set(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY,
100         "org.apache.hadoop.hbase.coprocessor.SimpleRegionObserver");
101 
102     util.startMiniCluster();
103     cluster = util.getMiniHBaseCluster();
104   }
105 
106   @AfterClass
107   public static void tearDownAfterClass() throws Exception {
108     util.shutdownMiniCluster();
109   }
110 
111   @Test
112   public void testRegionObserver() throws IOException {
113     TableName tableName = TableName.valueOf(TEST_TABLE.getNameAsString() + ".testRegionObserver");
114     // recreate table every time in order to reset the status of the
115     // coprocessor.
116     HTable table = util.createTable(tableName, new byte[][] {A, B, C});
117     try {
118       verifyMethodResult(SimpleRegionObserver.class, new String[] { "hadPreGet", "hadPostGet",
119           "hadPrePut", "hadPostPut", "hadDelete", "hadPostStartRegionOperation",
120           "hadPostCloseRegionOperation", "hadPostBatchMutateIndispensably" }, tableName,
121         new Boolean[] { false, false, false, false, false, false, false, false });
122 
123       Put put = new Put(ROW);
124       put.add(A, A, A);
125       put.add(B, B, B);
126       put.add(C, C, C);
127       table.put(put);
128 
129       verifyMethodResult(SimpleRegionObserver.class, new String[] { "hadPreGet", "hadPostGet",
130           "hadPrePut", "hadPostPut", "hadPreBatchMutate", "hadPostBatchMutate", "hadDelete",
131           "hadPostStartRegionOperation", "hadPostCloseRegionOperation",
132           "hadPostBatchMutateIndispensably" }, TEST_TABLE, new Boolean[] { false, false, true,
133           true, true, true, false, true, true, true });
134 
135       verifyMethodResult(SimpleRegionObserver.class,
136           new String[] {"getCtPreOpen", "getCtPostOpen", "getCtPreClose", "getCtPostClose"},
137           tableName,
138           new Integer[] {1, 1, 0, 0});
139 
140       Get get = new Get(ROW);
141       get.addColumn(A, A);
142       get.addColumn(B, B);
143       get.addColumn(C, C);
144       table.get(get);
145 
146       verifyMethodResult(SimpleRegionObserver.class,
147           new String[] {"hadPreGet", "hadPostGet", "hadPrePut", "hadPostPut",
148       "hadDelete"},
149       tableName,
150       new Boolean[] {true, true, true, true, false}
151           );
152 
153       Delete delete = new Delete(ROW);
154       delete.deleteColumn(A, A);
155       delete.deleteColumn(B, B);
156       delete.deleteColumn(C, C);
157       table.delete(delete);
158 
159       verifyMethodResult(SimpleRegionObserver.class,
160           new String[] {"hadPreGet", "hadPostGet", "hadPrePut", "hadPostPut",
161         "hadPreBatchMutate", "hadPostBatchMutate", "hadDelete"},
162         tableName,
163         new Boolean[] {true, true, true, true, true, true, true}
164           );
165     } finally {
166       util.deleteTable(tableName);
167       table.close();
168     }
169     verifyMethodResult(SimpleRegionObserver.class,
170         new String[] {"getCtPreOpen", "getCtPostOpen", "getCtPreClose", "getCtPostClose"},
171         tableName,
172         new Integer[] {1, 1, 1, 1});
173   }
174 
175   @Test
176   public void testRowMutation() throws IOException {
177     TableName tableName = TableName.valueOf(TEST_TABLE.getNameAsString() + ".testRowMutation");
178     HTable table = util.createTable(tableName, new byte[][] {A, B, C});
179     try {
180       verifyMethodResult(SimpleRegionObserver.class,
181         new String[] {"hadPreGet", "hadPostGet", "hadPrePut", "hadPostPut",
182             "hadDeleted"},
183         tableName,
184         new Boolean[] {false, false, false, false, false});
185       Put put = new Put(ROW);
186       put.add(A, A, A);
187       put.add(B, B, B);
188       put.add(C, C, C);
189 
190       Delete delete = new Delete(ROW);
191       delete.deleteColumn(A, A);
192       delete.deleteColumn(B, B);
193       delete.deleteColumn(C, C);
194 
195       RowMutations arm = new RowMutations(ROW);
196       arm.add(put);
197       arm.add(delete);
198       table.mutateRow(arm);
199 
200       verifyMethodResult(SimpleRegionObserver.class,
201           new String[] {"hadPreGet", "hadPostGet", "hadPrePut", "hadPostPut",
202       "hadDeleted"},
203       tableName,
204       new Boolean[] {false, false, true, true, true}
205           );
206     } finally {
207       util.deleteTable(tableName);
208       table.close();
209     }
210   }
211 
212   @Test
213   public void testIncrementHook() throws IOException {
214     TableName tableName = TableName.valueOf(TEST_TABLE.getNameAsString() + ".testIncrementHook");
215     HTable table = util.createTable(tableName, new byte[][] {A, B, C});
216     try {
217       Increment inc = new Increment(Bytes.toBytes(0));
218       inc.addColumn(A, A, 1);
219 
220       verifyMethodResult(SimpleRegionObserver.class,
221           new String[] {"hadPreIncrement", "hadPostIncrement"},
222           tableName,
223           new Boolean[] {false, false}
224           );
225 
226       table.increment(inc);
227 
228       verifyMethodResult(SimpleRegionObserver.class,
229           new String[] {"hadPreIncrement", "hadPostIncrement"},
230           tableName,
231           new Boolean[] {true, true}
232           );
233     } finally {
234       util.deleteTable(tableName);
235       table.close();
236     }
237   }
238 
239   @Test
240   // HBase-3583
241   public void testHBase3583() throws IOException {
242     TableName tableName =
243         TableName.valueOf("testHBase3583");
244     util.createTable(tableName, new byte[][] {A, B, C});
245 
246     verifyMethodResult(SimpleRegionObserver.class,
247         new String[] {"hadPreGet", "hadPostGet", "wasScannerNextCalled",
248             "wasScannerCloseCalled"},
249         tableName,
250         new Boolean[] {false, false, false, false}
251     );
252 
253     HTable table = new HTable(util.getConfiguration(), tableName);
254     Put put = new Put(ROW);
255     put.add(A, A, A);
256     table.put(put);
257 
258     Get get = new Get(ROW);
259     get.addColumn(A, A);
260     table.get(get);
261 
262     // verify that scannerNext and scannerClose upcalls won't be invoked
263     // when we perform get().
264     verifyMethodResult(SimpleRegionObserver.class,
265         new String[] {"hadPreGet", "hadPostGet", "wasScannerNextCalled",
266             "wasScannerCloseCalled"},
267         tableName,
268         new Boolean[] {true, true, false, false}
269     );
270 
271     Scan s = new Scan();
272     ResultScanner scanner = table.getScanner(s);
273     try {
274       for (Result rr = scanner.next(); rr != null; rr = scanner.next()) {
275       }
276     } finally {
277       scanner.close();
278     }
279 
280     // now scanner hooks should be invoked.
281     verifyMethodResult(SimpleRegionObserver.class,
282         new String[] {"wasScannerNextCalled", "wasScannerCloseCalled"},
283         tableName,
284         new Boolean[] {true, true}
285     );
286     util.deleteTable(tableName);
287     table.close();
288   }
289 
290   @Test
291   // HBase-3758
292   public void testHBase3758() throws IOException {
293     TableName tableName =
294         TableName.valueOf("testHBase3758");
295     util.createTable(tableName, new byte[][] {A, B, C});
296 
297     verifyMethodResult(SimpleRegionObserver.class,
298         new String[] {"hadDeleted", "wasScannerOpenCalled"},
299         tableName,
300         new Boolean[] {false, false}
301     );
302 
303     HTable table = new HTable(util.getConfiguration(), tableName);
304     Put put = new Put(ROW);
305     put.add(A, A, A);
306     table.put(put);
307 
308     Delete delete = new Delete(ROW);
309     table.delete(delete);
310 
311     verifyMethodResult(SimpleRegionObserver.class,
312         new String[] {"hadDeleted", "wasScannerOpenCalled"},
313         tableName,
314         new Boolean[] {true, false}
315     );
316 
317     Scan s = new Scan();
318     ResultScanner scanner = table.getScanner(s);
319     try {
320       for (Result rr = scanner.next(); rr != null; rr = scanner.next()) {
321       }
322     } finally {
323       scanner.close();
324     }
325 
326     // now scanner hooks should be invoked.
327     verifyMethodResult(SimpleRegionObserver.class,
328         new String[] {"wasScannerOpenCalled"},
329         tableName,
330         new Boolean[] {true}
331     );
332     util.deleteTable(tableName);
333     table.close();
334   }
335 
336   /* Overrides compaction to only output rows with keys that are even numbers */
337   public static class EvenOnlyCompactor extends BaseRegionObserver {
338     long lastCompaction;
339     long lastFlush;
340 
341     @Override
342     public InternalScanner preCompact(ObserverContext<RegionCoprocessorEnvironment> e,
343         Store store, final InternalScanner scanner, final ScanType scanType) {
344       return new InternalScanner() {
345         @Override
346         public boolean next(List<Cell> results) throws IOException {
347           return next(results, -1);
348         }
349 
350         @Override
351         public boolean next(List<Cell> results, int limit)
352             throws IOException{
353           List<Cell> internalResults = new ArrayList<Cell>();
354           boolean hasMore;
355           do {
356             hasMore = scanner.next(internalResults, limit);
357             if (!internalResults.isEmpty()) {
358               long row = Bytes.toLong(CellUtil.cloneValue(internalResults.get(0)));
359               if (row % 2 == 0) {
360                 // return this row
361                 break;
362               }
363               // clear and continue
364               internalResults.clear();
365             }
366           } while (hasMore);
367 
368           if (!internalResults.isEmpty()) {
369             results.addAll(internalResults);
370           }
371           return hasMore;
372         }
373 
374         @Override
375         public void close() throws IOException {
376           scanner.close();
377         }
378       };
379     }
380 
381     @Override
382     public void postCompact(ObserverContext<RegionCoprocessorEnvironment> e,
383         Store store, StoreFile resultFile) {
384       lastCompaction = EnvironmentEdgeManager.currentTimeMillis();
385     }
386 
387     @Override
388     public void postFlush(ObserverContext<RegionCoprocessorEnvironment> e) {
389       lastFlush = EnvironmentEdgeManager.currentTimeMillis();
390     }
391   }
392   /**
393    * Tests overriding compaction handling via coprocessor hooks
394    * @throws Exception
395    */
396   @Test
397   public void testCompactionOverride() throws Exception {
398     byte[] compactTable = Bytes.toBytes("TestCompactionOverride");
399     HBaseAdmin admin = util.getHBaseAdmin();
400     if (admin.tableExists(compactTable)) {
401       admin.disableTable(compactTable);
402       admin.deleteTable(compactTable);
403     }
404 
405     HTableDescriptor htd = new HTableDescriptor(TableName.valueOf(compactTable));
406     htd.addFamily(new HColumnDescriptor(A));
407     htd.addCoprocessor(EvenOnlyCompactor.class.getName());
408     admin.createTable(htd);
409 
410     HTable table = new HTable(util.getConfiguration(), compactTable);
411     for (long i=1; i<=10; i++) {
412       byte[] iBytes = Bytes.toBytes(i);
413       Put put = new Put(iBytes);
414       put.setDurability(Durability.SKIP_WAL);
415       put.add(A, A, iBytes);
416       table.put(put);
417     }
418 
419     HRegion firstRegion = cluster.getRegions(compactTable).get(0);
420     Coprocessor cp = firstRegion.getCoprocessorHost().findCoprocessor(
421         EvenOnlyCompactor.class.getName());
422     assertNotNull("EvenOnlyCompactor coprocessor should be loaded", cp);
423     EvenOnlyCompactor compactor = (EvenOnlyCompactor)cp;
424 
425     // force a compaction
426     long ts = System.currentTimeMillis();
427     admin.flush(compactTable);
428     // wait for flush
429     for (int i=0; i<10; i++) {
430       if (compactor.lastFlush >= ts) {
431         break;
432       }
433       Thread.sleep(1000);
434     }
435     assertTrue("Flush didn't complete", compactor.lastFlush >= ts);
436     LOG.debug("Flush complete");
437 
438     ts = compactor.lastFlush;
439     admin.majorCompact(compactTable);
440     // wait for compaction
441     for (int i=0; i<30; i++) {
442       if (compactor.lastCompaction >= ts) {
443         break;
444       }
445       Thread.sleep(1000);
446     }
447     LOG.debug("Last compaction was at "+compactor.lastCompaction);
448     assertTrue("Compaction didn't complete", compactor.lastCompaction >= ts);
449 
450     // only even rows should remain
451     ResultScanner scanner = table.getScanner(new Scan());
452     try {
453       for (long i=2; i<=10; i+=2) {
454         Result r = scanner.next();
455         assertNotNull(r);
456         assertFalse(r.isEmpty());
457         byte[] iBytes = Bytes.toBytes(i);
458         assertArrayEquals("Row should be "+i, r.getRow(), iBytes);
459         assertArrayEquals("Value should be "+i, r.getValue(A, A), iBytes);
460       }
461     } finally {
462       scanner.close();
463     }
464     table.close();
465   }
466 
467   @Test
468   public void bulkLoadHFileTest() throws Exception {
469     String testName = TestRegionObserverInterface.class.getName()+".bulkLoadHFileTest";
470     TableName tableName = TableName.valueOf(TEST_TABLE.getNameAsString() + ".bulkLoadHFileTest");
471     Configuration conf = util.getConfiguration();
472     HTable table = util.createTable(tableName, new byte[][] {A, B, C});
473     try {
474       verifyMethodResult(SimpleRegionObserver.class,
475           new String[] {"hadPreBulkLoadHFile", "hadPostBulkLoadHFile"},
476           tableName,
477           new Boolean[] {false, false}
478           );
479 
480       FileSystem fs = util.getTestFileSystem();
481       final Path dir = util.getDataTestDirOnTestFS(testName).makeQualified(fs);
482       Path familyDir = new Path(dir, Bytes.toString(A));
483 
484       createHFile(util.getConfiguration(), fs, new Path(familyDir,Bytes.toString(A)), A, A);
485 
486       //Bulk load
487       new LoadIncrementalHFiles(conf).doBulkLoad(dir, new HTable(conf, tableName));
488 
489       verifyMethodResult(SimpleRegionObserver.class,
490           new String[] {"hadPreBulkLoadHFile", "hadPostBulkLoadHFile"},
491           tableName,
492           new Boolean[] {true, true}
493           );
494     } finally {
495       util.deleteTable(tableName);
496       table.close();
497     }
498   }
499 
500   @Test
501   public void testRecovery() throws Exception {
502     LOG.info(TestRegionObserverInterface.class.getName() +".testRecovery");
503     TableName tableName = TableName.valueOf(TEST_TABLE.getNameAsString() + ".testRecovery");
504     HTable table = util.createTable(tableName, new byte[][] {A, B, C});
505     try {
506       JVMClusterUtil.RegionServerThread rs1 = cluster.startRegionServer();
507       ServerName sn2 = rs1.getRegionServer().getServerName();
508       String regEN = table.getRegionLocations().firstEntry().getKey().getEncodedName();
509 
510       util.getHBaseAdmin().move(regEN.getBytes(), sn2.getServerName().getBytes());
511       while (!sn2.equals(table.getRegionLocations().firstEntry().getValue() )){
512         Thread.sleep(100);
513       }
514 
515       Put put = new Put(ROW);
516       put.add(A, A, A);
517       put.add(B, B, B);
518       put.add(C, C, C);
519       table.put(put);
520 
521       verifyMethodResult(SimpleRegionObserver.class,
522           new String[] {"hadPreGet", "hadPostGet", "hadPrePut", "hadPostPut",
523         "hadPreBatchMutate", "hadPostBatchMutate", "hadDelete"},
524         tableName,
525         new Boolean[] {false, false, true, true, true, true, false}
526           );
527 
528       verifyMethodResult(SimpleRegionObserver.class,
529           new String[] {"getCtPreWALRestore", "getCtPostWALRestore", "getCtPrePut", "getCtPostPut"},
530           tableName,
531           new Integer[] {0, 0, 1, 1});
532 
533       cluster.killRegionServer(rs1.getRegionServer().getServerName());
534       Threads.sleep(1000); // Let the kill soak in.
535       util.waitUntilAllRegionsAssigned(tableName);
536       LOG.info("All regions assigned");
537 
538       verifyMethodResult(SimpleRegionObserver.class,
539           new String[]{"getCtPrePut", "getCtPostPut"},
540           tableName,
541           new Integer[]{0, 0});
542     } finally {
543       util.deleteTable(tableName);
544       table.close();
545     }
546   }
547 
548   @Test
549   public void testPreWALRestoreSkip() throws Exception {
550     LOG.info(TestRegionObserverInterface.class.getName() + ".testPreWALRestoreSkip");
551     TableName tableName = TableName.valueOf(SimpleRegionObserver.TABLE_SKIPPED);
552     HTable table = util.createTable(tableName, new byte[][] { A, B, C });
553 
554     JVMClusterUtil.RegionServerThread rs1 = cluster.startRegionServer();
555     ServerName sn2 = rs1.getRegionServer().getServerName();
556     String regEN = table.getRegionLocations().firstEntry().getKey().getEncodedName();
557 
558     util.getHBaseAdmin().move(regEN.getBytes(), sn2.getServerName().getBytes());
559     while (!sn2.equals(table.getRegionLocations().firstEntry().getValue())) {
560       Thread.sleep(100);
561     }
562 
563     Put put = new Put(ROW);
564     put.add(A, A, A);
565     put.add(B, B, B);
566     put.add(C, C, C);
567     table.put(put);
568     table.flushCommits();
569 
570     cluster.killRegionServer(rs1.getRegionServer().getServerName());
571     Threads.sleep(20000); // just to be sure that the kill has fully started.
572     util.waitUntilAllRegionsAssigned(tableName);
573 
574     verifyMethodResult(SimpleRegionObserver.class, new String[] { "getCtPreWALRestore",
575         "getCtPostWALRestore" }, tableName, new Integer[] { 0, 0 });
576 
577     util.deleteTable(tableName);
578     table.close();
579   }
580 
581   // check each region whether the coprocessor upcalls are called or not.
582   private void verifyMethodResult(Class<?> c, String methodName[], TableName tableName,
583                                   Object value[]) throws IOException {
584     try {
585       for (JVMClusterUtil.RegionServerThread t : cluster.getRegionServerThreads()) {
586         if (!t.isAlive() || t.getRegionServer().isAborted() || t.getRegionServer().isStopping()){
587           continue;
588         }
589         for (HRegionInfo r : ProtobufUtil.getOnlineRegions(t.getRegionServer())) {
590           if (!r.getTable().equals(tableName)) {
591             continue;
592           }
593           RegionCoprocessorHost cph = t.getRegionServer().getOnlineRegion(r.getRegionName()).
594               getCoprocessorHost();
595 
596           Coprocessor cp = cph.findCoprocessor(c.getName());
597           assertNotNull(cp);
598           for (int i = 0; i < methodName.length; ++i) {
599             Method m = c.getMethod(methodName[i]);
600             Object o = m.invoke(cp);
601             assertTrue("Result of " + c.getName() + "." + methodName[i]
602                 + " is expected to be " + value[i].toString()
603                 + ", while we get " + o.toString(), o.equals(value[i]));
604           }
605         }
606       }
607     } catch (Exception e) {
608       throw new IOException(e.toString());
609     }
610   }
611 
612   private static void createHFile(
613       Configuration conf,
614       FileSystem fs, Path path,
615       byte[] family, byte[] qualifier) throws IOException {
616     HFileContext context = new HFileContextBuilder().build();
617     HFile.Writer writer = HFile.getWriterFactory(conf, new CacheConfig(conf))
618         .withPath(fs, path)
619         .withFileContext(context)
620         .create();
621     long now = System.currentTimeMillis();
622     try {
623       for (int i =1;i<=9;i++) {
624         KeyValue kv = new KeyValue(Bytes.toBytes(i+""), family, qualifier, now, Bytes.toBytes(i+""));
625         writer.append(kv);
626       }
627     } finally {
628       writer.close();
629     }
630   }
631 
632 }