1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18 package org.apache.hadoop.hbase.regionserver;
19
20 import java.io.IOException;
21 import java.util.Collection;
22 import java.util.List;
23 import java.util.Map;
24
25 import org.apache.hadoop.hbase.Cell;
26 import org.apache.hadoop.hbase.HBaseInterfaceAudience;
27 import org.apache.hadoop.hbase.HDFSBlocksDistribution;
28 import org.apache.hadoop.hbase.HRegionInfo;
29 import org.apache.hadoop.hbase.HTableDescriptor;
30 import org.apache.hadoop.hbase.classification.InterfaceAudience;
31 import org.apache.hadoop.hbase.classification.InterfaceStability;
32 import org.apache.hadoop.hbase.client.Append;
33 import org.apache.hadoop.hbase.client.Delete;
34 import org.apache.hadoop.hbase.client.Get;
35 import org.apache.hadoop.hbase.client.Increment;
36 import org.apache.hadoop.hbase.client.IsolationLevel;
37 import org.apache.hadoop.hbase.client.Mutation;
38 import org.apache.hadoop.hbase.client.Put;
39 import org.apache.hadoop.hbase.client.Result;
40 import org.apache.hadoop.hbase.client.RowMutations;
41 import org.apache.hadoop.hbase.client.Scan;
42 import org.apache.hadoop.hbase.conf.ConfigurationObserver;
43 import org.apache.hadoop.hbase.exceptions.FailedSanityCheckException;
44 import org.apache.hadoop.hbase.filter.ByteArrayComparable;
45 import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
46 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetRegionInfoResponse.CompactionState;
47 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.CoprocessorServiceCall;
48 import org.apache.hadoop.hbase.util.Pair;
49 import org.apache.hadoop.hbase.wal.WALSplitter.MutationReplay;
50
51 import com.google.common.annotations.VisibleForTesting;
52 import com.google.protobuf.Message;
53 import com.google.protobuf.RpcController;
54 import com.google.protobuf.Service;
55
56 /**
57 * Regions store data for a certain region of a table. It stores all columns
58 * for each row. A given table consists of one or more Regions.
59 *
60 * <p>An Region is defined by its table and its key extent.
61 *
62 * <p>Locking at the Region level serves only one purpose: preventing the
63 * region from being closed (and consequently split) while other operations
64 * are ongoing. Each row level operation obtains both a row lock and a region
65 * read lock for the duration of the operation. While a scanner is being
66 * constructed, getScanner holds a read lock. If the scanner is successfully
67 * constructed, it holds a read lock until it is closed. A close takes out a
68 * write lock and consequently will block for ongoing operations and will block
69 * new operations from starting while the close is in progress.
70 */
71 @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.COPROC)
72 @InterfaceStability.Evolving
73 public interface Region extends ConfigurationObserver {
74
75 ///////////////////////////////////////////////////////////////////////////
76 // Region state
77
78 /** @return region information for this region */
79 HRegionInfo getRegionInfo();
80
81 /** @return table descriptor for this region */
82 HTableDescriptor getTableDesc();
83
84 /** @return true if region is available (not closed and not closing) */
85 boolean isAvailable();
86
87 /** @return true if region is closed */
88 boolean isClosed();
89
90 /** @return True if closing process has started */
91 boolean isClosing();
92
93 /** @return True if region is in recovering state */
94 boolean isRecovering();
95
96 /** @return True if region is read only */
97 boolean isReadOnly();
98
99 /**
100 * Return the list of Stores managed by this region
101 * <p>Use with caution. Exposed for use of fixup utilities.
102 * @return a list of the Stores managed by this region
103 */
104 List<Store> getStores();
105
106 /**
107 * Return the Store for the given family
108 * <p>Use with caution. Exposed for use of fixup utilities.
109 * @return the Store for the given family
110 */
111 Store getStore(byte[] family);
112
113 /** @return list of store file names for the given families */
114 List<String> getStoreFileList(byte [][] columns);
115
116 /**
117 * Check the region's underlying store files, open the files that have not
118 * been opened yet, and remove the store file readers for store files no
119 * longer available.
120 * @throws IOException
121 */
122 boolean refreshStoreFiles() throws IOException;
123
124 /** @return the latest sequence number that was read from storage when this region was opened */
125 long getOpenSeqNum();
126
127 /** @return the max sequence id of flushed data on this region; no edit in memory will have
128 * a sequence id that is less that what is returned here.
129 */
130 long getMaxFlushedSeqId();
131
132 /** @return the oldest flushed sequence id for the given family; can be beyond
133 * {@link #getMaxFlushedSeqId()} in case where we've flushed a subset of a regions column
134 * families
135 * @deprecated Since version 1.2.0. Exposes too much about our internals; shutting it down.
136 * Do not use.
137 */
138 @VisibleForTesting
139 @Deprecated
140 public long getOldestSeqIdOfStore(byte[] familyName);
141
142 /**
143 * This can be used to determine the last time all files of this region were major compacted.
144 * @param majorCompactioOnly Only consider HFile that are the result of major compaction
145 * @return the timestamp of the oldest HFile for all stores of this region
146 */
147 long getOldestHfileTs(boolean majorCompactioOnly) throws IOException;
148
149 /**
150 * @return map of column family names to max sequence id that was read from storage when this
151 * region was opened
152 */
153 public Map<byte[], Long> getMaxStoreSeqId();
154
155 /** @return true if loading column families on demand by default */
156 boolean isLoadingCfsOnDemandDefault();
157
158 /** @return readpoint considering given IsolationLevel */
159 long getReadpoint(IsolationLevel isolationLevel);
160
161 /**
162 * @return The earliest time a store in the region was flushed. All
163 * other stores in the region would have been flushed either at, or
164 * after this time.
165 */
166 long getEarliestFlushTimeForAllStores();
167
168 ///////////////////////////////////////////////////////////////////////////
169 // Metrics
170
171 /** @return read requests count for this region */
172 long getReadRequestsCount();
173
174 /**
175 * Update the read request count for this region
176 * @param i increment
177 */
178 void updateReadRequestsCount(long i);
179
180 /** @return write request count for this region */
181 long getWriteRequestsCount();
182
183 /**
184 * Update the write request count for this region
185 * @param i increment
186 */
187 void updateWriteRequestsCount(long i);
188
189 /** @return memstore size for this region, in bytes */
190 long getMemstoreSize();
191
192 /** @return the number of mutations processed bypassing the WAL */
193 long getNumMutationsWithoutWAL();
194
195 /** @return the size of data processed bypassing the WAL, in bytes */
196 long getDataInMemoryWithoutWAL();
197
198 /** @return the number of blocked requests */
199 long getBlockedRequestsCount();
200
201 /** @return the number of checkAndMutate guards that passed */
202 long getCheckAndMutateChecksPassed();
203
204 /** @return the number of failed checkAndMutate guards */
205 long getCheckAndMutateChecksFailed();
206
207 /** @return the MetricsRegion for this region */
208 MetricsRegion getMetrics();
209
210 /** @return the block distribution for all Stores managed by this region */
211 HDFSBlocksDistribution getHDFSBlocksDistribution();
212
213 ///////////////////////////////////////////////////////////////////////////
214 // Locking
215
216 // Region read locks
217
218 /**
219 * Operation enum is used in {@link Region#startRegionOperation} to provide context for
220 * various checks before any region operation begins.
221 */
222 enum Operation {
223 ANY, GET, PUT, DELETE, SCAN, APPEND, INCREMENT, SPLIT_REGION, MERGE_REGION, BATCH_MUTATE,
224 REPLAY_BATCH_MUTATE, COMPACT_REGION, REPLAY_EVENT
225 }
226
227 /**
228 * This method needs to be called before any public call that reads or
229 * modifies data.
230 * Acquires a read lock and checks if the region is closing or closed.
231 * <p>{@link #closeRegionOperation} MUST then always be called after
232 * the operation has completed, whether it succeeded or failed.
233 * @throws IOException
234 */
235 void startRegionOperation() throws IOException;
236
237 /**
238 * This method needs to be called before any public call that reads or
239 * modifies data.
240 * Acquires a read lock and checks if the region is closing or closed.
241 * <p>{@link #closeRegionOperation} MUST then always be called after
242 * the operation has completed, whether it succeeded or failed.
243 * @param op The operation is about to be taken on the region
244 * @throws IOException
245 */
246 void startRegionOperation(Operation op) throws IOException;
247
248 /**
249 * Closes the region operation lock.
250 * @throws IOException
251 */
252 void closeRegionOperation() throws IOException;
253
254 // Row write locks
255
256 /**
257 * Row lock held by a given thread.
258 * One thread may acquire multiple locks on the same row simultaneously.
259 * The locks must be released by calling release() from the same thread.
260 */
261 public interface RowLock {
262 /**
263 * Release the given lock. If there are no remaining locks held by the current thread
264 * then unlock the row and allow other threads to acquire the lock.
265 * @throws IllegalArgumentException if called by a different thread than the lock owning
266 * thread
267 */
268 void release();
269 }
270
271 /**
272 * Tries to acquire a lock on the given row.
273 * @param readlock if true, will block until the lock is available.
274 * Otherwise, just tries to obtain the lock and returns
275 * false if unavailable.
276 * @return the row lock if acquired,
277 * null if waitForLock was false and the lock was not acquired
278 * @throws IOException if waitForLock was true and the lock could not be acquired after waiting
279 */
280 RowLock getRowLock(byte[] row, boolean readlock) throws IOException;
281
282 /**
283 * If the given list of row locks is not null, releases all locks.
284 */
285 void releaseRowLocks(List<RowLock> rowLocks);
286
287 ///////////////////////////////////////////////////////////////////////////
288 // Region operations
289
290 /**
291 * Perform one or more append operations on a row.
292 * @param append
293 * @param nonceGroup
294 * @param nonce
295 * @return result of the operation
296 * @throws IOException
297 */
298 Result append(Append append, long nonceGroup, long nonce) throws IOException;
299
300 /**
301 * Perform a batch of mutations.
302 * <p>
303 * Note this supports only Put and Delete mutations and will ignore other types passed.
304 * @param mutations the list of mutations
305 * @param nonceGroup
306 * @param nonce
307 * @return an array of OperationStatus which internally contains the
308 * OperationStatusCode and the exceptionMessage if any.
309 * @throws IOException
310 */
311 OperationStatus[] batchMutate(Mutation[] mutations, long nonceGroup, long nonce)
312 throws IOException;
313
314 /**
315 * Replay a batch of mutations.
316 * @param mutations mutations to replay.
317 * @param replaySeqId
318 * @return an array of OperationStatus which internally contains the
319 * OperationStatusCode and the exceptionMessage if any.
320 * @throws IOException
321 */
322 OperationStatus[] batchReplay(MutationReplay[] mutations, long replaySeqId) throws IOException;
323
324 /**
325 * Atomically checks if a row/family/qualifier value matches the expected val
326 * If it does, it performs the row mutations. If the passed value is null, t
327 * is for the lack of column (ie: non-existence)
328 * @param row to check
329 * @param family column family to check
330 * @param qualifier column qualifier to check
331 * @param compareOp the comparison operator
332 * @param comparator
333 * @param mutation
334 * @param writeToWAL
335 * @return true if mutation was applied, false otherwise
336 * @throws IOException
337 */
338 boolean checkAndMutate(byte [] row, byte [] family, byte [] qualifier, CompareOp compareOp,
339 ByteArrayComparable comparator, Mutation mutation, boolean writeToWAL) throws IOException;
340
341 /**
342 * Atomically checks if a row/family/qualifier value matches the expected val
343 * If it does, it performs the row mutations. If the passed value is null, t
344 * is for the lack of column (ie: non-existence)
345 * @param row to check
346 * @param family column family to check
347 * @param qualifier column qualifier to check
348 * @param compareOp the comparison operator
349 * @param comparator
350 * @param mutations
351 * @param writeToWAL
352 * @return true if mutation was applied, false otherwise
353 * @throws IOException
354 */
355 boolean checkAndRowMutate(byte [] row, byte [] family, byte [] qualifier, CompareOp compareOp,
356 ByteArrayComparable comparator, RowMutations mutations, boolean writeToWAL)
357 throws IOException;
358
359 /**
360 * Deletes the specified cells/row.
361 * @param delete
362 * @throws IOException
363 */
364 void delete(Delete delete) throws IOException;
365
366 /**
367 * Do a get based on the get parameter.
368 * @param get query parameters
369 * @return result of the operation
370 */
371 Result get(Get get) throws IOException;
372
373 /**
374 * Do a get based on the get parameter.
375 * @param get query parameters
376 * @param withCoprocessor invoke coprocessor or not. We don't want to
377 * always invoke cp.
378 * @return list of cells resulting from the operation
379 */
380 List<Cell> get(Get get, boolean withCoprocessor) throws IOException;
381
382 /**
383 * Return all the data for the row that matches <i>row</i> exactly,
384 * or the one that immediately preceeds it, at or immediately before
385 * <i>ts</i>.
386 * @param row
387 * @param family
388 * @return result of the operation
389 * @throws IOException
390 */
391 Result getClosestRowBefore(byte[] row, byte[] family) throws IOException;
392
393 /**
394 * Return an iterator that scans over the HRegion, returning the indicated
395 * columns and rows specified by the {@link Scan}.
396 * <p>
397 * This Iterator must be closed by the caller.
398 *
399 * @param scan configured {@link Scan}
400 * @return RegionScanner
401 * @throws IOException read exceptions
402 */
403 RegionScanner getScanner(Scan scan) throws IOException;
404
405 /**
406 * Return an iterator that scans over the HRegion, returning the indicated columns and rows
407 * specified by the {@link Scan}. The scanner will also include the additional scanners passed
408 * along with the scanners for the specified Scan instance. Should be careful with the usage to
409 * pass additional scanners only within this Region
410 * <p>
411 * This Iterator must be closed by the caller.
412 *
413 * @param scan configured {@link Scan}
414 * @param additionalScanners Any additional scanners to be used
415 * @return RegionScanner
416 * @throws IOException read exceptions
417 */
418 RegionScanner getScanner(Scan scan, List<KeyValueScanner> additionalScanners) throws IOException;
419
420 /**
421 * Perform one or more increment operations on a row.
422 * @param increment
423 * @param nonceGroup
424 * @param nonce
425 * @return result of the operation
426 * @throws IOException
427 */
428 Result increment(Increment increment, long nonceGroup, long nonce) throws IOException;
429
430 /**
431 * Performs multiple mutations atomically on a single row. Currently
432 * {@link Put} and {@link Delete} are supported.
433 *
434 * @param mutations object that specifies the set of mutations to perform atomically
435 * @throws IOException
436 */
437 void mutateRow(RowMutations mutations) throws IOException;
438
439 /**
440 * Perform atomic mutations within the region.
441 *
442 * @param mutations The list of mutations to perform.
443 * <code>mutations</code> can contain operations for multiple rows.
444 * Caller has to ensure that all rows are contained in this region.
445 * @param rowsToLock Rows to lock
446 * @param nonceGroup Optional nonce group of the operation (client Id)
447 * @param nonce Optional nonce of the operation (unique random id to ensure "more idempotence")
448 * If multiple rows are locked care should be taken that
449 * <code>rowsToLock</code> is sorted in order to avoid deadlocks.
450 * @throws IOException
451 */
452 void mutateRowsWithLocks(Collection<Mutation> mutations, Collection<byte[]> rowsToLock,
453 long nonceGroup, long nonce) throws IOException;
454
455 /**
456 * Performs atomic multiple reads and writes on a given row.
457 *
458 * @param processor The object defines the reads and writes to a row.
459 */
460 void processRowsWithLocks(RowProcessor<?,?> processor) throws IOException;
461
462 /**
463 * Performs atomic multiple reads and writes on a given row.
464 *
465 * @param processor The object defines the reads and writes to a row.
466 * @param nonceGroup Optional nonce group of the operation (client Id)
467 * @param nonce Optional nonce of the operation (unique random id to ensure "more idempotence")
468 */
469 void processRowsWithLocks(RowProcessor<?,?> processor, long nonceGroup, long nonce)
470 throws IOException;
471
472 /**
473 * Performs atomic multiple reads and writes on a given row.
474 *
475 * @param processor The object defines the reads and writes to a row.
476 * @param timeout The timeout of the processor.process() execution
477 * Use a negative number to switch off the time bound
478 * @param nonceGroup Optional nonce group of the operation (client Id)
479 * @param nonce Optional nonce of the operation (unique random id to ensure "more idempotence")
480 */
481 void processRowsWithLocks(RowProcessor<?,?> processor, long timeout, long nonceGroup, long nonce)
482 throws IOException;
483
484 /**
485 * Puts some data in the table.
486 * @param put
487 * @throws IOException
488 */
489 void put(Put put) throws IOException;
490
491 /**
492 * Listener class to enable callers of
493 * bulkLoadHFile() to perform any necessary
494 * pre/post processing of a given bulkload call
495 */
496 interface BulkLoadListener {
497
498 /**
499 * Called before an HFile is actually loaded
500 * @param family family being loaded to
501 * @param srcPath path of HFile
502 * @return final path to be used for actual loading
503 * @throws IOException
504 */
505 String prepareBulkLoad(byte[] family, String srcPath) throws IOException;
506
507 /**
508 * Called after a successful HFile load
509 * @param family family being loaded to
510 * @param srcPath path of HFile
511 * @throws IOException
512 */
513 void doneBulkLoad(byte[] family, String srcPath) throws IOException;
514
515 /**
516 * Called after a failed HFile load
517 * @param family family being loaded to
518 * @param srcPath path of HFile
519 * @throws IOException
520 */
521 void failedBulkLoad(byte[] family, String srcPath) throws IOException;
522 }
523
524 /**
525 * Attempts to atomically load a group of hfiles. This is critical for loading
526 * rows with multiple column families atomically.
527 *
528 * @param familyPaths List of Pair<byte[] column family, String hfilePath>
529 * @param bulkLoadListener Internal hooks enabling massaging/preparation of a
530 * file about to be bulk loaded
531 * @param assignSeqId
532 * @return true if successful, false if failed recoverably
533 * @throws IOException if failed unrecoverably.
534 */
535 boolean bulkLoadHFiles(Collection<Pair<byte[], String>> familyPaths, boolean assignSeqId,
536 BulkLoadListener bulkLoadListener) throws IOException;
537
538 ///////////////////////////////////////////////////////////////////////////
539 // Coprocessors
540
541 /** @return the coprocessor host */
542 RegionCoprocessorHost getCoprocessorHost();
543
544 /**
545 * Executes a single protocol buffer coprocessor endpoint {@link Service} method using
546 * the registered protocol handlers. {@link Service} implementations must be registered via the
547 * {@link Region#registerService(com.google.protobuf.Service)}
548 * method before they are available.
549 *
550 * @param controller an {@code RpcContoller} implementation to pass to the invoked service
551 * @param call a {@code CoprocessorServiceCall} instance identifying the service, method,
552 * and parameters for the method invocation
553 * @return a protocol buffer {@code Message} instance containing the method's result
554 * @throws IOException if no registered service handler is found or an error
555 * occurs during the invocation
556 * @see org.apache.hadoop.hbase.regionserver.Region#registerService(com.google.protobuf.Service)
557 */
558 Message execService(RpcController controller, CoprocessorServiceCall call) throws IOException;
559
560 /**
561 * Registers a new protocol buffer {@link Service} subclass as a coprocessor endpoint to
562 * be available for handling
563 * {@link Region#execService(com.google.protobuf.RpcController,
564 * org.apache.hadoop.hbase.protobuf.generated.ClientProtos.CoprocessorServiceCall)}} calls.
565 *
566 * <p>
567 * Only a single instance may be registered per region for a given {@link Service} subclass (the
568 * instances are keyed on {@link com.google.protobuf.Descriptors.ServiceDescriptor#getFullName()}.
569 * After the first registration, subsequent calls with the same service name will fail with
570 * a return value of {@code false}.
571 * </p>
572 * @param instance the {@code Service} subclass instance to expose as a coprocessor endpoint
573 * @return {@code true} if the registration was successful, {@code false}
574 * otherwise
575 */
576 boolean registerService(Service instance);
577
578 ///////////////////////////////////////////////////////////////////////////
579 // RowMutation processor support
580
581 /**
582 * Check the collection of families for validity.
583 * @param families
584 * @throws NoSuchColumnFamilyException
585 */
586 void checkFamilies(Collection<byte[]> families) throws NoSuchColumnFamilyException;
587
588 /**
589 * Check the collection of families for valid timestamps
590 * @param familyMap
591 * @param now current timestamp
592 * @throws FailedSanityCheckException
593 */
594 void checkTimestamps(Map<byte[], List<Cell>> familyMap, long now)
595 throws FailedSanityCheckException;
596
597 /**
598 * Prepare a delete for a row mutation processor
599 * @param delete The passed delete is modified by this method. WARNING!
600 * @throws IOException
601 */
602 void prepareDelete(Delete delete) throws IOException;
603
604 /**
605 * Set up correct timestamps in the KVs in Delete object.
606 * <p>Caller should have the row and region locks.
607 * @param mutation
608 * @param familyCellMap
609 * @param now
610 * @throws IOException
611 */
612 void prepareDeleteTimestamps(Mutation mutation, Map<byte[], List<Cell>> familyCellMap,
613 byte[] now) throws IOException;
614
615 /**
616 * Replace any cell timestamps set to HConstants#LATEST_TIMESTAMP with the
617 * provided current timestamp.
618 * @param values
619 * @param now
620 */
621 void updateCellTimestamps(final Iterable<List<Cell>> values, final byte[] now)
622 throws IOException;
623
624 ///////////////////////////////////////////////////////////////////////////
625 // Flushes, compactions, splits, etc.
626 // Wizards only, please
627
628 interface FlushResult {
629 enum Result {
630 FLUSHED_NO_COMPACTION_NEEDED,
631 FLUSHED_COMPACTION_NEEDED,
632 // Special case where a flush didn't run because there's nothing in the memstores. Used when
633 // bulk loading to know when we can still load even if a flush didn't happen.
634 CANNOT_FLUSH_MEMSTORE_EMPTY,
635 CANNOT_FLUSH
636 }
637
638 /** @return the detailed result code */
639 Result getResult();
640
641 /** @return true if the memstores were flushed, else false */
642 boolean isFlushSucceeded();
643
644 /** @return True if the flush requested a compaction, else false */
645 boolean isCompactionNeeded();
646 }
647
648 /**
649 * Flush the cache.
650 *
651 * <p>When this method is called the cache will be flushed unless:
652 * <ol>
653 * <li>the cache is empty</li>
654 * <li>the region is closed.</li>
655 * <li>a flush is already in progress</li>
656 * <li>writes are disabled</li>
657 * </ol>
658 *
659 * <p>This method may block for some time, so it should not be called from a
660 * time-sensitive thread.
661 * @param force whether we want to force a flush of all stores
662 * @return FlushResult indicating whether the flush was successful or not and if
663 * the region needs compacting
664 *
665 * @throws IOException general io exceptions
666 * because a snapshot was not properly persisted.
667 */
668 FlushResult flush(boolean force) throws IOException;
669
670 /**
671 * Synchronously compact all stores in the region.
672 * <p>This operation could block for a long time, so don't call it from a
673 * time-sensitive thread.
674 * <p>Note that no locks are taken to prevent possible conflicts between
675 * compaction and splitting activities. The regionserver does not normally compact
676 * and split in parallel. However by calling this method you may introduce
677 * unexpected and unhandled concurrency. Don't do this unless you know what
678 * you are doing.
679 *
680 * @param majorCompaction True to force a major compaction regardless of thresholds
681 * @throws IOException
682 */
683 void compact(final boolean majorCompaction) throws IOException;
684
685 /**
686 * Trigger major compaction on all stores in the region.
687 * <p>
688 * Compaction will be performed asynchronously to this call by the RegionServer's
689 * CompactSplitThread. See also {@link Store#triggerMajorCompaction()}
690 * @throws IOException
691 */
692 void triggerMajorCompaction() throws IOException;
693
694 /**
695 * @return if a given region is in compaction now.
696 */
697 CompactionState getCompactionState();
698
699 /** Wait for all current flushes and compactions of the region to complete */
700 void waitForFlushesAndCompactions();
701
702 }