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