View Javadoc

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 majorCompactionOnly 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 majorCompactionOnly) 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, SNAPSHOT
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   /**
255    * Closes the region operation lock. This needs to be called in the finally block corresponding
256    * to the try block of {@link #startRegionOperation(Operation)}
257    * @throws IOException
258    */
259   void closeRegionOperation(Operation op) throws IOException;
260 
261   // Row write locks
262 
263   /**
264    * Row lock held by a given thread.
265    * One thread may acquire multiple locks on the same row simultaneously.
266    * The locks must be released by calling release() from the same thread.
267    */
268   public interface RowLock {
269     /**
270      * Release the given lock.  If there are no remaining locks held by the current thread
271      * then unlock the row and allow other threads to acquire the lock.
272      * @throws IllegalArgumentException if called by a different thread than the lock owning
273      *     thread
274      */
275     void release();
276   }
277 
278   /**
279    *
280    * Get a row lock for the specified row. All locks are reentrant.
281    *
282    * Before calling this function make sure that a region operation has already been
283    * started (the calling thread has already acquired the region-close-guard lock).
284    * 
285    * NOTE: the boolean passed here has changed. It used to be a boolean that
286    * stated whether or not to wait on the lock. Now it is whether it an exclusive
287    * lock is requested.
288    * 
289    * @param row The row actions will be performed against
290    * @param readLock is the lock reader or writer. True indicates that a non-exclusive
291    * lock is requested
292    * @see #startRegionOperation()
293    * @see #startRegionOperation(Operation)
294    */
295   RowLock getRowLock(byte[] row, boolean readLock) throws IOException;
296 
297   /**
298    * If the given list of row locks is not null, releases all locks.
299    */
300   void releaseRowLocks(List<RowLock> rowLocks);
301 
302   ///////////////////////////////////////////////////////////////////////////
303   // Region operations
304 
305   /**
306    * Perform one or more append operations on a row.
307    * @param append
308    * @param nonceGroup
309    * @param nonce
310    * @return result of the operation
311    * @throws IOException
312    */
313   Result append(Append append, long nonceGroup, long nonce) throws IOException;
314 
315   /**
316    * Perform a batch of mutations.
317    * <p>
318    * Note this supports only Put and Delete mutations and will ignore other types passed.
319    * @param mutations the list of mutations
320    * @param nonceGroup
321    * @param nonce
322    * @return an array of OperationStatus which internally contains the
323    *         OperationStatusCode and the exceptionMessage if any.
324    * @throws IOException
325    */
326   OperationStatus[] batchMutate(Mutation[] mutations, long nonceGroup, long nonce)
327       throws IOException;
328 
329   /**
330    * Replay a batch of mutations.
331    * @param mutations mutations to replay.
332    * @param replaySeqId
333    * @return an array of OperationStatus which internally contains the
334    *         OperationStatusCode and the exceptionMessage if any.
335    * @throws IOException
336    */
337    OperationStatus[] batchReplay(MutationReplay[] mutations, long replaySeqId) throws IOException;
338 
339   /**
340    * Atomically checks if a row/family/qualifier value matches the expected val
341    * If it does, it performs the row mutations.  If the passed value is null, t
342    * is for the lack of column (ie: non-existence)
343    * @param row to check
344    * @param family column family to check
345    * @param qualifier column qualifier to check
346    * @param compareOp the comparison operator
347    * @param comparator
348    * @param mutation
349    * @param writeToWAL
350    * @return true if mutation was applied, false otherwise
351    * @throws IOException
352    */
353   boolean checkAndMutate(byte [] row, byte [] family, byte [] qualifier, CompareOp compareOp,
354       ByteArrayComparable comparator, Mutation mutation, boolean writeToWAL) throws IOException;
355 
356   /**
357    * Atomically checks if a row/family/qualifier value matches the expected val
358    * If it does, it performs the row mutations.  If the passed value is null, t
359    * is for the lack of column (ie: non-existence)
360    * @param row to check
361    * @param family column family to check
362    * @param qualifier column qualifier to check
363    * @param compareOp the comparison operator
364    * @param comparator
365    * @param mutations
366    * @param writeToWAL
367    * @return true if mutation was applied, false otherwise
368    * @throws IOException
369    */
370   boolean checkAndRowMutate(byte [] row, byte [] family, byte [] qualifier, CompareOp compareOp,
371       ByteArrayComparable comparator, RowMutations mutations, boolean writeToWAL)
372       throws IOException;
373 
374   /**
375    * Deletes the specified cells/row.
376    * @param delete
377    * @throws IOException
378    */
379   void delete(Delete delete) throws IOException;
380 
381   /**
382    * Do a get based on the get parameter.
383    * @param get query parameters
384    * @return result of the operation
385    */
386   Result get(Get get) throws IOException;
387 
388   /**
389    * Do a get based on the get parameter.
390    * @param get query parameters
391    * @param withCoprocessor invoke coprocessor or not. We don't want to
392    * always invoke cp.
393    * @return list of cells resulting from the operation
394    */
395   List<Cell> get(Get get, boolean withCoprocessor) throws IOException;
396 
397   /**
398    * Do a get for duplicate non-idempotent operation.
399    * @param get query parameters.
400    * @param withCoprocessor
401    * @param nonceGroup Nonce group.
402    * @param nonce Nonce.
403    * @return list of cells resulting from the operation
404    * @throws IOException
405    */
406   List<Cell> get(Get get, boolean withCoprocessor, long nonceGroup, long nonce) throws IOException;
407 
408   /**
409    * Return all the data for the row that matches <i>row</i> exactly,
410    * or the one that immediately preceeds it, at or immediately before
411    * <i>ts</i>.
412    * @param row
413    * @param family
414    * @return result of the operation
415    * @throws IOException
416    */
417   Result getClosestRowBefore(byte[] row, byte[] family) throws IOException;
418 
419   /**
420    * Return an iterator that scans over the HRegion, returning the indicated
421    * columns and rows specified by the {@link Scan}.
422    * <p>
423    * This Iterator must be closed by the caller.
424    *
425    * @param scan configured {@link Scan}
426    * @return RegionScanner
427    * @throws IOException read exceptions
428    */
429   RegionScanner getScanner(Scan scan) throws IOException;
430 
431   /**
432    * Return an iterator that scans over the HRegion, returning the indicated columns and rows
433    * specified by the {@link Scan}. The scanner will also include the additional scanners passed
434    * along with the scanners for the specified Scan instance. Should be careful with the usage to
435    * pass additional scanners only within this Region
436    * <p>
437    * This Iterator must be closed by the caller.
438    *
439    * @param scan configured {@link Scan}
440    * @param additionalScanners Any additional scanners to be used
441    * @return RegionScanner
442    * @throws IOException read exceptions
443    */
444   RegionScanner getScanner(Scan scan, List<KeyValueScanner> additionalScanners) throws IOException;
445 
446   /**
447    * Perform one or more increment operations on a row.
448    * @param increment
449    * @param nonceGroup
450    * @param nonce
451    * @return result of the operation
452    * @throws IOException
453    */
454   Result increment(Increment increment, long nonceGroup, long nonce) throws IOException;
455 
456   /**
457    * Performs multiple mutations atomically on a single row. Currently
458    * {@link Put} and {@link Delete} are supported.
459    *
460    * @param mutations object that specifies the set of mutations to perform atomically
461    * @throws IOException
462    */
463   void mutateRow(RowMutations mutations) throws IOException;
464 
465   /**
466    * Perform atomic mutations within the region.
467    *
468    * @param mutations The list of mutations to perform.
469    * <code>mutations</code> can contain operations for multiple rows.
470    * Caller has to ensure that all rows are contained in this region.
471    * @param rowsToLock Rows to lock
472    * @param nonceGroup Optional nonce group of the operation (client Id)
473    * @param nonce Optional nonce of the operation (unique random id to ensure "more idempotence")
474    * If multiple rows are locked care should be taken that
475    * <code>rowsToLock</code> is sorted in order to avoid deadlocks.
476    * @throws IOException
477    */
478   void mutateRowsWithLocks(Collection<Mutation> mutations, Collection<byte[]> rowsToLock,
479       long nonceGroup, long nonce) throws IOException;
480 
481   /**
482    * Performs atomic multiple reads and writes on a given row.
483    *
484    * @param processor The object defines the reads and writes to a row.
485    */
486   void processRowsWithLocks(RowProcessor<?,?> processor) throws IOException;
487 
488   /**
489    * Performs atomic multiple reads and writes on a given row.
490    *
491    * @param processor The object defines the reads and writes to a row.
492    * @param nonceGroup Optional nonce group of the operation (client Id)
493    * @param nonce Optional nonce of the operation (unique random id to ensure "more idempotence")
494    */
495   void processRowsWithLocks(RowProcessor<?,?> processor, long nonceGroup, long nonce)
496       throws IOException;
497 
498   /**
499    * Performs atomic multiple reads and writes on a given row.
500    *
501    * @param processor The object defines the reads and writes to a row.
502    * @param timeout The timeout of the processor.process() execution
503    *                Use a negative number to switch off the time bound
504    * @param nonceGroup Optional nonce group of the operation (client Id)
505    * @param nonce Optional nonce of the operation (unique random id to ensure "more idempotence")
506    */
507   void processRowsWithLocks(RowProcessor<?,?> processor, long timeout, long nonceGroup, long nonce)
508       throws IOException;
509 
510   /**
511    * Puts some data in the table.
512    * @param put
513    * @throws IOException
514    */
515   void put(Put put) throws IOException;
516 
517   /**
518    * Listener class to enable callers of
519    * bulkLoadHFile() to perform any necessary
520    * pre/post processing of a given bulkload call
521    */
522   interface BulkLoadListener {
523 
524     /**
525      * Called before an HFile is actually loaded
526      * @param family family being loaded to
527      * @param srcPath path of HFile
528      * @return final path to be used for actual loading
529      * @throws IOException
530      */
531     String prepareBulkLoad(byte[] family, String srcPath) throws IOException;
532 
533     /**
534      * Called after a successful HFile load
535      * @param family family being loaded to
536      * @param srcPath path of HFile
537      * @throws IOException
538      */
539     void doneBulkLoad(byte[] family, String srcPath) throws IOException;
540 
541     /**
542      * Called after a failed HFile load
543      * @param family family being loaded to
544      * @param srcPath path of HFile
545      * @throws IOException
546      */
547     void failedBulkLoad(byte[] family, String srcPath) throws IOException;
548   }
549 
550   /**
551    * Attempts to atomically load a group of hfiles.  This is critical for loading
552    * rows with multiple column families atomically.
553    *
554    * @param familyPaths List of Pair&lt;byte[] column family, String hfilePath&gt;
555    * @param bulkLoadListener Internal hooks enabling massaging/preparation of a
556    * file about to be bulk loaded
557    * @param assignSeqId
558    * @return true if successful, false if failed recoverably
559    * @throws IOException if failed unrecoverably.
560    */
561   boolean bulkLoadHFiles(Collection<Pair<byte[], String>> familyPaths, boolean assignSeqId,
562       BulkLoadListener bulkLoadListener) throws IOException;
563 
564   ///////////////////////////////////////////////////////////////////////////
565   // Coprocessors
566 
567   /** @return the coprocessor host */
568   RegionCoprocessorHost getCoprocessorHost();
569 
570   /**
571    * Executes a single protocol buffer coprocessor endpoint {@link Service} method using
572    * the registered protocol handlers.  {@link Service} implementations must be registered via the
573    * {@link Region#registerService(com.google.protobuf.Service)}
574    * method before they are available.
575    *
576    * @param controller an {@code RpcContoller} implementation to pass to the invoked service
577    * @param call a {@code CoprocessorServiceCall} instance identifying the service, method,
578    *     and parameters for the method invocation
579    * @return a protocol buffer {@code Message} instance containing the method's result
580    * @throws IOException if no registered service handler is found or an error
581    *     occurs during the invocation
582    * @see org.apache.hadoop.hbase.regionserver.Region#registerService(com.google.protobuf.Service)
583    */
584   Message execService(RpcController controller, CoprocessorServiceCall call) throws IOException;
585 
586   /**
587    * Registers a new protocol buffer {@link Service} subclass as a coprocessor endpoint to
588    * be available for handling
589    * {@link Region#execService(com.google.protobuf.RpcController,
590    *    org.apache.hadoop.hbase.protobuf.generated.ClientProtos.CoprocessorServiceCall)}} calls.
591    *
592    * <p>
593    * Only a single instance may be registered per region for a given {@link Service} subclass (the
594    * instances are keyed on {@link com.google.protobuf.Descriptors.ServiceDescriptor#getFullName()}.
595    * After the first registration, subsequent calls with the same service name will fail with
596    * a return value of {@code false}.
597    * </p>
598    * @param instance the {@code Service} subclass instance to expose as a coprocessor endpoint
599    * @return {@code true} if the registration was successful, {@code false}
600    * otherwise
601    */
602   boolean registerService(Service instance);
603 
604   ///////////////////////////////////////////////////////////////////////////
605   // RowMutation processor support
606 
607   /**
608    * Check the collection of families for validity.
609    * @param families
610    * @throws NoSuchColumnFamilyException
611    */
612   void checkFamilies(Collection<byte[]> families) throws NoSuchColumnFamilyException;
613 
614   /**
615    * Check the collection of families for valid timestamps
616    * @param familyMap
617    * @param now current timestamp
618    * @throws FailedSanityCheckException
619    */
620   void checkTimestamps(Map<byte[], List<Cell>> familyMap, long now)
621       throws FailedSanityCheckException;
622 
623   /**
624    * Prepare a delete for a row mutation processor
625    * @param delete The passed delete is modified by this method. WARNING!
626    * @throws IOException
627    */
628   void prepareDelete(Delete delete) throws IOException;
629 
630   /**
631    * Set up correct timestamps in the KVs in Delete object.
632    * <p>Caller should have the row and region locks.
633    * @param mutation
634    * @param familyCellMap
635    * @param now
636    * @throws IOException
637    */
638   void prepareDeleteTimestamps(Mutation mutation, Map<byte[], List<Cell>> familyCellMap,
639       byte[] now) throws IOException;
640 
641   /**
642    * Replace any cell timestamps set to HConstants#LATEST_TIMESTAMP with the
643    * provided current timestamp.
644    * @param values
645    * @param now
646    */
647   void updateCellTimestamps(final Iterable<List<Cell>> values, final byte[] now)
648       throws IOException;
649 
650   ///////////////////////////////////////////////////////////////////////////
651   // Flushes, compactions, splits, etc.
652   // Wizards only, please
653 
654   interface FlushResult {
655     enum Result {
656       FLUSHED_NO_COMPACTION_NEEDED,
657       FLUSHED_COMPACTION_NEEDED,
658       // Special case where a flush didn't run because there's nothing in the memstores. Used when
659       // bulk loading to know when we can still load even if a flush didn't happen.
660       CANNOT_FLUSH_MEMSTORE_EMPTY,
661       CANNOT_FLUSH
662     }
663 
664     /** @return the detailed result code */
665     Result getResult();
666 
667     /** @return true if the memstores were flushed, else false */
668     boolean isFlushSucceeded();
669 
670     /** @return True if the flush requested a compaction, else false */
671     boolean isCompactionNeeded();
672   }
673 
674   /**
675    * Flush the cache.
676    *
677    * <p>When this method is called the cache will be flushed unless:
678    * <ol>
679    *   <li>the cache is empty</li>
680    *   <li>the region is closed.</li>
681    *   <li>a flush is already in progress</li>
682    *   <li>writes are disabled</li>
683    * </ol>
684    *
685    * <p>This method may block for some time, so it should not be called from a
686    * time-sensitive thread.
687    * @param force whether we want to force a flush of all stores
688    * @return FlushResult indicating whether the flush was successful or not and if
689    * the region needs compacting
690    *
691    * @throws IOException general io exceptions
692    * because a snapshot was not properly persisted.
693    */
694   FlushResult flush(boolean force) throws IOException;
695 
696   /**
697    * Synchronously compact all stores in the region.
698    * <p>This operation could block for a long time, so don't call it from a
699    * time-sensitive thread.
700    * <p>Note that no locks are taken to prevent possible conflicts between
701    * compaction and splitting activities. The regionserver does not normally compact
702    * and split in parallel. However by calling this method you may introduce
703    * unexpected and unhandled concurrency. Don't do this unless you know what
704    * you are doing.
705    *
706    * @param majorCompaction True to force a major compaction regardless of thresholds
707    * @throws IOException
708    */
709   void compact(final boolean majorCompaction) throws IOException;
710 
711   /**
712    * Trigger major compaction on all stores in the region.
713    * <p>
714    * Compaction will be performed asynchronously to this call by the RegionServer's
715    * CompactSplitThread. See also {@link Store#triggerMajorCompaction()}
716    * @throws IOException
717    */
718   void triggerMajorCompaction() throws IOException;
719 
720   /**
721    * @return if a given region is in compaction now.
722    */
723   CompactionState getCompactionState();
724 
725   /** Wait for all current flushes and compactions of the region to complete */
726   void waitForFlushesAndCompactions();
727 
728   /** Wait for all current flushes of the region to complete
729    */
730   void waitForFlushes();
731 }