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     util.waitUntilAllRegionsAssigned(tableName);
246 
247     verifyMethodResult(SimpleRegionObserver.class,
248         new String[] {"hadPreGet", "hadPostGet", "wasScannerNextCalled",
249             "wasScannerCloseCalled"},
250         tableName,
251         new Boolean[] {false, false, false, false}
252     );
253 
254     HTable table = new HTable(util.getConfiguration(), tableName);
255     Put put = new Put(ROW);
256     put.add(A, A, A);
257     table.put(put);
258 
259     Get get = new Get(ROW);
260     get.addColumn(A, A);
261     table.get(get);
262 
263     // verify that scannerNext and scannerClose upcalls won't be invoked
264     // when we perform get().
265     verifyMethodResult(SimpleRegionObserver.class,
266         new String[] {"hadPreGet", "hadPostGet", "wasScannerNextCalled",
267             "wasScannerCloseCalled"},
268         tableName,
269         new Boolean[] {true, true, false, false}
270     );
271 
272     Scan s = new Scan();
273     ResultScanner scanner = table.getScanner(s);
274     try {
275       for (Result rr = scanner.next(); rr != null; rr = scanner.next()) {
276       }
277     } finally {
278       scanner.close();
279     }
280 
281     // now scanner hooks should be invoked.
282     verifyMethodResult(SimpleRegionObserver.class,
283         new String[] {"wasScannerNextCalled", "wasScannerCloseCalled"},
284         tableName,
285         new Boolean[] {true, true}
286     );
287     util.deleteTable(tableName);
288     table.close();
289   }
290 
291   @Test
292   // HBase-3758
293   public void testHBase3758() throws IOException {
294     TableName tableName =
295         TableName.valueOf("testHBase3758");
296     util.createTable(tableName, new byte[][] {A, B, C});
297 
298     verifyMethodResult(SimpleRegionObserver.class,
299         new String[] {"hadDeleted", "wasScannerOpenCalled"},
300         tableName,
301         new Boolean[] {false, false}
302     );
303 
304     HTable table = new HTable(util.getConfiguration(), tableName);
305     Put put = new Put(ROW);
306     put.add(A, A, A);
307     table.put(put);
308 
309     Delete delete = new Delete(ROW);
310     table.delete(delete);
311 
312     verifyMethodResult(SimpleRegionObserver.class,
313         new String[] {"hadDeleted", "wasScannerOpenCalled"},
314         tableName,
315         new Boolean[] {true, false}
316     );
317 
318     Scan s = new Scan();
319     ResultScanner scanner = table.getScanner(s);
320     try {
321       for (Result rr = scanner.next(); rr != null; rr = scanner.next()) {
322       }
323     } finally {
324       scanner.close();
325     }
326 
327     // now scanner hooks should be invoked.
328     verifyMethodResult(SimpleRegionObserver.class,
329         new String[] {"wasScannerOpenCalled"},
330         tableName,
331         new Boolean[] {true}
332     );
333     util.deleteTable(tableName);
334     table.close();
335   }
336 
337   /* Overrides compaction to only output rows with keys that are even numbers */
338   public static class EvenOnlyCompactor extends BaseRegionObserver {
339     long lastCompaction;
340     long lastFlush;
341 
342     @Override
343     public InternalScanner preCompact(ObserverContext<RegionCoprocessorEnvironment> e,
344         Store store, final InternalScanner scanner, final ScanType scanType) {
345       return new InternalScanner() {
346         @Override
347         public boolean next(List<Cell> results) throws IOException {
348           return next(results, -1);
349         }
350 
351         @Override
352         public boolean next(List<Cell> results, int limit)
353             throws IOException{
354           List<Cell> internalResults = new ArrayList<Cell>();
355           boolean hasMore;
356           do {
357             hasMore = scanner.next(internalResults, limit);
358             if (!internalResults.isEmpty()) {
359               long row = Bytes.toLong(CellUtil.cloneValue(internalResults.get(0)));
360               if (row % 2 == 0) {
361                 // return this row
362                 break;
363               }
364               // clear and continue
365               internalResults.clear();
366             }
367           } while (hasMore);
368 
369           if (!internalResults.isEmpty()) {
370             results.addAll(internalResults);
371           }
372           return hasMore;
373         }
374 
375         @Override
376         public void close() throws IOException {
377           scanner.close();
378         }
379       };
380     }
381 
382     @Override
383     public void postCompact(ObserverContext<RegionCoprocessorEnvironment> e,
384         Store store, StoreFile resultFile) {
385       lastCompaction = EnvironmentEdgeManager.currentTimeMillis();
386     }
387 
388     @Override
389     public void postFlush(ObserverContext<RegionCoprocessorEnvironment> e) {
390       lastFlush = EnvironmentEdgeManager.currentTimeMillis();
391     }
392   }
393   /**
394    * Tests overriding compaction handling via coprocessor hooks
395    * @throws Exception
396    */
397   @Test
398   public void testCompactionOverride() throws Exception {
399     byte[] compactTable = Bytes.toBytes("TestCompactionOverride");
400     HBaseAdmin admin = util.getHBaseAdmin();
401     if (admin.tableExists(compactTable)) {
402       admin.disableTable(compactTable);
403       admin.deleteTable(compactTable);
404     }
405 
406     HTableDescriptor htd = new HTableDescriptor(TableName.valueOf(compactTable));
407     htd.addFamily(new HColumnDescriptor(A));
408     htd.addCoprocessor(EvenOnlyCompactor.class.getName());
409     admin.createTable(htd);
410 
411     HTable table = new HTable(util.getConfiguration(), compactTable);
412     for (long i=1; i<=10; i++) {
413       byte[] iBytes = Bytes.toBytes(i);
414       Put put = new Put(iBytes);
415       put.setDurability(Durability.SKIP_WAL);
416       put.add(A, A, iBytes);
417       table.put(put);
418     }
419 
420     HRegion firstRegion = cluster.getRegions(compactTable).get(0);
421     Coprocessor cp = firstRegion.getCoprocessorHost().findCoprocessor(
422         EvenOnlyCompactor.class.getName());
423     assertNotNull("EvenOnlyCompactor coprocessor should be loaded", cp);
424     EvenOnlyCompactor compactor = (EvenOnlyCompactor)cp;
425 
426     // force a compaction
427     long ts = System.currentTimeMillis();
428     admin.flush(compactTable);
429     // wait for flush
430     for (int i=0; i<10; i++) {
431       if (compactor.lastFlush >= ts) {
432         break;
433       }
434       Thread.sleep(1000);
435     }
436     assertTrue("Flush didn't complete", compactor.lastFlush >= ts);
437     LOG.debug("Flush complete");
438 
439     ts = compactor.lastFlush;
440     admin.majorCompact(compactTable);
441     // wait for compaction
442     for (int i=0; i<30; i++) {
443       if (compactor.lastCompaction >= ts) {
444         break;
445       }
446       Thread.sleep(1000);
447     }
448     LOG.debug("Last compaction was at "+compactor.lastCompaction);
449     assertTrue("Compaction didn't complete", compactor.lastCompaction >= ts);
450 
451     // only even rows should remain
452     ResultScanner scanner = table.getScanner(new Scan());
453     try {
454       for (long i=2; i<=10; i+=2) {
455         Result r = scanner.next();
456         assertNotNull(r);
457         assertFalse(r.isEmpty());
458         byte[] iBytes = Bytes.toBytes(i);
459         assertArrayEquals("Row should be "+i, r.getRow(), iBytes);
460         assertArrayEquals("Value should be "+i, r.getValue(A, A), iBytes);
461       }
462     } finally {
463       scanner.close();
464     }
465     table.close();
466   }
467 
468   @Test
469   public void bulkLoadHFileTest() throws Exception {
470     String testName = TestRegionObserverInterface.class.getName()+".bulkLoadHFileTest";
471     TableName tableName = TableName.valueOf(TEST_TABLE.getNameAsString() + ".bulkLoadHFileTest");
472     Configuration conf = util.getConfiguration();
473     HTable table = util.createTable(tableName, new byte[][] {A, B, C});
474     try {
475       verifyMethodResult(SimpleRegionObserver.class,
476           new String[] {"hadPreBulkLoadHFile", "hadPostBulkLoadHFile"},
477           tableName,
478           new Boolean[] {false, false}
479           );
480 
481       FileSystem fs = util.getTestFileSystem();
482       final Path dir = util.getDataTestDirOnTestFS(testName).makeQualified(fs);
483       Path familyDir = new Path(dir, Bytes.toString(A));
484 
485       createHFile(util.getConfiguration(), fs, new Path(familyDir,Bytes.toString(A)), A, A);
486 
487       //Bulk load
488       new LoadIncrementalHFiles(conf).doBulkLoad(dir, new HTable(conf, tableName));
489 
490       verifyMethodResult(SimpleRegionObserver.class,
491           new String[] {"hadPreBulkLoadHFile", "hadPostBulkLoadHFile"},
492           tableName,
493           new Boolean[] {true, true}
494           );
495     } finally {
496       util.deleteTable(tableName);
497       table.close();
498     }
499   }
500 
501   @Test
502   public void testRecovery() throws Exception {
503     LOG.info(TestRegionObserverInterface.class.getName() +".testRecovery");
504     TableName tableName = TableName.valueOf(TEST_TABLE.getNameAsString() + ".testRecovery");
505     HTable table = util.createTable(tableName, new byte[][] {A, B, C});
506     try {
507       JVMClusterUtil.RegionServerThread rs1 = cluster.startRegionServer();
508       ServerName sn2 = rs1.getRegionServer().getServerName();
509       String regEN = table.getRegionLocations().firstEntry().getKey().getEncodedName();
510 
511       util.getHBaseAdmin().move(regEN.getBytes(), sn2.getServerName().getBytes());
512       while (!sn2.equals(table.getRegionLocations().firstEntry().getValue() )){
513         Thread.sleep(100);
514       }
515 
516       Put put = new Put(ROW);
517       put.add(A, A, A);
518       put.add(B, B, B);
519       put.add(C, C, C);
520       table.put(put);
521 
522       verifyMethodResult(SimpleRegionObserver.class,
523           new String[] {"hadPreGet", "hadPostGet", "hadPrePut", "hadPostPut",
524         "hadPreBatchMutate", "hadPostBatchMutate", "hadDelete"},
525         tableName,
526         new Boolean[] {false, false, true, true, true, true, false}
527           );
528 
529       verifyMethodResult(SimpleRegionObserver.class,
530           new String[] {"getCtPreWALRestore", "getCtPostWALRestore", "getCtPrePut", "getCtPostPut"},
531           tableName,
532           new Integer[] {0, 0, 1, 1});
533 
534       cluster.killRegionServer(rs1.getRegionServer().getServerName());
535       Threads.sleep(1000); // Let the kill soak in.
536       util.waitUntilAllRegionsAssigned(tableName);
537       LOG.info("All regions assigned");
538 
539       verifyMethodResult(SimpleRegionObserver.class,
540           new String[]{"getCtPrePut", "getCtPostPut"},
541           tableName,
542           new Integer[]{0, 0});
543     } finally {
544       util.deleteTable(tableName);
545       table.close();
546     }
547   }
548 
549   @Test
550   public void testPreWALRestoreSkip() throws Exception {
551     LOG.info(TestRegionObserverInterface.class.getName() + ".testPreWALRestoreSkip");
552     TableName tableName = TableName.valueOf(SimpleRegionObserver.TABLE_SKIPPED);
553     HTable table = util.createTable(tableName, new byte[][] { A, B, C });
554 
555     JVMClusterUtil.RegionServerThread rs1 = cluster.startRegionServer();
556     ServerName sn2 = rs1.getRegionServer().getServerName();
557     String regEN = table.getRegionLocations().firstEntry().getKey().getEncodedName();
558 
559     util.getHBaseAdmin().move(regEN.getBytes(), sn2.getServerName().getBytes());
560     while (!sn2.equals(table.getRegionLocations().firstEntry().getValue())) {
561       Thread.sleep(100);
562     }
563 
564     Put put = new Put(ROW);
565     put.add(A, A, A);
566     put.add(B, B, B);
567     put.add(C, C, C);
568     table.put(put);
569     table.flushCommits();
570 
571     cluster.killRegionServer(rs1.getRegionServer().getServerName());
572     Threads.sleep(20000); // just to be sure that the kill has fully started.
573     util.waitUntilAllRegionsAssigned(tableName);
574 
575     verifyMethodResult(SimpleRegionObserver.class, new String[] { "getCtPreWALRestore",
576         "getCtPostWALRestore" }, tableName, new Integer[] { 0, 0 });
577 
578     util.deleteTable(tableName);
579     table.close();
580   }
581 
582   // check each region whether the coprocessor upcalls are called or not.
583   private void verifyMethodResult(Class<?> c, String methodName[], TableName tableName,
584                                   Object value[]) throws IOException {
585     try {
586       for (JVMClusterUtil.RegionServerThread t : cluster.getRegionServerThreads()) {
587         if (!t.isAlive() || t.getRegionServer().isAborted() || t.getRegionServer().isStopping()){
588           continue;
589         }
590         for (HRegionInfo r : ProtobufUtil.getOnlineRegions(t.getRegionServer())) {
591           if (!r.getTable().equals(tableName)) {
592             continue;
593           }
594           RegionCoprocessorHost cph = t.getRegionServer().getOnlineRegion(r.getRegionName()).
595               getCoprocessorHost();
596 
597           Coprocessor cp = cph.findCoprocessor(c.getName());
598           assertNotNull(cp);
599           for (int i = 0; i < methodName.length; ++i) {
600             Method m = c.getMethod(methodName[i]);
601             Object o = m.invoke(cp);
602             assertTrue("Result of " + c.getName() + "." + methodName[i]
603                 + " is expected to be " + value[i].toString()
604                 + ", while we get " + o.toString(), o.equals(value[i]));
605           }
606         }
607       }
608     } catch (Exception e) {
609       throw new IOException(e.toString());
610     }
611   }
612 
613   private static void createHFile(
614       Configuration conf,
615       FileSystem fs, Path path,
616       byte[] family, byte[] qualifier) throws IOException {
617     HFileContext context = new HFileContextBuilder().build();
618     HFile.Writer writer = HFile.getWriterFactory(conf, new CacheConfig(conf))
619         .withPath(fs, path)
620         .withFileContext(context)
621         .create();
622     long now = System.currentTimeMillis();
623     try {
624       for (int i =1;i<=9;i++) {
625         KeyValue kv = new KeyValue(Bytes.toBytes(i+""), family, qualifier, now, Bytes.toBytes(i+""));
626         writer.append(kv);
627       }
628     } finally {
629       writer.close();
630     }
631   }
632 
633 }