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.assertEquals;
24  import static org.junit.Assert.assertNotNull;
25  import static org.junit.Assert.assertTrue;
26  
27  import java.io.IOException;
28  import java.util.List;
29  import java.util.Map;
30  import java.util.NavigableSet;
31  import java.util.concurrent.atomic.AtomicBoolean;
32  import java.util.concurrent.atomic.AtomicInteger;
33  
34  import org.apache.commons.logging.Log;
35  import org.apache.commons.logging.LogFactory;
36  import org.apache.hadoop.fs.FileSystem;
37  import org.apache.hadoop.fs.Path;
38  import org.apache.hadoop.hbase.Cell;
39  import org.apache.hadoop.hbase.CellUtil;
40  import org.apache.hadoop.hbase.CoprocessorEnvironment;
41  import org.apache.hadoop.hbase.HRegionInfo;
42  import org.apache.hadoop.hbase.KeyValue;
43  import org.apache.hadoop.hbase.client.Append;
44  import org.apache.hadoop.hbase.client.Delete;
45  import org.apache.hadoop.hbase.client.Durability;
46  import org.apache.hadoop.hbase.client.Get;
47  import org.apache.hadoop.hbase.client.Increment;
48  import org.apache.hadoop.hbase.client.Mutation;
49  import org.apache.hadoop.hbase.client.Put;
50  import org.apache.hadoop.hbase.client.Result;
51  import org.apache.hadoop.hbase.client.Scan;
52  import org.apache.hadoop.hbase.filter.ByteArrayComparable;
53  import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
54  import org.apache.hadoop.hbase.io.FSDataInputStreamWrapper;
55  import org.apache.hadoop.hbase.io.Reference;
56  import org.apache.hadoop.hbase.io.hfile.CacheConfig;
57  import org.apache.hadoop.hbase.regionserver.InternalScanner;
58  import org.apache.hadoop.hbase.regionserver.KeyValueScanner;
59  import org.apache.hadoop.hbase.regionserver.Leases;
60  import org.apache.hadoop.hbase.regionserver.MiniBatchOperationInProgress;
61  import org.apache.hadoop.hbase.regionserver.Region;
62  import org.apache.hadoop.hbase.regionserver.Region.Operation;
63  import org.apache.hadoop.hbase.regionserver.RegionScanner;
64  import org.apache.hadoop.hbase.regionserver.ScanType;
65  import org.apache.hadoop.hbase.regionserver.Store;
66  import org.apache.hadoop.hbase.regionserver.StoreFile;
67  import org.apache.hadoop.hbase.regionserver.StoreFile.Reader;
68  import org.apache.hadoop.hbase.regionserver.wal.HLogKey;
69  import org.apache.hadoop.hbase.wal.WALKey;
70  import org.apache.hadoop.hbase.regionserver.wal.WALEdit;
71  import org.apache.hadoop.hbase.util.Bytes;
72  import org.apache.hadoop.hbase.util.Pair;
73  
74  import com.google.common.collect.ImmutableList;
75  
76  /**
77   * A sample region observer that tests the RegionObserver interface.
78   * It works with TestRegionObserverInterface to provide the test case.
79   */
80  public class SimpleRegionObserver extends BaseRegionObserver {
81    private static final Log LOG = LogFactory.getLog(TestRegionObserverInterface.class);
82  
83    final AtomicInteger ctBeforeDelete = new AtomicInteger(1);
84    final AtomicInteger ctPreOpen = new AtomicInteger(0);
85    final AtomicInteger ctPostOpen = new AtomicInteger(0);
86    final AtomicInteger ctPreClose = new AtomicInteger(0);
87    final AtomicInteger ctPostClose = new AtomicInteger(0);
88    final AtomicInteger ctPreFlush = new AtomicInteger(0);
89    final AtomicInteger ctPreFlushScannerOpen = new AtomicInteger(0);
90    final AtomicInteger ctPostFlush = new AtomicInteger(0);
91    final AtomicInteger ctPreSplit = new AtomicInteger(0);
92    final AtomicInteger ctPostSplit = new AtomicInteger(0);
93    final AtomicInteger ctPreCompactSelect = new AtomicInteger(0);
94    final AtomicInteger ctPostCompactSelect = new AtomicInteger(0);
95    final AtomicInteger ctPreCompactScanner = new AtomicInteger(0);
96    final AtomicInteger ctPreCompact = new AtomicInteger(0);
97    final AtomicInteger ctPostCompact = new AtomicInteger(0);
98    final AtomicInteger ctPreGet = new AtomicInteger(0);
99    final AtomicInteger ctPostGet = new AtomicInteger(0);
100   final AtomicInteger ctPrePut = new AtomicInteger(0);
101   final AtomicInteger ctPostPut = new AtomicInteger(0);
102   final AtomicInteger ctPreDeleted = new AtomicInteger(0);
103   final AtomicInteger ctPrePrepareDeleteTS = new AtomicInteger(0);
104   final AtomicInteger ctPostDeleted = new AtomicInteger(0);
105   final AtomicInteger ctPreGetClosestRowBefore = new AtomicInteger(0);
106   final AtomicInteger ctPostGetClosestRowBefore = new AtomicInteger(0);
107   final AtomicInteger ctPreIncrement = new AtomicInteger(0);
108   final AtomicInteger ctPreIncrementAfterRowLock = new AtomicInteger(0);
109   final AtomicInteger ctPreAppend = new AtomicInteger(0);
110   final AtomicInteger ctPreAppendAfterRowLock = new AtomicInteger(0);
111   final AtomicInteger ctPostIncrement = new AtomicInteger(0);
112   final AtomicInteger ctPostAppend = new AtomicInteger(0);
113   final AtomicInteger ctPreCheckAndPut = new AtomicInteger(0);
114   final AtomicInteger ctPreCheckAndPutAfterRowLock = new AtomicInteger(0);
115   final AtomicInteger ctPostCheckAndPut = new AtomicInteger(0);
116   final AtomicInteger ctPreCheckAndDelete = new AtomicInteger(0);
117   final AtomicInteger ctPreCheckAndDeleteAfterRowLock = new AtomicInteger(0);
118   final AtomicInteger ctPostCheckAndDelete = new AtomicInteger(0);
119   final AtomicInteger ctPreScannerNext = new AtomicInteger(0);
120   final AtomicInteger ctPostScannerNext = new AtomicInteger(0);
121   final AtomicInteger ctPostScannerFilterRow = new AtomicInteger(0);
122   final AtomicInteger ctPreScannerClose = new AtomicInteger(0);
123   final AtomicInteger ctPostScannerClose = new AtomicInteger(0);
124   final AtomicInteger ctPreScannerOpen = new AtomicInteger(0);
125   final AtomicInteger ctPreStoreScannerOpen = new AtomicInteger(0);
126   final AtomicInteger ctPostScannerOpen = new AtomicInteger(0);
127   final AtomicInteger ctPreBulkLoadHFile = new AtomicInteger(0);
128   final AtomicInteger ctPostBulkLoadHFile = new AtomicInteger(0);
129   final AtomicInteger ctPreBatchMutate = new AtomicInteger(0);
130   final AtomicInteger ctPostBatchMutate = new AtomicInteger(0);
131   final AtomicInteger ctPreWALRestore = new AtomicInteger(0);
132   final AtomicInteger ctPostWALRestore = new AtomicInteger(0);
133   final AtomicInteger ctPreWALRestoreDeprecated = new AtomicInteger(0);
134   final AtomicInteger ctPostWALRestoreDeprecated = new AtomicInteger(0);
135   final AtomicInteger ctPreSplitBeforePONR = new AtomicInteger(0);
136   final AtomicInteger ctPreSplitAfterPONR = new AtomicInteger(0);
137   final AtomicInteger ctPreStoreFileReaderOpen = new AtomicInteger(0);
138   final AtomicInteger ctPostStoreFileReaderOpen = new AtomicInteger(0);
139   final AtomicInteger ctPostBatchMutateIndispensably = new AtomicInteger(0);
140   final AtomicInteger ctPostStartRegionOperation = new AtomicInteger(0);
141   final AtomicInteger ctPostCloseRegionOperation = new AtomicInteger(0);
142   final AtomicBoolean throwOnPostFlush = new AtomicBoolean(false);
143   static final String TABLE_SKIPPED = "SKIPPED_BY_PREWALRESTORE";
144 
145   public void setThrowOnPostFlush(Boolean val){
146     throwOnPostFlush.set(val);
147   }
148 
149   @Override
150   public void start(CoprocessorEnvironment e) throws IOException {
151     // this only makes sure that leases and locks are available to coprocessors
152     // from external packages
153     RegionCoprocessorEnvironment re = (RegionCoprocessorEnvironment)e;
154     Leases leases = re.getRegionServerServices().getLeases();
155     leases.createLease(re.getRegion().getRegionInfo().getRegionNameAsString(), 2000, null);
156     leases.cancelLease(re.getRegion().getRegionInfo().getRegionNameAsString());
157   }
158 
159   @Override
160   public void preOpen(ObserverContext<RegionCoprocessorEnvironment> c) {
161     ctPreOpen.incrementAndGet();
162   }
163 
164   @Override
165   public void postOpen(ObserverContext<RegionCoprocessorEnvironment> c) {
166     ctPostOpen.incrementAndGet();
167   }
168 
169   public boolean wasOpened() {
170     return ctPreOpen.get() > 0 && ctPostOpen.get() > 0;
171   }
172 
173   @Override
174   public void preClose(ObserverContext<RegionCoprocessorEnvironment> c, boolean abortRequested) {
175     ctPreClose.incrementAndGet();
176   }
177 
178   @Override
179   public void postClose(ObserverContext<RegionCoprocessorEnvironment> c, boolean abortRequested) {
180     ctPostClose.incrementAndGet();
181   }
182 
183   public boolean wasClosed() {
184     return ctPreClose.get() > 0 && ctPostClose.get() > 0;
185   }
186 
187   @Override
188   public InternalScanner preFlush(ObserverContext<RegionCoprocessorEnvironment> c,
189       Store store, InternalScanner scanner) throws IOException {
190     ctPreFlush.incrementAndGet();
191     return scanner;
192   }
193 
194   @Override
195   public InternalScanner preFlushScannerOpen(final ObserverContext<RegionCoprocessorEnvironment> c,
196       Store store, KeyValueScanner memstoreScanner, InternalScanner s) throws IOException {
197     ctPreFlushScannerOpen.incrementAndGet();
198     return null;
199   }
200 
201   @Override
202   public void postFlush(ObserverContext<RegionCoprocessorEnvironment> c,
203       Store store, StoreFile resultFile) throws IOException {
204     ctPostFlush.incrementAndGet();
205     if (throwOnPostFlush.get()){
206       throw new IOException("throwOnPostFlush is true in postFlush");
207     }
208   }
209 
210   public boolean wasFlushed() {
211     return ctPreFlush.get() > 0 && ctPostFlush.get() > 0;
212   }
213 
214   @Override
215   public void preSplit(ObserverContext<RegionCoprocessorEnvironment> c) {
216     ctPreSplit.incrementAndGet();
217   }
218 
219   @Override
220   public void preSplitBeforePONR(
221       ObserverContext<RegionCoprocessorEnvironment> ctx, byte[] splitKey,
222       List<Mutation> metaEntries) throws IOException {
223     ctPreSplitBeforePONR.incrementAndGet();
224   }
225   
226   @Override
227   public void preSplitAfterPONR(
228       ObserverContext<RegionCoprocessorEnvironment> ctx) throws IOException {
229     ctPreSplitAfterPONR.incrementAndGet();
230   }
231   
232   @Override
233   public void postSplit(ObserverContext<RegionCoprocessorEnvironment> c, Region l, Region r) {
234     ctPostSplit.incrementAndGet();
235   }
236 
237   public boolean wasSplit() {
238     return ctPreSplit.get() > 0 && ctPostSplit.get() > 0;
239   }
240 
241   @Override
242   public void preCompactSelection(ObserverContext<RegionCoprocessorEnvironment> c,
243       Store store, List<StoreFile> candidates) {
244     ctPreCompactSelect.incrementAndGet();
245   }
246 
247   @Override
248   public void postCompactSelection(ObserverContext<RegionCoprocessorEnvironment> c,
249       Store store, ImmutableList<StoreFile> selected) {
250     ctPostCompactSelect.incrementAndGet();
251   }
252 
253   @Override
254   public InternalScanner preCompact(ObserverContext<RegionCoprocessorEnvironment> e,
255       Store store, InternalScanner scanner, ScanType scanType) {
256     ctPreCompact.incrementAndGet();
257     return scanner;
258   }
259 
260   @Override
261   public InternalScanner preCompactScannerOpen(
262       final ObserverContext<RegionCoprocessorEnvironment> c,
263       Store store, List<? extends KeyValueScanner> scanners, ScanType scanType, long earliestPutTs,
264       InternalScanner s) throws IOException {
265     ctPreCompactScanner.incrementAndGet();
266     return null;
267   }
268 
269   @Override
270   public void postCompact(ObserverContext<RegionCoprocessorEnvironment> e,
271       Store store, StoreFile resultFile) {
272     ctPostCompact.incrementAndGet();
273   }
274 
275   public boolean wasCompacted() {
276     return ctPreCompact.get() > 0 && ctPostCompact.get() > 0;
277   }
278 
279   @Override
280   public RegionScanner preScannerOpen(final ObserverContext<RegionCoprocessorEnvironment> c,
281       final Scan scan,
282       final RegionScanner s) throws IOException {
283     ctPreScannerOpen.incrementAndGet();
284     return null;
285   }
286 
287   @Override
288   public KeyValueScanner preStoreScannerOpen(final ObserverContext<RegionCoprocessorEnvironment> c,
289       final Store store, final Scan scan, final NavigableSet<byte[]> targetCols,
290       final KeyValueScanner s) throws IOException {
291     ctPreStoreScannerOpen.incrementAndGet();
292     return null;
293   }
294 
295   @Override
296   public RegionScanner postScannerOpen(final ObserverContext<RegionCoprocessorEnvironment> c,
297       final Scan scan, final RegionScanner s)
298       throws IOException {
299     ctPostScannerOpen.incrementAndGet();
300     return s;
301   }
302 
303   @Override
304   public boolean preScannerNext(final ObserverContext<RegionCoprocessorEnvironment> c,
305       final InternalScanner s, final List<Result> results,
306       final int limit, final boolean hasMore) throws IOException {
307     ctPreScannerNext.incrementAndGet();
308     return hasMore;
309   }
310 
311   @Override
312   public boolean postScannerNext(final ObserverContext<RegionCoprocessorEnvironment> c,
313       final InternalScanner s, final List<Result> results, final int limit,
314       final boolean hasMore) throws IOException {
315     ctPostScannerNext.incrementAndGet();
316     return hasMore;
317   }
318 
319   @Override
320   public boolean postScannerFilterRow(final ObserverContext<RegionCoprocessorEnvironment> e,
321       final InternalScanner s, final byte[] currentRow, final int offset, final short length,
322       final boolean hasMore) throws IOException {
323     ctPostScannerFilterRow.incrementAndGet();
324     return hasMore;
325   }
326 
327   @Override
328   public void preScannerClose(final ObserverContext<RegionCoprocessorEnvironment> c,
329       final InternalScanner s) throws IOException {
330     ctPreScannerClose.incrementAndGet();
331   }
332 
333   @Override
334   public void postScannerClose(final ObserverContext<RegionCoprocessorEnvironment> c,
335       final InternalScanner s) throws IOException {
336     ctPostScannerClose.incrementAndGet();
337   }
338 
339   @Override
340   public void preGetOp(final ObserverContext<RegionCoprocessorEnvironment> c, final Get get,
341       final List<Cell> results) throws IOException {
342     RegionCoprocessorEnvironment e = c.getEnvironment();
343     assertNotNull(e);
344     assertNotNull(e.getRegion());
345     assertNotNull(get);
346     assertNotNull(results);
347     ctPreGet.incrementAndGet();
348   }
349 
350   @Override
351   public void postGetOp(final ObserverContext<RegionCoprocessorEnvironment> c, final Get get,
352       final List<Cell> results) {
353     RegionCoprocessorEnvironment e = c.getEnvironment();
354     assertNotNull(e);
355     assertNotNull(e.getRegion());
356     assertNotNull(get);
357     assertNotNull(results);
358     if (e.getRegion().getTableDesc().getTableName().equals(
359         TestRegionObserverInterface.TEST_TABLE)) {
360       boolean foundA = false;
361       boolean foundB = false;
362       boolean foundC = false;
363       for (Cell kv: results) {
364         if (CellUtil.matchingFamily(kv, TestRegionObserverInterface.A)) {
365           foundA = true;
366         }
367         if (CellUtil.matchingFamily(kv, TestRegionObserverInterface.B)) {
368           foundB = true;
369         }
370         if (CellUtil.matchingFamily(kv, TestRegionObserverInterface.C)) {
371           foundC = true;
372         }
373       }
374       assertTrue(foundA);
375       assertTrue(foundB);
376       assertTrue(foundC);
377     }
378     ctPostGet.incrementAndGet();
379   }
380 
381   @Override
382   public void prePut(final ObserverContext<RegionCoprocessorEnvironment> c, 
383       final Put put, final WALEdit edit,
384       final Durability durability) throws IOException {
385     Map<byte[], List<Cell>> familyMap  = put.getFamilyCellMap();
386     RegionCoprocessorEnvironment e = c.getEnvironment();
387     assertNotNull(e);
388     assertNotNull(e.getRegion());
389     assertNotNull(familyMap);
390     if (e.getRegion().getTableDesc().getTableName().equals(
391         TestRegionObserverInterface.TEST_TABLE)) {
392       List<Cell> cells = familyMap.get(TestRegionObserverInterface.A);
393       assertNotNull(cells);
394       assertNotNull(cells.get(0));
395       KeyValue kv = (KeyValue)cells.get(0);
396       assertTrue(Bytes.equals(kv.getQualifier(),
397           TestRegionObserverInterface.A));
398       cells = familyMap.get(TestRegionObserverInterface.B);
399       assertNotNull(cells);
400       assertNotNull(cells.get(0));
401       kv = (KeyValue)cells.get(0);
402       assertTrue(Bytes.equals(kv.getQualifier(),
403           TestRegionObserverInterface.B));
404       cells = familyMap.get(TestRegionObserverInterface.C);
405       assertNotNull(cells);
406       assertNotNull(cells.get(0));
407       kv = (KeyValue)cells.get(0);
408       assertTrue(Bytes.equals(kv.getQualifier(),
409           TestRegionObserverInterface.C));
410     }
411     ctPrePut.incrementAndGet();
412   }
413 
414   @Override
415   public void postPut(final ObserverContext<RegionCoprocessorEnvironment> c,
416       final Put put, final WALEdit edit,
417       final Durability durability) throws IOException {
418     Map<byte[], List<Cell>> familyMap  = put.getFamilyCellMap();
419     RegionCoprocessorEnvironment e = c.getEnvironment();
420     assertNotNull(e);
421     assertNotNull(e.getRegion());
422     assertNotNull(familyMap);
423     List<Cell> cells = familyMap.get(TestRegionObserverInterface.A);
424     if (e.getRegion().getTableDesc().getTableName().equals(
425         TestRegionObserverInterface.TEST_TABLE)) {
426       assertNotNull(cells);
427       assertNotNull(cells.get(0));
428       // KeyValue v1 expectation.  Cast for now until we go all Cell all the time. TODO
429       KeyValue kv = (KeyValue)cells.get(0);
430       assertTrue(Bytes.equals(kv.getQualifier(), TestRegionObserverInterface.A));
431       cells = familyMap.get(TestRegionObserverInterface.B);
432       assertNotNull(cells);
433       assertNotNull(cells.get(0));
434       // KeyValue v1 expectation.  Cast for now until we go all Cell all the time. TODO
435       kv = (KeyValue)cells.get(0);
436       assertTrue(Bytes.equals(kv.getQualifier(), TestRegionObserverInterface.B));
437       cells = familyMap.get(TestRegionObserverInterface.C);
438       assertNotNull(cells);
439       assertNotNull(cells.get(0));
440       // KeyValue v1 expectation.  Cast for now until we go all Cell all the time. TODO
441       kv = (KeyValue)cells.get(0);
442       assertTrue(Bytes.equals(kv.getQualifier(), TestRegionObserverInterface.C));
443     }
444     ctPostPut.incrementAndGet();
445   }
446 
447   @Override
448   public void preDelete(final ObserverContext<RegionCoprocessorEnvironment> c, 
449       final Delete delete, final WALEdit edit,
450       final Durability durability) throws IOException {
451     Map<byte[], List<Cell>> familyMap  = delete.getFamilyCellMap();
452     RegionCoprocessorEnvironment e = c.getEnvironment();
453     assertNotNull(e);
454     assertNotNull(e.getRegion());
455     assertNotNull(familyMap);
456     if (ctBeforeDelete.get() > 0) {
457       ctPreDeleted.incrementAndGet();
458     }
459   }
460 
461   @Override
462   public void prePrepareTimeStampForDeleteVersion(ObserverContext<RegionCoprocessorEnvironment> e,
463       Mutation delete, Cell cell, byte[] byteNow, Get get) throws IOException {
464     ctPrePrepareDeleteTS.incrementAndGet();
465   }
466 
467   @Override
468   public void postDelete(final ObserverContext<RegionCoprocessorEnvironment> c, 
469       final Delete delete, final WALEdit edit,
470       final Durability durability) throws IOException {
471     Map<byte[], List<Cell>> familyMap  = delete.getFamilyCellMap();
472     RegionCoprocessorEnvironment e = c.getEnvironment();
473     assertNotNull(e);
474     assertNotNull(e.getRegion());
475     assertNotNull(familyMap);
476     ctBeforeDelete.set(0);
477     ctPostDeleted.incrementAndGet();
478   }
479   
480   @Override
481   public void preBatchMutate(ObserverContext<RegionCoprocessorEnvironment> c,
482       MiniBatchOperationInProgress<Mutation> miniBatchOp) throws IOException {
483     RegionCoprocessorEnvironment e = c.getEnvironment();
484     assertNotNull(e);
485     assertNotNull(e.getRegion());
486     assertNotNull(miniBatchOp);
487     ctPreBatchMutate.incrementAndGet();
488   }
489 
490   @Override
491   public void postBatchMutate(final ObserverContext<RegionCoprocessorEnvironment> c,
492       final MiniBatchOperationInProgress<Mutation> miniBatchOp) throws IOException {
493     RegionCoprocessorEnvironment e = c.getEnvironment();
494     assertNotNull(e);
495     assertNotNull(e.getRegion());
496     assertNotNull(miniBatchOp);
497     ctPostBatchMutate.incrementAndGet();
498   }
499 
500   @Override
501   public void postStartRegionOperation(final ObserverContext<RegionCoprocessorEnvironment> ctx,
502       Operation op) throws IOException {
503     ctPostStartRegionOperation.incrementAndGet();
504   }
505 
506   @Override
507   public void postCloseRegionOperation(final ObserverContext<RegionCoprocessorEnvironment> ctx,
508       Operation op) throws IOException {
509     if (ctPostStartRegionOperation.get() > 0) {
510       ctPostCloseRegionOperation.incrementAndGet();
511     }
512   }
513 
514   @Override
515   public void postBatchMutateIndispensably(final ObserverContext<RegionCoprocessorEnvironment> ctx,
516       MiniBatchOperationInProgress<Mutation> miniBatchOp, final boolean success) throws IOException {
517     ctPostBatchMutateIndispensably.incrementAndGet();
518   }
519 
520   @Override
521   public void preGetClosestRowBefore(final ObserverContext<RegionCoprocessorEnvironment> c,
522       final byte[] row, final byte[] family, final Result result)
523       throws IOException {
524     RegionCoprocessorEnvironment e = c.getEnvironment();
525     assertNotNull(e);
526     assertNotNull(e.getRegion());
527     assertNotNull(row);
528     assertNotNull(result);
529     if (ctBeforeDelete.get() > 0) {
530       ctPreGetClosestRowBefore.incrementAndGet();
531     }
532   }
533 
534   @Override
535   public void postGetClosestRowBefore(final ObserverContext<RegionCoprocessorEnvironment> c,
536       final byte[] row, final byte[] family, final Result result)
537       throws IOException {
538     RegionCoprocessorEnvironment e = c.getEnvironment();
539     assertNotNull(e);
540     assertNotNull(e.getRegion());
541     assertNotNull(row);
542     assertNotNull(result);
543     ctPostGetClosestRowBefore.incrementAndGet();
544   }
545 
546   @Override
547   public Result preIncrement(final ObserverContext<RegionCoprocessorEnvironment> c,
548       final Increment increment) throws IOException {
549     ctPreIncrement.incrementAndGet();
550     return null;
551   }
552 
553   @Override
554   public Result preIncrementAfterRowLock(ObserverContext<RegionCoprocessorEnvironment> e,
555       Increment increment) throws IOException {
556     ctPreIncrementAfterRowLock.incrementAndGet();
557     return null;
558   }
559 
560   @Override
561   public Result postIncrement(final ObserverContext<RegionCoprocessorEnvironment> c,
562       final Increment increment, final Result result) throws IOException {
563     ctPostIncrement.incrementAndGet();
564     return result;
565   }
566 
567   @Override
568   public boolean preCheckAndPut(ObserverContext<RegionCoprocessorEnvironment> e, byte[] row,
569       byte[] family, byte[] qualifier, CompareOp compareOp, ByteArrayComparable comparator,
570       Put put, boolean result) throws IOException {
571     ctPreCheckAndPut.incrementAndGet();
572     return true;
573   }
574 
575   @Override
576   public boolean preCheckAndPutAfterRowLock(ObserverContext<RegionCoprocessorEnvironment> e,
577       byte[] row, byte[] family, byte[] qualifier, CompareOp compareOp,
578       ByteArrayComparable comparator, Put put, boolean result) throws IOException {
579     ctPreCheckAndPutAfterRowLock.incrementAndGet();
580     return true;
581   }
582 
583   @Override
584   public boolean postCheckAndPut(ObserverContext<RegionCoprocessorEnvironment> e, byte[] row,
585       byte[] family, byte[] qualifier, CompareOp compareOp, ByteArrayComparable comparator,
586       Put put, boolean result) throws IOException {
587     ctPostCheckAndPut.incrementAndGet();
588     return true;
589   }
590 
591   @Override
592   public boolean preCheckAndDelete(ObserverContext<RegionCoprocessorEnvironment> e, byte[] row,
593       byte[] family, byte[] qualifier, CompareOp compareOp, ByteArrayComparable comparator,
594       Delete delete, boolean result) throws IOException {
595     ctPreCheckAndDelete.incrementAndGet();
596     return true;
597   }
598 
599   @Override
600   public boolean preCheckAndDeleteAfterRowLock(ObserverContext<RegionCoprocessorEnvironment> e,
601       byte[] row, byte[] family, byte[] qualifier, CompareOp compareOp,
602       ByteArrayComparable comparator, Delete delete, boolean result) throws IOException {
603     ctPreCheckAndDeleteAfterRowLock.incrementAndGet();
604     return true;
605   }
606 
607   @Override
608   public boolean postCheckAndDelete(ObserverContext<RegionCoprocessorEnvironment> e, byte[] row,
609       byte[] family, byte[] qualifier, CompareOp compareOp, ByteArrayComparable comparator,
610       Delete delete, boolean result) throws IOException {
611     ctPostCheckAndDelete.incrementAndGet();
612     return true;
613   }
614 
615   @Override
616   public Result preAppendAfterRowLock(ObserverContext<RegionCoprocessorEnvironment> e, 
617       Append append) throws IOException {
618     ctPreAppendAfterRowLock.incrementAndGet();
619     return null;
620   }
621 
622   @Override
623   public Result preAppend(ObserverContext<RegionCoprocessorEnvironment> e, Append append)
624       throws IOException {
625     ctPreAppend.incrementAndGet();
626     return null;
627   }
628 
629   @Override
630   public Result postAppend(ObserverContext<RegionCoprocessorEnvironment> e, Append append,
631       Result result) throws IOException {
632     ctPostAppend.incrementAndGet();
633     return null;
634   }
635 
636   @Override
637   public void preBulkLoadHFile(ObserverContext<RegionCoprocessorEnvironment> ctx,
638                                List<Pair<byte[], String>> familyPaths) throws IOException {
639     RegionCoprocessorEnvironment e = ctx.getEnvironment();
640     assertNotNull(e);
641     assertNotNull(e.getRegion());
642     if (e.getRegion().getTableDesc().getTableName().equals(
643         TestRegionObserverInterface.TEST_TABLE)) {
644       assertNotNull(familyPaths);
645       assertEquals(1,familyPaths.size());
646       assertArrayEquals(familyPaths.get(0).getFirst(), TestRegionObserverInterface.A);
647       String familyPath = familyPaths.get(0).getSecond();
648       String familyName = Bytes.toString(TestRegionObserverInterface.A);
649       assertEquals(familyPath.substring(familyPath.length()-familyName.length()-1),"/"+familyName);
650     }
651     ctPreBulkLoadHFile.incrementAndGet();
652   }
653 
654   @Override
655   public boolean postBulkLoadHFile(ObserverContext<RegionCoprocessorEnvironment> ctx,
656       List<Pair<byte[], String>> familyPaths, boolean hasLoaded) throws IOException {
657     RegionCoprocessorEnvironment e = ctx.getEnvironment();
658     assertNotNull(e);
659     assertNotNull(e.getRegion());
660     if (e.getRegion().getTableDesc().getTableName().equals(
661         TestRegionObserverInterface.TEST_TABLE)) {
662       assertNotNull(familyPaths);
663       assertEquals(1,familyPaths.size());
664       assertArrayEquals(familyPaths.get(0).getFirst(), TestRegionObserverInterface.A);
665       String familyPath = familyPaths.get(0).getSecond();
666       String familyName = Bytes.toString(TestRegionObserverInterface.A);
667       assertEquals(familyPath.substring(familyPath.length()-familyName.length()-1),"/"+familyName);
668     }
669     ctPostBulkLoadHFile.incrementAndGet();
670     return hasLoaded;
671   }
672 
673   @Override
674   public void preWALRestore(ObserverContext<? extends RegionCoprocessorEnvironment> env,
675       HRegionInfo info, WALKey logKey, WALEdit logEdit) throws IOException {
676     String tableName = logKey.getTablename().getNameAsString();
677     if (tableName.equals(TABLE_SKIPPED)) {
678       // skip recovery of TABLE_SKIPPED for testing purpose
679       env.bypass();
680       return;
681     }
682     ctPreWALRestore.incrementAndGet();
683   }
684 
685   @Override
686   public void preWALRestore(ObserverContext<RegionCoprocessorEnvironment> env, HRegionInfo info,
687                             HLogKey logKey, WALEdit logEdit) throws IOException {
688     preWALRestore(env, info, (WALKey)logKey, logEdit);
689     ctPreWALRestoreDeprecated.incrementAndGet();
690   }
691 
692   @Override
693   public void postWALRestore(ObserverContext<? extends RegionCoprocessorEnvironment> env,
694                              HRegionInfo info, WALKey logKey, WALEdit logEdit) throws IOException {
695     ctPostWALRestore.incrementAndGet();
696   }
697 
698   @Override
699   public void postWALRestore(ObserverContext<RegionCoprocessorEnvironment> env,
700                              HRegionInfo info, HLogKey logKey, WALEdit logEdit) throws IOException {
701     postWALRestore(env, info, (WALKey)logKey, logEdit);
702     ctPostWALRestoreDeprecated.incrementAndGet();
703   }
704 
705   @Override
706   public Reader preStoreFileReaderOpen(ObserverContext<RegionCoprocessorEnvironment> ctx,
707       FileSystem fs, Path p, FSDataInputStreamWrapper in, long size, CacheConfig cacheConf,
708       Reference r, Reader reader) throws IOException {
709     ctPreStoreFileReaderOpen.incrementAndGet();
710     return null;
711   }
712 
713   @Override
714   public Reader postStoreFileReaderOpen(ObserverContext<RegionCoprocessorEnvironment> ctx,
715       FileSystem fs, Path p, FSDataInputStreamWrapper in, long size, CacheConfig cacheConf,
716       Reference r, Reader reader) throws IOException {
717     ctPostStoreFileReaderOpen.incrementAndGet();
718     return reader;
719   }
720 
721   public boolean hadPreGet() {
722     return ctPreGet.get() > 0;
723   }
724 
725   public boolean hadPostGet() {
726     return ctPostGet.get() > 0;
727   }
728 
729   public boolean hadPrePut() {
730     return ctPrePut.get() > 0;
731   }
732 
733   public boolean hadPostPut() {
734     return ctPostPut.get() > 0;
735   }
736   
737   public boolean hadPreBatchMutate() {
738     return ctPreBatchMutate.get() > 0;
739   }
740 
741   public boolean hadPostBatchMutate() {
742     return ctPostBatchMutate.get() > 0;
743   }
744 
745   public boolean hadPostBatchMutateIndispensably() {
746     return ctPostBatchMutateIndispensably.get() > 0;
747   }
748 
749   public boolean hadPostStartRegionOperation() {
750     return ctPostStartRegionOperation.get() > 0;
751   }
752 
753   public boolean hadPostCloseRegionOperation() {
754     return ctPostCloseRegionOperation.get() > 0;
755   }
756 
757   public boolean hadDelete() {
758     return !(ctBeforeDelete.get() > 0);
759   }
760 
761   public int getCtPostStartRegionOperation() {
762     return ctPostStartRegionOperation.get();
763   }
764 
765   public int getCtPostCloseRegionOperation() {
766     return ctPostCloseRegionOperation.get();
767   }
768 
769   public boolean hadPreCheckAndPut() {
770     return ctPreCheckAndPut.get() > 0;
771   }
772 
773   public boolean hadPreCheckAndPutAfterRowLock() {
774     return ctPreCheckAndPutAfterRowLock.get() > 0;
775   }
776 
777   public boolean hadPostCheckAndPut() {
778     return ctPostCheckAndPut.get() > 0;
779   }
780 
781   public boolean hadPreCheckAndDelete() {
782     return ctPreCheckAndDelete.get() > 0;
783   }
784 
785   public boolean hadPreCheckAndDeleteAfterRowLock() {
786     return ctPreCheckAndDeleteAfterRowLock.get() > 0;
787   }
788 
789   public boolean hadPostCheckAndDelete() {
790     return ctPostCheckAndDelete.get() > 0;
791   }
792 
793   public boolean hadPreIncrement() {
794     return ctPreIncrement.get() > 0;
795   }
796   
797   public boolean hadPreIncrementAfterRowLock() {
798     return ctPreIncrementAfterRowLock.get() > 0;
799   }
800 
801   public boolean hadPostIncrement() {
802     return ctPostIncrement.get() > 0;
803   }
804 
805   public boolean hadPreAppend() {
806     return ctPreAppend.get() > 0;
807   }
808 
809   public boolean hadPreAppendAfterRowLock() {
810     return ctPreAppendAfterRowLock.get() > 0;
811   }
812 
813   public boolean hadPostAppend() {
814     return ctPostAppend.get() > 0;
815   }
816 
817   public boolean hadPrePreparedDeleteTS() {
818     return ctPrePrepareDeleteTS.get() > 0;
819   }
820   
821   public boolean hadPreWALRestore() {
822     return ctPreWALRestore.get() > 0;
823   }
824 
825   public boolean hadPostWALRestore() {
826     return ctPostWALRestore.get() > 0;
827   }
828 
829   public boolean wasScannerNextCalled() {
830     return ctPreScannerNext.get() > 0 && ctPostScannerNext.get() > 0;
831   }
832   public boolean wasScannerFilterRowCalled() {
833     return ctPostScannerFilterRow.get() > 0;
834   }
835   public boolean wasScannerCloseCalled() {
836     return ctPreScannerClose.get() > 0 && ctPostScannerClose.get() > 0;
837   }
838   public boolean wasScannerOpenCalled() {
839     return ctPreScannerOpen.get() > 0 && ctPostScannerOpen.get() > 0;
840   }
841   public boolean hadDeleted() {
842     return ctPreDeleted.get() > 0 && ctPostDeleted.get() > 0;
843   }
844 
845   public boolean hadPostBulkLoadHFile() {
846     return ctPostBulkLoadHFile.get() > 0;
847   }
848 
849   public boolean hadPreBulkLoadHFile() {
850     return ctPreBulkLoadHFile.get() > 0;
851   }
852 
853 
854   public int getCtBeforeDelete() {
855     return ctBeforeDelete.get();
856   }
857 
858   public int getCtPreOpen() {
859     return ctPreOpen.get();
860   }
861 
862   public int getCtPostOpen() {
863     return ctPostOpen.get();
864   }
865 
866   public int getCtPreClose() {
867     return ctPreClose.get();
868   }
869 
870   public int getCtPostClose() {
871     return ctPostClose.get();
872   }
873 
874   public int getCtPreFlush() {
875     return ctPreFlush.get();
876   }
877 
878   public int getCtPreFlushScannerOpen() {
879     return ctPreFlushScannerOpen.get();
880   }
881 
882   public int getCtPostFlush() {
883     return ctPostFlush.get();
884   }
885 
886   public int getCtPreSplit() {
887     return ctPreSplit.get();
888   }
889   
890   public int getCtPreSplitBeforePONR() {
891     return ctPreSplitBeforePONR.get();
892   }
893 
894   public int getCtPreSplitAfterPONR() {
895     return ctPreSplitAfterPONR.get();
896   }
897 
898   public int getCtPostSplit() {
899     return ctPostSplit.get();
900   }
901 
902   public int getCtPreCompactSelect() {
903     return ctPreCompactSelect.get();
904   }
905 
906   public int getCtPostCompactSelect() {
907     return ctPostCompactSelect.get();
908   }
909 
910   public int getCtPreCompactScanner() {
911     return ctPreCompactScanner.get();
912   }
913 
914   public int getCtPreCompact() {
915     return ctPreCompact.get();
916   }
917 
918   public int getCtPostCompact() {
919     return ctPostCompact.get();
920   }
921 
922   public int getCtPreGet() {
923     return ctPreGet.get();
924   }
925 
926   public int getCtPostGet() {
927     return ctPostGet.get();
928   }
929 
930   public int getCtPrePut() {
931     return ctPrePut.get();
932   }
933 
934   public int getCtPostPut() {
935     return ctPostPut.get();
936   }
937 
938   public int getCtPreDeleted() {
939     return ctPreDeleted.get();
940   }
941 
942   public int getCtPostDeleted() {
943     return ctPostDeleted.get();
944   }
945 
946   public int getCtPreGetClosestRowBefore() {
947     return ctPreGetClosestRowBefore.get();
948   }
949 
950   public int getCtPostGetClosestRowBefore() {
951     return ctPostGetClosestRowBefore.get();
952   }
953 
954   public int getCtPreIncrement() {
955     return ctPreIncrement.get();
956   }
957 
958   public int getCtPostIncrement() {
959     return ctPostIncrement.get();
960   }
961 
962   public int getCtPreWALRestore() {
963     return ctPreWALRestore.get();
964   }
965 
966   public int getCtPostWALRestore() {
967     return ctPostWALRestore.get();
968   }
969 
970   public int getCtPreWALRestoreDeprecated() {
971     return ctPreWALRestoreDeprecated.get();
972   }
973 
974   public int getCtPostWALRestoreDeprecated() {
975     return ctPostWALRestoreDeprecated.get();
976   }
977 
978   public boolean wasStoreFileReaderOpenCalled() {
979     return ctPreStoreFileReaderOpen.get() > 0 && ctPostStoreFileReaderOpen.get() > 0;
980   }
981 
982   /**
983    * This implementation should trigger our legacy support because it does not directly
984    * implement the newer API calls.
985    */
986   public static class Legacy extends SimpleRegionObserver {
987   }
988 }