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