001/**
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements.  See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership.  The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License.  You may obtain a copy of the License at
010 *
011 *     http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 */
019
020package org.apache.hadoop.hbase.coprocessor;
021
022import static org.junit.Assert.assertArrayEquals;
023import static org.junit.Assert.assertEquals;
024import static org.junit.Assert.assertNotNull;
025import static org.junit.Assert.assertTrue;
026
027import java.io.IOException;
028import java.util.HashMap;
029import java.util.List;
030import java.util.Map;
031import java.util.Optional;
032import java.util.concurrent.atomic.AtomicBoolean;
033import java.util.concurrent.atomic.AtomicInteger;
034
035import org.apache.hadoop.fs.FileSystem;
036import org.apache.hadoop.fs.Path;
037import org.apache.hadoop.hbase.Cell;
038import org.apache.hadoop.hbase.CellUtil;
039import org.apache.hadoop.hbase.CompareOperator;
040import org.apache.hadoop.hbase.CoprocessorEnvironment;
041import org.apache.hadoop.hbase.KeepDeletedCells;
042import org.apache.hadoop.hbase.client.Append;
043import org.apache.hadoop.hbase.client.CheckAndMutate;
044import org.apache.hadoop.hbase.client.CheckAndMutateResult;
045import org.apache.hadoop.hbase.client.Delete;
046import org.apache.hadoop.hbase.client.Durability;
047import org.apache.hadoop.hbase.client.Get;
048import org.apache.hadoop.hbase.client.Increment;
049import org.apache.hadoop.hbase.client.Mutation;
050import org.apache.hadoop.hbase.client.Put;
051import org.apache.hadoop.hbase.client.RegionInfo;
052import org.apache.hadoop.hbase.client.Result;
053import org.apache.hadoop.hbase.client.Scan;
054import org.apache.hadoop.hbase.filter.ByteArrayComparable;
055import org.apache.hadoop.hbase.filter.Filter;
056import org.apache.hadoop.hbase.io.FSDataInputStreamWrapper;
057import org.apache.hadoop.hbase.io.Reference;
058import org.apache.hadoop.hbase.io.hfile.CacheConfig;
059import org.apache.hadoop.hbase.regionserver.FlushLifeCycleTracker;
060import org.apache.hadoop.hbase.regionserver.InternalScanner;
061import org.apache.hadoop.hbase.regionserver.MiniBatchOperationInProgress;
062import org.apache.hadoop.hbase.regionserver.Region.Operation;
063import org.apache.hadoop.hbase.regionserver.RegionScanner;
064import org.apache.hadoop.hbase.regionserver.ScanOptions;
065import org.apache.hadoop.hbase.regionserver.ScanType;
066import org.apache.hadoop.hbase.regionserver.Store;
067import org.apache.hadoop.hbase.regionserver.StoreFile;
068import org.apache.hadoop.hbase.regionserver.StoreFileReader;
069import org.apache.hadoop.hbase.regionserver.compactions.CompactionLifeCycleTracker;
070import org.apache.hadoop.hbase.regionserver.compactions.CompactionRequest;
071import org.apache.hadoop.hbase.util.Bytes;
072import org.apache.hadoop.hbase.util.Pair;
073import org.apache.hadoop.hbase.wal.WALEdit;
074import org.apache.hadoop.hbase.wal.WALKey;
075
076/**
077 * A sample region observer that tests the RegionObserver interface.
078 * It works with TestRegionObserverInterface to provide the test case.
079 */
080public class SimpleRegionObserver implements RegionCoprocessor, RegionObserver {
081
082  final AtomicInteger ctBeforeDelete = new AtomicInteger(1);
083  final AtomicInteger ctPreOpen = new AtomicInteger(0);
084  final AtomicInteger ctPostOpen = new AtomicInteger(0);
085  final AtomicInteger ctPreClose = new AtomicInteger(0);
086  final AtomicInteger ctPostClose = new AtomicInteger(0);
087  final AtomicInteger ctPreFlush = new AtomicInteger(0);
088  final AtomicInteger ctPostFlush = new AtomicInteger(0);
089  final AtomicInteger ctPreCompactSelect = new AtomicInteger(0);
090  final AtomicInteger ctPostCompactSelect = new AtomicInteger(0);
091  final AtomicInteger ctPreCompact = new AtomicInteger(0);
092  final AtomicInteger ctPostCompact = new AtomicInteger(0);
093  final AtomicInteger ctPreGet = new AtomicInteger(0);
094  final AtomicInteger ctPostGet = new AtomicInteger(0);
095  final AtomicInteger ctPrePut = new AtomicInteger(0);
096  final AtomicInteger ctPostPut = new AtomicInteger(0);
097  final AtomicInteger ctPreDeleted = new AtomicInteger(0);
098  final AtomicInteger ctPrePrepareDeleteTS = new AtomicInteger(0);
099  final AtomicInteger ctPostDeleted = new AtomicInteger(0);
100  final AtomicInteger ctPreIncrement = new AtomicInteger(0);
101  final AtomicInteger ctPreIncrementAfterRowLock = new AtomicInteger(0);
102  final AtomicInteger ctPreAppend = new AtomicInteger(0);
103  final AtomicInteger ctPreAppendAfterRowLock = new AtomicInteger(0);
104  final AtomicInteger ctPostIncrement = new AtomicInteger(0);
105  final AtomicInteger ctPostAppend = new AtomicInteger(0);
106  final AtomicInteger ctPreCheckAndPut = new AtomicInteger(0);
107  final AtomicInteger ctPreCheckAndPutWithFilter = new AtomicInteger(0);
108  final AtomicInteger ctPreCheckAndPutAfterRowLock = new AtomicInteger(0);
109  final AtomicInteger ctPreCheckAndPutWithFilterAfterRowLock = new AtomicInteger(0);
110  final AtomicInteger ctPostCheckAndPut = new AtomicInteger(0);
111  final AtomicInteger ctPostCheckAndPutWithFilter = new AtomicInteger(0);
112  final AtomicInteger ctPreCheckAndDelete = new AtomicInteger(0);
113  final AtomicInteger ctPreCheckAndDeleteWithFilter = new AtomicInteger(0);
114  final AtomicInteger ctPreCheckAndDeleteAfterRowLock = new AtomicInteger(0);
115  final AtomicInteger ctPreCheckAndDeleteWithFilterAfterRowLock = new AtomicInteger(0);
116  final AtomicInteger ctPostCheckAndDelete = new AtomicInteger(0);
117  final AtomicInteger ctPostCheckAndDeleteWithFilter = new AtomicInteger(0);
118  final AtomicInteger ctPreCheckAndMutate = new AtomicInteger(0);
119  final AtomicInteger ctPreCheckAndMutateAfterRowLock = new AtomicInteger(0);
120  final AtomicInteger ctPostCheckAndMutate = new AtomicInteger(0);
121  final AtomicInteger ctPreScannerNext = new AtomicInteger(0);
122  final AtomicInteger ctPostScannerNext = new AtomicInteger(0);
123  final AtomicInteger ctPostScannerFilterRow = new AtomicInteger(0);
124  final AtomicInteger ctPreScannerClose = new AtomicInteger(0);
125  final AtomicInteger ctPostScannerClose = new AtomicInteger(0);
126  final AtomicInteger ctPreScannerOpen = new AtomicInteger(0);
127  final AtomicInteger ctPostScannerOpen = new AtomicInteger(0);
128  final AtomicInteger ctPreBulkLoadHFile = new AtomicInteger(0);
129  final AtomicInteger ctPostBulkLoadHFile = new AtomicInteger(0);
130  final AtomicInteger ctPreBatchMutate = new AtomicInteger(0);
131  final AtomicInteger ctPostBatchMutate = new AtomicInteger(0);
132  final AtomicInteger ctPreReplayWALs = new AtomicInteger(0);
133  final AtomicInteger ctPostReplayWALs = new AtomicInteger(0);
134  final AtomicInteger ctPreWALRestore = new AtomicInteger(0);
135  final AtomicInteger ctPostWALRestore = new AtomicInteger(0);
136  final AtomicInteger ctPreStoreFileReaderOpen = new AtomicInteger(0);
137  final AtomicInteger ctPostStoreFileReaderOpen = new AtomicInteger(0);
138  final AtomicInteger ctPostBatchMutateIndispensably = new AtomicInteger(0);
139  final AtomicInteger ctPostStartRegionOperation = new AtomicInteger(0);
140  final AtomicInteger ctPostCloseRegionOperation = new AtomicInteger(0);
141  final AtomicBoolean throwOnPostFlush = new AtomicBoolean(false);
142  final AtomicInteger ctPreWALAppend = new AtomicInteger(0);
143
144  static final String TABLE_SKIPPED = "SKIPPED_BY_PREWALRESTORE";
145  Map<String, byte[]> extendedAttributes = new HashMap<String,byte[]>();
146  static final byte[] WAL_EXTENDED_ATTRIBUTE_BYTES = Bytes.toBytes("foo");
147
148  public void setThrowOnPostFlush(Boolean val){
149    throwOnPostFlush.set(val);
150  }
151
152  @Override
153  public Optional<RegionObserver> getRegionObserver() {
154    return Optional.of(this);
155  }
156
157  @Override
158  public void start(CoprocessorEnvironment e) throws IOException {
159  }
160
161  @Override
162  public void preOpen(ObserverContext<RegionCoprocessorEnvironment> c) {
163    ctPreOpen.incrementAndGet();
164  }
165
166  @Override
167  public void postOpen(ObserverContext<RegionCoprocessorEnvironment> c) {
168    ctPostOpen.incrementAndGet();
169  }
170
171  public boolean wasOpened() {
172    return ctPreOpen.get() > 0 && ctPostOpen.get() > 0;
173  }
174
175  @Override
176  public void preClose(ObserverContext<RegionCoprocessorEnvironment> c, boolean abortRequested) {
177    ctPreClose.incrementAndGet();
178  }
179
180  @Override
181  public void postClose(ObserverContext<RegionCoprocessorEnvironment> c, boolean abortRequested) {
182    ctPostClose.incrementAndGet();
183  }
184
185  public boolean wasClosed() {
186    return ctPreClose.get() > 0 && ctPostClose.get() > 0;
187  }
188
189  @Override
190  public InternalScanner preFlush(ObserverContext<RegionCoprocessorEnvironment> c,
191      Store store, InternalScanner scanner, FlushLifeCycleTracker tracker) throws IOException {
192    ctPreFlush.incrementAndGet();
193    return scanner;
194  }
195
196  @Override
197  public void postFlush(ObserverContext<RegionCoprocessorEnvironment> c,
198      Store store, StoreFile resultFile, FlushLifeCycleTracker tracker) throws IOException {
199    ctPostFlush.incrementAndGet();
200    if (throwOnPostFlush.get()){
201      throw new IOException("throwOnPostFlush is true in postFlush");
202    }
203  }
204
205  public boolean wasFlushed() {
206    return ctPreFlush.get() > 0 && ctPostFlush.get() > 0;
207  }
208
209  @Override
210  public void preCompactSelection(ObserverContext<RegionCoprocessorEnvironment> c, Store store,
211      List<? extends StoreFile> candidates, CompactionLifeCycleTracker tracker) throws IOException {
212    ctPreCompactSelect.incrementAndGet();
213  }
214
215  @Override
216  public void postCompactSelection(ObserverContext<RegionCoprocessorEnvironment> c, Store store,
217      List<? extends StoreFile> selected, CompactionLifeCycleTracker tracker,
218      CompactionRequest request) {
219    ctPostCompactSelect.incrementAndGet();
220  }
221
222  @Override
223  public InternalScanner preCompact(ObserverContext<RegionCoprocessorEnvironment> c, Store store,
224      InternalScanner scanner, ScanType scanType, CompactionLifeCycleTracker tracker,
225      CompactionRequest request) throws IOException {
226    ctPreCompact.incrementAndGet();
227    return scanner;
228  }
229
230  @Override
231  public void postCompact(ObserverContext<RegionCoprocessorEnvironment> c, Store store,
232      StoreFile resultFile, CompactionLifeCycleTracker tracker,
233      CompactionRequest request) throws IOException {
234    ctPostCompact.incrementAndGet();
235  }
236
237  public boolean wasCompacted() {
238    return ctPreCompact.get() > 0 && ctPostCompact.get() > 0;
239  }
240
241  @Override
242  public void preScannerOpen(final ObserverContext<RegionCoprocessorEnvironment> c, final Scan scan)
243      throws IOException {
244    ctPreScannerOpen.incrementAndGet();
245  }
246
247  @Override
248  public RegionScanner postScannerOpen(final ObserverContext<RegionCoprocessorEnvironment> c,
249      final Scan scan, final RegionScanner s)
250      throws IOException {
251    ctPostScannerOpen.incrementAndGet();
252    return s;
253  }
254
255  @Override
256  public boolean preScannerNext(final ObserverContext<RegionCoprocessorEnvironment> c,
257      final InternalScanner s, final List<Result> results,
258      final int limit, final boolean hasMore) throws IOException {
259    ctPreScannerNext.incrementAndGet();
260    return hasMore;
261  }
262
263  @Override
264  public boolean postScannerNext(final ObserverContext<RegionCoprocessorEnvironment> c,
265      final InternalScanner s, final List<Result> results, final int limit,
266      final boolean hasMore) throws IOException {
267    ctPostScannerNext.incrementAndGet();
268    return hasMore;
269  }
270
271  @Override
272  public boolean postScannerFilterRow(final ObserverContext<RegionCoprocessorEnvironment> e,
273      final InternalScanner s, final Cell currentRow, final boolean hasMore) throws IOException {
274    ctPostScannerFilterRow.incrementAndGet();
275    return hasMore;
276  }
277
278  @Override
279  public void preScannerClose(final ObserverContext<RegionCoprocessorEnvironment> c,
280      final InternalScanner s) throws IOException {
281    ctPreScannerClose.incrementAndGet();
282  }
283
284  @Override
285  public void postScannerClose(final ObserverContext<RegionCoprocessorEnvironment> c,
286      final InternalScanner s) throws IOException {
287    ctPostScannerClose.incrementAndGet();
288  }
289
290  @Override
291  public void preGetOp(final ObserverContext<RegionCoprocessorEnvironment> c, final Get get,
292      final List<Cell> results) throws IOException {
293    RegionCoprocessorEnvironment e = c.getEnvironment();
294    assertNotNull(e);
295    assertNotNull(e.getRegion());
296    assertNotNull(get);
297    assertNotNull(results);
298    ctPreGet.incrementAndGet();
299  }
300
301  @Override
302  public void postGetOp(final ObserverContext<RegionCoprocessorEnvironment> c, final Get get,
303      final List<Cell> results) {
304    RegionCoprocessorEnvironment e = c.getEnvironment();
305    assertNotNull(e);
306    assertNotNull(e.getRegion());
307    assertNotNull(get);
308    assertNotNull(results);
309    if (e.getRegion().getTableDescriptor().getTableName().equals(
310        TestRegionObserverInterface.TEST_TABLE)) {
311      boolean foundA = false;
312      boolean foundB = false;
313      boolean foundC = false;
314      for (Cell kv: results) {
315        if (CellUtil.matchingFamily(kv, TestRegionObserverInterface.A)) {
316          foundA = true;
317        }
318        if (CellUtil.matchingFamily(kv, TestRegionObserverInterface.B)) {
319          foundB = true;
320        }
321        if (CellUtil.matchingFamily(kv, TestRegionObserverInterface.C)) {
322          foundC = true;
323        }
324      }
325      assertTrue(foundA);
326      assertTrue(foundB);
327      assertTrue(foundC);
328    }
329    ctPostGet.incrementAndGet();
330  }
331
332  @Override
333  public void prePut(final ObserverContext<RegionCoprocessorEnvironment> c,
334      final Put put, final WALEdit edit,
335      final Durability durability) throws IOException {
336    Map<byte[], List<Cell>> familyMap  = put.getFamilyCellMap();
337    RegionCoprocessorEnvironment e = c.getEnvironment();
338    assertNotNull(e);
339    assertNotNull(e.getRegion());
340    assertNotNull(familyMap);
341    if (e.getRegion().getTableDescriptor().getTableName().equals(
342        TestRegionObserverInterface.TEST_TABLE)) {
343      List<Cell> cells = familyMap.get(TestRegionObserverInterface.A);
344      assertNotNull(cells);
345      assertNotNull(cells.get(0));
346      Cell cell = cells.get(0);
347      assertTrue(Bytes.equals(cell.getQualifierArray(), cell.getQualifierOffset(),
348        cell.getQualifierLength(), TestRegionObserverInterface.A, 0,
349        TestRegionObserverInterface.A.length));
350      cells = familyMap.get(TestRegionObserverInterface.B);
351      assertNotNull(cells);
352      assertNotNull(cells.get(0));
353      cell = cells.get(0);
354      assertTrue(Bytes.equals(cell.getQualifierArray(), cell.getQualifierOffset(),
355        cell.getQualifierLength(), TestRegionObserverInterface.B, 0,
356        TestRegionObserverInterface.B.length));
357      cells = familyMap.get(TestRegionObserverInterface.C);
358      assertNotNull(cells);
359      assertNotNull(cells.get(0));
360      cell = cells.get(0);
361      assertTrue(Bytes.equals(cell.getQualifierArray(), cell.getQualifierOffset(),
362        cell.getQualifierLength(), TestRegionObserverInterface.C, 0,
363        TestRegionObserverInterface.C.length));
364    }
365    ctPrePut.incrementAndGet();
366  }
367
368  @Override
369  public void postPut(final ObserverContext<RegionCoprocessorEnvironment> c,
370      final Put put, final WALEdit edit,
371      final Durability durability) throws IOException {
372    Map<byte[], List<Cell>> familyMap  = put.getFamilyCellMap();
373    RegionCoprocessorEnvironment e = c.getEnvironment();
374    assertNotNull(e);
375    assertNotNull(e.getRegion());
376    assertNotNull(familyMap);
377    List<Cell> cells = familyMap.get(TestRegionObserverInterface.A);
378    if (e.getRegion().getTableDescriptor().getTableName().equals(
379        TestRegionObserverInterface.TEST_TABLE)) {
380      assertNotNull(cells);
381      assertNotNull(cells.get(0));
382      // KeyValue v1 expectation.  Cast for now until we go all Cell all the time. TODO
383      Cell cell = cells.get(0);
384      assertTrue(Bytes.equals(cell.getQualifierArray(), cell.getQualifierOffset(),
385        cell.getQualifierLength(), TestRegionObserverInterface.A, 0,
386        TestRegionObserverInterface.A.length));
387      cells = familyMap.get(TestRegionObserverInterface.B);
388      assertNotNull(cells);
389      assertNotNull(cells.get(0));
390      // KeyValue v1 expectation.  Cast for now until we go all Cell all the time. TODO
391      cell = cells.get(0);
392      assertTrue(Bytes.equals(cell.getQualifierArray(), cell.getQualifierOffset(),
393        cell.getQualifierLength(), TestRegionObserverInterface.B, 0,
394        TestRegionObserverInterface.B.length));
395      cells = familyMap.get(TestRegionObserverInterface.C);
396      assertNotNull(cells);
397      assertNotNull(cells.get(0));
398      // KeyValue v1 expectation.  Cast for now until we go all Cell all the time. TODO
399      cell = cells.get(0);
400      assertTrue(Bytes.equals(cell.getQualifierArray(), cell.getQualifierOffset(),
401        cell.getQualifierLength(), TestRegionObserverInterface.C, 0,
402        TestRegionObserverInterface.C.length));
403    }
404    ctPostPut.incrementAndGet();
405  }
406
407  @Override
408  public void preDelete(final ObserverContext<RegionCoprocessorEnvironment> c,
409      final Delete delete, final WALEdit edit,
410      final Durability durability) throws IOException {
411    Map<byte[], List<Cell>> familyMap  = delete.getFamilyCellMap();
412    RegionCoprocessorEnvironment e = c.getEnvironment();
413    assertNotNull(e);
414    assertNotNull(e.getRegion());
415    assertNotNull(familyMap);
416    if (ctBeforeDelete.get() > 0) {
417      ctPreDeleted.incrementAndGet();
418    }
419  }
420
421  @Override
422  public void prePrepareTimeStampForDeleteVersion(ObserverContext<RegionCoprocessorEnvironment> e,
423      Mutation delete, Cell cell, byte[] byteNow, Get get) throws IOException {
424    ctPrePrepareDeleteTS.incrementAndGet();
425  }
426
427  @Override
428  public void postDelete(final ObserverContext<RegionCoprocessorEnvironment> c,
429      final Delete delete, final WALEdit edit,
430      final Durability durability) throws IOException {
431    Map<byte[], List<Cell>> familyMap  = delete.getFamilyCellMap();
432    RegionCoprocessorEnvironment e = c.getEnvironment();
433    assertNotNull(e);
434    assertNotNull(e.getRegion());
435    assertNotNull(familyMap);
436    ctBeforeDelete.set(0);
437    ctPostDeleted.incrementAndGet();
438  }
439
440  @Override
441  public void preBatchMutate(ObserverContext<RegionCoprocessorEnvironment> c,
442      MiniBatchOperationInProgress<Mutation> miniBatchOp) throws IOException {
443    RegionCoprocessorEnvironment e = c.getEnvironment();
444    assertNotNull(e);
445    assertNotNull(e.getRegion());
446    assertNotNull(miniBatchOp);
447    ctPreBatchMutate.incrementAndGet();
448  }
449
450  @Override
451  public void postBatchMutate(final ObserverContext<RegionCoprocessorEnvironment> c,
452      final MiniBatchOperationInProgress<Mutation> miniBatchOp) throws IOException {
453    RegionCoprocessorEnvironment e = c.getEnvironment();
454    assertNotNull(e);
455    assertNotNull(e.getRegion());
456    assertNotNull(miniBatchOp);
457    ctPostBatchMutate.incrementAndGet();
458  }
459
460  @Override
461  public void postStartRegionOperation(final ObserverContext<RegionCoprocessorEnvironment> ctx,
462      Operation op) throws IOException {
463    ctPostStartRegionOperation.incrementAndGet();
464  }
465
466  @Override
467  public void postCloseRegionOperation(final ObserverContext<RegionCoprocessorEnvironment> ctx,
468      Operation op) throws IOException {
469    if (ctPostStartRegionOperation.get() > 0) {
470      ctPostCloseRegionOperation.incrementAndGet();
471    }
472  }
473
474  @Override
475  public void postBatchMutateIndispensably(final ObserverContext<RegionCoprocessorEnvironment> ctx,
476      MiniBatchOperationInProgress<Mutation> miniBatchOp, final boolean success) throws IOException {
477    ctPostBatchMutateIndispensably.incrementAndGet();
478  }
479
480  @Override
481  public Result preIncrement(final ObserverContext<RegionCoprocessorEnvironment> c,
482      final Increment increment) throws IOException {
483    ctPreIncrement.incrementAndGet();
484    return null;
485  }
486
487  @Override
488  public Result preIncrementAfterRowLock(ObserverContext<RegionCoprocessorEnvironment> e,
489      Increment increment) throws IOException {
490    ctPreIncrementAfterRowLock.incrementAndGet();
491    return null;
492  }
493
494  @Override
495  public Result postIncrement(final ObserverContext<RegionCoprocessorEnvironment> c,
496      final Increment increment, final Result result) throws IOException {
497    ctPostIncrement.incrementAndGet();
498    return result;
499  }
500
501  @Override
502  public boolean preCheckAndPut(ObserverContext<RegionCoprocessorEnvironment> e, byte[] row,
503                                byte[] family, byte[] qualifier, CompareOperator compareOp, ByteArrayComparable comparator,
504                                Put put, boolean result) throws IOException {
505    ctPreCheckAndPut.incrementAndGet();
506    return true;
507  }
508
509  @Override
510  public boolean preCheckAndPut(ObserverContext<RegionCoprocessorEnvironment> c, byte[] row,
511    Filter filter, Put put, boolean result) throws IOException {
512    ctPreCheckAndPutWithFilter.incrementAndGet();
513    return true;
514  }
515
516  @Override
517  public boolean preCheckAndPutAfterRowLock(ObserverContext<RegionCoprocessorEnvironment> e,
518      byte[] row, byte[] family, byte[] qualifier, CompareOperator compareOp,
519      ByteArrayComparable comparator, Put put, boolean result) throws IOException {
520    ctPreCheckAndPutAfterRowLock.incrementAndGet();
521    return true;
522  }
523
524  @Override
525  public boolean preCheckAndPutAfterRowLock(ObserverContext<RegionCoprocessorEnvironment> c,
526    byte[] row, Filter filter, Put put, boolean result) throws IOException {
527    ctPreCheckAndPutWithFilterAfterRowLock.incrementAndGet();
528    return true;
529  }
530
531  @Override
532  public boolean postCheckAndPut(ObserverContext<RegionCoprocessorEnvironment> e, byte[] row,
533                                 byte[] family, byte[] qualifier, CompareOperator compareOp, ByteArrayComparable comparator,
534                                 Put put, boolean result) throws IOException {
535    ctPostCheckAndPut.incrementAndGet();
536    return true;
537  }
538
539  @Override
540  public boolean postCheckAndPut(ObserverContext<RegionCoprocessorEnvironment> c, byte[] row,
541    Filter filter, Put put, boolean result) throws IOException {
542    ctPostCheckAndPutWithFilter.incrementAndGet();
543    return true;
544  }
545
546  @Override
547  public boolean preCheckAndDelete(ObserverContext<RegionCoprocessorEnvironment> e, byte[] row,
548                                   byte[] family, byte[] qualifier, CompareOperator compareOp, ByteArrayComparable comparator,
549                                   Delete delete, boolean result) throws IOException {
550    ctPreCheckAndDelete.incrementAndGet();
551    return true;
552  }
553
554  @Override
555  public boolean preCheckAndDelete(ObserverContext<RegionCoprocessorEnvironment> c, byte[] row,
556    Filter filter, Delete delete, boolean result) throws IOException {
557    ctPreCheckAndDeleteWithFilter.incrementAndGet();
558    return true;
559  }
560
561  @Override
562  public boolean preCheckAndDeleteAfterRowLock(ObserverContext<RegionCoprocessorEnvironment> e,
563      byte[] row, byte[] family, byte[] qualifier, CompareOperator compareOp,
564      ByteArrayComparable comparator, Delete delete, boolean result) throws IOException {
565    ctPreCheckAndDeleteAfterRowLock.incrementAndGet();
566    return true;
567  }
568
569  @Override
570  public boolean preCheckAndDeleteAfterRowLock(ObserverContext<RegionCoprocessorEnvironment> c,
571    byte[] row, Filter filter, Delete delete, boolean result) throws IOException {
572    ctPreCheckAndDeleteWithFilterAfterRowLock.incrementAndGet();
573    return true;
574  }
575
576  @Override
577  public boolean postCheckAndDelete(ObserverContext<RegionCoprocessorEnvironment> e, byte[] row,
578                                    byte[] family, byte[] qualifier, CompareOperator compareOp, ByteArrayComparable comparator,
579                                    Delete delete, boolean result) throws IOException {
580    ctPostCheckAndDelete.incrementAndGet();
581    return true;
582  }
583
584  @Override
585  public boolean postCheckAndDelete(ObserverContext<RegionCoprocessorEnvironment> e, byte[] row,
586    Filter filter, Delete delete, boolean result) throws IOException {
587    ctPostCheckAndDeleteWithFilter.incrementAndGet();
588    return true;
589  }
590
591  @Override
592  public CheckAndMutateResult preCheckAndMutate(ObserverContext<RegionCoprocessorEnvironment> c,
593    CheckAndMutate checkAndMutate, CheckAndMutateResult result) throws IOException {
594    ctPreCheckAndMutate.incrementAndGet();
595    return RegionObserver.super.preCheckAndMutate(c, checkAndMutate, result);
596  }
597
598  @Override
599  public CheckAndMutateResult preCheckAndMutateAfterRowLock(
600    ObserverContext<RegionCoprocessorEnvironment> c, CheckAndMutate checkAndMutate,
601    CheckAndMutateResult result) throws IOException {
602    ctPreCheckAndMutateAfterRowLock.incrementAndGet();
603    return RegionObserver.super.preCheckAndMutateAfterRowLock(c, checkAndMutate, result);
604  }
605
606  @Override
607  public CheckAndMutateResult postCheckAndMutate(ObserverContext<RegionCoprocessorEnvironment> c,
608    CheckAndMutate checkAndMutate, CheckAndMutateResult result) throws IOException {
609    ctPostCheckAndMutate.incrementAndGet();
610    return RegionObserver.super.postCheckAndMutate(c, checkAndMutate, result);
611  }
612
613  @Override
614  public Result preAppendAfterRowLock(ObserverContext<RegionCoprocessorEnvironment> e,
615      Append append) throws IOException {
616    ctPreAppendAfterRowLock.incrementAndGet();
617    return null;
618  }
619
620  @Override
621  public Result preAppend(ObserverContext<RegionCoprocessorEnvironment> e, Append append)
622      throws IOException {
623    ctPreAppend.incrementAndGet();
624    return null;
625  }
626
627  @Override
628  public Result postAppend(ObserverContext<RegionCoprocessorEnvironment> e, Append append,
629      Result result) throws IOException {
630    ctPostAppend.incrementAndGet();
631    return null;
632  }
633
634  @Override
635  public void preBulkLoadHFile(ObserverContext<RegionCoprocessorEnvironment> ctx,
636                               List<Pair<byte[], String>> familyPaths) throws IOException {
637    RegionCoprocessorEnvironment e = ctx.getEnvironment();
638    assertNotNull(e);
639    assertNotNull(e.getRegion());
640    if (e.getRegion().getTableDescriptor().getTableName().equals(
641        TestRegionObserverInterface.TEST_TABLE)) {
642      assertNotNull(familyPaths);
643      assertEquals(1,familyPaths.size());
644      assertArrayEquals(TestRegionObserverInterface.A, familyPaths.get(0).getFirst());
645      String familyPath = familyPaths.get(0).getSecond();
646      String familyName = Bytes.toString(TestRegionObserverInterface.A);
647      assertEquals(familyPath.substring(familyPath.length()-familyName.length()-1),"/"+familyName);
648    }
649    ctPreBulkLoadHFile.incrementAndGet();
650  }
651
652  @Override
653  public void postBulkLoadHFile(ObserverContext<RegionCoprocessorEnvironment> ctx,
654      List<Pair<byte[], String>> familyPaths, Map<byte[], List<Path>> map)
655          throws IOException {
656    RegionCoprocessorEnvironment e = ctx.getEnvironment();
657    assertNotNull(e);
658    assertNotNull(e.getRegion());
659    if (e.getRegion().getTableDescriptor().getTableName().equals(
660        TestRegionObserverInterface.TEST_TABLE)) {
661      assertNotNull(familyPaths);
662      assertEquals(1,familyPaths.size());
663      assertArrayEquals(TestRegionObserverInterface.A, familyPaths.get(0).getFirst());
664      String familyPath = familyPaths.get(0).getSecond();
665      String familyName = Bytes.toString(TestRegionObserverInterface.A);
666      assertEquals(familyPath.substring(familyPath.length()-familyName.length()-1),"/"+familyName);
667    }
668    ctPostBulkLoadHFile.incrementAndGet();
669  }
670
671  @Override
672  public void preReplayWALs(ObserverContext<? extends RegionCoprocessorEnvironment> env,
673      RegionInfo info, Path edits) throws IOException {
674    ctPreReplayWALs.incrementAndGet();
675  }
676
677  @Override
678  public void postReplayWALs(ObserverContext<? extends RegionCoprocessorEnvironment> env,
679      RegionInfo info, Path edits) throws IOException {
680    ctPostReplayWALs.incrementAndGet();
681  }
682
683  @Override
684  public void preWALRestore(ObserverContext<? extends RegionCoprocessorEnvironment> env,
685      RegionInfo info, WALKey logKey, WALEdit logEdit) throws IOException {
686    String tableName = logKey.getTableName().getNameAsString();
687    if (tableName.equals(TABLE_SKIPPED)) {
688      // skip recovery of TABLE_SKIPPED for testing purpose
689      env.bypass();
690      return;
691    }
692    ctPreWALRestore.incrementAndGet();
693  }
694
695  @Override
696  public void postWALRestore(ObserverContext<? extends RegionCoprocessorEnvironment> env,
697                             RegionInfo info, WALKey logKey, WALEdit logEdit) throws IOException {
698    ctPostWALRestore.incrementAndGet();
699  }
700
701  @Override
702  public StoreFileReader preStoreFileReaderOpen(ObserverContext<RegionCoprocessorEnvironment> ctx,
703      FileSystem fs, Path p, FSDataInputStreamWrapper in, long size, CacheConfig cacheConf,
704      Reference r, StoreFileReader reader) throws IOException {
705    ctPreStoreFileReaderOpen.incrementAndGet();
706    return null;
707  }
708
709  @Override
710  public StoreFileReader postStoreFileReaderOpen(ObserverContext<RegionCoprocessorEnvironment> ctx,
711      FileSystem fs, Path p, FSDataInputStreamWrapper in, long size, CacheConfig cacheConf,
712      Reference r, StoreFileReader reader) throws IOException {
713    ctPostStoreFileReaderOpen.incrementAndGet();
714    return reader;
715  }
716
717  @Override
718  public void preStoreScannerOpen(ObserverContext<RegionCoprocessorEnvironment> ctx,
719    Store store, ScanOptions options) throws IOException {
720    if (options.getScan().getTimeRange().isAllTime()) {
721      setScanOptions(options);
722    }
723  }
724
725  @Override
726  public void preCompactScannerOpen(ObserverContext<RegionCoprocessorEnvironment> c, Store store,
727    ScanType scanType, ScanOptions options, CompactionLifeCycleTracker tracker,
728    CompactionRequest request) throws IOException {
729    setScanOptions(options);
730  }
731
732  public void preFlushScannerOpen(ObserverContext<RegionCoprocessorEnvironment> c, Store store,
733    ScanOptions options,FlushLifeCycleTracker tracker) throws IOException {
734    setScanOptions(options);
735  }
736
737  public void preMemStoreCompactionCompactScannerOpen(
738    ObserverContext<RegionCoprocessorEnvironment> c, Store store, ScanOptions options)
739    throws IOException {
740    setScanOptions(options);
741  }
742
743  private void setScanOptions(ScanOptions options) {
744    options.setMaxVersions(TestRegionCoprocessorHost.MAX_VERSIONS);
745    options.setMinVersions(TestRegionCoprocessorHost.MIN_VERSIONS);
746    options.setKeepDeletedCells(KeepDeletedCells.TRUE);
747    options.setTTL(TestRegionCoprocessorHost.TTL);
748  }
749
750
751  @Override
752  public void preWALAppend(ObserverContext<RegionCoprocessorEnvironment> ctx,
753                                 WALKey key, WALEdit edit) throws IOException {
754    ctPreWALAppend.incrementAndGet();
755
756    key.addExtendedAttribute(Integer.toString(ctPreWALAppend.get()),
757        Bytes.toBytes("foo"));
758  }
759
760  public boolean hadPreGet() {
761    return ctPreGet.get() > 0;
762  }
763
764  public boolean hadPostGet() {
765    return ctPostGet.get() > 0;
766  }
767
768  public boolean hadPrePut() {
769    return ctPrePut.get() > 0;
770  }
771
772  public boolean hadPostPut() {
773    return ctPostPut.get() > 0;
774  }
775
776  public boolean hadPreBatchMutate() {
777    return ctPreBatchMutate.get() > 0;
778  }
779
780  public int getPreBatchMutate() {
781    return ctPreBatchMutate.get();
782  }
783
784  public boolean hadPostBatchMutate() {
785    return ctPostBatchMutate.get() > 0;
786  }
787
788  public int getPostBatchMutate() {
789    return ctPostBatchMutate.get();
790  }
791
792  public boolean hadPostBatchMutateIndispensably() {
793    return ctPostBatchMutateIndispensably.get() > 0;
794  }
795
796  public int getPostBatchMutateIndispensably() {
797    return ctPostBatchMutateIndispensably.get();
798  }
799
800  public boolean hadPostStartRegionOperation() {
801    return ctPostStartRegionOperation.get() > 0;
802  }
803
804  public boolean hadPostCloseRegionOperation() {
805    return ctPostCloseRegionOperation.get() > 0;
806  }
807
808  public boolean hadDelete() {
809    return !(ctBeforeDelete.get() > 0);
810  }
811
812  public int getCtPostStartRegionOperation() {
813    return ctPostStartRegionOperation.get();
814  }
815
816  public int getCtPostCloseRegionOperation() {
817    return ctPostCloseRegionOperation.get();
818  }
819
820  public int getPreCheckAndPut() {
821    return ctPreCheckAndPut.get();
822  }
823
824  public int getPreCheckAndPutWithFilter() {
825    return ctPreCheckAndPutWithFilter.get();
826  }
827
828  public int getPreCheckAndPutAfterRowLock() {
829    return ctPreCheckAndPutAfterRowLock.get();
830  }
831
832  public int getPreCheckAndPutWithFilterAfterRowLock() {
833    return ctPreCheckAndPutWithFilterAfterRowLock.get();
834  }
835
836  public int getPostCheckAndPut() {
837    return ctPostCheckAndPut.get();
838  }
839
840  public int getPostCheckAndPutWithFilter() {
841    return ctPostCheckAndPutWithFilter.get();
842  }
843
844  public int getPreCheckAndDelete() {
845    return ctPreCheckAndDelete.get();
846  }
847
848  public int getPreCheckAndDeleteWithFilter() {
849    return ctPreCheckAndDeleteWithFilter.get();
850  }
851
852  public int getPreCheckAndDeleteAfterRowLock() {
853    return ctPreCheckAndDeleteAfterRowLock.get();
854  }
855
856  public int getPreCheckAndDeleteWithFilterAfterRowLock() {
857    return ctPreCheckAndDeleteWithFilterAfterRowLock.get();
858  }
859
860  public int getPostCheckAndDelete() {
861    return ctPostCheckAndDelete.get();
862  }
863
864  public int getPostCheckAndDeleteWithFilter() {
865    return ctPostCheckAndDeleteWithFilter.get();
866  }
867
868  public int getPreCheckAndMutate() {
869    return ctPreCheckAndMutate.get();
870  }
871
872  public int getPreCheckAndMutateAfterRowLock() {
873    return ctPreCheckAndMutateAfterRowLock.get();
874  }
875
876  public int getPostCheckAndMutate() {
877    return ctPostCheckAndMutate.get();
878  }
879
880  public boolean hadPreIncrement() {
881    return ctPreIncrement.get() > 0;
882  }
883
884  public boolean hadPreIncrementAfterRowLock() {
885    return ctPreIncrementAfterRowLock.get() > 0;
886  }
887
888  public boolean hadPostIncrement() {
889    return ctPostIncrement.get() > 0;
890  }
891
892  public boolean hadPreAppend() {
893    return ctPreAppend.get() > 0;
894  }
895
896  public boolean hadPreAppendAfterRowLock() {
897    return ctPreAppendAfterRowLock.get() > 0;
898  }
899
900  public boolean hadPostAppend() {
901    return ctPostAppend.get() > 0;
902  }
903
904  public boolean hadPrePreparedDeleteTS() {
905    return ctPrePrepareDeleteTS.get() > 0;
906  }
907
908  public boolean hadPreReplayWALs() {
909    return ctPreReplayWALs.get() > 0;
910  }
911
912  public boolean hadPostReplayWALs() {
913    return ctPostReplayWALs.get() > 0;
914  }
915
916  public boolean hadPreWALRestore() {
917    return ctPreWALRestore.get() > 0;
918  }
919
920  public boolean hadPostWALRestore() {
921    return ctPostWALRestore.get() > 0;
922  }
923
924  public boolean wasScannerNextCalled() {
925    return ctPreScannerNext.get() > 0 && ctPostScannerNext.get() > 0;
926  }
927  public boolean wasScannerFilterRowCalled() {
928    return ctPostScannerFilterRow.get() > 0;
929  }
930  public boolean wasScannerCloseCalled() {
931    return ctPreScannerClose.get() > 0 && ctPostScannerClose.get() > 0;
932  }
933  public boolean wasScannerOpenCalled() {
934    return ctPreScannerOpen.get() > 0 && ctPostScannerOpen.get() > 0;
935  }
936  public boolean hadDeleted() {
937    return ctPreDeleted.get() > 0 && ctPostDeleted.get() > 0;
938  }
939
940  public boolean hadPostBulkLoadHFile() {
941    return ctPostBulkLoadHFile.get() > 0;
942  }
943
944  public boolean hadPreBulkLoadHFile() {
945    return ctPreBulkLoadHFile.get() > 0;
946  }
947
948
949  public int getCtBeforeDelete() {
950    return ctBeforeDelete.get();
951  }
952
953  public int getCtPreOpen() {
954    return ctPreOpen.get();
955  }
956
957  public int getCtPostOpen() {
958    return ctPostOpen.get();
959  }
960
961  public int getCtPreClose() {
962    return ctPreClose.get();
963  }
964
965  public int getCtPostClose() {
966    return ctPostClose.get();
967  }
968
969  public int getCtPreFlush() {
970    return ctPreFlush.get();
971  }
972
973  public int getCtPostFlush() {
974    return ctPostFlush.get();
975  }
976
977  public int getCtPreCompactSelect() {
978    return ctPreCompactSelect.get();
979  }
980
981  public int getCtPostCompactSelect() {
982    return ctPostCompactSelect.get();
983  }
984
985  public int getCtPreCompact() {
986    return ctPreCompact.get();
987  }
988
989  public int getCtPostCompact() {
990    return ctPostCompact.get();
991  }
992
993  public int getCtPreGet() {
994    return ctPreGet.get();
995  }
996
997  public int getCtPostGet() {
998    return ctPostGet.get();
999  }
1000
1001  public int getCtPrePut() {
1002    return ctPrePut.get();
1003  }
1004
1005  public int getCtPostPut() {
1006    return ctPostPut.get();
1007  }
1008
1009  public int getCtPreDeleted() {
1010    return ctPreDeleted.get();
1011  }
1012
1013  public int getCtPostDeleted() {
1014    return ctPostDeleted.get();
1015  }
1016
1017  public int getCtPreIncrement() {
1018    return ctPreIncrement.get();
1019  }
1020
1021  public int getCtPostIncrement() {
1022    return ctPostIncrement.get();
1023  }
1024
1025  public int getCtPreReplayWALs() {
1026    return ctPreReplayWALs.get();
1027  }
1028
1029  public int getCtPostReplayWALs() {
1030    return ctPostReplayWALs.get();
1031  }
1032
1033  public int getCtPreWALRestore() {
1034    return ctPreWALRestore.get();
1035  }
1036
1037  public int getCtPostWALRestore() {
1038    return ctPostWALRestore.get();
1039  }
1040
1041  public int getCtPreWALAppend() {
1042    return ctPreWALAppend.get();
1043  }
1044
1045  public boolean wasStoreFileReaderOpenCalled() {
1046    return ctPreStoreFileReaderOpen.get() > 0 && ctPostStoreFileReaderOpen.get() > 0;
1047  }
1048}