| <!DOCTYPE HTML> | 
 | <html lang="en"> | 
 | <head> | 
 | <!-- Generated by javadoc (17) --> | 
 | <title>Source code</title> | 
 | <meta name="viewport" content="width=device-width, initial-scale=1"> | 
 | <meta name="description" content="source: package: org.apache.hadoop.hbase.regionserver, class: HRegion"> | 
 | <meta name="generator" content="javadoc/SourceToHTMLConverter"> | 
 | <link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style"> | 
 | </head> | 
 | <body class="source-page"> | 
 | <main role="main"> | 
 | <div class="source-container"> | 
 | <pre><span class="source-line-no">001</span><span id="line-1">/*</span> | 
 | <span class="source-line-no">002</span><span id="line-2"> * Licensed to the Apache Software Foundation (ASF) under one</span> | 
 | <span class="source-line-no">003</span><span id="line-3"> * or more contributor license agreements.  See the NOTICE file</span> | 
 | <span class="source-line-no">004</span><span id="line-4"> * distributed with this work for additional information</span> | 
 | <span class="source-line-no">005</span><span id="line-5"> * regarding copyright ownership.  The ASF licenses this file</span> | 
 | <span class="source-line-no">006</span><span id="line-6"> * to you under the Apache License, Version 2.0 (the</span> | 
 | <span class="source-line-no">007</span><span id="line-7"> * "License"); you may not use this file except in compliance</span> | 
 | <span class="source-line-no">008</span><span id="line-8"> * with the License.  You may obtain a copy of the License at</span> | 
 | <span class="source-line-no">009</span><span id="line-9"> *</span> | 
 | <span class="source-line-no">010</span><span id="line-10"> *     http://www.apache.org/licenses/LICENSE-2.0</span> | 
 | <span class="source-line-no">011</span><span id="line-11"> *</span> | 
 | <span class="source-line-no">012</span><span id="line-12"> * Unless required by applicable law or agreed to in writing, software</span> | 
 | <span class="source-line-no">013</span><span id="line-13"> * distributed under the License is distributed on an "AS IS" BASIS,</span> | 
 | <span class="source-line-no">014</span><span id="line-14"> * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span> | 
 | <span class="source-line-no">015</span><span id="line-15"> * See the License for the specific language governing permissions and</span> | 
 | <span class="source-line-no">016</span><span id="line-16"> * limitations under the License.</span> | 
 | <span class="source-line-no">017</span><span id="line-17"> */</span> | 
 | <span class="source-line-no">018</span><span id="line-18">package org.apache.hadoop.hbase.regionserver;</span> | 
 | <span class="source-line-no">019</span><span id="line-19"></span> | 
 | <span class="source-line-no">020</span><span id="line-20">import static org.apache.hadoop.hbase.HConstants.REPLICATION_SCOPE_LOCAL;</span> | 
 | <span class="source-line-no">021</span><span id="line-21">import static org.apache.hadoop.hbase.regionserver.HStoreFile.MAJOR_COMPACTION_KEY;</span> | 
 | <span class="source-line-no">022</span><span id="line-22">import static org.apache.hadoop.hbase.trace.HBaseSemanticAttributes.REGION_NAMES_KEY;</span> | 
 | <span class="source-line-no">023</span><span id="line-23">import static org.apache.hadoop.hbase.trace.HBaseSemanticAttributes.ROW_LOCK_READ_LOCK_KEY;</span> | 
 | <span class="source-line-no">024</span><span id="line-24">import static org.apache.hadoop.hbase.util.ConcurrentMapUtils.computeIfAbsent;</span> | 
 | <span class="source-line-no">025</span><span id="line-25"></span> | 
 | <span class="source-line-no">026</span><span id="line-26">import com.google.errorprone.annotations.RestrictedApi;</span> | 
 | <span class="source-line-no">027</span><span id="line-27">import edu.umd.cs.findbugs.annotations.Nullable;</span> | 
 | <span class="source-line-no">028</span><span id="line-28">import io.opentelemetry.api.trace.Span;</span> | 
 | <span class="source-line-no">029</span><span id="line-29">import java.io.EOFException;</span> | 
 | <span class="source-line-no">030</span><span id="line-30">import java.io.FileNotFoundException;</span> | 
 | <span class="source-line-no">031</span><span id="line-31">import java.io.IOException;</span> | 
 | <span class="source-line-no">032</span><span id="line-32">import java.io.InterruptedIOException;</span> | 
 | <span class="source-line-no">033</span><span id="line-33">import java.lang.reflect.Constructor;</span> | 
 | <span class="source-line-no">034</span><span id="line-34">import java.nio.ByteBuffer;</span> | 
 | <span class="source-line-no">035</span><span id="line-35">import java.nio.charset.StandardCharsets;</span> | 
 | <span class="source-line-no">036</span><span id="line-36">import java.text.ParseException;</span> | 
 | <span class="source-line-no">037</span><span id="line-37">import java.util.ArrayList;</span> | 
 | <span class="source-line-no">038</span><span id="line-38">import java.util.Arrays;</span> | 
 | <span class="source-line-no">039</span><span id="line-39">import java.util.Collection;</span> | 
 | <span class="source-line-no">040</span><span id="line-40">import java.util.Collections;</span> | 
 | <span class="source-line-no">041</span><span id="line-41">import java.util.HashMap;</span> | 
 | <span class="source-line-no">042</span><span id="line-42">import java.util.HashSet;</span> | 
 | <span class="source-line-no">043</span><span id="line-43">import java.util.Iterator;</span> | 
 | <span class="source-line-no">044</span><span id="line-44">import java.util.List;</span> | 
 | <span class="source-line-no">045</span><span id="line-45">import java.util.Map;</span> | 
 | <span class="source-line-no">046</span><span id="line-46">import java.util.Map.Entry;</span> | 
 | <span class="source-line-no">047</span><span id="line-47">import java.util.NavigableMap;</span> | 
 | <span class="source-line-no">048</span><span id="line-48">import java.util.NavigableSet;</span> | 
 | <span class="source-line-no">049</span><span id="line-49">import java.util.Objects;</span> | 
 | <span class="source-line-no">050</span><span id="line-50">import java.util.Optional;</span> | 
 | <span class="source-line-no">051</span><span id="line-51">import java.util.RandomAccess;</span> | 
 | <span class="source-line-no">052</span><span id="line-52">import java.util.Set;</span> | 
 | <span class="source-line-no">053</span><span id="line-53">import java.util.TreeMap;</span> | 
 | <span class="source-line-no">054</span><span id="line-54">import java.util.UUID;</span> | 
 | <span class="source-line-no">055</span><span id="line-55">import java.util.concurrent.Callable;</span> | 
 | <span class="source-line-no">056</span><span id="line-56">import java.util.concurrent.CompletionService;</span> | 
 | <span class="source-line-no">057</span><span id="line-57">import java.util.concurrent.ConcurrentHashMap;</span> | 
 | <span class="source-line-no">058</span><span id="line-58">import java.util.concurrent.ConcurrentMap;</span> | 
 | <span class="source-line-no">059</span><span id="line-59">import java.util.concurrent.ConcurrentSkipListMap;</span> | 
 | <span class="source-line-no">060</span><span id="line-60">import java.util.concurrent.ExecutionException;</span> | 
 | <span class="source-line-no">061</span><span id="line-61">import java.util.concurrent.ExecutorCompletionService;</span> | 
 | <span class="source-line-no">062</span><span id="line-62">import java.util.concurrent.Future;</span> | 
 | <span class="source-line-no">063</span><span id="line-63">import java.util.concurrent.ThreadFactory;</span> | 
 | <span class="source-line-no">064</span><span id="line-64">import java.util.concurrent.ThreadPoolExecutor;</span> | 
 | <span class="source-line-no">065</span><span id="line-65">import java.util.concurrent.TimeUnit;</span> | 
 | <span class="source-line-no">066</span><span id="line-66">import java.util.concurrent.atomic.AtomicBoolean;</span> | 
 | <span class="source-line-no">067</span><span id="line-67">import java.util.concurrent.atomic.AtomicInteger;</span> | 
 | <span class="source-line-no">068</span><span id="line-68">import java.util.concurrent.atomic.LongAdder;</span> | 
 | <span class="source-line-no">069</span><span id="line-69">import java.util.concurrent.locks.Lock;</span> | 
 | <span class="source-line-no">070</span><span id="line-70">import java.util.concurrent.locks.ReadWriteLock;</span> | 
 | <span class="source-line-no">071</span><span id="line-71">import java.util.concurrent.locks.ReentrantLock;</span> | 
 | <span class="source-line-no">072</span><span id="line-72">import java.util.concurrent.locks.ReentrantReadWriteLock;</span> | 
 | <span class="source-line-no">073</span><span id="line-73">import java.util.function.Function;</span> | 
 | <span class="source-line-no">074</span><span id="line-74">import java.util.stream.Collectors;</span> | 
 | <span class="source-line-no">075</span><span id="line-75">import java.util.stream.Stream;</span> | 
 | <span class="source-line-no">076</span><span id="line-76">import org.apache.hadoop.conf.Configuration;</span> | 
 | <span class="source-line-no">077</span><span id="line-77">import org.apache.hadoop.fs.FileStatus;</span> | 
 | <span class="source-line-no">078</span><span id="line-78">import org.apache.hadoop.fs.FileSystem;</span> | 
 | <span class="source-line-no">079</span><span id="line-79">import org.apache.hadoop.fs.LocatedFileStatus;</span> | 
 | <span class="source-line-no">080</span><span id="line-80">import org.apache.hadoop.fs.Path;</span> | 
 | <span class="source-line-no">081</span><span id="line-81">import org.apache.hadoop.hbase.Cell;</span> | 
 | <span class="source-line-no">082</span><span id="line-82">import org.apache.hadoop.hbase.CellBuilderType;</span> | 
 | <span class="source-line-no">083</span><span id="line-83">import org.apache.hadoop.hbase.CellComparator;</span> | 
 | <span class="source-line-no">084</span><span id="line-84">import org.apache.hadoop.hbase.CellComparatorImpl;</span> | 
 | <span class="source-line-no">085</span><span id="line-85">import org.apache.hadoop.hbase.CellScanner;</span> | 
 | <span class="source-line-no">086</span><span id="line-86">import org.apache.hadoop.hbase.CellUtil;</span> | 
 | <span class="source-line-no">087</span><span id="line-87">import org.apache.hadoop.hbase.CompareOperator;</span> | 
 | <span class="source-line-no">088</span><span id="line-88">import org.apache.hadoop.hbase.CompoundConfiguration;</span> | 
 | <span class="source-line-no">089</span><span id="line-89">import org.apache.hadoop.hbase.DoNotRetryIOException;</span> | 
 | <span class="source-line-no">090</span><span id="line-90">import org.apache.hadoop.hbase.DroppedSnapshotException;</span> | 
 | <span class="source-line-no">091</span><span id="line-91">import org.apache.hadoop.hbase.ExtendedCell;</span> | 
 | <span class="source-line-no">092</span><span id="line-92">import org.apache.hadoop.hbase.ExtendedCellBuilderFactory;</span> | 
 | <span class="source-line-no">093</span><span id="line-93">import org.apache.hadoop.hbase.HConstants;</span> | 
 | <span class="source-line-no">094</span><span id="line-94">import org.apache.hadoop.hbase.HConstants.OperationStatusCode;</span> | 
 | <span class="source-line-no">095</span><span id="line-95">import org.apache.hadoop.hbase.HDFSBlocksDistribution;</span> | 
 | <span class="source-line-no">096</span><span id="line-96">import org.apache.hadoop.hbase.KeyValue;</span> | 
 | <span class="source-line-no">097</span><span id="line-97">import org.apache.hadoop.hbase.MetaCellComparator;</span> | 
 | <span class="source-line-no">098</span><span id="line-98">import org.apache.hadoop.hbase.NamespaceDescriptor;</span> | 
 | <span class="source-line-no">099</span><span id="line-99">import org.apache.hadoop.hbase.NotServingRegionException;</span> | 
 | <span class="source-line-no">100</span><span id="line-100">import org.apache.hadoop.hbase.PrivateCellUtil;</span> | 
 | <span class="source-line-no">101</span><span id="line-101">import org.apache.hadoop.hbase.RegionTooBusyException;</span> | 
 | <span class="source-line-no">102</span><span id="line-102">import org.apache.hadoop.hbase.Tag;</span> | 
 | <span class="source-line-no">103</span><span id="line-103">import org.apache.hadoop.hbase.TagUtil;</span> | 
 | <span class="source-line-no">104</span><span id="line-104">import org.apache.hadoop.hbase.client.Append;</span> | 
 | <span class="source-line-no">105</span><span id="line-105">import org.apache.hadoop.hbase.client.CheckAndMutate;</span> | 
 | <span class="source-line-no">106</span><span id="line-106">import org.apache.hadoop.hbase.client.CheckAndMutateResult;</span> | 
 | <span class="source-line-no">107</span><span id="line-107">import org.apache.hadoop.hbase.client.ClientInternalHelper;</span> | 
 | <span class="source-line-no">108</span><span id="line-108">import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor;</span> | 
 | <span class="source-line-no">109</span><span id="line-109">import org.apache.hadoop.hbase.client.CompactionState;</span> | 
 | <span class="source-line-no">110</span><span id="line-110">import org.apache.hadoop.hbase.client.Delete;</span> | 
 | <span class="source-line-no">111</span><span id="line-111">import org.apache.hadoop.hbase.client.Durability;</span> | 
 | <span class="source-line-no">112</span><span id="line-112">import org.apache.hadoop.hbase.client.Get;</span> | 
 | <span class="source-line-no">113</span><span id="line-113">import org.apache.hadoop.hbase.client.Increment;</span> | 
 | <span class="source-line-no">114</span><span id="line-114">import org.apache.hadoop.hbase.client.IsolationLevel;</span> | 
 | <span class="source-line-no">115</span><span id="line-115">import org.apache.hadoop.hbase.client.Mutation;</span> | 
 | <span class="source-line-no">116</span><span id="line-116">import org.apache.hadoop.hbase.client.Put;</span> | 
 | <span class="source-line-no">117</span><span id="line-117">import org.apache.hadoop.hbase.client.QueryMetrics;</span> | 
 | <span class="source-line-no">118</span><span id="line-118">import org.apache.hadoop.hbase.client.RegionInfo;</span> | 
 | <span class="source-line-no">119</span><span id="line-119">import org.apache.hadoop.hbase.client.RegionReplicaUtil;</span> | 
 | <span class="source-line-no">120</span><span id="line-120">import org.apache.hadoop.hbase.client.Result;</span> | 
 | <span class="source-line-no">121</span><span id="line-121">import org.apache.hadoop.hbase.client.Row;</span> | 
 | <span class="source-line-no">122</span><span id="line-122">import org.apache.hadoop.hbase.client.RowMutations;</span> | 
 | <span class="source-line-no">123</span><span id="line-123">import org.apache.hadoop.hbase.client.Scan;</span> | 
 | <span class="source-line-no">124</span><span id="line-124">import org.apache.hadoop.hbase.client.TableDescriptor;</span> | 
 | <span class="source-line-no">125</span><span id="line-125">import org.apache.hadoop.hbase.client.TableDescriptorBuilder;</span> | 
 | <span class="source-line-no">126</span><span id="line-126">import org.apache.hadoop.hbase.conf.ConfigKey;</span> | 
 | <span class="source-line-no">127</span><span id="line-127">import org.apache.hadoop.hbase.conf.ConfigurationManager;</span> | 
 | <span class="source-line-no">128</span><span id="line-128">import org.apache.hadoop.hbase.conf.PropagatingConfigurationObserver;</span> | 
 | <span class="source-line-no">129</span><span id="line-129">import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;</span> | 
 | <span class="source-line-no">130</span><span id="line-130">import org.apache.hadoop.hbase.coprocessor.ReadOnlyConfiguration;</span> | 
 | <span class="source-line-no">131</span><span id="line-131">import org.apache.hadoop.hbase.errorhandling.ForeignExceptionSnare;</span> | 
 | <span class="source-line-no">132</span><span id="line-132">import org.apache.hadoop.hbase.exceptions.FailedSanityCheckException;</span> | 
 | <span class="source-line-no">133</span><span id="line-133">import org.apache.hadoop.hbase.exceptions.TimeoutIOException;</span> | 
 | <span class="source-line-no">134</span><span id="line-134">import org.apache.hadoop.hbase.exceptions.UnknownProtocolException;</span> | 
 | <span class="source-line-no">135</span><span id="line-135">import org.apache.hadoop.hbase.filter.BinaryComparator;</span> | 
 | <span class="source-line-no">136</span><span id="line-136">import org.apache.hadoop.hbase.filter.ByteArrayComparable;</span> | 
 | <span class="source-line-no">137</span><span id="line-137">import org.apache.hadoop.hbase.filter.Filter;</span> | 
 | <span class="source-line-no">138</span><span id="line-138">import org.apache.hadoop.hbase.io.HFileLink;</span> | 
 | <span class="source-line-no">139</span><span id="line-139">import org.apache.hadoop.hbase.io.HeapSize;</span> | 
 | <span class="source-line-no">140</span><span id="line-140">import org.apache.hadoop.hbase.io.TimeRange;</span> | 
 | <span class="source-line-no">141</span><span id="line-141">import org.apache.hadoop.hbase.io.hfile.BlockCache;</span> | 
 | <span class="source-line-no">142</span><span id="line-142">import org.apache.hadoop.hbase.io.hfile.CombinedBlockCache;</span> | 
 | <span class="source-line-no">143</span><span id="line-143">import org.apache.hadoop.hbase.io.hfile.HFile;</span> | 
 | <span class="source-line-no">144</span><span id="line-144">import org.apache.hadoop.hbase.io.hfile.bucket.BucketCache;</span> | 
 | <span class="source-line-no">145</span><span id="line-145">import org.apache.hadoop.hbase.ipc.CoprocessorRpcUtils;</span> | 
 | <span class="source-line-no">146</span><span id="line-146">import org.apache.hadoop.hbase.ipc.RpcCall;</span> | 
 | <span class="source-line-no">147</span><span id="line-147">import org.apache.hadoop.hbase.ipc.RpcServer;</span> | 
 | <span class="source-line-no">148</span><span id="line-148">import org.apache.hadoop.hbase.ipc.ServerCall;</span> | 
 | <span class="source-line-no">149</span><span id="line-149">import org.apache.hadoop.hbase.mob.MobFileCache;</span> | 
 | <span class="source-line-no">150</span><span id="line-150">import org.apache.hadoop.hbase.monitoring.MonitoredTask;</span> | 
 | <span class="source-line-no">151</span><span id="line-151">import org.apache.hadoop.hbase.monitoring.TaskMonitor;</span> | 
 | <span class="source-line-no">152</span><span id="line-152">import org.apache.hadoop.hbase.quotas.RegionServerSpaceQuotaManager;</span> | 
 | <span class="source-line-no">153</span><span id="line-153">import org.apache.hadoop.hbase.regionserver.MultiVersionConcurrencyControl.WriteEntry;</span> | 
 | <span class="source-line-no">154</span><span id="line-154">import org.apache.hadoop.hbase.regionserver.compactions.CompactionContext;</span> | 
 | <span class="source-line-no">155</span><span id="line-155">import org.apache.hadoop.hbase.regionserver.compactions.CompactionLifeCycleTracker;</span> | 
 | <span class="source-line-no">156</span><span id="line-156">import org.apache.hadoop.hbase.regionserver.compactions.ForbidMajorCompactionChecker;</span> | 
 | <span class="source-line-no">157</span><span id="line-157">import org.apache.hadoop.hbase.regionserver.metrics.MetricsTableRequests;</span> | 
 | <span class="source-line-no">158</span><span id="line-158">import org.apache.hadoop.hbase.regionserver.regionreplication.RegionReplicationSink;</span> | 
 | <span class="source-line-no">159</span><span id="line-159">import org.apache.hadoop.hbase.regionserver.storefiletracker.StoreFileTracker;</span> | 
 | <span class="source-line-no">160</span><span id="line-160">import org.apache.hadoop.hbase.regionserver.storefiletracker.StoreFileTrackerFactory;</span> | 
 | <span class="source-line-no">161</span><span id="line-161">import org.apache.hadoop.hbase.regionserver.throttle.CompactionThroughputControllerFactory;</span> | 
 | <span class="source-line-no">162</span><span id="line-162">import org.apache.hadoop.hbase.regionserver.throttle.NoLimitThroughputController;</span> | 
 | <span class="source-line-no">163</span><span id="line-163">import org.apache.hadoop.hbase.regionserver.throttle.StoreHotnessProtector;</span> | 
 | <span class="source-line-no">164</span><span id="line-164">import org.apache.hadoop.hbase.regionserver.throttle.ThroughputController;</span> | 
 | <span class="source-line-no">165</span><span id="line-165">import org.apache.hadoop.hbase.regionserver.wal.WALSyncTimeoutIOException;</span> | 
 | <span class="source-line-no">166</span><span id="line-166">import org.apache.hadoop.hbase.regionserver.wal.WALUtil;</span> | 
 | <span class="source-line-no">167</span><span id="line-167">import org.apache.hadoop.hbase.replication.ReplicationUtils;</span> | 
 | <span class="source-line-no">168</span><span id="line-168">import org.apache.hadoop.hbase.replication.regionserver.ReplicationObserver;</span> | 
 | <span class="source-line-no">169</span><span id="line-169">import org.apache.hadoop.hbase.security.User;</span> | 
 | <span class="source-line-no">170</span><span id="line-170">import org.apache.hadoop.hbase.snapshot.SnapshotDescriptionUtils;</span> | 
 | <span class="source-line-no">171</span><span id="line-171">import org.apache.hadoop.hbase.snapshot.SnapshotManifest;</span> | 
 | <span class="source-line-no">172</span><span id="line-172">import org.apache.hadoop.hbase.trace.TraceUtil;</span> | 
 | <span class="source-line-no">173</span><span id="line-173">import org.apache.hadoop.hbase.util.Bytes;</span> | 
 | <span class="source-line-no">174</span><span id="line-174">import org.apache.hadoop.hbase.util.CancelableProgressable;</span> | 
 | <span class="source-line-no">175</span><span id="line-175">import org.apache.hadoop.hbase.util.ClassSize;</span> | 
 | <span class="source-line-no">176</span><span id="line-176">import org.apache.hadoop.hbase.util.CommonFSUtils;</span> | 
 | <span class="source-line-no">177</span><span id="line-177">import org.apache.hadoop.hbase.util.CoprocessorConfigurationUtil;</span> | 
 | <span class="source-line-no">178</span><span id="line-178">import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;</span> | 
 | <span class="source-line-no">179</span><span id="line-179">import org.apache.hadoop.hbase.util.FSUtils;</span> | 
 | <span class="source-line-no">180</span><span id="line-180">import org.apache.hadoop.hbase.util.HashedBytes;</span> | 
 | <span class="source-line-no">181</span><span id="line-181">import org.apache.hadoop.hbase.util.NonceKey;</span> | 
 | <span class="source-line-no">182</span><span id="line-182">import org.apache.hadoop.hbase.util.Pair;</span> | 
 | <span class="source-line-no">183</span><span id="line-183">import org.apache.hadoop.hbase.util.ServerRegionReplicaUtil;</span> | 
 | <span class="source-line-no">184</span><span id="line-184">import org.apache.hadoop.hbase.util.TableDescriptorChecker;</span> | 
 | <span class="source-line-no">185</span><span id="line-185">import org.apache.hadoop.hbase.util.Threads;</span> | 
 | <span class="source-line-no">186</span><span id="line-186">import org.apache.hadoop.hbase.wal.WAL;</span> | 
 | <span class="source-line-no">187</span><span id="line-187">import org.apache.hadoop.hbase.wal.WALEdit;</span> | 
 | <span class="source-line-no">188</span><span id="line-188">import org.apache.hadoop.hbase.wal.WALEditInternalHelper;</span> | 
 | <span class="source-line-no">189</span><span id="line-189">import org.apache.hadoop.hbase.wal.WALFactory;</span> | 
 | <span class="source-line-no">190</span><span id="line-190">import org.apache.hadoop.hbase.wal.WALKey;</span> | 
 | <span class="source-line-no">191</span><span id="line-191">import org.apache.hadoop.hbase.wal.WALKeyImpl;</span> | 
 | <span class="source-line-no">192</span><span id="line-192">import org.apache.hadoop.hbase.wal.WALSplitUtil;</span> | 
 | <span class="source-line-no">193</span><span id="line-193">import org.apache.hadoop.hbase.wal.WALSplitUtil.MutationReplay;</span> | 
 | <span class="source-line-no">194</span><span id="line-194">import org.apache.hadoop.hbase.wal.WALStreamReader;</span> | 
 | <span class="source-line-no">195</span><span id="line-195">import org.apache.hadoop.util.StringUtils;</span> | 
 | <span class="source-line-no">196</span><span id="line-196">import org.apache.yetus.audience.InterfaceAudience;</span> | 
 | <span class="source-line-no">197</span><span id="line-197">import org.slf4j.Logger;</span> | 
 | <span class="source-line-no">198</span><span id="line-198">import org.slf4j.LoggerFactory;</span> | 
 | <span class="source-line-no">199</span><span id="line-199"></span> | 
 | <span class="source-line-no">200</span><span id="line-200">import org.apache.hbase.thirdparty.com.google.common.base.Preconditions;</span> | 
 | <span class="source-line-no">201</span><span id="line-201">import org.apache.hbase.thirdparty.com.google.common.collect.Iterables;</span> | 
 | <span class="source-line-no">202</span><span id="line-202">import org.apache.hbase.thirdparty.com.google.common.collect.Lists;</span> | 
 | <span class="source-line-no">203</span><span id="line-203">import org.apache.hbase.thirdparty.com.google.common.collect.Maps;</span> | 
 | <span class="source-line-no">204</span><span id="line-204">import org.apache.hbase.thirdparty.com.google.common.io.Closeables;</span> | 
 | <span class="source-line-no">205</span><span id="line-205">import org.apache.hbase.thirdparty.com.google.protobuf.Descriptors.MethodDescriptor;</span> | 
 | <span class="source-line-no">206</span><span id="line-206">import org.apache.hbase.thirdparty.com.google.protobuf.Descriptors.ServiceDescriptor;</span> | 
 | <span class="source-line-no">207</span><span id="line-207">import org.apache.hbase.thirdparty.com.google.protobuf.Message;</span> | 
 | <span class="source-line-no">208</span><span id="line-208">import org.apache.hbase.thirdparty.com.google.protobuf.RpcCallback;</span> | 
 | <span class="source-line-no">209</span><span id="line-209">import org.apache.hbase.thirdparty.com.google.protobuf.RpcController;</span> | 
 | <span class="source-line-no">210</span><span id="line-210">import org.apache.hbase.thirdparty.com.google.protobuf.Service;</span> | 
 | <span class="source-line-no">211</span><span id="line-211">import org.apache.hbase.thirdparty.com.google.protobuf.TextFormat;</span> | 
 | <span class="source-line-no">212</span><span id="line-212">import org.apache.hbase.thirdparty.com.google.protobuf.UnsafeByteOperations;</span> | 
 | <span class="source-line-no">213</span><span id="line-213">import org.apache.hbase.thirdparty.org.apache.commons.collections4.CollectionUtils;</span> | 
 | <span class="source-line-no">214</span><span id="line-214"></span> | 
 | <span class="source-line-no">215</span><span id="line-215">import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;</span> | 
 | <span class="source-line-no">216</span><span id="line-216">import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.WALEntry;</span> | 
 | <span class="source-line-no">217</span><span id="line-217">import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos;</span> | 
 | <span class="source-line-no">218</span><span id="line-218">import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.CoprocessorServiceCall;</span> | 
 | <span class="source-line-no">219</span><span id="line-219">import org.apache.hadoop.hbase.shaded.protobuf.generated.ClusterStatusProtos.RegionLoad;</span> | 
 | <span class="source-line-no">220</span><span id="line-220">import org.apache.hadoop.hbase.shaded.protobuf.generated.ClusterStatusProtos.StoreSequenceId;</span> | 
 | <span class="source-line-no">221</span><span id="line-221">import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotDescription;</span> | 
 | <span class="source-line-no">222</span><span id="line-222">import org.apache.hadoop.hbase.shaded.protobuf.generated.WALProtos;</span> | 
 | <span class="source-line-no">223</span><span id="line-223">import org.apache.hadoop.hbase.shaded.protobuf.generated.WALProtos.CompactionDescriptor;</span> | 
 | <span class="source-line-no">224</span><span id="line-224">import org.apache.hadoop.hbase.shaded.protobuf.generated.WALProtos.FlushDescriptor;</span> | 
 | <span class="source-line-no">225</span><span id="line-225">import org.apache.hadoop.hbase.shaded.protobuf.generated.WALProtos.FlushDescriptor.FlushAction;</span> | 
 | <span class="source-line-no">226</span><span id="line-226">import org.apache.hadoop.hbase.shaded.protobuf.generated.WALProtos.FlushDescriptor.StoreFlushDescriptor;</span> | 
 | <span class="source-line-no">227</span><span id="line-227">import org.apache.hadoop.hbase.shaded.protobuf.generated.WALProtos.RegionEventDescriptor;</span> | 
 | <span class="source-line-no">228</span><span id="line-228">import org.apache.hadoop.hbase.shaded.protobuf.generated.WALProtos.RegionEventDescriptor.EventType;</span> | 
 | <span class="source-line-no">229</span><span id="line-229">import org.apache.hadoop.hbase.shaded.protobuf.generated.WALProtos.StoreDescriptor;</span> | 
 | <span class="source-line-no">230</span><span id="line-230"></span> | 
 | <span class="source-line-no">231</span><span id="line-231">/**</span> | 
 | <span class="source-line-no">232</span><span id="line-232"> * Regions store data for a certain region of a table. It stores all columns for each row. A given</span> | 
 | <span class="source-line-no">233</span><span id="line-233"> * table consists of one or more Regions.</span> | 
 | <span class="source-line-no">234</span><span id="line-234"> * <p></span> | 
 | <span class="source-line-no">235</span><span id="line-235"> * An Region is defined by its table and its key extent.</span> | 
 | <span class="source-line-no">236</span><span id="line-236"> * <p></span> | 
 | <span class="source-line-no">237</span><span id="line-237"> * Locking at the Region level serves only one purpose: preventing the region from being closed (and</span> | 
 | <span class="source-line-no">238</span><span id="line-238"> * consequently split) while other operations are ongoing. Each row level operation obtains both a</span> | 
 | <span class="source-line-no">239</span><span id="line-239"> * row lock and a region read lock for the duration of the operation. While a scanner is being</span> | 
 | <span class="source-line-no">240</span><span id="line-240"> * constructed, getScanner holds a read lock. If the scanner is successfully constructed, it holds a</span> | 
 | <span class="source-line-no">241</span><span id="line-241"> * read lock until it is closed. A close takes out a write lock and consequently will block for</span> | 
 | <span class="source-line-no">242</span><span id="line-242"> * ongoing operations and will block new operations from starting while the close is in progress.</span> | 
 | <span class="source-line-no">243</span><span id="line-243"> */</span> | 
 | <span class="source-line-no">244</span><span id="line-244">@SuppressWarnings("deprecation")</span> | 
 | <span class="source-line-no">245</span><span id="line-245">@InterfaceAudience.Private</span> | 
 | <span class="source-line-no">246</span><span id="line-246">public class HRegion implements HeapSize, PropagatingConfigurationObserver, Region {</span> | 
 | <span class="source-line-no">247</span><span id="line-247">  private static final Logger LOG = LoggerFactory.getLogger(HRegion.class);</span> | 
 | <span class="source-line-no">248</span><span id="line-248"></span> | 
 | <span class="source-line-no">249</span><span id="line-249">  public static final String LOAD_CFS_ON_DEMAND_CONFIG_KEY =</span> | 
 | <span class="source-line-no">250</span><span id="line-250">    "hbase.hregion.scan.loadColumnFamiliesOnDemand";</span> | 
 | <span class="source-line-no">251</span><span id="line-251"></span> | 
 | <span class="source-line-no">252</span><span id="line-252">  public static final String HBASE_MAX_CELL_SIZE_KEY =</span> | 
 | <span class="source-line-no">253</span><span id="line-253">    ConfigKey.LONG("hbase.server.keyvalue.maxsize");</span> | 
 | <span class="source-line-no">254</span><span id="line-254">  public static final int DEFAULT_MAX_CELL_SIZE = 10485760;</span> | 
 | <span class="source-line-no">255</span><span id="line-255"></span> | 
 | <span class="source-line-no">256</span><span id="line-256">  public static final String HBASE_REGIONSERVER_MINIBATCH_SIZE =</span> | 
 | <span class="source-line-no">257</span><span id="line-257">    ConfigKey.INT("hbase.regionserver.minibatch.size");</span> | 
 | <span class="source-line-no">258</span><span id="line-258">  public static final int DEFAULT_HBASE_REGIONSERVER_MINIBATCH_SIZE = 20000;</span> | 
 | <span class="source-line-no">259</span><span id="line-259"></span> | 
 | <span class="source-line-no">260</span><span id="line-260">  public static final String WAL_HSYNC_CONF_KEY = "hbase.wal.hsync";</span> | 
 | <span class="source-line-no">261</span><span id="line-261">  public static final boolean DEFAULT_WAL_HSYNC = false;</span> | 
 | <span class="source-line-no">262</span><span id="line-262"></span> | 
 | <span class="source-line-no">263</span><span id="line-263">  /** Parameter name for compaction after bulkload */</span> | 
 | <span class="source-line-no">264</span><span id="line-264">  public static final String COMPACTION_AFTER_BULKLOAD_ENABLE =</span> | 
 | <span class="source-line-no">265</span><span id="line-265">    "hbase.compaction.after.bulkload.enable";</span> | 
 | <span class="source-line-no">266</span><span id="line-266"></span> | 
 | <span class="source-line-no">267</span><span id="line-267">  /** Config for allow split when file count greater than the configured blocking file count */</span> | 
 | <span class="source-line-no">268</span><span id="line-268">  public static final String SPLIT_IGNORE_BLOCKING_ENABLED_KEY =</span> | 
 | <span class="source-line-no">269</span><span id="line-269">    "hbase.hregion.split.ignore.blocking.enabled";</span> | 
 | <span class="source-line-no">270</span><span id="line-270"></span> | 
 | <span class="source-line-no">271</span><span id="line-271">  public static final String REGION_STORAGE_POLICY_KEY = "hbase.hregion.block.storage.policy";</span> | 
 | <span class="source-line-no">272</span><span id="line-272">  public static final String DEFAULT_REGION_STORAGE_POLICY = "NONE";</span> | 
 | <span class="source-line-no">273</span><span id="line-273"></span> | 
 | <span class="source-line-no">274</span><span id="line-274">  /**</span> | 
 | <span class="source-line-no">275</span><span id="line-275">   * This is for for using HRegion as a local storage, where we may put the recovered edits in a</span> | 
 | <span class="source-line-no">276</span><span id="line-276">   * special place. Once this is set, we will only replay the recovered edits under this directory</span> | 
 | <span class="source-line-no">277</span><span id="line-277">   * and ignore the original replay directory configs.</span> | 
 | <span class="source-line-no">278</span><span id="line-278">   */</span> | 
 | <span class="source-line-no">279</span><span id="line-279">  public static final String SPECIAL_RECOVERED_EDITS_DIR =</span> | 
 | <span class="source-line-no">280</span><span id="line-280">    "hbase.hregion.special.recovered.edits.dir";</span> | 
 | <span class="source-line-no">281</span><span id="line-281"></span> | 
 | <span class="source-line-no">282</span><span id="line-282">  /**</span> | 
 | <span class="source-line-no">283</span><span id="line-283">   * Mainly used for master local region, where we will replay the WAL file directly without</span> | 
 | <span class="source-line-no">284</span><span id="line-284">   * splitting, so it is possible to have WAL files which are not closed cleanly, in this way,</span> | 
 | <span class="source-line-no">285</span><span id="line-285">   * hitting EOF is expected so should not consider it as a critical problem.</span> | 
 | <span class="source-line-no">286</span><span id="line-286">   */</span> | 
 | <span class="source-line-no">287</span><span id="line-287">  public static final String RECOVERED_EDITS_IGNORE_EOF =</span> | 
 | <span class="source-line-no">288</span><span id="line-288">    "hbase.hregion.recovered.edits.ignore.eof";</span> | 
 | <span class="source-line-no">289</span><span id="line-289"></span> | 
 | <span class="source-line-no">290</span><span id="line-290">  /**</span> | 
 | <span class="source-line-no">291</span><span id="line-291">   * Whether to use {@link MetaCellComparator} even if we are not meta region. Used when creating</span> | 
 | <span class="source-line-no">292</span><span id="line-292">   * master local region.</span> | 
 | <span class="source-line-no">293</span><span id="line-293">   */</span> | 
 | <span class="source-line-no">294</span><span id="line-294">  public static final String USE_META_CELL_COMPARATOR = "hbase.region.use.meta.cell.comparator";</span> | 
 | <span class="source-line-no">295</span><span id="line-295"></span> | 
 | <span class="source-line-no">296</span><span id="line-296">  public static final boolean DEFAULT_USE_META_CELL_COMPARATOR = false;</span> | 
 | <span class="source-line-no">297</span><span id="line-297"></span> | 
 | <span class="source-line-no">298</span><span id="line-298">  final AtomicBoolean closed = new AtomicBoolean(false);</span> | 
 | <span class="source-line-no">299</span><span id="line-299"></span> | 
 | <span class="source-line-no">300</span><span id="line-300">  /*</span> | 
 | <span class="source-line-no">301</span><span id="line-301">   * Closing can take some time; use the closing flag if there is stuff we don't want to do while in</span> | 
 | <span class="source-line-no">302</span><span id="line-302">   * closing state; e.g. like offer this region up to the master as a region to close if the</span> | 
 | <span class="source-line-no">303</span><span id="line-303">   * carrying regionserver is overloaded. Once set, it is never cleared.</span> | 
 | <span class="source-line-no">304</span><span id="line-304">   */</span> | 
 | <span class="source-line-no">305</span><span id="line-305">  final AtomicBoolean closing = new AtomicBoolean(false);</span> | 
 | <span class="source-line-no">306</span><span id="line-306"></span> | 
 | <span class="source-line-no">307</span><span id="line-307">  /**</span> | 
 | <span class="source-line-no">308</span><span id="line-308">   * The max sequence id of flushed data on this region. There is no edit in memory that is less</span> | 
 | <span class="source-line-no">309</span><span id="line-309">   * that this sequence id.</span> | 
 | <span class="source-line-no">310</span><span id="line-310">   */</span> | 
 | <span class="source-line-no">311</span><span id="line-311">  private volatile long maxFlushedSeqId = HConstants.NO_SEQNUM;</span> | 
 | <span class="source-line-no">312</span><span id="line-312"></span> | 
 | <span class="source-line-no">313</span><span id="line-313">  /**</span> | 
 | <span class="source-line-no">314</span><span id="line-314">   * Record the sequence id of last flush operation. Can be in advance of {@link #maxFlushedSeqId}</span> | 
 | <span class="source-line-no">315</span><span id="line-315">   * when flushing a single column family. In this case, {@link #maxFlushedSeqId} will be older than</span> | 
 | <span class="source-line-no">316</span><span id="line-316">   * the oldest edit in memory.</span> | 
 | <span class="source-line-no">317</span><span id="line-317">   */</span> | 
 | <span class="source-line-no">318</span><span id="line-318">  private volatile long lastFlushOpSeqId = HConstants.NO_SEQNUM;</span> | 
 | <span class="source-line-no">319</span><span id="line-319"></span> | 
 | <span class="source-line-no">320</span><span id="line-320">  /**</span> | 
 | <span class="source-line-no">321</span><span id="line-321">   * The sequence id of the last replayed open region event from the primary region. This is used to</span> | 
 | <span class="source-line-no">322</span><span id="line-322">   * skip entries before this due to the possibility of replay edits coming out of order from</span> | 
 | <span class="source-line-no">323</span><span id="line-323">   * replication.</span> | 
 | <span class="source-line-no">324</span><span id="line-324">   */</span> | 
 | <span class="source-line-no">325</span><span id="line-325">  protected volatile long lastReplayedOpenRegionSeqId = -1L;</span> | 
 | <span class="source-line-no">326</span><span id="line-326">  protected volatile long lastReplayedCompactionSeqId = -1L;</span> | 
 | <span class="source-line-no">327</span><span id="line-327"></span> | 
 | <span class="source-line-no">328</span><span id="line-328">  //////////////////////////////////////////////////////////////////////////////</span> | 
 | <span class="source-line-no">329</span><span id="line-329">  // Members</span> | 
 | <span class="source-line-no">330</span><span id="line-330">  //////////////////////////////////////////////////////////////////////////////</span> | 
 | <span class="source-line-no">331</span><span id="line-331"></span> | 
 | <span class="source-line-no">332</span><span id="line-332">  // map from a locked row to the context for that lock including:</span> | 
 | <span class="source-line-no">333</span><span id="line-333">  // - CountDownLatch for threads waiting on that row</span> | 
 | <span class="source-line-no">334</span><span id="line-334">  // - the thread that owns the lock (allow reentrancy)</span> | 
 | <span class="source-line-no">335</span><span id="line-335">  // - reference count of (reentrant) locks held by the thread</span> | 
 | <span class="source-line-no">336</span><span id="line-336">  // - the row itself</span> | 
 | <span class="source-line-no">337</span><span id="line-337">  private final ConcurrentHashMap<HashedBytes, RowLockContext> lockedRows =</span> | 
 | <span class="source-line-no">338</span><span id="line-338">    new ConcurrentHashMap<>();</span> | 
 | <span class="source-line-no">339</span><span id="line-339"></span> | 
 | <span class="source-line-no">340</span><span id="line-340">  protected final Map<byte[], HStore> stores =</span> | 
 | <span class="source-line-no">341</span><span id="line-341">    new ConcurrentSkipListMap<>(Bytes.BYTES_RAWCOMPARATOR);</span> | 
 | <span class="source-line-no">342</span><span id="line-342"></span> | 
 | <span class="source-line-no">343</span><span id="line-343">  // TODO: account for each registered handler in HeapSize computation</span> | 
 | <span class="source-line-no">344</span><span id="line-344">  private Map<String, Service> coprocessorServiceHandlers = Maps.newHashMap();</span> | 
 | <span class="source-line-no">345</span><span id="line-345"></span> | 
 | <span class="source-line-no">346</span><span id="line-346">  // Track data size in all memstores</span> | 
 | <span class="source-line-no">347</span><span id="line-347">  private final MemStoreSizing memStoreSizing = new ThreadSafeMemStoreSizing();</span> | 
 | <span class="source-line-no">348</span><span id="line-348">  RegionServicesForStores regionServicesForStores;</span> | 
 | <span class="source-line-no">349</span><span id="line-349"></span> | 
 | <span class="source-line-no">350</span><span id="line-350">  // Debug possible data loss due to WAL off</span> | 
 | <span class="source-line-no">351</span><span id="line-351">  final LongAdder numMutationsWithoutWAL = new LongAdder();</span> | 
 | <span class="source-line-no">352</span><span id="line-352">  final LongAdder dataInMemoryWithoutWAL = new LongAdder();</span> | 
 | <span class="source-line-no">353</span><span id="line-353"></span> | 
 | <span class="source-line-no">354</span><span id="line-354">  // Debug why CAS operations are taking a while.</span> | 
 | <span class="source-line-no">355</span><span id="line-355">  final LongAdder checkAndMutateChecksPassed = new LongAdder();</span> | 
 | <span class="source-line-no">356</span><span id="line-356">  final LongAdder checkAndMutateChecksFailed = new LongAdder();</span> | 
 | <span class="source-line-no">357</span><span id="line-357"></span> | 
 | <span class="source-line-no">358</span><span id="line-358">  // Number of requests</span> | 
 | <span class="source-line-no">359</span><span id="line-359">  // Count rows for scan</span> | 
 | <span class="source-line-no">360</span><span id="line-360">  final LongAdder readRequestsCount = new LongAdder();</span> | 
 | <span class="source-line-no">361</span><span id="line-361">  final LongAdder cpRequestsCount = new LongAdder();</span> | 
 | <span class="source-line-no">362</span><span id="line-362">  final LongAdder filteredReadRequestsCount = new LongAdder();</span> | 
 | <span class="source-line-no">363</span><span id="line-363">  // Count rows for multi row mutations</span> | 
 | <span class="source-line-no">364</span><span id="line-364">  final LongAdder writeRequestsCount = new LongAdder();</span> | 
 | <span class="source-line-no">365</span><span id="line-365"></span> | 
 | <span class="source-line-no">366</span><span id="line-366">  // Number of requests blocked by memstore size.</span> | 
 | <span class="source-line-no">367</span><span id="line-367">  private final LongAdder blockedRequestsCount = new LongAdder();</span> | 
 | <span class="source-line-no">368</span><span id="line-368"></span> | 
 | <span class="source-line-no">369</span><span id="line-369">  // Compaction LongAdders</span> | 
 | <span class="source-line-no">370</span><span id="line-370">  final LongAdder compactionsFinished = new LongAdder();</span> | 
 | <span class="source-line-no">371</span><span id="line-371">  final LongAdder compactionsFailed = new LongAdder();</span> | 
 | <span class="source-line-no">372</span><span id="line-372">  final LongAdder compactionNumFilesCompacted = new LongAdder();</span> | 
 | <span class="source-line-no">373</span><span id="line-373">  final LongAdder compactionNumBytesCompacted = new LongAdder();</span> | 
 | <span class="source-line-no">374</span><span id="line-374">  final LongAdder compactionsQueued = new LongAdder();</span> | 
 | <span class="source-line-no">375</span><span id="line-375">  final LongAdder flushesQueued = new LongAdder();</span> | 
 | <span class="source-line-no">376</span><span id="line-376"></span> | 
 | <span class="source-line-no">377</span><span id="line-377">  private BlockCache blockCache;</span> | 
 | <span class="source-line-no">378</span><span id="line-378">  private MobFileCache mobFileCache;</span> | 
 | <span class="source-line-no">379</span><span id="line-379">  private final WAL wal;</span> | 
 | <span class="source-line-no">380</span><span id="line-380">  private final HRegionFileSystem fs;</span> | 
 | <span class="source-line-no">381</span><span id="line-381">  protected final Configuration conf;</span> | 
 | <span class="source-line-no">382</span><span id="line-382">  private final Configuration baseConf;</span> | 
 | <span class="source-line-no">383</span><span id="line-383">  private final int rowLockWaitDuration;</span> | 
 | <span class="source-line-no">384</span><span id="line-384">  static final int DEFAULT_ROWLOCK_WAIT_DURATION = 30000;</span> | 
 | <span class="source-line-no">385</span><span id="line-385"></span> | 
 | <span class="source-line-no">386</span><span id="line-386">  private Path regionWalDir;</span> | 
 | <span class="source-line-no">387</span><span id="line-387">  private FileSystem walFS;</span> | 
 | <span class="source-line-no">388</span><span id="line-388"></span> | 
 | <span class="source-line-no">389</span><span id="line-389">  // set to true if the region is restored from snapshot for reading by ClientSideRegionScanner</span> | 
 | <span class="source-line-no">390</span><span id="line-390">  private boolean isRestoredRegion = false;</span> | 
 | <span class="source-line-no">391</span><span id="line-391"></span> | 
 | <span class="source-line-no">392</span><span id="line-392">  public void setRestoredRegion(boolean restoredRegion) {</span> | 
 | <span class="source-line-no">393</span><span id="line-393">    isRestoredRegion = restoredRegion;</span> | 
 | <span class="source-line-no">394</span><span id="line-394">  }</span> | 
 | <span class="source-line-no">395</span><span id="line-395"></span> | 
 | <span class="source-line-no">396</span><span id="line-396">  public MetricsTableRequests getMetricsTableRequests() {</span> | 
 | <span class="source-line-no">397</span><span id="line-397">    return metricsTableRequests;</span> | 
 | <span class="source-line-no">398</span><span id="line-398">  }</span> | 
 | <span class="source-line-no">399</span><span id="line-399"></span> | 
 | <span class="source-line-no">400</span><span id="line-400">  // Handle table latency metrics</span> | 
 | <span class="source-line-no">401</span><span id="line-401">  private MetricsTableRequests metricsTableRequests;</span> | 
 | <span class="source-line-no">402</span><span id="line-402"></span> | 
 | <span class="source-line-no">403</span><span id="line-403">  // The internal wait duration to acquire a lock before read/update</span> | 
 | <span class="source-line-no">404</span><span id="line-404">  // from the region. It is not per row. The purpose of this wait time</span> | 
 | <span class="source-line-no">405</span><span id="line-405">  // is to avoid waiting a long time while the region is busy, so that</span> | 
 | <span class="source-line-no">406</span><span id="line-406">  // we can release the IPC handler soon enough to improve the</span> | 
 | <span class="source-line-no">407</span><span id="line-407">  // availability of the region server. It can be adjusted by</span> | 
 | <span class="source-line-no">408</span><span id="line-408">  // tuning configuration "hbase.busy.wait.duration".</span> | 
 | <span class="source-line-no">409</span><span id="line-409">  final long busyWaitDuration;</span> | 
 | <span class="source-line-no">410</span><span id="line-410">  static final long DEFAULT_BUSY_WAIT_DURATION = HConstants.DEFAULT_HBASE_RPC_TIMEOUT;</span> | 
 | <span class="source-line-no">411</span><span id="line-411"></span> | 
 | <span class="source-line-no">412</span><span id="line-412">  // If updating multiple rows in one call, wait longer,</span> | 
 | <span class="source-line-no">413</span><span id="line-413">  // i.e. waiting for busyWaitDuration * # of rows. However,</span> | 
 | <span class="source-line-no">414</span><span id="line-414">  // we can limit the max multiplier.</span> | 
 | <span class="source-line-no">415</span><span id="line-415">  final int maxBusyWaitMultiplier;</span> | 
 | <span class="source-line-no">416</span><span id="line-416"></span> | 
 | <span class="source-line-no">417</span><span id="line-417">  // Max busy wait duration. There is no point to wait longer than the RPC</span> | 
 | <span class="source-line-no">418</span><span id="line-418">  // purge timeout, when a RPC call will be terminated by the RPC engine.</span> | 
 | <span class="source-line-no">419</span><span id="line-419">  final long maxBusyWaitDuration;</span> | 
 | <span class="source-line-no">420</span><span id="line-420"></span> | 
 | <span class="source-line-no">421</span><span id="line-421">  // Max cell size. If nonzero, the maximum allowed size for any given cell</span> | 
 | <span class="source-line-no">422</span><span id="line-422">  // in bytes</span> | 
 | <span class="source-line-no">423</span><span id="line-423">  final long maxCellSize;</span> | 
 | <span class="source-line-no">424</span><span id="line-424"></span> | 
 | <span class="source-line-no">425</span><span id="line-425">  // Number of mutations for minibatch processing.</span> | 
 | <span class="source-line-no">426</span><span id="line-426">  private final int miniBatchSize;</span> | 
 | <span class="source-line-no">427</span><span id="line-427"></span> | 
 | <span class="source-line-no">428</span><span id="line-428">  final ConcurrentHashMap<RegionScanner, Long> scannerReadPoints;</span> | 
 | <span class="source-line-no">429</span><span id="line-429">  final ReadPointCalculationLock smallestReadPointCalcLock;</span> | 
 | <span class="source-line-no">430</span><span id="line-430"></span> | 
 | <span class="source-line-no">431</span><span id="line-431">  /**</span> | 
 | <span class="source-line-no">432</span><span id="line-432">   * The sequence ID that was enLongAddered when this region was opened.</span> | 
 | <span class="source-line-no">433</span><span id="line-433">   */</span> | 
 | <span class="source-line-no">434</span><span id="line-434">  private long openSeqNum = HConstants.NO_SEQNUM;</span> | 
 | <span class="source-line-no">435</span><span id="line-435"></span> | 
 | <span class="source-line-no">436</span><span id="line-436">  /**</span> | 
 | <span class="source-line-no">437</span><span id="line-437">   * The default setting for whether to enable on-demand CF loading for scan requests to this</span> | 
 | <span class="source-line-no">438</span><span id="line-438">   * region. Requests can override it.</span> | 
 | <span class="source-line-no">439</span><span id="line-439">   */</span> | 
 | <span class="source-line-no">440</span><span id="line-440">  private boolean isLoadingCfsOnDemandDefault = false;</span> | 
 | <span class="source-line-no">441</span><span id="line-441"></span> | 
 | <span class="source-line-no">442</span><span id="line-442">  private final AtomicInteger majorInProgress = new AtomicInteger(0);</span> | 
 | <span class="source-line-no">443</span><span id="line-443">  private final AtomicInteger minorInProgress = new AtomicInteger(0);</span> | 
 | <span class="source-line-no">444</span><span id="line-444"></span> | 
 | <span class="source-line-no">445</span><span id="line-445">  //</span> | 
 | <span class="source-line-no">446</span><span id="line-446">  // Context: During replay we want to ensure that we do not lose any data. So, we</span> | 
 | <span class="source-line-no">447</span><span id="line-447">  // have to be conservative in how we replay wals. For each store, we calculate</span> | 
 | <span class="source-line-no">448</span><span id="line-448">  // the maxSeqId up to which the store was flushed. And, skip the edits which</span> | 
 | <span class="source-line-no">449</span><span id="line-449">  // are equal to or lower than maxSeqId for each store.</span> | 
 | <span class="source-line-no">450</span><span id="line-450">  // The following map is populated when opening the region</span> | 
 | <span class="source-line-no">451</span><span id="line-451">  Map<byte[], Long> maxSeqIdInStores = new TreeMap<>(Bytes.BYTES_COMPARATOR);</span> | 
 | <span class="source-line-no">452</span><span id="line-452"></span> | 
 | <span class="source-line-no">453</span><span id="line-453">  // lock used to protect the replay operation for secondary replicas, so the below two fields does</span> | 
 | <span class="source-line-no">454</span><span id="line-454">  // not need to be volatile.</span> | 
 | <span class="source-line-no">455</span><span id="line-455">  private Lock replayLock;</span> | 
 | <span class="source-line-no">456</span><span id="line-456"></span> | 
 | <span class="source-line-no">457</span><span id="line-457">  /** Saved state from replaying prepare flush cache */</span> | 
 | <span class="source-line-no">458</span><span id="line-458">  private PrepareFlushResult prepareFlushResult = null;</span> | 
 | <span class="source-line-no">459</span><span id="line-459"></span> | 
 | <span class="source-line-no">460</span><span id="line-460">  private long lastReplayedSequenceId = HConstants.NO_SEQNUM;</span> | 
 | <span class="source-line-no">461</span><span id="line-461"></span> | 
 | <span class="source-line-no">462</span><span id="line-462">  private volatile ConfigurationManager configurationManager;</span> | 
 | <span class="source-line-no">463</span><span id="line-463"></span> | 
 | <span class="source-line-no">464</span><span id="line-464">  // Used for testing.</span> | 
 | <span class="source-line-no">465</span><span id="line-465">  private volatile Long timeoutForWriteLock = null;</span> | 
 | <span class="source-line-no">466</span><span id="line-466"></span> | 
 | <span class="source-line-no">467</span><span id="line-467">  private final CellComparator cellComparator;</span> | 
 | <span class="source-line-no">468</span><span id="line-468"></span> | 
 | <span class="source-line-no">469</span><span id="line-469">  private final int minBlockSizeBytes;</span> | 
 | <span class="source-line-no">470</span><span id="line-470"></span> | 
 | <span class="source-line-no">471</span><span id="line-471">  /**</span> | 
 | <span class="source-line-no">472</span><span id="line-472">   * @return The smallest mvcc readPoint across all the scanners in this region. Writes older than</span> | 
 | <span class="source-line-no">473</span><span id="line-473">   *         this readPoint, are included in every read operation.</span> | 
 | <span class="source-line-no">474</span><span id="line-474">   */</span> | 
 | <span class="source-line-no">475</span><span id="line-475">  public long getSmallestReadPoint() {</span> | 
 | <span class="source-line-no">476</span><span id="line-476">    // We need to ensure that while we are calculating the smallestReadPoint</span> | 
 | <span class="source-line-no">477</span><span id="line-477">    // no new RegionScanners can grab a readPoint that we are unaware of.</span> | 
 | <span class="source-line-no">478</span><span id="line-478">    smallestReadPointCalcLock.lock(ReadPointCalculationLock.LockType.CALCULATION_LOCK);</span> | 
 | <span class="source-line-no">479</span><span id="line-479">    try {</span> | 
 | <span class="source-line-no">480</span><span id="line-480">      long minimumReadPoint = mvcc.getReadPoint();</span> | 
 | <span class="source-line-no">481</span><span id="line-481">      for (Long readPoint : this.scannerReadPoints.values()) {</span> | 
 | <span class="source-line-no">482</span><span id="line-482">        minimumReadPoint = Math.min(minimumReadPoint, readPoint);</span> | 
 | <span class="source-line-no">483</span><span id="line-483">      }</span> | 
 | <span class="source-line-no">484</span><span id="line-484">      return minimumReadPoint;</span> | 
 | <span class="source-line-no">485</span><span id="line-485">    } finally {</span> | 
 | <span class="source-line-no">486</span><span id="line-486">      smallestReadPointCalcLock.unlock(ReadPointCalculationLock.LockType.CALCULATION_LOCK);</span> | 
 | <span class="source-line-no">487</span><span id="line-487">    }</span> | 
 | <span class="source-line-no">488</span><span id="line-488">  }</span> | 
 | <span class="source-line-no">489</span><span id="line-489"></span> | 
 | <span class="source-line-no">490</span><span id="line-490">  /*</span> | 
 | <span class="source-line-no">491</span><span id="line-491">   * Data structure of write state flags used coordinating flushes, compactions and closes.</span> | 
 | <span class="source-line-no">492</span><span id="line-492">   */</span> | 
 | <span class="source-line-no">493</span><span id="line-493">  static class WriteState {</span> | 
 | <span class="source-line-no">494</span><span id="line-494">    // Set while a memstore flush is happening.</span> | 
 | <span class="source-line-no">495</span><span id="line-495">    volatile boolean flushing = false;</span> | 
 | <span class="source-line-no">496</span><span id="line-496">    // Set when a flush has been requested.</span> | 
 | <span class="source-line-no">497</span><span id="line-497">    volatile boolean flushRequested = false;</span> | 
 | <span class="source-line-no">498</span><span id="line-498">    // Number of compactions running.</span> | 
 | <span class="source-line-no">499</span><span id="line-499">    AtomicInteger compacting = new AtomicInteger(0);</span> | 
 | <span class="source-line-no">500</span><span id="line-500">    // Gets set in close. If set, cannot compact or flush again.</span> | 
 | <span class="source-line-no">501</span><span id="line-501">    volatile boolean writesEnabled = true;</span> | 
 | <span class="source-line-no">502</span><span id="line-502">    // Set if region is read-only</span> | 
 | <span class="source-line-no">503</span><span id="line-503">    volatile boolean readOnly = false;</span> | 
 | <span class="source-line-no">504</span><span id="line-504">    // whether the reads are enabled. This is different than readOnly, because readOnly is</span> | 
 | <span class="source-line-no">505</span><span id="line-505">    // static in the lifetime of the region, while readsEnabled is dynamic</span> | 
 | <span class="source-line-no">506</span><span id="line-506">    volatile boolean readsEnabled = true;</span> | 
 | <span class="source-line-no">507</span><span id="line-507"></span> | 
 | <span class="source-line-no">508</span><span id="line-508">    /**</span> | 
 | <span class="source-line-no">509</span><span id="line-509">     * Set flags that make this region read-only.</span> | 
 | <span class="source-line-no">510</span><span id="line-510">     * @param onOff flip value for region r/o setting</span> | 
 | <span class="source-line-no">511</span><span id="line-511">     */</span> | 
 | <span class="source-line-no">512</span><span id="line-512">    synchronized void setReadOnly(final boolean onOff) {</span> | 
 | <span class="source-line-no">513</span><span id="line-513">      this.writesEnabled = !onOff;</span> | 
 | <span class="source-line-no">514</span><span id="line-514">      this.readOnly = onOff;</span> | 
 | <span class="source-line-no">515</span><span id="line-515">    }</span> | 
 | <span class="source-line-no">516</span><span id="line-516"></span> | 
 | <span class="source-line-no">517</span><span id="line-517">    boolean isReadOnly() {</span> | 
 | <span class="source-line-no">518</span><span id="line-518">      return this.readOnly;</span> | 
 | <span class="source-line-no">519</span><span id="line-519">    }</span> | 
 | <span class="source-line-no">520</span><span id="line-520"></span> | 
 | <span class="source-line-no">521</span><span id="line-521">    boolean isFlushRequested() {</span> | 
 | <span class="source-line-no">522</span><span id="line-522">      return this.flushRequested;</span> | 
 | <span class="source-line-no">523</span><span id="line-523">    }</span> | 
 | <span class="source-line-no">524</span><span id="line-524"></span> | 
 | <span class="source-line-no">525</span><span id="line-525">    void setReadsEnabled(boolean readsEnabled) {</span> | 
 | <span class="source-line-no">526</span><span id="line-526">      this.readsEnabled = readsEnabled;</span> | 
 | <span class="source-line-no">527</span><span id="line-527">    }</span> | 
 | <span class="source-line-no">528</span><span id="line-528"></span> | 
 | <span class="source-line-no">529</span><span id="line-529">    static final long HEAP_SIZE = ClassSize.align(ClassSize.OBJECT + 5 * Bytes.SIZEOF_BOOLEAN);</span> | 
 | <span class="source-line-no">530</span><span id="line-530">  }</span> | 
 | <span class="source-line-no">531</span><span id="line-531"></span> | 
 | <span class="source-line-no">532</span><span id="line-532">  /**</span> | 
 | <span class="source-line-no">533</span><span id="line-533">   * Objects from this class are created when flushing to describe all the different states that</span> | 
 | <span class="source-line-no">534</span><span id="line-534">   * that method ends up in. The Result enum describes those states. The sequence id should only be</span> | 
 | <span class="source-line-no">535</span><span id="line-535">   * specified if the flush was successful, and the failure message should only be specified if it</span> | 
 | <span class="source-line-no">536</span><span id="line-536">   * didn't flush.</span> | 
 | <span class="source-line-no">537</span><span id="line-537">   */</span> | 
 | <span class="source-line-no">538</span><span id="line-538">  public static class FlushResultImpl implements FlushResult {</span> | 
 | <span class="source-line-no">539</span><span id="line-539">    final Result result;</span> | 
 | <span class="source-line-no">540</span><span id="line-540">    final String failureReason;</span> | 
 | <span class="source-line-no">541</span><span id="line-541">    final long flushSequenceId;</span> | 
 | <span class="source-line-no">542</span><span id="line-542">    final boolean wroteFlushWalMarker;</span> | 
 | <span class="source-line-no">543</span><span id="line-543"></span> | 
 | <span class="source-line-no">544</span><span id="line-544">    /**</span> | 
 | <span class="source-line-no">545</span><span id="line-545">     * Convenience constructor to use when the flush is successful, the failure message is set to</span> | 
 | <span class="source-line-no">546</span><span id="line-546">     * null.</span> | 
 | <span class="source-line-no">547</span><span id="line-547">     * @param result          Expecting FLUSHED_NO_COMPACTION_NEEDED or FLUSHED_COMPACTION_NEEDED.</span> | 
 | <span class="source-line-no">548</span><span id="line-548">     * @param flushSequenceId Generated sequence id that comes right after the edits in the</span> | 
 | <span class="source-line-no">549</span><span id="line-549">     *                        memstores.</span> | 
 | <span class="source-line-no">550</span><span id="line-550">     */</span> | 
 | <span class="source-line-no">551</span><span id="line-551">    FlushResultImpl(Result result, long flushSequenceId) {</span> | 
 | <span class="source-line-no">552</span><span id="line-552">      this(result, flushSequenceId, null, false);</span> | 
 | <span class="source-line-no">553</span><span id="line-553">      assert result == Result.FLUSHED_NO_COMPACTION_NEEDED</span> | 
 | <span class="source-line-no">554</span><span id="line-554">        || result == Result.FLUSHED_COMPACTION_NEEDED;</span> | 
 | <span class="source-line-no">555</span><span id="line-555">    }</span> | 
 | <span class="source-line-no">556</span><span id="line-556"></span> | 
 | <span class="source-line-no">557</span><span id="line-557">    /**</span> | 
 | <span class="source-line-no">558</span><span id="line-558">     * Convenience constructor to use when we cannot flush.</span> | 
 | <span class="source-line-no">559</span><span id="line-559">     * @param result        Expecting CANNOT_FLUSH_MEMSTORE_EMPTY or CANNOT_FLUSH.</span> | 
 | <span class="source-line-no">560</span><span id="line-560">     * @param failureReason Reason why we couldn't flush.</span> | 
 | <span class="source-line-no">561</span><span id="line-561">     */</span> | 
 | <span class="source-line-no">562</span><span id="line-562">    FlushResultImpl(Result result, String failureReason, boolean wroteFlushMarker) {</span> | 
 | <span class="source-line-no">563</span><span id="line-563">      this(result, -1, failureReason, wroteFlushMarker);</span> | 
 | <span class="source-line-no">564</span><span id="line-564">      assert result == Result.CANNOT_FLUSH_MEMSTORE_EMPTY || result == Result.CANNOT_FLUSH;</span> | 
 | <span class="source-line-no">565</span><span id="line-565">    }</span> | 
 | <span class="source-line-no">566</span><span id="line-566"></span> | 
 | <span class="source-line-no">567</span><span id="line-567">    /**</span> | 
 | <span class="source-line-no">568</span><span id="line-568">     * Constructor with all the parameters.</span> | 
 | <span class="source-line-no">569</span><span id="line-569">     * @param result          Any of the Result.</span> | 
 | <span class="source-line-no">570</span><span id="line-570">     * @param flushSequenceId Generated sequence id if the memstores were flushed else -1.</span> | 
 | <span class="source-line-no">571</span><span id="line-571">     * @param failureReason   Reason why we couldn't flush, or null.</span> | 
 | <span class="source-line-no">572</span><span id="line-572">     */</span> | 
 | <span class="source-line-no">573</span><span id="line-573">    FlushResultImpl(Result result, long flushSequenceId, String failureReason,</span> | 
 | <span class="source-line-no">574</span><span id="line-574">      boolean wroteFlushMarker) {</span> | 
 | <span class="source-line-no">575</span><span id="line-575">      this.result = result;</span> | 
 | <span class="source-line-no">576</span><span id="line-576">      this.flushSequenceId = flushSequenceId;</span> | 
 | <span class="source-line-no">577</span><span id="line-577">      this.failureReason = failureReason;</span> | 
 | <span class="source-line-no">578</span><span id="line-578">      this.wroteFlushWalMarker = wroteFlushMarker;</span> | 
 | <span class="source-line-no">579</span><span id="line-579">    }</span> | 
 | <span class="source-line-no">580</span><span id="line-580"></span> | 
 | <span class="source-line-no">581</span><span id="line-581">    /**</span> | 
 | <span class="source-line-no">582</span><span id="line-582">     * Convenience method, the equivalent of checking if result is FLUSHED_NO_COMPACTION_NEEDED or</span> | 
 | <span class="source-line-no">583</span><span id="line-583">     * FLUSHED_NO_COMPACTION_NEEDED.</span> | 
 | <span class="source-line-no">584</span><span id="line-584">     * @return true if the memstores were flushed, else false.</span> | 
 | <span class="source-line-no">585</span><span id="line-585">     */</span> | 
 | <span class="source-line-no">586</span><span id="line-586">    @Override</span> | 
 | <span class="source-line-no">587</span><span id="line-587">    public boolean isFlushSucceeded() {</span> | 
 | <span class="source-line-no">588</span><span id="line-588">      return result == Result.FLUSHED_NO_COMPACTION_NEEDED</span> | 
 | <span class="source-line-no">589</span><span id="line-589">        || result == Result.FLUSHED_COMPACTION_NEEDED;</span> | 
 | <span class="source-line-no">590</span><span id="line-590">    }</span> | 
 | <span class="source-line-no">591</span><span id="line-591"></span> | 
 | <span class="source-line-no">592</span><span id="line-592">    /**</span> | 
 | <span class="source-line-no">593</span><span id="line-593">     * Convenience method, the equivalent of checking if result is FLUSHED_COMPACTION_NEEDED.</span> | 
 | <span class="source-line-no">594</span><span id="line-594">     * @return True if the flush requested a compaction, else false (doesn't even mean it flushed).</span> | 
 | <span class="source-line-no">595</span><span id="line-595">     */</span> | 
 | <span class="source-line-no">596</span><span id="line-596">    @Override</span> | 
 | <span class="source-line-no">597</span><span id="line-597">    public boolean isCompactionNeeded() {</span> | 
 | <span class="source-line-no">598</span><span id="line-598">      return result == Result.FLUSHED_COMPACTION_NEEDED;</span> | 
 | <span class="source-line-no">599</span><span id="line-599">    }</span> | 
 | <span class="source-line-no">600</span><span id="line-600"></span> | 
 | <span class="source-line-no">601</span><span id="line-601">    @Override</span> | 
 | <span class="source-line-no">602</span><span id="line-602">    public String toString() {</span> | 
 | <span class="source-line-no">603</span><span id="line-603">      return new StringBuilder().append("flush result:").append(result).append(", ")</span> | 
 | <span class="source-line-no">604</span><span id="line-604">        .append("failureReason:").append(failureReason).append(",").append("flush seq id")</span> | 
 | <span class="source-line-no">605</span><span id="line-605">        .append(flushSequenceId).toString();</span> | 
 | <span class="source-line-no">606</span><span id="line-606">    }</span> | 
 | <span class="source-line-no">607</span><span id="line-607"></span> | 
 | <span class="source-line-no">608</span><span id="line-608">    @Override</span> | 
 | <span class="source-line-no">609</span><span id="line-609">    public Result getResult() {</span> | 
 | <span class="source-line-no">610</span><span id="line-610">      return result;</span> | 
 | <span class="source-line-no">611</span><span id="line-611">    }</span> | 
 | <span class="source-line-no">612</span><span id="line-612">  }</span> | 
 | <span class="source-line-no">613</span><span id="line-613"></span> | 
 | <span class="source-line-no">614</span><span id="line-614">  /** A result object from prepare flush cache stage */</span> | 
 | <span class="source-line-no">615</span><span id="line-615">  protected static class PrepareFlushResult {</span> | 
 | <span class="source-line-no">616</span><span id="line-616">    final FlushResultImpl result; // indicating a failure result from prepare</span> | 
 | <span class="source-line-no">617</span><span id="line-617">    final TreeMap<byte[], StoreFlushContext> storeFlushCtxs;</span> | 
 | <span class="source-line-no">618</span><span id="line-618">    final TreeMap<byte[], List<Path>> committedFiles;</span> | 
 | <span class="source-line-no">619</span><span id="line-619">    final TreeMap<byte[], MemStoreSize> storeFlushableSize;</span> | 
 | <span class="source-line-no">620</span><span id="line-620">    final long startTime;</span> | 
 | <span class="source-line-no">621</span><span id="line-621">    final long flushOpSeqId;</span> | 
 | <span class="source-line-no">622</span><span id="line-622">    final long flushedSeqId;</span> | 
 | <span class="source-line-no">623</span><span id="line-623">    final MemStoreSizing totalFlushableSize;</span> | 
 | <span class="source-line-no">624</span><span id="line-624"></span> | 
 | <span class="source-line-no">625</span><span id="line-625">    /** Constructs an early exit case */</span> | 
 | <span class="source-line-no">626</span><span id="line-626">    PrepareFlushResult(FlushResultImpl result, long flushSeqId) {</span> | 
 | <span class="source-line-no">627</span><span id="line-627">      this(result, null, null, null, Math.max(0, flushSeqId), 0, 0, MemStoreSizing.DUD);</span> | 
 | <span class="source-line-no">628</span><span id="line-628">    }</span> | 
 | <span class="source-line-no">629</span><span id="line-629"></span> | 
 | <span class="source-line-no">630</span><span id="line-630">    /** Constructs a successful prepare flush result */</span> | 
 | <span class="source-line-no">631</span><span id="line-631">    PrepareFlushResult(TreeMap<byte[], StoreFlushContext> storeFlushCtxs,</span> | 
 | <span class="source-line-no">632</span><span id="line-632">      TreeMap<byte[], List<Path>> committedFiles, TreeMap<byte[], MemStoreSize> storeFlushableSize,</span> | 
 | <span class="source-line-no">633</span><span id="line-633">      long startTime, long flushSeqId, long flushedSeqId, MemStoreSizing totalFlushableSize) {</span> | 
 | <span class="source-line-no">634</span><span id="line-634">      this(null, storeFlushCtxs, committedFiles, storeFlushableSize, startTime, flushSeqId,</span> | 
 | <span class="source-line-no">635</span><span id="line-635">        flushedSeqId, totalFlushableSize);</span> | 
 | <span class="source-line-no">636</span><span id="line-636">    }</span> | 
 | <span class="source-line-no">637</span><span id="line-637"></span> | 
 | <span class="source-line-no">638</span><span id="line-638">    private PrepareFlushResult(FlushResultImpl result,</span> | 
 | <span class="source-line-no">639</span><span id="line-639">      TreeMap<byte[], StoreFlushContext> storeFlushCtxs, TreeMap<byte[], List<Path>> committedFiles,</span> | 
 | <span class="source-line-no">640</span><span id="line-640">      TreeMap<byte[], MemStoreSize> storeFlushableSize, long startTime, long flushSeqId,</span> | 
 | <span class="source-line-no">641</span><span id="line-641">      long flushedSeqId, MemStoreSizing totalFlushableSize) {</span> | 
 | <span class="source-line-no">642</span><span id="line-642">      this.result = result;</span> | 
 | <span class="source-line-no">643</span><span id="line-643">      this.storeFlushCtxs = storeFlushCtxs;</span> | 
 | <span class="source-line-no">644</span><span id="line-644">      this.committedFiles = committedFiles;</span> | 
 | <span class="source-line-no">645</span><span id="line-645">      this.storeFlushableSize = storeFlushableSize;</span> | 
 | <span class="source-line-no">646</span><span id="line-646">      this.startTime = startTime;</span> | 
 | <span class="source-line-no">647</span><span id="line-647">      this.flushOpSeqId = flushSeqId;</span> | 
 | <span class="source-line-no">648</span><span id="line-648">      this.flushedSeqId = flushedSeqId;</span> | 
 | <span class="source-line-no">649</span><span id="line-649">      this.totalFlushableSize = totalFlushableSize;</span> | 
 | <span class="source-line-no">650</span><span id="line-650">    }</span> | 
 | <span class="source-line-no">651</span><span id="line-651"></span> | 
 | <span class="source-line-no">652</span><span id="line-652">    public FlushResult getResult() {</span> | 
 | <span class="source-line-no">653</span><span id="line-653">      return this.result;</span> | 
 | <span class="source-line-no">654</span><span id="line-654">    }</span> | 
 | <span class="source-line-no">655</span><span id="line-655">  }</span> | 
 | <span class="source-line-no">656</span><span id="line-656"></span> | 
 | <span class="source-line-no">657</span><span id="line-657">  /**</span> | 
 | <span class="source-line-no">658</span><span id="line-658">   * A class that tracks exceptions that have been observed in one batch. Not thread safe.</span> | 
 | <span class="source-line-no">659</span><span id="line-659">   */</span> | 
 | <span class="source-line-no">660</span><span id="line-660">  static class ObservedExceptionsInBatch {</span> | 
 | <span class="source-line-no">661</span><span id="line-661">    private boolean wrongRegion = false;</span> | 
 | <span class="source-line-no">662</span><span id="line-662">    private boolean failedSanityCheck = false;</span> | 
 | <span class="source-line-no">663</span><span id="line-663">    private boolean wrongFamily = false;</span> | 
 | <span class="source-line-no">664</span><span id="line-664"></span> | 
 | <span class="source-line-no">665</span><span id="line-665">    /** Returns If a {@link WrongRegionException} has been observed. */</span> | 
 | <span class="source-line-no">666</span><span id="line-666">    boolean hasSeenWrongRegion() {</span> | 
 | <span class="source-line-no">667</span><span id="line-667">      return wrongRegion;</span> | 
 | <span class="source-line-no">668</span><span id="line-668">    }</span> | 
 | <span class="source-line-no">669</span><span id="line-669"></span> | 
 | <span class="source-line-no">670</span><span id="line-670">    /**</span> | 
 | <span class="source-line-no">671</span><span id="line-671">     * Records that a {@link WrongRegionException} has been observed.</span> | 
 | <span class="source-line-no">672</span><span id="line-672">     */</span> | 
 | <span class="source-line-no">673</span><span id="line-673">    void sawWrongRegion() {</span> | 
 | <span class="source-line-no">674</span><span id="line-674">      wrongRegion = true;</span> | 
 | <span class="source-line-no">675</span><span id="line-675">    }</span> | 
 | <span class="source-line-no">676</span><span id="line-676"></span> | 
 | <span class="source-line-no">677</span><span id="line-677">    /** Returns If a {@link FailedSanityCheckException} has been observed. */</span> | 
 | <span class="source-line-no">678</span><span id="line-678">    boolean hasSeenFailedSanityCheck() {</span> | 
 | <span class="source-line-no">679</span><span id="line-679">      return failedSanityCheck;</span> | 
 | <span class="source-line-no">680</span><span id="line-680">    }</span> | 
 | <span class="source-line-no">681</span><span id="line-681"></span> | 
 | <span class="source-line-no">682</span><span id="line-682">    /**</span> | 
 | <span class="source-line-no">683</span><span id="line-683">     * Records that a {@link FailedSanityCheckException} has been observed.</span> | 
 | <span class="source-line-no">684</span><span id="line-684">     */</span> | 
 | <span class="source-line-no">685</span><span id="line-685">    void sawFailedSanityCheck() {</span> | 
 | <span class="source-line-no">686</span><span id="line-686">      failedSanityCheck = true;</span> | 
 | <span class="source-line-no">687</span><span id="line-687">    }</span> | 
 | <span class="source-line-no">688</span><span id="line-688"></span> | 
 | <span class="source-line-no">689</span><span id="line-689">    /** Returns If a {@link NoSuchColumnFamilyException} has been observed. */</span> | 
 | <span class="source-line-no">690</span><span id="line-690">    boolean hasSeenNoSuchFamily() {</span> | 
 | <span class="source-line-no">691</span><span id="line-691">      return wrongFamily;</span> | 
 | <span class="source-line-no">692</span><span id="line-692">    }</span> | 
 | <span class="source-line-no">693</span><span id="line-693"></span> | 
 | <span class="source-line-no">694</span><span id="line-694">    /**</span> | 
 | <span class="source-line-no">695</span><span id="line-695">     * Records that a {@link NoSuchColumnFamilyException} has been observed.</span> | 
 | <span class="source-line-no">696</span><span id="line-696">     */</span> | 
 | <span class="source-line-no">697</span><span id="line-697">    void sawNoSuchFamily() {</span> | 
 | <span class="source-line-no">698</span><span id="line-698">      wrongFamily = true;</span> | 
 | <span class="source-line-no">699</span><span id="line-699">    }</span> | 
 | <span class="source-line-no">700</span><span id="line-700">  }</span> | 
 | <span class="source-line-no">701</span><span id="line-701"></span> | 
 | <span class="source-line-no">702</span><span id="line-702">  final WriteState writestate = new WriteState();</span> | 
 | <span class="source-line-no">703</span><span id="line-703"></span> | 
 | <span class="source-line-no">704</span><span id="line-704">  long memstoreFlushSize;</span> | 
 | <span class="source-line-no">705</span><span id="line-705">  final long timestampSlop;</span> | 
 | <span class="source-line-no">706</span><span id="line-706"></span> | 
 | <span class="source-line-no">707</span><span id="line-707">  // Last flush time for each Store. Useful when we are flushing for each column</span> | 
 | <span class="source-line-no">708</span><span id="line-708">  private final ConcurrentMap<HStore, Long> lastStoreFlushTimeMap = new ConcurrentHashMap<>();</span> | 
 | <span class="source-line-no">709</span><span id="line-709"></span> | 
 | <span class="source-line-no">710</span><span id="line-710">  protected RegionServerServices rsServices;</span> | 
 | <span class="source-line-no">711</span><span id="line-711">  private RegionServerAccounting rsAccounting;</span> | 
 | <span class="source-line-no">712</span><span id="line-712">  private long flushCheckInterval;</span> | 
 | <span class="source-line-no">713</span><span id="line-713">  // flushPerChanges is to prevent too many changes in memstore</span> | 
 | <span class="source-line-no">714</span><span id="line-714">  private long flushPerChanges;</span> | 
 | <span class="source-line-no">715</span><span id="line-715">  private long blockingMemStoreSize;</span> | 
 | <span class="source-line-no">716</span><span id="line-716">  // Used to guard closes</span> | 
 | <span class="source-line-no">717</span><span id="line-717">  final ReentrantReadWriteLock lock;</span> | 
 | <span class="source-line-no">718</span><span id="line-718">  // Used to track interruptible holders of the region lock. Currently that is only RPC handler</span> | 
 | <span class="source-line-no">719</span><span id="line-719">  // threads. Boolean value in map determines if lock holder can be interrupted, normally true,</span> | 
 | <span class="source-line-no">720</span><span id="line-720">  // but may be false when thread is transiting a critical section.</span> | 
 | <span class="source-line-no">721</span><span id="line-721">  final ConcurrentHashMap<Thread, Boolean> regionLockHolders;</span> | 
 | <span class="source-line-no">722</span><span id="line-722"></span> | 
 | <span class="source-line-no">723</span><span id="line-723">  // Stop updates lock</span> | 
 | <span class="source-line-no">724</span><span id="line-724">  private final ReentrantReadWriteLock updatesLock = new ReentrantReadWriteLock();</span> | 
 | <span class="source-line-no">725</span><span id="line-725"></span> | 
 | <span class="source-line-no">726</span><span id="line-726">  private final MultiVersionConcurrencyControl mvcc;</span> | 
 | <span class="source-line-no">727</span><span id="line-727"></span> | 
 | <span class="source-line-no">728</span><span id="line-728">  // Coprocessor host</span> | 
 | <span class="source-line-no">729</span><span id="line-729">  private volatile RegionCoprocessorHost coprocessorHost;</span> | 
 | <span class="source-line-no">730</span><span id="line-730"></span> | 
 | <span class="source-line-no">731</span><span id="line-731">  private TableDescriptor htableDescriptor = null;</span> | 
 | <span class="source-line-no">732</span><span id="line-732">  private RegionSplitPolicy splitPolicy;</span> | 
 | <span class="source-line-no">733</span><span id="line-733">  private RegionSplitRestriction splitRestriction;</span> | 
 | <span class="source-line-no">734</span><span id="line-734">  private FlushPolicy flushPolicy;</span> | 
 | <span class="source-line-no">735</span><span id="line-735"></span> | 
 | <span class="source-line-no">736</span><span id="line-736">  private final MetricsRegion metricsRegion;</span> | 
 | <span class="source-line-no">737</span><span id="line-737">  private final MetricsRegionWrapperImpl metricsRegionWrapper;</span> | 
 | <span class="source-line-no">738</span><span id="line-738">  private final Durability regionDurability;</span> | 
 | <span class="source-line-no">739</span><span id="line-739">  private final boolean regionStatsEnabled;</span> | 
 | <span class="source-line-no">740</span><span id="line-740">  // Stores the replication scope of the various column families of the table</span> | 
 | <span class="source-line-no">741</span><span id="line-741">  // that has non-default scope</span> | 
 | <span class="source-line-no">742</span><span id="line-742">  private final NavigableMap<byte[], Integer> replicationScope =</span> | 
 | <span class="source-line-no">743</span><span id="line-743">    new TreeMap<>(Bytes.BYTES_COMPARATOR);</span> | 
 | <span class="source-line-no">744</span><span id="line-744"></span> | 
 | <span class="source-line-no">745</span><span id="line-745">  private final StoreHotnessProtector storeHotnessProtector;</span> | 
 | <span class="source-line-no">746</span><span id="line-746"></span> | 
 | <span class="source-line-no">747</span><span id="line-747">  protected Optional<RegionReplicationSink> regionReplicationSink = Optional.empty();</span> | 
 | <span class="source-line-no">748</span><span id="line-748"></span> | 
 | <span class="source-line-no">749</span><span id="line-749">  /**</span> | 
 | <span class="source-line-no">750</span><span id="line-750">   * HRegion constructor. This constructor should only be used for testing and extensions. Instances</span> | 
 | <span class="source-line-no">751</span><span id="line-751">   * of HRegion should be instantiated with the {@link HRegion#createHRegion} or</span> | 
 | <span class="source-line-no">752</span><span id="line-752">   * {@link HRegion#openHRegion} method.</span> | 
 | <span class="source-line-no">753</span><span id="line-753">   * @param tableDir   qualified path of directory where region should be located, usually the table</span> | 
 | <span class="source-line-no">754</span><span id="line-754">   *                   directory.</span> | 
 | <span class="source-line-no">755</span><span id="line-755">   * @param wal        The WAL is the outbound log for any updates to the HRegion The wal file is a</span> | 
 | <span class="source-line-no">756</span><span id="line-756">   *                   logfile from the previous execution that's custom-computed for this HRegion.</span> | 
 | <span class="source-line-no">757</span><span id="line-757">   *                   The HRegionServer computes and sorts the appropriate wal info for this</span> | 
 | <span class="source-line-no">758</span><span id="line-758">   *                   HRegion. If there is a previous wal file (implying that the HRegion has been</span> | 
 | <span class="source-line-no">759</span><span id="line-759">   *                   written-to before), then read it from the supplied path.</span> | 
 | <span class="source-line-no">760</span><span id="line-760">   * @param fs         is the filesystem.</span> | 
 | <span class="source-line-no">761</span><span id="line-761">   * @param confParam  is global configuration settings.</span> | 
 | <span class="source-line-no">762</span><span id="line-762">   * @param regionInfo - RegionInfo that describes the region is new), then read them from the</span> | 
 | <span class="source-line-no">763</span><span id="line-763">   *                   supplied path.</span> | 
 | <span class="source-line-no">764</span><span id="line-764">   * @param htd        the table descriptor</span> | 
 | <span class="source-line-no">765</span><span id="line-765">   * @param rsServices reference to {@link RegionServerServices} or null</span> | 
 | <span class="source-line-no">766</span><span id="line-766">   * @deprecated Use other constructors.</span> | 
 | <span class="source-line-no">767</span><span id="line-767">   */</span> | 
 | <span class="source-line-no">768</span><span id="line-768">  @Deprecated</span> | 
 | <span class="source-line-no">769</span><span id="line-769">  public HRegion(final Path tableDir, final WAL wal, final FileSystem fs,</span> | 
 | <span class="source-line-no">770</span><span id="line-770">    final Configuration confParam, final RegionInfo regionInfo, final TableDescriptor htd,</span> | 
 | <span class="source-line-no">771</span><span id="line-771">    final RegionServerServices rsServices) {</span> | 
 | <span class="source-line-no">772</span><span id="line-772">    this(new HRegionFileSystem(confParam, fs, tableDir, regionInfo), wal, confParam, htd,</span> | 
 | <span class="source-line-no">773</span><span id="line-773">      rsServices);</span> | 
 | <span class="source-line-no">774</span><span id="line-774">  }</span> | 
 | <span class="source-line-no">775</span><span id="line-775"></span> | 
 | <span class="source-line-no">776</span><span id="line-776">  /**</span> | 
 | <span class="source-line-no">777</span><span id="line-777">   * HRegion constructor. This constructor should only be used for testing and extensions. Instances</span> | 
 | <span class="source-line-no">778</span><span id="line-778">   * of HRegion should be instantiated with the {@link HRegion#createHRegion} or</span> | 
 | <span class="source-line-no">779</span><span id="line-779">   * {@link HRegion#openHRegion} method.</span> | 
 | <span class="source-line-no">780</span><span id="line-780">   * @param fs         is the filesystem.</span> | 
 | <span class="source-line-no">781</span><span id="line-781">   * @param wal        The WAL is the outbound log for any updates to the HRegion The wal file is a</span> | 
 | <span class="source-line-no">782</span><span id="line-782">   *                   logfile from the previous execution that's custom-computed for this HRegion.</span> | 
 | <span class="source-line-no">783</span><span id="line-783">   *                   The HRegionServer computes and sorts the appropriate wal info for this</span> | 
 | <span class="source-line-no">784</span><span id="line-784">   *                   HRegion. If there is a previous wal file (implying that the HRegion has been</span> | 
 | <span class="source-line-no">785</span><span id="line-785">   *                   written-to before), then read it from the supplied path.</span> | 
 | <span class="source-line-no">786</span><span id="line-786">   * @param confParam  is global configuration settings.</span> | 
 | <span class="source-line-no">787</span><span id="line-787">   * @param htd        the table descriptor</span> | 
 | <span class="source-line-no">788</span><span id="line-788">   * @param rsServices reference to {@link RegionServerServices} or null</span> | 
 | <span class="source-line-no">789</span><span id="line-789">   */</span> | 
 | <span class="source-line-no">790</span><span id="line-790">  public HRegion(final HRegionFileSystem fs, final WAL wal, final Configuration confParam,</span> | 
 | <span class="source-line-no">791</span><span id="line-791">    final TableDescriptor htd, final RegionServerServices rsServices) {</span> | 
 | <span class="source-line-no">792</span><span id="line-792">    if (htd == null) {</span> | 
 | <span class="source-line-no">793</span><span id="line-793">      throw new IllegalArgumentException("Need table descriptor");</span> | 
 | <span class="source-line-no">794</span><span id="line-794">    }</span> | 
 | <span class="source-line-no">795</span><span id="line-795"></span> | 
 | <span class="source-line-no">796</span><span id="line-796">    if (confParam instanceof CompoundConfiguration) {</span> | 
 | <span class="source-line-no">797</span><span id="line-797">      throw new IllegalArgumentException("Need original base configuration");</span> | 
 | <span class="source-line-no">798</span><span id="line-798">    }</span> | 
 | <span class="source-line-no">799</span><span id="line-799"></span> | 
 | <span class="source-line-no">800</span><span id="line-800">    this.wal = wal;</span> | 
 | <span class="source-line-no">801</span><span id="line-801">    this.fs = fs;</span> | 
 | <span class="source-line-no">802</span><span id="line-802">    this.mvcc = new MultiVersionConcurrencyControl(getRegionInfo().getShortNameToLog());</span> | 
 | <span class="source-line-no">803</span><span id="line-803"></span> | 
 | <span class="source-line-no">804</span><span id="line-804">    // 'conf' renamed to 'confParam' b/c we use this.conf in the constructor</span> | 
 | <span class="source-line-no">805</span><span id="line-805">    this.baseConf = confParam;</span> | 
 | <span class="source-line-no">806</span><span id="line-806">    this.conf = new CompoundConfiguration().add(confParam).addBytesMap(htd.getValues());</span> | 
 | <span class="source-line-no">807</span><span id="line-807">    this.cellComparator = htd.isMetaTable()</span> | 
 | <span class="source-line-no">808</span><span id="line-808">      || conf.getBoolean(USE_META_CELL_COMPARATOR, DEFAULT_USE_META_CELL_COMPARATOR)</span> | 
 | <span class="source-line-no">809</span><span id="line-809">        ? MetaCellComparator.META_COMPARATOR</span> | 
 | <span class="source-line-no">810</span><span id="line-810">        : CellComparatorImpl.COMPARATOR;</span> | 
 | <span class="source-line-no">811</span><span id="line-811">    this.lock = new ReentrantReadWriteLock(</span> | 
 | <span class="source-line-no">812</span><span id="line-812">      conf.getBoolean(FAIR_REENTRANT_CLOSE_LOCK, DEFAULT_FAIR_REENTRANT_CLOSE_LOCK));</span> | 
 | <span class="source-line-no">813</span><span id="line-813">    this.regionLockHolders = new ConcurrentHashMap<>();</span> | 
 | <span class="source-line-no">814</span><span id="line-814">    this.flushCheckInterval =</span> | 
 | <span class="source-line-no">815</span><span id="line-815">      conf.getInt(MEMSTORE_PERIODIC_FLUSH_INTERVAL, DEFAULT_CACHE_FLUSH_INTERVAL);</span> | 
 | <span class="source-line-no">816</span><span id="line-816">    this.flushPerChanges = conf.getLong(MEMSTORE_FLUSH_PER_CHANGES, DEFAULT_FLUSH_PER_CHANGES);</span> | 
 | <span class="source-line-no">817</span><span id="line-817">    if (this.flushPerChanges > MAX_FLUSH_PER_CHANGES) {</span> | 
 | <span class="source-line-no">818</span><span id="line-818">      throw new IllegalArgumentException(</span> | 
 | <span class="source-line-no">819</span><span id="line-819">        MEMSTORE_FLUSH_PER_CHANGES + " can not exceed " + MAX_FLUSH_PER_CHANGES);</span> | 
 | <span class="source-line-no">820</span><span id="line-820">    }</span> | 
 | <span class="source-line-no">821</span><span id="line-821">    int tmpRowLockDuration =</span> | 
 | <span class="source-line-no">822</span><span id="line-822">      conf.getInt("hbase.rowlock.wait.duration", DEFAULT_ROWLOCK_WAIT_DURATION);</span> | 
 | <span class="source-line-no">823</span><span id="line-823">    if (tmpRowLockDuration <= 0) {</span> | 
 | <span class="source-line-no">824</span><span id="line-824">      LOG.info("Found hbase.rowlock.wait.duration set to {}. values <= 0 will cause all row "</span> | 
 | <span class="source-line-no">825</span><span id="line-825">        + "locking to fail. Treating it as 1ms to avoid region failure.", tmpRowLockDuration);</span> | 
 | <span class="source-line-no">826</span><span id="line-826">      tmpRowLockDuration = 1;</span> | 
 | <span class="source-line-no">827</span><span id="line-827">    }</span> | 
 | <span class="source-line-no">828</span><span id="line-828">    this.rowLockWaitDuration = tmpRowLockDuration;</span> | 
 | <span class="source-line-no">829</span><span id="line-829"></span> | 
 | <span class="source-line-no">830</span><span id="line-830">    this.smallestReadPointCalcLock = new ReadPointCalculationLock(conf);</span> | 
 | <span class="source-line-no">831</span><span id="line-831"></span> | 
 | <span class="source-line-no">832</span><span id="line-832">    this.isLoadingCfsOnDemandDefault = conf.getBoolean(LOAD_CFS_ON_DEMAND_CONFIG_KEY, true);</span> | 
 | <span class="source-line-no">833</span><span id="line-833">    this.htableDescriptor = htd;</span> | 
 | <span class="source-line-no">834</span><span id="line-834">    Set<byte[]> families = this.htableDescriptor.getColumnFamilyNames();</span> | 
 | <span class="source-line-no">835</span><span id="line-835">    for (byte[] family : families) {</span> | 
 | <span class="source-line-no">836</span><span id="line-836">      if (!replicationScope.containsKey(family)) {</span> | 
 | <span class="source-line-no">837</span><span id="line-837">        int scope = htd.getColumnFamily(family).getScope();</span> | 
 | <span class="source-line-no">838</span><span id="line-838">        // Only store those families that has NON-DEFAULT scope</span> | 
 | <span class="source-line-no">839</span><span id="line-839">        if (scope != REPLICATION_SCOPE_LOCAL) {</span> | 
 | <span class="source-line-no">840</span><span id="line-840">          // Do a copy before storing it here.</span> | 
 | <span class="source-line-no">841</span><span id="line-841">          replicationScope.put(Bytes.copy(family), scope);</span> | 
 | <span class="source-line-no">842</span><span id="line-842">        }</span> | 
 | <span class="source-line-no">843</span><span id="line-843">      }</span> | 
 | <span class="source-line-no">844</span><span id="line-844">    }</span> | 
 | <span class="source-line-no">845</span><span id="line-845"></span> | 
 | <span class="source-line-no">846</span><span id="line-846">    this.rsServices = rsServices;</span> | 
 | <span class="source-line-no">847</span><span id="line-847">    if (this.rsServices != null) {</span> | 
 | <span class="source-line-no">848</span><span id="line-848">      this.blockCache = rsServices.getBlockCache().orElse(null);</span> | 
 | <span class="source-line-no">849</span><span id="line-849">      this.mobFileCache = rsServices.getMobFileCache().orElse(null);</span> | 
 | <span class="source-line-no">850</span><span id="line-850">    }</span> | 
 | <span class="source-line-no">851</span><span id="line-851">    this.regionServicesForStores = new RegionServicesForStores(this, rsServices);</span> | 
 | <span class="source-line-no">852</span><span id="line-852"></span> | 
 | <span class="source-line-no">853</span><span id="line-853">    setHTableSpecificConf();</span> | 
 | <span class="source-line-no">854</span><span id="line-854">    this.scannerReadPoints = new ConcurrentHashMap<>();</span> | 
 | <span class="source-line-no">855</span><span id="line-855"></span> | 
 | <span class="source-line-no">856</span><span id="line-856">    this.busyWaitDuration = conf.getLong("hbase.busy.wait.duration", DEFAULT_BUSY_WAIT_DURATION);</span> | 
 | <span class="source-line-no">857</span><span id="line-857">    this.maxBusyWaitMultiplier = conf.getInt("hbase.busy.wait.multiplier.max", 2);</span> | 
 | <span class="source-line-no">858</span><span id="line-858">    if (busyWaitDuration * maxBusyWaitMultiplier <= 0L) {</span> | 
 | <span class="source-line-no">859</span><span id="line-859">      throw new IllegalArgumentException("Invalid hbase.busy.wait.duration (" + busyWaitDuration</span> | 
 | <span class="source-line-no">860</span><span id="line-860">        + ") or hbase.busy.wait.multiplier.max (" + maxBusyWaitMultiplier</span> | 
 | <span class="source-line-no">861</span><span id="line-861">        + "). Their product should be positive");</span> | 
 | <span class="source-line-no">862</span><span id="line-862">    }</span> | 
 | <span class="source-line-no">863</span><span id="line-863">    this.maxBusyWaitDuration =</span> | 
 | <span class="source-line-no">864</span><span id="line-864">      conf.getLong("hbase.ipc.client.call.purge.timeout", 2 * HConstants.DEFAULT_HBASE_RPC_TIMEOUT);</span> | 
 | <span class="source-line-no">865</span><span id="line-865"></span> | 
 | <span class="source-line-no">866</span><span id="line-866">    /*</span> | 
 | <span class="source-line-no">867</span><span id="line-867">     * timestamp.slop provides a server-side constraint on the timestamp. This assumes that you base</span> | 
 | <span class="source-line-no">868</span><span id="line-868">     * your TS around EnvironmentEdgeManager.currentTime(). In this case, throw an error to the user</span> | 
 | <span class="source-line-no">869</span><span id="line-869">     * if the user-specified TS is newer than now + slop. LATEST_TIMESTAMP == don't use this</span> | 
 | <span class="source-line-no">870</span><span id="line-870">     * functionality</span> | 
 | <span class="source-line-no">871</span><span id="line-871">     */</span> | 
 | <span class="source-line-no">872</span><span id="line-872">    this.timestampSlop =</span> | 
 | <span class="source-line-no">873</span><span id="line-873">      conf.getLong("hbase.hregion.keyvalue.timestamp.slop.millisecs", HConstants.LATEST_TIMESTAMP);</span> | 
 | <span class="source-line-no">874</span><span id="line-874"></span> | 
 | <span class="source-line-no">875</span><span id="line-875">    this.storeHotnessProtector = new StoreHotnessProtector(this, conf);</span> | 
 | <span class="source-line-no">876</span><span id="line-876"></span> | 
 | <span class="source-line-no">877</span><span id="line-877">    boolean forceSync = conf.getBoolean(WAL_HSYNC_CONF_KEY, DEFAULT_WAL_HSYNC);</span> | 
 | <span class="source-line-no">878</span><span id="line-878">    /**</span> | 
 | <span class="source-line-no">879</span><span id="line-879">     * This is the global default value for durability. All tables/mutations not defining a</span> | 
 | <span class="source-line-no">880</span><span id="line-880">     * durability or using USE_DEFAULT will default to this value.</span> | 
 | <span class="source-line-no">881</span><span id="line-881">     */</span> | 
 | <span class="source-line-no">882</span><span id="line-882">    Durability defaultDurability = forceSync ? Durability.FSYNC_WAL : Durability.SYNC_WAL;</span> | 
 | <span class="source-line-no">883</span><span id="line-883">    this.regionDurability = this.htableDescriptor.getDurability() == Durability.USE_DEFAULT</span> | 
 | <span class="source-line-no">884</span><span id="line-884">      ? defaultDurability</span> | 
 | <span class="source-line-no">885</span><span id="line-885">      : this.htableDescriptor.getDurability();</span> | 
 | <span class="source-line-no">886</span><span id="line-886"></span> | 
 | <span class="source-line-no">887</span><span id="line-887">    decorateRegionConfiguration(conf);</span> | 
 | <span class="source-line-no">888</span><span id="line-888">    if (rsServices != null) {</span> | 
 | <span class="source-line-no">889</span><span id="line-889">      this.rsAccounting = this.rsServices.getRegionServerAccounting();</span> | 
 | <span class="source-line-no">890</span><span id="line-890">      // don't initialize coprocessors if not running within a regionserver</span> | 
 | <span class="source-line-no">891</span><span id="line-891">      // TODO: revisit if coprocessors should load in other cases</span> | 
 | <span class="source-line-no">892</span><span id="line-892">      this.coprocessorHost = new RegionCoprocessorHost(this, rsServices, conf);</span> | 
 | <span class="source-line-no">893</span><span id="line-893">      this.metricsRegionWrapper = new MetricsRegionWrapperImpl(this);</span> | 
 | <span class="source-line-no">894</span><span id="line-894">      this.metricsRegion = new MetricsRegion(this.metricsRegionWrapper, conf);</span> | 
 | <span class="source-line-no">895</span><span id="line-895">    } else {</span> | 
 | <span class="source-line-no">896</span><span id="line-896">      this.metricsRegionWrapper = null;</span> | 
 | <span class="source-line-no">897</span><span id="line-897">      this.metricsRegion = null;</span> | 
 | <span class="source-line-no">898</span><span id="line-898">    }</span> | 
 | <span class="source-line-no">899</span><span id="line-899">    if (LOG.isDebugEnabled()) {</span> | 
 | <span class="source-line-no">900</span><span id="line-900">      // Write out region name, its encoded name and storeHotnessProtector as string.</span> | 
 | <span class="source-line-no">901</span><span id="line-901">      LOG.debug("Instantiated " + this + "; " + storeHotnessProtector.toString());</span> | 
 | <span class="source-line-no">902</span><span id="line-902">    }</span> | 
 | <span class="source-line-no">903</span><span id="line-903"></span> | 
 | <span class="source-line-no">904</span><span id="line-904">    configurationManager = null;</span> | 
 | <span class="source-line-no">905</span><span id="line-905"></span> | 
 | <span class="source-line-no">906</span><span id="line-906">    // disable stats tracking system tables, but check the config for everything else</span> | 
 | <span class="source-line-no">907</span><span id="line-907">    this.regionStatsEnabled = htd.getTableName().getNamespaceAsString()</span> | 
 | <span class="source-line-no">908</span><span id="line-908">      .equals(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR)</span> | 
 | <span class="source-line-no">909</span><span id="line-909">        ? false</span> | 
 | <span class="source-line-no">910</span><span id="line-910">        : conf.getBoolean(HConstants.ENABLE_CLIENT_BACKPRESSURE,</span> | 
 | <span class="source-line-no">911</span><span id="line-911">          HConstants.DEFAULT_ENABLE_CLIENT_BACKPRESSURE);</span> | 
 | <span class="source-line-no">912</span><span id="line-912"></span> | 
 | <span class="source-line-no">913</span><span id="line-913">    this.maxCellSize = conf.getLong(HBASE_MAX_CELL_SIZE_KEY, DEFAULT_MAX_CELL_SIZE);</span> | 
 | <span class="source-line-no">914</span><span id="line-914">    this.miniBatchSize =</span> | 
 | <span class="source-line-no">915</span><span id="line-915">      conf.getInt(HBASE_REGIONSERVER_MINIBATCH_SIZE, DEFAULT_HBASE_REGIONSERVER_MINIBATCH_SIZE);</span> | 
 | <span class="source-line-no">916</span><span id="line-916"></span> | 
 | <span class="source-line-no">917</span><span id="line-917">    // recover the metrics of read and write requests count if they were retained</span> | 
 | <span class="source-line-no">918</span><span id="line-918">    if (rsServices != null && rsServices.getRegionServerAccounting() != null) {</span> | 
 | <span class="source-line-no">919</span><span id="line-919">      Pair<Long, Long> retainedRWRequestsCnt = rsServices.getRegionServerAccounting()</span> | 
 | <span class="source-line-no">920</span><span id="line-920">        .getRetainedRegionRWRequestsCnt().get(getRegionInfo().getEncodedName());</span> | 
 | <span class="source-line-no">921</span><span id="line-921">      if (retainedRWRequestsCnt != null) {</span> | 
 | <span class="source-line-no">922</span><span id="line-922">        this.addReadRequestsCount(retainedRWRequestsCnt.getFirst());</span> | 
 | <span class="source-line-no">923</span><span id="line-923">        this.addWriteRequestsCount(retainedRWRequestsCnt.getSecond());</span> | 
 | <span class="source-line-no">924</span><span id="line-924">        // remove them since won't use again</span> | 
 | <span class="source-line-no">925</span><span id="line-925">        rsServices.getRegionServerAccounting().getRetainedRegionRWRequestsCnt()</span> | 
 | <span class="source-line-no">926</span><span id="line-926">          .remove(getRegionInfo().getEncodedName());</span> | 
 | <span class="source-line-no">927</span><span id="line-927">      }</span> | 
 | <span class="source-line-no">928</span><span id="line-928">    }</span> | 
 | <span class="source-line-no">929</span><span id="line-929"></span> | 
 | <span class="source-line-no">930</span><span id="line-930">    minBlockSizeBytes = Arrays.stream(this.htableDescriptor.getColumnFamilies())</span> | 
 | <span class="source-line-no">931</span><span id="line-931">      .mapToInt(ColumnFamilyDescriptor::getBlocksize).min().orElse(HConstants.DEFAULT_BLOCKSIZE);</span> | 
 | <span class="source-line-no">932</span><span id="line-932">  }</span> | 
 | <span class="source-line-no">933</span><span id="line-933"></span> | 
 | <span class="source-line-no">934</span><span id="line-934">  private void setHTableSpecificConf() {</span> | 
 | <span class="source-line-no">935</span><span id="line-935">    if (this.htableDescriptor == null) {</span> | 
 | <span class="source-line-no">936</span><span id="line-936">      return;</span> | 
 | <span class="source-line-no">937</span><span id="line-937">    }</span> | 
 | <span class="source-line-no">938</span><span id="line-938">    long flushSize = this.htableDescriptor.getMemStoreFlushSize();</span> | 
 | <span class="source-line-no">939</span><span id="line-939"></span> | 
 | <span class="source-line-no">940</span><span id="line-940">    if (flushSize <= 0) {</span> | 
 | <span class="source-line-no">941</span><span id="line-941">      flushSize = conf.getLong(HConstants.HREGION_MEMSTORE_FLUSH_SIZE,</span> | 
 | <span class="source-line-no">942</span><span id="line-942">        TableDescriptorBuilder.DEFAULT_MEMSTORE_FLUSH_SIZE);</span> | 
 | <span class="source-line-no">943</span><span id="line-943">    }</span> | 
 | <span class="source-line-no">944</span><span id="line-944">    this.memstoreFlushSize = flushSize;</span> | 
 | <span class="source-line-no">945</span><span id="line-945">    long mult = conf.getLong(HConstants.HREGION_MEMSTORE_BLOCK_MULTIPLIER,</span> | 
 | <span class="source-line-no">946</span><span id="line-946">      HConstants.DEFAULT_HREGION_MEMSTORE_BLOCK_MULTIPLIER);</span> | 
 | <span class="source-line-no">947</span><span id="line-947">    this.blockingMemStoreSize = this.memstoreFlushSize * mult;</span> | 
 | <span class="source-line-no">948</span><span id="line-948">  }</span> | 
 | <span class="source-line-no">949</span><span id="line-949"></span> | 
 | <span class="source-line-no">950</span><span id="line-950">  /**</span> | 
 | <span class="source-line-no">951</span><span id="line-951">   * Initialize this region. Used only by tests and SplitTransaction to reopen the region. You</span> | 
 | <span class="source-line-no">952</span><span id="line-952">   * should use createHRegion() or openHRegion()</span> | 
 | <span class="source-line-no">953</span><span id="line-953">   * @return What the next sequence (edit) id should be.</span> | 
 | <span class="source-line-no">954</span><span id="line-954">   * @throws IOException e</span> | 
 | <span class="source-line-no">955</span><span id="line-955">   * @deprecated use HRegion.createHRegion() or HRegion.openHRegion()</span> | 
 | <span class="source-line-no">956</span><span id="line-956">   */</span> | 
 | <span class="source-line-no">957</span><span id="line-957">  @Deprecated</span> | 
 | <span class="source-line-no">958</span><span id="line-958">  public long initialize() throws IOException {</span> | 
 | <span class="source-line-no">959</span><span id="line-959">    return initialize(null);</span> | 
 | <span class="source-line-no">960</span><span id="line-960">  }</span> | 
 | <span class="source-line-no">961</span><span id="line-961"></span> | 
 | <span class="source-line-no">962</span><span id="line-962">  /**</span> | 
 | <span class="source-line-no">963</span><span id="line-963">   * Initialize this region.</span> | 
 | <span class="source-line-no">964</span><span id="line-964">   * @param reporter Tickle every so often if initialize is taking a while.</span> | 
 | <span class="source-line-no">965</span><span id="line-965">   * @return What the next sequence (edit) id should be.</span> | 
 | <span class="source-line-no">966</span><span id="line-966">   */</span> | 
 | <span class="source-line-no">967</span><span id="line-967">  long initialize(final CancelableProgressable reporter) throws IOException {</span> | 
 | <span class="source-line-no">968</span><span id="line-968"></span> | 
 | <span class="source-line-no">969</span><span id="line-969">    // Refuse to open the region if there is no column family in the table</span> | 
 | <span class="source-line-no">970</span><span id="line-970">    if (htableDescriptor.getColumnFamilyCount() == 0) {</span> | 
 | <span class="source-line-no">971</span><span id="line-971">      throw new DoNotRetryIOException("Table " + htableDescriptor.getTableName().getNameAsString()</span> | 
 | <span class="source-line-no">972</span><span id="line-972">        + " should have at least one column family.");</span> | 
 | <span class="source-line-no">973</span><span id="line-973">    }</span> | 
 | <span class="source-line-no">974</span><span id="line-974"></span> | 
 | <span class="source-line-no">975</span><span id="line-975">    MonitoredTask status =</span> | 
 | <span class="source-line-no">976</span><span id="line-976">      TaskMonitor.get().createStatus("Initializing region " + this, false, true);</span> | 
 | <span class="source-line-no">977</span><span id="line-977">    long nextSeqId = -1;</span> | 
 | <span class="source-line-no">978</span><span id="line-978">    try {</span> | 
 | <span class="source-line-no">979</span><span id="line-979">      nextSeqId = initializeRegionInternals(reporter, status);</span> | 
 | <span class="source-line-no">980</span><span id="line-980">      return nextSeqId;</span> | 
 | <span class="source-line-no">981</span><span id="line-981">    } catch (IOException e) {</span> | 
 | <span class="source-line-no">982</span><span id="line-982">      LOG.warn("Failed initialize of region= {}, starting to roll back memstore",</span> | 
 | <span class="source-line-no">983</span><span id="line-983">        getRegionInfo().getRegionNameAsString(), e);</span> | 
 | <span class="source-line-no">984</span><span id="line-984">      // global memstore size will be decreased when dropping memstore</span> | 
 | <span class="source-line-no">985</span><span id="line-985">      try {</span> | 
 | <span class="source-line-no">986</span><span id="line-986">        // drop the memory used by memstore if open region fails</span> | 
 | <span class="source-line-no">987</span><span id="line-987">        dropMemStoreContents();</span> | 
 | <span class="source-line-no">988</span><span id="line-988">      } catch (IOException ioE) {</span> | 
 | <span class="source-line-no">989</span><span id="line-989">        if (conf.getBoolean(MemStoreLAB.USEMSLAB_KEY, MemStoreLAB.USEMSLAB_DEFAULT)) {</span> | 
 | <span class="source-line-no">990</span><span id="line-990">          LOG.warn(</span> | 
 | <span class="source-line-no">991</span><span id="line-991">            "Failed drop memstore of region= {}, "</span> | 
 | <span class="source-line-no">992</span><span id="line-992">              + "some chunks may not released forever since MSLAB is enabled",</span> | 
 | <span class="source-line-no">993</span><span id="line-993">            getRegionInfo().getRegionNameAsString());</span> | 
 | <span class="source-line-no">994</span><span id="line-994">        }</span> | 
 | <span class="source-line-no">995</span><span id="line-995"></span> | 
 | <span class="source-line-no">996</span><span id="line-996">      }</span> | 
 | <span class="source-line-no">997</span><span id="line-997">      if (metricsTableRequests != null) {</span> | 
 | <span class="source-line-no">998</span><span id="line-998">        metricsTableRequests.removeRegistry();</span> | 
 | <span class="source-line-no">999</span><span id="line-999">      }</span> | 
 | <span class="source-line-no">1000</span><span id="line-1000">      throw e;</span> | 
 | <span class="source-line-no">1001</span><span id="line-1001">    } finally {</span> | 
 | <span class="source-line-no">1002</span><span id="line-1002">      // nextSeqid will be -1 if the initialization fails.</span> | 
 | <span class="source-line-no">1003</span><span id="line-1003">      // At least it will be 0 otherwise.</span> | 
 | <span class="source-line-no">1004</span><span id="line-1004">      if (nextSeqId == -1) {</span> | 
 | <span class="source-line-no">1005</span><span id="line-1005">        status.abort("Exception during region " + getRegionInfo().getRegionNameAsString()</span> | 
 | <span class="source-line-no">1006</span><span id="line-1006">          + " initialization.");</span> | 
 | <span class="source-line-no">1007</span><span id="line-1007">      }</span> | 
 | <span class="source-line-no">1008</span><span id="line-1008">      if (LOG.isDebugEnabled()) {</span> | 
 | <span class="source-line-no">1009</span><span id="line-1009">        LOG.debug("Region open journal for {}:\n{}", this.getRegionInfo().getEncodedName(),</span> | 
 | <span class="source-line-no">1010</span><span id="line-1010">          status.prettyPrintJournal());</span> | 
 | <span class="source-line-no">1011</span><span id="line-1011">      }</span> | 
 | <span class="source-line-no">1012</span><span id="line-1012">      status.cleanup();</span> | 
 | <span class="source-line-no">1013</span><span id="line-1013">    }</span> | 
 | <span class="source-line-no">1014</span><span id="line-1014">  }</span> | 
 | <span class="source-line-no">1015</span><span id="line-1015"></span> | 
 | <span class="source-line-no">1016</span><span id="line-1016">  private long initializeRegionInternals(final CancelableProgressable reporter,</span> | 
 | <span class="source-line-no">1017</span><span id="line-1017">    final MonitoredTask status) throws IOException {</span> | 
 | <span class="source-line-no">1018</span><span id="line-1018">    if (coprocessorHost != null) {</span> | 
 | <span class="source-line-no">1019</span><span id="line-1019">      status.setStatus("Running coprocessor pre-open hook");</span> | 
 | <span class="source-line-no">1020</span><span id="line-1020">      coprocessorHost.preOpen();</span> | 
 | <span class="source-line-no">1021</span><span id="line-1021">    }</span> | 
 | <span class="source-line-no">1022</span><span id="line-1022"></span> | 
 | <span class="source-line-no">1023</span><span id="line-1023">    String policyName = this.conf.get(REGION_STORAGE_POLICY_KEY, DEFAULT_REGION_STORAGE_POLICY);</span> | 
 | <span class="source-line-no">1024</span><span id="line-1024">    this.fs.setStoragePolicy(policyName.trim());</span> | 
 | <span class="source-line-no">1025</span><span id="line-1025"></span> | 
 | <span class="source-line-no">1026</span><span id="line-1026">    // Write HRI to a file in case we need to recover hbase:meta</span> | 
 | <span class="source-line-no">1027</span><span id="line-1027">    // Only the primary replica should write .regioninfo</span> | 
 | <span class="source-line-no">1028</span><span id="line-1028">    if (this.getRegionInfo().getReplicaId() == RegionInfo.DEFAULT_REPLICA_ID) {</span> | 
 | <span class="source-line-no">1029</span><span id="line-1029">      status.setStatus("Writing region info on filesystem");</span> | 
 | <span class="source-line-no">1030</span><span id="line-1030">      fs.checkRegionInfoOnFilesystem();</span> | 
 | <span class="source-line-no">1031</span><span id="line-1031">    }</span> | 
 | <span class="source-line-no">1032</span><span id="line-1032"></span> | 
 | <span class="source-line-no">1033</span><span id="line-1033">    // Initialize all the HStores</span> | 
 | <span class="source-line-no">1034</span><span id="line-1034">    status.setStatus("Initializing all the Stores");</span> | 
 | <span class="source-line-no">1035</span><span id="line-1035">    long maxSeqId = initializeStores(reporter, status);</span> | 
 | <span class="source-line-no">1036</span><span id="line-1036">    this.mvcc.advanceTo(maxSeqId);</span> | 
 | <span class="source-line-no">1037</span><span id="line-1037">    if (!isRestoredRegion && ServerRegionReplicaUtil.shouldReplayRecoveredEdits(this)) {</span> | 
 | <span class="source-line-no">1038</span><span id="line-1038">      Collection<HStore> stores = this.stores.values();</span> | 
 | <span class="source-line-no">1039</span><span id="line-1039">      try {</span> | 
 | <span class="source-line-no">1040</span><span id="line-1040">        // update the stores that we are replaying</span> | 
 | <span class="source-line-no">1041</span><span id="line-1041">        LOG.debug("replaying wal for " + this.getRegionInfo().getEncodedName());</span> | 
 | <span class="source-line-no">1042</span><span id="line-1042">        stores.forEach(HStore::startReplayingFromWAL);</span> | 
 | <span class="source-line-no">1043</span><span id="line-1043">        // Recover any edits if available.</span> | 
 | <span class="source-line-no">1044</span><span id="line-1044">        maxSeqId =</span> | 
 | <span class="source-line-no">1045</span><span id="line-1045">          Math.max(maxSeqId, replayRecoveredEditsIfAny(maxSeqIdInStores, reporter, status));</span> | 
 | <span class="source-line-no">1046</span><span id="line-1046">        // Recover any hfiles if available</span> | 
 | <span class="source-line-no">1047</span><span id="line-1047">        maxSeqId = Math.max(maxSeqId, loadRecoveredHFilesIfAny(stores));</span> | 
 | <span class="source-line-no">1048</span><span id="line-1048">        // Make sure mvcc is up to max.</span> | 
 | <span class="source-line-no">1049</span><span id="line-1049">        this.mvcc.advanceTo(maxSeqId);</span> | 
 | <span class="source-line-no">1050</span><span id="line-1050">      } finally {</span> | 
 | <span class="source-line-no">1051</span><span id="line-1051">        LOG.debug("stopping wal replay for " + this.getRegionInfo().getEncodedName());</span> | 
 | <span class="source-line-no">1052</span><span id="line-1052">        // update the stores that we are done replaying</span> | 
 | <span class="source-line-no">1053</span><span id="line-1053">        stores.forEach(HStore::stopReplayingFromWAL);</span> | 
 | <span class="source-line-no">1054</span><span id="line-1054">      }</span> | 
 | <span class="source-line-no">1055</span><span id="line-1055">    }</span> | 
 | <span class="source-line-no">1056</span><span id="line-1056">    this.lastReplayedOpenRegionSeqId = maxSeqId;</span> | 
 | <span class="source-line-no">1057</span><span id="line-1057"></span> | 
 | <span class="source-line-no">1058</span><span id="line-1058">    this.writestate.setReadOnly(ServerRegionReplicaUtil.isReadOnly(this));</span> | 
 | <span class="source-line-no">1059</span><span id="line-1059">    this.writestate.flushRequested = false;</span> | 
 | <span class="source-line-no">1060</span><span id="line-1060">    this.writestate.compacting.set(0);</span> | 
 | <span class="source-line-no">1061</span><span id="line-1061"></span> | 
 | <span class="source-line-no">1062</span><span id="line-1062">    if (this.writestate.writesEnabled) {</span> | 
 | <span class="source-line-no">1063</span><span id="line-1063">      LOG.debug("Cleaning up temporary data for " + this.getRegionInfo().getEncodedName());</span> | 
 | <span class="source-line-no">1064</span><span id="line-1064">      // Remove temporary data left over from old regions</span> | 
 | <span class="source-line-no">1065</span><span id="line-1065">      status.setStatus("Cleaning up temporary data from old regions");</span> | 
 | <span class="source-line-no">1066</span><span id="line-1066">      fs.cleanupTempDir();</span> | 
 | <span class="source-line-no">1067</span><span id="line-1067">    }</span> | 
 | <span class="source-line-no">1068</span><span id="line-1068"></span> | 
 | <span class="source-line-no">1069</span><span id="line-1069">    // Initialize split policy</span> | 
 | <span class="source-line-no">1070</span><span id="line-1070">    this.splitPolicy = RegionSplitPolicy.create(this, conf);</span> | 
 | <span class="source-line-no">1071</span><span id="line-1071"></span> | 
 | <span class="source-line-no">1072</span><span id="line-1072">    // Initialize split restriction</span> | 
 | <span class="source-line-no">1073</span><span id="line-1073">    splitRestriction = RegionSplitRestriction.create(getTableDescriptor(), conf);</span> | 
 | <span class="source-line-no">1074</span><span id="line-1074"></span> | 
 | <span class="source-line-no">1075</span><span id="line-1075">    // Initialize flush policy</span> | 
 | <span class="source-line-no">1076</span><span id="line-1076">    this.flushPolicy = FlushPolicyFactory.create(this, conf);</span> | 
 | <span class="source-line-no">1077</span><span id="line-1077"></span> | 
 | <span class="source-line-no">1078</span><span id="line-1078">    long lastFlushTime = EnvironmentEdgeManager.currentTime();</span> | 
 | <span class="source-line-no">1079</span><span id="line-1079">    for (HStore store : stores.values()) {</span> | 
 | <span class="source-line-no">1080</span><span id="line-1080">      this.lastStoreFlushTimeMap.put(store, lastFlushTime);</span> | 
 | <span class="source-line-no">1081</span><span id="line-1081">    }</span> | 
 | <span class="source-line-no">1082</span><span id="line-1082"></span> | 
 | <span class="source-line-no">1083</span><span id="line-1083">    // Use maximum of log sequenceid or that which was found in stores</span> | 
 | <span class="source-line-no">1084</span><span id="line-1084">    // (particularly if no recovered edits, seqid will be -1).</span> | 
 | <span class="source-line-no">1085</span><span id="line-1085">    long nextSeqId = maxSeqId + 1;</span> | 
 | <span class="source-line-no">1086</span><span id="line-1086">    if (!isRestoredRegion) {</span> | 
 | <span class="source-line-no">1087</span><span id="line-1087">      // always get openSeqNum from the default replica, even if we are secondary replicas</span> | 
 | <span class="source-line-no">1088</span><span id="line-1088">      long maxSeqIdFromFile = WALSplitUtil.getMaxRegionSequenceId(conf,</span> | 
 | <span class="source-line-no">1089</span><span id="line-1089">        RegionReplicaUtil.getRegionInfoForDefaultReplica(getRegionInfo()), this::getFilesystem,</span> | 
 | <span class="source-line-no">1090</span><span id="line-1090">        this::getWalFileSystem);</span> | 
 | <span class="source-line-no">1091</span><span id="line-1091">      nextSeqId = Math.max(maxSeqId, maxSeqIdFromFile) + 1;</span> | 
 | <span class="source-line-no">1092</span><span id="line-1092">      // The openSeqNum will always be increase even for read only region, as we rely on it to</span> | 
 | <span class="source-line-no">1093</span><span id="line-1093">      // determine whether a region has been successfully reopened, so here we always need to update</span> | 
 | <span class="source-line-no">1094</span><span id="line-1094">      // the max sequence id file.</span> | 
 | <span class="source-line-no">1095</span><span id="line-1095">      if (RegionReplicaUtil.isDefaultReplica(getRegionInfo())) {</span> | 
 | <span class="source-line-no">1096</span><span id="line-1096">        LOG.debug("writing seq id for {}", this.getRegionInfo().getEncodedName());</span> | 
 | <span class="source-line-no">1097</span><span id="line-1097">        WALSplitUtil.writeRegionSequenceIdFile(getWalFileSystem(), getWALRegionDir(),</span> | 
 | <span class="source-line-no">1098</span><span id="line-1098">          nextSeqId - 1);</span> | 
 | <span class="source-line-no">1099</span><span id="line-1099">        // This means we have replayed all the recovered edits and also written out the max sequence</span> | 
 | <span class="source-line-no">1100</span><span id="line-1100">        // id file, let's delete the wrong directories introduced in HBASE-20734, see HBASE-22617</span> | 
 | <span class="source-line-no">1101</span><span id="line-1101">        // for more details.</span> | 
 | <span class="source-line-no">1102</span><span id="line-1102">        Path wrongRegionWALDir = CommonFSUtils.getWrongWALRegionDir(conf,</span> | 
 | <span class="source-line-no">1103</span><span id="line-1103">          getRegionInfo().getTable(), getRegionInfo().getEncodedName());</span> | 
 | <span class="source-line-no">1104</span><span id="line-1104">        FileSystem walFs = getWalFileSystem();</span> | 
 | <span class="source-line-no">1105</span><span id="line-1105">        if (walFs.exists(wrongRegionWALDir)) {</span> | 
 | <span class="source-line-no">1106</span><span id="line-1106">          if (!walFs.delete(wrongRegionWALDir, true)) {</span> | 
 | <span class="source-line-no">1107</span><span id="line-1107">            LOG.debug("Failed to clean up wrong region WAL directory {}", wrongRegionWALDir);</span> | 
 | <span class="source-line-no">1108</span><span id="line-1108">          }</span> | 
 | <span class="source-line-no">1109</span><span id="line-1109">        }</span> | 
 | <span class="source-line-no">1110</span><span id="line-1110">      } else {</span> | 
 | <span class="source-line-no">1111</span><span id="line-1111">        lastReplayedSequenceId = nextSeqId - 1;</span> | 
 | <span class="source-line-no">1112</span><span id="line-1112">        replayLock = new ReentrantLock();</span> | 
 | <span class="source-line-no">1113</span><span id="line-1113">      }</span> | 
 | <span class="source-line-no">1114</span><span id="line-1114">      initializeRegionReplicationSink(reporter, status);</span> | 
 | <span class="source-line-no">1115</span><span id="line-1115">    }</span> | 
 | <span class="source-line-no">1116</span><span id="line-1116"></span> | 
 | <span class="source-line-no">1117</span><span id="line-1117">    LOG.info("Opened {}; next sequenceid={}; {}, {}", this.getRegionInfo().getShortNameToLog(),</span> | 
 | <span class="source-line-no">1118</span><span id="line-1118">      nextSeqId, this.splitPolicy, this.flushPolicy);</span> | 
 | <span class="source-line-no">1119</span><span id="line-1119"></span> | 
 | <span class="source-line-no">1120</span><span id="line-1120">    // A region can be reopened if failed a split; reset flags</span> | 
 | <span class="source-line-no">1121</span><span id="line-1121">    this.closing.set(false);</span> | 
 | <span class="source-line-no">1122</span><span id="line-1122">    this.closed.set(false);</span> | 
 | <span class="source-line-no">1123</span><span id="line-1123"></span> | 
 | <span class="source-line-no">1124</span><span id="line-1124">    if (coprocessorHost != null) {</span> | 
 | <span class="source-line-no">1125</span><span id="line-1125">      LOG.debug("Running coprocessor post-open hooks for " + this.getRegionInfo().getEncodedName());</span> | 
 | <span class="source-line-no">1126</span><span id="line-1126">      status.setStatus("Running coprocessor post-open hooks");</span> | 
 | <span class="source-line-no">1127</span><span id="line-1127">      coprocessorHost.postOpen();</span> | 
 | <span class="source-line-no">1128</span><span id="line-1128">    }</span> | 
 | <span class="source-line-no">1129</span><span id="line-1129"></span> | 
 | <span class="source-line-no">1130</span><span id="line-1130">    metricsTableRequests = new MetricsTableRequests(htableDescriptor.getTableName(), conf);</span> | 
 | <span class="source-line-no">1131</span><span id="line-1131"></span> | 
 | <span class="source-line-no">1132</span><span id="line-1132">    status.markComplete("Region opened successfully");</span> | 
 | <span class="source-line-no">1133</span><span id="line-1133">    return nextSeqId;</span> | 
 | <span class="source-line-no">1134</span><span id="line-1134">  }</span> | 
 | <span class="source-line-no">1135</span><span id="line-1135"></span> | 
 | <span class="source-line-no">1136</span><span id="line-1136">  private void initializeRegionReplicationSink(CancelableProgressable reporter,</span> | 
 | <span class="source-line-no">1137</span><span id="line-1137">    MonitoredTask status) {</span> | 
 | <span class="source-line-no">1138</span><span id="line-1138">    RegionServerServices rss = getRegionServerServices();</span> | 
 | <span class="source-line-no">1139</span><span id="line-1139">    TableDescriptor td = getTableDescriptor();</span> | 
 | <span class="source-line-no">1140</span><span id="line-1140">    int regionReplication = td.getRegionReplication();</span> | 
 | <span class="source-line-no">1141</span><span id="line-1141">    RegionInfo regionInfo = getRegionInfo();</span> | 
 | <span class="source-line-no">1142</span><span id="line-1142">    if (</span> | 
 | <span class="source-line-no">1143</span><span id="line-1143">      regionReplication <= 1 || !RegionReplicaUtil.isDefaultReplica(regionInfo)</span> | 
 | <span class="source-line-no">1144</span><span id="line-1144">        || !ServerRegionReplicaUtil.isRegionReplicaReplicationEnabled(conf, regionInfo.getTable())</span> | 
 | <span class="source-line-no">1145</span><span id="line-1145">        || rss == null</span> | 
 | <span class="source-line-no">1146</span><span id="line-1146">    ) {</span> | 
 | <span class="source-line-no">1147</span><span id="line-1147">      regionReplicationSink = Optional.empty();</span> | 
 | <span class="source-line-no">1148</span><span id="line-1148">      return;</span> | 
 | <span class="source-line-no">1149</span><span id="line-1149">    }</span> | 
 | <span class="source-line-no">1150</span><span id="line-1150">    status.setStatus("Initializaing region replication sink");</span> | 
 | <span class="source-line-no">1151</span><span id="line-1151">    regionReplicationSink = Optional.of(new RegionReplicationSink(conf, regionInfo, td,</span> | 
 | <span class="source-line-no">1152</span><span id="line-1152">      rss.getRegionReplicationBufferManager(), () -> rss.getFlushRequester().requestFlush(this,</span> | 
 | <span class="source-line-no">1153</span><span id="line-1153">        new ArrayList<>(td.getColumnFamilyNames()), FlushLifeCycleTracker.DUMMY),</span> | 
 | <span class="source-line-no">1154</span><span id="line-1154">      rss.getAsyncClusterConnection()));</span> | 
 | <span class="source-line-no">1155</span><span id="line-1155">  }</span> | 
 | <span class="source-line-no">1156</span><span id="line-1156"></span> | 
 | <span class="source-line-no">1157</span><span id="line-1157">  /**</span> | 
 | <span class="source-line-no">1158</span><span id="line-1158">   * Open all Stores.</span> | 
 | <span class="source-line-no">1159</span><span id="line-1159">   * @return Highest sequenceId found out in a Store.</span> | 
 | <span class="source-line-no">1160</span><span id="line-1160">   */</span> | 
 | <span class="source-line-no">1161</span><span id="line-1161">  private long initializeStores(CancelableProgressable reporter, MonitoredTask status)</span> | 
 | <span class="source-line-no">1162</span><span id="line-1162">    throws IOException {</span> | 
 | <span class="source-line-no">1163</span><span id="line-1163">    return initializeStores(reporter, status, false);</span> | 
 | <span class="source-line-no">1164</span><span id="line-1164">  }</span> | 
 | <span class="source-line-no">1165</span><span id="line-1165"></span> | 
 | <span class="source-line-no">1166</span><span id="line-1166">  private long initializeStores(CancelableProgressable reporter, MonitoredTask status,</span> | 
 | <span class="source-line-no">1167</span><span id="line-1167">    boolean warmup) throws IOException {</span> | 
 | <span class="source-line-no">1168</span><span id="line-1168">    // Load in all the HStores.</span> | 
 | <span class="source-line-no">1169</span><span id="line-1169">    long maxSeqId = -1;</span> | 
 | <span class="source-line-no">1170</span><span id="line-1170">    // initialized to -1 so that we pick up MemstoreTS from column families</span> | 
 | <span class="source-line-no">1171</span><span id="line-1171">    long maxMemstoreTS = -1;</span> | 
 | <span class="source-line-no">1172</span><span id="line-1172"></span> | 
 | <span class="source-line-no">1173</span><span id="line-1173">    if (htableDescriptor.getColumnFamilyCount() != 0) {</span> | 
 | <span class="source-line-no">1174</span><span id="line-1174">      // initialize the thread pool for opening stores in parallel.</span> | 
 | <span class="source-line-no">1175</span><span id="line-1175">      ThreadPoolExecutor storeOpenerThreadPool =</span> | 
 | <span class="source-line-no">1176</span><span id="line-1176">        getStoreOpenAndCloseThreadPool("StoreOpener-" + this.getRegionInfo().getShortNameToLog());</span> | 
 | <span class="source-line-no">1177</span><span id="line-1177">      CompletionService<HStore> completionService =</span> | 
 | <span class="source-line-no">1178</span><span id="line-1178">        new ExecutorCompletionService<>(storeOpenerThreadPool);</span> | 
 | <span class="source-line-no">1179</span><span id="line-1179"></span> | 
 | <span class="source-line-no">1180</span><span id="line-1180">      // initialize each store in parallel</span> | 
 | <span class="source-line-no">1181</span><span id="line-1181">      for (final ColumnFamilyDescriptor family : htableDescriptor.getColumnFamilies()) {</span> | 
 | <span class="source-line-no">1182</span><span id="line-1182">        status.setStatus("Instantiating store for column family " + family);</span> | 
 | <span class="source-line-no">1183</span><span id="line-1183">        completionService.submit(new Callable<HStore>() {</span> | 
 | <span class="source-line-no">1184</span><span id="line-1184">          @Override</span> | 
 | <span class="source-line-no">1185</span><span id="line-1185">          public HStore call() throws IOException {</span> | 
 | <span class="source-line-no">1186</span><span id="line-1186">            return instantiateHStore(family, warmup);</span> | 
 | <span class="source-line-no">1187</span><span id="line-1187">          }</span> | 
 | <span class="source-line-no">1188</span><span id="line-1188">        });</span> | 
 | <span class="source-line-no">1189</span><span id="line-1189">      }</span> | 
 | <span class="source-line-no">1190</span><span id="line-1190">      boolean allStoresOpened = false;</span> | 
 | <span class="source-line-no">1191</span><span id="line-1191">      boolean hasSloppyStores = false;</span> | 
 | <span class="source-line-no">1192</span><span id="line-1192">      try {</span> | 
 | <span class="source-line-no">1193</span><span id="line-1193">        for (int i = 0; i < htableDescriptor.getColumnFamilyCount(); i++) {</span> | 
 | <span class="source-line-no">1194</span><span id="line-1194">          Future<HStore> future = completionService.take();</span> | 
 | <span class="source-line-no">1195</span><span id="line-1195">          HStore store = future.get();</span> | 
 | <span class="source-line-no">1196</span><span id="line-1196">          this.stores.put(store.getColumnFamilyDescriptor().getName(), store);</span> | 
 | <span class="source-line-no">1197</span><span id="line-1197">          if (store.isSloppyMemStore()) {</span> | 
 | <span class="source-line-no">1198</span><span id="line-1198">            hasSloppyStores = true;</span> | 
 | <span class="source-line-no">1199</span><span id="line-1199">          }</span> | 
 | <span class="source-line-no">1200</span><span id="line-1200"></span> | 
 | <span class="source-line-no">1201</span><span id="line-1201">          long storeMaxSequenceId = store.getMaxSequenceId().orElse(0L);</span> | 
 | <span class="source-line-no">1202</span><span id="line-1202">          maxSeqIdInStores.put(Bytes.toBytes(store.getColumnFamilyName()), storeMaxSequenceId);</span> | 
 | <span class="source-line-no">1203</span><span id="line-1203">          if (maxSeqId == -1 || storeMaxSequenceId > maxSeqId) {</span> | 
 | <span class="source-line-no">1204</span><span id="line-1204">            maxSeqId = storeMaxSequenceId;</span> | 
 | <span class="source-line-no">1205</span><span id="line-1205">          }</span> | 
 | <span class="source-line-no">1206</span><span id="line-1206">          long maxStoreMemstoreTS = store.getMaxMemStoreTS().orElse(0L);</span> | 
 | <span class="source-line-no">1207</span><span id="line-1207">          if (maxStoreMemstoreTS > maxMemstoreTS) {</span> | 
 | <span class="source-line-no">1208</span><span id="line-1208">            maxMemstoreTS = maxStoreMemstoreTS;</span> | 
 | <span class="source-line-no">1209</span><span id="line-1209">          }</span> | 
 | <span class="source-line-no">1210</span><span id="line-1210">        }</span> | 
 | <span class="source-line-no">1211</span><span id="line-1211">        allStoresOpened = true;</span> | 
 | <span class="source-line-no">1212</span><span id="line-1212">        if (hasSloppyStores) {</span> | 
 | <span class="source-line-no">1213</span><span id="line-1213">          htableDescriptor = TableDescriptorBuilder.newBuilder(htableDescriptor)</span> | 
 | <span class="source-line-no">1214</span><span id="line-1214">            .setFlushPolicyClassName(FlushNonSloppyStoresFirstPolicy.class.getName()).build();</span> | 
 | <span class="source-line-no">1215</span><span id="line-1215">          LOG.info("Setting FlushNonSloppyStoresFirstPolicy for the region=" + this);</span> | 
 | <span class="source-line-no">1216</span><span id="line-1216">        }</span> | 
 | <span class="source-line-no">1217</span><span id="line-1217">      } catch (InterruptedException e) {</span> | 
 | <span class="source-line-no">1218</span><span id="line-1218">        throw throwOnInterrupt(e);</span> | 
 | <span class="source-line-no">1219</span><span id="line-1219">      } catch (ExecutionException e) {</span> | 
 | <span class="source-line-no">1220</span><span id="line-1220">        throw new IOException(e.getCause());</span> | 
 | <span class="source-line-no">1221</span><span id="line-1221">      } finally {</span> | 
 | <span class="source-line-no">1222</span><span id="line-1222">        storeOpenerThreadPool.shutdownNow();</span> | 
 | <span class="source-line-no">1223</span><span id="line-1223">        if (!allStoresOpened) {</span> | 
 | <span class="source-line-no">1224</span><span id="line-1224">          // something went wrong, close all opened stores</span> | 
 | <span class="source-line-no">1225</span><span id="line-1225">          LOG.error("Could not initialize all stores for the region=" + this);</span> | 
 | <span class="source-line-no">1226</span><span id="line-1226">          for (HStore store : this.stores.values()) {</span> | 
 | <span class="source-line-no">1227</span><span id="line-1227">            try {</span> | 
 | <span class="source-line-no">1228</span><span id="line-1228">              store.close();</span> | 
 | <span class="source-line-no">1229</span><span id="line-1229">            } catch (IOException e) {</span> | 
 | <span class="source-line-no">1230</span><span id="line-1230">              LOG.warn("close store {} failed in region {}", store.toString(), this, e);</span> | 
 | <span class="source-line-no">1231</span><span id="line-1231">            }</span> | 
 | <span class="source-line-no">1232</span><span id="line-1232">          }</span> | 
 | <span class="source-line-no">1233</span><span id="line-1233">        }</span> | 
 | <span class="source-line-no">1234</span><span id="line-1234">      }</span> | 
 | <span class="source-line-no">1235</span><span id="line-1235">    }</span> | 
 | <span class="source-line-no">1236</span><span id="line-1236">    return Math.max(maxSeqId, maxMemstoreTS + 1);</span> | 
 | <span class="source-line-no">1237</span><span id="line-1237">  }</span> | 
 | <span class="source-line-no">1238</span><span id="line-1238"></span> | 
 | <span class="source-line-no">1239</span><span id="line-1239">  private void initializeWarmup(final CancelableProgressable reporter) throws IOException {</span> | 
 | <span class="source-line-no">1240</span><span id="line-1240">    MonitoredTask status = TaskMonitor.get().createStatus("Initializing region " + this);</span> | 
 | <span class="source-line-no">1241</span><span id="line-1241">    // Initialize all the HStores</span> | 
 | <span class="source-line-no">1242</span><span id="line-1242">    status.setStatus("Warmup all stores of " + this.getRegionInfo().getRegionNameAsString());</span> | 
 | <span class="source-line-no">1243</span><span id="line-1243">    try {</span> | 
 | <span class="source-line-no">1244</span><span id="line-1244">      initializeStores(reporter, status, true);</span> | 
 | <span class="source-line-no">1245</span><span id="line-1245">    } finally {</span> | 
 | <span class="source-line-no">1246</span><span id="line-1246">      status.markComplete("Warmed up " + this.getRegionInfo().getRegionNameAsString());</span> | 
 | <span class="source-line-no">1247</span><span id="line-1247">    }</span> | 
 | <span class="source-line-no">1248</span><span id="line-1248">  }</span> | 
 | <span class="source-line-no">1249</span><span id="line-1249"></span> | 
 | <span class="source-line-no">1250</span><span id="line-1250">  /** Returns Map of StoreFiles by column family */</span> | 
 | <span class="source-line-no">1251</span><span id="line-1251">  private NavigableMap<byte[], List<Path>> getStoreFiles() {</span> | 
 | <span class="source-line-no">1252</span><span id="line-1252">    NavigableMap<byte[], List<Path>> allStoreFiles = new TreeMap<>(Bytes.BYTES_COMPARATOR);</span> | 
 | <span class="source-line-no">1253</span><span id="line-1253">    for (HStore store : stores.values()) {</span> | 
 | <span class="source-line-no">1254</span><span id="line-1254">      Collection<HStoreFile> storeFiles = store.getStorefiles();</span> | 
 | <span class="source-line-no">1255</span><span id="line-1255">      if (storeFiles == null) {</span> | 
 | <span class="source-line-no">1256</span><span id="line-1256">        continue;</span> | 
 | <span class="source-line-no">1257</span><span id="line-1257">      }</span> | 
 | <span class="source-line-no">1258</span><span id="line-1258">      List<Path> storeFileNames = new ArrayList<>();</span> | 
 | <span class="source-line-no">1259</span><span id="line-1259">      for (HStoreFile storeFile : storeFiles) {</span> | 
 | <span class="source-line-no">1260</span><span id="line-1260">        storeFileNames.add(storeFile.getPath());</span> | 
 | <span class="source-line-no">1261</span><span id="line-1261">      }</span> | 
 | <span class="source-line-no">1262</span><span id="line-1262">      allStoreFiles.put(store.getColumnFamilyDescriptor().getName(), storeFileNames);</span> | 
 | <span class="source-line-no">1263</span><span id="line-1263">    }</span> | 
 | <span class="source-line-no">1264</span><span id="line-1264">    return allStoreFiles;</span> | 
 | <span class="source-line-no">1265</span><span id="line-1265">  }</span> | 
 | <span class="source-line-no">1266</span><span id="line-1266"></span> | 
 | <span class="source-line-no">1267</span><span id="line-1267">  protected void writeRegionOpenMarker(WAL wal, long openSeqId) throws IOException {</span> | 
 | <span class="source-line-no">1268</span><span id="line-1268">    Map<byte[], List<Path>> storeFiles = getStoreFiles();</span> | 
 | <span class="source-line-no">1269</span><span id="line-1269">    RegionEventDescriptor regionOpenDesc =</span> | 
 | <span class="source-line-no">1270</span><span id="line-1270">      ProtobufUtil.toRegionEventDescriptor(RegionEventDescriptor.EventType.REGION_OPEN,</span> | 
 | <span class="source-line-no">1271</span><span id="line-1271">        getRegionInfo(), openSeqId, getRegionServerServices().getServerName(), storeFiles);</span> | 
 | <span class="source-line-no">1272</span><span id="line-1272">    WALUtil.writeRegionEventMarker(wal, getReplicationScope(), getRegionInfo(), regionOpenDesc,</span> | 
 | <span class="source-line-no">1273</span><span id="line-1273">      mvcc, regionReplicationSink.orElse(null));</span> | 
 | <span class="source-line-no">1274</span><span id="line-1274">  }</span> | 
 | <span class="source-line-no">1275</span><span id="line-1275"></span> | 
 | <span class="source-line-no">1276</span><span id="line-1276">  private void writeRegionCloseMarker(WAL wal) throws IOException {</span> | 
 | <span class="source-line-no">1277</span><span id="line-1277">    Map<byte[], List<Path>> storeFiles = getStoreFiles();</span> | 
 | <span class="source-line-no">1278</span><span id="line-1278">    RegionEventDescriptor regionEventDesc = ProtobufUtil.toRegionEventDescriptor(</span> | 
 | <span class="source-line-no">1279</span><span id="line-1279">      RegionEventDescriptor.EventType.REGION_CLOSE, getRegionInfo(), mvcc.getReadPoint(),</span> | 
 | <span class="source-line-no">1280</span><span id="line-1280">      getRegionServerServices().getServerName(), storeFiles);</span> | 
 | <span class="source-line-no">1281</span><span id="line-1281">    // we do not care region close event at secondary replica side so just pass a null</span> | 
 | <span class="source-line-no">1282</span><span id="line-1282">    // RegionReplicationSink</span> | 
 | <span class="source-line-no">1283</span><span id="line-1283">    WALUtil.writeRegionEventMarker(wal, getReplicationScope(), getRegionInfo(), regionEventDesc,</span> | 
 | <span class="source-line-no">1284</span><span id="line-1284">      mvcc, null);</span> | 
 | <span class="source-line-no">1285</span><span id="line-1285"></span> | 
 | <span class="source-line-no">1286</span><span id="line-1286">    // Store SeqId in WAL FileSystem when a region closes</span> | 
 | <span class="source-line-no">1287</span><span id="line-1287">    // checking region folder exists is due to many tests which delete the table folder while a</span> | 
 | <span class="source-line-no">1288</span><span id="line-1288">    // table is still online</span> | 
 | <span class="source-line-no">1289</span><span id="line-1289">    if (getWalFileSystem().exists(getWALRegionDir())) {</span> | 
 | <span class="source-line-no">1290</span><span id="line-1290">      WALSplitUtil.writeRegionSequenceIdFile(getWalFileSystem(), getWALRegionDir(),</span> | 
 | <span class="source-line-no">1291</span><span id="line-1291">        mvcc.getReadPoint());</span> | 
 | <span class="source-line-no">1292</span><span id="line-1292">    }</span> | 
 | <span class="source-line-no">1293</span><span id="line-1293">  }</span> | 
 | <span class="source-line-no">1294</span><span id="line-1294"></span> | 
 | <span class="source-line-no">1295</span><span id="line-1295">  /** Returns True if this region has references. */</span> | 
 | <span class="source-line-no">1296</span><span id="line-1296">  public boolean hasReferences() {</span> | 
 | <span class="source-line-no">1297</span><span id="line-1297">    return stores.values().stream().anyMatch(HStore::hasReferences);</span> | 
 | <span class="source-line-no">1298</span><span id="line-1298">  }</span> | 
 | <span class="source-line-no">1299</span><span id="line-1299"></span> | 
 | <span class="source-line-no">1300</span><span id="line-1300">  public void blockUpdates() {</span> | 
 | <span class="source-line-no">1301</span><span id="line-1301">    this.updatesLock.writeLock().lock();</span> | 
 | <span class="source-line-no">1302</span><span id="line-1302">  }</span> | 
 | <span class="source-line-no">1303</span><span id="line-1303"></span> | 
 | <span class="source-line-no">1304</span><span id="line-1304">  public void unblockUpdates() {</span> | 
 | <span class="source-line-no">1305</span><span id="line-1305">    this.updatesLock.writeLock().unlock();</span> | 
 | <span class="source-line-no">1306</span><span id="line-1306">  }</span> | 
 | <span class="source-line-no">1307</span><span id="line-1307"></span> | 
 | <span class="source-line-no">1308</span><span id="line-1308">  public HDFSBlocksDistribution getHDFSBlocksDistribution() {</span> | 
 | <span class="source-line-no">1309</span><span id="line-1309">    HDFSBlocksDistribution hdfsBlocksDistribution = new HDFSBlocksDistribution();</span> | 
 | <span class="source-line-no">1310</span><span id="line-1310">    stores.values().stream().filter(s -> s.getStorefiles() != null)</span> | 
 | <span class="source-line-no">1311</span><span id="line-1311">      .flatMap(s -> s.getStorefiles().stream()).map(HStoreFile::getHDFSBlockDistribution)</span> | 
 | <span class="source-line-no">1312</span><span id="line-1312">      .forEachOrdered(hdfsBlocksDistribution::add);</span> | 
 | <span class="source-line-no">1313</span><span id="line-1313">    return hdfsBlocksDistribution;</span> | 
 | <span class="source-line-no">1314</span><span id="line-1314">  }</span> | 
 | <span class="source-line-no">1315</span><span id="line-1315"></span> | 
 | <span class="source-line-no">1316</span><span id="line-1316">  /**</span> | 
 | <span class="source-line-no">1317</span><span id="line-1317">   * This is a helper function to compute HDFS block distribution on demand</span> | 
 | <span class="source-line-no">1318</span><span id="line-1318">   * @param conf            configuration</span> | 
 | <span class="source-line-no">1319</span><span id="line-1319">   * @param tableDescriptor TableDescriptor of the table</span> | 
 | <span class="source-line-no">1320</span><span id="line-1320">   * @param regionInfo      encoded name of the region</span> | 
 | <span class="source-line-no">1321</span><span id="line-1321">   * @return The HDFS blocks distribution for the given region.</span> | 
 | <span class="source-line-no">1322</span><span id="line-1322">   */</span> | 
 | <span class="source-line-no">1323</span><span id="line-1323">  public static HDFSBlocksDistribution computeHDFSBlocksDistribution(Configuration conf,</span> | 
 | <span class="source-line-no">1324</span><span id="line-1324">    TableDescriptor tableDescriptor, RegionInfo regionInfo) throws IOException {</span> | 
 | <span class="source-line-no">1325</span><span id="line-1325">    Path tablePath =</span> | 
 | <span class="source-line-no">1326</span><span id="line-1326">      CommonFSUtils.getTableDir(CommonFSUtils.getRootDir(conf), tableDescriptor.getTableName());</span> | 
 | <span class="source-line-no">1327</span><span id="line-1327">    return computeHDFSBlocksDistribution(conf, tableDescriptor, regionInfo, tablePath);</span> | 
 | <span class="source-line-no">1328</span><span id="line-1328">  }</span> | 
 | <span class="source-line-no">1329</span><span id="line-1329"></span> | 
 | <span class="source-line-no">1330</span><span id="line-1330">  /**</span> | 
 | <span class="source-line-no">1331</span><span id="line-1331">   * This is a helper function to compute HDFS block distribution on demand</span> | 
 | <span class="source-line-no">1332</span><span id="line-1332">   * @param conf            configuration</span> | 
 | <span class="source-line-no">1333</span><span id="line-1333">   * @param tableDescriptor TableDescriptor of the table</span> | 
 | <span class="source-line-no">1334</span><span id="line-1334">   * @param regionInfo      encoded name of the region</span> | 
 | <span class="source-line-no">1335</span><span id="line-1335">   * @param tablePath       the table directory</span> | 
 | <span class="source-line-no">1336</span><span id="line-1336">   * @return The HDFS blocks distribution for the given region.</span> | 
 | <span class="source-line-no">1337</span><span id="line-1337">   */</span> | 
 | <span class="source-line-no">1338</span><span id="line-1338">  public static HDFSBlocksDistribution computeHDFSBlocksDistribution(Configuration conf,</span> | 
 | <span class="source-line-no">1339</span><span id="line-1339">    TableDescriptor tableDescriptor, RegionInfo regionInfo, Path tablePath) throws IOException {</span> | 
 | <span class="source-line-no">1340</span><span id="line-1340">    HDFSBlocksDistribution hdfsBlocksDistribution = new HDFSBlocksDistribution();</span> | 
 | <span class="source-line-no">1341</span><span id="line-1341">    FileSystem fs = tablePath.getFileSystem(conf);</span> | 
 | <span class="source-line-no">1342</span><span id="line-1342"></span> | 
 | <span class="source-line-no">1343</span><span id="line-1343">    HRegionFileSystem regionFs = new HRegionFileSystem(conf, fs, tablePath, regionInfo);</span> | 
 | <span class="source-line-no">1344</span><span id="line-1344">    for (ColumnFamilyDescriptor family : tableDescriptor.getColumnFamilies()) {</span> | 
 | <span class="source-line-no">1345</span><span id="line-1345">      List<LocatedFileStatus> locatedFileStatusList =</span> | 
 | <span class="source-line-no">1346</span><span id="line-1346">        HRegionFileSystem.getStoreFilesLocatedStatus(regionFs, family.getNameAsString(), true);</span> | 
 | <span class="source-line-no">1347</span><span id="line-1347">      if (locatedFileStatusList == null) {</span> | 
 | <span class="source-line-no">1348</span><span id="line-1348">        continue;</span> | 
 | <span class="source-line-no">1349</span><span id="line-1349">      }</span> | 
 | <span class="source-line-no">1350</span><span id="line-1350"></span> | 
 | <span class="source-line-no">1351</span><span id="line-1351">      for (LocatedFileStatus status : locatedFileStatusList) {</span> | 
 | <span class="source-line-no">1352</span><span id="line-1352">        Path p = status.getPath();</span> | 
 | <span class="source-line-no">1353</span><span id="line-1353">        if (StoreFileInfo.isReference(p) || HFileLink.isHFileLink(p)) {</span> | 
 | <span class="source-line-no">1354</span><span id="line-1354">          // Only construct StoreFileInfo object if its not a hfile, save obj</span> | 
 | <span class="source-line-no">1355</span><span id="line-1355">          // creation</span> | 
 | <span class="source-line-no">1356</span><span id="line-1356">          StoreFileTracker sft =</span> | 
 | <span class="source-line-no">1357</span><span id="line-1357">            StoreFileTrackerFactory.create(conf, tableDescriptor, family, regionFs);</span> | 
 | <span class="source-line-no">1358</span><span id="line-1358">          StoreFileInfo storeFileInfo = sft.getStoreFileInfo(status, status.getPath(), false);</span> | 
 | <span class="source-line-no">1359</span><span id="line-1359">          hdfsBlocksDistribution.add(storeFileInfo.computeHDFSBlocksDistribution(fs));</span> | 
 | <span class="source-line-no">1360</span><span id="line-1360">        } else if (StoreFileInfo.isHFile(p)) {</span> | 
 | <span class="source-line-no">1361</span><span id="line-1361">          // If its a HFile, then lets just add to the block distribution</span> | 
 | <span class="source-line-no">1362</span><span id="line-1362">          // lets not create more objects here, not even another HDFSBlocksDistribution</span> | 
 | <span class="source-line-no">1363</span><span id="line-1363">          FSUtils.addToHDFSBlocksDistribution(hdfsBlocksDistribution, status.getBlockLocations());</span> | 
 | <span class="source-line-no">1364</span><span id="line-1364">        } else {</span> | 
 | <span class="source-line-no">1365</span><span id="line-1365">          throw new IOException("path=" + p + " doesn't look like a valid StoreFile");</span> | 
 | <span class="source-line-no">1366</span><span id="line-1366">        }</span> | 
 | <span class="source-line-no">1367</span><span id="line-1367">      }</span> | 
 | <span class="source-line-no">1368</span><span id="line-1368">    }</span> | 
 | <span class="source-line-no">1369</span><span id="line-1369">    return hdfsBlocksDistribution;</span> | 
 | <span class="source-line-no">1370</span><span id="line-1370">  }</span> | 
 | <span class="source-line-no">1371</span><span id="line-1371"></span> | 
 | <span class="source-line-no">1372</span><span id="line-1372">  /**</span> | 
 | <span class="source-line-no">1373</span><span id="line-1373">   * Increase the size of mem store in this region and the size of global mem store</span> | 
 | <span class="source-line-no">1374</span><span id="line-1374">   */</span> | 
 | <span class="source-line-no">1375</span><span id="line-1375">  private void incMemStoreSize(MemStoreSize mss) {</span> | 
 | <span class="source-line-no">1376</span><span id="line-1376">    incMemStoreSize(mss.getDataSize(), mss.getHeapSize(), mss.getOffHeapSize(),</span> | 
 | <span class="source-line-no">1377</span><span id="line-1377">      mss.getCellsCount());</span> | 
 | <span class="source-line-no">1378</span><span id="line-1378">  }</span> | 
 | <span class="source-line-no">1379</span><span id="line-1379"></span> | 
 | <span class="source-line-no">1380</span><span id="line-1380">  void incMemStoreSize(long dataSizeDelta, long heapSizeDelta, long offHeapSizeDelta,</span> | 
 | <span class="source-line-no">1381</span><span id="line-1381">    int cellsCountDelta) {</span> | 
 | <span class="source-line-no">1382</span><span id="line-1382">    if (this.rsAccounting != null) {</span> | 
 | <span class="source-line-no">1383</span><span id="line-1383">      rsAccounting.incGlobalMemStoreSize(dataSizeDelta, heapSizeDelta, offHeapSizeDelta);</span> | 
 | <span class="source-line-no">1384</span><span id="line-1384">    }</span> | 
 | <span class="source-line-no">1385</span><span id="line-1385">    long dataSize = this.memStoreSizing.incMemStoreSize(dataSizeDelta, heapSizeDelta,</span> | 
 | <span class="source-line-no">1386</span><span id="line-1386">      offHeapSizeDelta, cellsCountDelta);</span> | 
 | <span class="source-line-no">1387</span><span id="line-1387">    checkNegativeMemStoreDataSize(dataSize, dataSizeDelta);</span> | 
 | <span class="source-line-no">1388</span><span id="line-1388">  }</span> | 
 | <span class="source-line-no">1389</span><span id="line-1389"></span> | 
 | <span class="source-line-no">1390</span><span id="line-1390">  void decrMemStoreSize(MemStoreSize mss) {</span> | 
 | <span class="source-line-no">1391</span><span id="line-1391">    decrMemStoreSize(mss.getDataSize(), mss.getHeapSize(), mss.getOffHeapSize(),</span> | 
 | <span class="source-line-no">1392</span><span id="line-1392">      mss.getCellsCount());</span> | 
 | <span class="source-line-no">1393</span><span id="line-1393">  }</span> | 
 | <span class="source-line-no">1394</span><span id="line-1394"></span> | 
 | <span class="source-line-no">1395</span><span id="line-1395">  private void decrMemStoreSize(long dataSizeDelta, long heapSizeDelta, long offHeapSizeDelta,</span> | 
 | <span class="source-line-no">1396</span><span id="line-1396">    int cellsCountDelta) {</span> | 
 | <span class="source-line-no">1397</span><span id="line-1397">    if (this.rsAccounting != null) {</span> | 
 | <span class="source-line-no">1398</span><span id="line-1398">      rsAccounting.decGlobalMemStoreSize(dataSizeDelta, heapSizeDelta, offHeapSizeDelta);</span> | 
 | <span class="source-line-no">1399</span><span id="line-1399">    }</span> | 
 | <span class="source-line-no">1400</span><span id="line-1400">    long dataSize = this.memStoreSizing.decMemStoreSize(dataSizeDelta, heapSizeDelta,</span> | 
 | <span class="source-line-no">1401</span><span id="line-1401">      offHeapSizeDelta, cellsCountDelta);</span> | 
 | <span class="source-line-no">1402</span><span id="line-1402">    checkNegativeMemStoreDataSize(dataSize, -dataSizeDelta);</span> | 
 | <span class="source-line-no">1403</span><span id="line-1403">  }</span> | 
 | <span class="source-line-no">1404</span><span id="line-1404"></span> | 
 | <span class="source-line-no">1405</span><span id="line-1405">  private void checkNegativeMemStoreDataSize(long memStoreDataSize, long delta) {</span> | 
 | <span class="source-line-no">1406</span><span id="line-1406">    // This is extremely bad if we make memStoreSizing negative. Log as much info on the offending</span> | 
 | <span class="source-line-no">1407</span><span id="line-1407">    // caller as possible. (memStoreSizing might be a negative value already -- freeing memory)</span> | 
 | <span class="source-line-no">1408</span><span id="line-1408">    if (memStoreDataSize < 0) {</span> | 
 | <span class="source-line-no">1409</span><span id="line-1409">      LOG.error("Asked to modify this region's (" + this.toString()</span> | 
 | <span class="source-line-no">1410</span><span id="line-1410">        + ") memStoreSizing to a negative value which is incorrect. Current memStoreSizing="</span> | 
 | <span class="source-line-no">1411</span><span id="line-1411">        + (memStoreDataSize - delta) + ", delta=" + delta, new Exception());</span> | 
 | <span class="source-line-no">1412</span><span id="line-1412">    }</span> | 
 | <span class="source-line-no">1413</span><span id="line-1413">  }</span> | 
 | <span class="source-line-no">1414</span><span id="line-1414"></span> | 
 | <span class="source-line-no">1415</span><span id="line-1415">  @Override</span> | 
 | <span class="source-line-no">1416</span><span id="line-1416">  public RegionInfo getRegionInfo() {</span> | 
 | <span class="source-line-no">1417</span><span id="line-1417">    return this.fs.getRegionInfo();</span> | 
 | <span class="source-line-no">1418</span><span id="line-1418">  }</span> | 
 | <span class="source-line-no">1419</span><span id="line-1419"></span> | 
 | <span class="source-line-no">1420</span><span id="line-1420">  /**</span> | 
 | <span class="source-line-no">1421</span><span id="line-1421">   * Returns Instance of {@link RegionServerServices} used by this HRegion. Can be null.</span> | 
 | <span class="source-line-no">1422</span><span id="line-1422">   */</span> | 
 | <span class="source-line-no">1423</span><span id="line-1423">  RegionServerServices getRegionServerServices() {</span> | 
 | <span class="source-line-no">1424</span><span id="line-1424">    return this.rsServices;</span> | 
 | <span class="source-line-no">1425</span><span id="line-1425">  }</span> | 
 | <span class="source-line-no">1426</span><span id="line-1426"></span> | 
 | <span class="source-line-no">1427</span><span id="line-1427">  @Override</span> | 
 | <span class="source-line-no">1428</span><span id="line-1428">  public long getReadRequestsCount() {</span> | 
 | <span class="source-line-no">1429</span><span id="line-1429">    return readRequestsCount.sum();</span> | 
 | <span class="source-line-no">1430</span><span id="line-1430">  }</span> | 
 | <span class="source-line-no">1431</span><span id="line-1431"></span> | 
 | <span class="source-line-no">1432</span><span id="line-1432">  @Override</span> | 
 | <span class="source-line-no">1433</span><span id="line-1433">  public long getCpRequestsCount() {</span> | 
 | <span class="source-line-no">1434</span><span id="line-1434">    return cpRequestsCount.sum();</span> | 
 | <span class="source-line-no">1435</span><span id="line-1435">  }</span> | 
 | <span class="source-line-no">1436</span><span id="line-1436"></span> | 
 | <span class="source-line-no">1437</span><span id="line-1437">  @Override</span> | 
 | <span class="source-line-no">1438</span><span id="line-1438">  public long getFilteredReadRequestsCount() {</span> | 
 | <span class="source-line-no">1439</span><span id="line-1439">    return filteredReadRequestsCount.sum();</span> | 
 | <span class="source-line-no">1440</span><span id="line-1440">  }</span> | 
 | <span class="source-line-no">1441</span><span id="line-1441"></span> | 
 | <span class="source-line-no">1442</span><span id="line-1442">  @Override</span> | 
 | <span class="source-line-no">1443</span><span id="line-1443">  public long getWriteRequestsCount() {</span> | 
 | <span class="source-line-no">1444</span><span id="line-1444">    return writeRequestsCount.sum();</span> | 
 | <span class="source-line-no">1445</span><span id="line-1445">  }</span> | 
 | <span class="source-line-no">1446</span><span id="line-1446"></span> | 
 | <span class="source-line-no">1447</span><span id="line-1447">  @Override</span> | 
 | <span class="source-line-no">1448</span><span id="line-1448">  public long getMemStoreDataSize() {</span> | 
 | <span class="source-line-no">1449</span><span id="line-1449">    return memStoreSizing.getDataSize();</span> | 
 | <span class="source-line-no">1450</span><span id="line-1450">  }</span> | 
 | <span class="source-line-no">1451</span><span id="line-1451"></span> | 
 | <span class="source-line-no">1452</span><span id="line-1452">  @Override</span> | 
 | <span class="source-line-no">1453</span><span id="line-1453">  public long getMemStoreHeapSize() {</span> | 
 | <span class="source-line-no">1454</span><span id="line-1454">    return memStoreSizing.getHeapSize();</span> | 
 | <span class="source-line-no">1455</span><span id="line-1455">  }</span> | 
 | <span class="source-line-no">1456</span><span id="line-1456"></span> | 
 | <span class="source-line-no">1457</span><span id="line-1457">  @Override</span> | 
 | <span class="source-line-no">1458</span><span id="line-1458">  public long getMemStoreOffHeapSize() {</span> | 
 | <span class="source-line-no">1459</span><span id="line-1459">    return memStoreSizing.getOffHeapSize();</span> | 
 | <span class="source-line-no">1460</span><span id="line-1460">  }</span> | 
 | <span class="source-line-no">1461</span><span id="line-1461"></span> | 
 | <span class="source-line-no">1462</span><span id="line-1462">  /** Returns store services for this region, to access services required by store level needs */</span> | 
 | <span class="source-line-no">1463</span><span id="line-1463">  public RegionServicesForStores getRegionServicesForStores() {</span> | 
 | <span class="source-line-no">1464</span><span id="line-1464">    return regionServicesForStores;</span> | 
 | <span class="source-line-no">1465</span><span id="line-1465">  }</span> | 
 | <span class="source-line-no">1466</span><span id="line-1466"></span> | 
 | <span class="source-line-no">1467</span><span id="line-1467">  @Override</span> | 
 | <span class="source-line-no">1468</span><span id="line-1468">  public long getNumMutationsWithoutWAL() {</span> | 
 | <span class="source-line-no">1469</span><span id="line-1469">    return numMutationsWithoutWAL.sum();</span> | 
 | <span class="source-line-no">1470</span><span id="line-1470">  }</span> | 
 | <span class="source-line-no">1471</span><span id="line-1471"></span> | 
 | <span class="source-line-no">1472</span><span id="line-1472">  @Override</span> | 
 | <span class="source-line-no">1473</span><span id="line-1473">  public long getDataInMemoryWithoutWAL() {</span> | 
 | <span class="source-line-no">1474</span><span id="line-1474">    return dataInMemoryWithoutWAL.sum();</span> | 
 | <span class="source-line-no">1475</span><span id="line-1475">  }</span> | 
 | <span class="source-line-no">1476</span><span id="line-1476"></span> | 
 | <span class="source-line-no">1477</span><span id="line-1477">  @Override</span> | 
 | <span class="source-line-no">1478</span><span id="line-1478">  public long getBlockedRequestsCount() {</span> | 
 | <span class="source-line-no">1479</span><span id="line-1479">    return blockedRequestsCount.sum();</span> | 
 | <span class="source-line-no">1480</span><span id="line-1480">  }</span> | 
 | <span class="source-line-no">1481</span><span id="line-1481"></span> | 
 | <span class="source-line-no">1482</span><span id="line-1482">  @Override</span> | 
 | <span class="source-line-no">1483</span><span id="line-1483">  public long getCheckAndMutateChecksPassed() {</span> | 
 | <span class="source-line-no">1484</span><span id="line-1484">    return checkAndMutateChecksPassed.sum();</span> | 
 | <span class="source-line-no">1485</span><span id="line-1485">  }</span> | 
 | <span class="source-line-no">1486</span><span id="line-1486"></span> | 
 | <span class="source-line-no">1487</span><span id="line-1487">  @Override</span> | 
 | <span class="source-line-no">1488</span><span id="line-1488">  public long getCheckAndMutateChecksFailed() {</span> | 
 | <span class="source-line-no">1489</span><span id="line-1489">    return checkAndMutateChecksFailed.sum();</span> | 
 | <span class="source-line-no">1490</span><span id="line-1490">  }</span> | 
 | <span class="source-line-no">1491</span><span id="line-1491"></span> | 
 | <span class="source-line-no">1492</span><span id="line-1492">  // TODO Needs to check whether we should expose our metrics system to CPs. If CPs themselves doing</span> | 
 | <span class="source-line-no">1493</span><span id="line-1493">  // the op and bypassing the core, this might be needed? Should be stop supporting the bypass</span> | 
 | <span class="source-line-no">1494</span><span id="line-1494">  // feature?</span> | 
 | <span class="source-line-no">1495</span><span id="line-1495">  public MetricsRegion getMetrics() {</span> | 
 | <span class="source-line-no">1496</span><span id="line-1496">    return metricsRegion;</span> | 
 | <span class="source-line-no">1497</span><span id="line-1497">  }</span> | 
 | <span class="source-line-no">1498</span><span id="line-1498"></span> | 
 | <span class="source-line-no">1499</span><span id="line-1499">  @Override</span> | 
 | <span class="source-line-no">1500</span><span id="line-1500">  public boolean isClosed() {</span> | 
 | <span class="source-line-no">1501</span><span id="line-1501">    return this.closed.get();</span> | 
 | <span class="source-line-no">1502</span><span id="line-1502">  }</span> | 
 | <span class="source-line-no">1503</span><span id="line-1503"></span> | 
 | <span class="source-line-no">1504</span><span id="line-1504">  @Override</span> | 
 | <span class="source-line-no">1505</span><span id="line-1505">  public boolean isClosing() {</span> | 
 | <span class="source-line-no">1506</span><span id="line-1506">    return this.closing.get();</span> | 
 | <span class="source-line-no">1507</span><span id="line-1507">  }</span> | 
 | <span class="source-line-no">1508</span><span id="line-1508"></span> | 
 | <span class="source-line-no">1509</span><span id="line-1509">  @Override</span> | 
 | <span class="source-line-no">1510</span><span id="line-1510">  public boolean isReadOnly() {</span> | 
 | <span class="source-line-no">1511</span><span id="line-1511">    return this.writestate.isReadOnly();</span> | 
 | <span class="source-line-no">1512</span><span id="line-1512">  }</span> | 
 | <span class="source-line-no">1513</span><span id="line-1513"></span> | 
 | <span class="source-line-no">1514</span><span id="line-1514">  @Override</span> | 
 | <span class="source-line-no">1515</span><span id="line-1515">  public boolean isAvailable() {</span> | 
 | <span class="source-line-no">1516</span><span id="line-1516">    return !isClosed() && !isClosing();</span> | 
 | <span class="source-line-no">1517</span><span id="line-1517">  }</span> | 
 | <span class="source-line-no">1518</span><span id="line-1518"></span> | 
 | <span class="source-line-no">1519</span><span id="line-1519">  @Override</span> | 
 | <span class="source-line-no">1520</span><span id="line-1520">  public boolean isSplittable() {</span> | 
 | <span class="source-line-no">1521</span><span id="line-1521">    return splitPolicy.canSplit();</span> | 
 | <span class="source-line-no">1522</span><span id="line-1522">  }</span> | 
 | <span class="source-line-no">1523</span><span id="line-1523"></span> | 
 | <span class="source-line-no">1524</span><span id="line-1524">  @Override</span> | 
 | <span class="source-line-no">1525</span><span id="line-1525">  public boolean isMergeable() {</span> | 
 | <span class="source-line-no">1526</span><span id="line-1526">    if (!isAvailable()) {</span> | 
 | <span class="source-line-no">1527</span><span id="line-1527">      LOG.debug("Region " + this + " is not mergeable because it is closing or closed");</span> | 
 | <span class="source-line-no">1528</span><span id="line-1528">      return false;</span> | 
 | <span class="source-line-no">1529</span><span id="line-1529">    }</span> | 
 | <span class="source-line-no">1530</span><span id="line-1530">    if (hasReferences()) {</span> | 
 | <span class="source-line-no">1531</span><span id="line-1531">      LOG.debug("Region " + this + " is not mergeable because it has references");</span> | 
 | <span class="source-line-no">1532</span><span id="line-1532">      return false;</span> | 
 | <span class="source-line-no">1533</span><span id="line-1533">    }</span> | 
 | <span class="source-line-no">1534</span><span id="line-1534"></span> | 
 | <span class="source-line-no">1535</span><span id="line-1535">    return true;</span> | 
 | <span class="source-line-no">1536</span><span id="line-1536">  }</span> | 
 | <span class="source-line-no">1537</span><span id="line-1537"></span> | 
 | <span class="source-line-no">1538</span><span id="line-1538">  public boolean areWritesEnabled() {</span> | 
 | <span class="source-line-no">1539</span><span id="line-1539">    synchronized (this.writestate) {</span> | 
 | <span class="source-line-no">1540</span><span id="line-1540">      return this.writestate.writesEnabled;</span> | 
 | <span class="source-line-no">1541</span><span id="line-1541">    }</span> | 
 | <span class="source-line-no">1542</span><span id="line-1542">  }</span> | 
 | <span class="source-line-no">1543</span><span id="line-1543"></span> | 
 | <span class="source-line-no">1544</span><span id="line-1544">  public MultiVersionConcurrencyControl getMVCC() {</span> | 
 | <span class="source-line-no">1545</span><span id="line-1545">    return mvcc;</span> | 
 | <span class="source-line-no">1546</span><span id="line-1546">  }</span> | 
 | <span class="source-line-no">1547</span><span id="line-1547"></span> | 
 | <span class="source-line-no">1548</span><span id="line-1548">  @Override</span> | 
 | <span class="source-line-no">1549</span><span id="line-1549">  public long getMaxFlushedSeqId() {</span> | 
 | <span class="source-line-no">1550</span><span id="line-1550">    return maxFlushedSeqId;</span> | 
 | <span class="source-line-no">1551</span><span id="line-1551">  }</span> | 
 | <span class="source-line-no">1552</span><span id="line-1552"></span> | 
 | <span class="source-line-no">1553</span><span id="line-1553">  /** Returns readpoint considering given IsolationLevel. Pass {@code null} for default */</span> | 
 | <span class="source-line-no">1554</span><span id="line-1554">  public long getReadPoint(IsolationLevel isolationLevel) {</span> | 
 | <span class="source-line-no">1555</span><span id="line-1555">    if (isolationLevel != null && isolationLevel == IsolationLevel.READ_UNCOMMITTED) {</span> | 
 | <span class="source-line-no">1556</span><span id="line-1556">      // This scan can read even uncommitted transactions</span> | 
 | <span class="source-line-no">1557</span><span id="line-1557">      return Long.MAX_VALUE;</span> | 
 | <span class="source-line-no">1558</span><span id="line-1558">    }</span> | 
 | <span class="source-line-no">1559</span><span id="line-1559">    return mvcc.getReadPoint();</span> | 
 | <span class="source-line-no">1560</span><span id="line-1560">  }</span> | 
 | <span class="source-line-no">1561</span><span id="line-1561"></span> | 
 | <span class="source-line-no">1562</span><span id="line-1562">  public boolean isLoadingCfsOnDemandDefault() {</span> | 
 | <span class="source-line-no">1563</span><span id="line-1563">    return this.isLoadingCfsOnDemandDefault;</span> | 
 | <span class="source-line-no">1564</span><span id="line-1564">  }</span> | 
 | <span class="source-line-no">1565</span><span id="line-1565"></span> | 
 | <span class="source-line-no">1566</span><span id="line-1566">  /**</span> | 
 | <span class="source-line-no">1567</span><span id="line-1567">   * Close down this HRegion. Flush the cache, shut down each HStore, don't service any more calls.</span> | 
 | <span class="source-line-no">1568</span><span id="line-1568">   * <p></span> | 
 | <span class="source-line-no">1569</span><span id="line-1569">   * This method could take some time to execute, so don't call it from a time-sensitive thread.</span> | 
 | <span class="source-line-no">1570</span><span id="line-1570">   * @return Vector of all the storage files that the HRegion's component HStores make use of. It's</span> | 
 | <span class="source-line-no">1571</span><span id="line-1571">   *         a list of all StoreFile objects. Returns empty vector if already closed and null if</span> | 
 | <span class="source-line-no">1572</span><span id="line-1572">   *         judged that it should not close.</span> | 
 | <span class="source-line-no">1573</span><span id="line-1573">   * @throws IOException              e</span> | 
 | <span class="source-line-no">1574</span><span id="line-1574">   * @throws DroppedSnapshotException Thrown when replay of wal is required because a Snapshot was</span> | 
 | <span class="source-line-no">1575</span><span id="line-1575">   *                                  not properly persisted. The region is put in closing mode, and</span> | 
 | <span class="source-line-no">1576</span><span id="line-1576">   *                                  the caller MUST abort after this.</span> | 
 | <span class="source-line-no">1577</span><span id="line-1577">   */</span> | 
 | <span class="source-line-no">1578</span><span id="line-1578">  public Map<byte[], List<HStoreFile>> close() throws IOException {</span> | 
 | <span class="source-line-no">1579</span><span id="line-1579">    return close(false);</span> | 
 | <span class="source-line-no">1580</span><span id="line-1580">  }</span> | 
 | <span class="source-line-no">1581</span><span id="line-1581"></span> | 
 | <span class="source-line-no">1582</span><span id="line-1582">  private final Object closeLock = new Object();</span> | 
 | <span class="source-line-no">1583</span><span id="line-1583"></span> | 
 | <span class="source-line-no">1584</span><span id="line-1584">  /** Conf key for fair locking policy */</span> | 
 | <span class="source-line-no">1585</span><span id="line-1585">  public static final String FAIR_REENTRANT_CLOSE_LOCK =</span> | 
 | <span class="source-line-no">1586</span><span id="line-1586">    "hbase.regionserver.fair.region.close.lock";</span> | 
 | <span class="source-line-no">1587</span><span id="line-1587">  public static final boolean DEFAULT_FAIR_REENTRANT_CLOSE_LOCK = true;</span> | 
 | <span class="source-line-no">1588</span><span id="line-1588">  /** Conf key for the periodic flush interval */</span> | 
 | <span class="source-line-no">1589</span><span id="line-1589">  public static final String MEMSTORE_PERIODIC_FLUSH_INTERVAL =</span> | 
 | <span class="source-line-no">1590</span><span id="line-1590">    ConfigKey.INT("hbase.regionserver.optionalcacheflushinterval");</span> | 
 | <span class="source-line-no">1591</span><span id="line-1591">  /** Default interval for the memstore flush */</span> | 
 | <span class="source-line-no">1592</span><span id="line-1592">  public static final int DEFAULT_CACHE_FLUSH_INTERVAL = 3600000;</span> | 
 | <span class="source-line-no">1593</span><span id="line-1593">  /** Default interval for System tables memstore flush */</span> | 
 | <span class="source-line-no">1594</span><span id="line-1594">  public static final int SYSTEM_CACHE_FLUSH_INTERVAL = 300000; // 5 minutes</span> | 
 | <span class="source-line-no">1595</span><span id="line-1595"></span> | 
 | <span class="source-line-no">1596</span><span id="line-1596">  /** Conf key to force a flush if there are already enough changes for one region in memstore */</span> | 
 | <span class="source-line-no">1597</span><span id="line-1597">  public static final String MEMSTORE_FLUSH_PER_CHANGES = "hbase.regionserver.flush.per.changes";</span> | 
 | <span class="source-line-no">1598</span><span id="line-1598">  public static final long DEFAULT_FLUSH_PER_CHANGES = 30000000; // 30 millions</span> | 
 | <span class="source-line-no">1599</span><span id="line-1599">  /**</span> | 
 | <span class="source-line-no">1600</span><span id="line-1600">   * The following MAX_FLUSH_PER_CHANGES is large enough because each KeyValue has 20+ bytes</span> | 
 | <span class="source-line-no">1601</span><span id="line-1601">   * overhead. Therefore, even 1G empty KVs occupy at least 20GB memstore size for a single region</span> | 
 | <span class="source-line-no">1602</span><span id="line-1602">   */</span> | 
 | <span class="source-line-no">1603</span><span id="line-1603">  public static final long MAX_FLUSH_PER_CHANGES = 1000000000; // 1G</span> | 
 | <span class="source-line-no">1604</span><span id="line-1604"></span> | 
 | <span class="source-line-no">1605</span><span id="line-1605">  public static final String CLOSE_WAIT_ABORT = "hbase.regionserver.close.wait.abort";</span> | 
 | <span class="source-line-no">1606</span><span id="line-1606">  public static final boolean DEFAULT_CLOSE_WAIT_ABORT = true;</span> | 
 | <span class="source-line-no">1607</span><span id="line-1607">  public static final String CLOSE_WAIT_TIME = "hbase.regionserver.close.wait.time.ms";</span> | 
 | <span class="source-line-no">1608</span><span id="line-1608">  public static final long DEFAULT_CLOSE_WAIT_TIME = 60000; // 1 minute</span> | 
 | <span class="source-line-no">1609</span><span id="line-1609">  public static final String CLOSE_WAIT_INTERVAL = "hbase.regionserver.close.wait.interval.ms";</span> | 
 | <span class="source-line-no">1610</span><span id="line-1610">  public static final long DEFAULT_CLOSE_WAIT_INTERVAL = 10000; // 10 seconds</span> | 
 | <span class="source-line-no">1611</span><span id="line-1611"></span> | 
 | <span class="source-line-no">1612</span><span id="line-1612">  public Map<byte[], List<HStoreFile>> close(boolean abort) throws IOException {</span> | 
 | <span class="source-line-no">1613</span><span id="line-1613">    return close(abort, false);</span> | 
 | <span class="source-line-no">1614</span><span id="line-1614">  }</span> | 
 | <span class="source-line-no">1615</span><span id="line-1615"></span> | 
 | <span class="source-line-no">1616</span><span id="line-1616">  /**</span> | 
 | <span class="source-line-no">1617</span><span id="line-1617">   * Close this HRegion.</span> | 
 | <span class="source-line-no">1618</span><span id="line-1618">   * @param abort        true if server is aborting (only during testing)</span> | 
 | <span class="source-line-no">1619</span><span id="line-1619">   * @param ignoreStatus true if ignore the status (won't be showed on task list)</span> | 
 | <span class="source-line-no">1620</span><span id="line-1620">   * @return Vector of all the storage files that the HRegion's component HStores make use of. It's</span> | 
 | <span class="source-line-no">1621</span><span id="line-1621">   *         a list of StoreFile objects. Can be null if we are not to close at this time, or we are</span> | 
 | <span class="source-line-no">1622</span><span id="line-1622">   *         already closed.</span> | 
 | <span class="source-line-no">1623</span><span id="line-1623">   * @throws IOException              e</span> | 
 | <span class="source-line-no">1624</span><span id="line-1624">   * @throws DroppedSnapshotException Thrown when replay of wal is required because a Snapshot was</span> | 
 | <span class="source-line-no">1625</span><span id="line-1625">   *                                  not properly persisted. The region is put in closing mode, and</span> | 
 | <span class="source-line-no">1626</span><span id="line-1626">   *                                  the caller MUST abort after this.</span> | 
 | <span class="source-line-no">1627</span><span id="line-1627">   */</span> | 
 | <span class="source-line-no">1628</span><span id="line-1628">  public Map<byte[], List<HStoreFile>> close(boolean abort, boolean ignoreStatus)</span> | 
 | <span class="source-line-no">1629</span><span id="line-1629">    throws IOException {</span> | 
 | <span class="source-line-no">1630</span><span id="line-1630">    return close(abort, ignoreStatus, false);</span> | 
 | <span class="source-line-no">1631</span><span id="line-1631">  }</span> | 
 | <span class="source-line-no">1632</span><span id="line-1632"></span> | 
 | <span class="source-line-no">1633</span><span id="line-1633">  /**</span> | 
 | <span class="source-line-no">1634</span><span id="line-1634">   * Close down this HRegion. Flush the cache unless abort parameter is true, Shut down each HStore,</span> | 
 | <span class="source-line-no">1635</span><span id="line-1635">   * don't service any more calls. This method could take some time to execute, so don't call it</span> | 
 | <span class="source-line-no">1636</span><span id="line-1636">   * from a time-sensitive thread.</span> | 
 | <span class="source-line-no">1637</span><span id="line-1637">   * @param abort          true if server is aborting (only during testing)</span> | 
 | <span class="source-line-no">1638</span><span id="line-1638">   * @param ignoreStatus   true if ignore the status (wont be showed on task list)</span> | 
 | <span class="source-line-no">1639</span><span id="line-1639">   * @param isGracefulStop true if region is being closed during graceful stop and the blocks in the</span> | 
 | <span class="source-line-no">1640</span><span id="line-1640">   *                       BucketCache should not be evicted.</span> | 
 | <span class="source-line-no">1641</span><span id="line-1641">   * @return Vector of all the storage files that the HRegion's component HStores make use of. It's</span> | 
 | <span class="source-line-no">1642</span><span id="line-1642">   *         a list of StoreFile objects. Can be null if we are not to close at this time or we are</span> | 
 | <span class="source-line-no">1643</span><span id="line-1643">   *         already closed.</span> | 
 | <span class="source-line-no">1644</span><span id="line-1644">   * @throws IOException              e</span> | 
 | <span class="source-line-no">1645</span><span id="line-1645">   * @throws DroppedSnapshotException Thrown when replay of wal is required because a Snapshot was</span> | 
 | <span class="source-line-no">1646</span><span id="line-1646">   *                                  not properly persisted. The region is put in closing mode, and</span> | 
 | <span class="source-line-no">1647</span><span id="line-1647">   *                                  the caller MUST abort after this.</span> | 
 | <span class="source-line-no">1648</span><span id="line-1648">   */</span> | 
 | <span class="source-line-no">1649</span><span id="line-1649">  public Map<byte[], List<HStoreFile>> close(boolean abort, boolean ignoreStatus,</span> | 
 | <span class="source-line-no">1650</span><span id="line-1650">    boolean isGracefulStop) throws IOException {</span> | 
 | <span class="source-line-no">1651</span><span id="line-1651">    // Only allow one thread to close at a time. Serialize them so dual</span> | 
 | <span class="source-line-no">1652</span><span id="line-1652">    // threads attempting to close will run up against each other.</span> | 
 | <span class="source-line-no">1653</span><span id="line-1653">    MonitoredTask status =</span> | 
 | <span class="source-line-no">1654</span><span id="line-1654">      TaskMonitor.get().createStatus("Closing region " + this.getRegionInfo().getEncodedName()</span> | 
 | <span class="source-line-no">1655</span><span id="line-1655">        + (abort ? " due to abort" : " as it is being closed"), ignoreStatus, true);</span> | 
 | <span class="source-line-no">1656</span><span id="line-1656">    status.setStatus("Waiting for close lock");</span> | 
 | <span class="source-line-no">1657</span><span id="line-1657">    try {</span> | 
 | <span class="source-line-no">1658</span><span id="line-1658">      synchronized (closeLock) {</span> | 
 | <span class="source-line-no">1659</span><span id="line-1659">        if (isGracefulStop && rsServices != null) {</span> | 
 | <span class="source-line-no">1660</span><span id="line-1660">          rsServices.getBlockCache().ifPresent(blockCache -> {</span> | 
 | <span class="source-line-no">1661</span><span id="line-1661">            if (blockCache instanceof CombinedBlockCache) {</span> | 
 | <span class="source-line-no">1662</span><span id="line-1662">              BlockCache l2 = ((CombinedBlockCache) blockCache).getSecondLevelCache();</span> | 
 | <span class="source-line-no">1663</span><span id="line-1663">              if (l2 instanceof BucketCache) {</span> | 
 | <span class="source-line-no">1664</span><span id="line-1664">                if (((BucketCache) l2).isCachePersistenceEnabled()) {</span> | 
 | <span class="source-line-no">1665</span><span id="line-1665">                  LOG.info(</span> | 
 | <span class="source-line-no">1666</span><span id="line-1666">                    "Closing region {} during a graceful stop, and cache persistence is on, "</span> | 
 | <span class="source-line-no">1667</span><span id="line-1667">                      + "so setting evict on close to false. ",</span> | 
 | <span class="source-line-no">1668</span><span id="line-1668">                    this.getRegionInfo().getRegionNameAsString());</span> | 
 | <span class="source-line-no">1669</span><span id="line-1669">                  this.getStores().forEach(s -> s.getCacheConfig().setEvictOnClose(false));</span> | 
 | <span class="source-line-no">1670</span><span id="line-1670">                }</span> | 
 | <span class="source-line-no">1671</span><span id="line-1671">              }</span> | 
 | <span class="source-line-no">1672</span><span id="line-1672">            }</span> | 
 | <span class="source-line-no">1673</span><span id="line-1673">          });</span> | 
 | <span class="source-line-no">1674</span><span id="line-1674">        }</span> | 
 | <span class="source-line-no">1675</span><span id="line-1675">        return doClose(abort, status);</span> | 
 | <span class="source-line-no">1676</span><span id="line-1676">      }</span> | 
 | <span class="source-line-no">1677</span><span id="line-1677">    } finally {</span> | 
 | <span class="source-line-no">1678</span><span id="line-1678">      if (LOG.isDebugEnabled()) {</span> | 
 | <span class="source-line-no">1679</span><span id="line-1679">        LOG.debug("Region close journal for {}:\n{}", this.getRegionInfo().getEncodedName(),</span> | 
 | <span class="source-line-no">1680</span><span id="line-1680">          status.prettyPrintJournal());</span> | 
 | <span class="source-line-no">1681</span><span id="line-1681">      }</span> | 
 | <span class="source-line-no">1682</span><span id="line-1682">      status.cleanup();</span> | 
 | <span class="source-line-no">1683</span><span id="line-1683">    }</span> | 
 | <span class="source-line-no">1684</span><span id="line-1684">  }</span> | 
 | <span class="source-line-no">1685</span><span id="line-1685"></span> | 
 | <span class="source-line-no">1686</span><span id="line-1686">  /**</span> | 
 | <span class="source-line-no">1687</span><span id="line-1687">   * Exposed for some very specific unit tests.</span> | 
 | <span class="source-line-no">1688</span><span id="line-1688">   */</span> | 
 | <span class="source-line-no">1689</span><span id="line-1689">  public void setClosing(boolean closing) {</span> | 
 | <span class="source-line-no">1690</span><span id="line-1690">    this.closing.set(closing);</span> | 
 | <span class="source-line-no">1691</span><span id="line-1691">  }</span> | 
 | <span class="source-line-no">1692</span><span id="line-1692"></span> | 
 | <span class="source-line-no">1693</span><span id="line-1693">  /**</span> | 
 | <span class="source-line-no">1694</span><span id="line-1694">   * The {@link HRegion#doClose} will block forever if someone tries proving the dead lock via the</span> | 
 | <span class="source-line-no">1695</span><span id="line-1695">   * unit test. Instead of blocking, the {@link HRegion#doClose} will throw exception if you set the</span> | 
 | <span class="source-line-no">1696</span><span id="line-1696">   * timeout.</span> | 
 | <span class="source-line-no">1697</span><span id="line-1697">   * @param timeoutForWriteLock the second time to wait for the write lock in</span> | 
 | <span class="source-line-no">1698</span><span id="line-1698">   *                            {@link HRegion#doClose}</span> | 
 | <span class="source-line-no">1699</span><span id="line-1699">   */</span> | 
 | <span class="source-line-no">1700</span><span id="line-1700">  public void setTimeoutForWriteLock(long timeoutForWriteLock) {</span> | 
 | <span class="source-line-no">1701</span><span id="line-1701">    assert timeoutForWriteLock >= 0;</span> | 
 | <span class="source-line-no">1702</span><span id="line-1702">    this.timeoutForWriteLock = timeoutForWriteLock;</span> | 
 | <span class="source-line-no">1703</span><span id="line-1703">  }</span> | 
 | <span class="source-line-no">1704</span><span id="line-1704"></span> | 
 | <span class="source-line-no">1705</span><span id="line-1705">  @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "UL_UNRELEASED_LOCK_EXCEPTION_PATH",</span> | 
 | <span class="source-line-no">1706</span><span id="line-1706">      justification = "I think FindBugs is confused")</span> | 
 | <span class="source-line-no">1707</span><span id="line-1707">  private Map<byte[], List<HStoreFile>> doClose(boolean abort, MonitoredTask status)</span> | 
 | <span class="source-line-no">1708</span><span id="line-1708">    throws IOException {</span> | 
 | <span class="source-line-no">1709</span><span id="line-1709">    if (isClosed()) {</span> | 
 | <span class="source-line-no">1710</span><span id="line-1710">      LOG.warn("Region " + this + " already closed");</span> | 
 | <span class="source-line-no">1711</span><span id="line-1711">      return null;</span> | 
 | <span class="source-line-no">1712</span><span id="line-1712">    }</span> | 
 | <span class="source-line-no">1713</span><span id="line-1713"></span> | 
 | <span class="source-line-no">1714</span><span id="line-1714">    if (coprocessorHost != null) {</span> | 
 | <span class="source-line-no">1715</span><span id="line-1715">      status.setStatus("Running coprocessor pre-close hooks");</span> | 
 | <span class="source-line-no">1716</span><span id="line-1716">      this.coprocessorHost.preClose(abort);</span> | 
 | <span class="source-line-no">1717</span><span id="line-1717">    }</span> | 
 | <span class="source-line-no">1718</span><span id="line-1718">    status.setStatus("Disabling compacts and flushes for region");</span> | 
 | <span class="source-line-no">1719</span><span id="line-1719">    boolean canFlush = true;</span> | 
 | <span class="source-line-no">1720</span><span id="line-1720">    synchronized (writestate) {</span> | 
 | <span class="source-line-no">1721</span><span id="line-1721">      // Disable compacting and flushing by background threads for this</span> | 
 | <span class="source-line-no">1722</span><span id="line-1722">      // region.</span> | 
 | <span class="source-line-no">1723</span><span id="line-1723">      canFlush = !writestate.readOnly;</span> | 
 | <span class="source-line-no">1724</span><span id="line-1724">      writestate.writesEnabled = false;</span> | 
 | <span class="source-line-no">1725</span><span id="line-1725">      LOG.debug("Closing {}, disabling compactions & flushes",</span> | 
 | <span class="source-line-no">1726</span><span id="line-1726">        this.getRegionInfo().getEncodedName());</span> | 
 | <span class="source-line-no">1727</span><span id="line-1727">      waitForFlushesAndCompactions();</span> | 
 | <span class="source-line-no">1728</span><span id="line-1728">    }</span> | 
 | <span class="source-line-no">1729</span><span id="line-1729">    // If we were not just flushing, is it worth doing a preflush...one</span> | 
 | <span class="source-line-no">1730</span><span id="line-1730">    // that will clear out of the bulk of the memstore before we put up</span> | 
 | <span class="source-line-no">1731</span><span id="line-1731">    // the close flag?</span> | 
 | <span class="source-line-no">1732</span><span id="line-1732">    if (!abort && worthPreFlushing() && canFlush) {</span> | 
 | <span class="source-line-no">1733</span><span id="line-1733">      status.setStatus("Pre-flushing region before close");</span> | 
 | <span class="source-line-no">1734</span><span id="line-1734">      LOG.info("Running close preflush of {}", this.getRegionInfo().getEncodedName());</span> | 
 | <span class="source-line-no">1735</span><span id="line-1735">      try {</span> | 
 | <span class="source-line-no">1736</span><span id="line-1736">        internalFlushcache(status);</span> | 
 | <span class="source-line-no">1737</span><span id="line-1737">      } catch (IOException ioe) {</span> | 
 | <span class="source-line-no">1738</span><span id="line-1738">        // Failed to flush the region. Keep going.</span> | 
 | <span class="source-line-no">1739</span><span id="line-1739">        status.setStatus("Failed pre-flush " + this + "; " + ioe.getMessage());</span> | 
 | <span class="source-line-no">1740</span><span id="line-1740">      }</span> | 
 | <span class="source-line-no">1741</span><span id="line-1741">    }</span> | 
 | <span class="source-line-no">1742</span><span id="line-1742">    if (regionReplicationSink.isPresent()) {</span> | 
 | <span class="source-line-no">1743</span><span id="line-1743">      // stop replicating to secondary replicas</span> | 
 | <span class="source-line-no">1744</span><span id="line-1744">      // the open event marker can make secondary replicas refresh store files and catch up</span> | 
 | <span class="source-line-no">1745</span><span id="line-1745">      // everything, so here we just give up replicating later edits, to speed up the reopen process</span> | 
 | <span class="source-line-no">1746</span><span id="line-1746">      RegionReplicationSink sink = regionReplicationSink.get();</span> | 
 | <span class="source-line-no">1747</span><span id="line-1747">      sink.stop();</span> | 
 | <span class="source-line-no">1748</span><span id="line-1748">      try {</span> | 
 | <span class="source-line-no">1749</span><span id="line-1749">        regionReplicationSink.get().waitUntilStopped();</span> | 
 | <span class="source-line-no">1750</span><span id="line-1750">      } catch (InterruptedException e) {</span> | 
 | <span class="source-line-no">1751</span><span id="line-1751">        throw throwOnInterrupt(e);</span> | 
 | <span class="source-line-no">1752</span><span id="line-1752">      }</span> | 
 | <span class="source-line-no">1753</span><span id="line-1753">    }</span> | 
 | <span class="source-line-no">1754</span><span id="line-1754">    // Set the closing flag</span> | 
 | <span class="source-line-no">1755</span><span id="line-1755">    // From this point new arrivals at the region lock will get NSRE.</span> | 
 | <span class="source-line-no">1756</span><span id="line-1756"></span> | 
 | <span class="source-line-no">1757</span><span id="line-1757">    this.closing.set(true);</span> | 
 | <span class="source-line-no">1758</span><span id="line-1758">    LOG.info("Closing region {}", this);</span> | 
 | <span class="source-line-no">1759</span><span id="line-1759"></span> | 
 | <span class="source-line-no">1760</span><span id="line-1760">    // Acquire the close lock</span> | 
 | <span class="source-line-no">1761</span><span id="line-1761"></span> | 
 | <span class="source-line-no">1762</span><span id="line-1762">    // The configuration parameter CLOSE_WAIT_ABORT is overloaded to enable both</span> | 
 | <span class="source-line-no">1763</span><span id="line-1763">    // the new regionserver abort condition and interrupts for running requests.</span> | 
 | <span class="source-line-no">1764</span><span id="line-1764">    // If CLOSE_WAIT_ABORT is not enabled there is no change from earlier behavior,</span> | 
 | <span class="source-line-no">1765</span><span id="line-1765">    // we will not attempt to interrupt threads servicing requests nor crash out</span> | 
 | <span class="source-line-no">1766</span><span id="line-1766">    // the regionserver if something remains stubborn.</span> | 
 | <span class="source-line-no">1767</span><span id="line-1767"></span> | 
 | <span class="source-line-no">1768</span><span id="line-1768">    final boolean canAbort = conf.getBoolean(CLOSE_WAIT_ABORT, DEFAULT_CLOSE_WAIT_ABORT);</span> | 
 | <span class="source-line-no">1769</span><span id="line-1769">    boolean useTimedWait = false;</span> | 
 | <span class="source-line-no">1770</span><span id="line-1770">    if (timeoutForWriteLock != null && timeoutForWriteLock != Long.MAX_VALUE) {</span> | 
 | <span class="source-line-no">1771</span><span id="line-1771">      // convert legacy use of timeoutForWriteLock in seconds to new use in millis</span> | 
 | <span class="source-line-no">1772</span><span id="line-1772">      timeoutForWriteLock = TimeUnit.SECONDS.toMillis(timeoutForWriteLock);</span> | 
 | <span class="source-line-no">1773</span><span id="line-1773">      useTimedWait = true;</span> | 
 | <span class="source-line-no">1774</span><span id="line-1774">    } else if (canAbort) {</span> | 
 | <span class="source-line-no">1775</span><span id="line-1775">      timeoutForWriteLock = conf.getLong(CLOSE_WAIT_TIME, DEFAULT_CLOSE_WAIT_TIME);</span> | 
 | <span class="source-line-no">1776</span><span id="line-1776">      useTimedWait = true;</span> | 
 | <span class="source-line-no">1777</span><span id="line-1777">    }</span> | 
 | <span class="source-line-no">1778</span><span id="line-1778">    if (LOG.isDebugEnabled()) {</span> | 
 | <span class="source-line-no">1779</span><span id="line-1779">      LOG.debug((useTimedWait ? "Time limited wait" : "Waiting without time limit")</span> | 
 | <span class="source-line-no">1780</span><span id="line-1780">        + " for close lock on " + this);</span> | 
 | <span class="source-line-no">1781</span><span id="line-1781">    }</span> | 
 | <span class="source-line-no">1782</span><span id="line-1782">    final long closeWaitInterval = conf.getLong(CLOSE_WAIT_INTERVAL, DEFAULT_CLOSE_WAIT_INTERVAL);</span> | 
 | <span class="source-line-no">1783</span><span id="line-1783">    long elapsedWaitTime = 0;</span> | 
 | <span class="source-line-no">1784</span><span id="line-1784">    if (useTimedWait) {</span> | 
 | <span class="source-line-no">1785</span><span id="line-1785">      // Sanity check configuration</span> | 
 | <span class="source-line-no">1786</span><span id="line-1786">      long remainingWaitTime = timeoutForWriteLock;</span> | 
 | <span class="source-line-no">1787</span><span id="line-1787">      if (remainingWaitTime < closeWaitInterval) {</span> | 
 | <span class="source-line-no">1788</span><span id="line-1788">        LOG.warn("Time limit for close wait of " + timeoutForWriteLock</span> | 
 | <span class="source-line-no">1789</span><span id="line-1789">          + " ms is less than the configured lock acquisition wait interval " + closeWaitInterval</span> | 
 | <span class="source-line-no">1790</span><span id="line-1790">          + " ms, using wait interval as time limit");</span> | 
 | <span class="source-line-no">1791</span><span id="line-1791">        remainingWaitTime = closeWaitInterval;</span> | 
 | <span class="source-line-no">1792</span><span id="line-1792">      }</span> | 
 | <span class="source-line-no">1793</span><span id="line-1793">      boolean acquired = false;</span> | 
 | <span class="source-line-no">1794</span><span id="line-1794">      do {</span> | 
 | <span class="source-line-no">1795</span><span id="line-1795">        long start = EnvironmentEdgeManager.currentTime();</span> | 
 | <span class="source-line-no">1796</span><span id="line-1796">        try {</span> | 
 | <span class="source-line-no">1797</span><span id="line-1797">          acquired = lock.writeLock().tryLock(Math.min(remainingWaitTime, closeWaitInterval),</span> | 
 | <span class="source-line-no">1798</span><span id="line-1798">            TimeUnit.MILLISECONDS);</span> | 
 | <span class="source-line-no">1799</span><span id="line-1799">        } catch (InterruptedException e) {</span> | 
 | <span class="source-line-no">1800</span><span id="line-1800">          // Interrupted waiting for close lock. More likely the server is shutting down, not</span> | 
 | <span class="source-line-no">1801</span><span id="line-1801">          // normal operation, so aborting upon interrupt while waiting on this lock would not</span> | 
 | <span class="source-line-no">1802</span><span id="line-1802">          // provide much value. Throw an IOE (as IIOE) like we would in the case where we</span> | 
 | <span class="source-line-no">1803</span><span id="line-1803">          // fail to acquire the lock.</span> | 
 | <span class="source-line-no">1804</span><span id="line-1804">          String msg = "Interrupted while waiting for close lock on " + this;</span> | 
 | <span class="source-line-no">1805</span><span id="line-1805">          LOG.warn(msg, e);</span> | 
 | <span class="source-line-no">1806</span><span id="line-1806">          throw (InterruptedIOException) new InterruptedIOException(msg).initCause(e);</span> | 
 | <span class="source-line-no">1807</span><span id="line-1807">        }</span> | 
 | <span class="source-line-no">1808</span><span id="line-1808">        long elapsed = EnvironmentEdgeManager.currentTime() - start;</span> | 
 | <span class="source-line-no">1809</span><span id="line-1809">        elapsedWaitTime += elapsed;</span> | 
 | <span class="source-line-no">1810</span><span id="line-1810">        remainingWaitTime -= elapsed;</span> | 
 | <span class="source-line-no">1811</span><span id="line-1811">        if (canAbort && !acquired && remainingWaitTime > 0) {</span> | 
 | <span class="source-line-no">1812</span><span id="line-1812">          // Before we loop to wait again, interrupt all region operations that might</span> | 
 | <span class="source-line-no">1813</span><span id="line-1813">          // still be in progress, to encourage them to break out of waiting states or</span> | 
 | <span class="source-line-no">1814</span><span id="line-1814">          // inner loops, throw an exception to clients, and release the read lock via</span> | 
 | <span class="source-line-no">1815</span><span id="line-1815">          // endRegionOperation.</span> | 
 | <span class="source-line-no">1816</span><span id="line-1816">          if (LOG.isDebugEnabled()) {</span> | 
 | <span class="source-line-no">1817</span><span id="line-1817">            LOG.debug("Interrupting region operations after waiting for close lock for "</span> | 
 | <span class="source-line-no">1818</span><span id="line-1818">              + elapsedWaitTime + " ms on " + this + ", " + remainingWaitTime + " ms remaining");</span> | 
 | <span class="source-line-no">1819</span><span id="line-1819">          }</span> | 
 | <span class="source-line-no">1820</span><span id="line-1820">          interruptRegionOperations();</span> | 
 | <span class="source-line-no">1821</span><span id="line-1821">        }</span> | 
 | <span class="source-line-no">1822</span><span id="line-1822">      } while (!acquired && remainingWaitTime > 0);</span> | 
 | <span class="source-line-no">1823</span><span id="line-1823"></span> | 
 | <span class="source-line-no">1824</span><span id="line-1824">      // If we fail to acquire the lock, trigger an abort if we can; otherwise throw an IOE</span> | 
 | <span class="source-line-no">1825</span><span id="line-1825">      // to let the caller know we could not proceed with the close.</span> | 
 | <span class="source-line-no">1826</span><span id="line-1826">      if (!acquired) {</span> | 
 | <span class="source-line-no">1827</span><span id="line-1827">        String msg =</span> | 
 | <span class="source-line-no">1828</span><span id="line-1828">          "Failed to acquire close lock on " + this + " after waiting " + elapsedWaitTime + " ms";</span> | 
 | <span class="source-line-no">1829</span><span id="line-1829">        LOG.error(msg);</span> | 
 | <span class="source-line-no">1830</span><span id="line-1830">        if (canAbort) {</span> | 
 | <span class="source-line-no">1831</span><span id="line-1831">          // If we failed to acquire the write lock, abort the server</span> | 
 | <span class="source-line-no">1832</span><span id="line-1832">          rsServices.abort(msg, null);</span> | 
 | <span class="source-line-no">1833</span><span id="line-1833">        }</span> | 
 | <span class="source-line-no">1834</span><span id="line-1834">        throw new IOException(msg);</span> | 
 | <span class="source-line-no">1835</span><span id="line-1835">      }</span> | 
 | <span class="source-line-no">1836</span><span id="line-1836"></span> | 
 | <span class="source-line-no">1837</span><span id="line-1837">    } else {</span> | 
 | <span class="source-line-no">1838</span><span id="line-1838"></span> | 
 | <span class="source-line-no">1839</span><span id="line-1839">      long start = EnvironmentEdgeManager.currentTime();</span> | 
 | <span class="source-line-no">1840</span><span id="line-1840">      lock.writeLock().lock();</span> | 
 | <span class="source-line-no">1841</span><span id="line-1841">      elapsedWaitTime = EnvironmentEdgeManager.currentTime() - start;</span> | 
 | <span class="source-line-no">1842</span><span id="line-1842"></span> | 
 | <span class="source-line-no">1843</span><span id="line-1843">    }</span> | 
 | <span class="source-line-no">1844</span><span id="line-1844"></span> | 
 | <span class="source-line-no">1845</span><span id="line-1845">    if (LOG.isDebugEnabled()) {</span> | 
 | <span class="source-line-no">1846</span><span id="line-1846">      LOG.debug("Acquired close lock on " + this + " after waiting " + elapsedWaitTime + " ms");</span> | 
 | <span class="source-line-no">1847</span><span id="line-1847">    }</span> | 
 | <span class="source-line-no">1848</span><span id="line-1848"></span> | 
 | <span class="source-line-no">1849</span><span id="line-1849">    status.setStatus("Disabling writes for close");</span> | 
 | <span class="source-line-no">1850</span><span id="line-1850">    try {</span> | 
 | <span class="source-line-no">1851</span><span id="line-1851">      if (this.isClosed()) {</span> | 
 | <span class="source-line-no">1852</span><span id="line-1852">        status.abort("Already got closed by another process");</span> | 
 | <span class="source-line-no">1853</span><span id="line-1853">        // SplitTransaction handles the null</span> | 
 | <span class="source-line-no">1854</span><span id="line-1854">        return null;</span> | 
 | <span class="source-line-no">1855</span><span id="line-1855">      }</span> | 
 | <span class="source-line-no">1856</span><span id="line-1856">      LOG.debug("Updates disabled for region " + this);</span> | 
 | <span class="source-line-no">1857</span><span id="line-1857">      // Don't flush the cache if we are aborting</span> | 
 | <span class="source-line-no">1858</span><span id="line-1858">      if (!abort && canFlush) {</span> | 
 | <span class="source-line-no">1859</span><span id="line-1859">        int failedfFlushCount = 0;</span> | 
 | <span class="source-line-no">1860</span><span id="line-1860">        int flushCount = 0;</span> | 
 | <span class="source-line-no">1861</span><span id="line-1861">        long tmp = 0;</span> | 
 | <span class="source-line-no">1862</span><span id="line-1862">        long remainingSize = this.memStoreSizing.getDataSize();</span> | 
 | <span class="source-line-no">1863</span><span id="line-1863">        while (remainingSize > 0) {</span> | 
 | <span class="source-line-no">1864</span><span id="line-1864">          try {</span> | 
 | <span class="source-line-no">1865</span><span id="line-1865">            internalFlushcache(status);</span> | 
 | <span class="source-line-no">1866</span><span id="line-1866">            if (flushCount > 0) {</span> | 
 | <span class="source-line-no">1867</span><span id="line-1867">              LOG.info("Running extra flush, " + flushCount + " (carrying snapshot?) " + this);</span> | 
 | <span class="source-line-no">1868</span><span id="line-1868">            }</span> | 
 | <span class="source-line-no">1869</span><span id="line-1869">            flushCount++;</span> | 
 | <span class="source-line-no">1870</span><span id="line-1870">            tmp = this.memStoreSizing.getDataSize();</span> | 
 | <span class="source-line-no">1871</span><span id="line-1871">            if (tmp >= remainingSize) {</span> | 
 | <span class="source-line-no">1872</span><span id="line-1872">              failedfFlushCount++;</span> | 
 | <span class="source-line-no">1873</span><span id="line-1873">            }</span> | 
 | <span class="source-line-no">1874</span><span id="line-1874">            remainingSize = tmp;</span> | 
 | <span class="source-line-no">1875</span><span id="line-1875">            if (failedfFlushCount > 5) {</span> | 
 | <span class="source-line-no">1876</span><span id="line-1876">              // If we failed 5 times and are unable to clear memory, abort</span> | 
 | <span class="source-line-no">1877</span><span id="line-1877">              // so we do not lose data</span> | 
 | <span class="source-line-no">1878</span><span id="line-1878">              throw new DroppedSnapshotException("Failed clearing memory after " + flushCount</span> | 
 | <span class="source-line-no">1879</span><span id="line-1879">                + " attempts on region: " + Bytes.toStringBinary(getRegionInfo().getRegionName()));</span> | 
 | <span class="source-line-no">1880</span><span id="line-1880">            }</span> | 
 | <span class="source-line-no">1881</span><span id="line-1881">          } catch (IOException ioe) {</span> | 
 | <span class="source-line-no">1882</span><span id="line-1882">            status.setStatus("Failed flush " + this + ", putting online again");</span> | 
 | <span class="source-line-no">1883</span><span id="line-1883">            synchronized (writestate) {</span> | 
 | <span class="source-line-no">1884</span><span id="line-1884">              writestate.writesEnabled = true;</span> | 
 | <span class="source-line-no">1885</span><span id="line-1885">            }</span> | 
 | <span class="source-line-no">1886</span><span id="line-1886">            // Have to throw to upper layers. I can't abort server from here.</span> | 
 | <span class="source-line-no">1887</span><span id="line-1887">            throw ioe;</span> | 
 | <span class="source-line-no">1888</span><span id="line-1888">          }</span> | 
 | <span class="source-line-no">1889</span><span id="line-1889">        }</span> | 
 | <span class="source-line-no">1890</span><span id="line-1890">      }</span> | 
 | <span class="source-line-no">1891</span><span id="line-1891"></span> | 
 | <span class="source-line-no">1892</span><span id="line-1892">      Map<byte[], List<HStoreFile>> result = new TreeMap<>(Bytes.BYTES_COMPARATOR);</span> | 
 | <span class="source-line-no">1893</span><span id="line-1893">      if (!stores.isEmpty()) {</span> | 
 | <span class="source-line-no">1894</span><span id="line-1894">        // initialize the thread pool for closing stores in parallel.</span> | 
 | <span class="source-line-no">1895</span><span id="line-1895">        ThreadPoolExecutor storeCloserThreadPool =</span> | 
 | <span class="source-line-no">1896</span><span id="line-1896">          getStoreOpenAndCloseThreadPool("StoreCloser-" + getRegionInfo().getRegionNameAsString());</span> | 
 | <span class="source-line-no">1897</span><span id="line-1897">        CompletionService<Pair<byte[], Collection<HStoreFile>>> completionService =</span> | 
 | <span class="source-line-no">1898</span><span id="line-1898">          new ExecutorCompletionService<>(storeCloserThreadPool);</span> | 
 | <span class="source-line-no">1899</span><span id="line-1899"></span> | 
 | <span class="source-line-no">1900</span><span id="line-1900">        // close each store in parallel</span> | 
 | <span class="source-line-no">1901</span><span id="line-1901">        for (HStore store : stores.values()) {</span> | 
 | <span class="source-line-no">1902</span><span id="line-1902">          MemStoreSize mss = store.getFlushableSize();</span> | 
 | <span class="source-line-no">1903</span><span id="line-1903">          if (!(abort || mss.getDataSize() == 0 || writestate.readOnly)) {</span> | 
 | <span class="source-line-no">1904</span><span id="line-1904">            if (getRegionServerServices() != null) {</span> | 
 | <span class="source-line-no">1905</span><span id="line-1905">              getRegionServerServices().abort("Assertion failed while closing store "</span> | 
 | <span class="source-line-no">1906</span><span id="line-1906">                + getRegionInfo().getRegionNameAsString() + " " + store</span> | 
 | <span class="source-line-no">1907</span><span id="line-1907">                + ". flushableSize expected=0, actual={" + mss + "}. Current memStoreSize="</span> | 
 | <span class="source-line-no">1908</span><span id="line-1908">                + this.memStoreSizing.getMemStoreSize() + ". Maybe a coprocessor "</span> | 
 | <span class="source-line-no">1909</span><span id="line-1909">                + "operation failed and left the memstore in a partially updated state.", null);</span> | 
 | <span class="source-line-no">1910</span><span id="line-1910">            }</span> | 
 | <span class="source-line-no">1911</span><span id="line-1911">          }</span> | 
 | <span class="source-line-no">1912</span><span id="line-1912">          completionService.submit(new Callable<Pair<byte[], Collection<HStoreFile>>>() {</span> | 
 | <span class="source-line-no">1913</span><span id="line-1913">            @Override</span> | 
 | <span class="source-line-no">1914</span><span id="line-1914">            public Pair<byte[], Collection<HStoreFile>> call() throws IOException {</span> | 
 | <span class="source-line-no">1915</span><span id="line-1915">              return new Pair<>(store.getColumnFamilyDescriptor().getName(), store.close());</span> | 
 | <span class="source-line-no">1916</span><span id="line-1916">            }</span> | 
 | <span class="source-line-no">1917</span><span id="line-1917">          });</span> | 
 | <span class="source-line-no">1918</span><span id="line-1918">        }</span> | 
 | <span class="source-line-no">1919</span><span id="line-1919">        try {</span> | 
 | <span class="source-line-no">1920</span><span id="line-1920">          for (int i = 0; i < stores.size(); i++) {</span> | 
 | <span class="source-line-no">1921</span><span id="line-1921">            Future<Pair<byte[], Collection<HStoreFile>>> future = completionService.take();</span> | 
 | <span class="source-line-no">1922</span><span id="line-1922">            Pair<byte[], Collection<HStoreFile>> storeFiles = future.get();</span> | 
 | <span class="source-line-no">1923</span><span id="line-1923">            List<HStoreFile> familyFiles = result.get(storeFiles.getFirst());</span> | 
 | <span class="source-line-no">1924</span><span id="line-1924">            if (familyFiles == null) {</span> | 
 | <span class="source-line-no">1925</span><span id="line-1925">              familyFiles = new ArrayList<>();</span> | 
 | <span class="source-line-no">1926</span><span id="line-1926">              result.put(storeFiles.getFirst(), familyFiles);</span> | 
 | <span class="source-line-no">1927</span><span id="line-1927">            }</span> | 
 | <span class="source-line-no">1928</span><span id="line-1928">            familyFiles.addAll(storeFiles.getSecond());</span> | 
 | <span class="source-line-no">1929</span><span id="line-1929">          }</span> | 
 | <span class="source-line-no">1930</span><span id="line-1930">        } catch (InterruptedException e) {</span> | 
 | <span class="source-line-no">1931</span><span id="line-1931">          throw throwOnInterrupt(e);</span> | 
 | <span class="source-line-no">1932</span><span id="line-1932">        } catch (ExecutionException e) {</span> | 
 | <span class="source-line-no">1933</span><span id="line-1933">          Throwable cause = e.getCause();</span> | 
 | <span class="source-line-no">1934</span><span id="line-1934">          if (cause instanceof IOException) {</span> | 
 | <span class="source-line-no">1935</span><span id="line-1935">            throw (IOException) cause;</span> | 
 | <span class="source-line-no">1936</span><span id="line-1936">          }</span> | 
 | <span class="source-line-no">1937</span><span id="line-1937">          throw new IOException(cause);</span> | 
 | <span class="source-line-no">1938</span><span id="line-1938">        } finally {</span> | 
 | <span class="source-line-no">1939</span><span id="line-1939">          storeCloserThreadPool.shutdownNow();</span> | 
 | <span class="source-line-no">1940</span><span id="line-1940">        }</span> | 
 | <span class="source-line-no">1941</span><span id="line-1941">      }</span> | 
 | <span class="source-line-no">1942</span><span id="line-1942"></span> | 
 | <span class="source-line-no">1943</span><span id="line-1943">      status.setStatus("Writing region close event to WAL");</span> | 
 | <span class="source-line-no">1944</span><span id="line-1944">      // Always write close marker to wal even for read only table. This is not a big problem as we</span> | 
 | <span class="source-line-no">1945</span><span id="line-1945">      // do not write any data into the region; it is just a meta edit in the WAL file.</span> | 
 | <span class="source-line-no">1946</span><span id="line-1946">      if (</span> | 
 | <span class="source-line-no">1947</span><span id="line-1947">        !abort && wal != null && getRegionServerServices() != null</span> | 
 | <span class="source-line-no">1948</span><span id="line-1948">          && RegionReplicaUtil.isDefaultReplica(getRegionInfo())</span> | 
 | <span class="source-line-no">1949</span><span id="line-1949">      ) {</span> | 
 | <span class="source-line-no">1950</span><span id="line-1950">        writeRegionCloseMarker(wal);</span> | 
 | <span class="source-line-no">1951</span><span id="line-1951">      }</span> | 
 | <span class="source-line-no">1952</span><span id="line-1952">      this.closed.set(true);</span> | 
 | <span class="source-line-no">1953</span><span id="line-1953"></span> | 
 | <span class="source-line-no">1954</span><span id="line-1954">      // Decrease refCount of table latency metric registry.</span> | 
 | <span class="source-line-no">1955</span><span id="line-1955">      // Do this after closed#set to make sure only -1.</span> | 
 | <span class="source-line-no">1956</span><span id="line-1956">      if (metricsTableRequests != null) {</span> | 
 | <span class="source-line-no">1957</span><span id="line-1957">        metricsTableRequests.removeRegistry();</span> | 
 | <span class="source-line-no">1958</span><span id="line-1958">      }</span> | 
 | <span class="source-line-no">1959</span><span id="line-1959"></span> | 
 | <span class="source-line-no">1960</span><span id="line-1960">      if (!canFlush) {</span> | 
 | <span class="source-line-no">1961</span><span id="line-1961">        decrMemStoreSize(this.memStoreSizing.getMemStoreSize());</span> | 
 | <span class="source-line-no">1962</span><span id="line-1962">      } else if (this.memStoreSizing.getDataSize() != 0) {</span> | 
 | <span class="source-line-no">1963</span><span id="line-1963">        LOG.error("Memstore data size is {} in region {}", this.memStoreSizing.getDataSize(), this);</span> | 
 | <span class="source-line-no">1964</span><span id="line-1964">      }</span> | 
 | <span class="source-line-no">1965</span><span id="line-1965">      if (coprocessorHost != null) {</span> | 
 | <span class="source-line-no">1966</span><span id="line-1966">        status.setStatus("Running coprocessor post-close hooks");</span> | 
 | <span class="source-line-no">1967</span><span id="line-1967">        this.coprocessorHost.postClose(abort);</span> | 
 | <span class="source-line-no">1968</span><span id="line-1968">      }</span> | 
 | <span class="source-line-no">1969</span><span id="line-1969">      if (this.metricsRegion != null) {</span> | 
 | <span class="source-line-no">1970</span><span id="line-1970">        this.metricsRegion.close();</span> | 
 | <span class="source-line-no">1971</span><span id="line-1971">      }</span> | 
 | <span class="source-line-no">1972</span><span id="line-1972">      if (this.metricsRegionWrapper != null) {</span> | 
 | <span class="source-line-no">1973</span><span id="line-1973">        Closeables.close(this.metricsRegionWrapper, true);</span> | 
 | <span class="source-line-no">1974</span><span id="line-1974">      }</span> | 
 | <span class="source-line-no">1975</span><span id="line-1975">      status.markComplete("Closed");</span> | 
 | <span class="source-line-no">1976</span><span id="line-1976">      LOG.info("Closed {}", this);</span> | 
 | <span class="source-line-no">1977</span><span id="line-1977">      return result;</span> | 
 | <span class="source-line-no">1978</span><span id="line-1978">    } finally {</span> | 
 | <span class="source-line-no">1979</span><span id="line-1979">      lock.writeLock().unlock();</span> | 
 | <span class="source-line-no">1980</span><span id="line-1980">    }</span> | 
 | <span class="source-line-no">1981</span><span id="line-1981">  }</span> | 
 | <span class="source-line-no">1982</span><span id="line-1982"></span> | 
 | <span class="source-line-no">1983</span><span id="line-1983">  /** Wait for all current flushes and compactions of the region to complete */</span> | 
 | <span class="source-line-no">1984</span><span id="line-1984">  // TODO HBASE-18906. Check the usage (if any) in Phoenix and expose this or give alternate way for</span> | 
 | <span class="source-line-no">1985</span><span id="line-1985">  // Phoenix needs.</span> | 
 | <span class="source-line-no">1986</span><span id="line-1986">  public void waitForFlushesAndCompactions() {</span> | 
 | <span class="source-line-no">1987</span><span id="line-1987">    synchronized (writestate) {</span> | 
 | <span class="source-line-no">1988</span><span id="line-1988">      if (this.writestate.readOnly) {</span> | 
 | <span class="source-line-no">1989</span><span id="line-1989">        // we should not wait for replayed flushed if we are read only (for example in case the</span> | 
 | <span class="source-line-no">1990</span><span id="line-1990">        // region is a secondary replica).</span> | 
 | <span class="source-line-no">1991</span><span id="line-1991">        return;</span> | 
 | <span class="source-line-no">1992</span><span id="line-1992">      }</span> | 
 | <span class="source-line-no">1993</span><span id="line-1993">      boolean interrupted = false;</span> | 
 | <span class="source-line-no">1994</span><span id="line-1994">      try {</span> | 
 | <span class="source-line-no">1995</span><span id="line-1995">        while (writestate.compacting.get() > 0 || writestate.flushing) {</span> | 
 | <span class="source-line-no">1996</span><span id="line-1996">          LOG.debug("waiting for " + writestate.compacting + " compactions"</span> | 
 | <span class="source-line-no">1997</span><span id="line-1997">            + (writestate.flushing ? " & cache flush" : "") + " to complete for region " + this);</span> | 
 | <span class="source-line-no">1998</span><span id="line-1998">          try {</span> | 
 | <span class="source-line-no">1999</span><span id="line-1999">            writestate.wait();</span> | 
 | <span class="source-line-no">2000</span><span id="line-2000">          } catch (InterruptedException iex) {</span> | 
 | <span class="source-line-no">2001</span><span id="line-2001">            // essentially ignore and propagate the interrupt back up</span> | 
 | <span class="source-line-no">2002</span><span id="line-2002">            LOG.warn("Interrupted while waiting in region {}", this);</span> | 
 | <span class="source-line-no">2003</span><span id="line-2003">            interrupted = true;</span> | 
 | <span class="source-line-no">2004</span><span id="line-2004">            break;</span> | 
 | <span class="source-line-no">2005</span><span id="line-2005">          }</span> | 
 | <span class="source-line-no">2006</span><span id="line-2006">        }</span> | 
 | <span class="source-line-no">2007</span><span id="line-2007">      } finally {</span> | 
 | <span class="source-line-no">2008</span><span id="line-2008">        if (interrupted) {</span> | 
 | <span class="source-line-no">2009</span><span id="line-2009">          Thread.currentThread().interrupt();</span> | 
 | <span class="source-line-no">2010</span><span id="line-2010">        }</span> | 
 | <span class="source-line-no">2011</span><span id="line-2011">      }</span> | 
 | <span class="source-line-no">2012</span><span id="line-2012">    }</span> | 
 | <span class="source-line-no">2013</span><span id="line-2013">  }</span> | 
 | <span class="source-line-no">2014</span><span id="line-2014"></span> | 
 | <span class="source-line-no">2015</span><span id="line-2015">  /**</span> | 
 | <span class="source-line-no">2016</span><span id="line-2016">   * Wait for all current flushes of the region to complete</span> | 
 | <span class="source-line-no">2017</span><span id="line-2017">   */</span> | 
 | <span class="source-line-no">2018</span><span id="line-2018">  public void waitForFlushes() {</span> | 
 | <span class="source-line-no">2019</span><span id="line-2019">    waitForFlushes(0);// Unbound wait</span> | 
 | <span class="source-line-no">2020</span><span id="line-2020">  }</span> | 
 | <span class="source-line-no">2021</span><span id="line-2021"></span> | 
 | <span class="source-line-no">2022</span><span id="line-2022">  @Override</span> | 
 | <span class="source-line-no">2023</span><span id="line-2023">  public boolean waitForFlushes(long timeout) {</span> | 
 | <span class="source-line-no">2024</span><span id="line-2024">    synchronized (writestate) {</span> | 
 | <span class="source-line-no">2025</span><span id="line-2025">      if (this.writestate.readOnly) {</span> | 
 | <span class="source-line-no">2026</span><span id="line-2026">        // we should not wait for replayed flushed if we are read only (for example in case the</span> | 
 | <span class="source-line-no">2027</span><span id="line-2027">        // region is a secondary replica).</span> | 
 | <span class="source-line-no">2028</span><span id="line-2028">        return true;</span> | 
 | <span class="source-line-no">2029</span><span id="line-2029">      }</span> | 
 | <span class="source-line-no">2030</span><span id="line-2030">      if (!writestate.flushing) return true;</span> | 
 | <span class="source-line-no">2031</span><span id="line-2031">      long start = EnvironmentEdgeManager.currentTime();</span> | 
 | <span class="source-line-no">2032</span><span id="line-2032">      long duration = 0;</span> | 
 | <span class="source-line-no">2033</span><span id="line-2033">      boolean interrupted = false;</span> | 
 | <span class="source-line-no">2034</span><span id="line-2034">      LOG.debug("waiting for cache flush to complete for region " + this);</span> | 
 | <span class="source-line-no">2035</span><span id="line-2035">      try {</span> | 
 | <span class="source-line-no">2036</span><span id="line-2036">        while (writestate.flushing) {</span> | 
 | <span class="source-line-no">2037</span><span id="line-2037">          if (timeout > 0 && duration >= timeout) break;</span> | 
 | <span class="source-line-no">2038</span><span id="line-2038">          try {</span> | 
 | <span class="source-line-no">2039</span><span id="line-2039">            long toWait = timeout == 0 ? 0 : (timeout - duration);</span> | 
 | <span class="source-line-no">2040</span><span id="line-2040">            writestate.wait(toWait);</span> | 
 | <span class="source-line-no">2041</span><span id="line-2041">          } catch (InterruptedException iex) {</span> | 
 | <span class="source-line-no">2042</span><span id="line-2042">            // essentially ignore and propagate the interrupt back up</span> | 
 | <span class="source-line-no">2043</span><span id="line-2043">            LOG.warn("Interrupted while waiting in region {}", this);</span> | 
 | <span class="source-line-no">2044</span><span id="line-2044">            interrupted = true;</span> | 
 | <span class="source-line-no">2045</span><span id="line-2045">            break;</span> | 
 | <span class="source-line-no">2046</span><span id="line-2046">          } finally {</span> | 
 | <span class="source-line-no">2047</span><span id="line-2047">            duration = EnvironmentEdgeManager.currentTime() - start;</span> | 
 | <span class="source-line-no">2048</span><span id="line-2048">          }</span> | 
 | <span class="source-line-no">2049</span><span id="line-2049">        }</span> | 
 | <span class="source-line-no">2050</span><span id="line-2050">      } finally {</span> | 
 | <span class="source-line-no">2051</span><span id="line-2051">        if (interrupted) {</span> | 
 | <span class="source-line-no">2052</span><span id="line-2052">          Thread.currentThread().interrupt();</span> | 
 | <span class="source-line-no">2053</span><span id="line-2053">        }</span> | 
 | <span class="source-line-no">2054</span><span id="line-2054">      }</span> | 
 | <span class="source-line-no">2055</span><span id="line-2055">      LOG.debug("Waited {} ms for region {} flush to complete", duration, this);</span> | 
 | <span class="source-line-no">2056</span><span id="line-2056">      return !(writestate.flushing);</span> | 
 | <span class="source-line-no">2057</span><span id="line-2057">    }</span> | 
 | <span class="source-line-no">2058</span><span id="line-2058">  }</span> | 
 | <span class="source-line-no">2059</span><span id="line-2059"></span> | 
 | <span class="source-line-no">2060</span><span id="line-2060">  @Override</span> | 
 | <span class="source-line-no">2061</span><span id="line-2061">  public Configuration getReadOnlyConfiguration() {</span> | 
 | <span class="source-line-no">2062</span><span id="line-2062">    return new ReadOnlyConfiguration(this.conf);</span> | 
 | <span class="source-line-no">2063</span><span id="line-2063">  }</span> | 
 | <span class="source-line-no">2064</span><span id="line-2064"></span> | 
 | <span class="source-line-no">2065</span><span id="line-2065">  @Override</span> | 
 | <span class="source-line-no">2066</span><span id="line-2066">  public int getMinBlockSizeBytes() {</span> | 
 | <span class="source-line-no">2067</span><span id="line-2067">    return minBlockSizeBytes;</span> | 
 | <span class="source-line-no">2068</span><span id="line-2068">  }</span> | 
 | <span class="source-line-no">2069</span><span id="line-2069"></span> | 
 | <span class="source-line-no">2070</span><span id="line-2070">  private ThreadPoolExecutor getStoreOpenAndCloseThreadPool(final String threadNamePrefix) {</span> | 
 | <span class="source-line-no">2071</span><span id="line-2071">    int numStores = Math.max(1, this.htableDescriptor.getColumnFamilyCount());</span> | 
 | <span class="source-line-no">2072</span><span id="line-2072">    int maxThreads = Math.min(numStores, conf.getInt(HConstants.HSTORE_OPEN_AND_CLOSE_THREADS_MAX,</span> | 
 | <span class="source-line-no">2073</span><span id="line-2073">      HConstants.DEFAULT_HSTORE_OPEN_AND_CLOSE_THREADS_MAX));</span> | 
 | <span class="source-line-no">2074</span><span id="line-2074">    return getOpenAndCloseThreadPool(maxThreads, threadNamePrefix);</span> | 
 | <span class="source-line-no">2075</span><span id="line-2075">  }</span> | 
 | <span class="source-line-no">2076</span><span id="line-2076"></span> | 
 | <span class="source-line-no">2077</span><span id="line-2077">  ThreadPoolExecutor getStoreFileOpenAndCloseThreadPool(final String threadNamePrefix) {</span> | 
 | <span class="source-line-no">2078</span><span id="line-2078">    int numStores = Math.max(1, this.htableDescriptor.getColumnFamilyCount());</span> | 
 | <span class="source-line-no">2079</span><span id="line-2079">    int maxThreads = Math.max(1, conf.getInt(HConstants.HSTORE_OPEN_AND_CLOSE_THREADS_MAX,</span> | 
 | <span class="source-line-no">2080</span><span id="line-2080">      HConstants.DEFAULT_HSTORE_OPEN_AND_CLOSE_THREADS_MAX) / numStores);</span> | 
 | <span class="source-line-no">2081</span><span id="line-2081">    return getOpenAndCloseThreadPool(maxThreads, threadNamePrefix);</span> | 
 | <span class="source-line-no">2082</span><span id="line-2082">  }</span> | 
 | <span class="source-line-no">2083</span><span id="line-2083"></span> | 
 | <span class="source-line-no">2084</span><span id="line-2084">  private static ThreadPoolExecutor getOpenAndCloseThreadPool(int maxThreads,</span> | 
 | <span class="source-line-no">2085</span><span id="line-2085">    final String threadNamePrefix) {</span> | 
 | <span class="source-line-no">2086</span><span id="line-2086">    return Threads.getBoundedCachedThreadPool(maxThreads, 30L, TimeUnit.SECONDS,</span> | 
 | <span class="source-line-no">2087</span><span id="line-2087">      new ThreadFactory() {</span> | 
 | <span class="source-line-no">2088</span><span id="line-2088">        private int count = 1;</span> | 
 | <span class="source-line-no">2089</span><span id="line-2089"></span> | 
 | <span class="source-line-no">2090</span><span id="line-2090">        @Override</span> | 
 | <span class="source-line-no">2091</span><span id="line-2091">        public Thread newThread(Runnable r) {</span> | 
 | <span class="source-line-no">2092</span><span id="line-2092">          return new Thread(r, threadNamePrefix + "-" + count++);</span> | 
 | <span class="source-line-no">2093</span><span id="line-2093">        }</span> | 
 | <span class="source-line-no">2094</span><span id="line-2094">      });</span> | 
 | <span class="source-line-no">2095</span><span id="line-2095">  }</span> | 
 | <span class="source-line-no">2096</span><span id="line-2096"></span> | 
 | <span class="source-line-no">2097</span><span id="line-2097">  /** Returns True if its worth doing a flush before we put up the close flag. */</span> | 
 | <span class="source-line-no">2098</span><span id="line-2098">  private boolean worthPreFlushing() {</span> | 
 | <span class="source-line-no">2099</span><span id="line-2099">    return this.memStoreSizing.getDataSize()</span> | 
 | <span class="source-line-no">2100</span><span id="line-2100">        > this.conf.getLong("hbase.hregion.preclose.flush.size", 1024 * 1024 * 5);</span> | 
 | <span class="source-line-no">2101</span><span id="line-2101">  }</span> | 
 | <span class="source-line-no">2102</span><span id="line-2102"></span> | 
 | <span class="source-line-no">2103</span><span id="line-2103">  //////////////////////////////////////////////////////////////////////////////</span> | 
 | <span class="source-line-no">2104</span><span id="line-2104">  // HRegion accessors</span> | 
 | <span class="source-line-no">2105</span><span id="line-2105">  //////////////////////////////////////////////////////////////////////////////</span> | 
 | <span class="source-line-no">2106</span><span id="line-2106"></span> | 
 | <span class="source-line-no">2107</span><span id="line-2107">  @Override</span> | 
 | <span class="source-line-no">2108</span><span id="line-2108">  public TableDescriptor getTableDescriptor() {</span> | 
 | <span class="source-line-no">2109</span><span id="line-2109">    return this.htableDescriptor;</span> | 
 | <span class="source-line-no">2110</span><span id="line-2110">  }</span> | 
 | <span class="source-line-no">2111</span><span id="line-2111"></span> | 
 | <span class="source-line-no">2112</span><span id="line-2112">  public void setTableDescriptor(TableDescriptor desc) {</span> | 
 | <span class="source-line-no">2113</span><span id="line-2113">    htableDescriptor = desc;</span> | 
 | <span class="source-line-no">2114</span><span id="line-2114">  }</span> | 
 | <span class="source-line-no">2115</span><span id="line-2115"></span> | 
 | <span class="source-line-no">2116</span><span id="line-2116">  /** Returns WAL in use for this region */</span> | 
 | <span class="source-line-no">2117</span><span id="line-2117">  public WAL getWAL() {</span> | 
 | <span class="source-line-no">2118</span><span id="line-2118">    return this.wal;</span> | 
 | <span class="source-line-no">2119</span><span id="line-2119">  }</span> | 
 | <span class="source-line-no">2120</span><span id="line-2120"></span> | 
 | <span class="source-line-no">2121</span><span id="line-2121">  public BlockCache getBlockCache() {</span> | 
 | <span class="source-line-no">2122</span><span id="line-2122">    return this.blockCache;</span> | 
 | <span class="source-line-no">2123</span><span id="line-2123">  }</span> | 
 | <span class="source-line-no">2124</span><span id="line-2124"></span> | 
 | <span class="source-line-no">2125</span><span id="line-2125">  /**</span> | 
 | <span class="source-line-no">2126</span><span id="line-2126">   * Only used for unit test which doesn't start region server.</span> | 
 | <span class="source-line-no">2127</span><span id="line-2127">   */</span> | 
 | <span class="source-line-no">2128</span><span id="line-2128">  public void setBlockCache(BlockCache blockCache) {</span> | 
 | <span class="source-line-no">2129</span><span id="line-2129">    this.blockCache = blockCache;</span> | 
 | <span class="source-line-no">2130</span><span id="line-2130">  }</span> | 
 | <span class="source-line-no">2131</span><span id="line-2131"></span> | 
 | <span class="source-line-no">2132</span><span id="line-2132">  public MobFileCache getMobFileCache() {</span> | 
 | <span class="source-line-no">2133</span><span id="line-2133">    return this.mobFileCache;</span> | 
 | <span class="source-line-no">2134</span><span id="line-2134">  }</span> | 
 | <span class="source-line-no">2135</span><span id="line-2135"></span> | 
 | <span class="source-line-no">2136</span><span id="line-2136">  /**</span> | 
 | <span class="source-line-no">2137</span><span id="line-2137">   * Only used for unit test which doesn't start region server.</span> | 
 | <span class="source-line-no">2138</span><span id="line-2138">   */</span> | 
 | <span class="source-line-no">2139</span><span id="line-2139">  public void setMobFileCache(MobFileCache mobFileCache) {</span> | 
 | <span class="source-line-no">2140</span><span id="line-2140">    this.mobFileCache = mobFileCache;</span> | 
 | <span class="source-line-no">2141</span><span id="line-2141">  }</span> | 
 | <span class="source-line-no">2142</span><span id="line-2142"></span> | 
 | <span class="source-line-no">2143</span><span id="line-2143">  /** Returns split policy for this region. */</span> | 
 | <span class="source-line-no">2144</span><span id="line-2144">  RegionSplitPolicy getSplitPolicy() {</span> | 
 | <span class="source-line-no">2145</span><span id="line-2145">    return this.splitPolicy;</span> | 
 | <span class="source-line-no">2146</span><span id="line-2146">  }</span> | 
 | <span class="source-line-no">2147</span><span id="line-2147"></span> | 
 | <span class="source-line-no">2148</span><span id="line-2148">  /**</span> | 
 | <span class="source-line-no">2149</span><span id="line-2149">   * A split takes the config from the parent region & passes it to the daughter region's</span> | 
 | <span class="source-line-no">2150</span><span id="line-2150">   * constructor. If 'conf' was passed, you would end up using the HTD of the parent region in</span> | 
 | <span class="source-line-no">2151</span><span id="line-2151">   * addition to the new daughter HTD. Pass 'baseConf' to the daughter regions to avoid this tricky</span> | 
 | <span class="source-line-no">2152</span><span id="line-2152">   * dedupe problem.</span> | 
 | <span class="source-line-no">2153</span><span id="line-2153">   * @return Configuration object</span> | 
 | <span class="source-line-no">2154</span><span id="line-2154">   */</span> | 
 | <span class="source-line-no">2155</span><span id="line-2155">  Configuration getBaseConf() {</span> | 
 | <span class="source-line-no">2156</span><span id="line-2156">    return this.baseConf;</span> | 
 | <span class="source-line-no">2157</span><span id="line-2157">  }</span> | 
 | <span class="source-line-no">2158</span><span id="line-2158"></span> | 
 | <span class="source-line-no">2159</span><span id="line-2159">  /** Returns {@link FileSystem} being used by this region */</span> | 
 | <span class="source-line-no">2160</span><span id="line-2160">  public FileSystem getFilesystem() {</span> | 
 | <span class="source-line-no">2161</span><span id="line-2161">    return fs.getFileSystem();</span> | 
 | <span class="source-line-no">2162</span><span id="line-2162">  }</span> | 
 | <span class="source-line-no">2163</span><span id="line-2163"></span> | 
 | <span class="source-line-no">2164</span><span id="line-2164">  /** Returns the {@link HRegionFileSystem} used by this region */</span> | 
 | <span class="source-line-no">2165</span><span id="line-2165">  public HRegionFileSystem getRegionFileSystem() {</span> | 
 | <span class="source-line-no">2166</span><span id="line-2166">    return this.fs;</span> | 
 | <span class="source-line-no">2167</span><span id="line-2167">  }</span> | 
 | <span class="source-line-no">2168</span><span id="line-2168"></span> | 
 | <span class="source-line-no">2169</span><span id="line-2169">  /** Returns the WAL {@link HRegionFileSystem} used by this region */</span> | 
 | <span class="source-line-no">2170</span><span id="line-2170">  HRegionWALFileSystem getRegionWALFileSystem() throws IOException {</span> | 
 | <span class="source-line-no">2171</span><span id="line-2171">    return new HRegionWALFileSystem(conf, getWalFileSystem(),</span> | 
 | <span class="source-line-no">2172</span><span id="line-2172">      CommonFSUtils.getWALTableDir(conf, htableDescriptor.getTableName()), fs.getRegionInfo());</span> | 
 | <span class="source-line-no">2173</span><span id="line-2173">  }</span> | 
 | <span class="source-line-no">2174</span><span id="line-2174"></span> | 
 | <span class="source-line-no">2175</span><span id="line-2175">  /** Returns the WAL {@link FileSystem} being used by this region */</span> | 
 | <span class="source-line-no">2176</span><span id="line-2176">  FileSystem getWalFileSystem() throws IOException {</span> | 
 | <span class="source-line-no">2177</span><span id="line-2177">    if (walFS == null) {</span> | 
 | <span class="source-line-no">2178</span><span id="line-2178">      walFS = CommonFSUtils.getWALFileSystem(conf);</span> | 
 | <span class="source-line-no">2179</span><span id="line-2179">    }</span> | 
 | <span class="source-line-no">2180</span><span id="line-2180">    return walFS;</span> | 
 | <span class="source-line-no">2181</span><span id="line-2181">  }</span> | 
 | <span class="source-line-no">2182</span><span id="line-2182"></span> | 
 | <span class="source-line-no">2183</span><span id="line-2183">  /**</span> | 
 | <span class="source-line-no">2184</span><span id="line-2184">   * @return the Region directory under WALRootDirectory</span> | 
 | <span class="source-line-no">2185</span><span id="line-2185">   * @throws IOException if there is an error getting WALRootDir</span> | 
 | <span class="source-line-no">2186</span><span id="line-2186">   */</span> | 
 | <span class="source-line-no">2187</span><span id="line-2187">  public Path getWALRegionDir() throws IOException {</span> | 
 | <span class="source-line-no">2188</span><span id="line-2188">    if (regionWalDir == null) {</span> | 
 | <span class="source-line-no">2189</span><span id="line-2189">      regionWalDir = CommonFSUtils.getWALRegionDir(conf, getRegionInfo().getTable(),</span> | 
 | <span class="source-line-no">2190</span><span id="line-2190">        getRegionInfo().getEncodedName());</span> | 
 | <span class="source-line-no">2191</span><span id="line-2191">    }</span> | 
 | <span class="source-line-no">2192</span><span id="line-2192">    return regionWalDir;</span> | 
 | <span class="source-line-no">2193</span><span id="line-2193">  }</span> | 
 | <span class="source-line-no">2194</span><span id="line-2194"></span> | 
 | <span class="source-line-no">2195</span><span id="line-2195">  @Override</span> | 
 | <span class="source-line-no">2196</span><span id="line-2196">  public long getEarliestFlushTimeForAllStores() {</span> | 
 | <span class="source-line-no">2197</span><span id="line-2197">    return Collections.min(lastStoreFlushTimeMap.values());</span> | 
 | <span class="source-line-no">2198</span><span id="line-2198">  }</span> | 
 | <span class="source-line-no">2199</span><span id="line-2199"></span> | 
 | <span class="source-line-no">2200</span><span id="line-2200">  @Override</span> | 
 | <span class="source-line-no">2201</span><span id="line-2201">  public long getOldestHfileTs(boolean majorCompactionOnly) throws IOException {</span> | 
 | <span class="source-line-no">2202</span><span id="line-2202">    long result = Long.MAX_VALUE;</span> | 
 | <span class="source-line-no">2203</span><span id="line-2203">    for (HStore store : stores.values()) {</span> | 
 | <span class="source-line-no">2204</span><span id="line-2204">      Collection<HStoreFile> storeFiles = store.getStorefiles();</span> | 
 | <span class="source-line-no">2205</span><span id="line-2205">      if (storeFiles == null) {</span> | 
 | <span class="source-line-no">2206</span><span id="line-2206">        continue;</span> | 
 | <span class="source-line-no">2207</span><span id="line-2207">      }</span> | 
 | <span class="source-line-no">2208</span><span id="line-2208">      for (HStoreFile file : storeFiles) {</span> | 
 | <span class="source-line-no">2209</span><span id="line-2209">        StoreFileReader sfReader = file.getReader();</span> | 
 | <span class="source-line-no">2210</span><span id="line-2210">        if (sfReader == null) {</span> | 
 | <span class="source-line-no">2211</span><span id="line-2211">          continue;</span> | 
 | <span class="source-line-no">2212</span><span id="line-2212">        }</span> | 
 | <span class="source-line-no">2213</span><span id="line-2213">        HFile.Reader reader = sfReader.getHFileReader();</span> | 
 | <span class="source-line-no">2214</span><span id="line-2214">        if (reader == null) {</span> | 
 | <span class="source-line-no">2215</span><span id="line-2215">          continue;</span> | 
 | <span class="source-line-no">2216</span><span id="line-2216">        }</span> | 
 | <span class="source-line-no">2217</span><span id="line-2217">        if (majorCompactionOnly) {</span> | 
 | <span class="source-line-no">2218</span><span id="line-2218">          byte[] val = reader.getHFileInfo().get(MAJOR_COMPACTION_KEY);</span> | 
 | <span class="source-line-no">2219</span><span id="line-2219">          if (val == null || !Bytes.toBoolean(val)) {</span> | 
 | <span class="source-line-no">2220</span><span id="line-2220">            continue;</span> | 
 | <span class="source-line-no">2221</span><span id="line-2221">          }</span> | 
 | <span class="source-line-no">2222</span><span id="line-2222">        }</span> | 
 | <span class="source-line-no">2223</span><span id="line-2223">        result = Math.min(result, reader.getFileContext().getFileCreateTime());</span> | 
 | <span class="source-line-no">2224</span><span id="line-2224">      }</span> | 
 | <span class="source-line-no">2225</span><span id="line-2225">    }</span> | 
 | <span class="source-line-no">2226</span><span id="line-2226">    return result == Long.MAX_VALUE ? 0 : result;</span> | 
 | <span class="source-line-no">2227</span><span id="line-2227">  }</span> | 
 | <span class="source-line-no">2228</span><span id="line-2228"></span> | 
 | <span class="source-line-no">2229</span><span id="line-2229">  RegionLoad.Builder setCompleteSequenceId(RegionLoad.Builder regionLoadBldr) {</span> | 
 | <span class="source-line-no">2230</span><span id="line-2230">    long lastFlushOpSeqIdLocal = this.lastFlushOpSeqId;</span> | 
 | <span class="source-line-no">2231</span><span id="line-2231">    byte[] encodedRegionName = this.getRegionInfo().getEncodedNameAsBytes();</span> | 
 | <span class="source-line-no">2232</span><span id="line-2232">    regionLoadBldr.clearStoreCompleteSequenceId();</span> | 
 | <span class="source-line-no">2233</span><span id="line-2233">    for (byte[] familyName : this.stores.keySet()) {</span> | 
 | <span class="source-line-no">2234</span><span id="line-2234">      long earliest = this.wal.getEarliestMemStoreSeqNum(encodedRegionName, familyName);</span> | 
 | <span class="source-line-no">2235</span><span id="line-2235">      // Subtract - 1 to go earlier than the current oldest, unflushed edit in memstore; this will</span> | 
 | <span class="source-line-no">2236</span><span id="line-2236">      // give us a sequence id that is for sure flushed. We want edit replay to start after this</span> | 
 | <span class="source-line-no">2237</span><span id="line-2237">      // sequence id in this region. If NO_SEQNUM, use the regions maximum flush id.</span> | 
 | <span class="source-line-no">2238</span><span id="line-2238">      long csid = (earliest == HConstants.NO_SEQNUM) ? lastFlushOpSeqIdLocal : earliest - 1;</span> | 
 | <span class="source-line-no">2239</span><span id="line-2239">      regionLoadBldr.addStoreCompleteSequenceId(StoreSequenceId.newBuilder()</span> | 
 | <span class="source-line-no">2240</span><span id="line-2240">        .setFamilyName(UnsafeByteOperations.unsafeWrap(familyName)).setSequenceId(csid).build());</span> | 
 | <span class="source-line-no">2241</span><span id="line-2241">    }</span> | 
 | <span class="source-line-no">2242</span><span id="line-2242">    return regionLoadBldr.setCompleteSequenceId(getMaxFlushedSeqId());</span> | 
 | <span class="source-line-no">2243</span><span id="line-2243">  }</span> | 
 | <span class="source-line-no">2244</span><span id="line-2244"></span> | 
 | <span class="source-line-no">2245</span><span id="line-2245">  //////////////////////////////////////////////////////////////////////////////</span> | 
 | <span class="source-line-no">2246</span><span id="line-2246">  // HRegion maintenance.</span> | 
 | <span class="source-line-no">2247</span><span id="line-2247">  //</span> | 
 | <span class="source-line-no">2248</span><span id="line-2248">  // These methods are meant to be called periodically by the HRegionServer for</span> | 
 | <span class="source-line-no">2249</span><span id="line-2249">  // upkeep.</span> | 
 | <span class="source-line-no">2250</span><span id="line-2250">  //////////////////////////////////////////////////////////////////////////////</span> | 
 | <span class="source-line-no">2251</span><span id="line-2251"></span> | 
 | <span class="source-line-no">2252</span><span id="line-2252">  /**</span> | 
 | <span class="source-line-no">2253</span><span id="line-2253">   * Do preparation for pending compaction.</span> | 
 | <span class="source-line-no">2254</span><span id="line-2254">   */</span> | 
 | <span class="source-line-no">2255</span><span id="line-2255">  protected void doRegionCompactionPrep() throws IOException {</span> | 
 | <span class="source-line-no">2256</span><span id="line-2256">  }</span> | 
 | <span class="source-line-no">2257</span><span id="line-2257"></span> | 
 | <span class="source-line-no">2258</span><span id="line-2258">  /**</span> | 
 | <span class="source-line-no">2259</span><span id="line-2259">   * Synchronously compact all stores in the region.</span> | 
 | <span class="source-line-no">2260</span><span id="line-2260">   * <p></span> | 
 | <span class="source-line-no">2261</span><span id="line-2261">   * This operation could block for a long time, so don't call it from a time-sensitive thread.</span> | 
 | <span class="source-line-no">2262</span><span id="line-2262">   * <p></span> | 
 | <span class="source-line-no">2263</span><span id="line-2263">   * Note that no locks are taken to prevent possible conflicts between compaction and splitting</span> | 
 | <span class="source-line-no">2264</span><span id="line-2264">   * activities. The regionserver does not normally compact and split in parallel. However by</span> | 
 | <span class="source-line-no">2265</span><span id="line-2265">   * calling this method you may introduce unexpected and unhandled concurrency. Don't do this</span> | 
 | <span class="source-line-no">2266</span><span id="line-2266">   * unless you know what you are doing.</span> | 
 | <span class="source-line-no">2267</span><span id="line-2267">   * @param majorCompaction True to force a major compaction regardless of thresholds</span> | 
 | <span class="source-line-no">2268</span><span id="line-2268">   */</span> | 
 | <span class="source-line-no">2269</span><span id="line-2269">  public void compact(boolean majorCompaction) throws IOException {</span> | 
 | <span class="source-line-no">2270</span><span id="line-2270">    if (majorCompaction) {</span> | 
 | <span class="source-line-no">2271</span><span id="line-2271">      stores.values().forEach(HStore::triggerMajorCompaction);</span> | 
 | <span class="source-line-no">2272</span><span id="line-2272">    }</span> | 
 | <span class="source-line-no">2273</span><span id="line-2273">    for (HStore s : stores.values()) {</span> | 
 | <span class="source-line-no">2274</span><span id="line-2274">      Optional<CompactionContext> compaction = s.requestCompaction();</span> | 
 | <span class="source-line-no">2275</span><span id="line-2275">      if (compaction.isPresent()) {</span> | 
 | <span class="source-line-no">2276</span><span id="line-2276">        ThroughputController controller = null;</span> | 
 | <span class="source-line-no">2277</span><span id="line-2277">        if (rsServices != null) {</span> | 
 | <span class="source-line-no">2278</span><span id="line-2278">          controller = CompactionThroughputControllerFactory.create(rsServices, conf);</span> | 
 | <span class="source-line-no">2279</span><span id="line-2279">        }</span> | 
 | <span class="source-line-no">2280</span><span id="line-2280">        if (controller == null) {</span> | 
 | <span class="source-line-no">2281</span><span id="line-2281">          controller = NoLimitThroughputController.INSTANCE;</span> | 
 | <span class="source-line-no">2282</span><span id="line-2282">        }</span> | 
 | <span class="source-line-no">2283</span><span id="line-2283">        compact(compaction.get(), s, controller, null);</span> | 
 | <span class="source-line-no">2284</span><span id="line-2284">      }</span> | 
 | <span class="source-line-no">2285</span><span id="line-2285">    }</span> | 
 | <span class="source-line-no">2286</span><span id="line-2286">  }</span> | 
 | <span class="source-line-no">2287</span><span id="line-2287"></span> | 
 | <span class="source-line-no">2288</span><span id="line-2288">  /**</span> | 
 | <span class="source-line-no">2289</span><span id="line-2289">   * This is a helper function that compact all the stores synchronously.</span> | 
 | <span class="source-line-no">2290</span><span id="line-2290">   * <p></span> | 
 | <span class="source-line-no">2291</span><span id="line-2291">   * It is used by utilities and testing</span> | 
 | <span class="source-line-no">2292</span><span id="line-2292">   */</span> | 
 | <span class="source-line-no">2293</span><span id="line-2293">  public void compactStores() throws IOException {</span> | 
 | <span class="source-line-no">2294</span><span id="line-2294">    for (HStore s : stores.values()) {</span> | 
 | <span class="source-line-no">2295</span><span id="line-2295">      Optional<CompactionContext> compaction = s.requestCompaction();</span> | 
 | <span class="source-line-no">2296</span><span id="line-2296">      if (compaction.isPresent()) {</span> | 
 | <span class="source-line-no">2297</span><span id="line-2297">        compact(compaction.get(), s, NoLimitThroughputController.INSTANCE, null);</span> | 
 | <span class="source-line-no">2298</span><span id="line-2298">      }</span> | 
 | <span class="source-line-no">2299</span><span id="line-2299">    }</span> | 
 | <span class="source-line-no">2300</span><span id="line-2300">  }</span> | 
 | <span class="source-line-no">2301</span><span id="line-2301"></span> | 
 | <span class="source-line-no">2302</span><span id="line-2302">  /**</span> | 
 | <span class="source-line-no">2303</span><span id="line-2303">   * This is a helper function that compact the given store.</span> | 
 | <span class="source-line-no">2304</span><span id="line-2304">   * <p></span> | 
 | <span class="source-line-no">2305</span><span id="line-2305">   * It is used by utilities and testing</span> | 
 | <span class="source-line-no">2306</span><span id="line-2306">   */</span> | 
 | <span class="source-line-no">2307</span><span id="line-2307">  void compactStore(byte[] family, ThroughputController throughputController) throws IOException {</span> | 
 | <span class="source-line-no">2308</span><span id="line-2308">    HStore s = getStore(family);</span> | 
 | <span class="source-line-no">2309</span><span id="line-2309">    Optional<CompactionContext> compaction = s.requestCompaction();</span> | 
 | <span class="source-line-no">2310</span><span id="line-2310">    if (compaction.isPresent()) {</span> | 
 | <span class="source-line-no">2311</span><span id="line-2311">      compact(compaction.get(), s, throughputController, null);</span> | 
 | <span class="source-line-no">2312</span><span id="line-2312">    }</span> | 
 | <span class="source-line-no">2313</span><span id="line-2313">  }</span> | 
 | <span class="source-line-no">2314</span><span id="line-2314"></span> | 
 | <span class="source-line-no">2315</span><span id="line-2315">  /**</span> | 
 | <span class="source-line-no">2316</span><span id="line-2316">   * Called by compaction thread and after region is opened to compact the HStores if necessary.</span> | 
 | <span class="source-line-no">2317</span><span id="line-2317">   * <p></span> | 
 | <span class="source-line-no">2318</span><span id="line-2318">   * This operation could block for a long time, so don't call it from a time-sensitive thread. Note</span> | 
 | <span class="source-line-no">2319</span><span id="line-2319">   * that no locking is necessary at this level because compaction only conflicts with a region</span> | 
 | <span class="source-line-no">2320</span><span id="line-2320">   * split, and that cannot happen because the region server does them sequentially and not in</span> | 
 | <span class="source-line-no">2321</span><span id="line-2321">   * parallel.</span> | 
 | <span class="source-line-no">2322</span><span id="line-2322">   * @param compaction Compaction details, obtained by requestCompaction()</span> | 
 | <span class="source-line-no">2323</span><span id="line-2323">   * @return whether the compaction completed</span> | 
 | <span class="source-line-no">2324</span><span id="line-2324">   */</span> | 
 | <span class="source-line-no">2325</span><span id="line-2325">  public boolean compact(CompactionContext compaction, HStore store,</span> | 
 | <span class="source-line-no">2326</span><span id="line-2326">    ThroughputController throughputController) throws IOException {</span> | 
 | <span class="source-line-no">2327</span><span id="line-2327">    return compact(compaction, store, throughputController, null);</span> | 
 | <span class="source-line-no">2328</span><span id="line-2328">  }</span> | 
 | <span class="source-line-no">2329</span><span id="line-2329"></span> | 
 | <span class="source-line-no">2330</span><span id="line-2330">  private boolean shouldForbidMajorCompaction() {</span> | 
 | <span class="source-line-no">2331</span><span id="line-2331">    if (rsServices != null && rsServices.getReplicationSourceService() != null) {</span> | 
 | <span class="source-line-no">2332</span><span id="line-2332">      return rsServices.getReplicationSourceService().getSyncReplicationPeerInfoProvider()</span> | 
 | <span class="source-line-no">2333</span><span id="line-2333">        .checkState(getRegionInfo().getTable(), ForbidMajorCompactionChecker.get());</span> | 
 | <span class="source-line-no">2334</span><span id="line-2334">    }</span> | 
 | <span class="source-line-no">2335</span><span id="line-2335">    return false;</span> | 
 | <span class="source-line-no">2336</span><span id="line-2336">  }</span> | 
 | <span class="source-line-no">2337</span><span id="line-2337"></span> | 
 | <span class="source-line-no">2338</span><span id="line-2338">  /**</span> | 
 | <span class="source-line-no">2339</span><span id="line-2339">   * <p></span> | 
 | <span class="source-line-no">2340</span><span id="line-2340">   * We are trying to remove / relax the region read lock for compaction. Let's see what are the</span> | 
 | <span class="source-line-no">2341</span><span id="line-2341">   * potential race conditions among the operations (user scan, region split, region close and</span> | 
 | <span class="source-line-no">2342</span><span id="line-2342">   * region bulk load).</span> | 
 | <span class="source-line-no">2343</span><span id="line-2343">   * </p></span> | 
 | <span class="source-line-no">2344</span><span id="line-2344">   *</span> | 
 | <span class="source-line-no">2345</span><span id="line-2345">   * <pre></span> | 
 | <span class="source-line-no">2346</span><span id="line-2346">   *   user scan ---> region read lock</span> | 
 | <span class="source-line-no">2347</span><span id="line-2347">   *   region split --> region close first --> region write lock</span> | 
 | <span class="source-line-no">2348</span><span id="line-2348">   *   region close --> region write lock</span> | 
 | <span class="source-line-no">2349</span><span id="line-2349">   *   region bulk load --> region write lock</span> | 
 | <span class="source-line-no">2350</span><span id="line-2350">   * </pre></span> | 
 | <span class="source-line-no">2351</span><span id="line-2351">   * <p></span> | 
 | <span class="source-line-no">2352</span><span id="line-2352">   * read lock is compatible with read lock. ---> no problem with user scan/read region bulk load</span> | 
 | <span class="source-line-no">2353</span><span id="line-2353">   * does not cause problem for compaction (no consistency problem, store lock will help the store</span> | 
 | <span class="source-line-no">2354</span><span id="line-2354">   * file accounting). They can run almost concurrently at the region level.</span> | 
 | <span class="source-line-no">2355</span><span id="line-2355">   * </p></span> | 
 | <span class="source-line-no">2356</span><span id="line-2356">   * <p></span> | 
 | <span class="source-line-no">2357</span><span id="line-2357">   * The only remaining race condition is between the region close and compaction. So we will</span> | 
 | <span class="source-line-no">2358</span><span id="line-2358">   * evaluate, below, how region close intervenes with compaction if compaction does not acquire</span> | 
 | <span class="source-line-no">2359</span><span id="line-2359">   * region read lock.</span> | 
 | <span class="source-line-no">2360</span><span id="line-2360">   * </p></span> | 
 | <span class="source-line-no">2361</span><span id="line-2361">   * <p></span> | 
 | <span class="source-line-no">2362</span><span id="line-2362">   * Here are the steps for compaction:</span> | 
 | <span class="source-line-no">2363</span><span id="line-2363">   * <ol></span> | 
 | <span class="source-line-no">2364</span><span id="line-2364">   * <li>obtain list of StoreFile's</li></span> | 
 | <span class="source-line-no">2365</span><span id="line-2365">   * <li>create StoreFileScanner's based on list from #1</li></span> | 
 | <span class="source-line-no">2366</span><span id="line-2366">   * <li>perform compaction and save resulting files under tmp dir</li></span> | 
 | <span class="source-line-no">2367</span><span id="line-2367">   * <li>swap in compacted files</li></span> | 
 | <span class="source-line-no">2368</span><span id="line-2368">   * </ol></span> | 
 | <span class="source-line-no">2369</span><span id="line-2369">   * </p></span> | 
 | <span class="source-line-no">2370</span><span id="line-2370">   * <p></span> | 
 | <span class="source-line-no">2371</span><span id="line-2371">   * #1 is guarded by store lock. This patch does not change this --> no worse or better For #2, we</span> | 
 | <span class="source-line-no">2372</span><span id="line-2372">   * obtain smallest read point (for region) across all the Scanners (for both default compactor and</span> | 
 | <span class="source-line-no">2373</span><span id="line-2373">   * stripe compactor). The read points are for user scans. Region keeps the read points for all</span> | 
 | <span class="source-line-no">2374</span><span id="line-2374">   * currently open user scanners. Compaction needs to know the smallest read point so that during</span> | 
 | <span class="source-line-no">2375</span><span id="line-2375">   * re-write of the hfiles, it can remove the mvcc points for the cells if their mvccs are older</span> | 
 | <span class="source-line-no">2376</span><span id="line-2376">   * than the smallest since they are not needed anymore. This will not conflict with compaction.</span> | 
 | <span class="source-line-no">2377</span><span id="line-2377">   * </p></span> | 
 | <span class="source-line-no">2378</span><span id="line-2378">   * <p></span> | 
 | <span class="source-line-no">2379</span><span id="line-2379">   * For #3, it can be performed in parallel to other operations.</span> | 
 | <span class="source-line-no">2380</span><span id="line-2380">   * </p></span> | 
 | <span class="source-line-no">2381</span><span id="line-2381">   * <p></span> | 
 | <span class="source-line-no">2382</span><span id="line-2382">   * For #4 bulk load and compaction don't conflict with each other on the region level (for</span> | 
 | <span class="source-line-no">2383</span><span id="line-2383">   * multi-family atomicy).</span> | 
 | <span class="source-line-no">2384</span><span id="line-2384">   * </p></span> | 
 | <span class="source-line-no">2385</span><span id="line-2385">   * <p></span> | 
 | <span class="source-line-no">2386</span><span id="line-2386">   * Region close and compaction are guarded pretty well by the 'writestate'. In HRegion#doClose(),</span> | 
 | <span class="source-line-no">2387</span><span id="line-2387">   * we have :</span> | 
 | <span class="source-line-no">2388</span><span id="line-2388">   *</span> | 
 | <span class="source-line-no">2389</span><span id="line-2389">   * <pre></span> | 
 | <span class="source-line-no">2390</span><span id="line-2390">   * synchronized (writestate) {</span> | 
 | <span class="source-line-no">2391</span><span id="line-2391">   *   // Disable compacting and flushing by background threads for this</span> | 
 | <span class="source-line-no">2392</span><span id="line-2392">   *   // region.</span> | 
 | <span class="source-line-no">2393</span><span id="line-2393">   *   canFlush = !writestate.readOnly;</span> | 
 | <span class="source-line-no">2394</span><span id="line-2394">   *   writestate.writesEnabled = false;</span> | 
 | <span class="source-line-no">2395</span><span id="line-2395">   *   LOG.debug("Closing " + this + ": disabling compactions & flushes");</span> | 
 | <span class="source-line-no">2396</span><span id="line-2396">   *   waitForFlushesAndCompactions();</span> | 
 | <span class="source-line-no">2397</span><span id="line-2397">   * }</span> | 
 | <span class="source-line-no">2398</span><span id="line-2398">   * </pre></span> | 
 | <span class="source-line-no">2399</span><span id="line-2399">   *</span> | 
 | <span class="source-line-no">2400</span><span id="line-2400">   * {@code waitForFlushesAndCompactions()} would wait for {@code writestate.compacting} to come</span> | 
 | <span class="source-line-no">2401</span><span id="line-2401">   * down to 0. and in {@code HRegion.compact()}</span> | 
 | <span class="source-line-no">2402</span><span id="line-2402">   *</span> | 
 | <span class="source-line-no">2403</span><span id="line-2403">   * <pre></span> | 
 | <span class="source-line-no">2404</span><span id="line-2404">   *   try {</span> | 
 | <span class="source-line-no">2405</span><span id="line-2405">   *     synchronized (writestate) {</span> | 
 | <span class="source-line-no">2406</span><span id="line-2406">   *       if (writestate.writesEnabled) {</span> | 
 | <span class="source-line-no">2407</span><span id="line-2407">   *         wasStateSet = true;</span> | 
 | <span class="source-line-no">2408</span><span id="line-2408">   *         ++writestate.compacting;</span> | 
 | <span class="source-line-no">2409</span><span id="line-2409">   *       } else {</span> | 
 | <span class="source-line-no">2410</span><span id="line-2410">   *         String msg = "NOT compacting region " + this + ". Writes disabled.";</span> | 
 | <span class="source-line-no">2411</span><span id="line-2411">   *         LOG.info(msg);</span> | 
 | <span class="source-line-no">2412</span><span id="line-2412">   *         status.abort(msg);</span> | 
 | <span class="source-line-no">2413</span><span id="line-2413">   *         return false;</span> | 
 | <span class="source-line-no">2414</span><span id="line-2414">   *       }</span> | 
 | <span class="source-line-no">2415</span><span id="line-2415">   *     }</span> | 
 | <span class="source-line-no">2416</span><span id="line-2416">   *   }</span> | 
 | <span class="source-line-no">2417</span><span id="line-2417">   * </pre></span> | 
 | <span class="source-line-no">2418</span><span id="line-2418">   *</span> | 
 | <span class="source-line-no">2419</span><span id="line-2419">   * Also in {@code compactor.performCompaction()}: check periodically to see if a system stop is</span> | 
 | <span class="source-line-no">2420</span><span id="line-2420">   * requested</span> | 
 | <span class="source-line-no">2421</span><span id="line-2421">   *</span> | 
 | <span class="source-line-no">2422</span><span id="line-2422">   * <pre></span> | 
 | <span class="source-line-no">2423</span><span id="line-2423">   * if (closeChecker != null && closeChecker.isTimeLimit(store, now)) {</span> | 
 | <span class="source-line-no">2424</span><span id="line-2424">   *   progress.cancel();</span> | 
 | <span class="source-line-no">2425</span><span id="line-2425">   *   return false;</span> | 
 | <span class="source-line-no">2426</span><span id="line-2426">   * }</span> | 
 | <span class="source-line-no">2427</span><span id="line-2427">   * if (closeChecker != null && closeChecker.isSizeLimit(store, len)) {</span> | 
 | <span class="source-line-no">2428</span><span id="line-2428">   *   progress.cancel();</span> | 
 | <span class="source-line-no">2429</span><span id="line-2429">   *   return false;</span> | 
 | <span class="source-line-no">2430</span><span id="line-2430">   * }</span> | 
 | <span class="source-line-no">2431</span><span id="line-2431">   * </pre></span> | 
 | <span class="source-line-no">2432</span><span id="line-2432">   * </p></span> | 
 | <span class="source-line-no">2433</span><span id="line-2433">   */</span> | 
 | <span class="source-line-no">2434</span><span id="line-2434">  public boolean compact(CompactionContext compaction, HStore store,</span> | 
 | <span class="source-line-no">2435</span><span id="line-2435">    ThroughputController throughputController, User user) throws IOException {</span> | 
 | <span class="source-line-no">2436</span><span id="line-2436">    assert compaction != null && compaction.hasSelection();</span> | 
 | <span class="source-line-no">2437</span><span id="line-2437">    assert !compaction.getRequest().getFiles().isEmpty();</span> | 
 | <span class="source-line-no">2438</span><span id="line-2438">    if (this.closing.get() || this.closed.get()) {</span> | 
 | <span class="source-line-no">2439</span><span id="line-2439">      LOG.debug("Skipping compaction on " + this + " because closing/closed");</span> | 
 | <span class="source-line-no">2440</span><span id="line-2440">      store.cancelRequestedCompaction(compaction);</span> | 
 | <span class="source-line-no">2441</span><span id="line-2441">      return false;</span> | 
 | <span class="source-line-no">2442</span><span id="line-2442">    }</span> | 
 | <span class="source-line-no">2443</span><span id="line-2443"></span> | 
 | <span class="source-line-no">2444</span><span id="line-2444">    if (compaction.getRequest().isAllFiles() && shouldForbidMajorCompaction()) {</span> | 
 | <span class="source-line-no">2445</span><span id="line-2445">      LOG.warn("Skipping major compaction on " + this</span> | 
 | <span class="source-line-no">2446</span><span id="line-2446">        + " because this cluster is transiting sync replication state"</span> | 
 | <span class="source-line-no">2447</span><span id="line-2447">        + " from STANDBY to DOWNGRADE_ACTIVE");</span> | 
 | <span class="source-line-no">2448</span><span id="line-2448">      store.cancelRequestedCompaction(compaction);</span> | 
 | <span class="source-line-no">2449</span><span id="line-2449">      return false;</span> | 
 | <span class="source-line-no">2450</span><span id="line-2450">    }</span> | 
 | <span class="source-line-no">2451</span><span id="line-2451"></span> | 
 | <span class="source-line-no">2452</span><span id="line-2452">    MonitoredTask status = null;</span> | 
 | <span class="source-line-no">2453</span><span id="line-2453">    boolean requestNeedsCancellation = true;</span> | 
 | <span class="source-line-no">2454</span><span id="line-2454">    try {</span> | 
 | <span class="source-line-no">2455</span><span id="line-2455">      byte[] cf = Bytes.toBytes(store.getColumnFamilyName());</span> | 
 | <span class="source-line-no">2456</span><span id="line-2456">      if (stores.get(cf) != store) {</span> | 
 | <span class="source-line-no">2457</span><span id="line-2457">        LOG.warn("Store " + store.getColumnFamilyName() + " on region " + this</span> | 
 | <span class="source-line-no">2458</span><span id="line-2458">          + " has been re-instantiated, cancel this compaction request. "</span> | 
 | <span class="source-line-no">2459</span><span id="line-2459">          + " It may be caused by the roll back of split transaction");</span> | 
 | <span class="source-line-no">2460</span><span id="line-2460">        return false;</span> | 
 | <span class="source-line-no">2461</span><span id="line-2461">      }</span> | 
 | <span class="source-line-no">2462</span><span id="line-2462"></span> | 
 | <span class="source-line-no">2463</span><span id="line-2463">      status = TaskMonitor.get().createStatus("Compacting " + store + " in " + this);</span> | 
 | <span class="source-line-no">2464</span><span id="line-2464">      if (this.closed.get()) {</span> | 
 | <span class="source-line-no">2465</span><span id="line-2465">        String msg = "Skipping compaction on " + this + " because closed";</span> | 
 | <span class="source-line-no">2466</span><span id="line-2466">        LOG.debug(msg);</span> | 
 | <span class="source-line-no">2467</span><span id="line-2467">        status.abort(msg);</span> | 
 | <span class="source-line-no">2468</span><span id="line-2468">        return false;</span> | 
 | <span class="source-line-no">2469</span><span id="line-2469">      }</span> | 
 | <span class="source-line-no">2470</span><span id="line-2470">      boolean wasStateSet = false;</span> | 
 | <span class="source-line-no">2471</span><span id="line-2471">      try {</span> | 
 | <span class="source-line-no">2472</span><span id="line-2472">        synchronized (writestate) {</span> | 
 | <span class="source-line-no">2473</span><span id="line-2473">          if (writestate.writesEnabled) {</span> | 
 | <span class="source-line-no">2474</span><span id="line-2474">            wasStateSet = true;</span> | 
 | <span class="source-line-no">2475</span><span id="line-2475">            writestate.compacting.incrementAndGet();</span> | 
 | <span class="source-line-no">2476</span><span id="line-2476">          } else {</span> | 
 | <span class="source-line-no">2477</span><span id="line-2477">            String msg = "NOT compacting region " + this + ". Writes disabled.";</span> | 
 | <span class="source-line-no">2478</span><span id="line-2478">            LOG.info(msg);</span> | 
 | <span class="source-line-no">2479</span><span id="line-2479">            status.abort(msg);</span> | 
 | <span class="source-line-no">2480</span><span id="line-2480">            return false;</span> | 
 | <span class="source-line-no">2481</span><span id="line-2481">          }</span> | 
 | <span class="source-line-no">2482</span><span id="line-2482">        }</span> | 
 | <span class="source-line-no">2483</span><span id="line-2483">        LOG.info("Starting compaction of {} in {}{}", store, this,</span> | 
 | <span class="source-line-no">2484</span><span id="line-2484">          (compaction.getRequest().isOffPeak() ? " as an off-peak compaction" : ""));</span> | 
 | <span class="source-line-no">2485</span><span id="line-2485">        doRegionCompactionPrep();</span> | 
 | <span class="source-line-no">2486</span><span id="line-2486">        try {</span> | 
 | <span class="source-line-no">2487</span><span id="line-2487">          status.setStatus("Compacting store " + store);</span> | 
 | <span class="source-line-no">2488</span><span id="line-2488">          // We no longer need to cancel the request on the way out of this</span> | 
 | <span class="source-line-no">2489</span><span id="line-2489">          // method because Store#compact will clean up unconditionally</span> | 
 | <span class="source-line-no">2490</span><span id="line-2490">          requestNeedsCancellation = false;</span> | 
 | <span class="source-line-no">2491</span><span id="line-2491">          store.compact(compaction, throughputController, user);</span> | 
 | <span class="source-line-no">2492</span><span id="line-2492">        } catch (InterruptedIOException iioe) {</span> | 
 | <span class="source-line-no">2493</span><span id="line-2493">          String msg = "region " + this + " compaction interrupted";</span> | 
 | <span class="source-line-no">2494</span><span id="line-2494">          LOG.info(msg, iioe);</span> | 
 | <span class="source-line-no">2495</span><span id="line-2495">          status.abort(msg);</span> | 
 | <span class="source-line-no">2496</span><span id="line-2496">          return false;</span> | 
 | <span class="source-line-no">2497</span><span id="line-2497">        }</span> | 
 | <span class="source-line-no">2498</span><span id="line-2498">      } finally {</span> | 
 | <span class="source-line-no">2499</span><span id="line-2499">        if (wasStateSet) {</span> | 
 | <span class="source-line-no">2500</span><span id="line-2500">          synchronized (writestate) {</span> | 
 | <span class="source-line-no">2501</span><span id="line-2501">            writestate.compacting.decrementAndGet();</span> | 
 | <span class="source-line-no">2502</span><span id="line-2502">            if (writestate.compacting.get() <= 0) {</span> | 
 | <span class="source-line-no">2503</span><span id="line-2503">              writestate.notifyAll();</span> | 
 | <span class="source-line-no">2504</span><span id="line-2504">            }</span> | 
 | <span class="source-line-no">2505</span><span id="line-2505">          }</span> | 
 | <span class="source-line-no">2506</span><span id="line-2506">        }</span> | 
 | <span class="source-line-no">2507</span><span id="line-2507">      }</span> | 
 | <span class="source-line-no">2508</span><span id="line-2508">      status.markComplete("Compaction complete");</span> | 
 | <span class="source-line-no">2509</span><span id="line-2509">      return true;</span> | 
 | <span class="source-line-no">2510</span><span id="line-2510">    } finally {</span> | 
 | <span class="source-line-no">2511</span><span id="line-2511">      if (requestNeedsCancellation) store.cancelRequestedCompaction(compaction);</span> | 
 | <span class="source-line-no">2512</span><span id="line-2512">      if (status != null) {</span> | 
 | <span class="source-line-no">2513</span><span id="line-2513">        LOG.debug("Compaction status journal for {}:\n{}", this.getRegionInfo().getEncodedName(),</span> | 
 | <span class="source-line-no">2514</span><span id="line-2514">          status.prettyPrintJournal());</span> | 
 | <span class="source-line-no">2515</span><span id="line-2515">        status.cleanup();</span> | 
 | <span class="source-line-no">2516</span><span id="line-2516">      }</span> | 
 | <span class="source-line-no">2517</span><span id="line-2517">    }</span> | 
 | <span class="source-line-no">2518</span><span id="line-2518">  }</span> | 
 | <span class="source-line-no">2519</span><span id="line-2519"></span> | 
 | <span class="source-line-no">2520</span><span id="line-2520">  /**</span> | 
 | <span class="source-line-no">2521</span><span id="line-2521">   * Flush the cache.</span> | 
 | <span class="source-line-no">2522</span><span id="line-2522">   * <p></span> | 
 | <span class="source-line-no">2523</span><span id="line-2523">   * When this method is called the cache will be flushed unless:</span> | 
 | <span class="source-line-no">2524</span><span id="line-2524">   * <ol></span> | 
 | <span class="source-line-no">2525</span><span id="line-2525">   * <li>the cache is empty</li></span> | 
 | <span class="source-line-no">2526</span><span id="line-2526">   * <li>the region is closed.</li></span> | 
 | <span class="source-line-no">2527</span><span id="line-2527">   * <li>a flush is already in progress</li></span> | 
 | <span class="source-line-no">2528</span><span id="line-2528">   * <li>writes are disabled</li></span> | 
 | <span class="source-line-no">2529</span><span id="line-2529">   * </ol></span> | 
 | <span class="source-line-no">2530</span><span id="line-2530">   * <p></span> | 
 | <span class="source-line-no">2531</span><span id="line-2531">   * This method may block for some time, so it should not be called from a time-sensitive thread.</span> | 
 | <span class="source-line-no">2532</span><span id="line-2532">   * @param flushAllStores whether we want to force a flush of all stores</span> | 
 | <span class="source-line-no">2533</span><span id="line-2533">   * @return FlushResult indicating whether the flush was successful or not and if the region needs</span> | 
 | <span class="source-line-no">2534</span><span id="line-2534">   *         compacting</span> | 
 | <span class="source-line-no">2535</span><span id="line-2535">   * @throws IOException general io exceptions because a snapshot was not properly persisted.</span> | 
 | <span class="source-line-no">2536</span><span id="line-2536">   */</span> | 
 | <span class="source-line-no">2537</span><span id="line-2537">  // TODO HBASE-18905. We might have to expose a requestFlush API for CPs</span> | 
 | <span class="source-line-no">2538</span><span id="line-2538">  public FlushResult flush(boolean flushAllStores) throws IOException {</span> | 
 | <span class="source-line-no">2539</span><span id="line-2539">    return flushcache(flushAllStores, false, FlushLifeCycleTracker.DUMMY);</span> | 
 | <span class="source-line-no">2540</span><span id="line-2540">  }</span> | 
 | <span class="source-line-no">2541</span><span id="line-2541"></span> | 
 | <span class="source-line-no">2542</span><span id="line-2542">  public interface FlushResult {</span> | 
 | <span class="source-line-no">2543</span><span id="line-2543">    enum Result {</span> | 
 | <span class="source-line-no">2544</span><span id="line-2544">      FLUSHED_NO_COMPACTION_NEEDED,</span> | 
 | <span class="source-line-no">2545</span><span id="line-2545">      FLUSHED_COMPACTION_NEEDED,</span> | 
 | <span class="source-line-no">2546</span><span id="line-2546">      // Special case where a flush didn't run because there's nothing in the memstores. Used when</span> | 
 | <span class="source-line-no">2547</span><span id="line-2547">      // bulk loading to know when we can still load even if a flush didn't happen.</span> | 
 | <span class="source-line-no">2548</span><span id="line-2548">      CANNOT_FLUSH_MEMSTORE_EMPTY,</span> | 
 | <span class="source-line-no">2549</span><span id="line-2549">      CANNOT_FLUSH</span> | 
 | <span class="source-line-no">2550</span><span id="line-2550">    }</span> | 
 | <span class="source-line-no">2551</span><span id="line-2551"></span> | 
 | <span class="source-line-no">2552</span><span id="line-2552">    /** Returns the detailed result code */</span> | 
 | <span class="source-line-no">2553</span><span id="line-2553">    Result getResult();</span> | 
 | <span class="source-line-no">2554</span><span id="line-2554"></span> | 
 | <span class="source-line-no">2555</span><span id="line-2555">    /** Returns true if the memstores were flushed, else false */</span> | 
 | <span class="source-line-no">2556</span><span id="line-2556">    boolean isFlushSucceeded();</span> | 
 | <span class="source-line-no">2557</span><span id="line-2557"></span> | 
 | <span class="source-line-no">2558</span><span id="line-2558">    /** Returns True if the flush requested a compaction, else false */</span> | 
 | <span class="source-line-no">2559</span><span id="line-2559">    boolean isCompactionNeeded();</span> | 
 | <span class="source-line-no">2560</span><span id="line-2560">  }</span> | 
 | <span class="source-line-no">2561</span><span id="line-2561"></span> | 
 | <span class="source-line-no">2562</span><span id="line-2562">  public FlushResultImpl flushcache(boolean flushAllStores, boolean writeFlushRequestWalMarker,</span> | 
 | <span class="source-line-no">2563</span><span id="line-2563">    FlushLifeCycleTracker tracker) throws IOException {</span> | 
 | <span class="source-line-no">2564</span><span id="line-2564">    List<byte[]> families = null;</span> | 
 | <span class="source-line-no">2565</span><span id="line-2565">    if (flushAllStores) {</span> | 
 | <span class="source-line-no">2566</span><span id="line-2566">      families = new ArrayList<>();</span> | 
 | <span class="source-line-no">2567</span><span id="line-2567">      families.addAll(this.getTableDescriptor().getColumnFamilyNames());</span> | 
 | <span class="source-line-no">2568</span><span id="line-2568">    }</span> | 
 | <span class="source-line-no">2569</span><span id="line-2569">    return this.flushcache(families, writeFlushRequestWalMarker, tracker);</span> | 
 | <span class="source-line-no">2570</span><span id="line-2570">  }</span> | 
 | <span class="source-line-no">2571</span><span id="line-2571"></span> | 
 | <span class="source-line-no">2572</span><span id="line-2572">  /**</span> | 
 | <span class="source-line-no">2573</span><span id="line-2573">   * Flush the cache. When this method is called the cache will be flushed unless:</span> | 
 | <span class="source-line-no">2574</span><span id="line-2574">   * <ol></span> | 
 | <span class="source-line-no">2575</span><span id="line-2575">   * <li>the cache is empty</li></span> | 
 | <span class="source-line-no">2576</span><span id="line-2576">   * <li>the region is closed.</li></span> | 
 | <span class="source-line-no">2577</span><span id="line-2577">   * <li>a flush is already in progress</li></span> | 
 | <span class="source-line-no">2578</span><span id="line-2578">   * <li>writes are disabled</li></span> | 
 | <span class="source-line-no">2579</span><span id="line-2579">   * </ol></span> | 
 | <span class="source-line-no">2580</span><span id="line-2580">   * <p></span> | 
 | <span class="source-line-no">2581</span><span id="line-2581">   * This method may block for some time, so it should not be called from a time-sensitive thread.</span> | 
 | <span class="source-line-no">2582</span><span id="line-2582">   * @param families                   stores of region to flush.</span> | 
 | <span class="source-line-no">2583</span><span id="line-2583">   * @param writeFlushRequestWalMarker whether to write the flush request marker to WAL</span> | 
 | <span class="source-line-no">2584</span><span id="line-2584">   * @param tracker                    used to track the life cycle of this flush</span> | 
 | <span class="source-line-no">2585</span><span id="line-2585">   * @return whether the flush is success and whether the region needs compacting</span> | 
 | <span class="source-line-no">2586</span><span id="line-2586">   * @throws IOException              general io exceptions</span> | 
 | <span class="source-line-no">2587</span><span id="line-2587">   * @throws DroppedSnapshotException Thrown when replay of wal is required because a Snapshot was</span> | 
 | <span class="source-line-no">2588</span><span id="line-2588">   *                                  not properly persisted. The region is put in closing mode, and</span> | 
 | <span class="source-line-no">2589</span><span id="line-2589">   *                                  the caller MUST abort after this.</span> | 
 | <span class="source-line-no">2590</span><span id="line-2590">   */</span> | 
 | <span class="source-line-no">2591</span><span id="line-2591">  public FlushResultImpl flushcache(List<byte[]> families, boolean writeFlushRequestWalMarker,</span> | 
 | <span class="source-line-no">2592</span><span id="line-2592">    FlushLifeCycleTracker tracker) throws IOException {</span> | 
 | <span class="source-line-no">2593</span><span id="line-2593">    // fail-fast instead of waiting on the lock</span> | 
 | <span class="source-line-no">2594</span><span id="line-2594">    if (this.closing.get()) {</span> | 
 | <span class="source-line-no">2595</span><span id="line-2595">      String msg = "Skipping flush on " + this + " because closing";</span> | 
 | <span class="source-line-no">2596</span><span id="line-2596">      LOG.debug(msg);</span> | 
 | <span class="source-line-no">2597</span><span id="line-2597">      return new FlushResultImpl(FlushResult.Result.CANNOT_FLUSH, msg, false);</span> | 
 | <span class="source-line-no">2598</span><span id="line-2598">    }</span> | 
 | <span class="source-line-no">2599</span><span id="line-2599">    MonitoredTask status = TaskMonitor.get().createStatus("Flushing " + this);</span> | 
 | <span class="source-line-no">2600</span><span id="line-2600">    status.setStatus("Acquiring readlock on region");</span> | 
 | <span class="source-line-no">2601</span><span id="line-2601">    // block waiting for the lock for flushing cache</span> | 
 | <span class="source-line-no">2602</span><span id="line-2602">    lock.readLock().lock();</span> | 
 | <span class="source-line-no">2603</span><span id="line-2603">    boolean flushed = true;</span> | 
 | <span class="source-line-no">2604</span><span id="line-2604">    try {</span> | 
 | <span class="source-line-no">2605</span><span id="line-2605">      if (this.closed.get()) {</span> | 
 | <span class="source-line-no">2606</span><span id="line-2606">        String msg = "Skipping flush on " + this + " because closed";</span> | 
 | <span class="source-line-no">2607</span><span id="line-2607">        LOG.debug(msg);</span> | 
 | <span class="source-line-no">2608</span><span id="line-2608">        status.abort(msg);</span> | 
 | <span class="source-line-no">2609</span><span id="line-2609">        flushed = false;</span> | 
 | <span class="source-line-no">2610</span><span id="line-2610">        return new FlushResultImpl(FlushResult.Result.CANNOT_FLUSH, msg, false);</span> | 
 | <span class="source-line-no">2611</span><span id="line-2611">      }</span> | 
 | <span class="source-line-no">2612</span><span id="line-2612">      if (coprocessorHost != null) {</span> | 
 | <span class="source-line-no">2613</span><span id="line-2613">        status.setStatus("Running coprocessor pre-flush hooks");</span> | 
 | <span class="source-line-no">2614</span><span id="line-2614">        coprocessorHost.preFlush(tracker);</span> | 
 | <span class="source-line-no">2615</span><span id="line-2615">      }</span> | 
 | <span class="source-line-no">2616</span><span id="line-2616">      // TODO: this should be managed within memstore with the snapshot, updated only after flush</span> | 
 | <span class="source-line-no">2617</span><span id="line-2617">      // successful</span> | 
 | <span class="source-line-no">2618</span><span id="line-2618">      if (numMutationsWithoutWAL.sum() > 0) {</span> | 
 | <span class="source-line-no">2619</span><span id="line-2619">        numMutationsWithoutWAL.reset();</span> | 
 | <span class="source-line-no">2620</span><span id="line-2620">        dataInMemoryWithoutWAL.reset();</span> | 
 | <span class="source-line-no">2621</span><span id="line-2621">      }</span> | 
 | <span class="source-line-no">2622</span><span id="line-2622">      synchronized (writestate) {</span> | 
 | <span class="source-line-no">2623</span><span id="line-2623">        if (!writestate.flushing && writestate.writesEnabled) {</span> | 
 | <span class="source-line-no">2624</span><span id="line-2624">          this.writestate.flushing = true;</span> | 
 | <span class="source-line-no">2625</span><span id="line-2625">        } else {</span> | 
 | <span class="source-line-no">2626</span><span id="line-2626">          String msg = "NOT flushing " + this + " as "</span> | 
 | <span class="source-line-no">2627</span><span id="line-2627">            + (writestate.flushing ? "already flushing" : "writes are not enabled");</span> | 
 | <span class="source-line-no">2628</span><span id="line-2628">          LOG.debug(msg);</span> | 
 | <span class="source-line-no">2629</span><span id="line-2629">          status.abort(msg);</span> | 
 | <span class="source-line-no">2630</span><span id="line-2630">          flushed = false;</span> | 
 | <span class="source-line-no">2631</span><span id="line-2631">          return new FlushResultImpl(FlushResult.Result.CANNOT_FLUSH, msg, false);</span> | 
 | <span class="source-line-no">2632</span><span id="line-2632">        }</span> | 
 | <span class="source-line-no">2633</span><span id="line-2633">      }</span> | 
 | <span class="source-line-no">2634</span><span id="line-2634"></span> | 
 | <span class="source-line-no">2635</span><span id="line-2635">      try {</span> | 
 | <span class="source-line-no">2636</span><span id="line-2636">        // The reason that we do not always use flushPolicy is, when the flush is</span> | 
 | <span class="source-line-no">2637</span><span id="line-2637">        // caused by logRoller, we should select stores which must be flushed</span> | 
 | <span class="source-line-no">2638</span><span id="line-2638">        // rather than could be flushed.</span> | 
 | <span class="source-line-no">2639</span><span id="line-2639">        Collection<HStore> specificStoresToFlush = null;</span> | 
 | <span class="source-line-no">2640</span><span id="line-2640">        if (families != null) {</span> | 
 | <span class="source-line-no">2641</span><span id="line-2641">          specificStoresToFlush = getSpecificStores(families);</span> | 
 | <span class="source-line-no">2642</span><span id="line-2642">        } else {</span> | 
 | <span class="source-line-no">2643</span><span id="line-2643">          specificStoresToFlush = flushPolicy.selectStoresToFlush();</span> | 
 | <span class="source-line-no">2644</span><span id="line-2644">        }</span> | 
 | <span class="source-line-no">2645</span><span id="line-2645">        FlushResultImpl fs =</span> | 
 | <span class="source-line-no">2646</span><span id="line-2646">          internalFlushcache(specificStoresToFlush, status, writeFlushRequestWalMarker, tracker);</span> | 
 | <span class="source-line-no">2647</span><span id="line-2647"></span> | 
 | <span class="source-line-no">2648</span><span id="line-2648">        if (coprocessorHost != null) {</span> | 
 | <span class="source-line-no">2649</span><span id="line-2649">          status.setStatus("Running post-flush coprocessor hooks");</span> | 
 | <span class="source-line-no">2650</span><span id="line-2650">          coprocessorHost.postFlush(tracker);</span> | 
 | <span class="source-line-no">2651</span><span id="line-2651">        }</span> | 
 | <span class="source-line-no">2652</span><span id="line-2652"></span> | 
 | <span class="source-line-no">2653</span><span id="line-2653">        if (fs.isFlushSucceeded()) {</span> | 
 | <span class="source-line-no">2654</span><span id="line-2654">          flushesQueued.reset();</span> | 
 | <span class="source-line-no">2655</span><span id="line-2655">        }</span> | 
 | <span class="source-line-no">2656</span><span id="line-2656"></span> | 
 | <span class="source-line-no">2657</span><span id="line-2657">        status.markComplete("Flush successful " + fs.toString());</span> | 
 | <span class="source-line-no">2658</span><span id="line-2658">        return fs;</span> | 
 | <span class="source-line-no">2659</span><span id="line-2659">      } finally {</span> | 
 | <span class="source-line-no">2660</span><span id="line-2660">        synchronized (writestate) {</span> | 
 | <span class="source-line-no">2661</span><span id="line-2661">          writestate.flushing = false;</span> | 
 | <span class="source-line-no">2662</span><span id="line-2662">          this.writestate.flushRequested = false;</span> | 
 | <span class="source-line-no">2663</span><span id="line-2663">          writestate.notifyAll();</span> | 
 | <span class="source-line-no">2664</span><span id="line-2664">        }</span> | 
 | <span class="source-line-no">2665</span><span id="line-2665">      }</span> | 
 | <span class="source-line-no">2666</span><span id="line-2666">    } finally {</span> | 
 | <span class="source-line-no">2667</span><span id="line-2667">      lock.readLock().unlock();</span> | 
 | <span class="source-line-no">2668</span><span id="line-2668">      if (flushed) {</span> | 
 | <span class="source-line-no">2669</span><span id="line-2669">        // Don't log this journal stuff if no flush -- confusing.</span> | 
 | <span class="source-line-no">2670</span><span id="line-2670">        LOG.debug("Flush status journal for {}:\n{}", this.getRegionInfo().getEncodedName(),</span> | 
 | <span class="source-line-no">2671</span><span id="line-2671">          status.prettyPrintJournal());</span> | 
 | <span class="source-line-no">2672</span><span id="line-2672">      }</span> | 
 | <span class="source-line-no">2673</span><span id="line-2673">      status.cleanup();</span> | 
 | <span class="source-line-no">2674</span><span id="line-2674">    }</span> | 
 | <span class="source-line-no">2675</span><span id="line-2675">  }</span> | 
 | <span class="source-line-no">2676</span><span id="line-2676"></span> | 
 | <span class="source-line-no">2677</span><span id="line-2677">  /**</span> | 
 | <span class="source-line-no">2678</span><span id="line-2678">   * get stores which matches the specified families</span> | 
 | <span class="source-line-no">2679</span><span id="line-2679">   * @return the stores need to be flushed.</span> | 
 | <span class="source-line-no">2680</span><span id="line-2680">   */</span> | 
 | <span class="source-line-no">2681</span><span id="line-2681">  private Collection<HStore> getSpecificStores(List<byte[]> families) {</span> | 
 | <span class="source-line-no">2682</span><span id="line-2682">    Collection<HStore> specificStoresToFlush = new ArrayList<>();</span> | 
 | <span class="source-line-no">2683</span><span id="line-2683">    for (byte[] family : families) {</span> | 
 | <span class="source-line-no">2684</span><span id="line-2684">      specificStoresToFlush.add(stores.get(family));</span> | 
 | <span class="source-line-no">2685</span><span id="line-2685">    }</span> | 
 | <span class="source-line-no">2686</span><span id="line-2686">    return specificStoresToFlush;</span> | 
 | <span class="source-line-no">2687</span><span id="line-2687">  }</span> | 
 | <span class="source-line-no">2688</span><span id="line-2688"></span> | 
 | <span class="source-line-no">2689</span><span id="line-2689">  /**</span> | 
 | <span class="source-line-no">2690</span><span id="line-2690">   * Should the store be flushed because it is old enough.</span> | 
 | <span class="source-line-no">2691</span><span id="line-2691">   * <p></span> | 
 | <span class="source-line-no">2692</span><span id="line-2692">   * Every FlushPolicy should call this to determine whether a store is old enough to flush (except</span> | 
 | <span class="source-line-no">2693</span><span id="line-2693">   * that you always flush all stores). Otherwise the method will always returns true which will</span> | 
 | <span class="source-line-no">2694</span><span id="line-2694">   * make a lot of flush requests.</span> | 
 | <span class="source-line-no">2695</span><span id="line-2695">   */</span> | 
 | <span class="source-line-no">2696</span><span id="line-2696">  boolean shouldFlushStore(HStore store) {</span> | 
 | <span class="source-line-no">2697</span><span id="line-2697">    long earliest = this.wal.getEarliestMemStoreSeqNum(getRegionInfo().getEncodedNameAsBytes(),</span> | 
 | <span class="source-line-no">2698</span><span id="line-2698">      store.getColumnFamilyDescriptor().getName()) - 1;</span> | 
 | <span class="source-line-no">2699</span><span id="line-2699">    if (earliest > 0 && earliest + flushPerChanges < mvcc.getReadPoint()) {</span> | 
 | <span class="source-line-no">2700</span><span id="line-2700">      if (LOG.isDebugEnabled()) {</span> | 
 | <span class="source-line-no">2701</span><span id="line-2701">        LOG.debug("Flush column family " + store.getColumnFamilyName() + " of "</span> | 
 | <span class="source-line-no">2702</span><span id="line-2702">          + getRegionInfo().getEncodedName() + " because unflushed sequenceid=" + earliest</span> | 
 | <span class="source-line-no">2703</span><span id="line-2703">          + " is > " + this.flushPerChanges + " from current=" + mvcc.getReadPoint());</span> | 
 | <span class="source-line-no">2704</span><span id="line-2704">      }</span> | 
 | <span class="source-line-no">2705</span><span id="line-2705">      return true;</span> | 
 | <span class="source-line-no">2706</span><span id="line-2706">    }</span> | 
 | <span class="source-line-no">2707</span><span id="line-2707">    if (this.flushCheckInterval <= 0) {</span> | 
 | <span class="source-line-no">2708</span><span id="line-2708">      return false;</span> | 
 | <span class="source-line-no">2709</span><span id="line-2709">    }</span> | 
 | <span class="source-line-no">2710</span><span id="line-2710">    long now = EnvironmentEdgeManager.currentTime();</span> | 
 | <span class="source-line-no">2711</span><span id="line-2711">    if (store.timeOfOldestEdit() < now - this.flushCheckInterval) {</span> | 
 | <span class="source-line-no">2712</span><span id="line-2712">      if (LOG.isDebugEnabled()) {</span> | 
 | <span class="source-line-no">2713</span><span id="line-2713">        LOG.debug("Flush column family: " + store.getColumnFamilyName() + " of "</span> | 
 | <span class="source-line-no">2714</span><span id="line-2714">          + getRegionInfo().getEncodedName() + " because time of oldest edit="</span> | 
 | <span class="source-line-no">2715</span><span id="line-2715">          + store.timeOfOldestEdit() + " is > " + this.flushCheckInterval + " from now =" + now);</span> | 
 | <span class="source-line-no">2716</span><span id="line-2716">      }</span> | 
 | <span class="source-line-no">2717</span><span id="line-2717">      return true;</span> | 
 | <span class="source-line-no">2718</span><span id="line-2718">    }</span> | 
 | <span class="source-line-no">2719</span><span id="line-2719">    return false;</span> | 
 | <span class="source-line-no">2720</span><span id="line-2720">  }</span> | 
 | <span class="source-line-no">2721</span><span id="line-2721"></span> | 
 | <span class="source-line-no">2722</span><span id="line-2722">  /**</span> | 
 | <span class="source-line-no">2723</span><span id="line-2723">   * Should the memstore be flushed now</span> | 
 | <span class="source-line-no">2724</span><span id="line-2724">   */</span> | 
 | <span class="source-line-no">2725</span><span id="line-2725">  boolean shouldFlush(final StringBuilder whyFlush) {</span> | 
 | <span class="source-line-no">2726</span><span id="line-2726">    whyFlush.setLength(0);</span> | 
 | <span class="source-line-no">2727</span><span id="line-2727">    // This is a rough measure.</span> | 
 | <span class="source-line-no">2728</span><span id="line-2728">    if (</span> | 
 | <span class="source-line-no">2729</span><span id="line-2729">      this.maxFlushedSeqId > 0</span> | 
 | <span class="source-line-no">2730</span><span id="line-2730">        && (this.maxFlushedSeqId + this.flushPerChanges < this.mvcc.getReadPoint())</span> | 
 | <span class="source-line-no">2731</span><span id="line-2731">    ) {</span> | 
 | <span class="source-line-no">2732</span><span id="line-2732">      whyFlush.append("more than max edits, " + this.flushPerChanges + ", since last flush");</span> | 
 | <span class="source-line-no">2733</span><span id="line-2733">      return true;</span> | 
 | <span class="source-line-no">2734</span><span id="line-2734">    }</span> | 
 | <span class="source-line-no">2735</span><span id="line-2735">    long modifiedFlushCheckInterval = flushCheckInterval;</span> | 
 | <span class="source-line-no">2736</span><span id="line-2736">    if (</span> | 
 | <span class="source-line-no">2737</span><span id="line-2737">      getRegionInfo().getTable().isSystemTable()</span> | 
 | <span class="source-line-no">2738</span><span id="line-2738">        && getRegionInfo().getReplicaId() == RegionInfo.DEFAULT_REPLICA_ID</span> | 
 | <span class="source-line-no">2739</span><span id="line-2739">    ) {</span> | 
 | <span class="source-line-no">2740</span><span id="line-2740">      modifiedFlushCheckInterval = SYSTEM_CACHE_FLUSH_INTERVAL;</span> | 
 | <span class="source-line-no">2741</span><span id="line-2741">    }</span> | 
 | <span class="source-line-no">2742</span><span id="line-2742">    if (modifiedFlushCheckInterval <= 0) { // disabled</span> | 
 | <span class="source-line-no">2743</span><span id="line-2743">      return false;</span> | 
 | <span class="source-line-no">2744</span><span id="line-2744">    }</span> | 
 | <span class="source-line-no">2745</span><span id="line-2745">    long now = EnvironmentEdgeManager.currentTime();</span> | 
 | <span class="source-line-no">2746</span><span id="line-2746">    // if we flushed in the recent past, we don't need to do again now</span> | 
 | <span class="source-line-no">2747</span><span id="line-2747">    if ((now - getEarliestFlushTimeForAllStores() < modifiedFlushCheckInterval)) {</span> | 
 | <span class="source-line-no">2748</span><span id="line-2748">      return false;</span> | 
 | <span class="source-line-no">2749</span><span id="line-2749">    }</span> | 
 | <span class="source-line-no">2750</span><span id="line-2750">    // since we didn't flush in the recent past, flush now if certain conditions</span> | 
 | <span class="source-line-no">2751</span><span id="line-2751">    // are met. Return true on first such memstore hit.</span> | 
 | <span class="source-line-no">2752</span><span id="line-2752">    for (HStore s : stores.values()) {</span> | 
 | <span class="source-line-no">2753</span><span id="line-2753">      if (s.timeOfOldestEdit() < now - modifiedFlushCheckInterval) {</span> | 
 | <span class="source-line-no">2754</span><span id="line-2754">        // we have an old enough edit in the memstore, flush</span> | 
 | <span class="source-line-no">2755</span><span id="line-2755">        whyFlush.append(s.toString() + " has an old edit so flush to free WALs");</span> | 
 | <span class="source-line-no">2756</span><span id="line-2756">        return true;</span> | 
 | <span class="source-line-no">2757</span><span id="line-2757">      }</span> | 
 | <span class="source-line-no">2758</span><span id="line-2758">    }</span> | 
 | <span class="source-line-no">2759</span><span id="line-2759">    return false;</span> | 
 | <span class="source-line-no">2760</span><span id="line-2760">  }</span> | 
 | <span class="source-line-no">2761</span><span id="line-2761"></span> | 
 | <span class="source-line-no">2762</span><span id="line-2762">  /**</span> | 
 | <span class="source-line-no">2763</span><span id="line-2763">   * Flushing all stores.</span> | 
 | <span class="source-line-no">2764</span><span id="line-2764">   * @see #internalFlushcache(Collection, MonitoredTask, boolean, FlushLifeCycleTracker)</span> | 
 | <span class="source-line-no">2765</span><span id="line-2765">   */</span> | 
 | <span class="source-line-no">2766</span><span id="line-2766">  private FlushResult internalFlushcache(MonitoredTask status) throws IOException {</span> | 
 | <span class="source-line-no">2767</span><span id="line-2767">    return internalFlushcache(stores.values(), status, false, FlushLifeCycleTracker.DUMMY);</span> | 
 | <span class="source-line-no">2768</span><span id="line-2768">  }</span> | 
 | <span class="source-line-no">2769</span><span id="line-2769"></span> | 
 | <span class="source-line-no">2770</span><span id="line-2770">  /**</span> | 
 | <span class="source-line-no">2771</span><span id="line-2771">   * Flushing given stores.</span> | 
 | <span class="source-line-no">2772</span><span id="line-2772">   * @see #internalFlushcache(WAL, long, Collection, MonitoredTask, boolean, FlushLifeCycleTracker)</span> | 
 | <span class="source-line-no">2773</span><span id="line-2773">   */</span> | 
 | <span class="source-line-no">2774</span><span id="line-2774">  private FlushResultImpl internalFlushcache(Collection<HStore> storesToFlush, MonitoredTask status,</span> | 
 | <span class="source-line-no">2775</span><span id="line-2775">    boolean writeFlushWalMarker, FlushLifeCycleTracker tracker) throws IOException {</span> | 
 | <span class="source-line-no">2776</span><span id="line-2776">    return internalFlushcache(this.wal, HConstants.NO_SEQNUM, storesToFlush, status,</span> | 
 | <span class="source-line-no">2777</span><span id="line-2777">      writeFlushWalMarker, tracker);</span> | 
 | <span class="source-line-no">2778</span><span id="line-2778">  }</span> | 
 | <span class="source-line-no">2779</span><span id="line-2779"></span> | 
 | <span class="source-line-no">2780</span><span id="line-2780">  /**</span> | 
 | <span class="source-line-no">2781</span><span id="line-2781">   * Flush the memstore. Flushing the memstore is a little tricky. We have a lot of updates in the</span> | 
 | <span class="source-line-no">2782</span><span id="line-2782">   * memstore, all of which have also been written to the wal. We need to write those updates in the</span> | 
 | <span class="source-line-no">2783</span><span id="line-2783">   * memstore out to disk, while being able to process reads/writes as much as possible during the</span> | 
 | <span class="source-line-no">2784</span><span id="line-2784">   * flush operation.</span> | 
 | <span class="source-line-no">2785</span><span id="line-2785">   * <p></span> | 
 | <span class="source-line-no">2786</span><span id="line-2786">   * This method may block for some time. Every time you call it, we up the regions sequence id even</span> | 
 | <span class="source-line-no">2787</span><span id="line-2787">   * if we don't flush; i.e. the returned region id will be at least one larger than the last edit</span> | 
 | <span class="source-line-no">2788</span><span id="line-2788">   * applied to this region. The returned id does not refer to an actual edit. The returned id can</span> | 
 | <span class="source-line-no">2789</span><span id="line-2789">   * be used for say installing a bulk loaded file just ahead of the last hfile that was the result</span> | 
 | <span class="source-line-no">2790</span><span id="line-2790">   * of this flush, etc.</span> | 
 | <span class="source-line-no">2791</span><span id="line-2791">   * @param wal           Null if we're NOT to go via wal.</span> | 
 | <span class="source-line-no">2792</span><span id="line-2792">   * @param myseqid       The seqid to use if <code>wal</code> is null writing out flush file.</span> | 
 | <span class="source-line-no">2793</span><span id="line-2793">   * @param storesToFlush The list of stores to flush.</span> | 
 | <span class="source-line-no">2794</span><span id="line-2794">   * @return object describing the flush's state</span> | 
 | <span class="source-line-no">2795</span><span id="line-2795">   * @throws IOException              general io exceptions</span> | 
 | <span class="source-line-no">2796</span><span id="line-2796">   * @throws DroppedSnapshotException Thrown when replay of WAL is required.</span> | 
 | <span class="source-line-no">2797</span><span id="line-2797">   */</span> | 
 | <span class="source-line-no">2798</span><span id="line-2798">  protected FlushResultImpl internalFlushcache(WAL wal, long myseqid,</span> | 
 | <span class="source-line-no">2799</span><span id="line-2799">    Collection<HStore> storesToFlush, MonitoredTask status, boolean writeFlushWalMarker,</span> | 
 | <span class="source-line-no">2800</span><span id="line-2800">    FlushLifeCycleTracker tracker) throws IOException {</span> | 
 | <span class="source-line-no">2801</span><span id="line-2801">    PrepareFlushResult result =</span> | 
 | <span class="source-line-no">2802</span><span id="line-2802">      internalPrepareFlushCache(wal, myseqid, storesToFlush, status, writeFlushWalMarker, tracker);</span> | 
 | <span class="source-line-no">2803</span><span id="line-2803">    if (result.result == null) {</span> | 
 | <span class="source-line-no">2804</span><span id="line-2804">      return internalFlushCacheAndCommit(wal, status, result, storesToFlush);</span> | 
 | <span class="source-line-no">2805</span><span id="line-2805">    } else {</span> | 
 | <span class="source-line-no">2806</span><span id="line-2806">      return result.result; // early exit due to failure from prepare stage</span> | 
 | <span class="source-line-no">2807</span><span id="line-2807">    }</span> | 
 | <span class="source-line-no">2808</span><span id="line-2808">  }</span> | 
 | <span class="source-line-no">2809</span><span id="line-2809"></span> | 
 | <span class="source-line-no">2810</span><span id="line-2810">  @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "DLS_DEAD_LOCAL_STORE",</span> | 
 | <span class="source-line-no">2811</span><span id="line-2811">      justification = "FindBugs seems confused about trxId")</span> | 
 | <span class="source-line-no">2812</span><span id="line-2812">  protected PrepareFlushResult internalPrepareFlushCache(WAL wal, long myseqid,</span> | 
 | <span class="source-line-no">2813</span><span id="line-2813">    Collection<HStore> storesToFlush, MonitoredTask status, boolean writeFlushWalMarker,</span> | 
 | <span class="source-line-no">2814</span><span id="line-2814">    FlushLifeCycleTracker tracker) throws IOException {</span> | 
 | <span class="source-line-no">2815</span><span id="line-2815">    if (this.rsServices != null && this.rsServices.isAborted()) {</span> | 
 | <span class="source-line-no">2816</span><span id="line-2816">      // Don't flush when server aborting, it's unsafe</span> | 
 | <span class="source-line-no">2817</span><span id="line-2817">      throw new IOException("Aborting flush because server is aborted...");</span> | 
 | <span class="source-line-no">2818</span><span id="line-2818">    }</span> | 
 | <span class="source-line-no">2819</span><span id="line-2819">    final long startTime = EnvironmentEdgeManager.currentTime();</span> | 
 | <span class="source-line-no">2820</span><span id="line-2820">    // If nothing to flush, return, but return with a valid unused sequenceId.</span> | 
 | <span class="source-line-no">2821</span><span id="line-2821">    // Its needed by bulk upload IIRC. It flushes until no edits in memory so it can insert a</span> | 
 | <span class="source-line-no">2822</span><span id="line-2822">    // bulk loaded file between memory and existing hfiles. It wants a good seqeunceId that belongs</span> | 
 | <span class="source-line-no">2823</span><span id="line-2823">    // to no other that it can use to associate with the bulk load. Hence this little dance below</span> | 
 | <span class="source-line-no">2824</span><span id="line-2824">    // to go get one.</span> | 
 | <span class="source-line-no">2825</span><span id="line-2825">    if (this.memStoreSizing.getDataSize() <= 0) {</span> | 
 | <span class="source-line-no">2826</span><span id="line-2826">      // Take an update lock so no edits can come into memory just yet.</span> | 
 | <span class="source-line-no">2827</span><span id="line-2827">      this.updatesLock.writeLock().lock();</span> | 
 | <span class="source-line-no">2828</span><span id="line-2828">      WriteEntry writeEntry = null;</span> | 
 | <span class="source-line-no">2829</span><span id="line-2829">      try {</span> | 
 | <span class="source-line-no">2830</span><span id="line-2830">        if (this.memStoreSizing.getDataSize() <= 0) {</span> | 
 | <span class="source-line-no">2831</span><span id="line-2831">          // Presume that if there are still no edits in the memstore, then there are no edits for</span> | 
 | <span class="source-line-no">2832</span><span id="line-2832">          // this region out in the WAL subsystem so no need to do any trickery clearing out</span> | 
 | <span class="source-line-no">2833</span><span id="line-2833">          // edits in the WAL sub-system. Up the sequence number so the resulting flush id is for</span> | 
 | <span class="source-line-no">2834</span><span id="line-2834">          // sure just beyond the last appended region edit and not associated with any edit</span> | 
 | <span class="source-line-no">2835</span><span id="line-2835">          // (useful as marker when bulk loading, etc.).</span> | 
 | <span class="source-line-no">2836</span><span id="line-2836">          if (wal != null) {</span> | 
 | <span class="source-line-no">2837</span><span id="line-2837">            writeEntry = mvcc.begin();</span> | 
 | <span class="source-line-no">2838</span><span id="line-2838">            long flushOpSeqId = writeEntry.getWriteNumber();</span> | 
 | <span class="source-line-no">2839</span><span id="line-2839">            FlushResultImpl flushResult = new FlushResultImpl(</span> | 
 | <span class="source-line-no">2840</span><span id="line-2840">              FlushResult.Result.CANNOT_FLUSH_MEMSTORE_EMPTY, flushOpSeqId, "Nothing to flush",</span> | 
 | <span class="source-line-no">2841</span><span id="line-2841">              writeCanNotFlushMarkerToWAL(writeEntry, wal, writeFlushWalMarker));</span> | 
 | <span class="source-line-no">2842</span><span id="line-2842">            mvcc.completeAndWait(writeEntry);</span> | 
 | <span class="source-line-no">2843</span><span id="line-2843">            // Set to null so we don't complete it again down in finally block.</span> | 
 | <span class="source-line-no">2844</span><span id="line-2844">            writeEntry = null;</span> | 
 | <span class="source-line-no">2845</span><span id="line-2845">            return new PrepareFlushResult(flushResult, myseqid);</span> | 
 | <span class="source-line-no">2846</span><span id="line-2846">          } else {</span> | 
 | <span class="source-line-no">2847</span><span id="line-2847">            return new PrepareFlushResult(new FlushResultImpl(</span> | 
 | <span class="source-line-no">2848</span><span id="line-2848">              FlushResult.Result.CANNOT_FLUSH_MEMSTORE_EMPTY, "Nothing to flush", false), myseqid);</span> | 
 | <span class="source-line-no">2849</span><span id="line-2849">          }</span> | 
 | <span class="source-line-no">2850</span><span id="line-2850">        }</span> | 
 | <span class="source-line-no">2851</span><span id="line-2851">      } finally {</span> | 
 | <span class="source-line-no">2852</span><span id="line-2852">        if (writeEntry != null) {</span> | 
 | <span class="source-line-no">2853</span><span id="line-2853">          // If writeEntry is non-null, this operation failed; the mvcc transaction failed...</span> | 
 | <span class="source-line-no">2854</span><span id="line-2854">          // but complete it anyways so it doesn't block the mvcc queue.</span> | 
 | <span class="source-line-no">2855</span><span id="line-2855">          mvcc.complete(writeEntry);</span> | 
 | <span class="source-line-no">2856</span><span id="line-2856">        }</span> | 
 | <span class="source-line-no">2857</span><span id="line-2857">        this.updatesLock.writeLock().unlock();</span> | 
 | <span class="source-line-no">2858</span><span id="line-2858">      }</span> | 
 | <span class="source-line-no">2859</span><span id="line-2859">    }</span> | 
 | <span class="source-line-no">2860</span><span id="line-2860">    logFatLineOnFlush(storesToFlush, myseqid);</span> | 
 | <span class="source-line-no">2861</span><span id="line-2861">    // Stop updates while we snapshot the memstore of all of these regions' stores. We only have</span> | 
 | <span class="source-line-no">2862</span><span id="line-2862">    // to do this for a moment. It is quick. We also set the memstore size to zero here before we</span> | 
 | <span class="source-line-no">2863</span><span id="line-2863">    // allow updates again so its value will represent the size of the updates received</span> | 
 | <span class="source-line-no">2864</span><span id="line-2864">    // during flush</span> | 
 | <span class="source-line-no">2865</span><span id="line-2865"></span> | 
 | <span class="source-line-no">2866</span><span id="line-2866">    // We have to take an update lock during snapshot, or else a write could end up in both snapshot</span> | 
 | <span class="source-line-no">2867</span><span id="line-2867">    // and memstore (makes it difficult to do atomic rows then)</span> | 
 | <span class="source-line-no">2868</span><span id="line-2868">    status.setStatus("Obtaining lock to block concurrent updates");</span> | 
 | <span class="source-line-no">2869</span><span id="line-2869">    // block waiting for the lock for internal flush</span> | 
 | <span class="source-line-no">2870</span><span id="line-2870">    this.updatesLock.writeLock().lock();</span> | 
 | <span class="source-line-no">2871</span><span id="line-2871">    status.setStatus("Preparing flush snapshotting stores in " + getRegionInfo().getEncodedName());</span> | 
 | <span class="source-line-no">2872</span><span id="line-2872">    MemStoreSizing totalSizeOfFlushableStores = new NonThreadSafeMemStoreSizing();</span> | 
 | <span class="source-line-no">2873</span><span id="line-2873"></span> | 
 | <span class="source-line-no">2874</span><span id="line-2874">    Map<byte[], Long> flushedFamilyNamesToSeq = new HashMap<>();</span> | 
 | <span class="source-line-no">2875</span><span id="line-2875">    for (HStore store : storesToFlush) {</span> | 
 | <span class="source-line-no">2876</span><span id="line-2876">      flushedFamilyNamesToSeq.put(store.getColumnFamilyDescriptor().getName(),</span> | 
 | <span class="source-line-no">2877</span><span id="line-2877">        store.preFlushSeqIDEstimation());</span> | 
 | <span class="source-line-no">2878</span><span id="line-2878">    }</span> | 
 | <span class="source-line-no">2879</span><span id="line-2879"></span> | 
 | <span class="source-line-no">2880</span><span id="line-2880">    TreeMap<byte[], StoreFlushContext> storeFlushCtxs = new TreeMap<>(Bytes.BYTES_COMPARATOR);</span> | 
 | <span class="source-line-no">2881</span><span id="line-2881">    TreeMap<byte[], List<Path>> committedFiles = new TreeMap<>(Bytes.BYTES_COMPARATOR);</span> | 
 | <span class="source-line-no">2882</span><span id="line-2882">    TreeMap<byte[], MemStoreSize> storeFlushableSize = new TreeMap<>(Bytes.BYTES_COMPARATOR);</span> | 
 | <span class="source-line-no">2883</span><span id="line-2883">    // The sequence id of this flush operation which is used to log FlushMarker and pass to</span> | 
 | <span class="source-line-no">2884</span><span id="line-2884">    // createFlushContext to use as the store file's sequence id. It can be in advance of edits</span> | 
 | <span class="source-line-no">2885</span><span id="line-2885">    // still in the memstore, edits that are in other column families yet to be flushed.</span> | 
 | <span class="source-line-no">2886</span><span id="line-2886">    long flushOpSeqId = HConstants.NO_SEQNUM;</span> | 
 | <span class="source-line-no">2887</span><span id="line-2887">    // The max flushed sequence id after this flush operation completes. All edits in memstore</span> | 
 | <span class="source-line-no">2888</span><span id="line-2888">    // will be in advance of this sequence id.</span> | 
 | <span class="source-line-no">2889</span><span id="line-2889">    long flushedSeqId = HConstants.NO_SEQNUM;</span> | 
 | <span class="source-line-no">2890</span><span id="line-2890">    byte[] encodedRegionName = getRegionInfo().getEncodedNameAsBytes();</span> | 
 | <span class="source-line-no">2891</span><span id="line-2891">    try {</span> | 
 | <span class="source-line-no">2892</span><span id="line-2892">      if (wal != null) {</span> | 
 | <span class="source-line-no">2893</span><span id="line-2893">        Long earliestUnflushedSequenceIdForTheRegion =</span> | 
 | <span class="source-line-no">2894</span><span id="line-2894">          wal.startCacheFlush(encodedRegionName, flushedFamilyNamesToSeq);</span> | 
 | <span class="source-line-no">2895</span><span id="line-2895">        if (earliestUnflushedSequenceIdForTheRegion == null) {</span> | 
 | <span class="source-line-no">2896</span><span id="line-2896">          // This should never happen. This is how startCacheFlush signals flush cannot proceed.</span> | 
 | <span class="source-line-no">2897</span><span id="line-2897">          String msg = this.getRegionInfo().getEncodedName() + " flush aborted; WAL closing.";</span> | 
 | <span class="source-line-no">2898</span><span id="line-2898">          status.setStatus(msg);</span> | 
 | <span class="source-line-no">2899</span><span id="line-2899">          return new PrepareFlushResult(</span> | 
 | <span class="source-line-no">2900</span><span id="line-2900">            new FlushResultImpl(FlushResult.Result.CANNOT_FLUSH, msg, false), myseqid);</span> | 
 | <span class="source-line-no">2901</span><span id="line-2901">        }</span> | 
 | <span class="source-line-no">2902</span><span id="line-2902">        flushOpSeqId = getNextSequenceId(wal);</span> | 
 | <span class="source-line-no">2903</span><span id="line-2903">        // Back up 1, minus 1 from oldest sequence id in memstore to get last 'flushed' edit</span> | 
 | <span class="source-line-no">2904</span><span id="line-2904">        flushedSeqId = earliestUnflushedSequenceIdForTheRegion.longValue() == HConstants.NO_SEQNUM</span> | 
 | <span class="source-line-no">2905</span><span id="line-2905">          ? flushOpSeqId</span> | 
 | <span class="source-line-no">2906</span><span id="line-2906">          : earliestUnflushedSequenceIdForTheRegion.longValue() - 1;</span> | 
 | <span class="source-line-no">2907</span><span id="line-2907">      } else {</span> | 
 | <span class="source-line-no">2908</span><span id="line-2908">        // use the provided sequence Id as WAL is not being used for this flush.</span> | 
 | <span class="source-line-no">2909</span><span id="line-2909">        flushedSeqId = flushOpSeqId = myseqid;</span> | 
 | <span class="source-line-no">2910</span><span id="line-2910">      }</span> | 
 | <span class="source-line-no">2911</span><span id="line-2911"></span> | 
 | <span class="source-line-no">2912</span><span id="line-2912">      for (HStore s : storesToFlush) {</span> | 
 | <span class="source-line-no">2913</span><span id="line-2913">        storeFlushCtxs.put(s.getColumnFamilyDescriptor().getName(),</span> | 
 | <span class="source-line-no">2914</span><span id="line-2914">          s.createFlushContext(flushOpSeqId, tracker));</span> | 
 | <span class="source-line-no">2915</span><span id="line-2915">        // for writing stores to WAL</span> | 
 | <span class="source-line-no">2916</span><span id="line-2916">        committedFiles.put(s.getColumnFamilyDescriptor().getName(), null);</span> | 
 | <span class="source-line-no">2917</span><span id="line-2917">      }</span> | 
 | <span class="source-line-no">2918</span><span id="line-2918"></span> | 
 | <span class="source-line-no">2919</span><span id="line-2919">      // write the snapshot start to WAL</span> | 
 | <span class="source-line-no">2920</span><span id="line-2920">      if (wal != null && !writestate.readOnly) {</span> | 
 | <span class="source-line-no">2921</span><span id="line-2921">        FlushDescriptor desc = ProtobufUtil.toFlushDescriptor(FlushAction.START_FLUSH,</span> | 
 | <span class="source-line-no">2922</span><span id="line-2922">          getRegionInfo(), flushOpSeqId, committedFiles);</span> | 
 | <span class="source-line-no">2923</span><span id="line-2923">        // No sync. Sync is below where no updates lock and we do FlushAction.COMMIT_FLUSH</span> | 
 | <span class="source-line-no">2924</span><span id="line-2924">        WALUtil.writeFlushMarker(wal, this.getReplicationScope(), getRegionInfo(), desc, false,</span> | 
 | <span class="source-line-no">2925</span><span id="line-2925">          mvcc, regionReplicationSink.orElse(null));</span> | 
 | <span class="source-line-no">2926</span><span id="line-2926">      }</span> | 
 | <span class="source-line-no">2927</span><span id="line-2927"></span> | 
 | <span class="source-line-no">2928</span><span id="line-2928">      // Prepare flush (take a snapshot)</span> | 
 | <span class="source-line-no">2929</span><span id="line-2929">      storeFlushCtxs.forEach((name, flush) -> {</span> | 
 | <span class="source-line-no">2930</span><span id="line-2930">        MemStoreSize snapshotSize = flush.prepare();</span> | 
 | <span class="source-line-no">2931</span><span id="line-2931">        totalSizeOfFlushableStores.incMemStoreSize(snapshotSize);</span> | 
 | <span class="source-line-no">2932</span><span id="line-2932">        storeFlushableSize.put(name, snapshotSize);</span> | 
 | <span class="source-line-no">2933</span><span id="line-2933">      });</span> | 
 | <span class="source-line-no">2934</span><span id="line-2934">    } catch (IOException ex) {</span> | 
 | <span class="source-line-no">2935</span><span id="line-2935">      doAbortFlushToWAL(wal, flushOpSeqId, committedFiles);</span> | 
 | <span class="source-line-no">2936</span><span id="line-2936">      throw ex;</span> | 
 | <span class="source-line-no">2937</span><span id="line-2937">    } finally {</span> | 
 | <span class="source-line-no">2938</span><span id="line-2938">      this.updatesLock.writeLock().unlock();</span> | 
 | <span class="source-line-no">2939</span><span id="line-2939">    }</span> | 
 | <span class="source-line-no">2940</span><span id="line-2940">    String s = "Finished memstore snapshotting " + this + ", syncing WAL and waiting on mvcc, "</span> | 
 | <span class="source-line-no">2941</span><span id="line-2941">      + "flushsize=" + totalSizeOfFlushableStores;</span> | 
 | <span class="source-line-no">2942</span><span id="line-2942">    status.setStatus(s);</span> | 
 | <span class="source-line-no">2943</span><span id="line-2943">    doSyncOfUnflushedWALChanges(wal, getRegionInfo());</span> | 
 | <span class="source-line-no">2944</span><span id="line-2944">    return new PrepareFlushResult(storeFlushCtxs, committedFiles, storeFlushableSize, startTime,</span> | 
 | <span class="source-line-no">2945</span><span id="line-2945">      flushOpSeqId, flushedSeqId, totalSizeOfFlushableStores);</span> | 
 | <span class="source-line-no">2946</span><span id="line-2946">  }</span> | 
 | <span class="source-line-no">2947</span><span id="line-2947"></span> | 
 | <span class="source-line-no">2948</span><span id="line-2948">  /**</span> | 
 | <span class="source-line-no">2949</span><span id="line-2949">   * Utility method broken out of internalPrepareFlushCache so that method is smaller.</span> | 
 | <span class="source-line-no">2950</span><span id="line-2950">   */</span> | 
 | <span class="source-line-no">2951</span><span id="line-2951">  private void logFatLineOnFlush(Collection<HStore> storesToFlush, long sequenceId) {</span> | 
 | <span class="source-line-no">2952</span><span id="line-2952">    if (!LOG.isInfoEnabled()) {</span> | 
 | <span class="source-line-no">2953</span><span id="line-2953">      return;</span> | 
 | <span class="source-line-no">2954</span><span id="line-2954">    }</span> | 
 | <span class="source-line-no">2955</span><span id="line-2955">    // Log a fat line detailing what is being flushed.</span> | 
 | <span class="source-line-no">2956</span><span id="line-2956">    StringBuilder perCfExtras = null;</span> | 
 | <span class="source-line-no">2957</span><span id="line-2957">    if (!isAllFamilies(storesToFlush)) {</span> | 
 | <span class="source-line-no">2958</span><span id="line-2958">      perCfExtras = new StringBuilder();</span> | 
 | <span class="source-line-no">2959</span><span id="line-2959">      for (HStore store : storesToFlush) {</span> | 
 | <span class="source-line-no">2960</span><span id="line-2960">        MemStoreSize mss = store.getFlushableSize();</span> | 
 | <span class="source-line-no">2961</span><span id="line-2961">        perCfExtras.append("; ").append(store.getColumnFamilyName());</span> | 
 | <span class="source-line-no">2962</span><span id="line-2962">        perCfExtras.append("={dataSize=").append(StringUtils.byteDesc(mss.getDataSize()));</span> | 
 | <span class="source-line-no">2963</span><span id="line-2963">        perCfExtras.append(", heapSize=").append(StringUtils.byteDesc(mss.getHeapSize()));</span> | 
 | <span class="source-line-no">2964</span><span id="line-2964">        perCfExtras.append(", offHeapSize=").append(StringUtils.byteDesc(mss.getOffHeapSize()));</span> | 
 | <span class="source-line-no">2965</span><span id="line-2965">        perCfExtras.append("}");</span> | 
 | <span class="source-line-no">2966</span><span id="line-2966">      }</span> | 
 | <span class="source-line-no">2967</span><span id="line-2967">    }</span> | 
 | <span class="source-line-no">2968</span><span id="line-2968">    MemStoreSize mss = this.memStoreSizing.getMemStoreSize();</span> | 
 | <span class="source-line-no">2969</span><span id="line-2969">    LOG.info("Flushing " + this.getRegionInfo().getEncodedName() + " " + storesToFlush.size() + "/"</span> | 
 | <span class="source-line-no">2970</span><span id="line-2970">      + stores.size() + " column families," + " dataSize=" + StringUtils.byteDesc(mss.getDataSize())</span> | 
 | <span class="source-line-no">2971</span><span id="line-2971">      + " heapSize=" + StringUtils.byteDesc(mss.getHeapSize())</span> | 
 | <span class="source-line-no">2972</span><span id="line-2972">      + ((perCfExtras != null && perCfExtras.length() > 0) ? perCfExtras.toString() : "")</span> | 
 | <span class="source-line-no">2973</span><span id="line-2973">      + ((wal != null) ? "" : "; WAL is null, using passed sequenceid=" + sequenceId));</span> | 
 | <span class="source-line-no">2974</span><span id="line-2974">  }</span> | 
 | <span class="source-line-no">2975</span><span id="line-2975"></span> | 
 | <span class="source-line-no">2976</span><span id="line-2976">  private void doAbortFlushToWAL(final WAL wal, final long flushOpSeqId,</span> | 
 | <span class="source-line-no">2977</span><span id="line-2977">    final Map<byte[], List<Path>> committedFiles) {</span> | 
 | <span class="source-line-no">2978</span><span id="line-2978">    if (wal == null) return;</span> | 
 | <span class="source-line-no">2979</span><span id="line-2979">    try {</span> | 
 | <span class="source-line-no">2980</span><span id="line-2980">      FlushDescriptor desc = ProtobufUtil.toFlushDescriptor(FlushAction.ABORT_FLUSH,</span> | 
 | <span class="source-line-no">2981</span><span id="line-2981">        getRegionInfo(), flushOpSeqId, committedFiles);</span> | 
 | <span class="source-line-no">2982</span><span id="line-2982">      WALUtil.writeFlushMarker(wal, this.getReplicationScope(), getRegionInfo(), desc, false, mvcc,</span> | 
 | <span class="source-line-no">2983</span><span id="line-2983">        null);</span> | 
 | <span class="source-line-no">2984</span><span id="line-2984">    } catch (Throwable t) {</span> | 
 | <span class="source-line-no">2985</span><span id="line-2985">      LOG.warn("Received unexpected exception trying to write ABORT_FLUSH marker to WAL: {} in "</span> | 
 | <span class="source-line-no">2986</span><span id="line-2986">        + " region {}", StringUtils.stringifyException(t), this);</span> | 
 | <span class="source-line-no">2987</span><span id="line-2987">      // ignore this since we will be aborting the RS with DSE.</span> | 
 | <span class="source-line-no">2988</span><span id="line-2988">    }</span> | 
 | <span class="source-line-no">2989</span><span id="line-2989">    // we have called wal.startCacheFlush(), now we have to abort it</span> | 
 | <span class="source-line-no">2990</span><span id="line-2990">    wal.abortCacheFlush(this.getRegionInfo().getEncodedNameAsBytes());</span> | 
 | <span class="source-line-no">2991</span><span id="line-2991">  }</span> | 
 | <span class="source-line-no">2992</span><span id="line-2992"></span> | 
 | <span class="source-line-no">2993</span><span id="line-2993">  /**</span> | 
 | <span class="source-line-no">2994</span><span id="line-2994">   * Sync unflushed WAL changes. See HBASE-8208 for details</span> | 
 | <span class="source-line-no">2995</span><span id="line-2995">   */</span> | 
 | <span class="source-line-no">2996</span><span id="line-2996">  private static void doSyncOfUnflushedWALChanges(final WAL wal, final RegionInfo hri)</span> | 
 | <span class="source-line-no">2997</span><span id="line-2997">    throws IOException {</span> | 
 | <span class="source-line-no">2998</span><span id="line-2998">    if (wal == null) {</span> | 
 | <span class="source-line-no">2999</span><span id="line-2999">      return;</span> | 
 | <span class="source-line-no">3000</span><span id="line-3000">    }</span> | 
 | <span class="source-line-no">3001</span><span id="line-3001">    try {</span> | 
 | <span class="source-line-no">3002</span><span id="line-3002">      wal.sync(); // ensure that flush marker is sync'ed</span> | 
 | <span class="source-line-no">3003</span><span id="line-3003">    } catch (IOException ioe) {</span> | 
 | <span class="source-line-no">3004</span><span id="line-3004">      wal.abortCacheFlush(hri.getEncodedNameAsBytes());</span> | 
 | <span class="source-line-no">3005</span><span id="line-3005">      throw ioe;</span> | 
 | <span class="source-line-no">3006</span><span id="line-3006">    }</span> | 
 | <span class="source-line-no">3007</span><span id="line-3007">  }</span> | 
 | <span class="source-line-no">3008</span><span id="line-3008"></span> | 
 | <span class="source-line-no">3009</span><span id="line-3009">  /** Returns True if passed Set is all families in the region. */</span> | 
 | <span class="source-line-no">3010</span><span id="line-3010">  private boolean isAllFamilies(Collection<HStore> families) {</span> | 
 | <span class="source-line-no">3011</span><span id="line-3011">    return families == null || this.stores.size() == families.size();</span> | 
 | <span class="source-line-no">3012</span><span id="line-3012">  }</span> | 
 | <span class="source-line-no">3013</span><span id="line-3013"></span> | 
 | <span class="source-line-no">3014</span><span id="line-3014">  /**</span> | 
 | <span class="source-line-no">3015</span><span id="line-3015">   * This method is only used when we flush but the memstore is empty,if writeFlushWalMarker is</span> | 
 | <span class="source-line-no">3016</span><span id="line-3016">   * true,we write the {@link FlushAction#CANNOT_FLUSH} flush marker to WAL when the memstore is</span> | 
 | <span class="source-line-no">3017</span><span id="line-3017">   * empty. Ignores exceptions from WAL. Returns whether the write succeeded.</span> | 
 | <span class="source-line-no">3018</span><span id="line-3018">   * @return whether WAL write was successful</span> | 
 | <span class="source-line-no">3019</span><span id="line-3019">   */</span> | 
 | <span class="source-line-no">3020</span><span id="line-3020">  private boolean writeCanNotFlushMarkerToWAL(WriteEntry flushOpSeqIdMVCCEntry, WAL wal,</span> | 
 | <span class="source-line-no">3021</span><span id="line-3021">    boolean writeFlushWalMarker) {</span> | 
 | <span class="source-line-no">3022</span><span id="line-3022">    FlushDescriptor desc = ProtobufUtil.toFlushDescriptor(FlushAction.CANNOT_FLUSH, getRegionInfo(),</span> | 
 | <span class="source-line-no">3023</span><span id="line-3023">      -1, new TreeMap<>(Bytes.BYTES_COMPARATOR));</span> | 
 | <span class="source-line-no">3024</span><span id="line-3024">    RegionReplicationSink sink = regionReplicationSink.orElse(null);</span> | 
 | <span class="source-line-no">3025</span><span id="line-3025"></span> | 
 | <span class="source-line-no">3026</span><span id="line-3026">    if (sink != null && !writeFlushWalMarker) {</span> | 
 | <span class="source-line-no">3027</span><span id="line-3027">      /**</span> | 
 | <span class="source-line-no">3028</span><span id="line-3028">       * Here for replication to secondary region replica could use {@link FlushAction#CANNOT_FLUSH}</span> | 
 | <span class="source-line-no">3029</span><span id="line-3029">       * to recover when writeFlushWalMarker is false, we create {@link WALEdit} for</span> | 
 | <span class="source-line-no">3030</span><span id="line-3030">       * {@link FlushDescriptor} and attach the {@link RegionReplicationSink#add} to the</span> | 
 | <span class="source-line-no">3031</span><span id="line-3031">       * flushOpSeqIdMVCCEntry,see HBASE-26960 for more details.</span> | 
 | <span class="source-line-no">3032</span><span id="line-3032">       */</span> | 
 | <span class="source-line-no">3033</span><span id="line-3033">      this.attachRegionReplicationToFlushOpSeqIdMVCCEntry(flushOpSeqIdMVCCEntry, desc, sink);</span> | 
 | <span class="source-line-no">3034</span><span id="line-3034">      return false;</span> | 
 | <span class="source-line-no">3035</span><span id="line-3035">    }</span> | 
 | <span class="source-line-no">3036</span><span id="line-3036"></span> | 
 | <span class="source-line-no">3037</span><span id="line-3037">    if (writeFlushWalMarker && wal != null && !writestate.readOnly) {</span> | 
 | <span class="source-line-no">3038</span><span id="line-3038">      try {</span> | 
 | <span class="source-line-no">3039</span><span id="line-3039">        WALUtil.writeFlushMarker(wal, this.getReplicationScope(), getRegionInfo(), desc, true, mvcc,</span> | 
 | <span class="source-line-no">3040</span><span id="line-3040">          sink);</span> | 
 | <span class="source-line-no">3041</span><span id="line-3041">        return true;</span> | 
 | <span class="source-line-no">3042</span><span id="line-3042">      } catch (IOException e) {</span> | 
 | <span class="source-line-no">3043</span><span id="line-3043">        LOG.warn(getRegionInfo().getEncodedName() + " : "</span> | 
 | <span class="source-line-no">3044</span><span id="line-3044">          + "Received exception while trying to write the flush request to wal", e);</span> | 
 | <span class="source-line-no">3045</span><span id="line-3045">      }</span> | 
 | <span class="source-line-no">3046</span><span id="line-3046">    }</span> | 
 | <span class="source-line-no">3047</span><span id="line-3047">    return false;</span> | 
 | <span class="source-line-no">3048</span><span id="line-3048">  }</span> | 
 | <span class="source-line-no">3049</span><span id="line-3049"></span> | 
 | <span class="source-line-no">3050</span><span id="line-3050">  /**</span> | 
 | <span class="source-line-no">3051</span><span id="line-3051">   * Create {@link WALEdit} for {@link FlushDescriptor} and attach {@link RegionReplicationSink#add}</span> | 
 | <span class="source-line-no">3052</span><span id="line-3052">   * to the flushOpSeqIdMVCCEntry.</span> | 
 | <span class="source-line-no">3053</span><span id="line-3053">   */</span> | 
 | <span class="source-line-no">3054</span><span id="line-3054">  private void attachRegionReplicationToFlushOpSeqIdMVCCEntry(WriteEntry flushOpSeqIdMVCCEntry,</span> | 
 | <span class="source-line-no">3055</span><span id="line-3055">    FlushDescriptor desc, RegionReplicationSink sink) {</span> | 
 | <span class="source-line-no">3056</span><span id="line-3056">    assert !flushOpSeqIdMVCCEntry.getCompletionAction().isPresent();</span> | 
 | <span class="source-line-no">3057</span><span id="line-3057">    WALEdit flushMarkerWALEdit = WALEdit.createFlushWALEdit(getRegionInfo(), desc);</span> | 
 | <span class="source-line-no">3058</span><span id="line-3058">    WALKeyImpl walKey =</span> | 
 | <span class="source-line-no">3059</span><span id="line-3059">      WALUtil.createWALKey(getRegionInfo(), mvcc, this.getReplicationScope(), null);</span> | 
 | <span class="source-line-no">3060</span><span id="line-3060">    walKey.setWriteEntry(flushOpSeqIdMVCCEntry);</span> | 
 | <span class="source-line-no">3061</span><span id="line-3061">    /**</span> | 
 | <span class="source-line-no">3062</span><span id="line-3062">     * Here the {@link ServerCall} is null for {@link RegionReplicationSink#add} because the</span> | 
 | <span class="source-line-no">3063</span><span id="line-3063">     * flushMarkerWALEdit is created by ourselves, not from rpc.</span> | 
 | <span class="source-line-no">3064</span><span id="line-3064">     */</span> | 
 | <span class="source-line-no">3065</span><span id="line-3065">    flushOpSeqIdMVCCEntry.attachCompletionAction(() -> sink.add(walKey, flushMarkerWALEdit, null));</span> | 
 | <span class="source-line-no">3066</span><span id="line-3066">  }</span> | 
 | <span class="source-line-no">3067</span><span id="line-3067"></span> | 
 | <span class="source-line-no">3068</span><span id="line-3068">  @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "NN_NAKED_NOTIFY",</span> | 
 | <span class="source-line-no">3069</span><span id="line-3069">      justification = "Intentional; notify is about completed flush")</span> | 
 | <span class="source-line-no">3070</span><span id="line-3070">  FlushResultImpl internalFlushCacheAndCommit(WAL wal, MonitoredTask status,</span> | 
 | <span class="source-line-no">3071</span><span id="line-3071">    PrepareFlushResult prepareResult, Collection<HStore> storesToFlush) throws IOException {</span> | 
 | <span class="source-line-no">3072</span><span id="line-3072">    // prepare flush context is carried via PrepareFlushResult</span> | 
 | <span class="source-line-no">3073</span><span id="line-3073">    TreeMap<byte[], StoreFlushContext> storeFlushCtxs = prepareResult.storeFlushCtxs;</span> | 
 | <span class="source-line-no">3074</span><span id="line-3074">    TreeMap<byte[], List<Path>> committedFiles = prepareResult.committedFiles;</span> | 
 | <span class="source-line-no">3075</span><span id="line-3075">    long startTime = prepareResult.startTime;</span> | 
 | <span class="source-line-no">3076</span><span id="line-3076">    long flushOpSeqId = prepareResult.flushOpSeqId;</span> | 
 | <span class="source-line-no">3077</span><span id="line-3077">    long flushedSeqId = prepareResult.flushedSeqId;</span> | 
 | <span class="source-line-no">3078</span><span id="line-3078"></span> | 
 | <span class="source-line-no">3079</span><span id="line-3079">    String s = "Flushing stores of " + this;</span> | 
 | <span class="source-line-no">3080</span><span id="line-3080">    status.setStatus(s);</span> | 
 | <span class="source-line-no">3081</span><span id="line-3081">    if (LOG.isTraceEnabled()) LOG.trace(s);</span> | 
 | <span class="source-line-no">3082</span><span id="line-3082"></span> | 
 | <span class="source-line-no">3083</span><span id="line-3083">    // Any failure from here on out will be catastrophic requiring server</span> | 
 | <span class="source-line-no">3084</span><span id="line-3084">    // restart so wal content can be replayed and put back into the memstore.</span> | 
 | <span class="source-line-no">3085</span><span id="line-3085">    // Otherwise, the snapshot content while backed up in the wal, it will not</span> | 
 | <span class="source-line-no">3086</span><span id="line-3086">    // be part of the current running servers state.</span> | 
 | <span class="source-line-no">3087</span><span id="line-3087">    boolean compactionRequested = false;</span> | 
 | <span class="source-line-no">3088</span><span id="line-3088">    long flushedOutputFileSize = 0;</span> | 
 | <span class="source-line-no">3089</span><span id="line-3089">    try {</span> | 
 | <span class="source-line-no">3090</span><span id="line-3090">      // A. Flush memstore to all the HStores.</span> | 
 | <span class="source-line-no">3091</span><span id="line-3091">      // Keep running vector of all store files that includes both old and the</span> | 
 | <span class="source-line-no">3092</span><span id="line-3092">      // just-made new flush store file. The new flushed file is still in the</span> | 
 | <span class="source-line-no">3093</span><span id="line-3093">      // tmp directory.</span> | 
 | <span class="source-line-no">3094</span><span id="line-3094"></span> | 
 | <span class="source-line-no">3095</span><span id="line-3095">      for (StoreFlushContext flush : storeFlushCtxs.values()) {</span> | 
 | <span class="source-line-no">3096</span><span id="line-3096">        flush.flushCache(status);</span> | 
 | <span class="source-line-no">3097</span><span id="line-3097">      }</span> | 
 | <span class="source-line-no">3098</span><span id="line-3098"></span> | 
 | <span class="source-line-no">3099</span><span id="line-3099">      // Switch snapshot (in memstore) -> new hfile (thus causing</span> | 
 | <span class="source-line-no">3100</span><span id="line-3100">      // all the store scanners to reset/reseek).</span> | 
 | <span class="source-line-no">3101</span><span id="line-3101">      for (Map.Entry<byte[], StoreFlushContext> flushEntry : storeFlushCtxs.entrySet()) {</span> | 
 | <span class="source-line-no">3102</span><span id="line-3102">        StoreFlushContext sfc = flushEntry.getValue();</span> | 
 | <span class="source-line-no">3103</span><span id="line-3103">        boolean needsCompaction = sfc.commit(status);</span> | 
 | <span class="source-line-no">3104</span><span id="line-3104">        if (needsCompaction) {</span> | 
 | <span class="source-line-no">3105</span><span id="line-3105">          compactionRequested = true;</span> | 
 | <span class="source-line-no">3106</span><span id="line-3106">        }</span> | 
 | <span class="source-line-no">3107</span><span id="line-3107">        byte[] storeName = flushEntry.getKey();</span> | 
 | <span class="source-line-no">3108</span><span id="line-3108">        List<Path> storeCommittedFiles = sfc.getCommittedFiles();</span> | 
 | <span class="source-line-no">3109</span><span id="line-3109">        committedFiles.put(storeName, storeCommittedFiles);</span> | 
 | <span class="source-line-no">3110</span><span id="line-3110">        // Flush committed no files, indicating flush is empty or flush was canceled</span> | 
 | <span class="source-line-no">3111</span><span id="line-3111">        if (storeCommittedFiles == null || storeCommittedFiles.isEmpty()) {</span> | 
 | <span class="source-line-no">3112</span><span id="line-3112">          MemStoreSize storeFlushableSize = prepareResult.storeFlushableSize.get(storeName);</span> | 
 | <span class="source-line-no">3113</span><span id="line-3113">          prepareResult.totalFlushableSize.decMemStoreSize(storeFlushableSize);</span> | 
 | <span class="source-line-no">3114</span><span id="line-3114">        }</span> | 
 | <span class="source-line-no">3115</span><span id="line-3115">        flushedOutputFileSize += sfc.getOutputFileSize();</span> | 
 | <span class="source-line-no">3116</span><span id="line-3116">      }</span> | 
 | <span class="source-line-no">3117</span><span id="line-3117">      storeFlushCtxs.clear();</span> | 
 | <span class="source-line-no">3118</span><span id="line-3118"></span> | 
 | <span class="source-line-no">3119</span><span id="line-3119">      // Set down the memstore size by amount of flush.</span> | 
 | <span class="source-line-no">3120</span><span id="line-3120">      MemStoreSize mss = prepareResult.totalFlushableSize.getMemStoreSize();</span> | 
 | <span class="source-line-no">3121</span><span id="line-3121">      this.decrMemStoreSize(mss);</span> | 
 | <span class="source-line-no">3122</span><span id="line-3122"></span> | 
 | <span class="source-line-no">3123</span><span id="line-3123">      // Increase the size of this Region for the purposes of quota. Noop if quotas are disabled.</span> | 
 | <span class="source-line-no">3124</span><span id="line-3124">      // During startup, quota manager may not be initialized yet.</span> | 
 | <span class="source-line-no">3125</span><span id="line-3125">      if (rsServices != null) {</span> | 
 | <span class="source-line-no">3126</span><span id="line-3126">        RegionServerSpaceQuotaManager quotaManager = rsServices.getRegionServerSpaceQuotaManager();</span> | 
 | <span class="source-line-no">3127</span><span id="line-3127">        if (quotaManager != null) {</span> | 
 | <span class="source-line-no">3128</span><span id="line-3128">          quotaManager.getRegionSizeStore().incrementRegionSize(this.getRegionInfo(),</span> | 
 | <span class="source-line-no">3129</span><span id="line-3129">            flushedOutputFileSize);</span> | 
 | <span class="source-line-no">3130</span><span id="line-3130">        }</span> | 
 | <span class="source-line-no">3131</span><span id="line-3131">      }</span> | 
 | <span class="source-line-no">3132</span><span id="line-3132"></span> | 
 | <span class="source-line-no">3133</span><span id="line-3133">      if (wal != null) {</span> | 
 | <span class="source-line-no">3134</span><span id="line-3134">        // write flush marker to WAL. If fail, we should throw DroppedSnapshotException</span> | 
 | <span class="source-line-no">3135</span><span id="line-3135">        FlushDescriptor desc = ProtobufUtil.toFlushDescriptor(FlushAction.COMMIT_FLUSH,</span> | 
 | <span class="source-line-no">3136</span><span id="line-3136">          getRegionInfo(), flushOpSeqId, committedFiles);</span> | 
 | <span class="source-line-no">3137</span><span id="line-3137">        WALUtil.writeFlushMarker(wal, this.getReplicationScope(), getRegionInfo(), desc, true, mvcc,</span> | 
 | <span class="source-line-no">3138</span><span id="line-3138">          regionReplicationSink.orElse(null));</span> | 
 | <span class="source-line-no">3139</span><span id="line-3139">      }</span> | 
 | <span class="source-line-no">3140</span><span id="line-3140">    } catch (Throwable t) {</span> | 
 | <span class="source-line-no">3141</span><span id="line-3141">      // An exception here means that the snapshot was not persisted.</span> | 
 | <span class="source-line-no">3142</span><span id="line-3142">      // The wal needs to be replayed so its content is restored to memstore.</span> | 
 | <span class="source-line-no">3143</span><span id="line-3143">      // Currently, only a server restart will do this.</span> | 
 | <span class="source-line-no">3144</span><span id="line-3144">      // We used to only catch IOEs but its possible that we'd get other</span> | 
 | <span class="source-line-no">3145</span><span id="line-3145">      // exceptions -- e.g. HBASE-659 was about an NPE -- so now we catch</span> | 
 | <span class="source-line-no">3146</span><span id="line-3146">      // all and sundry.</span> | 
 | <span class="source-line-no">3147</span><span id="line-3147">      if (wal != null) {</span> | 
 | <span class="source-line-no">3148</span><span id="line-3148">        try {</span> | 
 | <span class="source-line-no">3149</span><span id="line-3149">          FlushDescriptor desc = ProtobufUtil.toFlushDescriptor(FlushAction.ABORT_FLUSH,</span> | 
 | <span class="source-line-no">3150</span><span id="line-3150">            getRegionInfo(), flushOpSeqId, committedFiles);</span> | 
 | <span class="source-line-no">3151</span><span id="line-3151">          WALUtil.writeFlushMarker(wal, this.replicationScope, getRegionInfo(), desc, false, mvcc,</span> | 
 | <span class="source-line-no">3152</span><span id="line-3152">            null);</span> | 
 | <span class="source-line-no">3153</span><span id="line-3153">        } catch (Throwable ex) {</span> | 
 | <span class="source-line-no">3154</span><span id="line-3154">          LOG.warn(</span> | 
 | <span class="source-line-no">3155</span><span id="line-3155">            getRegionInfo().getEncodedName() + " : " + "failed writing ABORT_FLUSH marker to WAL",</span> | 
 | <span class="source-line-no">3156</span><span id="line-3156">            ex);</span> | 
 | <span class="source-line-no">3157</span><span id="line-3157">          // ignore this since we will be aborting the RS with DSE.</span> | 
 | <span class="source-line-no">3158</span><span id="line-3158">        }</span> | 
 | <span class="source-line-no">3159</span><span id="line-3159">        wal.abortCacheFlush(this.getRegionInfo().getEncodedNameAsBytes());</span> | 
 | <span class="source-line-no">3160</span><span id="line-3160">      }</span> | 
 | <span class="source-line-no">3161</span><span id="line-3161">      DroppedSnapshotException dse = new DroppedSnapshotException(</span> | 
 | <span class="source-line-no">3162</span><span id="line-3162">        "region: " + Bytes.toStringBinary(getRegionInfo().getRegionName()), t);</span> | 
 | <span class="source-line-no">3163</span><span id="line-3163">      status.abort("Flush failed: " + StringUtils.stringifyException(t));</span> | 
 | <span class="source-line-no">3164</span><span id="line-3164"></span> | 
 | <span class="source-line-no">3165</span><span id="line-3165">      // Callers for flushcache() should catch DroppedSnapshotException and abort the region server.</span> | 
 | <span class="source-line-no">3166</span><span id="line-3166">      // However, since we may have the region read lock, we cannot call close(true) here since</span> | 
 | <span class="source-line-no">3167</span><span id="line-3167">      // we cannot promote to a write lock. Instead we are setting closing so that all other region</span> | 
 | <span class="source-line-no">3168</span><span id="line-3168">      // operations except for close will be rejected.</span> | 
 | <span class="source-line-no">3169</span><span id="line-3169">      this.closing.set(true);</span> | 
 | <span class="source-line-no">3170</span><span id="line-3170"></span> | 
 | <span class="source-line-no">3171</span><span id="line-3171">      if (rsServices != null) {</span> | 
 | <span class="source-line-no">3172</span><span id="line-3172">        // This is a safeguard against the case where the caller fails to explicitly handle aborting</span> | 
 | <span class="source-line-no">3173</span><span id="line-3173">        rsServices.abort("Replay of WAL required. Forcing server shutdown", dse);</span> | 
 | <span class="source-line-no">3174</span><span id="line-3174">      }</span> | 
 | <span class="source-line-no">3175</span><span id="line-3175"></span> | 
 | <span class="source-line-no">3176</span><span id="line-3176">      throw dse;</span> | 
 | <span class="source-line-no">3177</span><span id="line-3177">    }</span> | 
 | <span class="source-line-no">3178</span><span id="line-3178"></span> | 
 | <span class="source-line-no">3179</span><span id="line-3179">    // If we get to here, the HStores have been written.</span> | 
 | <span class="source-line-no">3180</span><span id="line-3180">    if (wal != null) {</span> | 
 | <span class="source-line-no">3181</span><span id="line-3181">      wal.completeCacheFlush(this.getRegionInfo().getEncodedNameAsBytes(), flushedSeqId);</span> | 
 | <span class="source-line-no">3182</span><span id="line-3182">    }</span> | 
 | <span class="source-line-no">3183</span><span id="line-3183"></span> | 
 | <span class="source-line-no">3184</span><span id="line-3184">    // Record latest flush time</span> | 
 | <span class="source-line-no">3185</span><span id="line-3185">    for (HStore store : storesToFlush) {</span> | 
 | <span class="source-line-no">3186</span><span id="line-3186">      this.lastStoreFlushTimeMap.put(store, startTime);</span> | 
 | <span class="source-line-no">3187</span><span id="line-3187">    }</span> | 
 | <span class="source-line-no">3188</span><span id="line-3188"></span> | 
 | <span class="source-line-no">3189</span><span id="line-3189">    this.maxFlushedSeqId = flushedSeqId;</span> | 
 | <span class="source-line-no">3190</span><span id="line-3190">    this.lastFlushOpSeqId = flushOpSeqId;</span> | 
 | <span class="source-line-no">3191</span><span id="line-3191"></span> | 
 | <span class="source-line-no">3192</span><span id="line-3192">    // C. Finally notify anyone waiting on memstore to clear:</span> | 
 | <span class="source-line-no">3193</span><span id="line-3193">    // e.g. checkResources().</span> | 
 | <span class="source-line-no">3194</span><span id="line-3194">    synchronized (this) {</span> | 
 | <span class="source-line-no">3195</span><span id="line-3195">      notifyAll(); // FindBugs NN_NAKED_NOTIFY</span> | 
 | <span class="source-line-no">3196</span><span id="line-3196">    }</span> | 
 | <span class="source-line-no">3197</span><span id="line-3197"></span> | 
 | <span class="source-line-no">3198</span><span id="line-3198">    long time = EnvironmentEdgeManager.currentTime() - startTime;</span> | 
 | <span class="source-line-no">3199</span><span id="line-3199">    MemStoreSize mss = prepareResult.totalFlushableSize.getMemStoreSize();</span> | 
 | <span class="source-line-no">3200</span><span id="line-3200">    long memstoresize = this.memStoreSizing.getMemStoreSize().getDataSize();</span> | 
 | <span class="source-line-no">3201</span><span id="line-3201">    String msg = "Finished flush of" + " dataSize ~" + StringUtils.byteDesc(mss.getDataSize()) + "/"</span> | 
 | <span class="source-line-no">3202</span><span id="line-3202">      + mss.getDataSize() + ", heapSize ~" + StringUtils.byteDesc(mss.getHeapSize()) + "/"</span> | 
 | <span class="source-line-no">3203</span><span id="line-3203">      + mss.getHeapSize() + ", currentSize=" + StringUtils.byteDesc(memstoresize) + "/"</span> | 
 | <span class="source-line-no">3204</span><span id="line-3204">      + memstoresize + " for " + this.getRegionInfo().getEncodedName() + " in " + time</span> | 
 | <span class="source-line-no">3205</span><span id="line-3205">      + "ms, sequenceid=" + flushOpSeqId + ", compaction requested=" + compactionRequested</span> | 
 | <span class="source-line-no">3206</span><span id="line-3206">      + ((wal == null) ? "; wal=null" : "");</span> | 
 | <span class="source-line-no">3207</span><span id="line-3207">    LOG.info(msg);</span> | 
 | <span class="source-line-no">3208</span><span id="line-3208">    status.setStatus(msg);</span> | 
 | <span class="source-line-no">3209</span><span id="line-3209"></span> | 
 | <span class="source-line-no">3210</span><span id="line-3210">    if (rsServices != null && rsServices.getMetrics() != null) {</span> | 
 | <span class="source-line-no">3211</span><span id="line-3211">      rsServices.getMetrics().updateFlush(getTableDescriptor().getTableName().getNameAsString(),</span> | 
 | <span class="source-line-no">3212</span><span id="line-3212">        time, mss.getDataSize(), flushedOutputFileSize);</span> | 
 | <span class="source-line-no">3213</span><span id="line-3213">    }</span> | 
 | <span class="source-line-no">3214</span><span id="line-3214"></span> | 
 | <span class="source-line-no">3215</span><span id="line-3215">    return new FlushResultImpl(compactionRequested</span> | 
 | <span class="source-line-no">3216</span><span id="line-3216">      ? FlushResult.Result.FLUSHED_COMPACTION_NEEDED</span> | 
 | <span class="source-line-no">3217</span><span id="line-3217">      : FlushResult.Result.FLUSHED_NO_COMPACTION_NEEDED, flushOpSeqId);</span> | 
 | <span class="source-line-no">3218</span><span id="line-3218">  }</span> | 
 | <span class="source-line-no">3219</span><span id="line-3219"></span> | 
 | <span class="source-line-no">3220</span><span id="line-3220">  /**</span> | 
 | <span class="source-line-no">3221</span><span id="line-3221">   * Method to safely get the next sequence number.</span> | 
 | <span class="source-line-no">3222</span><span id="line-3222">   * @return Next sequence number unassociated with any actual edit.</span> | 
 | <span class="source-line-no">3223</span><span id="line-3223">   */</span> | 
 | <span class="source-line-no">3224</span><span id="line-3224">  protected long getNextSequenceId(final WAL wal) throws IOException {</span> | 
 | <span class="source-line-no">3225</span><span id="line-3225">    WriteEntry we = mvcc.begin();</span> | 
 | <span class="source-line-no">3226</span><span id="line-3226">    mvcc.completeAndWait(we);</span> | 
 | <span class="source-line-no">3227</span><span id="line-3227">    return we.getWriteNumber();</span> | 
 | <span class="source-line-no">3228</span><span id="line-3228">  }</span> | 
 | <span class="source-line-no">3229</span><span id="line-3229"></span> | 
 | <span class="source-line-no">3230</span><span id="line-3230">  //////////////////////////////////////////////////////////////////////////////</span> | 
 | <span class="source-line-no">3231</span><span id="line-3231">  // get() methods for client use.</span> | 
 | <span class="source-line-no">3232</span><span id="line-3232">  //////////////////////////////////////////////////////////////////////////////</span> | 
 | <span class="source-line-no">3233</span><span id="line-3233"></span> | 
 | <span class="source-line-no">3234</span><span id="line-3234">  @Override</span> | 
 | <span class="source-line-no">3235</span><span id="line-3235">  public RegionScannerImpl getScanner(Scan scan) throws IOException {</span> | 
 | <span class="source-line-no">3236</span><span id="line-3236">    return getScanner(scan, null);</span> | 
 | <span class="source-line-no">3237</span><span id="line-3237">  }</span> | 
 | <span class="source-line-no">3238</span><span id="line-3238"></span> | 
 | <span class="source-line-no">3239</span><span id="line-3239">  @Override</span> | 
 | <span class="source-line-no">3240</span><span id="line-3240">  public RegionScannerImpl getScanner(Scan scan, List<KeyValueScanner> additionalScanners)</span> | 
 | <span class="source-line-no">3241</span><span id="line-3241">    throws IOException {</span> | 
 | <span class="source-line-no">3242</span><span id="line-3242">    return getScanner(scan, additionalScanners, HConstants.NO_NONCE, HConstants.NO_NONCE);</span> | 
 | <span class="source-line-no">3243</span><span id="line-3243">  }</span> | 
 | <span class="source-line-no">3244</span><span id="line-3244"></span> | 
 | <span class="source-line-no">3245</span><span id="line-3245">  private RegionScannerImpl getScanner(Scan scan, List<KeyValueScanner> additionalScanners,</span> | 
 | <span class="source-line-no">3246</span><span id="line-3246">    long nonceGroup, long nonce) throws IOException {</span> | 
 | <span class="source-line-no">3247</span><span id="line-3247">    return TraceUtil.trace(() -> {</span> | 
 | <span class="source-line-no">3248</span><span id="line-3248">      startRegionOperation(Operation.SCAN);</span> | 
 | <span class="source-line-no">3249</span><span id="line-3249">      try {</span> | 
 | <span class="source-line-no">3250</span><span id="line-3250">        // Verify families are all valid</span> | 
 | <span class="source-line-no">3251</span><span id="line-3251">        if (!scan.hasFamilies()) {</span> | 
 | <span class="source-line-no">3252</span><span id="line-3252">          // Adding all families to scanner</span> | 
 | <span class="source-line-no">3253</span><span id="line-3253">          for (byte[] family : this.htableDescriptor.getColumnFamilyNames()) {</span> | 
 | <span class="source-line-no">3254</span><span id="line-3254">            scan.addFamily(family);</span> | 
 | <span class="source-line-no">3255</span><span id="line-3255">          }</span> | 
 | <span class="source-line-no">3256</span><span id="line-3256">        } else {</span> | 
 | <span class="source-line-no">3257</span><span id="line-3257">          for (byte[] family : scan.getFamilyMap().keySet()) {</span> | 
 | <span class="source-line-no">3258</span><span id="line-3258">            checkFamily(family);</span> | 
 | <span class="source-line-no">3259</span><span id="line-3259">          }</span> | 
 | <span class="source-line-no">3260</span><span id="line-3260">        }</span> | 
 | <span class="source-line-no">3261</span><span id="line-3261">        return instantiateRegionScanner(scan, additionalScanners, nonceGroup, nonce);</span> | 
 | <span class="source-line-no">3262</span><span id="line-3262">      } finally {</span> | 
 | <span class="source-line-no">3263</span><span id="line-3263">        closeRegionOperation(Operation.SCAN);</span> | 
 | <span class="source-line-no">3264</span><span id="line-3264">      }</span> | 
 | <span class="source-line-no">3265</span><span id="line-3265">    }, () -> createRegionSpan("Region.getScanner"));</span> | 
 | <span class="source-line-no">3266</span><span id="line-3266">  }</span> | 
 | <span class="source-line-no">3267</span><span id="line-3267"></span> | 
 | <span class="source-line-no">3268</span><span id="line-3268">  protected RegionScannerImpl instantiateRegionScanner(Scan scan,</span> | 
 | <span class="source-line-no">3269</span><span id="line-3269">    List<KeyValueScanner> additionalScanners, long nonceGroup, long nonce) throws IOException {</span> | 
 | <span class="source-line-no">3270</span><span id="line-3270">    if (scan.isReversed()) {</span> | 
 | <span class="source-line-no">3271</span><span id="line-3271">      if (scan.getFilter() != null) {</span> | 
 | <span class="source-line-no">3272</span><span id="line-3272">        scan.getFilter().setReversed(true);</span> | 
 | <span class="source-line-no">3273</span><span id="line-3273">      }</span> | 
 | <span class="source-line-no">3274</span><span id="line-3274">      return new ReversedRegionScannerImpl(scan, additionalScanners, this, nonceGroup, nonce);</span> | 
 | <span class="source-line-no">3275</span><span id="line-3275">    }</span> | 
 | <span class="source-line-no">3276</span><span id="line-3276">    return new RegionScannerImpl(scan, additionalScanners, this, nonceGroup, nonce);</span> | 
 | <span class="source-line-no">3277</span><span id="line-3277">  }</span> | 
 | <span class="source-line-no">3278</span><span id="line-3278"></span> | 
 | <span class="source-line-no">3279</span><span id="line-3279">  /**</span> | 
 | <span class="source-line-no">3280</span><span id="line-3280">   * Prepare a delete for a row mutation processor</span> | 
 | <span class="source-line-no">3281</span><span id="line-3281">   * @param delete The passed delete is modified by this method. WARNING!</span> | 
 | <span class="source-line-no">3282</span><span id="line-3282">   */</span> | 
 | <span class="source-line-no">3283</span><span id="line-3283">  private void prepareDelete(Delete delete) throws IOException {</span> | 
 | <span class="source-line-no">3284</span><span id="line-3284">    // Check to see if this is a deleteRow insert</span> | 
 | <span class="source-line-no">3285</span><span id="line-3285">    if (delete.getFamilyCellMap().isEmpty()) {</span> | 
 | <span class="source-line-no">3286</span><span id="line-3286">      for (byte[] family : this.htableDescriptor.getColumnFamilyNames()) {</span> | 
 | <span class="source-line-no">3287</span><span id="line-3287">        // Don't eat the timestamp</span> | 
 | <span class="source-line-no">3288</span><span id="line-3288">        delete.addFamily(family, delete.getTimestamp());</span> | 
 | <span class="source-line-no">3289</span><span id="line-3289">      }</span> | 
 | <span class="source-line-no">3290</span><span id="line-3290">    } else {</span> | 
 | <span class="source-line-no">3291</span><span id="line-3291">      for (byte[] family : delete.getFamilyCellMap().keySet()) {</span> | 
 | <span class="source-line-no">3292</span><span id="line-3292">        if (family == null) {</span> | 
 | <span class="source-line-no">3293</span><span id="line-3293">          throw new NoSuchColumnFamilyException("Empty family is invalid");</span> | 
 | <span class="source-line-no">3294</span><span id="line-3294">        }</span> | 
 | <span class="source-line-no">3295</span><span id="line-3295">        checkFamily(family, delete.getDurability());</span> | 
 | <span class="source-line-no">3296</span><span id="line-3296">      }</span> | 
 | <span class="source-line-no">3297</span><span id="line-3297">    }</span> | 
 | <span class="source-line-no">3298</span><span id="line-3298">  }</span> | 
 | <span class="source-line-no">3299</span><span id="line-3299"></span> | 
 | <span class="source-line-no">3300</span><span id="line-3300">  @Override</span> | 
 | <span class="source-line-no">3301</span><span id="line-3301">  public void delete(Delete delete) throws IOException {</span> | 
 | <span class="source-line-no">3302</span><span id="line-3302">    TraceUtil.trace(() -> {</span> | 
 | <span class="source-line-no">3303</span><span id="line-3303">      checkReadOnly();</span> | 
 | <span class="source-line-no">3304</span><span id="line-3304">      checkResources();</span> | 
 | <span class="source-line-no">3305</span><span id="line-3305">      startRegionOperation(Operation.DELETE);</span> | 
 | <span class="source-line-no">3306</span><span id="line-3306">      try {</span> | 
 | <span class="source-line-no">3307</span><span id="line-3307">        // All edits for the given row (across all column families) must happen atomically.</span> | 
 | <span class="source-line-no">3308</span><span id="line-3308">        return mutate(delete);</span> | 
 | <span class="source-line-no">3309</span><span id="line-3309">      } finally {</span> | 
 | <span class="source-line-no">3310</span><span id="line-3310">        closeRegionOperation(Operation.DELETE);</span> | 
 | <span class="source-line-no">3311</span><span id="line-3311">      }</span> | 
 | <span class="source-line-no">3312</span><span id="line-3312">    }, () -> createRegionSpan("Region.delete"));</span> | 
 | <span class="source-line-no">3313</span><span id="line-3313">  }</span> | 
 | <span class="source-line-no">3314</span><span id="line-3314"></span> | 
 | <span class="source-line-no">3315</span><span id="line-3315">  /**</span> | 
 | <span class="source-line-no">3316</span><span id="line-3316">   * Set up correct timestamps in the KVs in Delete object.</span> | 
 | <span class="source-line-no">3317</span><span id="line-3317">   * <p/></span> | 
 | <span class="source-line-no">3318</span><span id="line-3318">   * Caller should have the row and region locks.</span> | 
 | <span class="source-line-no">3319</span><span id="line-3319">   */</span> | 
 | <span class="source-line-no">3320</span><span id="line-3320">  private void prepareDeleteTimestamps(Mutation mutation, Map<byte[], List<ExtendedCell>> familyMap,</span> | 
 | <span class="source-line-no">3321</span><span id="line-3321">    byte[] byteNow) throws IOException {</span> | 
 | <span class="source-line-no">3322</span><span id="line-3322">    for (Map.Entry<byte[], List<ExtendedCell>> e : familyMap.entrySet()) {</span> | 
 | <span class="source-line-no">3323</span><span id="line-3323"></span> | 
 | <span class="source-line-no">3324</span><span id="line-3324">      byte[] family = e.getKey();</span> | 
 | <span class="source-line-no">3325</span><span id="line-3325">      List<ExtendedCell> cells = e.getValue();</span> | 
 | <span class="source-line-no">3326</span><span id="line-3326">      assert cells instanceof RandomAccess;</span> | 
 | <span class="source-line-no">3327</span><span id="line-3327"></span> | 
 | <span class="source-line-no">3328</span><span id="line-3328">      Map<byte[], Integer> kvCount = new TreeMap<>(Bytes.BYTES_COMPARATOR);</span> | 
 | <span class="source-line-no">3329</span><span id="line-3329">      int listSize = cells.size();</span> | 
 | <span class="source-line-no">3330</span><span id="line-3330">      for (int i = 0; i < listSize; i++) {</span> | 
 | <span class="source-line-no">3331</span><span id="line-3331">        ExtendedCell cell = cells.get(i);</span> | 
 | <span class="source-line-no">3332</span><span id="line-3332">        // Check if time is LATEST, change to time of most recent addition if so</span> | 
 | <span class="source-line-no">3333</span><span id="line-3333">        // This is expensive.</span> | 
 | <span class="source-line-no">3334</span><span id="line-3334">        if (</span> | 
 | <span class="source-line-no">3335</span><span id="line-3335">          cell.getTimestamp() == HConstants.LATEST_TIMESTAMP && PrivateCellUtil.isDeleteType(cell)</span> | 
 | <span class="source-line-no">3336</span><span id="line-3336">        ) {</span> | 
 | <span class="source-line-no">3337</span><span id="line-3337">          byte[] qual = CellUtil.cloneQualifier(cell);</span> | 
 | <span class="source-line-no">3338</span><span id="line-3338"></span> | 
 | <span class="source-line-no">3339</span><span id="line-3339">          Integer count = kvCount.get(qual);</span> | 
 | <span class="source-line-no">3340</span><span id="line-3340">          if (count == null) {</span> | 
 | <span class="source-line-no">3341</span><span id="line-3341">            kvCount.put(qual, 1);</span> | 
 | <span class="source-line-no">3342</span><span id="line-3342">          } else {</span> | 
 | <span class="source-line-no">3343</span><span id="line-3343">            kvCount.put(qual, count + 1);</span> | 
 | <span class="source-line-no">3344</span><span id="line-3344">          }</span> | 
 | <span class="source-line-no">3345</span><span id="line-3345">          count = kvCount.get(qual);</span> | 
 | <span class="source-line-no">3346</span><span id="line-3346"></span> | 
 | <span class="source-line-no">3347</span><span id="line-3347">          Get get = new Get(CellUtil.cloneRow(cell));</span> | 
 | <span class="source-line-no">3348</span><span id="line-3348">          get.readVersions(count);</span> | 
 | <span class="source-line-no">3349</span><span id="line-3349">          get.addColumn(family, qual);</span> | 
 | <span class="source-line-no">3350</span><span id="line-3350">          if (coprocessorHost != null) {</span> | 
 | <span class="source-line-no">3351</span><span id="line-3351">            if (</span> | 
 | <span class="source-line-no">3352</span><span id="line-3352">              !coprocessorHost.prePrepareTimeStampForDeleteVersion(mutation, cell, byteNow, get)</span> | 
 | <span class="source-line-no">3353</span><span id="line-3353">            ) {</span> | 
 | <span class="source-line-no">3354</span><span id="line-3354">              updateDeleteLatestVersionTimestamp(cell, get, count, byteNow);</span> | 
 | <span class="source-line-no">3355</span><span id="line-3355">            }</span> | 
 | <span class="source-line-no">3356</span><span id="line-3356">          } else {</span> | 
 | <span class="source-line-no">3357</span><span id="line-3357">            updateDeleteLatestVersionTimestamp(cell, get, count, byteNow);</span> | 
 | <span class="source-line-no">3358</span><span id="line-3358">          }</span> | 
 | <span class="source-line-no">3359</span><span id="line-3359">        } else {</span> | 
 | <span class="source-line-no">3360</span><span id="line-3360">          PrivateCellUtil.updateLatestStamp(cell, byteNow);</span> | 
 | <span class="source-line-no">3361</span><span id="line-3361">        }</span> | 
 | <span class="source-line-no">3362</span><span id="line-3362">      }</span> | 
 | <span class="source-line-no">3363</span><span id="line-3363">    }</span> | 
 | <span class="source-line-no">3364</span><span id="line-3364">  }</span> | 
 | <span class="source-line-no">3365</span><span id="line-3365"></span> | 
 | <span class="source-line-no">3366</span><span id="line-3366">  private void updateDeleteLatestVersionTimestamp(Cell cell, Get get, int count, byte[] byteNow)</span> | 
 | <span class="source-line-no">3367</span><span id="line-3367">    throws IOException {</span> | 
 | <span class="source-line-no">3368</span><span id="line-3368">    try (RegionScanner scanner = getScanner(new Scan(get))) {</span> | 
 | <span class="source-line-no">3369</span><span id="line-3369">      // NOTE: Please don't use HRegion.get() instead,</span> | 
 | <span class="source-line-no">3370</span><span id="line-3370">      // because it will copy cells to heap. See HBASE-26036</span> | 
 | <span class="source-line-no">3371</span><span id="line-3371">      List<ExtendedCell> result = new ArrayList<>();</span> | 
 | <span class="source-line-no">3372</span><span id="line-3372">      scanner.next(result);</span> | 
 | <span class="source-line-no">3373</span><span id="line-3373"></span> | 
 | <span class="source-line-no">3374</span><span id="line-3374">      if (result.size() < count) {</span> | 
 | <span class="source-line-no">3375</span><span id="line-3375">        // Nothing to delete</span> | 
 | <span class="source-line-no">3376</span><span id="line-3376">        PrivateCellUtil.updateLatestStamp(cell, byteNow);</span> | 
 | <span class="source-line-no">3377</span><span id="line-3377">        return;</span> | 
 | <span class="source-line-no">3378</span><span id="line-3378">      }</span> | 
 | <span class="source-line-no">3379</span><span id="line-3379">      if (result.size() > count) {</span> | 
 | <span class="source-line-no">3380</span><span id="line-3380">        throw new RuntimeException("Unexpected size: " + result.size());</span> | 
 | <span class="source-line-no">3381</span><span id="line-3381">      }</span> | 
 | <span class="source-line-no">3382</span><span id="line-3382">      Cell getCell = result.get(count - 1);</span> | 
 | <span class="source-line-no">3383</span><span id="line-3383">      PrivateCellUtil.setTimestamp(cell, getCell.getTimestamp());</span> | 
 | <span class="source-line-no">3384</span><span id="line-3384">    }</span> | 
 | <span class="source-line-no">3385</span><span id="line-3385">  }</span> | 
 | <span class="source-line-no">3386</span><span id="line-3386"></span> | 
 | <span class="source-line-no">3387</span><span id="line-3387">  @Override</span> | 
 | <span class="source-line-no">3388</span><span id="line-3388">  public void put(Put put) throws IOException {</span> | 
 | <span class="source-line-no">3389</span><span id="line-3389">    TraceUtil.trace(() -> {</span> | 
 | <span class="source-line-no">3390</span><span id="line-3390">      checkReadOnly();</span> | 
 | <span class="source-line-no">3391</span><span id="line-3391"></span> | 
 | <span class="source-line-no">3392</span><span id="line-3392">      // Do a rough check that we have resources to accept a write. The check is</span> | 
 | <span class="source-line-no">3393</span><span id="line-3393">      // 'rough' in that between the resource check and the call to obtain a</span> | 
 | <span class="source-line-no">3394</span><span id="line-3394">      // read lock, resources may run out. For now, the thought is that this</span> | 
 | <span class="source-line-no">3395</span><span id="line-3395">      // will be extremely rare; we'll deal with it when it happens.</span> | 
 | <span class="source-line-no">3396</span><span id="line-3396">      checkResources();</span> | 
 | <span class="source-line-no">3397</span><span id="line-3397">      startRegionOperation(Operation.PUT);</span> | 
 | <span class="source-line-no">3398</span><span id="line-3398">      try {</span> | 
 | <span class="source-line-no">3399</span><span id="line-3399">        // All edits for the given row (across all column families) must happen atomically.</span> | 
 | <span class="source-line-no">3400</span><span id="line-3400">        return mutate(put);</span> | 
 | <span class="source-line-no">3401</span><span id="line-3401">      } finally {</span> | 
 | <span class="source-line-no">3402</span><span id="line-3402">        closeRegionOperation(Operation.PUT);</span> | 
 | <span class="source-line-no">3403</span><span id="line-3403">      }</span> | 
 | <span class="source-line-no">3404</span><span id="line-3404">    }, () -> createRegionSpan("Region.put"));</span> | 
 | <span class="source-line-no">3405</span><span id="line-3405">  }</span> | 
 | <span class="source-line-no">3406</span><span id="line-3406"></span> | 
 | <span class="source-line-no">3407</span><span id="line-3407">  /**</span> | 
 | <span class="source-line-no">3408</span><span id="line-3408">   * Class that tracks the progress of a batch operations, accumulating status codes and tracking</span> | 
 | <span class="source-line-no">3409</span><span id="line-3409">   * the index at which processing is proceeding. These batch operations may get split into</span> | 
 | <span class="source-line-no">3410</span><span id="line-3410">   * mini-batches for processing.</span> | 
 | <span class="source-line-no">3411</span><span id="line-3411">   */</span> | 
 | <span class="source-line-no">3412</span><span id="line-3412">  private abstract static class BatchOperation<T> {</span> | 
 | <span class="source-line-no">3413</span><span id="line-3413">    protected final T[] operations;</span> | 
 | <span class="source-line-no">3414</span><span id="line-3414">    protected final OperationStatus[] retCodeDetails;</span> | 
 | <span class="source-line-no">3415</span><span id="line-3415">    protected final WALEdit[] walEditsFromCoprocessors;</span> | 
 | <span class="source-line-no">3416</span><span id="line-3416">    // reference family cell maps directly so coprocessors can mutate them if desired</span> | 
 | <span class="source-line-no">3417</span><span id="line-3417">    protected final Map<byte[], List<ExtendedCell>>[] familyCellMaps;</span> | 
 | <span class="source-line-no">3418</span><span id="line-3418">    // For Increment/Append operations</span> | 
 | <span class="source-line-no">3419</span><span id="line-3419">    protected final Result[] results;</span> | 
 | <span class="source-line-no">3420</span><span id="line-3420"></span> | 
 | <span class="source-line-no">3421</span><span id="line-3421">    protected final HRegion region;</span> | 
 | <span class="source-line-no">3422</span><span id="line-3422">    protected int nextIndexToProcess = 0;</span> | 
 | <span class="source-line-no">3423</span><span id="line-3423">    protected final ObservedExceptionsInBatch observedExceptions;</span> | 
 | <span class="source-line-no">3424</span><span id="line-3424">    // Durability of the batch (highest durability of all operations)</span> | 
 | <span class="source-line-no">3425</span><span id="line-3425">    protected Durability durability;</span> | 
 | <span class="source-line-no">3426</span><span id="line-3426">    protected boolean atomic = false;</span> | 
 | <span class="source-line-no">3427</span><span id="line-3427"></span> | 
 | <span class="source-line-no">3428</span><span id="line-3428">    public BatchOperation(final HRegion region, T[] operations) {</span> | 
 | <span class="source-line-no">3429</span><span id="line-3429">      this.operations = operations;</span> | 
 | <span class="source-line-no">3430</span><span id="line-3430">      this.retCodeDetails = new OperationStatus[operations.length];</span> | 
 | <span class="source-line-no">3431</span><span id="line-3431">      Arrays.fill(this.retCodeDetails, OperationStatus.NOT_RUN);</span> | 
 | <span class="source-line-no">3432</span><span id="line-3432">      this.walEditsFromCoprocessors = new WALEdit[operations.length];</span> | 
 | <span class="source-line-no">3433</span><span id="line-3433">      familyCellMaps = new Map[operations.length];</span> | 
 | <span class="source-line-no">3434</span><span id="line-3434">      this.results = new Result[operations.length];</span> | 
 | <span class="source-line-no">3435</span><span id="line-3435"></span> | 
 | <span class="source-line-no">3436</span><span id="line-3436">      this.region = region;</span> | 
 | <span class="source-line-no">3437</span><span id="line-3437">      observedExceptions = new ObservedExceptionsInBatch();</span> | 
 | <span class="source-line-no">3438</span><span id="line-3438">      durability = Durability.USE_DEFAULT;</span> | 
 | <span class="source-line-no">3439</span><span id="line-3439">    }</span> | 
 | <span class="source-line-no">3440</span><span id="line-3440"></span> | 
 | <span class="source-line-no">3441</span><span id="line-3441">    /**</span> | 
 | <span class="source-line-no">3442</span><span id="line-3442">     * Visitor interface for batch operations</span> | 
 | <span class="source-line-no">3443</span><span id="line-3443">     */</span> | 
 | <span class="source-line-no">3444</span><span id="line-3444">    @FunctionalInterface</span> | 
 | <span class="source-line-no">3445</span><span id="line-3445">    interface Visitor {</span> | 
 | <span class="source-line-no">3446</span><span id="line-3446">      /**</span> | 
 | <span class="source-line-no">3447</span><span id="line-3447">       * @param index operation index</span> | 
 | <span class="source-line-no">3448</span><span id="line-3448">       * @return If true continue visiting remaining entries, break otherwise</span> | 
 | <span class="source-line-no">3449</span><span id="line-3449">       */</span> | 
 | <span class="source-line-no">3450</span><span id="line-3450">      boolean visit(int index) throws IOException;</span> | 
 | <span class="source-line-no">3451</span><span id="line-3451">    }</span> | 
 | <span class="source-line-no">3452</span><span id="line-3452"></span> | 
 | <span class="source-line-no">3453</span><span id="line-3453">    /**</span> | 
 | <span class="source-line-no">3454</span><span id="line-3454">     * Helper method for visiting pending/ all batch operations</span> | 
 | <span class="source-line-no">3455</span><span id="line-3455">     */</span> | 
 | <span class="source-line-no">3456</span><span id="line-3456">    public void visitBatchOperations(boolean pendingOnly, int lastIndexExclusive, Visitor visitor)</span> | 
 | <span class="source-line-no">3457</span><span id="line-3457">      throws IOException {</span> | 
 | <span class="source-line-no">3458</span><span id="line-3458">      assert lastIndexExclusive <= this.size();</span> | 
 | <span class="source-line-no">3459</span><span id="line-3459">      for (int i = nextIndexToProcess; i < lastIndexExclusive; i++) {</span> | 
 | <span class="source-line-no">3460</span><span id="line-3460">        if (!pendingOnly || isOperationPending(i)) {</span> | 
 | <span class="source-line-no">3461</span><span id="line-3461">          if (!visitor.visit(i)) {</span> | 
 | <span class="source-line-no">3462</span><span id="line-3462">            break;</span> | 
 | <span class="source-line-no">3463</span><span id="line-3463">          }</span> | 
 | <span class="source-line-no">3464</span><span id="line-3464">        }</span> | 
 | <span class="source-line-no">3465</span><span id="line-3465">      }</span> | 
 | <span class="source-line-no">3466</span><span id="line-3466">    }</span> | 
 | <span class="source-line-no">3467</span><span id="line-3467"></span> | 
 | <span class="source-line-no">3468</span><span id="line-3468">    public abstract Mutation getMutation(int index);</span> | 
 | <span class="source-line-no">3469</span><span id="line-3469"></span> | 
 | <span class="source-line-no">3470</span><span id="line-3470">    public abstract long getNonceGroup(int index);</span> | 
 | <span class="source-line-no">3471</span><span id="line-3471"></span> | 
 | <span class="source-line-no">3472</span><span id="line-3472">    public abstract long getNonce(int index);</span> | 
 | <span class="source-line-no">3473</span><span id="line-3473"></span> | 
 | <span class="source-line-no">3474</span><span id="line-3474">    /**</span> | 
 | <span class="source-line-no">3475</span><span id="line-3475">     * This method is potentially expensive and useful mostly for non-replay CP path.</span> | 
 | <span class="source-line-no">3476</span><span id="line-3476">     */</span> | 
 | <span class="source-line-no">3477</span><span id="line-3477">    public abstract Mutation[] getMutationsForCoprocs();</span> | 
 | <span class="source-line-no">3478</span><span id="line-3478"></span> | 
 | <span class="source-line-no">3479</span><span id="line-3479">    public abstract boolean isInReplay();</span> | 
 | <span class="source-line-no">3480</span><span id="line-3480"></span> | 
 | <span class="source-line-no">3481</span><span id="line-3481">    public abstract long getOrigLogSeqNum();</span> | 
 | <span class="source-line-no">3482</span><span id="line-3482"></span> | 
 | <span class="source-line-no">3483</span><span id="line-3483">    public abstract void startRegionOperation() throws IOException;</span> | 
 | <span class="source-line-no">3484</span><span id="line-3484"></span> | 
 | <span class="source-line-no">3485</span><span id="line-3485">    public abstract void closeRegionOperation() throws IOException;</span> | 
 | <span class="source-line-no">3486</span><span id="line-3486"></span> | 
 | <span class="source-line-no">3487</span><span id="line-3487">    /**</span> | 
 | <span class="source-line-no">3488</span><span id="line-3488">     * Validates each mutation and prepares a batch for write. If necessary (non-replay case), runs</span> | 
 | <span class="source-line-no">3489</span><span id="line-3489">     * CP prePut()/preDelete()/preIncrement()/preAppend() hooks for all mutations in a batch. This</span> | 
 | <span class="source-line-no">3490</span><span id="line-3490">     * is intended to operate on entire batch and will be called from outside of class to check and</span> | 
 | <span class="source-line-no">3491</span><span id="line-3491">     * prepare batch. This can be implemented by calling helper method</span> | 
 | <span class="source-line-no">3492</span><span id="line-3492">     * {@link #checkAndPrepareMutation(int, long)} in a 'for' loop over mutations.</span> | 
 | <span class="source-line-no">3493</span><span id="line-3493">     */</span> | 
 | <span class="source-line-no">3494</span><span id="line-3494">    public abstract void checkAndPrepare() throws IOException;</span> | 
 | <span class="source-line-no">3495</span><span id="line-3495"></span> | 
 | <span class="source-line-no">3496</span><span id="line-3496">    /**</span> | 
 | <span class="source-line-no">3497</span><span id="line-3497">     * Implement any Put request specific check and prepare logic here. Please refer to</span> | 
 | <span class="source-line-no">3498</span><span id="line-3498">     * {@link #checkAndPrepareMutation(Mutation, long)} for how its used.</span> | 
 | <span class="source-line-no">3499</span><span id="line-3499">     */</span> | 
 | <span class="source-line-no">3500</span><span id="line-3500">    protected abstract void checkAndPreparePut(final Put p) throws IOException;</span> | 
 | <span class="source-line-no">3501</span><span id="line-3501"></span> | 
 | <span class="source-line-no">3502</span><span id="line-3502">    /**</span> | 
 | <span class="source-line-no">3503</span><span id="line-3503">     * If necessary, calls preBatchMutate() CP hook for a mini-batch and updates metrics, cell</span> | 
 | <span class="source-line-no">3504</span><span id="line-3504">     * count, tags and timestamp for all cells of all operations in a mini-batch.</span> | 
 | <span class="source-line-no">3505</span><span id="line-3505">     */</span> | 
 | <span class="source-line-no">3506</span><span id="line-3506">    public abstract void prepareMiniBatchOperations(</span> | 
 | <span class="source-line-no">3507</span><span id="line-3507">      MiniBatchOperationInProgress<Mutation> miniBatchOp, long timestamp,</span> | 
 | <span class="source-line-no">3508</span><span id="line-3508">      final List<RowLock> acquiredRowLocks) throws IOException;</span> | 
 | <span class="source-line-no">3509</span><span id="line-3509"></span> | 
 | <span class="source-line-no">3510</span><span id="line-3510">    /**</span> | 
 | <span class="source-line-no">3511</span><span id="line-3511">     * Write mini-batch operations to MemStore</span> | 
 | <span class="source-line-no">3512</span><span id="line-3512">     */</span> | 
 | <span class="source-line-no">3513</span><span id="line-3513">    public abstract WriteEntry writeMiniBatchOperationsToMemStore(</span> | 
 | <span class="source-line-no">3514</span><span id="line-3514">      final MiniBatchOperationInProgress<Mutation> miniBatchOp, final WriteEntry writeEntry,</span> | 
 | <span class="source-line-no">3515</span><span id="line-3515">      long now) throws IOException;</span> | 
 | <span class="source-line-no">3516</span><span id="line-3516"></span> | 
 | <span class="source-line-no">3517</span><span id="line-3517">    protected void writeMiniBatchOperationsToMemStore(</span> | 
 | <span class="source-line-no">3518</span><span id="line-3518">      final MiniBatchOperationInProgress<Mutation> miniBatchOp, final long writeNumber)</span> | 
 | <span class="source-line-no">3519</span><span id="line-3519">      throws IOException {</span> | 
 | <span class="source-line-no">3520</span><span id="line-3520">      MemStoreSizing memStoreAccounting = new NonThreadSafeMemStoreSizing();</span> | 
 | <span class="source-line-no">3521</span><span id="line-3521">      visitBatchOperations(true, miniBatchOp.getLastIndexExclusive(), (int index) -> {</span> | 
 | <span class="source-line-no">3522</span><span id="line-3522">        // We need to update the sequence id for following reasons.</span> | 
 | <span class="source-line-no">3523</span><span id="line-3523">        // 1) If the op is in replay mode, FSWALEntry#stampRegionSequenceId won't stamp sequence id.</span> | 
 | <span class="source-line-no">3524</span><span id="line-3524">        // 2) If no WAL, FSWALEntry won't be used</span> | 
 | <span class="source-line-no">3525</span><span id="line-3525">        // we use durability of the original mutation for the mutation passed by CP.</span> | 
 | <span class="source-line-no">3526</span><span id="line-3526">        if (isInReplay() || getMutation(index).getDurability() == Durability.SKIP_WAL) {</span> | 
 | <span class="source-line-no">3527</span><span id="line-3527">          region.updateSequenceId(familyCellMaps[index].values(), writeNumber);</span> | 
 | <span class="source-line-no">3528</span><span id="line-3528">        }</span> | 
 | <span class="source-line-no">3529</span><span id="line-3529">        applyFamilyMapToMemStore(familyCellMaps[index], memStoreAccounting);</span> | 
 | <span class="source-line-no">3530</span><span id="line-3530">        return true;</span> | 
 | <span class="source-line-no">3531</span><span id="line-3531">      });</span> | 
 | <span class="source-line-no">3532</span><span id="line-3532">      // update memStore size</span> | 
 | <span class="source-line-no">3533</span><span id="line-3533">      region.incMemStoreSize(memStoreAccounting.getDataSize(), memStoreAccounting.getHeapSize(),</span> | 
 | <span class="source-line-no">3534</span><span id="line-3534">        memStoreAccounting.getOffHeapSize(), memStoreAccounting.getCellsCount());</span> | 
 | <span class="source-line-no">3535</span><span id="line-3535">    }</span> | 
 | <span class="source-line-no">3536</span><span id="line-3536"></span> | 
 | <span class="source-line-no">3537</span><span id="line-3537">    public boolean isDone() {</span> | 
 | <span class="source-line-no">3538</span><span id="line-3538">      return nextIndexToProcess == operations.length;</span> | 
 | <span class="source-line-no">3539</span><span id="line-3539">    }</span> | 
 | <span class="source-line-no">3540</span><span id="line-3540"></span> | 
 | <span class="source-line-no">3541</span><span id="line-3541">    public int size() {</span> | 
 | <span class="source-line-no">3542</span><span id="line-3542">      return operations.length;</span> | 
 | <span class="source-line-no">3543</span><span id="line-3543">    }</span> | 
 | <span class="source-line-no">3544</span><span id="line-3544"></span> | 
 | <span class="source-line-no">3545</span><span id="line-3545">    public boolean isOperationPending(int index) {</span> | 
 | <span class="source-line-no">3546</span><span id="line-3546">      return retCodeDetails[index].getOperationStatusCode() == OperationStatusCode.NOT_RUN;</span> | 
 | <span class="source-line-no">3547</span><span id="line-3547">    }</span> | 
 | <span class="source-line-no">3548</span><span id="line-3548"></span> | 
 | <span class="source-line-no">3549</span><span id="line-3549">    public List<UUID> getClusterIds() {</span> | 
 | <span class="source-line-no">3550</span><span id="line-3550">      assert size() != 0;</span> | 
 | <span class="source-line-no">3551</span><span id="line-3551">      return getMutation(0).getClusterIds();</span> | 
 | <span class="source-line-no">3552</span><span id="line-3552">    }</span> | 
 | <span class="source-line-no">3553</span><span id="line-3553"></span> | 
 | <span class="source-line-no">3554</span><span id="line-3554">    boolean isAtomic() {</span> | 
 | <span class="source-line-no">3555</span><span id="line-3555">      return atomic;</span> | 
 | <span class="source-line-no">3556</span><span id="line-3556">    }</span> | 
 | <span class="source-line-no">3557</span><span id="line-3557"></span> | 
 | <span class="source-line-no">3558</span><span id="line-3558">    /**</span> | 
 | <span class="source-line-no">3559</span><span id="line-3559">     * Helper method that checks and prepares only one mutation. This can be used to implement</span> | 
 | <span class="source-line-no">3560</span><span id="line-3560">     * {@link #checkAndPrepare()} for entire Batch. NOTE: As CP</span> | 
 | <span class="source-line-no">3561</span><span id="line-3561">     * prePut()/preDelete()/preIncrement()/preAppend() hooks may modify mutations, this method</span> | 
 | <span class="source-line-no">3562</span><span id="line-3562">     * should be called after prePut()/preDelete()/preIncrement()/preAppend() CP hooks are run for</span> | 
 | <span class="source-line-no">3563</span><span id="line-3563">     * the mutation</span> | 
 | <span class="source-line-no">3564</span><span id="line-3564">     */</span> | 
 | <span class="source-line-no">3565</span><span id="line-3565">    protected void checkAndPrepareMutation(Mutation mutation, final long timestamp)</span> | 
 | <span class="source-line-no">3566</span><span id="line-3566">      throws IOException {</span> | 
 | <span class="source-line-no">3567</span><span id="line-3567">      region.checkRow(mutation.getRow(), "batchMutate");</span> | 
 | <span class="source-line-no">3568</span><span id="line-3568">      if (mutation instanceof Put) {</span> | 
 | <span class="source-line-no">3569</span><span id="line-3569">        // Check the families in the put. If bad, skip this one.</span> | 
 | <span class="source-line-no">3570</span><span id="line-3570">        checkAndPreparePut((Put) mutation);</span> | 
 | <span class="source-line-no">3571</span><span id="line-3571">        region.checkTimestamps(mutation.getFamilyCellMap(), timestamp);</span> | 
 | <span class="source-line-no">3572</span><span id="line-3572">      } else if (mutation instanceof Delete) {</span> | 
 | <span class="source-line-no">3573</span><span id="line-3573">        region.prepareDelete((Delete) mutation);</span> | 
 | <span class="source-line-no">3574</span><span id="line-3574">      } else if (mutation instanceof Increment || mutation instanceof Append) {</span> | 
 | <span class="source-line-no">3575</span><span id="line-3575">        region.checkFamilies(mutation.getFamilyCellMap().keySet(), mutation.getDurability());</span> | 
 | <span class="source-line-no">3576</span><span id="line-3576">      }</span> | 
 | <span class="source-line-no">3577</span><span id="line-3577">    }</span> | 
 | <span class="source-line-no">3578</span><span id="line-3578"></span> | 
 | <span class="source-line-no">3579</span><span id="line-3579">    protected void checkAndPrepareMutation(int index, long timestamp) throws IOException {</span> | 
 | <span class="source-line-no">3580</span><span id="line-3580">      Mutation mutation = getMutation(index);</span> | 
 | <span class="source-line-no">3581</span><span id="line-3581">      try {</span> | 
 | <span class="source-line-no">3582</span><span id="line-3582">        this.checkAndPrepareMutation(mutation, timestamp);</span> | 
 | <span class="source-line-no">3583</span><span id="line-3583"></span> | 
 | <span class="source-line-no">3584</span><span id="line-3584">        if (mutation instanceof Put || mutation instanceof Delete) {</span> | 
 | <span class="source-line-no">3585</span><span id="line-3585">          // store the family map reference to allow for mutations</span> | 
 | <span class="source-line-no">3586</span><span id="line-3586">          // we know that in mutation, only ExtendedCells are allow so here we do a fake cast, to</span> | 
 | <span class="source-line-no">3587</span><span id="line-3587">          // simplify later logic</span> | 
 | <span class="source-line-no">3588</span><span id="line-3588">          familyCellMaps[index] = ClientInternalHelper.getExtendedFamilyCellMap(mutation);</span> | 
 | <span class="source-line-no">3589</span><span id="line-3589">        }</span> | 
 | <span class="source-line-no">3590</span><span id="line-3590"></span> | 
 | <span class="source-line-no">3591</span><span id="line-3591">        // store durability for the batch (highest durability of all operations in the batch)</span> | 
 | <span class="source-line-no">3592</span><span id="line-3592">        Durability tmpDur = region.getEffectiveDurability(mutation.getDurability());</span> | 
 | <span class="source-line-no">3593</span><span id="line-3593">        if (tmpDur.ordinal() > durability.ordinal()) {</span> | 
 | <span class="source-line-no">3594</span><span id="line-3594">          durability = tmpDur;</span> | 
 | <span class="source-line-no">3595</span><span id="line-3595">        }</span> | 
 | <span class="source-line-no">3596</span><span id="line-3596">      } catch (NoSuchColumnFamilyException nscfe) {</span> | 
 | <span class="source-line-no">3597</span><span id="line-3597">        final String msg = "No such column family in batch mutation in region " + this;</span> | 
 | <span class="source-line-no">3598</span><span id="line-3598">        if (observedExceptions.hasSeenNoSuchFamily()) {</span> | 
 | <span class="source-line-no">3599</span><span id="line-3599">          LOG.warn(msg + nscfe.getMessage());</span> | 
 | <span class="source-line-no">3600</span><span id="line-3600">        } else {</span> | 
 | <span class="source-line-no">3601</span><span id="line-3601">          LOG.warn(msg, nscfe);</span> | 
 | <span class="source-line-no">3602</span><span id="line-3602">          observedExceptions.sawNoSuchFamily();</span> | 
 | <span class="source-line-no">3603</span><span id="line-3603">        }</span> | 
 | <span class="source-line-no">3604</span><span id="line-3604">        retCodeDetails[index] =</span> | 
 | <span class="source-line-no">3605</span><span id="line-3605">          new OperationStatus(OperationStatusCode.BAD_FAMILY, nscfe.getMessage());</span> | 
 | <span class="source-line-no">3606</span><span id="line-3606">        if (isAtomic()) { // fail, atomic means all or none</span> | 
 | <span class="source-line-no">3607</span><span id="line-3607">          throw nscfe;</span> | 
 | <span class="source-line-no">3608</span><span id="line-3608">        }</span> | 
 | <span class="source-line-no">3609</span><span id="line-3609">      } catch (FailedSanityCheckException fsce) {</span> | 
 | <span class="source-line-no">3610</span><span id="line-3610">        final String msg = "Batch Mutation did not pass sanity check in region " + this;</span> | 
 | <span class="source-line-no">3611</span><span id="line-3611">        if (observedExceptions.hasSeenFailedSanityCheck()) {</span> | 
 | <span class="source-line-no">3612</span><span id="line-3612">          LOG.warn(msg + fsce.getMessage());</span> | 
 | <span class="source-line-no">3613</span><span id="line-3613">        } else {</span> | 
 | <span class="source-line-no">3614</span><span id="line-3614">          LOG.warn(msg, fsce);</span> | 
 | <span class="source-line-no">3615</span><span id="line-3615">          observedExceptions.sawFailedSanityCheck();</span> | 
 | <span class="source-line-no">3616</span><span id="line-3616">        }</span> | 
 | <span class="source-line-no">3617</span><span id="line-3617">        retCodeDetails[index] =</span> | 
 | <span class="source-line-no">3618</span><span id="line-3618">          new OperationStatus(OperationStatusCode.SANITY_CHECK_FAILURE, fsce.getMessage());</span> | 
 | <span class="source-line-no">3619</span><span id="line-3619">        if (isAtomic()) {</span> | 
 | <span class="source-line-no">3620</span><span id="line-3620">          throw fsce;</span> | 
 | <span class="source-line-no">3621</span><span id="line-3621">        }</span> | 
 | <span class="source-line-no">3622</span><span id="line-3622">      } catch (WrongRegionException we) {</span> | 
 | <span class="source-line-no">3623</span><span id="line-3623">        final String msg = "Batch mutation had a row that does not belong to this region " + this;</span> | 
 | <span class="source-line-no">3624</span><span id="line-3624">        if (observedExceptions.hasSeenWrongRegion()) {</span> | 
 | <span class="source-line-no">3625</span><span id="line-3625">          LOG.warn(msg + we.getMessage());</span> | 
 | <span class="source-line-no">3626</span><span id="line-3626">        } else {</span> | 
 | <span class="source-line-no">3627</span><span id="line-3627">          LOG.warn(msg, we);</span> | 
 | <span class="source-line-no">3628</span><span id="line-3628">          observedExceptions.sawWrongRegion();</span> | 
 | <span class="source-line-no">3629</span><span id="line-3629">        }</span> | 
 | <span class="source-line-no">3630</span><span id="line-3630">        retCodeDetails[index] =</span> | 
 | <span class="source-line-no">3631</span><span id="line-3631">          new OperationStatus(OperationStatusCode.SANITY_CHECK_FAILURE, we.getMessage());</span> | 
 | <span class="source-line-no">3632</span><span id="line-3632">        if (isAtomic()) {</span> | 
 | <span class="source-line-no">3633</span><span id="line-3633">          throw we;</span> | 
 | <span class="source-line-no">3634</span><span id="line-3634">        }</span> | 
 | <span class="source-line-no">3635</span><span id="line-3635">      }</span> | 
 | <span class="source-line-no">3636</span><span id="line-3636">    }</span> | 
 | <span class="source-line-no">3637</span><span id="line-3637"></span> | 
 | <span class="source-line-no">3638</span><span id="line-3638">    /**</span> | 
 | <span class="source-line-no">3639</span><span id="line-3639">     * Creates Mini-batch of all operations [nextIndexToProcess, lastIndexExclusive) for which a row</span> | 
 | <span class="source-line-no">3640</span><span id="line-3640">     * lock can be acquired. All mutations with locked rows are considered to be In-progress</span> | 
 | <span class="source-line-no">3641</span><span id="line-3641">     * operations and hence the name {@link MiniBatchOperationInProgress}. Mini batch is window over</span> | 
 | <span class="source-line-no">3642</span><span id="line-3642">     * {@link BatchOperation} and contains contiguous pending operations.</span> | 
 | <span class="source-line-no">3643</span><span id="line-3643">     * @param acquiredRowLocks keeps track of rowLocks acquired.</span> | 
 | <span class="source-line-no">3644</span><span id="line-3644">     */</span> | 
 | <span class="source-line-no">3645</span><span id="line-3645">    public MiniBatchOperationInProgress<Mutation></span> | 
 | <span class="source-line-no">3646</span><span id="line-3646">      lockRowsAndBuildMiniBatch(List<RowLock> acquiredRowLocks) throws IOException {</span> | 
 | <span class="source-line-no">3647</span><span id="line-3647">      int readyToWriteCount = 0;</span> | 
 | <span class="source-line-no">3648</span><span id="line-3648">      int lastIndexExclusive = 0;</span> | 
 | <span class="source-line-no">3649</span><span id="line-3649">      RowLock prevRowLock = null;</span> | 
 | <span class="source-line-no">3650</span><span id="line-3650">      for (; lastIndexExclusive < size(); lastIndexExclusive++) {</span> | 
 | <span class="source-line-no">3651</span><span id="line-3651">        // It reaches the miniBatchSize, stop here and process the miniBatch</span> | 
 | <span class="source-line-no">3652</span><span id="line-3652">        // This only applies to non-atomic batch operations.</span> | 
 | <span class="source-line-no">3653</span><span id="line-3653">        if (!isAtomic() && (readyToWriteCount == region.miniBatchSize)) {</span> | 
 | <span class="source-line-no">3654</span><span id="line-3654">          break;</span> | 
 | <span class="source-line-no">3655</span><span id="line-3655">        }</span> | 
 | <span class="source-line-no">3656</span><span id="line-3656"></span> | 
 | <span class="source-line-no">3657</span><span id="line-3657">        if (!isOperationPending(lastIndexExclusive)) {</span> | 
 | <span class="source-line-no">3658</span><span id="line-3658">          continue;</span> | 
 | <span class="source-line-no">3659</span><span id="line-3659">        }</span> | 
 | <span class="source-line-no">3660</span><span id="line-3660"></span> | 
 | <span class="source-line-no">3661</span><span id="line-3661">        // HBASE-19389 Limit concurrency of put with dense (hundreds) columns to avoid exhausting</span> | 
 | <span class="source-line-no">3662</span><span id="line-3662">        // RS handlers, covering both MutationBatchOperation and ReplayBatchOperation</span> | 
 | <span class="source-line-no">3663</span><span id="line-3663">        // The BAD_FAMILY/SANITY_CHECK_FAILURE cases are handled in checkAndPrepare phase and won't</span> | 
 | <span class="source-line-no">3664</span><span id="line-3664">        // pass the isOperationPending check</span> | 
 | <span class="source-line-no">3665</span><span id="line-3665">        Map<byte[], List<Cell>> curFamilyCellMap =</span> | 
 | <span class="source-line-no">3666</span><span id="line-3666">          getMutation(lastIndexExclusive).getFamilyCellMap();</span> | 
 | <span class="source-line-no">3667</span><span id="line-3667">        try {</span> | 
 | <span class="source-line-no">3668</span><span id="line-3668">          // start the protector before acquiring row lock considering performance, and will finish</span> | 
 | <span class="source-line-no">3669</span><span id="line-3669">          // it when encountering exception</span> | 
 | <span class="source-line-no">3670</span><span id="line-3670">          region.storeHotnessProtector.start(curFamilyCellMap);</span> | 
 | <span class="source-line-no">3671</span><span id="line-3671">        } catch (RegionTooBusyException rtbe) {</span> | 
 | <span class="source-line-no">3672</span><span id="line-3672">          region.storeHotnessProtector.finish(curFamilyCellMap);</span> | 
 | <span class="source-line-no">3673</span><span id="line-3673">          if (isAtomic()) {</span> | 
 | <span class="source-line-no">3674</span><span id="line-3674">            throw rtbe;</span> | 
 | <span class="source-line-no">3675</span><span id="line-3675">          }</span> | 
 | <span class="source-line-no">3676</span><span id="line-3676">          retCodeDetails[lastIndexExclusive] =</span> | 
 | <span class="source-line-no">3677</span><span id="line-3677">            new OperationStatus(OperationStatusCode.STORE_TOO_BUSY, rtbe.getMessage());</span> | 
 | <span class="source-line-no">3678</span><span id="line-3678">          continue;</span> | 
 | <span class="source-line-no">3679</span><span id="line-3679">        }</span> | 
 | <span class="source-line-no">3680</span><span id="line-3680"></span> | 
 | <span class="source-line-no">3681</span><span id="line-3681">        Mutation mutation = getMutation(lastIndexExclusive);</span> | 
 | <span class="source-line-no">3682</span><span id="line-3682">        // If we haven't got any rows in our batch, we should block to get the next one.</span> | 
 | <span class="source-line-no">3683</span><span id="line-3683">        RowLock rowLock = null;</span> | 
 | <span class="source-line-no">3684</span><span id="line-3684">        boolean throwException = false;</span> | 
 | <span class="source-line-no">3685</span><span id="line-3685">        try {</span> | 
 | <span class="source-line-no">3686</span><span id="line-3686">          // if atomic then get exclusive lock, else shared lock</span> | 
 | <span class="source-line-no">3687</span><span id="line-3687">          rowLock = region.getRowLock(mutation.getRow(), !isAtomic(), prevRowLock);</span> | 
 | <span class="source-line-no">3688</span><span id="line-3688">        } catch (TimeoutIOException | InterruptedIOException e) {</span> | 
 | <span class="source-line-no">3689</span><span id="line-3689">          // NOTE: We will retry when other exceptions, but we should stop if we receive</span> | 
 | <span class="source-line-no">3690</span><span id="line-3690">          // TimeoutIOException or InterruptedIOException as operation has timed out or</span> | 
 | <span class="source-line-no">3691</span><span id="line-3691">          // interrupted respectively.</span> | 
 | <span class="source-line-no">3692</span><span id="line-3692">          throwException = true;</span> | 
 | <span class="source-line-no">3693</span><span id="line-3693">          throw e;</span> | 
 | <span class="source-line-no">3694</span><span id="line-3694">        } catch (IOException ioe) {</span> | 
 | <span class="source-line-no">3695</span><span id="line-3695">          LOG.warn("Failed getting lock, row={}, in region {}",</span> | 
 | <span class="source-line-no">3696</span><span id="line-3696">            Bytes.toStringBinary(mutation.getRow()), this, ioe);</span> | 
 | <span class="source-line-no">3697</span><span id="line-3697">          if (isAtomic()) { // fail, atomic means all or none</span> | 
 | <span class="source-line-no">3698</span><span id="line-3698">            throwException = true;</span> | 
 | <span class="source-line-no">3699</span><span id="line-3699">            throw ioe;</span> | 
 | <span class="source-line-no">3700</span><span id="line-3700">          }</span> | 
 | <span class="source-line-no">3701</span><span id="line-3701">        } catch (Throwable throwable) {</span> | 
 | <span class="source-line-no">3702</span><span id="line-3702">          throwException = true;</span> | 
 | <span class="source-line-no">3703</span><span id="line-3703">          throw throwable;</span> | 
 | <span class="source-line-no">3704</span><span id="line-3704">        } finally {</span> | 
 | <span class="source-line-no">3705</span><span id="line-3705">          if (throwException) {</span> | 
 | <span class="source-line-no">3706</span><span id="line-3706">            region.storeHotnessProtector.finish(curFamilyCellMap);</span> | 
 | <span class="source-line-no">3707</span><span id="line-3707">          }</span> | 
 | <span class="source-line-no">3708</span><span id="line-3708">        }</span> | 
 | <span class="source-line-no">3709</span><span id="line-3709">        if (rowLock == null) {</span> | 
 | <span class="source-line-no">3710</span><span id="line-3710">          // We failed to grab another lock</span> | 
 | <span class="source-line-no">3711</span><span id="line-3711">          if (isAtomic()) {</span> | 
 | <span class="source-line-no">3712</span><span id="line-3712">            region.storeHotnessProtector.finish(curFamilyCellMap);</span> | 
 | <span class="source-line-no">3713</span><span id="line-3713">            throw new IOException("Can't apply all operations atomically!");</span> | 
 | <span class="source-line-no">3714</span><span id="line-3714">          }</span> | 
 | <span class="source-line-no">3715</span><span id="line-3715">          break; // Stop acquiring more rows for this batch</span> | 
 | <span class="source-line-no">3716</span><span id="line-3716">        } else {</span> | 
 | <span class="source-line-no">3717</span><span id="line-3717">          if (rowLock != prevRowLock) {</span> | 
 | <span class="source-line-no">3718</span><span id="line-3718">            // It is a different row now, add this to the acquiredRowLocks and</span> | 
 | <span class="source-line-no">3719</span><span id="line-3719">            // set prevRowLock to the new returned rowLock</span> | 
 | <span class="source-line-no">3720</span><span id="line-3720">            acquiredRowLocks.add(rowLock);</span> | 
 | <span class="source-line-no">3721</span><span id="line-3721">            prevRowLock = rowLock;</span> | 
 | <span class="source-line-no">3722</span><span id="line-3722">          }</span> | 
 | <span class="source-line-no">3723</span><span id="line-3723">        }</span> | 
 | <span class="source-line-no">3724</span><span id="line-3724"></span> | 
 | <span class="source-line-no">3725</span><span id="line-3725">        readyToWriteCount++;</span> | 
 | <span class="source-line-no">3726</span><span id="line-3726">      }</span> | 
 | <span class="source-line-no">3727</span><span id="line-3727">      return createMiniBatch(lastIndexExclusive, readyToWriteCount);</span> | 
 | <span class="source-line-no">3728</span><span id="line-3728">    }</span> | 
 | <span class="source-line-no">3729</span><span id="line-3729"></span> | 
 | <span class="source-line-no">3730</span><span id="line-3730">    protected MiniBatchOperationInProgress<Mutation> createMiniBatch(final int lastIndexExclusive,</span> | 
 | <span class="source-line-no">3731</span><span id="line-3731">      final int readyToWriteCount) {</span> | 
 | <span class="source-line-no">3732</span><span id="line-3732">      return new MiniBatchOperationInProgress<>(getMutationsForCoprocs(), retCodeDetails,</span> | 
 | <span class="source-line-no">3733</span><span id="line-3733">        walEditsFromCoprocessors, nextIndexToProcess, lastIndexExclusive, readyToWriteCount);</span> | 
 | <span class="source-line-no">3734</span><span id="line-3734">    }</span> | 
 | <span class="source-line-no">3735</span><span id="line-3735"></span> | 
 | <span class="source-line-no">3736</span><span id="line-3736">    protected WALEdit createWALEdit(final MiniBatchOperationInProgress<Mutation> miniBatchOp) {</span> | 
 | <span class="source-line-no">3737</span><span id="line-3737">      return new WALEdit(miniBatchOp.getCellCount(), isInReplay());</span> | 
 | <span class="source-line-no">3738</span><span id="line-3738">    }</span> | 
 | <span class="source-line-no">3739</span><span id="line-3739"></span> | 
 | <span class="source-line-no">3740</span><span id="line-3740">    /**</span> | 
 | <span class="source-line-no">3741</span><span id="line-3741">     * Builds separate WALEdit per nonce by applying input mutations. If WALEdits from CP are</span> | 
 | <span class="source-line-no">3742</span><span id="line-3742">     * present, they are merged to result WALEdit.</span> | 
 | <span class="source-line-no">3743</span><span id="line-3743">     */</span> | 
 | <span class="source-line-no">3744</span><span id="line-3744">    public List<Pair<NonceKey, WALEdit>></span> | 
 | <span class="source-line-no">3745</span><span id="line-3745">      buildWALEdits(final MiniBatchOperationInProgress<Mutation> miniBatchOp) throws IOException {</span> | 
 | <span class="source-line-no">3746</span><span id="line-3746">      List<Pair<NonceKey, WALEdit>> walEdits = new ArrayList<>();</span> | 
 | <span class="source-line-no">3747</span><span id="line-3747"></span> | 
 | <span class="source-line-no">3748</span><span id="line-3748">      visitBatchOperations(true, nextIndexToProcess + miniBatchOp.size(), new Visitor() {</span> | 
 | <span class="source-line-no">3749</span><span id="line-3749">        private Pair<NonceKey, WALEdit> curWALEditForNonce;</span> | 
 | <span class="source-line-no">3750</span><span id="line-3750"></span> | 
 | <span class="source-line-no">3751</span><span id="line-3751">        @Override</span> | 
 | <span class="source-line-no">3752</span><span id="line-3752">        public boolean visit(int index) throws IOException {</span> | 
 | <span class="source-line-no">3753</span><span id="line-3753">          Mutation m = getMutation(index);</span> | 
 | <span class="source-line-no">3754</span><span id="line-3754">          // we use durability of the original mutation for the mutation passed by CP.</span> | 
 | <span class="source-line-no">3755</span><span id="line-3755">          if (region.getEffectiveDurability(m.getDurability()) == Durability.SKIP_WAL) {</span> | 
 | <span class="source-line-no">3756</span><span id="line-3756">            region.recordMutationWithoutWal(m.getFamilyCellMap());</span> | 
 | <span class="source-line-no">3757</span><span id="line-3757">            /**</span> | 
 | <span class="source-line-no">3758</span><span id="line-3758">             * Here is for HBASE-26993,in order to make the new framework for region replication</span> | 
 | <span class="source-line-no">3759</span><span id="line-3759">             * could work for SKIP_WAL, we save the {@link Mutation} which</span> | 
 | <span class="source-line-no">3760</span><span id="line-3760">             * {@link Mutation#getDurability} is {@link Durability#SKIP_WAL} in miniBatchOp.</span> | 
 | <span class="source-line-no">3761</span><span id="line-3761">             */</span> | 
 | <span class="source-line-no">3762</span><span id="line-3762">            cacheSkipWALMutationForRegionReplication(miniBatchOp, walEdits, familyCellMaps[index]);</span> | 
 | <span class="source-line-no">3763</span><span id="line-3763">            return true;</span> | 
 | <span class="source-line-no">3764</span><span id="line-3764">          }</span> | 
 | <span class="source-line-no">3765</span><span id="line-3765"></span> | 
 | <span class="source-line-no">3766</span><span id="line-3766">          // the batch may contain multiple nonce keys (replay case). If so, write WALEdit for each.</span> | 
 | <span class="source-line-no">3767</span><span id="line-3767">          // Given how nonce keys are originally written, these should be contiguous.</span> | 
 | <span class="source-line-no">3768</span><span id="line-3768">          // They don't have to be, it will still work, just write more WALEdits than needed.</span> | 
 | <span class="source-line-no">3769</span><span id="line-3769">          long nonceGroup = getNonceGroup(index);</span> | 
 | <span class="source-line-no">3770</span><span id="line-3770">          long nonce = getNonce(index);</span> | 
 | <span class="source-line-no">3771</span><span id="line-3771">          if (</span> | 
 | <span class="source-line-no">3772</span><span id="line-3772">            curWALEditForNonce == null</span> | 
 | <span class="source-line-no">3773</span><span id="line-3773">              || curWALEditForNonce.getFirst().getNonceGroup() != nonceGroup</span> | 
 | <span class="source-line-no">3774</span><span id="line-3774">              || curWALEditForNonce.getFirst().getNonce() != nonce</span> | 
 | <span class="source-line-no">3775</span><span id="line-3775">          ) {</span> | 
 | <span class="source-line-no">3776</span><span id="line-3776">            curWALEditForNonce =</span> | 
 | <span class="source-line-no">3777</span><span id="line-3777">              new Pair<>(new NonceKey(nonceGroup, nonce), createWALEdit(miniBatchOp));</span> | 
 | <span class="source-line-no">3778</span><span id="line-3778">            walEdits.add(curWALEditForNonce);</span> | 
 | <span class="source-line-no">3779</span><span id="line-3779">          }</span> | 
 | <span class="source-line-no">3780</span><span id="line-3780">          WALEdit walEdit = curWALEditForNonce.getSecond();</span> | 
 | <span class="source-line-no">3781</span><span id="line-3781"></span> | 
 | <span class="source-line-no">3782</span><span id="line-3782">          // Add WAL edits from CPs.</span> | 
 | <span class="source-line-no">3783</span><span id="line-3783">          WALEdit fromCP = walEditsFromCoprocessors[index];</span> | 
 | <span class="source-line-no">3784</span><span id="line-3784">          List<ExtendedCell> cellsFromCP = fromCP == null</span> | 
 | <span class="source-line-no">3785</span><span id="line-3785">            ? Collections.emptyList()</span> | 
 | <span class="source-line-no">3786</span><span id="line-3786">            : WALEditInternalHelper.getExtendedCells(fromCP);</span> | 
 | <span class="source-line-no">3787</span><span id="line-3787">          addNonSkipWALMutationsToWALEdit(miniBatchOp, walEdit, cellsFromCP, familyCellMaps[index]);</span> | 
 | <span class="source-line-no">3788</span><span id="line-3788">          return true;</span> | 
 | <span class="source-line-no">3789</span><span id="line-3789">        }</span> | 
 | <span class="source-line-no">3790</span><span id="line-3790">      });</span> | 
 | <span class="source-line-no">3791</span><span id="line-3791">      return walEdits;</span> | 
 | <span class="source-line-no">3792</span><span id="line-3792">    }</span> | 
 | <span class="source-line-no">3793</span><span id="line-3793"></span> | 
 | <span class="source-line-no">3794</span><span id="line-3794">    protected void addNonSkipWALMutationsToWALEdit(</span> | 
 | <span class="source-line-no">3795</span><span id="line-3795">      final MiniBatchOperationInProgress<Mutation> miniBatchOp, WALEdit walEdit,</span> | 
 | <span class="source-line-no">3796</span><span id="line-3796">      List<ExtendedCell> cellsFromCP, Map<byte[], List<ExtendedCell>> familyCellMap) {</span> | 
 | <span class="source-line-no">3797</span><span id="line-3797">      doAddCellsToWALEdit(walEdit, cellsFromCP, familyCellMap);</span> | 
 | <span class="source-line-no">3798</span><span id="line-3798">    }</span> | 
 | <span class="source-line-no">3799</span><span id="line-3799"></span> | 
 | <span class="source-line-no">3800</span><span id="line-3800">    protected static void doAddCellsToWALEdit(WALEdit walEdit, List<ExtendedCell> cellsFromCP,</span> | 
 | <span class="source-line-no">3801</span><span id="line-3801">      Map<byte[], List<ExtendedCell>> familyCellMap) {</span> | 
 | <span class="source-line-no">3802</span><span id="line-3802">      WALEditInternalHelper.addExtendedCell(walEdit, cellsFromCP);</span> | 
 | <span class="source-line-no">3803</span><span id="line-3803">      WALEditInternalHelper.addMap(walEdit, familyCellMap);</span> | 
 | <span class="source-line-no">3804</span><span id="line-3804">    }</span> | 
 | <span class="source-line-no">3805</span><span id="line-3805"></span> | 
 | <span class="source-line-no">3806</span><span id="line-3806">    protected abstract void cacheSkipWALMutationForRegionReplication(</span> | 
 | <span class="source-line-no">3807</span><span id="line-3807">      final MiniBatchOperationInProgress<Mutation> miniBatchOp,</span> | 
 | <span class="source-line-no">3808</span><span id="line-3808">      List<Pair<NonceKey, WALEdit>> walEdits, Map<byte[], List<ExtendedCell>> familyCellMap);</span> | 
 | <span class="source-line-no">3809</span><span id="line-3809"></span> | 
 | <span class="source-line-no">3810</span><span id="line-3810">    /**</span> | 
 | <span class="source-line-no">3811</span><span id="line-3811">     * This method completes mini-batch operations by calling postBatchMutate() CP hook (if</span> | 
 | <span class="source-line-no">3812</span><span id="line-3812">     * required) and completing mvcc.</span> | 
 | <span class="source-line-no">3813</span><span id="line-3813">     */</span> | 
 | <span class="source-line-no">3814</span><span id="line-3814">    public void completeMiniBatchOperations(</span> | 
 | <span class="source-line-no">3815</span><span id="line-3815">      final MiniBatchOperationInProgress<Mutation> miniBatchOp, final WriteEntry writeEntry)</span> | 
 | <span class="source-line-no">3816</span><span id="line-3816">      throws IOException {</span> | 
 | <span class="source-line-no">3817</span><span id="line-3817">      if (writeEntry != null) {</span> | 
 | <span class="source-line-no">3818</span><span id="line-3818">        region.mvcc.completeAndWait(writeEntry);</span> | 
 | <span class="source-line-no">3819</span><span id="line-3819">      }</span> | 
 | <span class="source-line-no">3820</span><span id="line-3820">    }</span> | 
 | <span class="source-line-no">3821</span><span id="line-3821"></span> | 
 | <span class="source-line-no">3822</span><span id="line-3822">    public void doPostOpCleanupForMiniBatch(</span> | 
 | <span class="source-line-no">3823</span><span id="line-3823">      final MiniBatchOperationInProgress<Mutation> miniBatchOp, final WALEdit walEdit,</span> | 
 | <span class="source-line-no">3824</span><span id="line-3824">      boolean success) throws IOException {</span> | 
 | <span class="source-line-no">3825</span><span id="line-3825">      doFinishHotnessProtector(miniBatchOp);</span> | 
 | <span class="source-line-no">3826</span><span id="line-3826">    }</span> | 
 | <span class="source-line-no">3827</span><span id="line-3827"></span> | 
 | <span class="source-line-no">3828</span><span id="line-3828">    private void</span> | 
 | <span class="source-line-no">3829</span><span id="line-3829">      doFinishHotnessProtector(final MiniBatchOperationInProgress<Mutation> miniBatchOp) {</span> | 
 | <span class="source-line-no">3830</span><span id="line-3830">      // check and return if the protector is not enabled</span> | 
 | <span class="source-line-no">3831</span><span id="line-3831">      if (!region.storeHotnessProtector.isEnable()) {</span> | 
 | <span class="source-line-no">3832</span><span id="line-3832">        return;</span> | 
 | <span class="source-line-no">3833</span><span id="line-3833">      }</span> | 
 | <span class="source-line-no">3834</span><span id="line-3834">      // miniBatchOp is null, if and only if lockRowsAndBuildMiniBatch throwing exception.</span> | 
 | <span class="source-line-no">3835</span><span id="line-3835">      // This case was handled.</span> | 
 | <span class="source-line-no">3836</span><span id="line-3836">      if (miniBatchOp == null) {</span> | 
 | <span class="source-line-no">3837</span><span id="line-3837">        return;</span> | 
 | <span class="source-line-no">3838</span><span id="line-3838">      }</span> | 
 | <span class="source-line-no">3839</span><span id="line-3839"></span> | 
 | <span class="source-line-no">3840</span><span id="line-3840">      final int finalLastIndexExclusive = miniBatchOp.getLastIndexExclusive();</span> | 
 | <span class="source-line-no">3841</span><span id="line-3841"></span> | 
 | <span class="source-line-no">3842</span><span id="line-3842">      for (int i = nextIndexToProcess; i < finalLastIndexExclusive; i++) {</span> | 
 | <span class="source-line-no">3843</span><span id="line-3843">        switch (retCodeDetails[i].getOperationStatusCode()) {</span> | 
 | <span class="source-line-no">3844</span><span id="line-3844">          case SUCCESS:</span> | 
 | <span class="source-line-no">3845</span><span id="line-3845">          case FAILURE:</span> | 
 | <span class="source-line-no">3846</span><span id="line-3846">            region.storeHotnessProtector.finish(getMutation(i).getFamilyCellMap());</span> | 
 | <span class="source-line-no">3847</span><span id="line-3847">            break;</span> | 
 | <span class="source-line-no">3848</span><span id="line-3848">          default:</span> | 
 | <span class="source-line-no">3849</span><span id="line-3849">            // do nothing</span> | 
 | <span class="source-line-no">3850</span><span id="line-3850">            // We won't start the protector for NOT_RUN/BAD_FAMILY/SANITY_CHECK_FAILURE and the</span> | 
 | <span class="source-line-no">3851</span><span id="line-3851">            // STORE_TOO_BUSY case is handled in StoreHotnessProtector#start</span> | 
 | <span class="source-line-no">3852</span><span id="line-3852">            break;</span> | 
 | <span class="source-line-no">3853</span><span id="line-3853">        }</span> | 
 | <span class="source-line-no">3854</span><span id="line-3854">      }</span> | 
 | <span class="source-line-no">3855</span><span id="line-3855">    }</span> | 
 | <span class="source-line-no">3856</span><span id="line-3856"></span> | 
 | <span class="source-line-no">3857</span><span id="line-3857">    /**</span> | 
 | <span class="source-line-no">3858</span><span id="line-3858">     * Atomically apply the given map of family->edits to the memstore. This handles the consistency</span> | 
 | <span class="source-line-no">3859</span><span id="line-3859">     * control on its own, but the caller should already have locked updatesLock.readLock(). This</span> | 
 | <span class="source-line-no">3860</span><span id="line-3860">     * also does <b>not</b> check the families for validity.</span> | 
 | <span class="source-line-no">3861</span><span id="line-3861">     * @param familyMap Map of Cells by family</span> | 
 | <span class="source-line-no">3862</span><span id="line-3862">     */</span> | 
 | <span class="source-line-no">3863</span><span id="line-3863">    protected void applyFamilyMapToMemStore(Map<byte[], List<ExtendedCell>> familyMap,</span> | 
 | <span class="source-line-no">3864</span><span id="line-3864">      MemStoreSizing memstoreAccounting) {</span> | 
 | <span class="source-line-no">3865</span><span id="line-3865">      for (Map.Entry<byte[], List<ExtendedCell>> e : familyMap.entrySet()) {</span> | 
 | <span class="source-line-no">3866</span><span id="line-3866">        byte[] family = e.getKey();</span> | 
 | <span class="source-line-no">3867</span><span id="line-3867">        List<ExtendedCell> cells = e.getValue();</span> | 
 | <span class="source-line-no">3868</span><span id="line-3868">        assert cells instanceof RandomAccess;</span> | 
 | <span class="source-line-no">3869</span><span id="line-3869">        region.applyToMemStore(region.getStore(family), cells, false, memstoreAccounting);</span> | 
 | <span class="source-line-no">3870</span><span id="line-3870">      }</span> | 
 | <span class="source-line-no">3871</span><span id="line-3871">    }</span> | 
 | <span class="source-line-no">3872</span><span id="line-3872">  }</span> | 
 | <span class="source-line-no">3873</span><span id="line-3873"></span> | 
 | <span class="source-line-no">3874</span><span id="line-3874">  /**</span> | 
 | <span class="source-line-no">3875</span><span id="line-3875">   * Batch of mutation operations. Base class is shared with {@link ReplayBatchOperation} as most of</span> | 
 | <span class="source-line-no">3876</span><span id="line-3876">   * the logic is same.</span> | 
 | <span class="source-line-no">3877</span><span id="line-3877">   */</span> | 
 | <span class="source-line-no">3878</span><span id="line-3878">  private static class MutationBatchOperation extends BatchOperation<Mutation> {</span> | 
 | <span class="source-line-no">3879</span><span id="line-3879"></span> | 
 | <span class="source-line-no">3880</span><span id="line-3880">    // For nonce operations</span> | 
 | <span class="source-line-no">3881</span><span id="line-3881">    private long nonceGroup;</span> | 
 | <span class="source-line-no">3882</span><span id="line-3882">    private long nonce;</span> | 
 | <span class="source-line-no">3883</span><span id="line-3883">    protected boolean canProceed;</span> | 
 | <span class="source-line-no">3884</span><span id="line-3884">    private boolean regionReplicateEnable;</span> | 
 | <span class="source-line-no">3885</span><span id="line-3885"></span> | 
 | <span class="source-line-no">3886</span><span id="line-3886">    public MutationBatchOperation(final HRegion region, Mutation[] operations, boolean atomic,</span> | 
 | <span class="source-line-no">3887</span><span id="line-3887">      long nonceGroup, long nonce) {</span> | 
 | <span class="source-line-no">3888</span><span id="line-3888">      super(region, operations);</span> | 
 | <span class="source-line-no">3889</span><span id="line-3889">      this.atomic = atomic;</span> | 
 | <span class="source-line-no">3890</span><span id="line-3890">      this.nonceGroup = nonceGroup;</span> | 
 | <span class="source-line-no">3891</span><span id="line-3891">      this.nonce = nonce;</span> | 
 | <span class="source-line-no">3892</span><span id="line-3892">      this.regionReplicateEnable = region.regionReplicationSink.isPresent();</span> | 
 | <span class="source-line-no">3893</span><span id="line-3893">    }</span> | 
 | <span class="source-line-no">3894</span><span id="line-3894"></span> | 
 | <span class="source-line-no">3895</span><span id="line-3895">    @Override</span> | 
 | <span class="source-line-no">3896</span><span id="line-3896">    public Mutation getMutation(int index) {</span> | 
 | <span class="source-line-no">3897</span><span id="line-3897">      return this.operations[index];</span> | 
 | <span class="source-line-no">3898</span><span id="line-3898">    }</span> | 
 | <span class="source-line-no">3899</span><span id="line-3899"></span> | 
 | <span class="source-line-no">3900</span><span id="line-3900">    @Override</span> | 
 | <span class="source-line-no">3901</span><span id="line-3901">    public long getNonceGroup(int index) {</span> | 
 | <span class="source-line-no">3902</span><span id="line-3902">      return nonceGroup;</span> | 
 | <span class="source-line-no">3903</span><span id="line-3903">    }</span> | 
 | <span class="source-line-no">3904</span><span id="line-3904"></span> | 
 | <span class="source-line-no">3905</span><span id="line-3905">    @Override</span> | 
 | <span class="source-line-no">3906</span><span id="line-3906">    public long getNonce(int index) {</span> | 
 | <span class="source-line-no">3907</span><span id="line-3907">      return nonce;</span> | 
 | <span class="source-line-no">3908</span><span id="line-3908">    }</span> | 
 | <span class="source-line-no">3909</span><span id="line-3909"></span> | 
 | <span class="source-line-no">3910</span><span id="line-3910">    @Override</span> | 
 | <span class="source-line-no">3911</span><span id="line-3911">    public Mutation[] getMutationsForCoprocs() {</span> | 
 | <span class="source-line-no">3912</span><span id="line-3912">      return this.operations;</span> | 
 | <span class="source-line-no">3913</span><span id="line-3913">    }</span> | 
 | <span class="source-line-no">3914</span><span id="line-3914"></span> | 
 | <span class="source-line-no">3915</span><span id="line-3915">    @Override</span> | 
 | <span class="source-line-no">3916</span><span id="line-3916">    public boolean isInReplay() {</span> | 
 | <span class="source-line-no">3917</span><span id="line-3917">      return false;</span> | 
 | <span class="source-line-no">3918</span><span id="line-3918">    }</span> | 
 | <span class="source-line-no">3919</span><span id="line-3919"></span> | 
 | <span class="source-line-no">3920</span><span id="line-3920">    @Override</span> | 
 | <span class="source-line-no">3921</span><span id="line-3921">    public long getOrigLogSeqNum() {</span> | 
 | <span class="source-line-no">3922</span><span id="line-3922">      return SequenceId.NO_SEQUENCE_ID;</span> | 
 | <span class="source-line-no">3923</span><span id="line-3923">    }</span> | 
 | <span class="source-line-no">3924</span><span id="line-3924"></span> | 
 | <span class="source-line-no">3925</span><span id="line-3925">    @Override</span> | 
 | <span class="source-line-no">3926</span><span id="line-3926">    public void startRegionOperation() throws IOException {</span> | 
 | <span class="source-line-no">3927</span><span id="line-3927">      region.startRegionOperation(Operation.BATCH_MUTATE);</span> | 
 | <span class="source-line-no">3928</span><span id="line-3928">    }</span> | 
 | <span class="source-line-no">3929</span><span id="line-3929"></span> | 
 | <span class="source-line-no">3930</span><span id="line-3930">    @Override</span> | 
 | <span class="source-line-no">3931</span><span id="line-3931">    public void closeRegionOperation() throws IOException {</span> | 
 | <span class="source-line-no">3932</span><span id="line-3932">      region.closeRegionOperation(Operation.BATCH_MUTATE);</span> | 
 | <span class="source-line-no">3933</span><span id="line-3933">    }</span> | 
 | <span class="source-line-no">3934</span><span id="line-3934"></span> | 
 | <span class="source-line-no">3935</span><span id="line-3935">    @Override</span> | 
 | <span class="source-line-no">3936</span><span id="line-3936">    public void checkAndPreparePut(Put p) throws IOException {</span> | 
 | <span class="source-line-no">3937</span><span id="line-3937">      region.checkFamilies(p.getFamilyCellMap().keySet(), p.getDurability());</span> | 
 | <span class="source-line-no">3938</span><span id="line-3938">    }</span> | 
 | <span class="source-line-no">3939</span><span id="line-3939"></span> | 
 | <span class="source-line-no">3940</span><span id="line-3940">    @Override</span> | 
 | <span class="source-line-no">3941</span><span id="line-3941">    public void checkAndPrepare() throws IOException {</span> | 
 | <span class="source-line-no">3942</span><span id="line-3942">      // index 0: puts, index 1: deletes, index 2: increments, index 3: append</span> | 
 | <span class="source-line-no">3943</span><span id="line-3943">      final int[] metrics = { 0, 0, 0, 0 };</span> | 
 | <span class="source-line-no">3944</span><span id="line-3944"></span> | 
 | <span class="source-line-no">3945</span><span id="line-3945">      visitBatchOperations(true, this.size(), new Visitor() {</span> | 
 | <span class="source-line-no">3946</span><span id="line-3946">        private long now = EnvironmentEdgeManager.currentTime();</span> | 
 | <span class="source-line-no">3947</span><span id="line-3947">        private WALEdit walEdit;</span> | 
 | <span class="source-line-no">3948</span><span id="line-3948"></span> | 
 | <span class="source-line-no">3949</span><span id="line-3949">        @Override</span> | 
 | <span class="source-line-no">3950</span><span id="line-3950">        public boolean visit(int index) throws IOException {</span> | 
 | <span class="source-line-no">3951</span><span id="line-3951">          // Run coprocessor pre hook outside of locks to avoid deadlock</span> | 
 | <span class="source-line-no">3952</span><span id="line-3952">          if (region.coprocessorHost != null) {</span> | 
 | <span class="source-line-no">3953</span><span id="line-3953">            if (walEdit == null) {</span> | 
 | <span class="source-line-no">3954</span><span id="line-3954">              walEdit = new WALEdit();</span> | 
 | <span class="source-line-no">3955</span><span id="line-3955">            }</span> | 
 | <span class="source-line-no">3956</span><span id="line-3956">            callPreMutateCPHook(index, walEdit, metrics);</span> | 
 | <span class="source-line-no">3957</span><span id="line-3957">            if (!walEdit.isEmpty()) {</span> | 
 | <span class="source-line-no">3958</span><span id="line-3958">              walEditsFromCoprocessors[index] = walEdit;</span> | 
 | <span class="source-line-no">3959</span><span id="line-3959">              walEdit = null;</span> | 
 | <span class="source-line-no">3960</span><span id="line-3960">            }</span> | 
 | <span class="source-line-no">3961</span><span id="line-3961">          }</span> | 
 | <span class="source-line-no">3962</span><span id="line-3962">          if (isOperationPending(index)) {</span> | 
 | <span class="source-line-no">3963</span><span id="line-3963">            // TODO: Currently validation is done with current time before acquiring locks and</span> | 
 | <span class="source-line-no">3964</span><span id="line-3964">            // updates are done with different timestamps after acquiring locks. This behavior is</span> | 
 | <span class="source-line-no">3965</span><span id="line-3965">            // inherited from the code prior to this change. Can this be changed?</span> | 
 | <span class="source-line-no">3966</span><span id="line-3966">            checkAndPrepareMutation(index, now);</span> | 
 | <span class="source-line-no">3967</span><span id="line-3967">          }</span> | 
 | <span class="source-line-no">3968</span><span id="line-3968">          return true;</span> | 
 | <span class="source-line-no">3969</span><span id="line-3969">        }</span> | 
 | <span class="source-line-no">3970</span><span id="line-3970">      });</span> | 
 | <span class="source-line-no">3971</span><span id="line-3971"></span> | 
 | <span class="source-line-no">3972</span><span id="line-3972">      // FIXME: we may update metrics twice! here for all operations bypassed by CP and later in</span> | 
 | <span class="source-line-no">3973</span><span id="line-3973">      // normal processing.</span> | 
 | <span class="source-line-no">3974</span><span id="line-3974">      // Update metrics in same way as it is done when we go the normal processing route (we now</span> | 
 | <span class="source-line-no">3975</span><span id="line-3975">      // update general metrics though a Coprocessor did the work).</span> | 
 | <span class="source-line-no">3976</span><span id="line-3976">      if (region.metricsRegion != null) {</span> | 
 | <span class="source-line-no">3977</span><span id="line-3977">        if (metrics[0] > 0) {</span> | 
 | <span class="source-line-no">3978</span><span id="line-3978">          // There were some Puts in the batch.</span> | 
 | <span class="source-line-no">3979</span><span id="line-3979">          region.metricsRegion.updatePut();</span> | 
 | <span class="source-line-no">3980</span><span id="line-3980">        }</span> | 
 | <span class="source-line-no">3981</span><span id="line-3981">        if (metrics[1] > 0) {</span> | 
 | <span class="source-line-no">3982</span><span id="line-3982">          // There were some Deletes in the batch.</span> | 
 | <span class="source-line-no">3983</span><span id="line-3983">          region.metricsRegion.updateDelete();</span> | 
 | <span class="source-line-no">3984</span><span id="line-3984">        }</span> | 
 | <span class="source-line-no">3985</span><span id="line-3985">        if (metrics[2] > 0) {</span> | 
 | <span class="source-line-no">3986</span><span id="line-3986">          // There were some Increment in the batch.</span> | 
 | <span class="source-line-no">3987</span><span id="line-3987">          region.metricsRegion.updateIncrement();</span> | 
 | <span class="source-line-no">3988</span><span id="line-3988">        }</span> | 
 | <span class="source-line-no">3989</span><span id="line-3989">        if (metrics[3] > 0) {</span> | 
 | <span class="source-line-no">3990</span><span id="line-3990">          // There were some Append in the batch.</span> | 
 | <span class="source-line-no">3991</span><span id="line-3991">          region.metricsRegion.updateAppend();</span> | 
 | <span class="source-line-no">3992</span><span id="line-3992">        }</span> | 
 | <span class="source-line-no">3993</span><span id="line-3993">      }</span> | 
 | <span class="source-line-no">3994</span><span id="line-3994">    }</span> | 
 | <span class="source-line-no">3995</span><span id="line-3995"></span> | 
 | <span class="source-line-no">3996</span><span id="line-3996">    @Override</span> | 
 | <span class="source-line-no">3997</span><span id="line-3997">    public void prepareMiniBatchOperations(MiniBatchOperationInProgress<Mutation> miniBatchOp,</span> | 
 | <span class="source-line-no">3998</span><span id="line-3998">      long timestamp, final List<RowLock> acquiredRowLocks) throws IOException {</span> | 
 | <span class="source-line-no">3999</span><span id="line-3999">      // For nonce operations</span> | 
 | <span class="source-line-no">4000</span><span id="line-4000">      canProceed = startNonceOperation();</span> | 
 | <span class="source-line-no">4001</span><span id="line-4001"></span> | 
 | <span class="source-line-no">4002</span><span id="line-4002">      visitBatchOperations(true, miniBatchOp.getLastIndexExclusive(), (int index) -> {</span> | 
 | <span class="source-line-no">4003</span><span id="line-4003">        Mutation mutation = getMutation(index);</span> | 
 | <span class="source-line-no">4004</span><span id="line-4004">        if (mutation instanceof Put) {</span> | 
 | <span class="source-line-no">4005</span><span id="line-4005">          HRegion.updateCellTimestamps(familyCellMaps[index].values(), Bytes.toBytes(timestamp));</span> | 
 | <span class="source-line-no">4006</span><span id="line-4006">          miniBatchOp.incrementNumOfPuts();</span> | 
 | <span class="source-line-no">4007</span><span id="line-4007">        } else if (mutation instanceof Delete) {</span> | 
 | <span class="source-line-no">4008</span><span id="line-4008">          region.prepareDeleteTimestamps(mutation, familyCellMaps[index], Bytes.toBytes(timestamp));</span> | 
 | <span class="source-line-no">4009</span><span id="line-4009">          miniBatchOp.incrementNumOfDeletes();</span> | 
 | <span class="source-line-no">4010</span><span id="line-4010">        } else if (mutation instanceof Increment || mutation instanceof Append) {</span> | 
 | <span class="source-line-no">4011</span><span id="line-4011">          boolean returnResults;</span> | 
 | <span class="source-line-no">4012</span><span id="line-4012">          if (mutation instanceof Increment) {</span> | 
 | <span class="source-line-no">4013</span><span id="line-4013">            returnResults = ((Increment) mutation).isReturnResults();</span> | 
 | <span class="source-line-no">4014</span><span id="line-4014">          } else {</span> | 
 | <span class="source-line-no">4015</span><span id="line-4015">            returnResults = ((Append) mutation).isReturnResults();</span> | 
 | <span class="source-line-no">4016</span><span id="line-4016">          }</span> | 
 | <span class="source-line-no">4017</span><span id="line-4017"></span> | 
 | <span class="source-line-no">4018</span><span id="line-4018">          // For nonce operations</span> | 
 | <span class="source-line-no">4019</span><span id="line-4019">          if (!canProceed) {</span> | 
 | <span class="source-line-no">4020</span><span id="line-4020">            Result result;</span> | 
 | <span class="source-line-no">4021</span><span id="line-4021">            if (returnResults) {</span> | 
 | <span class="source-line-no">4022</span><span id="line-4022">              // convert duplicate increment/append to get</span> | 
 | <span class="source-line-no">4023</span><span id="line-4023">              List<Cell> results = region.get(toGet(mutation), false, nonceGroup, nonce);</span> | 
 | <span class="source-line-no">4024</span><span id="line-4024">              result = Result.create(results);</span> | 
 | <span class="source-line-no">4025</span><span id="line-4025">            } else {</span> | 
 | <span class="source-line-no">4026</span><span id="line-4026">              result = Result.EMPTY_RESULT;</span> | 
 | <span class="source-line-no">4027</span><span id="line-4027">            }</span> | 
 | <span class="source-line-no">4028</span><span id="line-4028">            retCodeDetails[index] = new OperationStatus(OperationStatusCode.SUCCESS, result);</span> | 
 | <span class="source-line-no">4029</span><span id="line-4029">            return true;</span> | 
 | <span class="source-line-no">4030</span><span id="line-4030">          }</span> | 
 | <span class="source-line-no">4031</span><span id="line-4031"></span> | 
 | <span class="source-line-no">4032</span><span id="line-4032">          Result result = null;</span> | 
 | <span class="source-line-no">4033</span><span id="line-4033">          if (region.coprocessorHost != null) {</span> | 
 | <span class="source-line-no">4034</span><span id="line-4034">            if (mutation instanceof Increment) {</span> | 
 | <span class="source-line-no">4035</span><span id="line-4035">              result = region.coprocessorHost.preIncrementAfterRowLock((Increment) mutation);</span> | 
 | <span class="source-line-no">4036</span><span id="line-4036">            } else {</span> | 
 | <span class="source-line-no">4037</span><span id="line-4037">              result = region.coprocessorHost.preAppendAfterRowLock((Append) mutation);</span> | 
 | <span class="source-line-no">4038</span><span id="line-4038">            }</span> | 
 | <span class="source-line-no">4039</span><span id="line-4039">          }</span> | 
 | <span class="source-line-no">4040</span><span id="line-4040">          if (result != null) {</span> | 
 | <span class="source-line-no">4041</span><span id="line-4041">            retCodeDetails[index] = new OperationStatus(OperationStatusCode.SUCCESS,</span> | 
 | <span class="source-line-no">4042</span><span id="line-4042">              returnResults ? result : Result.EMPTY_RESULT);</span> | 
 | <span class="source-line-no">4043</span><span id="line-4043">            return true;</span> | 
 | <span class="source-line-no">4044</span><span id="line-4044">          }</span> | 
 | <span class="source-line-no">4045</span><span id="line-4045"></span> | 
 | <span class="source-line-no">4046</span><span id="line-4046">          List<ExtendedCell> results = returnResults ? new ArrayList<>(mutation.size()) : null;</span> | 
 | <span class="source-line-no">4047</span><span id="line-4047">          familyCellMaps[index] = reckonDeltas(mutation, results, timestamp);</span> | 
 | <span class="source-line-no">4048</span><span id="line-4048">          this.results[index] = results != null ? Result.create(results) : Result.EMPTY_RESULT;</span> | 
 | <span class="source-line-no">4049</span><span id="line-4049"></span> | 
 | <span class="source-line-no">4050</span><span id="line-4050">          if (mutation instanceof Increment) {</span> | 
 | <span class="source-line-no">4051</span><span id="line-4051">            miniBatchOp.incrementNumOfIncrements();</span> | 
 | <span class="source-line-no">4052</span><span id="line-4052">          } else {</span> | 
 | <span class="source-line-no">4053</span><span id="line-4053">            miniBatchOp.incrementNumOfAppends();</span> | 
 | <span class="source-line-no">4054</span><span id="line-4054">          }</span> | 
 | <span class="source-line-no">4055</span><span id="line-4055">        }</span> | 
 | <span class="source-line-no">4056</span><span id="line-4056">        region.rewriteCellTags(familyCellMaps[index], mutation);</span> | 
 | <span class="source-line-no">4057</span><span id="line-4057"></span> | 
 | <span class="source-line-no">4058</span><span id="line-4058">        // update cell count</span> | 
 | <span class="source-line-no">4059</span><span id="line-4059">        if (region.getEffectiveDurability(mutation.getDurability()) != Durability.SKIP_WAL) {</span> | 
 | <span class="source-line-no">4060</span><span id="line-4060">          for (List<Cell> cells : mutation.getFamilyCellMap().values()) {</span> | 
 | <span class="source-line-no">4061</span><span id="line-4061">            miniBatchOp.addCellCount(cells.size());</span> | 
 | <span class="source-line-no">4062</span><span id="line-4062">          }</span> | 
 | <span class="source-line-no">4063</span><span id="line-4063">        }</span> | 
 | <span class="source-line-no">4064</span><span id="line-4064"></span> | 
 | <span class="source-line-no">4065</span><span id="line-4065">        WALEdit fromCP = walEditsFromCoprocessors[index];</span> | 
 | <span class="source-line-no">4066</span><span id="line-4066">        if (fromCP != null) {</span> | 
 | <span class="source-line-no">4067</span><span id="line-4067">          miniBatchOp.addCellCount(fromCP.size());</span> | 
 | <span class="source-line-no">4068</span><span id="line-4068">        }</span> | 
 | <span class="source-line-no">4069</span><span id="line-4069">        return true;</span> | 
 | <span class="source-line-no">4070</span><span id="line-4070">      });</span> | 
 | <span class="source-line-no">4071</span><span id="line-4071"></span> | 
 | <span class="source-line-no">4072</span><span id="line-4072">      if (region.coprocessorHost != null) {</span> | 
 | <span class="source-line-no">4073</span><span id="line-4073">        // calling the pre CP hook for batch mutation</span> | 
 | <span class="source-line-no">4074</span><span id="line-4074">        region.coprocessorHost.preBatchMutate(miniBatchOp);</span> | 
 | <span class="source-line-no">4075</span><span id="line-4075">        checkAndMergeCPMutations(miniBatchOp, acquiredRowLocks, timestamp);</span> | 
 | <span class="source-line-no">4076</span><span id="line-4076">      }</span> | 
 | <span class="source-line-no">4077</span><span id="line-4077">    }</span> | 
 | <span class="source-line-no">4078</span><span id="line-4078"></span> | 
 | <span class="source-line-no">4079</span><span id="line-4079">    /**</span> | 
 | <span class="source-line-no">4080</span><span id="line-4080">     * Starts the nonce operation for a mutation, if needed.</span> | 
 | <span class="source-line-no">4081</span><span id="line-4081">     * @return whether to proceed this mutation.</span> | 
 | <span class="source-line-no">4082</span><span id="line-4082">     */</span> | 
 | <span class="source-line-no">4083</span><span id="line-4083">    private boolean startNonceOperation() throws IOException {</span> | 
 | <span class="source-line-no">4084</span><span id="line-4084">      if (</span> | 
 | <span class="source-line-no">4085</span><span id="line-4085">        region.rsServices == null || region.rsServices.getNonceManager() == null</span> | 
 | <span class="source-line-no">4086</span><span id="line-4086">          || nonce == HConstants.NO_NONCE</span> | 
 | <span class="source-line-no">4087</span><span id="line-4087">      ) {</span> | 
 | <span class="source-line-no">4088</span><span id="line-4088">        return true;</span> | 
 | <span class="source-line-no">4089</span><span id="line-4089">      }</span> | 
 | <span class="source-line-no">4090</span><span id="line-4090">      boolean canProceed;</span> | 
 | <span class="source-line-no">4091</span><span id="line-4091">      try {</span> | 
 | <span class="source-line-no">4092</span><span id="line-4092">        canProceed =</span> | 
 | <span class="source-line-no">4093</span><span id="line-4093">          region.rsServices.getNonceManager().startOperation(nonceGroup, nonce, region.rsServices);</span> | 
 | <span class="source-line-no">4094</span><span id="line-4094">      } catch (InterruptedException ex) {</span> | 
 | <span class="source-line-no">4095</span><span id="line-4095">        throw new InterruptedIOException("Nonce start operation interrupted");</span> | 
 | <span class="source-line-no">4096</span><span id="line-4096">      }</span> | 
 | <span class="source-line-no">4097</span><span id="line-4097">      return canProceed;</span> | 
 | <span class="source-line-no">4098</span><span id="line-4098">    }</span> | 
 | <span class="source-line-no">4099</span><span id="line-4099"></span> | 
 | <span class="source-line-no">4100</span><span id="line-4100">    /**</span> | 
 | <span class="source-line-no">4101</span><span id="line-4101">     * Ends nonce operation for a mutation, if needed.</span> | 
 | <span class="source-line-no">4102</span><span id="line-4102">     * @param success Whether the operation for this nonce has succeeded.</span> | 
 | <span class="source-line-no">4103</span><span id="line-4103">     */</span> | 
 | <span class="source-line-no">4104</span><span id="line-4104">    private void endNonceOperation(boolean success) {</span> | 
 | <span class="source-line-no">4105</span><span id="line-4105">      if (</span> | 
 | <span class="source-line-no">4106</span><span id="line-4106">        region.rsServices != null && region.rsServices.getNonceManager() != null</span> | 
 | <span class="source-line-no">4107</span><span id="line-4107">          && nonce != HConstants.NO_NONCE</span> | 
 | <span class="source-line-no">4108</span><span id="line-4108">      ) {</span> | 
 | <span class="source-line-no">4109</span><span id="line-4109">        region.rsServices.getNonceManager().endOperation(nonceGroup, nonce, success);</span> | 
 | <span class="source-line-no">4110</span><span id="line-4110">      }</span> | 
 | <span class="source-line-no">4111</span><span id="line-4111">    }</span> | 
 | <span class="source-line-no">4112</span><span id="line-4112"></span> | 
 | <span class="source-line-no">4113</span><span id="line-4113">    private static Get toGet(final Mutation mutation) throws IOException {</span> | 
 | <span class="source-line-no">4114</span><span id="line-4114">      assert mutation instanceof Increment || mutation instanceof Append;</span> | 
 | <span class="source-line-no">4115</span><span id="line-4115">      Get get = new Get(mutation.getRow());</span> | 
 | <span class="source-line-no">4116</span><span id="line-4116">      CellScanner cellScanner = mutation.cellScanner();</span> | 
 | <span class="source-line-no">4117</span><span id="line-4117">      while (cellScanner.advance()) {</span> | 
 | <span class="source-line-no">4118</span><span id="line-4118">        Cell cell = cellScanner.current();</span> | 
 | <span class="source-line-no">4119</span><span id="line-4119">        get.addColumn(CellUtil.cloneFamily(cell), CellUtil.cloneQualifier(cell));</span> | 
 | <span class="source-line-no">4120</span><span id="line-4120">      }</span> | 
 | <span class="source-line-no">4121</span><span id="line-4121">      if (mutation instanceof Increment) {</span> | 
 | <span class="source-line-no">4122</span><span id="line-4122">        // Increment</span> | 
 | <span class="source-line-no">4123</span><span id="line-4123">        Increment increment = (Increment) mutation;</span> | 
 | <span class="source-line-no">4124</span><span id="line-4124">        get.setTimeRange(increment.getTimeRange().getMin(), increment.getTimeRange().getMax());</span> | 
 | <span class="source-line-no">4125</span><span id="line-4125">      } else {</span> | 
 | <span class="source-line-no">4126</span><span id="line-4126">        // Append</span> | 
 | <span class="source-line-no">4127</span><span id="line-4127">        Append append = (Append) mutation;</span> | 
 | <span class="source-line-no">4128</span><span id="line-4128">        get.setTimeRange(append.getTimeRange().getMin(), append.getTimeRange().getMax());</span> | 
 | <span class="source-line-no">4129</span><span id="line-4129">      }</span> | 
 | <span class="source-line-no">4130</span><span id="line-4130">      for (Entry<String, byte[]> entry : mutation.getAttributesMap().entrySet()) {</span> | 
 | <span class="source-line-no">4131</span><span id="line-4131">        get.setAttribute(entry.getKey(), entry.getValue());</span> | 
 | <span class="source-line-no">4132</span><span id="line-4132">      }</span> | 
 | <span class="source-line-no">4133</span><span id="line-4133">      return get;</span> | 
 | <span class="source-line-no">4134</span><span id="line-4134">    }</span> | 
 | <span class="source-line-no">4135</span><span id="line-4135"></span> | 
 | <span class="source-line-no">4136</span><span id="line-4136">    private Map<byte[], List<ExtendedCell>> reckonDeltas(Mutation mutation,</span> | 
 | <span class="source-line-no">4137</span><span id="line-4137">      List<ExtendedCell> results, long now) throws IOException {</span> | 
 | <span class="source-line-no">4138</span><span id="line-4138">      assert mutation instanceof Increment || mutation instanceof Append;</span> | 
 | <span class="source-line-no">4139</span><span id="line-4139">      Map<byte[], List<ExtendedCell>> ret = new TreeMap<>(Bytes.BYTES_COMPARATOR);</span> | 
 | <span class="source-line-no">4140</span><span id="line-4140">      // Process a Store/family at a time.</span> | 
 | <span class="source-line-no">4141</span><span id="line-4141">      for (Map.Entry<byte[], List<ExtendedCell>> entry : ClientInternalHelper</span> | 
 | <span class="source-line-no">4142</span><span id="line-4142">        .getExtendedFamilyCellMap(mutation).entrySet()) {</span> | 
 | <span class="source-line-no">4143</span><span id="line-4143">        final byte[] columnFamilyName = entry.getKey();</span> | 
 | <span class="source-line-no">4144</span><span id="line-4144">        List<ExtendedCell> deltas = entry.getValue();</span> | 
 | <span class="source-line-no">4145</span><span id="line-4145">        // Reckon for the Store what to apply to WAL and MemStore.</span> | 
 | <span class="source-line-no">4146</span><span id="line-4146">        List<ExtendedCell> toApply =</span> | 
 | <span class="source-line-no">4147</span><span id="line-4147">          reckonDeltasByStore(region.stores.get(columnFamilyName), mutation, now, deltas, results);</span> | 
 | <span class="source-line-no">4148</span><span id="line-4148">        if (!toApply.isEmpty()) {</span> | 
 | <span class="source-line-no">4149</span><span id="line-4149">          for (ExtendedCell cell : toApply) {</span> | 
 | <span class="source-line-no">4150</span><span id="line-4150">            HStore store = region.getStore(cell);</span> | 
 | <span class="source-line-no">4151</span><span id="line-4151">            if (store == null) {</span> | 
 | <span class="source-line-no">4152</span><span id="line-4152">              region.checkFamily(CellUtil.cloneFamily(cell));</span> | 
 | <span class="source-line-no">4153</span><span id="line-4153">            } else {</span> | 
 | <span class="source-line-no">4154</span><span id="line-4154">              ret.computeIfAbsent(store.getColumnFamilyDescriptor().getName(),</span> | 
 | <span class="source-line-no">4155</span><span id="line-4155">                key -> new ArrayList<>()).add(cell);</span> | 
 | <span class="source-line-no">4156</span><span id="line-4156">            }</span> | 
 | <span class="source-line-no">4157</span><span id="line-4157">          }</span> | 
 | <span class="source-line-no">4158</span><span id="line-4158">        }</span> | 
 | <span class="source-line-no">4159</span><span id="line-4159">      }</span> | 
 | <span class="source-line-no">4160</span><span id="line-4160">      return ret;</span> | 
 | <span class="source-line-no">4161</span><span id="line-4161">    }</span> | 
 | <span class="source-line-no">4162</span><span id="line-4162"></span> | 
 | <span class="source-line-no">4163</span><span id="line-4163">    /**</span> | 
 | <span class="source-line-no">4164</span><span id="line-4164">     * Reckon the Cells to apply to WAL, memstore, and to return to the Client in passed column</span> | 
 | <span class="source-line-no">4165</span><span id="line-4165">     * family/Store. Does Get of current value and then adds passed in deltas for this Store</span> | 
 | <span class="source-line-no">4166</span><span id="line-4166">     * returning the result.</span> | 
 | <span class="source-line-no">4167</span><span id="line-4167">     * @param mutation The encompassing Mutation object</span> | 
 | <span class="source-line-no">4168</span><span id="line-4168">     * @param deltas   Changes to apply to this Store; either increment amount or data to append</span> | 
 | <span class="source-line-no">4169</span><span id="line-4169">     * @param results  In here we accumulate all the Cells we are to return to the client. If null,</span> | 
 | <span class="source-line-no">4170</span><span id="line-4170">     *                 client doesn't want results returned.</span> | 
 | <span class="source-line-no">4171</span><span id="line-4171">     * @return Resulting Cells after <code>deltas</code> have been applied to current values. Side</span> | 
 | <span class="source-line-no">4172</span><span id="line-4172">     *         effect is our filling out of the <code>results</code> List.</span> | 
 | <span class="source-line-no">4173</span><span id="line-4173">     */</span> | 
 | <span class="source-line-no">4174</span><span id="line-4174">    private List<ExtendedCell> reckonDeltasByStore(HStore store, Mutation mutation, long now,</span> | 
 | <span class="source-line-no">4175</span><span id="line-4175">      List<ExtendedCell> deltas, List<ExtendedCell> results) throws IOException {</span> | 
 | <span class="source-line-no">4176</span><span id="line-4176">      assert mutation instanceof Increment || mutation instanceof Append;</span> | 
 | <span class="source-line-no">4177</span><span id="line-4177">      byte[] columnFamily = store.getColumnFamilyDescriptor().getName();</span> | 
 | <span class="source-line-no">4178</span><span id="line-4178">      List<Pair<ExtendedCell, ExtendedCell>> cellPairs = new ArrayList<>(deltas.size());</span> | 
 | <span class="source-line-no">4179</span><span id="line-4179"></span> | 
 | <span class="source-line-no">4180</span><span id="line-4180">      // Sort the cells so that they match the order that they appear in the Get results.</span> | 
 | <span class="source-line-no">4181</span><span id="line-4181">      // Otherwise, we won't be able to find the existing values if the cells are not specified</span> | 
 | <span class="source-line-no">4182</span><span id="line-4182">      // in order by the client since cells are in an array list.</span> | 
 | <span class="source-line-no">4183</span><span id="line-4183">      deltas.sort(store.getComparator());</span> | 
 | <span class="source-line-no">4184</span><span id="line-4184"></span> | 
 | <span class="source-line-no">4185</span><span id="line-4185">      // Get previous values for all columns in this family.</span> | 
 | <span class="source-line-no">4186</span><span id="line-4186">      Get get = new Get(mutation.getRow());</span> | 
 | <span class="source-line-no">4187</span><span id="line-4187">      for (ExtendedCell cell : deltas) {</span> | 
 | <span class="source-line-no">4188</span><span id="line-4188">        get.addColumn(columnFamily, CellUtil.cloneQualifier(cell));</span> | 
 | <span class="source-line-no">4189</span><span id="line-4189">      }</span> | 
 | <span class="source-line-no">4190</span><span id="line-4190">      TimeRange tr;</span> | 
 | <span class="source-line-no">4191</span><span id="line-4191">      if (mutation instanceof Increment) {</span> | 
 | <span class="source-line-no">4192</span><span id="line-4192">        tr = ((Increment) mutation).getTimeRange();</span> | 
 | <span class="source-line-no">4193</span><span id="line-4193">      } else {</span> | 
 | <span class="source-line-no">4194</span><span id="line-4194">        tr = ((Append) mutation).getTimeRange();</span> | 
 | <span class="source-line-no">4195</span><span id="line-4195">      }</span> | 
 | <span class="source-line-no">4196</span><span id="line-4196"></span> | 
 | <span class="source-line-no">4197</span><span id="line-4197">      if (tr != null) {</span> | 
 | <span class="source-line-no">4198</span><span id="line-4198">        get.setTimeRange(tr.getMin(), tr.getMax());</span> | 
 | <span class="source-line-no">4199</span><span id="line-4199">      }</span> | 
 | <span class="source-line-no">4200</span><span id="line-4200"></span> | 
 | <span class="source-line-no">4201</span><span id="line-4201">      try (RegionScanner scanner = region.getScanner(new Scan(get))) {</span> | 
 | <span class="source-line-no">4202</span><span id="line-4202">        // NOTE: Please don't use HRegion.get() instead,</span> | 
 | <span class="source-line-no">4203</span><span id="line-4203">        // because it will copy cells to heap. See HBASE-26036</span> | 
 | <span class="source-line-no">4204</span><span id="line-4204">        List<ExtendedCell> currentValues = new ArrayList<>();</span> | 
 | <span class="source-line-no">4205</span><span id="line-4205">        scanner.next(currentValues);</span> | 
 | <span class="source-line-no">4206</span><span id="line-4206">        // Iterate the input columns and update existing values if they were found, otherwise</span> | 
 | <span class="source-line-no">4207</span><span id="line-4207">        // add new column initialized to the delta amount</span> | 
 | <span class="source-line-no">4208</span><span id="line-4208">        int currentValuesIndex = 0;</span> | 
 | <span class="source-line-no">4209</span><span id="line-4209">        for (int i = 0; i < deltas.size(); i++) {</span> | 
 | <span class="source-line-no">4210</span><span id="line-4210">          ExtendedCell delta = deltas.get(i);</span> | 
 | <span class="source-line-no">4211</span><span id="line-4211">          ExtendedCell currentValue = null;</span> | 
 | <span class="source-line-no">4212</span><span id="line-4212">          if (</span> | 
 | <span class="source-line-no">4213</span><span id="line-4213">            currentValuesIndex < currentValues.size()</span> | 
 | <span class="source-line-no">4214</span><span id="line-4214">              && CellUtil.matchingQualifier(currentValues.get(currentValuesIndex), delta)</span> | 
 | <span class="source-line-no">4215</span><span id="line-4215">          ) {</span> | 
 | <span class="source-line-no">4216</span><span id="line-4216">            currentValue = currentValues.get(currentValuesIndex);</span> | 
 | <span class="source-line-no">4217</span><span id="line-4217">            if (i < (deltas.size() - 1) && !CellUtil.matchingQualifier(delta, deltas.get(i + 1))) {</span> | 
 | <span class="source-line-no">4218</span><span id="line-4218">              currentValuesIndex++;</span> | 
 | <span class="source-line-no">4219</span><span id="line-4219">            }</span> | 
 | <span class="source-line-no">4220</span><span id="line-4220">          }</span> | 
 | <span class="source-line-no">4221</span><span id="line-4221">          // Switch on whether this an increment or an append building the new Cell to apply.</span> | 
 | <span class="source-line-no">4222</span><span id="line-4222">          ExtendedCell newCell;</span> | 
 | <span class="source-line-no">4223</span><span id="line-4223">          if (mutation instanceof Increment) {</span> | 
 | <span class="source-line-no">4224</span><span id="line-4224">            long deltaAmount = getLongValue(delta);</span> | 
 | <span class="source-line-no">4225</span><span id="line-4225">            final long newValue =</span> | 
 | <span class="source-line-no">4226</span><span id="line-4226">              currentValue == null ? deltaAmount : getLongValue(currentValue) + deltaAmount;</span> | 
 | <span class="source-line-no">4227</span><span id="line-4227">            newCell = reckonDelta(delta, currentValue, columnFamily, now, mutation,</span> | 
 | <span class="source-line-no">4228</span><span id="line-4228">              (oldCell) -> Bytes.toBytes(newValue));</span> | 
 | <span class="source-line-no">4229</span><span id="line-4229">          } else {</span> | 
 | <span class="source-line-no">4230</span><span id="line-4230">            newCell = reckonDelta(delta, currentValue, columnFamily, now, mutation,</span> | 
 | <span class="source-line-no">4231</span><span id="line-4231">              (oldCell) -> ByteBuffer</span> | 
 | <span class="source-line-no">4232</span><span id="line-4232">                .wrap(new byte[delta.getValueLength() + oldCell.getValueLength()])</span> | 
 | <span class="source-line-no">4233</span><span id="line-4233">                .put(oldCell.getValueArray(), oldCell.getValueOffset(), oldCell.getValueLength())</span> | 
 | <span class="source-line-no">4234</span><span id="line-4234">                .put(delta.getValueArray(), delta.getValueOffset(), delta.getValueLength())</span> | 
 | <span class="source-line-no">4235</span><span id="line-4235">                .array());</span> | 
 | <span class="source-line-no">4236</span><span id="line-4236">          }</span> | 
 | <span class="source-line-no">4237</span><span id="line-4237">          if (region.maxCellSize > 0) {</span> | 
 | <span class="source-line-no">4238</span><span id="line-4238">            int newCellSize = PrivateCellUtil.estimatedSerializedSizeOf(newCell);</span> | 
 | <span class="source-line-no">4239</span><span id="line-4239">            if (newCellSize > region.maxCellSize) {</span> | 
 | <span class="source-line-no">4240</span><span id="line-4240">              String msg = "Cell with size " + newCellSize + " exceeds limit of "</span> | 
 | <span class="source-line-no">4241</span><span id="line-4241">                + region.maxCellSize + " bytes in region " + this;</span> | 
 | <span class="source-line-no">4242</span><span id="line-4242">              LOG.debug(msg);</span> | 
 | <span class="source-line-no">4243</span><span id="line-4243">              throw new DoNotRetryIOException(msg);</span> | 
 | <span class="source-line-no">4244</span><span id="line-4244">            }</span> | 
 | <span class="source-line-no">4245</span><span id="line-4245">          }</span> | 
 | <span class="source-line-no">4246</span><span id="line-4246">          cellPairs.add(new Pair<>(currentValue, newCell));</span> | 
 | <span class="source-line-no">4247</span><span id="line-4247">          // Add to results to get returned to the Client. If null, cilent does not want results.</span> | 
 | <span class="source-line-no">4248</span><span id="line-4248">          if (results != null) {</span> | 
 | <span class="source-line-no">4249</span><span id="line-4249">            results.add(newCell);</span> | 
 | <span class="source-line-no">4250</span><span id="line-4250">          }</span> | 
 | <span class="source-line-no">4251</span><span id="line-4251">        }</span> | 
 | <span class="source-line-no">4252</span><span id="line-4252">        // Give coprocessors a chance to update the new cells before apply to WAL or memstore</span> | 
 | <span class="source-line-no">4253</span><span id="line-4253">        if (region.coprocessorHost != null) {</span> | 
 | <span class="source-line-no">4254</span><span id="line-4254">          // Here the operation must be increment or append.</span> | 
 | <span class="source-line-no">4255</span><span id="line-4255">          cellPairs = mutation instanceof Increment</span> | 
 | <span class="source-line-no">4256</span><span id="line-4256">            ? region.coprocessorHost.postIncrementBeforeWAL(mutation, (List) cellPairs)</span> | 
 | <span class="source-line-no">4257</span><span id="line-4257">            : region.coprocessorHost.postAppendBeforeWAL(mutation, (List) cellPairs);</span> | 
 | <span class="source-line-no">4258</span><span id="line-4258">        }</span> | 
 | <span class="source-line-no">4259</span><span id="line-4259">      }</span> | 
 | <span class="source-line-no">4260</span><span id="line-4260">      return cellPairs.stream().map(Pair::getSecond).collect(Collectors.toList());</span> | 
 | <span class="source-line-no">4261</span><span id="line-4261">    }</span> | 
 | <span class="source-line-no">4262</span><span id="line-4262"></span> | 
 | <span class="source-line-no">4263</span><span id="line-4263">    private static ExtendedCell reckonDelta(final ExtendedCell delta,</span> | 
 | <span class="source-line-no">4264</span><span id="line-4264">      final ExtendedCell currentCell, final byte[] columnFamily, final long now, Mutation mutation,</span> | 
 | <span class="source-line-no">4265</span><span id="line-4265">      Function<ExtendedCell, byte[]> supplier) throws IOException {</span> | 
 | <span class="source-line-no">4266</span><span id="line-4266">      // Forward any tags found on the delta.</span> | 
 | <span class="source-line-no">4267</span><span id="line-4267">      List<Tag> tags = TagUtil.carryForwardTags(delta);</span> | 
 | <span class="source-line-no">4268</span><span id="line-4268">      if (currentCell != null) {</span> | 
 | <span class="source-line-no">4269</span><span id="line-4269">        tags = TagUtil.carryForwardTags(tags, currentCell);</span> | 
 | <span class="source-line-no">4270</span><span id="line-4270">        tags = TagUtil.carryForwardTTLTag(tags, mutation.getTTL());</span> | 
 | <span class="source-line-no">4271</span><span id="line-4271">        byte[] newValue = supplier.apply(currentCell);</span> | 
 | <span class="source-line-no">4272</span><span id="line-4272">        return ExtendedCellBuilderFactory.create(CellBuilderType.SHALLOW_COPY)</span> | 
 | <span class="source-line-no">4273</span><span id="line-4273">          .setRow(mutation.getRow(), 0, mutation.getRow().length)</span> | 
 | <span class="source-line-no">4274</span><span id="line-4274">          .setFamily(columnFamily, 0, columnFamily.length)</span> | 
 | <span class="source-line-no">4275</span><span id="line-4275">          // copy the qualifier if the cell is located in shared memory.</span> | 
 | <span class="source-line-no">4276</span><span id="line-4276">          .setQualifier(CellUtil.cloneQualifier(delta))</span> | 
 | <span class="source-line-no">4277</span><span id="line-4277">          .setTimestamp(Math.max(currentCell.getTimestamp() + 1, now))</span> | 
 | <span class="source-line-no">4278</span><span id="line-4278">          .setType(KeyValue.Type.Put.getCode()).setValue(newValue, 0, newValue.length)</span> | 
 | <span class="source-line-no">4279</span><span id="line-4279">          .setTags(TagUtil.fromList(tags)).build();</span> | 
 | <span class="source-line-no">4280</span><span id="line-4280">      } else {</span> | 
 | <span class="source-line-no">4281</span><span id="line-4281">        tags = TagUtil.carryForwardTTLTag(tags, mutation.getTTL());</span> | 
 | <span class="source-line-no">4282</span><span id="line-4282">        PrivateCellUtil.updateLatestStamp(delta, now);</span> | 
 | <span class="source-line-no">4283</span><span id="line-4283">        ExtendedCell deltaCell = (ExtendedCell) delta;</span> | 
 | <span class="source-line-no">4284</span><span id="line-4284">        return CollectionUtils.isEmpty(tags)</span> | 
 | <span class="source-line-no">4285</span><span id="line-4285">          ? deltaCell</span> | 
 | <span class="source-line-no">4286</span><span id="line-4286">          : PrivateCellUtil.createCell(deltaCell, tags);</span> | 
 | <span class="source-line-no">4287</span><span id="line-4287">      }</span> | 
 | <span class="source-line-no">4288</span><span id="line-4288">    }</span> | 
 | <span class="source-line-no">4289</span><span id="line-4289"></span> | 
 | <span class="source-line-no">4290</span><span id="line-4290">    /** Returns Get the long out of the passed in Cell */</span> | 
 | <span class="source-line-no">4291</span><span id="line-4291">    private static long getLongValue(final Cell cell) throws DoNotRetryIOException {</span> | 
 | <span class="source-line-no">4292</span><span id="line-4292">      int len = cell.getValueLength();</span> | 
 | <span class="source-line-no">4293</span><span id="line-4293">      if (len != Bytes.SIZEOF_LONG) {</span> | 
 | <span class="source-line-no">4294</span><span id="line-4294">        // throw DoNotRetryIOException instead of IllegalArgumentException</span> | 
 | <span class="source-line-no">4295</span><span id="line-4295">        throw new DoNotRetryIOException("Field is not a long, it's " + len + " bytes wide");</span> | 
 | <span class="source-line-no">4296</span><span id="line-4296">      }</span> | 
 | <span class="source-line-no">4297</span><span id="line-4297">      return PrivateCellUtil.getValueAsLong(cell);</span> | 
 | <span class="source-line-no">4298</span><span id="line-4298">    }</span> | 
 | <span class="source-line-no">4299</span><span id="line-4299"></span> | 
 | <span class="source-line-no">4300</span><span id="line-4300">    @Override</span> | 
 | <span class="source-line-no">4301</span><span id="line-4301">    public List<Pair<NonceKey, WALEdit>></span> | 
 | <span class="source-line-no">4302</span><span id="line-4302">      buildWALEdits(final MiniBatchOperationInProgress<Mutation> miniBatchOp) throws IOException {</span> | 
 | <span class="source-line-no">4303</span><span id="line-4303">      List<Pair<NonceKey, WALEdit>> walEdits = super.buildWALEdits(miniBatchOp);</span> | 
 | <span class="source-line-no">4304</span><span id="line-4304">      // for MutationBatchOperation, more than one nonce is not allowed</span> | 
 | <span class="source-line-no">4305</span><span id="line-4305">      if (walEdits.size() > 1) {</span> | 
 | <span class="source-line-no">4306</span><span id="line-4306">        throw new IOException("Found multiple nonce keys per batch!");</span> | 
 | <span class="source-line-no">4307</span><span id="line-4307">      }</span> | 
 | <span class="source-line-no">4308</span><span id="line-4308">      return walEdits;</span> | 
 | <span class="source-line-no">4309</span><span id="line-4309">    }</span> | 
 | <span class="source-line-no">4310</span><span id="line-4310"></span> | 
 | <span class="source-line-no">4311</span><span id="line-4311">    /**</span> | 
 | <span class="source-line-no">4312</span><span id="line-4312">     * Here is for HBASE-26993,in order to make the new framework for region replication could work</span> | 
 | <span class="source-line-no">4313</span><span id="line-4313">     * for SKIP_WAL, we save the {@link Mutation} which {@link Mutation#getDurability} is</span> | 
 | <span class="source-line-no">4314</span><span id="line-4314">     * {@link Durability#SKIP_WAL} in miniBatchOp.</span> | 
 | <span class="source-line-no">4315</span><span id="line-4315">     */</span> | 
 | <span class="source-line-no">4316</span><span id="line-4316">    @Override</span> | 
 | <span class="source-line-no">4317</span><span id="line-4317">    protected void cacheSkipWALMutationForRegionReplication(</span> | 
 | <span class="source-line-no">4318</span><span id="line-4318">      MiniBatchOperationInProgress<Mutation> miniBatchOp,</span> | 
 | <span class="source-line-no">4319</span><span id="line-4319">      List<Pair<NonceKey, WALEdit>> nonceKeyAndWALEdits,</span> | 
 | <span class="source-line-no">4320</span><span id="line-4320">      Map<byte[], List<ExtendedCell>> familyCellMap) {</span> | 
 | <span class="source-line-no">4321</span><span id="line-4321">      if (!this.regionReplicateEnable) {</span> | 
 | <span class="source-line-no">4322</span><span id="line-4322">        return;</span> | 
 | <span class="source-line-no">4323</span><span id="line-4323">      }</span> | 
 | <span class="source-line-no">4324</span><span id="line-4324"></span> | 
 | <span class="source-line-no">4325</span><span id="line-4325">      WALEdit walEditForReplicateIfExistsSkipWAL =</span> | 
 | <span class="source-line-no">4326</span><span id="line-4326">        miniBatchOp.getWalEditForReplicateIfExistsSkipWAL();</span> | 
 | <span class="source-line-no">4327</span><span id="line-4327">      /**</span> | 
 | <span class="source-line-no">4328</span><span id="line-4328">       * When there is a SKIP_WAL {@link Mutation},we create a new {@link WALEdit} for replicating</span> | 
 | <span class="source-line-no">4329</span><span id="line-4329">       * to region replica,first we fill the existing {@link WALEdit} to it and then add the</span> | 
 | <span class="source-line-no">4330</span><span id="line-4330">       * {@link Mutation} which is SKIP_WAL to it.</span> | 
 | <span class="source-line-no">4331</span><span id="line-4331">       */</span> | 
 | <span class="source-line-no">4332</span><span id="line-4332">      if (walEditForReplicateIfExistsSkipWAL == null) {</span> | 
 | <span class="source-line-no">4333</span><span id="line-4333">        walEditForReplicateIfExistsSkipWAL =</span> | 
 | <span class="source-line-no">4334</span><span id="line-4334">          this.createWALEditForReplicateSkipWAL(miniBatchOp, nonceKeyAndWALEdits);</span> | 
 | <span class="source-line-no">4335</span><span id="line-4335">        miniBatchOp.setWalEditForReplicateIfExistsSkipWAL(walEditForReplicateIfExistsSkipWAL);</span> | 
 | <span class="source-line-no">4336</span><span id="line-4336">      }</span> | 
 | <span class="source-line-no">4337</span><span id="line-4337">      WALEditInternalHelper.addMap(walEditForReplicateIfExistsSkipWAL, familyCellMap);</span> | 
 | <span class="source-line-no">4338</span><span id="line-4338"></span> | 
 | <span class="source-line-no">4339</span><span id="line-4339">    }</span> | 
 | <span class="source-line-no">4340</span><span id="line-4340"></span> | 
 | <span class="source-line-no">4341</span><span id="line-4341">    private WALEdit createWALEditForReplicateSkipWAL(</span> | 
 | <span class="source-line-no">4342</span><span id="line-4342">      MiniBatchOperationInProgress<Mutation> miniBatchOp,</span> | 
 | <span class="source-line-no">4343</span><span id="line-4343">      List<Pair<NonceKey, WALEdit>> nonceKeyAndWALEdits) {</span> | 
 | <span class="source-line-no">4344</span><span id="line-4344">      if (nonceKeyAndWALEdits.isEmpty()) {</span> | 
 | <span class="source-line-no">4345</span><span id="line-4345">        return this.createWALEdit(miniBatchOp);</span> | 
 | <span class="source-line-no">4346</span><span id="line-4346">      }</span> | 
 | <span class="source-line-no">4347</span><span id="line-4347">      // for MutationBatchOperation, more than one nonce is not allowed</span> | 
 | <span class="source-line-no">4348</span><span id="line-4348">      assert nonceKeyAndWALEdits.size() == 1;</span> | 
 | <span class="source-line-no">4349</span><span id="line-4349">      WALEdit currentWALEdit = nonceKeyAndWALEdits.get(0).getSecond();</span> | 
 | <span class="source-line-no">4350</span><span id="line-4350">      return new WALEdit(currentWALEdit);</span> | 
 | <span class="source-line-no">4351</span><span id="line-4351">    }</span> | 
 | <span class="source-line-no">4352</span><span id="line-4352"></span> | 
 | <span class="source-line-no">4353</span><span id="line-4353">    @Override</span> | 
 | <span class="source-line-no">4354</span><span id="line-4354">    protected void addNonSkipWALMutationsToWALEdit(</span> | 
 | <span class="source-line-no">4355</span><span id="line-4355">      final MiniBatchOperationInProgress<Mutation> miniBatchOp, WALEdit walEdit,</span> | 
 | <span class="source-line-no">4356</span><span id="line-4356">      List<ExtendedCell> cellsFromCP, Map<byte[], List<ExtendedCell>> familyCellMap) {</span> | 
 | <span class="source-line-no">4357</span><span id="line-4357">      super.addNonSkipWALMutationsToWALEdit(miniBatchOp, walEdit, cellsFromCP, familyCellMap);</span> | 
 | <span class="source-line-no">4358</span><span id="line-4358">      WALEdit walEditForReplicateIfExistsSkipWAL =</span> | 
 | <span class="source-line-no">4359</span><span id="line-4359">        miniBatchOp.getWalEditForReplicateIfExistsSkipWAL();</span> | 
 | <span class="source-line-no">4360</span><span id="line-4360">      if (walEditForReplicateIfExistsSkipWAL == null) {</span> | 
 | <span class="source-line-no">4361</span><span id="line-4361">        return;</span> | 
 | <span class="source-line-no">4362</span><span id="line-4362">      }</span> | 
 | <span class="source-line-no">4363</span><span id="line-4363">      /**</span> | 
 | <span class="source-line-no">4364</span><span id="line-4364">       * When walEditForReplicateIfExistsSkipWAL is not null,it means there exists SKIP_WAL</span> | 
 | <span class="source-line-no">4365</span><span id="line-4365">       * {@link Mutation} and we create a new {@link WALEdit} in</span> | 
 | <span class="source-line-no">4366</span><span id="line-4366">       * {@link MutationBatchOperation#cacheSkipWALMutationForReplicateRegionReplica} for</span> | 
 | <span class="source-line-no">4367</span><span id="line-4367">       * replicating to region replica, so here we also add non SKIP_WAL{@link Mutation}s to</span> | 
 | <span class="source-line-no">4368</span><span id="line-4368">       * walEditForReplicateIfExistsSkipWAL.</span> | 
 | <span class="source-line-no">4369</span><span id="line-4369">       */</span> | 
 | <span class="source-line-no">4370</span><span id="line-4370">      doAddCellsToWALEdit(walEditForReplicateIfExistsSkipWAL, cellsFromCP, familyCellMap);</span> | 
 | <span class="source-line-no">4371</span><span id="line-4371">    }</span> | 
 | <span class="source-line-no">4372</span><span id="line-4372"></span> | 
 | <span class="source-line-no">4373</span><span id="line-4373">    @Override</span> | 
 | <span class="source-line-no">4374</span><span id="line-4374">    public WriteEntry writeMiniBatchOperationsToMemStore(</span> | 
 | <span class="source-line-no">4375</span><span id="line-4375">      final MiniBatchOperationInProgress<Mutation> miniBatchOp, @Nullable WriteEntry writeEntry,</span> | 
 | <span class="source-line-no">4376</span><span id="line-4376">      long now) throws IOException {</span> | 
 | <span class="source-line-no">4377</span><span id="line-4377">      boolean newWriteEntry = false;</span> | 
 | <span class="source-line-no">4378</span><span id="line-4378">      if (writeEntry == null) {</span> | 
 | <span class="source-line-no">4379</span><span id="line-4379">        writeEntry = region.mvcc.begin();</span> | 
 | <span class="source-line-no">4380</span><span id="line-4380">        newWriteEntry = true;</span> | 
 | <span class="source-line-no">4381</span><span id="line-4381">      }</span> | 
 | <span class="source-line-no">4382</span><span id="line-4382">      super.writeMiniBatchOperationsToMemStore(miniBatchOp, writeEntry.getWriteNumber());</span> | 
 | <span class="source-line-no">4383</span><span id="line-4383">      if (newWriteEntry) {</span> | 
 | <span class="source-line-no">4384</span><span id="line-4384">        /**</span> | 
 | <span class="source-line-no">4385</span><span id="line-4385">         * Here is for HBASE-26993 case 2,all {@link Mutation}s are {@link Durability#SKIP_WAL}. In</span> | 
 | <span class="source-line-no">4386</span><span id="line-4386">         * order to make the new framework for region replication could work for SKIP_WAL,because</span> | 
 | <span class="source-line-no">4387</span><span id="line-4387">         * there is no {@link RegionReplicationSink#add} attached in {@link HRegion#doWALAppend},so</span> | 
 | <span class="source-line-no">4388</span><span id="line-4388">         * here we get {@link WALEdit} from</span> | 
 | <span class="source-line-no">4389</span><span id="line-4389">         * {@link MiniBatchOperationInProgress#getWalEditForReplicateIfExistsSkipWAL} and attach</span> | 
 | <span class="source-line-no">4390</span><span id="line-4390">         * {@link RegionReplicationSink#add} to the new mvcc writeEntry.</span> | 
 | <span class="source-line-no">4391</span><span id="line-4391">         */</span> | 
 | <span class="source-line-no">4392</span><span id="line-4392">        attachRegionReplicationToMVCCEntry(miniBatchOp, writeEntry, now);</span> | 
 | <span class="source-line-no">4393</span><span id="line-4393">      }</span> | 
 | <span class="source-line-no">4394</span><span id="line-4394">      return writeEntry;</span> | 
 | <span class="source-line-no">4395</span><span id="line-4395">    }</span> | 
 | <span class="source-line-no">4396</span><span id="line-4396"></span> | 
 | <span class="source-line-no">4397</span><span id="line-4397">    private WALKeyImpl createWALKey(long now) {</span> | 
 | <span class="source-line-no">4398</span><span id="line-4398">      // for MutationBatchOperation,isReplay is false.</span> | 
 | <span class="source-line-no">4399</span><span id="line-4399">      return this.region.createWALKeyForWALAppend(false, this, now, this.nonceGroup, this.nonce);</span> | 
 | <span class="source-line-no">4400</span><span id="line-4400">    }</span> | 
 | <span class="source-line-no">4401</span><span id="line-4401"></span> | 
 | <span class="source-line-no">4402</span><span id="line-4402">    /**</span> | 
 | <span class="source-line-no">4403</span><span id="line-4403">     * Create {@link WALKeyImpl} and get {@link WALEdit} from miniBatchOp and attach</span> | 
 | <span class="source-line-no">4404</span><span id="line-4404">     * {@link RegionReplicationSink#add} to the mvccWriteEntry.</span> | 
 | <span class="source-line-no">4405</span><span id="line-4405">     */</span> | 
 | <span class="source-line-no">4406</span><span id="line-4406">    private void attachRegionReplicationToMVCCEntry(</span> | 
 | <span class="source-line-no">4407</span><span id="line-4407">      final MiniBatchOperationInProgress<Mutation> miniBatchOp, WriteEntry mvccWriteEntry, long now)</span> | 
 | <span class="source-line-no">4408</span><span id="line-4408">      throws IOException {</span> | 
 | <span class="source-line-no">4409</span><span id="line-4409">      if (!this.regionReplicateEnable) {</span> | 
 | <span class="source-line-no">4410</span><span id="line-4410">        return;</span> | 
 | <span class="source-line-no">4411</span><span id="line-4411">      }</span> | 
 | <span class="source-line-no">4412</span><span id="line-4412">      assert !mvccWriteEntry.getCompletionAction().isPresent();</span> | 
 | <span class="source-line-no">4413</span><span id="line-4413"></span> | 
 | <span class="source-line-no">4414</span><span id="line-4414">      final WALKeyImpl walKey = this.createWALKey(now);</span> | 
 | <span class="source-line-no">4415</span><span id="line-4415">      walKey.setWriteEntry(mvccWriteEntry);</span> | 
 | <span class="source-line-no">4416</span><span id="line-4416">      region.doAttachReplicateRegionReplicaAction(walKey,</span> | 
 | <span class="source-line-no">4417</span><span id="line-4417">        miniBatchOp.getWalEditForReplicateIfExistsSkipWAL(), mvccWriteEntry);</span> | 
 | <span class="source-line-no">4418</span><span id="line-4418">    }</span> | 
 | <span class="source-line-no">4419</span><span id="line-4419"></span> | 
 | <span class="source-line-no">4420</span><span id="line-4420">    @Override</span> | 
 | <span class="source-line-no">4421</span><span id="line-4421">    public void completeMiniBatchOperations(</span> | 
 | <span class="source-line-no">4422</span><span id="line-4422">      final MiniBatchOperationInProgress<Mutation> miniBatchOp, final WriteEntry writeEntry)</span> | 
 | <span class="source-line-no">4423</span><span id="line-4423">      throws IOException {</span> | 
 | <span class="source-line-no">4424</span><span id="line-4424">      // TODO: can it be done after completing mvcc?</span> | 
 | <span class="source-line-no">4425</span><span id="line-4425">      // calling the post CP hook for batch mutation</span> | 
 | <span class="source-line-no">4426</span><span id="line-4426">      if (region.coprocessorHost != null) {</span> | 
 | <span class="source-line-no">4427</span><span id="line-4427">        region.coprocessorHost.postBatchMutate(miniBatchOp);</span> | 
 | <span class="source-line-no">4428</span><span id="line-4428">      }</span> | 
 | <span class="source-line-no">4429</span><span id="line-4429">      super.completeMiniBatchOperations(miniBatchOp, writeEntry);</span> | 
 | <span class="source-line-no">4430</span><span id="line-4430"></span> | 
 | <span class="source-line-no">4431</span><span id="line-4431">      if (nonce != HConstants.NO_NONCE) {</span> | 
 | <span class="source-line-no">4432</span><span id="line-4432">        if (region.rsServices != null && region.rsServices.getNonceManager() != null) {</span> | 
 | <span class="source-line-no">4433</span><span id="line-4433">          region.rsServices.getNonceManager().addMvccToOperationContext(nonceGroup, nonce,</span> | 
 | <span class="source-line-no">4434</span><span id="line-4434">            writeEntry.getWriteNumber());</span> | 
 | <span class="source-line-no">4435</span><span id="line-4435">        }</span> | 
 | <span class="source-line-no">4436</span><span id="line-4436">      }</span> | 
 | <span class="source-line-no">4437</span><span id="line-4437">    }</span> | 
 | <span class="source-line-no">4438</span><span id="line-4438"></span> | 
 | <span class="source-line-no">4439</span><span id="line-4439">    @Override</span> | 
 | <span class="source-line-no">4440</span><span id="line-4440">    public void doPostOpCleanupForMiniBatch(MiniBatchOperationInProgress<Mutation> miniBatchOp,</span> | 
 | <span class="source-line-no">4441</span><span id="line-4441">      final WALEdit walEdit, boolean success) throws IOException {</span> | 
 | <span class="source-line-no">4442</span><span id="line-4442"></span> | 
 | <span class="source-line-no">4443</span><span id="line-4443">      super.doPostOpCleanupForMiniBatch(miniBatchOp, walEdit, success);</span> | 
 | <span class="source-line-no">4444</span><span id="line-4444">      if (miniBatchOp != null) {</span> | 
 | <span class="source-line-no">4445</span><span id="line-4445">        // synced so that the coprocessor contract is adhered to.</span> | 
 | <span class="source-line-no">4446</span><span id="line-4446">        if (region.coprocessorHost != null) {</span> | 
 | <span class="source-line-no">4447</span><span id="line-4447">          visitBatchOperations(false, miniBatchOp.getLastIndexExclusive(), (int i) -> {</span> | 
 | <span class="source-line-no">4448</span><span id="line-4448">            // only for successful puts/deletes/increments/appends</span> | 
 | <span class="source-line-no">4449</span><span id="line-4449">            if (retCodeDetails[i].getOperationStatusCode() == OperationStatusCode.SUCCESS) {</span> | 
 | <span class="source-line-no">4450</span><span id="line-4450">              Mutation m = getMutation(i);</span> | 
 | <span class="source-line-no">4451</span><span id="line-4451">              if (m instanceof Put) {</span> | 
 | <span class="source-line-no">4452</span><span id="line-4452">                region.coprocessorHost.postPut((Put) m, walEdit);</span> | 
 | <span class="source-line-no">4453</span><span id="line-4453">              } else if (m instanceof Delete) {</span> | 
 | <span class="source-line-no">4454</span><span id="line-4454">                region.coprocessorHost.postDelete((Delete) m, walEdit);</span> | 
 | <span class="source-line-no">4455</span><span id="line-4455">              } else if (m instanceof Increment) {</span> | 
 | <span class="source-line-no">4456</span><span id="line-4456">                Result result =</span> | 
 | <span class="source-line-no">4457</span><span id="line-4457">                  region.getCoprocessorHost().postIncrement((Increment) m, results[i], walEdit);</span> | 
 | <span class="source-line-no">4458</span><span id="line-4458">                if (result != results[i]) {</span> | 
 | <span class="source-line-no">4459</span><span id="line-4459">                  retCodeDetails[i] =</span> | 
 | <span class="source-line-no">4460</span><span id="line-4460">                    new OperationStatus(retCodeDetails[i].getOperationStatusCode(), result);</span> | 
 | <span class="source-line-no">4461</span><span id="line-4461">                }</span> | 
 | <span class="source-line-no">4462</span><span id="line-4462">              } else if (m instanceof Append) {</span> | 
 | <span class="source-line-no">4463</span><span id="line-4463">                Result result =</span> | 
 | <span class="source-line-no">4464</span><span id="line-4464">                  region.getCoprocessorHost().postAppend((Append) m, results[i], walEdit);</span> | 
 | <span class="source-line-no">4465</span><span id="line-4465">                if (result != results[i]) {</span> | 
 | <span class="source-line-no">4466</span><span id="line-4466">                  retCodeDetails[i] =</span> | 
 | <span class="source-line-no">4467</span><span id="line-4467">                    new OperationStatus(retCodeDetails[i].getOperationStatusCode(), result);</span> | 
 | <span class="source-line-no">4468</span><span id="line-4468">                }</span> | 
 | <span class="source-line-no">4469</span><span id="line-4469">              }</span> | 
 | <span class="source-line-no">4470</span><span id="line-4470">            }</span> | 
 | <span class="source-line-no">4471</span><span id="line-4471">            return true;</span> | 
 | <span class="source-line-no">4472</span><span id="line-4472">          });</span> | 
 | <span class="source-line-no">4473</span><span id="line-4473">        }</span> | 
 | <span class="source-line-no">4474</span><span id="line-4474"></span> | 
 | <span class="source-line-no">4475</span><span id="line-4475">        // For nonce operations</span> | 
 | <span class="source-line-no">4476</span><span id="line-4476">        if (canProceed && nonce != HConstants.NO_NONCE) {</span> | 
 | <span class="source-line-no">4477</span><span id="line-4477">          boolean[] areAllIncrementsAndAppendsSuccessful = new boolean[] { true };</span> | 
 | <span class="source-line-no">4478</span><span id="line-4478">          visitBatchOperations(false, miniBatchOp.getLastIndexExclusive(), (int i) -> {</span> | 
 | <span class="source-line-no">4479</span><span id="line-4479">            Mutation mutation = getMutation(i);</span> | 
 | <span class="source-line-no">4480</span><span id="line-4480">            if (mutation instanceof Increment || mutation instanceof Append) {</span> | 
 | <span class="source-line-no">4481</span><span id="line-4481">              if (retCodeDetails[i].getOperationStatusCode() != OperationStatusCode.SUCCESS) {</span> | 
 | <span class="source-line-no">4482</span><span id="line-4482">                areAllIncrementsAndAppendsSuccessful[0] = false;</span> | 
 | <span class="source-line-no">4483</span><span id="line-4483">                return false;</span> | 
 | <span class="source-line-no">4484</span><span id="line-4484">              }</span> | 
 | <span class="source-line-no">4485</span><span id="line-4485">            }</span> | 
 | <span class="source-line-no">4486</span><span id="line-4486">            return true;</span> | 
 | <span class="source-line-no">4487</span><span id="line-4487">          });</span> | 
 | <span class="source-line-no">4488</span><span id="line-4488">          endNonceOperation(areAllIncrementsAndAppendsSuccessful[0]);</span> | 
 | <span class="source-line-no">4489</span><span id="line-4489">        }</span> | 
 | <span class="source-line-no">4490</span><span id="line-4490"></span> | 
 | <span class="source-line-no">4491</span><span id="line-4491">        // See if the column families were consistent through the whole thing.</span> | 
 | <span class="source-line-no">4492</span><span id="line-4492">        // if they were then keep them. If they were not then pass a null.</span> | 
 | <span class="source-line-no">4493</span><span id="line-4493">        // null will be treated as unknown.</span> | 
 | <span class="source-line-no">4494</span><span id="line-4494">        // Total time taken might be involving Puts, Deletes, Increments and Appends.</span> | 
 | <span class="source-line-no">4495</span><span id="line-4495">        // Split the time for puts and deletes based on the total number of Puts, Deletes,</span> | 
 | <span class="source-line-no">4496</span><span id="line-4496">        // Increments and Appends.</span> | 
 | <span class="source-line-no">4497</span><span id="line-4497">        if (region.metricsRegion != null) {</span> | 
 | <span class="source-line-no">4498</span><span id="line-4498">          if (miniBatchOp.getNumOfPuts() > 0) {</span> | 
 | <span class="source-line-no">4499</span><span id="line-4499">            // There were some Puts in the batch.</span> | 
 | <span class="source-line-no">4500</span><span id="line-4500">            region.metricsRegion.updatePut();</span> | 
 | <span class="source-line-no">4501</span><span id="line-4501">          }</span> | 
 | <span class="source-line-no">4502</span><span id="line-4502">          if (miniBatchOp.getNumOfDeletes() > 0) {</span> | 
 | <span class="source-line-no">4503</span><span id="line-4503">            // There were some Deletes in the batch.</span> | 
 | <span class="source-line-no">4504</span><span id="line-4504">            region.metricsRegion.updateDelete();</span> | 
 | <span class="source-line-no">4505</span><span id="line-4505">          }</span> | 
 | <span class="source-line-no">4506</span><span id="line-4506">          if (miniBatchOp.getNumOfIncrements() > 0) {</span> | 
 | <span class="source-line-no">4507</span><span id="line-4507">            // There were some Increments in the batch.</span> | 
 | <span class="source-line-no">4508</span><span id="line-4508">            region.metricsRegion.updateIncrement();</span> | 
 | <span class="source-line-no">4509</span><span id="line-4509">          }</span> | 
 | <span class="source-line-no">4510</span><span id="line-4510">          if (miniBatchOp.getNumOfAppends() > 0) {</span> | 
 | <span class="source-line-no">4511</span><span id="line-4511">            // There were some Appends in the batch.</span> | 
 | <span class="source-line-no">4512</span><span id="line-4512">            region.metricsRegion.updateAppend();</span> | 
 | <span class="source-line-no">4513</span><span id="line-4513">          }</span> | 
 | <span class="source-line-no">4514</span><span id="line-4514">        }</span> | 
 | <span class="source-line-no">4515</span><span id="line-4515">      }</span> | 
 | <span class="source-line-no">4516</span><span id="line-4516"></span> | 
 | <span class="source-line-no">4517</span><span id="line-4517">      if (region.coprocessorHost != null) {</span> | 
 | <span class="source-line-no">4518</span><span id="line-4518">        // call the coprocessor hook to do any finalization steps after the put is done</span> | 
 | <span class="source-line-no">4519</span><span id="line-4519">        region.coprocessorHost.postBatchMutateIndispensably(</span> | 
 | <span class="source-line-no">4520</span><span id="line-4520">          miniBatchOp != null ? miniBatchOp : createMiniBatch(size(), 0), success);</span> | 
 | <span class="source-line-no">4521</span><span id="line-4521">      }</span> | 
 | <span class="source-line-no">4522</span><span id="line-4522">    }</span> | 
 | <span class="source-line-no">4523</span><span id="line-4523"></span> | 
 | <span class="source-line-no">4524</span><span id="line-4524">    /**</span> | 
 | <span class="source-line-no">4525</span><span id="line-4525">     * Runs prePut/preDelete/preIncrement/preAppend coprocessor hook for input mutation in a batch</span> | 
 | <span class="source-line-no">4526</span><span id="line-4526">     * @param metrics Array of 2 ints. index 0: count of puts, index 1: count of deletes, index 2:</span> | 
 | <span class="source-line-no">4527</span><span id="line-4527">     *                count of increments and 3: count of appends</span> | 
 | <span class="source-line-no">4528</span><span id="line-4528">     */</span> | 
 | <span class="source-line-no">4529</span><span id="line-4529">    private void callPreMutateCPHook(int index, final WALEdit walEdit, final int[] metrics)</span> | 
 | <span class="source-line-no">4530</span><span id="line-4530">      throws IOException {</span> | 
 | <span class="source-line-no">4531</span><span id="line-4531">      Mutation m = getMutation(index);</span> | 
 | <span class="source-line-no">4532</span><span id="line-4532">      if (m instanceof Put) {</span> | 
 | <span class="source-line-no">4533</span><span id="line-4533">        if (region.coprocessorHost.prePut((Put) m, walEdit)) {</span> | 
 | <span class="source-line-no">4534</span><span id="line-4534">          // pre hook says skip this Put</span> | 
 | <span class="source-line-no">4535</span><span id="line-4535">          // mark as success and skip in doMiniBatchMutation</span> | 
 | <span class="source-line-no">4536</span><span id="line-4536">          metrics[0]++;</span> | 
 | <span class="source-line-no">4537</span><span id="line-4537">          retCodeDetails[index] = OperationStatus.SUCCESS;</span> | 
 | <span class="source-line-no">4538</span><span id="line-4538">        }</span> | 
 | <span class="source-line-no">4539</span><span id="line-4539">      } else if (m instanceof Delete) {</span> | 
 | <span class="source-line-no">4540</span><span id="line-4540">        Delete curDel = (Delete) m;</span> | 
 | <span class="source-line-no">4541</span><span id="line-4541">        if (curDel.getFamilyCellMap().isEmpty()) {</span> | 
 | <span class="source-line-no">4542</span><span id="line-4542">          // handle deleting a row case</span> | 
 | <span class="source-line-no">4543</span><span id="line-4543">          // TODO: prepareDelete() has been called twice, before and after preDelete() CP hook.</span> | 
 | <span class="source-line-no">4544</span><span id="line-4544">          // Can this be avoided?</span> | 
 | <span class="source-line-no">4545</span><span id="line-4545">          region.prepareDelete(curDel);</span> | 
 | <span class="source-line-no">4546</span><span id="line-4546">        }</span> | 
 | <span class="source-line-no">4547</span><span id="line-4547">        if (region.coprocessorHost.preDelete(curDel, walEdit)) {</span> | 
 | <span class="source-line-no">4548</span><span id="line-4548">          // pre hook says skip this Delete</span> | 
 | <span class="source-line-no">4549</span><span id="line-4549">          // mark as success and skip in doMiniBatchMutation</span> | 
 | <span class="source-line-no">4550</span><span id="line-4550">          metrics[1]++;</span> | 
 | <span class="source-line-no">4551</span><span id="line-4551">          retCodeDetails[index] = OperationStatus.SUCCESS;</span> | 
 | <span class="source-line-no">4552</span><span id="line-4552">        }</span> | 
 | <span class="source-line-no">4553</span><span id="line-4553">      } else if (m instanceof Increment) {</span> | 
 | <span class="source-line-no">4554</span><span id="line-4554">        Increment increment = (Increment) m;</span> | 
 | <span class="source-line-no">4555</span><span id="line-4555">        Result result = region.coprocessorHost.preIncrement(increment, walEdit);</span> | 
 | <span class="source-line-no">4556</span><span id="line-4556">        if (result != null) {</span> | 
 | <span class="source-line-no">4557</span><span id="line-4557">          // pre hook says skip this Increment</span> | 
 | <span class="source-line-no">4558</span><span id="line-4558">          // mark as success and skip in doMiniBatchMutation</span> | 
 | <span class="source-line-no">4559</span><span id="line-4559">          metrics[2]++;</span> | 
 | <span class="source-line-no">4560</span><span id="line-4560">          retCodeDetails[index] = new OperationStatus(OperationStatusCode.SUCCESS, result);</span> | 
 | <span class="source-line-no">4561</span><span id="line-4561">        }</span> | 
 | <span class="source-line-no">4562</span><span id="line-4562">      } else if (m instanceof Append) {</span> | 
 | <span class="source-line-no">4563</span><span id="line-4563">        Append append = (Append) m;</span> | 
 | <span class="source-line-no">4564</span><span id="line-4564">        Result result = region.coprocessorHost.preAppend(append, walEdit);</span> | 
 | <span class="source-line-no">4565</span><span id="line-4565">        if (result != null) {</span> | 
 | <span class="source-line-no">4566</span><span id="line-4566">          // pre hook says skip this Append</span> | 
 | <span class="source-line-no">4567</span><span id="line-4567">          // mark as success and skip in doMiniBatchMutation</span> | 
 | <span class="source-line-no">4568</span><span id="line-4568">          metrics[3]++;</span> | 
 | <span class="source-line-no">4569</span><span id="line-4569">          retCodeDetails[index] = new OperationStatus(OperationStatusCode.SUCCESS, result);</span> | 
 | <span class="source-line-no">4570</span><span id="line-4570">        }</span> | 
 | <span class="source-line-no">4571</span><span id="line-4571">      } else {</span> | 
 | <span class="source-line-no">4572</span><span id="line-4572">        String msg = "Put/Delete/Increment/Append mutations only supported in a batch";</span> | 
 | <span class="source-line-no">4573</span><span id="line-4573">        retCodeDetails[index] = new OperationStatus(OperationStatusCode.FAILURE, msg);</span> | 
 | <span class="source-line-no">4574</span><span id="line-4574">        if (isAtomic()) { // fail, atomic means all or none</span> | 
 | <span class="source-line-no">4575</span><span id="line-4575">          throw new IOException(msg);</span> | 
 | <span class="source-line-no">4576</span><span id="line-4576">        }</span> | 
 | <span class="source-line-no">4577</span><span id="line-4577">      }</span> | 
 | <span class="source-line-no">4578</span><span id="line-4578">    }</span> | 
 | <span class="source-line-no">4579</span><span id="line-4579"></span> | 
 | <span class="source-line-no">4580</span><span id="line-4580">    // TODO Support Increment/Append operations</span> | 
 | <span class="source-line-no">4581</span><span id="line-4581">    private void checkAndMergeCPMutations(final MiniBatchOperationInProgress<Mutation> miniBatchOp,</span> | 
 | <span class="source-line-no">4582</span><span id="line-4582">      final List<RowLock> acquiredRowLocks, final long timestamp) throws IOException {</span> | 
 | <span class="source-line-no">4583</span><span id="line-4583">      visitBatchOperations(true, nextIndexToProcess + miniBatchOp.size(), (int i) -> {</span> | 
 | <span class="source-line-no">4584</span><span id="line-4584">        // we pass (i - firstIndex) below since the call expects a relative index</span> | 
 | <span class="source-line-no">4585</span><span id="line-4585">        Mutation[] cpMutations = miniBatchOp.getOperationsFromCoprocessors(i - nextIndexToProcess);</span> | 
 | <span class="source-line-no">4586</span><span id="line-4586">        if (cpMutations == null) {</span> | 
 | <span class="source-line-no">4587</span><span id="line-4587">          return true;</span> | 
 | <span class="source-line-no">4588</span><span id="line-4588">        }</span> | 
 | <span class="source-line-no">4589</span><span id="line-4589">        // Else Coprocessor added more Mutations corresponding to the Mutation at this index.</span> | 
 | <span class="source-line-no">4590</span><span id="line-4590">        Mutation mutation = getMutation(i);</span> | 
 | <span class="source-line-no">4591</span><span id="line-4591">        for (Mutation cpMutation : cpMutations) {</span> | 
 | <span class="source-line-no">4592</span><span id="line-4592">          this.checkAndPrepareMutation(cpMutation, timestamp);</span> | 
 | <span class="source-line-no">4593</span><span id="line-4593"></span> | 
 | <span class="source-line-no">4594</span><span id="line-4594">          // Acquire row locks. If not, the whole batch will fail.</span> | 
 | <span class="source-line-no">4595</span><span id="line-4595">          acquiredRowLocks.add(region.getRowLock(cpMutation.getRow(), true, null));</span> | 
 | <span class="source-line-no">4596</span><span id="line-4596"></span> | 
 | <span class="source-line-no">4597</span><span id="line-4597">          // Returned mutations from coprocessor correspond to the Mutation at index i. We can</span> | 
 | <span class="source-line-no">4598</span><span id="line-4598">          // directly add the cells from those mutations to the familyMaps of this mutation.</span> | 
 | <span class="source-line-no">4599</span><span id="line-4599">          Map<byte[], List<ExtendedCell>> cpFamilyMap =</span> | 
 | <span class="source-line-no">4600</span><span id="line-4600">            ClientInternalHelper.getExtendedFamilyCellMap(cpMutation);</span> | 
 | <span class="source-line-no">4601</span><span id="line-4601">          region.rewriteCellTags(cpFamilyMap, mutation);</span> | 
 | <span class="source-line-no">4602</span><span id="line-4602">          // will get added to the memStore later</span> | 
 | <span class="source-line-no">4603</span><span id="line-4603">          mergeFamilyMaps(familyCellMaps[i], cpFamilyMap);</span> | 
 | <span class="source-line-no">4604</span><span id="line-4604"></span> | 
 | <span class="source-line-no">4605</span><span id="line-4605">          // The durability of returned mutation is replaced by the corresponding mutation.</span> | 
 | <span class="source-line-no">4606</span><span id="line-4606">          // If the corresponding mutation contains the SKIP_WAL, we shouldn't count the</span> | 
 | <span class="source-line-no">4607</span><span id="line-4607">          // cells of returned mutation.</span> | 
 | <span class="source-line-no">4608</span><span id="line-4608">          if (region.getEffectiveDurability(mutation.getDurability()) != Durability.SKIP_WAL) {</span> | 
 | <span class="source-line-no">4609</span><span id="line-4609">            for (List<ExtendedCell> cells : cpFamilyMap.values()) {</span> | 
 | <span class="source-line-no">4610</span><span id="line-4610">              miniBatchOp.addCellCount(cells.size());</span> | 
 | <span class="source-line-no">4611</span><span id="line-4611">            }</span> | 
 | <span class="source-line-no">4612</span><span id="line-4612">          }</span> | 
 | <span class="source-line-no">4613</span><span id="line-4613">        }</span> | 
 | <span class="source-line-no">4614</span><span id="line-4614">        return true;</span> | 
 | <span class="source-line-no">4615</span><span id="line-4615">      });</span> | 
 | <span class="source-line-no">4616</span><span id="line-4616">    }</span> | 
 | <span class="source-line-no">4617</span><span id="line-4617"></span> | 
 | <span class="source-line-no">4618</span><span id="line-4618">    private void mergeFamilyMaps(Map<byte[], List<ExtendedCell>> familyMap,</span> | 
 | <span class="source-line-no">4619</span><span id="line-4619">      Map<byte[], List<ExtendedCell>> toBeMerged) {</span> | 
 | <span class="source-line-no">4620</span><span id="line-4620">      for (Map.Entry<byte[], List<ExtendedCell>> entry : toBeMerged.entrySet()) {</span> | 
 | <span class="source-line-no">4621</span><span id="line-4621">        List<ExtendedCell> cells = familyMap.get(entry.getKey());</span> | 
 | <span class="source-line-no">4622</span><span id="line-4622">        if (cells == null) {</span> | 
 | <span class="source-line-no">4623</span><span id="line-4623">          familyMap.put(entry.getKey(), entry.getValue());</span> | 
 | <span class="source-line-no">4624</span><span id="line-4624">        } else {</span> | 
 | <span class="source-line-no">4625</span><span id="line-4625">          cells.addAll(entry.getValue());</span> | 
 | <span class="source-line-no">4626</span><span id="line-4626">        }</span> | 
 | <span class="source-line-no">4627</span><span id="line-4627">      }</span> | 
 | <span class="source-line-no">4628</span><span id="line-4628">    }</span> | 
 | <span class="source-line-no">4629</span><span id="line-4629">  }</span> | 
 | <span class="source-line-no">4630</span><span id="line-4630"></span> | 
 | <span class="source-line-no">4631</span><span id="line-4631">  /**</span> | 
 | <span class="source-line-no">4632</span><span id="line-4632">   * Batch of mutations for replay. Base class is shared with {@link MutationBatchOperation} as most</span> | 
 | <span class="source-line-no">4633</span><span id="line-4633">   * of the logic is same.</span> | 
 | <span class="source-line-no">4634</span><span id="line-4634">   * @deprecated Since 3.0.0, will be removed in 4.0.0. Now we will not use this operation to apply</span> | 
 | <span class="source-line-no">4635</span><span id="line-4635">   *             edits at secondary replica side.</span> | 
 | <span class="source-line-no">4636</span><span id="line-4636">   */</span> | 
 | <span class="source-line-no">4637</span><span id="line-4637">  @Deprecated</span> | 
 | <span class="source-line-no">4638</span><span id="line-4638">  private static final class ReplayBatchOperation extends BatchOperation<MutationReplay> {</span> | 
 | <span class="source-line-no">4639</span><span id="line-4639"></span> | 
 | <span class="source-line-no">4640</span><span id="line-4640">    private long origLogSeqNum = 0;</span> | 
 | <span class="source-line-no">4641</span><span id="line-4641"></span> | 
 | <span class="source-line-no">4642</span><span id="line-4642">    public ReplayBatchOperation(final HRegion region, MutationReplay[] operations,</span> | 
 | <span class="source-line-no">4643</span><span id="line-4643">      long origLogSeqNum) {</span> | 
 | <span class="source-line-no">4644</span><span id="line-4644">      super(region, operations);</span> | 
 | <span class="source-line-no">4645</span><span id="line-4645">      this.origLogSeqNum = origLogSeqNum;</span> | 
 | <span class="source-line-no">4646</span><span id="line-4646">    }</span> | 
 | <span class="source-line-no">4647</span><span id="line-4647"></span> | 
 | <span class="source-line-no">4648</span><span id="line-4648">    @Override</span> | 
 | <span class="source-line-no">4649</span><span id="line-4649">    public Mutation getMutation(int index) {</span> | 
 | <span class="source-line-no">4650</span><span id="line-4650">      return this.operations[index].mutation;</span> | 
 | <span class="source-line-no">4651</span><span id="line-4651">    }</span> | 
 | <span class="source-line-no">4652</span><span id="line-4652"></span> | 
 | <span class="source-line-no">4653</span><span id="line-4653">    @Override</span> | 
 | <span class="source-line-no">4654</span><span id="line-4654">    public long getNonceGroup(int index) {</span> | 
 | <span class="source-line-no">4655</span><span id="line-4655">      return this.operations[index].nonceGroup;</span> | 
 | <span class="source-line-no">4656</span><span id="line-4656">    }</span> | 
 | <span class="source-line-no">4657</span><span id="line-4657"></span> | 
 | <span class="source-line-no">4658</span><span id="line-4658">    @Override</span> | 
 | <span class="source-line-no">4659</span><span id="line-4659">    public long getNonce(int index) {</span> | 
 | <span class="source-line-no">4660</span><span id="line-4660">      return this.operations[index].nonce;</span> | 
 | <span class="source-line-no">4661</span><span id="line-4661">    }</span> | 
 | <span class="source-line-no">4662</span><span id="line-4662"></span> | 
 | <span class="source-line-no">4663</span><span id="line-4663">    @Override</span> | 
 | <span class="source-line-no">4664</span><span id="line-4664">    public Mutation[] getMutationsForCoprocs() {</span> | 
 | <span class="source-line-no">4665</span><span id="line-4665">      return null;</span> | 
 | <span class="source-line-no">4666</span><span id="line-4666">    }</span> | 
 | <span class="source-line-no">4667</span><span id="line-4667"></span> | 
 | <span class="source-line-no">4668</span><span id="line-4668">    @Override</span> | 
 | <span class="source-line-no">4669</span><span id="line-4669">    public boolean isInReplay() {</span> | 
 | <span class="source-line-no">4670</span><span id="line-4670">      return true;</span> | 
 | <span class="source-line-no">4671</span><span id="line-4671">    }</span> | 
 | <span class="source-line-no">4672</span><span id="line-4672"></span> | 
 | <span class="source-line-no">4673</span><span id="line-4673">    @Override</span> | 
 | <span class="source-line-no">4674</span><span id="line-4674">    public long getOrigLogSeqNum() {</span> | 
 | <span class="source-line-no">4675</span><span id="line-4675">      return this.origLogSeqNum;</span> | 
 | <span class="source-line-no">4676</span><span id="line-4676">    }</span> | 
 | <span class="source-line-no">4677</span><span id="line-4677"></span> | 
 | <span class="source-line-no">4678</span><span id="line-4678">    @Override</span> | 
 | <span class="source-line-no">4679</span><span id="line-4679">    public void startRegionOperation() throws IOException {</span> | 
 | <span class="source-line-no">4680</span><span id="line-4680">      region.startRegionOperation(Operation.REPLAY_BATCH_MUTATE);</span> | 
 | <span class="source-line-no">4681</span><span id="line-4681">    }</span> | 
 | <span class="source-line-no">4682</span><span id="line-4682"></span> | 
 | <span class="source-line-no">4683</span><span id="line-4683">    @Override</span> | 
 | <span class="source-line-no">4684</span><span id="line-4684">    public void closeRegionOperation() throws IOException {</span> | 
 | <span class="source-line-no">4685</span><span id="line-4685">      region.closeRegionOperation(Operation.REPLAY_BATCH_MUTATE);</span> | 
 | <span class="source-line-no">4686</span><span id="line-4686">    }</span> | 
 | <span class="source-line-no">4687</span><span id="line-4687"></span> | 
 | <span class="source-line-no">4688</span><span id="line-4688">    /**</span> | 
 | <span class="source-line-no">4689</span><span id="line-4689">     * During replay, there could exist column families which are removed between region server</span> | 
 | <span class="source-line-no">4690</span><span id="line-4690">     * failure and replay</span> | 
 | <span class="source-line-no">4691</span><span id="line-4691">     */</span> | 
 | <span class="source-line-no">4692</span><span id="line-4692">    @Override</span> | 
 | <span class="source-line-no">4693</span><span id="line-4693">    protected void checkAndPreparePut(Put p) throws IOException {</span> | 
 | <span class="source-line-no">4694</span><span id="line-4694">      Map<byte[], List<Cell>> familyCellMap = p.getFamilyCellMap();</span> | 
 | <span class="source-line-no">4695</span><span id="line-4695">      List<byte[]> nonExistentList = null;</span> | 
 | <span class="source-line-no">4696</span><span id="line-4696">      for (byte[] family : familyCellMap.keySet()) {</span> | 
 | <span class="source-line-no">4697</span><span id="line-4697">        if (!region.htableDescriptor.hasColumnFamily(family)) {</span> | 
 | <span class="source-line-no">4698</span><span id="line-4698">          if (nonExistentList == null) {</span> | 
 | <span class="source-line-no">4699</span><span id="line-4699">            nonExistentList = new ArrayList<>();</span> | 
 | <span class="source-line-no">4700</span><span id="line-4700">          }</span> | 
 | <span class="source-line-no">4701</span><span id="line-4701">          nonExistentList.add(family);</span> | 
 | <span class="source-line-no">4702</span><span id="line-4702">        }</span> | 
 | <span class="source-line-no">4703</span><span id="line-4703">      }</span> | 
 | <span class="source-line-no">4704</span><span id="line-4704">      if (nonExistentList != null) {</span> | 
 | <span class="source-line-no">4705</span><span id="line-4705">        for (byte[] family : nonExistentList) {</span> | 
 | <span class="source-line-no">4706</span><span id="line-4706">          // Perhaps schema was changed between crash and replay</span> | 
 | <span class="source-line-no">4707</span><span id="line-4707">          LOG.info("No family for {} omit from reply in region {}.", Bytes.toString(family), this);</span> | 
 | <span class="source-line-no">4708</span><span id="line-4708">          familyCellMap.remove(family);</span> | 
 | <span class="source-line-no">4709</span><span id="line-4709">        }</span> | 
 | <span class="source-line-no">4710</span><span id="line-4710">      }</span> | 
 | <span class="source-line-no">4711</span><span id="line-4711">    }</span> | 
 | <span class="source-line-no">4712</span><span id="line-4712"></span> | 
 | <span class="source-line-no">4713</span><span id="line-4713">    @Override</span> | 
 | <span class="source-line-no">4714</span><span id="line-4714">    public void checkAndPrepare() throws IOException {</span> | 
 | <span class="source-line-no">4715</span><span id="line-4715">      long now = EnvironmentEdgeManager.currentTime();</span> | 
 | <span class="source-line-no">4716</span><span id="line-4716">      visitBatchOperations(true, this.size(), (int index) -> {</span> | 
 | <span class="source-line-no">4717</span><span id="line-4717">        checkAndPrepareMutation(index, now);</span> | 
 | <span class="source-line-no">4718</span><span id="line-4718">        return true;</span> | 
 | <span class="source-line-no">4719</span><span id="line-4719">      });</span> | 
 | <span class="source-line-no">4720</span><span id="line-4720">    }</span> | 
 | <span class="source-line-no">4721</span><span id="line-4721"></span> | 
 | <span class="source-line-no">4722</span><span id="line-4722">    @Override</span> | 
 | <span class="source-line-no">4723</span><span id="line-4723">    public void prepareMiniBatchOperations(MiniBatchOperationInProgress<Mutation> miniBatchOp,</span> | 
 | <span class="source-line-no">4724</span><span id="line-4724">      long timestamp, final List<RowLock> acquiredRowLocks) throws IOException {</span> | 
 | <span class="source-line-no">4725</span><span id="line-4725">      visitBatchOperations(true, miniBatchOp.getLastIndexExclusive(), (int index) -> {</span> | 
 | <span class="source-line-no">4726</span><span id="line-4726">        // update cell count</span> | 
 | <span class="source-line-no">4727</span><span id="line-4727">        for (List<Cell> cells : getMutation(index).getFamilyCellMap().values()) {</span> | 
 | <span class="source-line-no">4728</span><span id="line-4728">          miniBatchOp.addCellCount(cells.size());</span> | 
 | <span class="source-line-no">4729</span><span id="line-4729">        }</span> | 
 | <span class="source-line-no">4730</span><span id="line-4730">        return true;</span> | 
 | <span class="source-line-no">4731</span><span id="line-4731">      });</span> | 
 | <span class="source-line-no">4732</span><span id="line-4732">    }</span> | 
 | <span class="source-line-no">4733</span><span id="line-4733"></span> | 
 | <span class="source-line-no">4734</span><span id="line-4734">    @Override</span> | 
 | <span class="source-line-no">4735</span><span id="line-4735">    public WriteEntry writeMiniBatchOperationsToMemStore(</span> | 
 | <span class="source-line-no">4736</span><span id="line-4736">      final MiniBatchOperationInProgress<Mutation> miniBatchOp, final WriteEntry writeEntry,</span> | 
 | <span class="source-line-no">4737</span><span id="line-4737">      long now) throws IOException {</span> | 
 | <span class="source-line-no">4738</span><span id="line-4738">      super.writeMiniBatchOperationsToMemStore(miniBatchOp, getOrigLogSeqNum());</span> | 
 | <span class="source-line-no">4739</span><span id="line-4739">      return writeEntry;</span> | 
 | <span class="source-line-no">4740</span><span id="line-4740">    }</span> | 
 | <span class="source-line-no">4741</span><span id="line-4741"></span> | 
 | <span class="source-line-no">4742</span><span id="line-4742">    @Override</span> | 
 | <span class="source-line-no">4743</span><span id="line-4743">    public void completeMiniBatchOperations(</span> | 
 | <span class="source-line-no">4744</span><span id="line-4744">      final MiniBatchOperationInProgress<Mutation> miniBatchOp, final WriteEntry writeEntry)</span> | 
 | <span class="source-line-no">4745</span><span id="line-4745">      throws IOException {</span> | 
 | <span class="source-line-no">4746</span><span id="line-4746">      super.completeMiniBatchOperations(miniBatchOp, writeEntry);</span> | 
 | <span class="source-line-no">4747</span><span id="line-4747">      region.mvcc.advanceTo(getOrigLogSeqNum());</span> | 
 | <span class="source-line-no">4748</span><span id="line-4748">    }</span> | 
 | <span class="source-line-no">4749</span><span id="line-4749"></span> | 
 | <span class="source-line-no">4750</span><span id="line-4750">    @Override</span> | 
 | <span class="source-line-no">4751</span><span id="line-4751">    protected void cacheSkipWALMutationForRegionReplication(</span> | 
 | <span class="source-line-no">4752</span><span id="line-4752">      MiniBatchOperationInProgress<Mutation> miniBatchOp, List<Pair<NonceKey, WALEdit>> walEdits,</span> | 
 | <span class="source-line-no">4753</span><span id="line-4753">      Map<byte[], List<ExtendedCell>> familyCellMap) {</span> | 
 | <span class="source-line-no">4754</span><span id="line-4754">      // There is no action to do if current region is secondary replica</span> | 
 | <span class="source-line-no">4755</span><span id="line-4755">    }</span> | 
 | <span class="source-line-no">4756</span><span id="line-4756"></span> | 
 | <span class="source-line-no">4757</span><span id="line-4757">  }</span> | 
 | <span class="source-line-no">4758</span><span id="line-4758"></span> | 
 | <span class="source-line-no">4759</span><span id="line-4759">  public OperationStatus[] batchMutate(Mutation[] mutations, boolean atomic, long nonceGroup,</span> | 
 | <span class="source-line-no">4760</span><span id="line-4760">    long nonce) throws IOException {</span> | 
 | <span class="source-line-no">4761</span><span id="line-4761">    // As it stands, this is used for 3 things</span> | 
 | <span class="source-line-no">4762</span><span id="line-4762">    // * batchMutate with single mutation - put/delete/increment/append, separate or from</span> | 
 | <span class="source-line-no">4763</span><span id="line-4763">    // checkAndMutate.</span> | 
 | <span class="source-line-no">4764</span><span id="line-4764">    // * coprocessor calls (see ex. BulkDeleteEndpoint).</span> | 
 | <span class="source-line-no">4765</span><span id="line-4765">    // So nonces are not really ever used by HBase. They could be by coprocs, and checkAnd...</span> | 
 | <span class="source-line-no">4766</span><span id="line-4766">    return batchMutate(new MutationBatchOperation(this, mutations, atomic, nonceGroup, nonce));</span> | 
 | <span class="source-line-no">4767</span><span id="line-4767">  }</span> | 
 | <span class="source-line-no">4768</span><span id="line-4768"></span> | 
 | <span class="source-line-no">4769</span><span id="line-4769">  @Override</span> | 
 | <span class="source-line-no">4770</span><span id="line-4770">  public OperationStatus[] batchMutate(Mutation[] mutations) throws IOException {</span> | 
 | <span class="source-line-no">4771</span><span id="line-4771">    // If the mutations has any Increment/Append operations, we need to do batchMutate atomically</span> | 
 | <span class="source-line-no">4772</span><span id="line-4772">    boolean atomic =</span> | 
 | <span class="source-line-no">4773</span><span id="line-4773">      Arrays.stream(mutations).anyMatch(m -> m instanceof Increment || m instanceof Append);</span> | 
 | <span class="source-line-no">4774</span><span id="line-4774">    return batchMutate(mutations, atomic);</span> | 
 | <span class="source-line-no">4775</span><span id="line-4775">  }</span> | 
 | <span class="source-line-no">4776</span><span id="line-4776"></span> | 
 | <span class="source-line-no">4777</span><span id="line-4777">  OperationStatus[] batchMutate(Mutation[] mutations, boolean atomic) throws IOException {</span> | 
 | <span class="source-line-no">4778</span><span id="line-4778">    return TraceUtil.trace(</span> | 
 | <span class="source-line-no">4779</span><span id="line-4779">      () -> batchMutate(mutations, atomic, HConstants.NO_NONCE, HConstants.NO_NONCE),</span> | 
 | <span class="source-line-no">4780</span><span id="line-4780">      () -> createRegionSpan("Region.batchMutate"));</span> | 
 | <span class="source-line-no">4781</span><span id="line-4781">  }</span> | 
 | <span class="source-line-no">4782</span><span id="line-4782"></span> | 
 | <span class="source-line-no">4783</span><span id="line-4783">  /**</span> | 
 | <span class="source-line-no">4784</span><span id="line-4784">   * @deprecated Since 3.0.0, will be removed in 4.0.0. Now we use</span> | 
 | <span class="source-line-no">4785</span><span id="line-4785">   *             {@link #replayWALEntry(WALEntry, CellScanner)} for replaying edits at secondary</span> | 
 | <span class="source-line-no">4786</span><span id="line-4786">   *             replica side.</span> | 
 | <span class="source-line-no">4787</span><span id="line-4787">   */</span> | 
 | <span class="source-line-no">4788</span><span id="line-4788">  @Deprecated</span> | 
 | <span class="source-line-no">4789</span><span id="line-4789">  OperationStatus[] batchReplay(MutationReplay[] mutations, long replaySeqId) throws IOException {</span> | 
 | <span class="source-line-no">4790</span><span id="line-4790">    if (</span> | 
 | <span class="source-line-no">4791</span><span id="line-4791">      !RegionReplicaUtil.isDefaultReplica(getRegionInfo())</span> | 
 | <span class="source-line-no">4792</span><span id="line-4792">        && replaySeqId < lastReplayedOpenRegionSeqId</span> | 
 | <span class="source-line-no">4793</span><span id="line-4793">    ) {</span> | 
 | <span class="source-line-no">4794</span><span id="line-4794">      // if it is a secondary replica we should ignore these entries silently</span> | 
 | <span class="source-line-no">4795</span><span id="line-4795">      // since they are coming out of order</span> | 
 | <span class="source-line-no">4796</span><span id="line-4796">      if (LOG.isTraceEnabled()) {</span> | 
 | <span class="source-line-no">4797</span><span id="line-4797">        LOG.trace(getRegionInfo().getEncodedName() + " : " + "Skipping " + mutations.length</span> | 
 | <span class="source-line-no">4798</span><span id="line-4798">          + " mutations with replaySeqId=" + replaySeqId</span> | 
 | <span class="source-line-no">4799</span><span id="line-4799">          + " which is < than lastReplayedOpenRegionSeqId=" + lastReplayedOpenRegionSeqId);</span> | 
 | <span class="source-line-no">4800</span><span id="line-4800">        for (MutationReplay mut : mutations) {</span> | 
 | <span class="source-line-no">4801</span><span id="line-4801">          LOG.trace(getRegionInfo().getEncodedName() + " : Skipping : " + mut.mutation);</span> | 
 | <span class="source-line-no">4802</span><span id="line-4802">        }</span> | 
 | <span class="source-line-no">4803</span><span id="line-4803">      }</span> | 
 | <span class="source-line-no">4804</span><span id="line-4804"></span> | 
 | <span class="source-line-no">4805</span><span id="line-4805">      OperationStatus[] statuses = new OperationStatus[mutations.length];</span> | 
 | <span class="source-line-no">4806</span><span id="line-4806">      for (int i = 0; i < statuses.length; i++) {</span> | 
 | <span class="source-line-no">4807</span><span id="line-4807">        statuses[i] = OperationStatus.SUCCESS;</span> | 
 | <span class="source-line-no">4808</span><span id="line-4808">      }</span> | 
 | <span class="source-line-no">4809</span><span id="line-4809">      return statuses;</span> | 
 | <span class="source-line-no">4810</span><span id="line-4810">    }</span> | 
 | <span class="source-line-no">4811</span><span id="line-4811">    return batchMutate(new ReplayBatchOperation(this, mutations, replaySeqId));</span> | 
 | <span class="source-line-no">4812</span><span id="line-4812">  }</span> | 
 | <span class="source-line-no">4813</span><span id="line-4813"></span> | 
 | <span class="source-line-no">4814</span><span id="line-4814">  /**</span> | 
 | <span class="source-line-no">4815</span><span id="line-4815">   * Perform a batch of mutations.</span> | 
 | <span class="source-line-no">4816</span><span id="line-4816">   * <p/></span> | 
 | <span class="source-line-no">4817</span><span id="line-4817">   * Operations in a batch are stored with highest durability specified of for all operations in a</span> | 
 | <span class="source-line-no">4818</span><span id="line-4818">   * batch, except for {@link Durability#SKIP_WAL}.</span> | 
 | <span class="source-line-no">4819</span><span id="line-4819">   * <p/></span> | 
 | <span class="source-line-no">4820</span><span id="line-4820">   * This function is called from {@link #batchReplay(WALSplitUtil.MutationReplay[], long)} with</span> | 
 | <span class="source-line-no">4821</span><span id="line-4821">   * {@link ReplayBatchOperation} instance and {@link #batchMutate(Mutation[])} with</span> | 
 | <span class="source-line-no">4822</span><span id="line-4822">   * {@link MutationBatchOperation} instance as an argument. As the processing of replay batch and</span> | 
 | <span class="source-line-no">4823</span><span id="line-4823">   * mutation batch is very similar, lot of code is shared by providing generic methods in base</span> | 
 | <span class="source-line-no">4824</span><span id="line-4824">   * class {@link BatchOperation}. The logic for this method and</span> | 
 | <span class="source-line-no">4825</span><span id="line-4825">   * {@link #doMiniBatchMutate(BatchOperation)} is implemented using methods in base class which are</span> | 
 | <span class="source-line-no">4826</span><span id="line-4826">   * overridden by derived classes to implement special behavior.</span> | 
 | <span class="source-line-no">4827</span><span id="line-4827">   * @param batchOp contains the list of mutations</span> | 
 | <span class="source-line-no">4828</span><span id="line-4828">   * @return an array of OperationStatus which internally contains the OperationStatusCode and the</span> | 
 | <span class="source-line-no">4829</span><span id="line-4829">   *         exceptionMessage if any.</span> | 
 | <span class="source-line-no">4830</span><span id="line-4830">   * @throws IOException if an IO problem is encountered</span> | 
 | <span class="source-line-no">4831</span><span id="line-4831">   */</span> | 
 | <span class="source-line-no">4832</span><span id="line-4832">  private OperationStatus[] batchMutate(BatchOperation<?> batchOp) throws IOException {</span> | 
 | <span class="source-line-no">4833</span><span id="line-4833">    boolean initialized = false;</span> | 
 | <span class="source-line-no">4834</span><span id="line-4834">    batchOp.startRegionOperation();</span> | 
 | <span class="source-line-no">4835</span><span id="line-4835">    try {</span> | 
 | <span class="source-line-no">4836</span><span id="line-4836">      while (!batchOp.isDone()) {</span> | 
 | <span class="source-line-no">4837</span><span id="line-4837">        if (!batchOp.isInReplay()) {</span> | 
 | <span class="source-line-no">4838</span><span id="line-4838">          checkReadOnly();</span> | 
 | <span class="source-line-no">4839</span><span id="line-4839">        }</span> | 
 | <span class="source-line-no">4840</span><span id="line-4840">        checkResources();</span> | 
 | <span class="source-line-no">4841</span><span id="line-4841"></span> | 
 | <span class="source-line-no">4842</span><span id="line-4842">        if (!initialized) {</span> | 
 | <span class="source-line-no">4843</span><span id="line-4843">          this.writeRequestsCount.add(batchOp.size());</span> | 
 | <span class="source-line-no">4844</span><span id="line-4844">          // validate and prepare batch for write, for MutationBatchOperation it also calls CP</span> | 
 | <span class="source-line-no">4845</span><span id="line-4845">          // prePut()/preDelete()/preIncrement()/preAppend() hooks</span> | 
 | <span class="source-line-no">4846</span><span id="line-4846">          batchOp.checkAndPrepare();</span> | 
 | <span class="source-line-no">4847</span><span id="line-4847">          initialized = true;</span> | 
 | <span class="source-line-no">4848</span><span id="line-4848">        }</span> | 
 | <span class="source-line-no">4849</span><span id="line-4849">        doMiniBatchMutate(batchOp);</span> | 
 | <span class="source-line-no">4850</span><span id="line-4850">        requestFlushIfNeeded();</span> | 
 | <span class="source-line-no">4851</span><span id="line-4851">      }</span> | 
 | <span class="source-line-no">4852</span><span id="line-4852">    } finally {</span> | 
 | <span class="source-line-no">4853</span><span id="line-4853">      if (rsServices != null && rsServices.getMetrics() != null) {</span> | 
 | <span class="source-line-no">4854</span><span id="line-4854">        rsServices.getMetrics().updateWriteQueryMeter(this, batchOp.size());</span> | 
 | <span class="source-line-no">4855</span><span id="line-4855">      }</span> | 
 | <span class="source-line-no">4856</span><span id="line-4856">      batchOp.closeRegionOperation();</span> | 
 | <span class="source-line-no">4857</span><span id="line-4857">    }</span> | 
 | <span class="source-line-no">4858</span><span id="line-4858">    return batchOp.retCodeDetails;</span> | 
 | <span class="source-line-no">4859</span><span id="line-4859">  }</span> | 
 | <span class="source-line-no">4860</span><span id="line-4860"></span> | 
 | <span class="source-line-no">4861</span><span id="line-4861">  /**</span> | 
 | <span class="source-line-no">4862</span><span id="line-4862">   * Called to do a piece of the batch that came in to {@link #batchMutate(Mutation[])} In here we</span> | 
 | <span class="source-line-no">4863</span><span id="line-4863">   * also handle replay of edits on region recover. Also gets change in size brought about by</span> | 
 | <span class="source-line-no">4864</span><span id="line-4864">   * applying {@code batchOp}.</span> | 
 | <span class="source-line-no">4865</span><span id="line-4865">   */</span> | 
 | <span class="source-line-no">4866</span><span id="line-4866">  private void doMiniBatchMutate(BatchOperation<?> batchOp) throws IOException {</span> | 
 | <span class="source-line-no">4867</span><span id="line-4867">    boolean success = false;</span> | 
 | <span class="source-line-no">4868</span><span id="line-4868">    WALEdit walEdit = null;</span> | 
 | <span class="source-line-no">4869</span><span id="line-4869">    WriteEntry writeEntry = null;</span> | 
 | <span class="source-line-no">4870</span><span id="line-4870">    boolean locked = false;</span> | 
 | <span class="source-line-no">4871</span><span id="line-4871">    // We try to set up a batch in the range [batchOp.nextIndexToProcess,lastIndexExclusive)</span> | 
 | <span class="source-line-no">4872</span><span id="line-4872">    MiniBatchOperationInProgress<Mutation> miniBatchOp = null;</span> | 
 | <span class="source-line-no">4873</span><span id="line-4873">    /** Keep track of the locks we hold so we can release them in finally clause */</span> | 
 | <span class="source-line-no">4874</span><span id="line-4874">    List<RowLock> acquiredRowLocks = Lists.newArrayListWithCapacity(batchOp.size());</span> | 
 | <span class="source-line-no">4875</span><span id="line-4875"></span> | 
 | <span class="source-line-no">4876</span><span id="line-4876">    // Check for thread interrupt status in case we have been signaled from</span> | 
 | <span class="source-line-no">4877</span><span id="line-4877">    // #interruptRegionOperation.</span> | 
 | <span class="source-line-no">4878</span><span id="line-4878">    checkInterrupt();</span> | 
 | <span class="source-line-no">4879</span><span id="line-4879"></span> | 
 | <span class="source-line-no">4880</span><span id="line-4880">    try {</span> | 
 | <span class="source-line-no">4881</span><span id="line-4881">      // STEP 1. Try to acquire as many locks as we can and build mini-batch of operations with</span> | 
 | <span class="source-line-no">4882</span><span id="line-4882">      // locked rows</span> | 
 | <span class="source-line-no">4883</span><span id="line-4883">      miniBatchOp = batchOp.lockRowsAndBuildMiniBatch(acquiredRowLocks);</span> | 
 | <span class="source-line-no">4884</span><span id="line-4884"></span> | 
 | <span class="source-line-no">4885</span><span id="line-4885">      // We've now grabbed as many mutations off the list as we can</span> | 
 | <span class="source-line-no">4886</span><span id="line-4886">      // Ensure we acquire at least one.</span> | 
 | <span class="source-line-no">4887</span><span id="line-4887">      if (miniBatchOp.getReadyToWriteCount() <= 0) {</span> | 
 | <span class="source-line-no">4888</span><span id="line-4888">        // Nothing to put/delete/increment/append -- an exception in the above such as</span> | 
 | <span class="source-line-no">4889</span><span id="line-4889">        // NoSuchColumnFamily?</span> | 
 | <span class="source-line-no">4890</span><span id="line-4890">        return;</span> | 
 | <span class="source-line-no">4891</span><span id="line-4891">      }</span> | 
 | <span class="source-line-no">4892</span><span id="line-4892"></span> | 
 | <span class="source-line-no">4893</span><span id="line-4893">      // Check for thread interrupt status in case we have been signaled from</span> | 
 | <span class="source-line-no">4894</span><span id="line-4894">      // #interruptRegionOperation. Do it before we take the lock and disable interrupts for</span> | 
 | <span class="source-line-no">4895</span><span id="line-4895">      // the WAL append.</span> | 
 | <span class="source-line-no">4896</span><span id="line-4896">      checkInterrupt();</span> | 
 | <span class="source-line-no">4897</span><span id="line-4897"></span> | 
 | <span class="source-line-no">4898</span><span id="line-4898">      lock(this.updatesLock.readLock(), miniBatchOp.getReadyToWriteCount());</span> | 
 | <span class="source-line-no">4899</span><span id="line-4899">      locked = true;</span> | 
 | <span class="source-line-no">4900</span><span id="line-4900"></span> | 
 | <span class="source-line-no">4901</span><span id="line-4901">      // From this point until memstore update this operation should not be interrupted.</span> | 
 | <span class="source-line-no">4902</span><span id="line-4902">      disableInterrupts();</span> | 
 | <span class="source-line-no">4903</span><span id="line-4903"></span> | 
 | <span class="source-line-no">4904</span><span id="line-4904">      // STEP 2. Update mini batch of all operations in progress with LATEST_TIMESTAMP timestamp</span> | 
 | <span class="source-line-no">4905</span><span id="line-4905">      // We should record the timestamp only after we have acquired the rowLock,</span> | 
 | <span class="source-line-no">4906</span><span id="line-4906">      // otherwise, newer puts/deletes/increment/append are not guaranteed to have a newer</span> | 
 | <span class="source-line-no">4907</span><span id="line-4907">      // timestamp</span> | 
 | <span class="source-line-no">4908</span><span id="line-4908"></span> | 
 | <span class="source-line-no">4909</span><span id="line-4909">      long now = EnvironmentEdgeManager.currentTime();</span> | 
 | <span class="source-line-no">4910</span><span id="line-4910">      batchOp.prepareMiniBatchOperations(miniBatchOp, now, acquiredRowLocks);</span> | 
 | <span class="source-line-no">4911</span><span id="line-4911"></span> | 
 | <span class="source-line-no">4912</span><span id="line-4912">      // STEP 3. Build WAL edit</span> | 
 | <span class="source-line-no">4913</span><span id="line-4913"></span> | 
 | <span class="source-line-no">4914</span><span id="line-4914">      List<Pair<NonceKey, WALEdit>> walEdits = batchOp.buildWALEdits(miniBatchOp);</span> | 
 | <span class="source-line-no">4915</span><span id="line-4915"></span> | 
 | <span class="source-line-no">4916</span><span id="line-4916">      // STEP 4. Append the WALEdits to WAL and sync.</span> | 
 | <span class="source-line-no">4917</span><span id="line-4917"></span> | 
 | <span class="source-line-no">4918</span><span id="line-4918">      for (Iterator<Pair<NonceKey, WALEdit>> it = walEdits.iterator(); it.hasNext();) {</span> | 
 | <span class="source-line-no">4919</span><span id="line-4919">        Pair<NonceKey, WALEdit> nonceKeyWALEditPair = it.next();</span> | 
 | <span class="source-line-no">4920</span><span id="line-4920">        walEdit = nonceKeyWALEditPair.getSecond();</span> | 
 | <span class="source-line-no">4921</span><span id="line-4921">        NonceKey nonceKey = nonceKeyWALEditPair.getFirst();</span> | 
 | <span class="source-line-no">4922</span><span id="line-4922"></span> | 
 | <span class="source-line-no">4923</span><span id="line-4923">        if (walEdit != null && !walEdit.isEmpty()) {</span> | 
 | <span class="source-line-no">4924</span><span id="line-4924">          writeEntry = doWALAppend(walEdit, batchOp, miniBatchOp, now, nonceKey);</span> | 
 | <span class="source-line-no">4925</span><span id="line-4925">        }</span> | 
 | <span class="source-line-no">4926</span><span id="line-4926"></span> | 
 | <span class="source-line-no">4927</span><span id="line-4927">        // Complete mvcc for all but last writeEntry (for replay case)</span> | 
 | <span class="source-line-no">4928</span><span id="line-4928">        if (it.hasNext() && writeEntry != null) {</span> | 
 | <span class="source-line-no">4929</span><span id="line-4929">          mvcc.complete(writeEntry);</span> | 
 | <span class="source-line-no">4930</span><span id="line-4930">          writeEntry = null;</span> | 
 | <span class="source-line-no">4931</span><span id="line-4931">        }</span> | 
 | <span class="source-line-no">4932</span><span id="line-4932">      }</span> | 
 | <span class="source-line-no">4933</span><span id="line-4933"></span> | 
 | <span class="source-line-no">4934</span><span id="line-4934">      // STEP 5. Write back to memStore</span> | 
 | <span class="source-line-no">4935</span><span id="line-4935">      // NOTE: writeEntry can be null here</span> | 
 | <span class="source-line-no">4936</span><span id="line-4936">      writeEntry = batchOp.writeMiniBatchOperationsToMemStore(miniBatchOp, writeEntry, now);</span> | 
 | <span class="source-line-no">4937</span><span id="line-4937"></span> | 
 | <span class="source-line-no">4938</span><span id="line-4938">      // STEP 6. Complete MiniBatchOperations: If required calls postBatchMutate() CP hook and</span> | 
 | <span class="source-line-no">4939</span><span id="line-4939">      // complete mvcc for last writeEntry</span> | 
 | <span class="source-line-no">4940</span><span id="line-4940">      batchOp.completeMiniBatchOperations(miniBatchOp, writeEntry);</span> | 
 | <span class="source-line-no">4941</span><span id="line-4941">      writeEntry = null;</span> | 
 | <span class="source-line-no">4942</span><span id="line-4942">      success = true;</span> | 
 | <span class="source-line-no">4943</span><span id="line-4943">    } finally {</span> | 
 | <span class="source-line-no">4944</span><span id="line-4944">      // Call complete rather than completeAndWait because we probably had error if walKey != null</span> | 
 | <span class="source-line-no">4945</span><span id="line-4945">      if (writeEntry != null) mvcc.complete(writeEntry);</span> | 
 | <span class="source-line-no">4946</span><span id="line-4946"></span> | 
 | <span class="source-line-no">4947</span><span id="line-4947">      if (locked) {</span> | 
 | <span class="source-line-no">4948</span><span id="line-4948">        this.updatesLock.readLock().unlock();</span> | 
 | <span class="source-line-no">4949</span><span id="line-4949">      }</span> | 
 | <span class="source-line-no">4950</span><span id="line-4950">      releaseRowLocks(acquiredRowLocks);</span> | 
 | <span class="source-line-no">4951</span><span id="line-4951"></span> | 
 | <span class="source-line-no">4952</span><span id="line-4952">      enableInterrupts();</span> | 
 | <span class="source-line-no">4953</span><span id="line-4953"></span> | 
 | <span class="source-line-no">4954</span><span id="line-4954">      final int finalLastIndexExclusive =</span> | 
 | <span class="source-line-no">4955</span><span id="line-4955">        miniBatchOp != null ? miniBatchOp.getLastIndexExclusive() : batchOp.size();</span> | 
 | <span class="source-line-no">4956</span><span id="line-4956">      final boolean finalSuccess = success;</span> | 
 | <span class="source-line-no">4957</span><span id="line-4957">      batchOp.visitBatchOperations(true, finalLastIndexExclusive, (int i) -> {</span> | 
 | <span class="source-line-no">4958</span><span id="line-4958">        Mutation mutation = batchOp.getMutation(i);</span> | 
 | <span class="source-line-no">4959</span><span id="line-4959">        if (mutation instanceof Increment || mutation instanceof Append) {</span> | 
 | <span class="source-line-no">4960</span><span id="line-4960">          if (finalSuccess) {</span> | 
 | <span class="source-line-no">4961</span><span id="line-4961">            batchOp.retCodeDetails[i] =</span> | 
 | <span class="source-line-no">4962</span><span id="line-4962">              new OperationStatus(OperationStatusCode.SUCCESS, batchOp.results[i]);</span> | 
 | <span class="source-line-no">4963</span><span id="line-4963">          } else {</span> | 
 | <span class="source-line-no">4964</span><span id="line-4964">            batchOp.retCodeDetails[i] = OperationStatus.FAILURE;</span> | 
 | <span class="source-line-no">4965</span><span id="line-4965">          }</span> | 
 | <span class="source-line-no">4966</span><span id="line-4966">        } else {</span> | 
 | <span class="source-line-no">4967</span><span id="line-4967">          batchOp.retCodeDetails[i] =</span> | 
 | <span class="source-line-no">4968</span><span id="line-4968">            finalSuccess ? OperationStatus.SUCCESS : OperationStatus.FAILURE;</span> | 
 | <span class="source-line-no">4969</span><span id="line-4969">        }</span> | 
 | <span class="source-line-no">4970</span><span id="line-4970">        return true;</span> | 
 | <span class="source-line-no">4971</span><span id="line-4971">      });</span> | 
 | <span class="source-line-no">4972</span><span id="line-4972"></span> | 
 | <span class="source-line-no">4973</span><span id="line-4973">      batchOp.doPostOpCleanupForMiniBatch(miniBatchOp, walEdit, finalSuccess);</span> | 
 | <span class="source-line-no">4974</span><span id="line-4974"></span> | 
 | <span class="source-line-no">4975</span><span id="line-4975">      batchOp.nextIndexToProcess = finalLastIndexExclusive;</span> | 
 | <span class="source-line-no">4976</span><span id="line-4976">    }</span> | 
 | <span class="source-line-no">4977</span><span id="line-4977">  }</span> | 
 | <span class="source-line-no">4978</span><span id="line-4978"></span> | 
 | <span class="source-line-no">4979</span><span id="line-4979">  /**</span> | 
 | <span class="source-line-no">4980</span><span id="line-4980">   * Returns effective durability from the passed durability and the table descriptor.</span> | 
 | <span class="source-line-no">4981</span><span id="line-4981">   */</span> | 
 | <span class="source-line-no">4982</span><span id="line-4982">  private Durability getEffectiveDurability(Durability d) {</span> | 
 | <span class="source-line-no">4983</span><span id="line-4983">    return d == Durability.USE_DEFAULT ? this.regionDurability : d;</span> | 
 | <span class="source-line-no">4984</span><span id="line-4984">  }</span> | 
 | <span class="source-line-no">4985</span><span id="line-4985"></span> | 
 | <span class="source-line-no">4986</span><span id="line-4986">  @Override</span> | 
 | <span class="source-line-no">4987</span><span id="line-4987">  @Deprecated</span> | 
 | <span class="source-line-no">4988</span><span id="line-4988">  public boolean checkAndMutate(byte[] row, byte[] family, byte[] qualifier, CompareOperator op,</span> | 
 | <span class="source-line-no">4989</span><span id="line-4989">    ByteArrayComparable comparator, TimeRange timeRange, Mutation mutation) throws IOException {</span> | 
 | <span class="source-line-no">4990</span><span id="line-4990">    CheckAndMutate checkAndMutate;</span> | 
 | <span class="source-line-no">4991</span><span id="line-4991">    try {</span> | 
 | <span class="source-line-no">4992</span><span id="line-4992">      CheckAndMutate.Builder builder = CheckAndMutate.newBuilder(row)</span> | 
 | <span class="source-line-no">4993</span><span id="line-4993">        .ifMatches(family, qualifier, op, comparator.getValue()).timeRange(timeRange);</span> | 
 | <span class="source-line-no">4994</span><span id="line-4994">      if (mutation instanceof Put) {</span> | 
 | <span class="source-line-no">4995</span><span id="line-4995">        checkAndMutate = builder.build((Put) mutation);</span> | 
 | <span class="source-line-no">4996</span><span id="line-4996">      } else if (mutation instanceof Delete) {</span> | 
 | <span class="source-line-no">4997</span><span id="line-4997">        checkAndMutate = builder.build((Delete) mutation);</span> | 
 | <span class="source-line-no">4998</span><span id="line-4998">      } else {</span> | 
 | <span class="source-line-no">4999</span><span id="line-4999">        throw new DoNotRetryIOException(</span> | 
 | <span class="source-line-no">5000</span><span id="line-5000">          "Unsupported mutate type: " + mutation.getClass().getSimpleName().toUpperCase());</span> | 
 | <span class="source-line-no">5001</span><span id="line-5001">      }</span> | 
 | <span class="source-line-no">5002</span><span id="line-5002">    } catch (IllegalArgumentException e) {</span> | 
 | <span class="source-line-no">5003</span><span id="line-5003">      throw new DoNotRetryIOException(e.getMessage());</span> | 
 | <span class="source-line-no">5004</span><span id="line-5004">    }</span> | 
 | <span class="source-line-no">5005</span><span id="line-5005">    return checkAndMutate(checkAndMutate).isSuccess();</span> | 
 | <span class="source-line-no">5006</span><span id="line-5006">  }</span> | 
 | <span class="source-line-no">5007</span><span id="line-5007"></span> | 
 | <span class="source-line-no">5008</span><span id="line-5008">  @Override</span> | 
 | <span class="source-line-no">5009</span><span id="line-5009">  @Deprecated</span> | 
 | <span class="source-line-no">5010</span><span id="line-5010">  public boolean checkAndMutate(byte[] row, Filter filter, TimeRange timeRange, Mutation mutation)</span> | 
 | <span class="source-line-no">5011</span><span id="line-5011">    throws IOException {</span> | 
 | <span class="source-line-no">5012</span><span id="line-5012">    CheckAndMutate checkAndMutate;</span> | 
 | <span class="source-line-no">5013</span><span id="line-5013">    try {</span> | 
 | <span class="source-line-no">5014</span><span id="line-5014">      CheckAndMutate.Builder builder =</span> | 
 | <span class="source-line-no">5015</span><span id="line-5015">        CheckAndMutate.newBuilder(row).ifMatches(filter).timeRange(timeRange);</span> | 
 | <span class="source-line-no">5016</span><span id="line-5016">      if (mutation instanceof Put) {</span> | 
 | <span class="source-line-no">5017</span><span id="line-5017">        checkAndMutate = builder.build((Put) mutation);</span> | 
 | <span class="source-line-no">5018</span><span id="line-5018">      } else if (mutation instanceof Delete) {</span> | 
 | <span class="source-line-no">5019</span><span id="line-5019">        checkAndMutate = builder.build((Delete) mutation);</span> | 
 | <span class="source-line-no">5020</span><span id="line-5020">      } else {</span> | 
 | <span class="source-line-no">5021</span><span id="line-5021">        throw new DoNotRetryIOException(</span> | 
 | <span class="source-line-no">5022</span><span id="line-5022">          "Unsupported mutate type: " + mutation.getClass().getSimpleName().toUpperCase());</span> | 
 | <span class="source-line-no">5023</span><span id="line-5023">      }</span> | 
 | <span class="source-line-no">5024</span><span id="line-5024">    } catch (IllegalArgumentException e) {</span> | 
 | <span class="source-line-no">5025</span><span id="line-5025">      throw new DoNotRetryIOException(e.getMessage());</span> | 
 | <span class="source-line-no">5026</span><span id="line-5026">    }</span> | 
 | <span class="source-line-no">5027</span><span id="line-5027">    return checkAndMutate(checkAndMutate).isSuccess();</span> | 
 | <span class="source-line-no">5028</span><span id="line-5028">  }</span> | 
 | <span class="source-line-no">5029</span><span id="line-5029"></span> | 
 | <span class="source-line-no">5030</span><span id="line-5030">  @Override</span> | 
 | <span class="source-line-no">5031</span><span id="line-5031">  @Deprecated</span> | 
 | <span class="source-line-no">5032</span><span id="line-5032">  public boolean checkAndRowMutate(byte[] row, byte[] family, byte[] qualifier, CompareOperator op,</span> | 
 | <span class="source-line-no">5033</span><span id="line-5033">    ByteArrayComparable comparator, TimeRange timeRange, RowMutations rm) throws IOException {</span> | 
 | <span class="source-line-no">5034</span><span id="line-5034">    CheckAndMutate checkAndMutate;</span> | 
 | <span class="source-line-no">5035</span><span id="line-5035">    try {</span> | 
 | <span class="source-line-no">5036</span><span id="line-5036">      checkAndMutate = CheckAndMutate.newBuilder(row)</span> | 
 | <span class="source-line-no">5037</span><span id="line-5037">        .ifMatches(family, qualifier, op, comparator.getValue()).timeRange(timeRange).build(rm);</span> | 
 | <span class="source-line-no">5038</span><span id="line-5038">    } catch (IllegalArgumentException e) {</span> | 
 | <span class="source-line-no">5039</span><span id="line-5039">      throw new DoNotRetryIOException(e.getMessage());</span> | 
 | <span class="source-line-no">5040</span><span id="line-5040">    }</span> | 
 | <span class="source-line-no">5041</span><span id="line-5041">    return checkAndMutate(checkAndMutate).isSuccess();</span> | 
 | <span class="source-line-no">5042</span><span id="line-5042">  }</span> | 
 | <span class="source-line-no">5043</span><span id="line-5043"></span> | 
 | <span class="source-line-no">5044</span><span id="line-5044">  @Override</span> | 
 | <span class="source-line-no">5045</span><span id="line-5045">  @Deprecated</span> | 
 | <span class="source-line-no">5046</span><span id="line-5046">  public boolean checkAndRowMutate(byte[] row, Filter filter, TimeRange timeRange, RowMutations rm)</span> | 
 | <span class="source-line-no">5047</span><span id="line-5047">    throws IOException {</span> | 
 | <span class="source-line-no">5048</span><span id="line-5048">    CheckAndMutate checkAndMutate;</span> | 
 | <span class="source-line-no">5049</span><span id="line-5049">    try {</span> | 
 | <span class="source-line-no">5050</span><span id="line-5050">      checkAndMutate =</span> | 
 | <span class="source-line-no">5051</span><span id="line-5051">        CheckAndMutate.newBuilder(row).ifMatches(filter).timeRange(timeRange).build(rm);</span> | 
 | <span class="source-line-no">5052</span><span id="line-5052">    } catch (IllegalArgumentException e) {</span> | 
 | <span class="source-line-no">5053</span><span id="line-5053">      throw new DoNotRetryIOException(e.getMessage());</span> | 
 | <span class="source-line-no">5054</span><span id="line-5054">    }</span> | 
 | <span class="source-line-no">5055</span><span id="line-5055">    return checkAndMutate(checkAndMutate).isSuccess();</span> | 
 | <span class="source-line-no">5056</span><span id="line-5056">  }</span> | 
 | <span class="source-line-no">5057</span><span id="line-5057"></span> | 
 | <span class="source-line-no">5058</span><span id="line-5058">  @Override</span> | 
 | <span class="source-line-no">5059</span><span id="line-5059">  public CheckAndMutateResult checkAndMutate(CheckAndMutate checkAndMutate) throws IOException {</span> | 
 | <span class="source-line-no">5060</span><span id="line-5060">    return checkAndMutate(checkAndMutate, HConstants.NO_NONCE, HConstants.NO_NONCE);</span> | 
 | <span class="source-line-no">5061</span><span id="line-5061">  }</span> | 
 | <span class="source-line-no">5062</span><span id="line-5062"></span> | 
 | <span class="source-line-no">5063</span><span id="line-5063">  public CheckAndMutateResult checkAndMutate(CheckAndMutate checkAndMutate, long nonceGroup,</span> | 
 | <span class="source-line-no">5064</span><span id="line-5064">    long nonce) throws IOException {</span> | 
 | <span class="source-line-no">5065</span><span id="line-5065">    return TraceUtil.trace(() -> checkAndMutateInternal(checkAndMutate, nonceGroup, nonce),</span> | 
 | <span class="source-line-no">5066</span><span id="line-5066">      () -> createRegionSpan("Region.checkAndMutate"));</span> | 
 | <span class="source-line-no">5067</span><span id="line-5067">  }</span> | 
 | <span class="source-line-no">5068</span><span id="line-5068"></span> | 
 | <span class="source-line-no">5069</span><span id="line-5069">  private CheckAndMutateResult checkAndMutateInternal(CheckAndMutate checkAndMutate,</span> | 
 | <span class="source-line-no">5070</span><span id="line-5070">    long nonceGroup, long nonce) throws IOException {</span> | 
 | <span class="source-line-no">5071</span><span id="line-5071">    byte[] row = checkAndMutate.getRow();</span> | 
 | <span class="source-line-no">5072</span><span id="line-5072">    Filter filter = null;</span> | 
 | <span class="source-line-no">5073</span><span id="line-5073">    byte[] family = null;</span> | 
 | <span class="source-line-no">5074</span><span id="line-5074">    byte[] qualifier = null;</span> | 
 | <span class="source-line-no">5075</span><span id="line-5075">    CompareOperator op = null;</span> | 
 | <span class="source-line-no">5076</span><span id="line-5076">    ByteArrayComparable comparator = null;</span> | 
 | <span class="source-line-no">5077</span><span id="line-5077">    if (checkAndMutate.hasFilter()) {</span> | 
 | <span class="source-line-no">5078</span><span id="line-5078">      filter = checkAndMutate.getFilter();</span> | 
 | <span class="source-line-no">5079</span><span id="line-5079">    } else {</span> | 
 | <span class="source-line-no">5080</span><span id="line-5080">      family = checkAndMutate.getFamily();</span> | 
 | <span class="source-line-no">5081</span><span id="line-5081">      qualifier = checkAndMutate.getQualifier();</span> | 
 | <span class="source-line-no">5082</span><span id="line-5082">      op = checkAndMutate.getCompareOp();</span> | 
 | <span class="source-line-no">5083</span><span id="line-5083">      comparator = new BinaryComparator(checkAndMutate.getValue());</span> | 
 | <span class="source-line-no">5084</span><span id="line-5084">    }</span> | 
 | <span class="source-line-no">5085</span><span id="line-5085">    TimeRange timeRange = checkAndMutate.getTimeRange();</span> | 
 | <span class="source-line-no">5086</span><span id="line-5086"></span> | 
 | <span class="source-line-no">5087</span><span id="line-5087">    Mutation mutation = null;</span> | 
 | <span class="source-line-no">5088</span><span id="line-5088">    RowMutations rowMutations = null;</span> | 
 | <span class="source-line-no">5089</span><span id="line-5089">    if (checkAndMutate.getAction() instanceof Mutation) {</span> | 
 | <span class="source-line-no">5090</span><span id="line-5090">      mutation = (Mutation) checkAndMutate.getAction();</span> | 
 | <span class="source-line-no">5091</span><span id="line-5091">    } else {</span> | 
 | <span class="source-line-no">5092</span><span id="line-5092">      rowMutations = (RowMutations) checkAndMutate.getAction();</span> | 
 | <span class="source-line-no">5093</span><span id="line-5093">    }</span> | 
 | <span class="source-line-no">5094</span><span id="line-5094"></span> | 
 | <span class="source-line-no">5095</span><span id="line-5095">    if (mutation != null) {</span> | 
 | <span class="source-line-no">5096</span><span id="line-5096">      checkMutationType(mutation);</span> | 
 | <span class="source-line-no">5097</span><span id="line-5097">      checkRow(mutation, row);</span> | 
 | <span class="source-line-no">5098</span><span id="line-5098">    } else {</span> | 
 | <span class="source-line-no">5099</span><span id="line-5099">      checkRow(rowMutations, row);</span> | 
 | <span class="source-line-no">5100</span><span id="line-5100">    }</span> | 
 | <span class="source-line-no">5101</span><span id="line-5101">    checkReadOnly();</span> | 
 | <span class="source-line-no">5102</span><span id="line-5102">    // TODO, add check for value length also move this check to the client</span> | 
 | <span class="source-line-no">5103</span><span id="line-5103">    checkResources();</span> | 
 | <span class="source-line-no">5104</span><span id="line-5104">    startRegionOperation();</span> | 
 | <span class="source-line-no">5105</span><span id="line-5105">    try {</span> | 
 | <span class="source-line-no">5106</span><span id="line-5106">      Get get = new Get(row);</span> | 
 | <span class="source-line-no">5107</span><span id="line-5107">      if (family != null) {</span> | 
 | <span class="source-line-no">5108</span><span id="line-5108">        checkFamily(family);</span> | 
 | <span class="source-line-no">5109</span><span id="line-5109">        get.addColumn(family, qualifier);</span> | 
 | <span class="source-line-no">5110</span><span id="line-5110">      }</span> | 
 | <span class="source-line-no">5111</span><span id="line-5111">      if (filter != null) {</span> | 
 | <span class="source-line-no">5112</span><span id="line-5112">        get.setFilter(filter);</span> | 
 | <span class="source-line-no">5113</span><span id="line-5113">      }</span> | 
 | <span class="source-line-no">5114</span><span id="line-5114">      if (timeRange != null) {</span> | 
 | <span class="source-line-no">5115</span><span id="line-5115">        get.setTimeRange(timeRange.getMin(), timeRange.getMax());</span> | 
 | <span class="source-line-no">5116</span><span id="line-5116">      }</span> | 
 | <span class="source-line-no">5117</span><span id="line-5117">      // Lock row - note that doBatchMutate will relock this row if called</span> | 
 | <span class="source-line-no">5118</span><span id="line-5118">      checkRow(row, "doCheckAndRowMutate");</span> | 
 | <span class="source-line-no">5119</span><span id="line-5119">      RowLock rowLock = getRowLock(get.getRow(), false, null);</span> | 
 | <span class="source-line-no">5120</span><span id="line-5120">      try {</span> | 
 | <span class="source-line-no">5121</span><span id="line-5121">        if (this.getCoprocessorHost() != null) {</span> | 
 | <span class="source-line-no">5122</span><span id="line-5122">          CheckAndMutateResult result =</span> | 
 | <span class="source-line-no">5123</span><span id="line-5123">            getCoprocessorHost().preCheckAndMutateAfterRowLock(checkAndMutate);</span> | 
 | <span class="source-line-no">5124</span><span id="line-5124">          if (result != null) {</span> | 
 | <span class="source-line-no">5125</span><span id="line-5125">            return result;</span> | 
 | <span class="source-line-no">5126</span><span id="line-5126">          }</span> | 
 | <span class="source-line-no">5127</span><span id="line-5127">        }</span> | 
 | <span class="source-line-no">5128</span><span id="line-5128"></span> | 
 | <span class="source-line-no">5129</span><span id="line-5129">        // NOTE: We used to wait here until mvcc caught up: mvcc.await();</span> | 
 | <span class="source-line-no">5130</span><span id="line-5130">        // Supposition is that now all changes are done under row locks, then when we go to read,</span> | 
 | <span class="source-line-no">5131</span><span id="line-5131">        // we'll get the latest on this row.</span> | 
 | <span class="source-line-no">5132</span><span id="line-5132">        boolean matches = false;</span> | 
 | <span class="source-line-no">5133</span><span id="line-5133">        long cellTs = 0;</span> | 
 | <span class="source-line-no">5134</span><span id="line-5134">        QueryMetrics metrics = null;</span> | 
 | <span class="source-line-no">5135</span><span id="line-5135">        try (RegionScannerImpl scanner = getScanner(new Scan(get))) {</span> | 
 | <span class="source-line-no">5136</span><span id="line-5136">          // NOTE: Please don't use HRegion.get() instead,</span> | 
 | <span class="source-line-no">5137</span><span id="line-5137">          // because it will copy cells to heap. See HBASE-26036</span> | 
 | <span class="source-line-no">5138</span><span id="line-5138">          List<ExtendedCell> result = new ArrayList<>(1);</span> | 
 | <span class="source-line-no">5139</span><span id="line-5139">          scanner.next(result);</span> | 
 | <span class="source-line-no">5140</span><span id="line-5140">          if (filter != null) {</span> | 
 | <span class="source-line-no">5141</span><span id="line-5141">            if (!result.isEmpty()) {</span> | 
 | <span class="source-line-no">5142</span><span id="line-5142">              matches = true;</span> | 
 | <span class="source-line-no">5143</span><span id="line-5143">              cellTs = result.get(0).getTimestamp();</span> | 
 | <span class="source-line-no">5144</span><span id="line-5144">            }</span> | 
 | <span class="source-line-no">5145</span><span id="line-5145">          } else {</span> | 
 | <span class="source-line-no">5146</span><span id="line-5146">            boolean valueIsNull =</span> | 
 | <span class="source-line-no">5147</span><span id="line-5147">              comparator.getValue() == null || comparator.getValue().length == 0;</span> | 
 | <span class="source-line-no">5148</span><span id="line-5148">            if (result.isEmpty() && valueIsNull) {</span> | 
 | <span class="source-line-no">5149</span><span id="line-5149">              matches = op != CompareOperator.NOT_EQUAL;</span> | 
 | <span class="source-line-no">5150</span><span id="line-5150">            } else if (result.size() > 0 && valueIsNull) {</span> | 
 | <span class="source-line-no">5151</span><span id="line-5151">              matches = (result.get(0).getValueLength() == 0) == (op != CompareOperator.NOT_EQUAL);</span> | 
 | <span class="source-line-no">5152</span><span id="line-5152">              cellTs = result.get(0).getTimestamp();</span> | 
 | <span class="source-line-no">5153</span><span id="line-5153">            } else if (result.size() == 1) {</span> | 
 | <span class="source-line-no">5154</span><span id="line-5154">              ExtendedCell kv = result.get(0);</span> | 
 | <span class="source-line-no">5155</span><span id="line-5155">              cellTs = kv.getTimestamp();</span> | 
 | <span class="source-line-no">5156</span><span id="line-5156">              int compareResult = PrivateCellUtil.compareValue(kv, comparator);</span> | 
 | <span class="source-line-no">5157</span><span id="line-5157">              matches = matches(op, compareResult);</span> | 
 | <span class="source-line-no">5158</span><span id="line-5158">            }</span> | 
 | <span class="source-line-no">5159</span><span id="line-5159">          }</span> | 
 | <span class="source-line-no">5160</span><span id="line-5160">          if (checkAndMutate.isQueryMetricsEnabled()) {</span> | 
 | <span class="source-line-no">5161</span><span id="line-5161">            metrics = new QueryMetrics(scanner.getContext().getBlockSizeProgress());</span> | 
 | <span class="source-line-no">5162</span><span id="line-5162">          }</span> | 
 | <span class="source-line-no">5163</span><span id="line-5163">        }</span> | 
 | <span class="source-line-no">5164</span><span id="line-5164"></span> | 
 | <span class="source-line-no">5165</span><span id="line-5165">        // If matches, perform the mutation or the rowMutations</span> | 
 | <span class="source-line-no">5166</span><span id="line-5166">        if (matches) {</span> | 
 | <span class="source-line-no">5167</span><span id="line-5167">          // We have acquired the row lock already. If the system clock is NOT monotonically</span> | 
 | <span class="source-line-no">5168</span><span id="line-5168">          // non-decreasing (see HBASE-14070) we should make sure that the mutation has a</span> | 
 | <span class="source-line-no">5169</span><span id="line-5169">          // larger timestamp than what was observed via Get. doBatchMutate already does this, but</span> | 
 | <span class="source-line-no">5170</span><span id="line-5170">          // there is no way to pass the cellTs. See HBASE-14054.</span> | 
 | <span class="source-line-no">5171</span><span id="line-5171">          long now = EnvironmentEdgeManager.currentTime();</span> | 
 | <span class="source-line-no">5172</span><span id="line-5172">          long ts = Math.max(now, cellTs); // ensure write is not eclipsed</span> | 
 | <span class="source-line-no">5173</span><span id="line-5173">          byte[] byteTs = Bytes.toBytes(ts);</span> | 
 | <span class="source-line-no">5174</span><span id="line-5174">          if (mutation != null) {</span> | 
 | <span class="source-line-no">5175</span><span id="line-5175">            if (mutation instanceof Put) {</span> | 
 | <span class="source-line-no">5176</span><span id="line-5176">              updateCellTimestamps(ClientInternalHelper.getExtendedFamilyCellMap(mutation).values(),</span> | 
 | <span class="source-line-no">5177</span><span id="line-5177">                byteTs);</span> | 
 | <span class="source-line-no">5178</span><span id="line-5178">            }</span> | 
 | <span class="source-line-no">5179</span><span id="line-5179">            // And else 'delete' is not needed since it already does a second get, and sets the</span> | 
 | <span class="source-line-no">5180</span><span id="line-5180">            // timestamp from get (see prepareDeleteTimestamps).</span> | 
 | <span class="source-line-no">5181</span><span id="line-5181">          } else {</span> | 
 | <span class="source-line-no">5182</span><span id="line-5182">            for (Mutation m : rowMutations.getMutations()) {</span> | 
 | <span class="source-line-no">5183</span><span id="line-5183">              if (m instanceof Put) {</span> | 
 | <span class="source-line-no">5184</span><span id="line-5184">                updateCellTimestamps(ClientInternalHelper.getExtendedFamilyCellMap(m).values(),</span> | 
 | <span class="source-line-no">5185</span><span id="line-5185">                  byteTs);</span> | 
 | <span class="source-line-no">5186</span><span id="line-5186">              }</span> | 
 | <span class="source-line-no">5187</span><span id="line-5187">            }</span> | 
 | <span class="source-line-no">5188</span><span id="line-5188">            // And else 'delete' is not needed since it already does a second get, and sets the</span> | 
 | <span class="source-line-no">5189</span><span id="line-5189">            // timestamp from get (see prepareDeleteTimestamps).</span> | 
 | <span class="source-line-no">5190</span><span id="line-5190">          }</span> | 
 | <span class="source-line-no">5191</span><span id="line-5191">          // All edits for the given row (across all column families) must happen atomically.</span> | 
 | <span class="source-line-no">5192</span><span id="line-5192">          Result r;</span> | 
 | <span class="source-line-no">5193</span><span id="line-5193">          if (mutation != null) {</span> | 
 | <span class="source-line-no">5194</span><span id="line-5194">            r = mutate(mutation, true, nonceGroup, nonce).getResult();</span> | 
 | <span class="source-line-no">5195</span><span id="line-5195">          } else {</span> | 
 | <span class="source-line-no">5196</span><span id="line-5196">            r = mutateRow(rowMutations, nonceGroup, nonce);</span> | 
 | <span class="source-line-no">5197</span><span id="line-5197">          }</span> | 
 | <span class="source-line-no">5198</span><span id="line-5198">          this.checkAndMutateChecksPassed.increment();</span> | 
 | <span class="source-line-no">5199</span><span id="line-5199">          return new CheckAndMutateResult(true, r).setMetrics(metrics);</span> | 
 | <span class="source-line-no">5200</span><span id="line-5200">        }</span> | 
 | <span class="source-line-no">5201</span><span id="line-5201">        this.checkAndMutateChecksFailed.increment();</span> | 
 | <span class="source-line-no">5202</span><span id="line-5202">        return new CheckAndMutateResult(false, null).setMetrics(metrics);</span> | 
 | <span class="source-line-no">5203</span><span id="line-5203">      } finally {</span> | 
 | <span class="source-line-no">5204</span><span id="line-5204">        rowLock.release();</span> | 
 | <span class="source-line-no">5205</span><span id="line-5205">      }</span> | 
 | <span class="source-line-no">5206</span><span id="line-5206">    } finally {</span> | 
 | <span class="source-line-no">5207</span><span id="line-5207">      closeRegionOperation();</span> | 
 | <span class="source-line-no">5208</span><span id="line-5208">    }</span> | 
 | <span class="source-line-no">5209</span><span id="line-5209">  }</span> | 
 | <span class="source-line-no">5210</span><span id="line-5210"></span> | 
 | <span class="source-line-no">5211</span><span id="line-5211">  private void checkMutationType(final Mutation mutation) throws DoNotRetryIOException {</span> | 
 | <span class="source-line-no">5212</span><span id="line-5212">    if (</span> | 
 | <span class="source-line-no">5213</span><span id="line-5213">      !(mutation instanceof Put) && !(mutation instanceof Delete)</span> | 
 | <span class="source-line-no">5214</span><span id="line-5214">        && !(mutation instanceof Increment) && !(mutation instanceof Append)</span> | 
 | <span class="source-line-no">5215</span><span id="line-5215">    ) {</span> | 
 | <span class="source-line-no">5216</span><span id="line-5216">      throw new org.apache.hadoop.hbase.DoNotRetryIOException(</span> | 
 | <span class="source-line-no">5217</span><span id="line-5217">        "Action must be Put or Delete or Increment or Delete");</span> | 
 | <span class="source-line-no">5218</span><span id="line-5218">    }</span> | 
 | <span class="source-line-no">5219</span><span id="line-5219">  }</span> | 
 | <span class="source-line-no">5220</span><span id="line-5220"></span> | 
 | <span class="source-line-no">5221</span><span id="line-5221">  private void checkRow(final Row action, final byte[] row) throws DoNotRetryIOException {</span> | 
 | <span class="source-line-no">5222</span><span id="line-5222">    if (!Bytes.equals(row, action.getRow())) {</span> | 
 | <span class="source-line-no">5223</span><span id="line-5223">      throw new org.apache.hadoop.hbase.DoNotRetryIOException("Action's getRow must match");</span> | 
 | <span class="source-line-no">5224</span><span id="line-5224">    }</span> | 
 | <span class="source-line-no">5225</span><span id="line-5225">  }</span> | 
 | <span class="source-line-no">5226</span><span id="line-5226"></span> | 
 | <span class="source-line-no">5227</span><span id="line-5227">  private boolean matches(final CompareOperator op, final int compareResult) {</span> | 
 | <span class="source-line-no">5228</span><span id="line-5228">    boolean matches = false;</span> | 
 | <span class="source-line-no">5229</span><span id="line-5229">    switch (op) {</span> | 
 | <span class="source-line-no">5230</span><span id="line-5230">      case LESS:</span> | 
 | <span class="source-line-no">5231</span><span id="line-5231">        matches = compareResult < 0;</span> | 
 | <span class="source-line-no">5232</span><span id="line-5232">        break;</span> | 
 | <span class="source-line-no">5233</span><span id="line-5233">      case LESS_OR_EQUAL:</span> | 
 | <span class="source-line-no">5234</span><span id="line-5234">        matches = compareResult <= 0;</span> | 
 | <span class="source-line-no">5235</span><span id="line-5235">        break;</span> | 
 | <span class="source-line-no">5236</span><span id="line-5236">      case EQUAL:</span> | 
 | <span class="source-line-no">5237</span><span id="line-5237">        matches = compareResult == 0;</span> | 
 | <span class="source-line-no">5238</span><span id="line-5238">        break;</span> | 
 | <span class="source-line-no">5239</span><span id="line-5239">      case NOT_EQUAL:</span> | 
 | <span class="source-line-no">5240</span><span id="line-5240">        matches = compareResult != 0;</span> | 
 | <span class="source-line-no">5241</span><span id="line-5241">        break;</span> | 
 | <span class="source-line-no">5242</span><span id="line-5242">      case GREATER_OR_EQUAL:</span> | 
 | <span class="source-line-no">5243</span><span id="line-5243">        matches = compareResult >= 0;</span> | 
 | <span class="source-line-no">5244</span><span id="line-5244">        break;</span> | 
 | <span class="source-line-no">5245</span><span id="line-5245">      case GREATER:</span> | 
 | <span class="source-line-no">5246</span><span id="line-5246">        matches = compareResult > 0;</span> | 
 | <span class="source-line-no">5247</span><span id="line-5247">        break;</span> | 
 | <span class="source-line-no">5248</span><span id="line-5248">      default:</span> | 
 | <span class="source-line-no">5249</span><span id="line-5249">        throw new RuntimeException("Unknown Compare op " + op.name());</span> | 
 | <span class="source-line-no">5250</span><span id="line-5250">    }</span> | 
 | <span class="source-line-no">5251</span><span id="line-5251">    return matches;</span> | 
 | <span class="source-line-no">5252</span><span id="line-5252">  }</span> | 
 | <span class="source-line-no">5253</span><span id="line-5253"></span> | 
 | <span class="source-line-no">5254</span><span id="line-5254">  private OperationStatus mutate(Mutation mutation) throws IOException {</span> | 
 | <span class="source-line-no">5255</span><span id="line-5255">    return mutate(mutation, false);</span> | 
 | <span class="source-line-no">5256</span><span id="line-5256">  }</span> | 
 | <span class="source-line-no">5257</span><span id="line-5257"></span> | 
 | <span class="source-line-no">5258</span><span id="line-5258">  private OperationStatus mutate(Mutation mutation, boolean atomic) throws IOException {</span> | 
 | <span class="source-line-no">5259</span><span id="line-5259">    return mutate(mutation, atomic, HConstants.NO_NONCE, HConstants.NO_NONCE);</span> | 
 | <span class="source-line-no">5260</span><span id="line-5260">  }</span> | 
 | <span class="source-line-no">5261</span><span id="line-5261"></span> | 
 | <span class="source-line-no">5262</span><span id="line-5262">  private OperationStatus mutate(Mutation mutation, boolean atomic, long nonceGroup, long nonce)</span> | 
 | <span class="source-line-no">5263</span><span id="line-5263">    throws IOException {</span> | 
 | <span class="source-line-no">5264</span><span id="line-5264">    OperationStatus[] status =</span> | 
 | <span class="source-line-no">5265</span><span id="line-5265">      this.batchMutate(new Mutation[] { mutation }, atomic, nonceGroup, nonce);</span> | 
 | <span class="source-line-no">5266</span><span id="line-5266">    if (status[0].getOperationStatusCode().equals(OperationStatusCode.SANITY_CHECK_FAILURE)) {</span> | 
 | <span class="source-line-no">5267</span><span id="line-5267">      throw new FailedSanityCheckException(status[0].getExceptionMsg());</span> | 
 | <span class="source-line-no">5268</span><span id="line-5268">    } else if (status[0].getOperationStatusCode().equals(OperationStatusCode.BAD_FAMILY)) {</span> | 
 | <span class="source-line-no">5269</span><span id="line-5269">      throw new NoSuchColumnFamilyException(status[0].getExceptionMsg());</span> | 
 | <span class="source-line-no">5270</span><span id="line-5270">    } else if (status[0].getOperationStatusCode().equals(OperationStatusCode.STORE_TOO_BUSY)) {</span> | 
 | <span class="source-line-no">5271</span><span id="line-5271">      throw new RegionTooBusyException(status[0].getExceptionMsg());</span> | 
 | <span class="source-line-no">5272</span><span id="line-5272">    }</span> | 
 | <span class="source-line-no">5273</span><span id="line-5273">    return status[0];</span> | 
 | <span class="source-line-no">5274</span><span id="line-5274">  }</span> | 
 | <span class="source-line-no">5275</span><span id="line-5275"></span> | 
 | <span class="source-line-no">5276</span><span id="line-5276">  /**</span> | 
 | <span class="source-line-no">5277</span><span id="line-5277">   * Complete taking the snapshot on the region. Writes the region info and adds references to the</span> | 
 | <span class="source-line-no">5278</span><span id="line-5278">   * working snapshot directory. TODO for api consistency, consider adding another version with no</span> | 
 | <span class="source-line-no">5279</span><span id="line-5279">   * {@link ForeignExceptionSnare} arg. (In the future other cancellable HRegion methods could</span> | 
 | <span class="source-line-no">5280</span><span id="line-5280">   * eventually add a {@link ForeignExceptionSnare}, or we could do something fancier).</span> | 
 | <span class="source-line-no">5281</span><span id="line-5281">   * @param desc     snapshot description object</span> | 
 | <span class="source-line-no">5282</span><span id="line-5282">   * @param exnSnare ForeignExceptionSnare that captures external exceptions in case we need to bail</span> | 
 | <span class="source-line-no">5283</span><span id="line-5283">   *                 out. This is allowed to be null and will just be ignored in that case.</span> | 
 | <span class="source-line-no">5284</span><span id="line-5284">   * @throws IOException if there is an external or internal error causing the snapshot to fail</span> | 
 | <span class="source-line-no">5285</span><span id="line-5285">   */</span> | 
 | <span class="source-line-no">5286</span><span id="line-5286">  public void addRegionToSnapshot(SnapshotDescription desc, ForeignExceptionSnare exnSnare)</span> | 
 | <span class="source-line-no">5287</span><span id="line-5287">    throws IOException {</span> | 
 | <span class="source-line-no">5288</span><span id="line-5288">    Path rootDir = CommonFSUtils.getRootDir(conf);</span> | 
 | <span class="source-line-no">5289</span><span id="line-5289">    Path snapshotDir = SnapshotDescriptionUtils.getWorkingSnapshotDir(desc, rootDir, conf);</span> | 
 | <span class="source-line-no">5290</span><span id="line-5290"></span> | 
 | <span class="source-line-no">5291</span><span id="line-5291">    SnapshotManifest manifest =</span> | 
 | <span class="source-line-no">5292</span><span id="line-5292">      SnapshotManifest.create(conf, getFilesystem(), snapshotDir, desc, exnSnare);</span> | 
 | <span class="source-line-no">5293</span><span id="line-5293">    manifest.addRegion(this);</span> | 
 | <span class="source-line-no">5294</span><span id="line-5294">  }</span> | 
 | <span class="source-line-no">5295</span><span id="line-5295"></span> | 
 | <span class="source-line-no">5296</span><span id="line-5296">  private void updateSequenceId(final Iterable<List<ExtendedCell>> cellItr, final long sequenceId)</span> | 
 | <span class="source-line-no">5297</span><span id="line-5297">    throws IOException {</span> | 
 | <span class="source-line-no">5298</span><span id="line-5298">    for (List<ExtendedCell> cells : cellItr) {</span> | 
 | <span class="source-line-no">5299</span><span id="line-5299">      if (cells == null) {</span> | 
 | <span class="source-line-no">5300</span><span id="line-5300">        return;</span> | 
 | <span class="source-line-no">5301</span><span id="line-5301">      }</span> | 
 | <span class="source-line-no">5302</span><span id="line-5302">      for (ExtendedCell cell : cells) {</span> | 
 | <span class="source-line-no">5303</span><span id="line-5303">        cell.setSequenceId(sequenceId);</span> | 
 | <span class="source-line-no">5304</span><span id="line-5304">      }</span> | 
 | <span class="source-line-no">5305</span><span id="line-5305">    }</span> | 
 | <span class="source-line-no">5306</span><span id="line-5306">  }</span> | 
 | <span class="source-line-no">5307</span><span id="line-5307"></span> | 
 | <span class="source-line-no">5308</span><span id="line-5308">  /**</span> | 
 | <span class="source-line-no">5309</span><span id="line-5309">   * Replace any cell timestamps set to {@link org.apache.hadoop.hbase.HConstants#LATEST_TIMESTAMP}</span> | 
 | <span class="source-line-no">5310</span><span id="line-5310">   * provided current timestamp.</span> | 
 | <span class="source-line-no">5311</span><span id="line-5311">   */</span> | 
 | <span class="source-line-no">5312</span><span id="line-5312">  private static void updateCellTimestamps(final Iterable<List<ExtendedCell>> cellItr,</span> | 
 | <span class="source-line-no">5313</span><span id="line-5313">    final byte[] now) throws IOException {</span> | 
 | <span class="source-line-no">5314</span><span id="line-5314">    for (List<ExtendedCell> cells : cellItr) {</span> | 
 | <span class="source-line-no">5315</span><span id="line-5315">      if (cells == null) {</span> | 
 | <span class="source-line-no">5316</span><span id="line-5316">        continue;</span> | 
 | <span class="source-line-no">5317</span><span id="line-5317">      }</span> | 
 | <span class="source-line-no">5318</span><span id="line-5318">      // Optimization: 'foreach' loop is not used. See:</span> | 
 | <span class="source-line-no">5319</span><span id="line-5319">      // HBASE-12023 HRegion.applyFamilyMapToMemstore creates too many iterator objects</span> | 
 | <span class="source-line-no">5320</span><span id="line-5320">      assert cells instanceof RandomAccess;</span> | 
 | <span class="source-line-no">5321</span><span id="line-5321">      int listSize = cells.size();</span> | 
 | <span class="source-line-no">5322</span><span id="line-5322">      for (int i = 0; i < listSize; i++) {</span> | 
 | <span class="source-line-no">5323</span><span id="line-5323">        PrivateCellUtil.updateLatestStamp(cells.get(i), now);</span> | 
 | <span class="source-line-no">5324</span><span id="line-5324">      }</span> | 
 | <span class="source-line-no">5325</span><span id="line-5325">    }</span> | 
 | <span class="source-line-no">5326</span><span id="line-5326">  }</span> | 
 | <span class="source-line-no">5327</span><span id="line-5327"></span> | 
 | <span class="source-line-no">5328</span><span id="line-5328">  /**</span> | 
 | <span class="source-line-no">5329</span><span id="line-5329">   * Possibly rewrite incoming cell tags.</span> | 
 | <span class="source-line-no">5330</span><span id="line-5330">   */</span> | 
 | <span class="source-line-no">5331</span><span id="line-5331">  private void rewriteCellTags(Map<byte[], List<ExtendedCell>> familyMap, final Mutation m) {</span> | 
 | <span class="source-line-no">5332</span><span id="line-5332">    // Check if we have any work to do and early out otherwise</span> | 
 | <span class="source-line-no">5333</span><span id="line-5333">    // Update these checks as more logic is added here</span> | 
 | <span class="source-line-no">5334</span><span id="line-5334">    if (m.getTTL() == Long.MAX_VALUE) {</span> | 
 | <span class="source-line-no">5335</span><span id="line-5335">      return;</span> | 
 | <span class="source-line-no">5336</span><span id="line-5336">    }</span> | 
 | <span class="source-line-no">5337</span><span id="line-5337"></span> | 
 | <span class="source-line-no">5338</span><span id="line-5338">    // From this point we know we have some work to do</span> | 
 | <span class="source-line-no">5339</span><span id="line-5339">    for (Map.Entry<byte[], List<ExtendedCell>> e : familyMap.entrySet()) {</span> | 
 | <span class="source-line-no">5340</span><span id="line-5340">      List<ExtendedCell> cells = e.getValue();</span> | 
 | <span class="source-line-no">5341</span><span id="line-5341">      assert cells instanceof RandomAccess;</span> | 
 | <span class="source-line-no">5342</span><span id="line-5342">      int listSize = cells.size();</span> | 
 | <span class="source-line-no">5343</span><span id="line-5343">      for (int i = 0; i < listSize; i++) {</span> | 
 | <span class="source-line-no">5344</span><span id="line-5344">        ExtendedCell cell = cells.get(i);</span> | 
 | <span class="source-line-no">5345</span><span id="line-5345">        List<Tag> newTags = TagUtil.carryForwardTags(null, cell);</span> | 
 | <span class="source-line-no">5346</span><span id="line-5346">        newTags = TagUtil.carryForwardTTLTag(newTags, m.getTTL());</span> | 
 | <span class="source-line-no">5347</span><span id="line-5347">        // Rewrite the cell with the updated set of tags</span> | 
 | <span class="source-line-no">5348</span><span id="line-5348">        cells.set(i, PrivateCellUtil.createCell(cell, newTags));</span> | 
 | <span class="source-line-no">5349</span><span id="line-5349">      }</span> | 
 | <span class="source-line-no">5350</span><span id="line-5350">    }</span> | 
 | <span class="source-line-no">5351</span><span id="line-5351">  }</span> | 
 | <span class="source-line-no">5352</span><span id="line-5352"></span> | 
 | <span class="source-line-no">5353</span><span id="line-5353">  /**</span> | 
 | <span class="source-line-no">5354</span><span id="line-5354">   * Check if resources to support an update.</span> | 
 | <span class="source-line-no">5355</span><span id="line-5355">   * <p/></span> | 
 | <span class="source-line-no">5356</span><span id="line-5356">   * We throw RegionTooBusyException if above memstore limit and expect client to retry using some</span> | 
 | <span class="source-line-no">5357</span><span id="line-5357">   * kind of backoff</span> | 
 | <span class="source-line-no">5358</span><span id="line-5358">   */</span> | 
 | <span class="source-line-no">5359</span><span id="line-5359">  private void checkResources() throws RegionTooBusyException {</span> | 
 | <span class="source-line-no">5360</span><span id="line-5360">    // If catalog region, do not impose resource constraints or block updates.</span> | 
 | <span class="source-line-no">5361</span><span id="line-5361">    if (this.getRegionInfo().isMetaRegion()) {</span> | 
 | <span class="source-line-no">5362</span><span id="line-5362">      return;</span> | 
 | <span class="source-line-no">5363</span><span id="line-5363">    }</span> | 
 | <span class="source-line-no">5364</span><span id="line-5364"></span> | 
 | <span class="source-line-no">5365</span><span id="line-5365">    MemStoreSize mss = this.memStoreSizing.getMemStoreSize();</span> | 
 | <span class="source-line-no">5366</span><span id="line-5366">    if (mss.getHeapSize() + mss.getOffHeapSize() > this.blockingMemStoreSize) {</span> | 
 | <span class="source-line-no">5367</span><span id="line-5367">      blockedRequestsCount.increment();</span> | 
 | <span class="source-line-no">5368</span><span id="line-5368">      requestFlush();</span> | 
 | <span class="source-line-no">5369</span><span id="line-5369">      // Don't print current limit because it will vary too much. The message is used as a key</span> | 
 | <span class="source-line-no">5370</span><span id="line-5370">      // over in RetriesExhaustedWithDetailsException processing.</span> | 
 | <span class="source-line-no">5371</span><span id="line-5371">      final String regionName =</span> | 
 | <span class="source-line-no">5372</span><span id="line-5372">        this.getRegionInfo() == null ? "unknown" : this.getRegionInfo().getEncodedName();</span> | 
 | <span class="source-line-no">5373</span><span id="line-5373">      final String serverName = this.getRegionServerServices() == null</span> | 
 | <span class="source-line-no">5374</span><span id="line-5374">        ? "unknown"</span> | 
 | <span class="source-line-no">5375</span><span id="line-5375">        : (this.getRegionServerServices().getServerName() == null</span> | 
 | <span class="source-line-no">5376</span><span id="line-5376">          ? "unknown"</span> | 
 | <span class="source-line-no">5377</span><span id="line-5377">          : this.getRegionServerServices().getServerName().toString());</span> | 
 | <span class="source-line-no">5378</span><span id="line-5378">      RegionTooBusyException rtbe = new RegionTooBusyException("Over memstore limit="</span> | 
 | <span class="source-line-no">5379</span><span id="line-5379">        + org.apache.hadoop.hbase.procedure2.util.StringUtils.humanSize(this.blockingMemStoreSize)</span> | 
 | <span class="source-line-no">5380</span><span id="line-5380">        + ", regionName=" + regionName + ", server=" + serverName);</span> | 
 | <span class="source-line-no">5381</span><span id="line-5381">      LOG.warn("Region is too busy due to exceeding memstore size limit.", rtbe);</span> | 
 | <span class="source-line-no">5382</span><span id="line-5382">      throw rtbe;</span> | 
 | <span class="source-line-no">5383</span><span id="line-5383">    }</span> | 
 | <span class="source-line-no">5384</span><span id="line-5384">  }</span> | 
 | <span class="source-line-no">5385</span><span id="line-5385"></span> | 
 | <span class="source-line-no">5386</span><span id="line-5386">  /**</span> | 
 | <span class="source-line-no">5387</span><span id="line-5387">   * @throws IOException Throws exception if region is in read-only mode.</span> | 
 | <span class="source-line-no">5388</span><span id="line-5388">   */</span> | 
 | <span class="source-line-no">5389</span><span id="line-5389">  private void checkReadOnly() throws IOException {</span> | 
 | <span class="source-line-no">5390</span><span id="line-5390">    if (isReadOnly()) {</span> | 
 | <span class="source-line-no">5391</span><span id="line-5391">      throw new DoNotRetryIOException("region is read only");</span> | 
 | <span class="source-line-no">5392</span><span id="line-5392">    }</span> | 
 | <span class="source-line-no">5393</span><span id="line-5393">  }</span> | 
 | <span class="source-line-no">5394</span><span id="line-5394"></span> | 
 | <span class="source-line-no">5395</span><span id="line-5395">  private void checkReadsEnabled() throws IOException {</span> | 
 | <span class="source-line-no">5396</span><span id="line-5396">    if (!this.writestate.readsEnabled) {</span> | 
 | <span class="source-line-no">5397</span><span id="line-5397">      throw new IOException(getRegionInfo().getEncodedName()</span> | 
 | <span class="source-line-no">5398</span><span id="line-5398">        + ": The region's reads are disabled. Cannot serve the request");</span> | 
 | <span class="source-line-no">5399</span><span id="line-5399">    }</span> | 
 | <span class="source-line-no">5400</span><span id="line-5400">  }</span> | 
 | <span class="source-line-no">5401</span><span id="line-5401"></span> | 
 | <span class="source-line-no">5402</span><span id="line-5402">  public void setReadsEnabled(boolean readsEnabled) {</span> | 
 | <span class="source-line-no">5403</span><span id="line-5403">    if (readsEnabled && !this.writestate.readsEnabled) {</span> | 
 | <span class="source-line-no">5404</span><span id="line-5404">      LOG.info("Enabling reads for {}", getRegionInfo().getEncodedName());</span> | 
 | <span class="source-line-no">5405</span><span id="line-5405">    }</span> | 
 | <span class="source-line-no">5406</span><span id="line-5406">    this.writestate.setReadsEnabled(readsEnabled);</span> | 
 | <span class="source-line-no">5407</span><span id="line-5407">  }</span> | 
 | <span class="source-line-no">5408</span><span id="line-5408"></span> | 
 | <span class="source-line-no">5409</span><span id="line-5409">  /**</span> | 
 | <span class="source-line-no">5410</span><span id="line-5410">   * @param delta If we are doing delta changes -- e.g. increment/append -- then this flag will be</span> | 
 | <span class="source-line-no">5411</span><span id="line-5411">   *              set; when set we will run operations that make sense in the increment/append</span> | 
 | <span class="source-line-no">5412</span><span id="line-5412">   *              scenario but that do not make sense otherwise.</span> | 
 | <span class="source-line-no">5413</span><span id="line-5413">   */</span> | 
 | <span class="source-line-no">5414</span><span id="line-5414">  private void applyToMemStore(HStore store, List<ExtendedCell> cells, boolean delta,</span> | 
 | <span class="source-line-no">5415</span><span id="line-5415">    MemStoreSizing memstoreAccounting) {</span> | 
 | <span class="source-line-no">5416</span><span id="line-5416">    // Any change in how we update Store/MemStore needs to also be done in other applyToMemStore!!!!</span> | 
 | <span class="source-line-no">5417</span><span id="line-5417">    boolean upsert = delta && store.getColumnFamilyDescriptor().getMaxVersions() == 1;</span> | 
 | <span class="source-line-no">5418</span><span id="line-5418">    if (upsert) {</span> | 
 | <span class="source-line-no">5419</span><span id="line-5419">      store.upsert(cells, getSmallestReadPoint(), memstoreAccounting);</span> | 
 | <span class="source-line-no">5420</span><span id="line-5420">    } else {</span> | 
 | <span class="source-line-no">5421</span><span id="line-5421">      store.add(cells, memstoreAccounting);</span> | 
 | <span class="source-line-no">5422</span><span id="line-5422">    }</span> | 
 | <span class="source-line-no">5423</span><span id="line-5423">  }</span> | 
 | <span class="source-line-no">5424</span><span id="line-5424"></span> | 
 | <span class="source-line-no">5425</span><span id="line-5425">  private void checkFamilies(Collection<byte[]> families, Durability durability)</span> | 
 | <span class="source-line-no">5426</span><span id="line-5426">    throws NoSuchColumnFamilyException, InvalidMutationDurabilityException {</span> | 
 | <span class="source-line-no">5427</span><span id="line-5427">    for (byte[] family : families) {</span> | 
 | <span class="source-line-no">5428</span><span id="line-5428">      checkFamily(family, durability);</span> | 
 | <span class="source-line-no">5429</span><span id="line-5429">    }</span> | 
 | <span class="source-line-no">5430</span><span id="line-5430">  }</span> | 
 | <span class="source-line-no">5431</span><span id="line-5431"></span> | 
 | <span class="source-line-no">5432</span><span id="line-5432">  private void checkFamily(final byte[] family, Durability durability)</span> | 
 | <span class="source-line-no">5433</span><span id="line-5433">    throws NoSuchColumnFamilyException, InvalidMutationDurabilityException {</span> | 
 | <span class="source-line-no">5434</span><span id="line-5434">    checkFamily(family);</span> | 
 | <span class="source-line-no">5435</span><span id="line-5435">    if (</span> | 
 | <span class="source-line-no">5436</span><span id="line-5436">      durability.equals(Durability.SKIP_WAL)</span> | 
 | <span class="source-line-no">5437</span><span id="line-5437">        && htableDescriptor.getColumnFamily(family).getScope() != HConstants.REPLICATION_SCOPE_LOCAL</span> | 
 | <span class="source-line-no">5438</span><span id="line-5438">    ) {</span> | 
 | <span class="source-line-no">5439</span><span id="line-5439">      throw new InvalidMutationDurabilityException(</span> | 
 | <span class="source-line-no">5440</span><span id="line-5440">        "Mutation's durability is SKIP_WAL but table's column family " + Bytes.toString(family)</span> | 
 | <span class="source-line-no">5441</span><span id="line-5441">          + " need replication");</span> | 
 | <span class="source-line-no">5442</span><span id="line-5442">    }</span> | 
 | <span class="source-line-no">5443</span><span id="line-5443">  }</span> | 
 | <span class="source-line-no">5444</span><span id="line-5444"></span> | 
 | <span class="source-line-no">5445</span><span id="line-5445">  private void checkFamily(final byte[] family) throws NoSuchColumnFamilyException {</span> | 
 | <span class="source-line-no">5446</span><span id="line-5446">    if (!this.htableDescriptor.hasColumnFamily(family)) {</span> | 
 | <span class="source-line-no">5447</span><span id="line-5447">      throw new NoSuchColumnFamilyException("Column family " + Bytes.toString(family)</span> | 
 | <span class="source-line-no">5448</span><span id="line-5448">        + " does not exist in region " + this + " in table " + this.htableDescriptor);</span> | 
 | <span class="source-line-no">5449</span><span id="line-5449">    }</span> | 
 | <span class="source-line-no">5450</span><span id="line-5450">  }</span> | 
 | <span class="source-line-no">5451</span><span id="line-5451"></span> | 
 | <span class="source-line-no">5452</span><span id="line-5452">  /**</span> | 
 | <span class="source-line-no">5453</span><span id="line-5453">   * Check the collection of families for valid timestamps</span> | 
 | <span class="source-line-no">5454</span><span id="line-5454">   * @param now current timestamp</span> | 
 | <span class="source-line-no">5455</span><span id="line-5455">   */</span> | 
 | <span class="source-line-no">5456</span><span id="line-5456">  public void checkTimestamps(final Map<byte[], List<Cell>> familyMap, long now)</span> | 
 | <span class="source-line-no">5457</span><span id="line-5457">    throws FailedSanityCheckException {</span> | 
 | <span class="source-line-no">5458</span><span id="line-5458">    if (timestampSlop == HConstants.LATEST_TIMESTAMP) {</span> | 
 | <span class="source-line-no">5459</span><span id="line-5459">      return;</span> | 
 | <span class="source-line-no">5460</span><span id="line-5460">    }</span> | 
 | <span class="source-line-no">5461</span><span id="line-5461">    long maxTs = now + timestampSlop;</span> | 
 | <span class="source-line-no">5462</span><span id="line-5462">    for (List<Cell> kvs : familyMap.values()) {</span> | 
 | <span class="source-line-no">5463</span><span id="line-5463">      // Optimization: 'foreach' loop is not used. See:</span> | 
 | <span class="source-line-no">5464</span><span id="line-5464">      // HBASE-12023 HRegion.applyFamilyMapToMemstore creates too many iterator objects</span> | 
 | <span class="source-line-no">5465</span><span id="line-5465">      assert kvs instanceof RandomAccess;</span> | 
 | <span class="source-line-no">5466</span><span id="line-5466">      int listSize = kvs.size();</span> | 
 | <span class="source-line-no">5467</span><span id="line-5467">      for (int i = 0; i < listSize; i++) {</span> | 
 | <span class="source-line-no">5468</span><span id="line-5468">        Cell cell = kvs.get(i);</span> | 
 | <span class="source-line-no">5469</span><span id="line-5469">        // see if the user-side TS is out of range. latest = server-side</span> | 
 | <span class="source-line-no">5470</span><span id="line-5470">        long ts = cell.getTimestamp();</span> | 
 | <span class="source-line-no">5471</span><span id="line-5471">        if (ts != HConstants.LATEST_TIMESTAMP && ts > maxTs) {</span> | 
 | <span class="source-line-no">5472</span><span id="line-5472">          throw new FailedSanityCheckException(</span> | 
 | <span class="source-line-no">5473</span><span id="line-5473">            "Timestamp for KV out of range " + cell + " (too.new=" + timestampSlop + ")");</span> | 
 | <span class="source-line-no">5474</span><span id="line-5474">        }</span> | 
 | <span class="source-line-no">5475</span><span id="line-5475">      }</span> | 
 | <span class="source-line-no">5476</span><span id="line-5476">    }</span> | 
 | <span class="source-line-no">5477</span><span id="line-5477">  }</span> | 
 | <span class="source-line-no">5478</span><span id="line-5478"></span> | 
 | <span class="source-line-no">5479</span><span id="line-5479">  /*</span> | 
 | <span class="source-line-no">5480</span><span id="line-5480">   * @return True if size is over the flush threshold</span> | 
 | <span class="source-line-no">5481</span><span id="line-5481">   */</span> | 
 | <span class="source-line-no">5482</span><span id="line-5482">  private boolean isFlushSize(MemStoreSize size) {</span> | 
 | <span class="source-line-no">5483</span><span id="line-5483">    return size.getHeapSize() + size.getOffHeapSize() > getMemStoreFlushSize();</span> | 
 | <span class="source-line-no">5484</span><span id="line-5484">  }</span> | 
 | <span class="source-line-no">5485</span><span id="line-5485"></span> | 
 | <span class="source-line-no">5486</span><span id="line-5486">  private void deleteRecoveredEdits(FileSystem fs, Iterable<Path> files) throws IOException {</span> | 
 | <span class="source-line-no">5487</span><span id="line-5487">    for (Path file : files) {</span> | 
 | <span class="source-line-no">5488</span><span id="line-5488">      if (!fs.delete(file, false)) {</span> | 
 | <span class="source-line-no">5489</span><span id="line-5489">        LOG.error("Failed delete of {}", file);</span> | 
 | <span class="source-line-no">5490</span><span id="line-5490">      } else {</span> | 
 | <span class="source-line-no">5491</span><span id="line-5491">        LOG.debug("Deleted recovered.edits file={}", file);</span> | 
 | <span class="source-line-no">5492</span><span id="line-5492">      }</span> | 
 | <span class="source-line-no">5493</span><span id="line-5493">    }</span> | 
 | <span class="source-line-no">5494</span><span id="line-5494">  }</span> | 
 | <span class="source-line-no">5495</span><span id="line-5495"></span> | 
 | <span class="source-line-no">5496</span><span id="line-5496">  /**</span> | 
 | <span class="source-line-no">5497</span><span id="line-5497">   * Read the edits put under this region by wal splitting process. Put the recovered edits back up</span> | 
 | <span class="source-line-no">5498</span><span id="line-5498">   * into this region.</span> | 
 | <span class="source-line-no">5499</span><span id="line-5499">   * <p></span> | 
 | <span class="source-line-no">5500</span><span id="line-5500">   * We can ignore any wal message that has a sequence ID that's equal to or lower than minSeqId.</span> | 
 | <span class="source-line-no">5501</span><span id="line-5501">   * (Because we know such messages are already reflected in the HFiles.)</span> | 
 | <span class="source-line-no">5502</span><span id="line-5502">   * <p></span> | 
 | <span class="source-line-no">5503</span><span id="line-5503">   * While this is running we are putting pressure on memory yet we are outside of our usual</span> | 
 | <span class="source-line-no">5504</span><span id="line-5504">   * accounting because we are not yet an onlined region (this stuff is being run as part of Region</span> | 
 | <span class="source-line-no">5505</span><span id="line-5505">   * initialization). This means that if we're up against global memory limits, we'll not be flagged</span> | 
 | <span class="source-line-no">5506</span><span id="line-5506">   * to flush because we are not online. We can't be flushed by usual mechanisms anyways; we're not</span> | 
 | <span class="source-line-no">5507</span><span id="line-5507">   * yet online so our relative sequenceids are not yet aligned with WAL sequenceids -- not till we</span> | 
 | <span class="source-line-no">5508</span><span id="line-5508">   * come up online, post processing of split edits.</span> | 
 | <span class="source-line-no">5509</span><span id="line-5509">   * <p></span> | 
 | <span class="source-line-no">5510</span><span id="line-5510">   * But to help relieve memory pressure, at least manage our own heap size flushing if are in</span> | 
 | <span class="source-line-no">5511</span><span id="line-5511">   * excess of per-region limits. Flushing, though, we have to be careful and avoid using the</span> | 
 | <span class="source-line-no">5512</span><span id="line-5512">   * regionserver/wal sequenceid. Its running on a different line to whats going on in here in this</span> | 
 | <span class="source-line-no">5513</span><span id="line-5513">   * region context so if we crashed replaying these edits, but in the midst had a flush that used</span> | 
 | <span class="source-line-no">5514</span><span id="line-5514">   * the regionserver wal with a sequenceid in excess of whats going on in here in this region and</span> | 
 | <span class="source-line-no">5515</span><span id="line-5515">   * with its split editlogs, then we could miss edits the next time we go to recover. So, we have</span> | 
 | <span class="source-line-no">5516</span><span id="line-5516">   * to flush inline, using seqids that make sense in a this single region context only -- until we</span> | 
 | <span class="source-line-no">5517</span><span id="line-5517">   * online.</span> | 
 | <span class="source-line-no">5518</span><span id="line-5518">   * @param maxSeqIdInStores Any edit found in split editlogs needs to be in excess of the maxSeqId</span> | 
 | <span class="source-line-no">5519</span><span id="line-5519">   *                         for the store to be applied, else its skipped.</span> | 
 | <span class="source-line-no">5520</span><span id="line-5520">   * @return the sequence id of the last edit added to this region out of the recovered edits log or</span> | 
 | <span class="source-line-no">5521</span><span id="line-5521">   *         <code>minSeqId</code> if nothing added from editlogs.</span> | 
 | <span class="source-line-no">5522</span><span id="line-5522">   */</span> | 
 | <span class="source-line-no">5523</span><span id="line-5523">  long replayRecoveredEditsIfAny(Map<byte[], Long> maxSeqIdInStores,</span> | 
 | <span class="source-line-no">5524</span><span id="line-5524">    final CancelableProgressable reporter, final MonitoredTask status) throws IOException {</span> | 
 | <span class="source-line-no">5525</span><span id="line-5525">    long minSeqIdForTheRegion = -1;</span> | 
 | <span class="source-line-no">5526</span><span id="line-5526">    for (Long maxSeqIdInStore : maxSeqIdInStores.values()) {</span> | 
 | <span class="source-line-no">5527</span><span id="line-5527">      if (maxSeqIdInStore < minSeqIdForTheRegion || minSeqIdForTheRegion == -1) {</span> | 
 | <span class="source-line-no">5528</span><span id="line-5528">        minSeqIdForTheRegion = maxSeqIdInStore;</span> | 
 | <span class="source-line-no">5529</span><span id="line-5529">      }</span> | 
 | <span class="source-line-no">5530</span><span id="line-5530">    }</span> | 
 | <span class="source-line-no">5531</span><span id="line-5531">    long seqId = minSeqIdForTheRegion;</span> | 
 | <span class="source-line-no">5532</span><span id="line-5532">    String specialRecoveredEditsDirStr = conf.get(SPECIAL_RECOVERED_EDITS_DIR);</span> | 
 | <span class="source-line-no">5533</span><span id="line-5533">    if (org.apache.commons.lang3.StringUtils.isBlank(specialRecoveredEditsDirStr)) {</span> | 
 | <span class="source-line-no">5534</span><span id="line-5534">      FileSystem walFS = getWalFileSystem();</span> | 
 | <span class="source-line-no">5535</span><span id="line-5535">      FileSystem rootFS = getFilesystem();</span> | 
 | <span class="source-line-no">5536</span><span id="line-5536">      Path wrongRegionWALDir = CommonFSUtils.getWrongWALRegionDir(conf, getRegionInfo().getTable(),</span> | 
 | <span class="source-line-no">5537</span><span id="line-5537">        getRegionInfo().getEncodedName());</span> | 
 | <span class="source-line-no">5538</span><span id="line-5538">      Path regionWALDir = getWALRegionDir();</span> | 
 | <span class="source-line-no">5539</span><span id="line-5539">      Path regionDir =</span> | 
 | <span class="source-line-no">5540</span><span id="line-5540">        FSUtils.getRegionDirFromRootDir(CommonFSUtils.getRootDir(conf), getRegionInfo());</span> | 
 | <span class="source-line-no">5541</span><span id="line-5541"></span> | 
 | <span class="source-line-no">5542</span><span id="line-5542">      // We made a mistake in HBASE-20734 so we need to do this dirty hack...</span> | 
 | <span class="source-line-no">5543</span><span id="line-5543">      NavigableSet<Path> filesUnderWrongRegionWALDir =</span> | 
 | <span class="source-line-no">5544</span><span id="line-5544">        WALSplitUtil.getSplitEditFilesSorted(walFS, wrongRegionWALDir);</span> | 
 | <span class="source-line-no">5545</span><span id="line-5545">      seqId = Math.max(seqId, replayRecoveredEditsForPaths(minSeqIdForTheRegion, walFS,</span> | 
 | <span class="source-line-no">5546</span><span id="line-5546">        filesUnderWrongRegionWALDir, reporter, regionDir));</span> | 
 | <span class="source-line-no">5547</span><span id="line-5547">      // This is to ensure backwards compatability with HBASE-20723 where recovered edits can appear</span> | 
 | <span class="source-line-no">5548</span><span id="line-5548">      // under the root dir even if walDir is set.</span> | 
 | <span class="source-line-no">5549</span><span id="line-5549">      NavigableSet<Path> filesUnderRootDir = Collections.emptyNavigableSet();</span> | 
 | <span class="source-line-no">5550</span><span id="line-5550">      if (!regionWALDir.equals(regionDir)) {</span> | 
 | <span class="source-line-no">5551</span><span id="line-5551">        filesUnderRootDir = WALSplitUtil.getSplitEditFilesSorted(rootFS, regionDir);</span> | 
 | <span class="source-line-no">5552</span><span id="line-5552">        seqId = Math.max(seqId, replayRecoveredEditsForPaths(minSeqIdForTheRegion, rootFS,</span> | 
 | <span class="source-line-no">5553</span><span id="line-5553">          filesUnderRootDir, reporter, regionDir));</span> | 
 | <span class="source-line-no">5554</span><span id="line-5554">      }</span> | 
 | <span class="source-line-no">5555</span><span id="line-5555"></span> | 
 | <span class="source-line-no">5556</span><span id="line-5556">      NavigableSet<Path> files = WALSplitUtil.getSplitEditFilesSorted(walFS, regionWALDir);</span> | 
 | <span class="source-line-no">5557</span><span id="line-5557">      seqId = Math.max(seqId,</span> | 
 | <span class="source-line-no">5558</span><span id="line-5558">        replayRecoveredEditsForPaths(minSeqIdForTheRegion, walFS, files, reporter, regionWALDir));</span> | 
 | <span class="source-line-no">5559</span><span id="line-5559">      if (seqId > minSeqIdForTheRegion) {</span> | 
 | <span class="source-line-no">5560</span><span id="line-5560">        // Then we added some edits to memory. Flush and cleanup split edit files.</span> | 
 | <span class="source-line-no">5561</span><span id="line-5561">        internalFlushcache(null, seqId, stores.values(), status, false,</span> | 
 | <span class="source-line-no">5562</span><span id="line-5562">          FlushLifeCycleTracker.DUMMY);</span> | 
 | <span class="source-line-no">5563</span><span id="line-5563">      }</span> | 
 | <span class="source-line-no">5564</span><span id="line-5564">      // Now delete the content of recovered edits. We're done w/ them.</span> | 
 | <span class="source-line-no">5565</span><span id="line-5565">      if (files.size() > 0 && this.conf.getBoolean("hbase.region.archive.recovered.edits", false)) {</span> | 
 | <span class="source-line-no">5566</span><span id="line-5566">        // For debugging data loss issues!</span> | 
 | <span class="source-line-no">5567</span><span id="line-5567">        // If this flag is set, make use of the hfile archiving by making recovered.edits a fake</span> | 
 | <span class="source-line-no">5568</span><span id="line-5568">        // column family. Have to fake out file type too by casting our recovered.edits as</span> | 
 | <span class="source-line-no">5569</span><span id="line-5569">        // storefiles</span> | 
 | <span class="source-line-no">5570</span><span id="line-5570">        String fakeFamilyName = WALSplitUtil.getRegionDirRecoveredEditsDir(regionWALDir).getName();</span> | 
 | <span class="source-line-no">5571</span><span id="line-5571">        StoreContext storeContext =</span> | 
 | <span class="source-line-no">5572</span><span id="line-5572">          StoreContext.getBuilder().withRegionFileSystem(getRegionFileSystem()).build();</span> | 
 | <span class="source-line-no">5573</span><span id="line-5573">        StoreFileTracker sft = StoreFileTrackerFactory.create(this.conf, true, storeContext);</span> | 
 | <span class="source-line-no">5574</span><span id="line-5574">        Set<HStoreFile> fakeStoreFiles = new HashSet<>(files.size());</span> | 
 | <span class="source-line-no">5575</span><span id="line-5575">        for (Path file : files) {</span> | 
 | <span class="source-line-no">5576</span><span id="line-5576">          fakeStoreFiles.add(new HStoreFile(walFS, file, this.conf, null, null, true, sft));</span> | 
 | <span class="source-line-no">5577</span><span id="line-5577">        }</span> | 
 | <span class="source-line-no">5578</span><span id="line-5578">        getRegionWALFileSystem().archiveRecoveredEdits(fakeFamilyName, fakeStoreFiles);</span> | 
 | <span class="source-line-no">5579</span><span id="line-5579">      } else {</span> | 
 | <span class="source-line-no">5580</span><span id="line-5580">        deleteRecoveredEdits(walFS, Iterables.concat(files, filesUnderWrongRegionWALDir));</span> | 
 | <span class="source-line-no">5581</span><span id="line-5581">        deleteRecoveredEdits(rootFS, filesUnderRootDir);</span> | 
 | <span class="source-line-no">5582</span><span id="line-5582">      }</span> | 
 | <span class="source-line-no">5583</span><span id="line-5583">    } else {</span> | 
 | <span class="source-line-no">5584</span><span id="line-5584">      Path recoveredEditsDir = new Path(specialRecoveredEditsDirStr);</span> | 
 | <span class="source-line-no">5585</span><span id="line-5585">      FileSystem fs = recoveredEditsDir.getFileSystem(conf);</span> | 
 | <span class="source-line-no">5586</span><span id="line-5586">      FileStatus[] files = fs.listStatus(recoveredEditsDir);</span> | 
 | <span class="source-line-no">5587</span><span id="line-5587">      LOG.debug("Found {} recovered edits file(s) under {}", files == null ? 0 : files.length,</span> | 
 | <span class="source-line-no">5588</span><span id="line-5588">        recoveredEditsDir);</span> | 
 | <span class="source-line-no">5589</span><span id="line-5589">      if (files != null) {</span> | 
 | <span class="source-line-no">5590</span><span id="line-5590">        for (FileStatus file : files) {</span> | 
 | <span class="source-line-no">5591</span><span id="line-5591">          // it is safe to trust the zero-length in this case because we've been through rename and</span> | 
 | <span class="source-line-no">5592</span><span id="line-5592">          // lease recovery in the above.</span> | 
 | <span class="source-line-no">5593</span><span id="line-5593">          if (isZeroLengthThenDelete(fs, file, file.getPath())) {</span> | 
 | <span class="source-line-no">5594</span><span id="line-5594">            continue;</span> | 
 | <span class="source-line-no">5595</span><span id="line-5595">          }</span> | 
 | <span class="source-line-no">5596</span><span id="line-5596">          seqId =</span> | 
 | <span class="source-line-no">5597</span><span id="line-5597">            Math.max(seqId, replayRecoveredEdits(file.getPath(), maxSeqIdInStores, reporter, fs));</span> | 
 | <span class="source-line-no">5598</span><span id="line-5598">        }</span> | 
 | <span class="source-line-no">5599</span><span id="line-5599">      }</span> | 
 | <span class="source-line-no">5600</span><span id="line-5600">      if (seqId > minSeqIdForTheRegion) {</span> | 
 | <span class="source-line-no">5601</span><span id="line-5601">        // Then we added some edits to memory. Flush and cleanup split edit files.</span> | 
 | <span class="source-line-no">5602</span><span id="line-5602">        internalFlushcache(null, seqId, stores.values(), status, false,</span> | 
 | <span class="source-line-no">5603</span><span id="line-5603">          FlushLifeCycleTracker.DUMMY);</span> | 
 | <span class="source-line-no">5604</span><span id="line-5604">      }</span> | 
 | <span class="source-line-no">5605</span><span id="line-5605">      deleteRecoveredEdits(fs,</span> | 
 | <span class="source-line-no">5606</span><span id="line-5606">        Stream.of(files).map(FileStatus::getPath).collect(Collectors.toList()));</span> | 
 | <span class="source-line-no">5607</span><span id="line-5607">    }</span> | 
 | <span class="source-line-no">5608</span><span id="line-5608"></span> | 
 | <span class="source-line-no">5609</span><span id="line-5609">    return seqId;</span> | 
 | <span class="source-line-no">5610</span><span id="line-5610">  }</span> | 
 | <span class="source-line-no">5611</span><span id="line-5611"></span> | 
 | <span class="source-line-no">5612</span><span id="line-5612">  private long replayRecoveredEditsForPaths(long minSeqIdForTheRegion, FileSystem fs,</span> | 
 | <span class="source-line-no">5613</span><span id="line-5613">    final NavigableSet<Path> files, final CancelableProgressable reporter, final Path regionDir)</span> | 
 | <span class="source-line-no">5614</span><span id="line-5614">    throws IOException {</span> | 
 | <span class="source-line-no">5615</span><span id="line-5615">    long seqid = minSeqIdForTheRegion;</span> | 
 | <span class="source-line-no">5616</span><span id="line-5616">    if (LOG.isDebugEnabled()) {</span> | 
 | <span class="source-line-no">5617</span><span id="line-5617">      LOG.debug("Found " + (files == null ? 0 : files.size()) + " recovered edits file(s) under "</span> | 
 | <span class="source-line-no">5618</span><span id="line-5618">        + regionDir);</span> | 
 | <span class="source-line-no">5619</span><span id="line-5619">    }</span> | 
 | <span class="source-line-no">5620</span><span id="line-5620"></span> | 
 | <span class="source-line-no">5621</span><span id="line-5621">    if (files == null || files.isEmpty()) {</span> | 
 | <span class="source-line-no">5622</span><span id="line-5622">      return minSeqIdForTheRegion;</span> | 
 | <span class="source-line-no">5623</span><span id="line-5623">    }</span> | 
 | <span class="source-line-no">5624</span><span id="line-5624"></span> | 
 | <span class="source-line-no">5625</span><span id="line-5625">    for (Path edits : files) {</span> | 
 | <span class="source-line-no">5626</span><span id="line-5626">      if (edits == null || !fs.exists(edits)) {</span> | 
 | <span class="source-line-no">5627</span><span id="line-5627">        LOG.warn("Null or non-existent edits file: " + edits);</span> | 
 | <span class="source-line-no">5628</span><span id="line-5628">        continue;</span> | 
 | <span class="source-line-no">5629</span><span id="line-5629">      }</span> | 
 | <span class="source-line-no">5630</span><span id="line-5630">      if (isZeroLengthThenDelete(fs, fs.getFileStatus(edits), edits)) {</span> | 
 | <span class="source-line-no">5631</span><span id="line-5631">        continue;</span> | 
 | <span class="source-line-no">5632</span><span id="line-5632">      }</span> | 
 | <span class="source-line-no">5633</span><span id="line-5633"></span> | 
 | <span class="source-line-no">5634</span><span id="line-5634">      long maxSeqId;</span> | 
 | <span class="source-line-no">5635</span><span id="line-5635">      String fileName = edits.getName();</span> | 
 | <span class="source-line-no">5636</span><span id="line-5636">      maxSeqId = Math.abs(Long.parseLong(fileName));</span> | 
 | <span class="source-line-no">5637</span><span id="line-5637">      if (maxSeqId <= minSeqIdForTheRegion) {</span> | 
 | <span class="source-line-no">5638</span><span id="line-5638">        if (LOG.isDebugEnabled()) {</span> | 
 | <span class="source-line-no">5639</span><span id="line-5639">          String msg = "Maximum sequenceid for this wal is " + maxSeqId</span> | 
 | <span class="source-line-no">5640</span><span id="line-5640">            + " and minimum sequenceid for the region " + this + "  is " + minSeqIdForTheRegion</span> | 
 | <span class="source-line-no">5641</span><span id="line-5641">            + ", skipped the whole file, path=" + edits;</span> | 
 | <span class="source-line-no">5642</span><span id="line-5642">          LOG.debug(msg);</span> | 
 | <span class="source-line-no">5643</span><span id="line-5643">        }</span> | 
 | <span class="source-line-no">5644</span><span id="line-5644">        continue;</span> | 
 | <span class="source-line-no">5645</span><span id="line-5645">      }</span> | 
 | <span class="source-line-no">5646</span><span id="line-5646"></span> | 
 | <span class="source-line-no">5647</span><span id="line-5647">      try {</span> | 
 | <span class="source-line-no">5648</span><span id="line-5648">        // replay the edits. Replay can return -1 if everything is skipped, only update</span> | 
 | <span class="source-line-no">5649</span><span id="line-5649">        // if seqId is greater</span> | 
 | <span class="source-line-no">5650</span><span id="line-5650">        seqid = Math.max(seqid, replayRecoveredEdits(edits, maxSeqIdInStores, reporter, fs));</span> | 
 | <span class="source-line-no">5651</span><span id="line-5651">      } catch (IOException e) {</span> | 
 | <span class="source-line-no">5652</span><span id="line-5652">        handleException(fs, edits, e);</span> | 
 | <span class="source-line-no">5653</span><span id="line-5653">      }</span> | 
 | <span class="source-line-no">5654</span><span id="line-5654">    }</span> | 
 | <span class="source-line-no">5655</span><span id="line-5655">    return seqid;</span> | 
 | <span class="source-line-no">5656</span><span id="line-5656">  }</span> | 
 | <span class="source-line-no">5657</span><span id="line-5657"></span> | 
 | <span class="source-line-no">5658</span><span id="line-5658">  private void handleException(FileSystem fs, Path edits, IOException e) throws IOException {</span> | 
 | <span class="source-line-no">5659</span><span id="line-5659">    boolean skipErrors = conf.getBoolean(HConstants.HREGION_EDITS_REPLAY_SKIP_ERRORS,</span> | 
 | <span class="source-line-no">5660</span><span id="line-5660">      conf.getBoolean("hbase.skip.errors", HConstants.DEFAULT_HREGION_EDITS_REPLAY_SKIP_ERRORS));</span> | 
 | <span class="source-line-no">5661</span><span id="line-5661">    if (conf.get("hbase.skip.errors") != null) {</span> | 
 | <span class="source-line-no">5662</span><span id="line-5662">      LOG.warn("The property 'hbase.skip.errors' has been deprecated. Please use "</span> | 
 | <span class="source-line-no">5663</span><span id="line-5663">        + HConstants.HREGION_EDITS_REPLAY_SKIP_ERRORS + " instead.");</span> | 
 | <span class="source-line-no">5664</span><span id="line-5664">    }</span> | 
 | <span class="source-line-no">5665</span><span id="line-5665">    if (skipErrors) {</span> | 
 | <span class="source-line-no">5666</span><span id="line-5666">      Path p = WALSplitUtil.moveAsideBadEditsFile(fs, edits);</span> | 
 | <span class="source-line-no">5667</span><span id="line-5667">      LOG.error(HConstants.HREGION_EDITS_REPLAY_SKIP_ERRORS + "=true so continuing. Renamed "</span> | 
 | <span class="source-line-no">5668</span><span id="line-5668">        + edits + " as " + p, e);</span> | 
 | <span class="source-line-no">5669</span><span id="line-5669">    } else {</span> | 
 | <span class="source-line-no">5670</span><span id="line-5670">      throw e;</span> | 
 | <span class="source-line-no">5671</span><span id="line-5671">    }</span> | 
 | <span class="source-line-no">5672</span><span id="line-5672">  }</span> | 
 | <span class="source-line-no">5673</span><span id="line-5673"></span> | 
 | <span class="source-line-no">5674</span><span id="line-5674">  /**</span> | 
 | <span class="source-line-no">5675</span><span id="line-5675">   * @param edits            File of recovered edits.</span> | 
 | <span class="source-line-no">5676</span><span id="line-5676">   * @param maxSeqIdInStores Maximum sequenceid found in each store. Edits in wal must be larger</span> | 
 | <span class="source-line-no">5677</span><span id="line-5677">   *                         than this to be replayed for each store.</span> | 
 | <span class="source-line-no">5678</span><span id="line-5678">   * @return the sequence id of the last edit added to this region out of the recovered edits log or</span> | 
 | <span class="source-line-no">5679</span><span id="line-5679">   *         <code>minSeqId</code> if nothing added from editlogs.</span> | 
 | <span class="source-line-no">5680</span><span id="line-5680">   */</span> | 
 | <span class="source-line-no">5681</span><span id="line-5681">  private long replayRecoveredEdits(final Path edits, Map<byte[], Long> maxSeqIdInStores,</span> | 
 | <span class="source-line-no">5682</span><span id="line-5682">    final CancelableProgressable reporter, FileSystem fs) throws IOException {</span> | 
 | <span class="source-line-no">5683</span><span id="line-5683">    String msg = "Replaying edits from " + edits;</span> | 
 | <span class="source-line-no">5684</span><span id="line-5684">    LOG.info(msg);</span> | 
 | <span class="source-line-no">5685</span><span id="line-5685">    MonitoredTask status = TaskMonitor.get().createStatus(msg);</span> | 
 | <span class="source-line-no">5686</span><span id="line-5686"></span> | 
 | <span class="source-line-no">5687</span><span id="line-5687">    status.setStatus("Opening recovered edits");</span> | 
 | <span class="source-line-no">5688</span><span id="line-5688">    try (WALStreamReader reader = WALFactory.createStreamReader(fs, edits, conf)) {</span> | 
 | <span class="source-line-no">5689</span><span id="line-5689">      long currentEditSeqId = -1;</span> | 
 | <span class="source-line-no">5690</span><span id="line-5690">      long currentReplaySeqId = -1;</span> | 
 | <span class="source-line-no">5691</span><span id="line-5691">      long firstSeqIdInLog = -1;</span> | 
 | <span class="source-line-no">5692</span><span id="line-5692">      long skippedEdits = 0;</span> | 
 | <span class="source-line-no">5693</span><span id="line-5693">      long editsCount = 0;</span> | 
 | <span class="source-line-no">5694</span><span id="line-5694">      long intervalEdits = 0;</span> | 
 | <span class="source-line-no">5695</span><span id="line-5695">      WAL.Entry entry;</span> | 
 | <span class="source-line-no">5696</span><span id="line-5696">      HStore store = null;</span> | 
 | <span class="source-line-no">5697</span><span id="line-5697">      boolean reported_once = false;</span> | 
 | <span class="source-line-no">5698</span><span id="line-5698">      ServerNonceManager ng = this.rsServices == null ? null : this.rsServices.getNonceManager();</span> | 
 | <span class="source-line-no">5699</span><span id="line-5699"></span> | 
 | <span class="source-line-no">5700</span><span id="line-5700">      try {</span> | 
 | <span class="source-line-no">5701</span><span id="line-5701">        // How many edits seen before we check elapsed time</span> | 
 | <span class="source-line-no">5702</span><span id="line-5702">        int interval = this.conf.getInt("hbase.hstore.report.interval.edits", 2000);</span> | 
 | <span class="source-line-no">5703</span><span id="line-5703">        // How often to send a progress report (default 1/2 master timeout)</span> | 
 | <span class="source-line-no">5704</span><span id="line-5704">        int period = this.conf.getInt("hbase.hstore.report.period", 300000);</span> | 
 | <span class="source-line-no">5705</span><span id="line-5705">        long lastReport = EnvironmentEdgeManager.currentTime();</span> | 
 | <span class="source-line-no">5706</span><span id="line-5706"></span> | 
 | <span class="source-line-no">5707</span><span id="line-5707">        if (coprocessorHost != null) {</span> | 
 | <span class="source-line-no">5708</span><span id="line-5708">          coprocessorHost.preReplayWALs(this.getRegionInfo(), edits);</span> | 
 | <span class="source-line-no">5709</span><span id="line-5709">        }</span> | 
 | <span class="source-line-no">5710</span><span id="line-5710"></span> | 
 | <span class="source-line-no">5711</span><span id="line-5711">        while ((entry = reader.next()) != null) {</span> | 
 | <span class="source-line-no">5712</span><span id="line-5712">          WALKey key = entry.getKey();</span> | 
 | <span class="source-line-no">5713</span><span id="line-5713">          WALEdit val = entry.getEdit();</span> | 
 | <span class="source-line-no">5714</span><span id="line-5714"></span> | 
 | <span class="source-line-no">5715</span><span id="line-5715">          if (ng != null) { // some test, or nonces disabled</span> | 
 | <span class="source-line-no">5716</span><span id="line-5716">            ng.reportOperationFromWal(key.getNonceGroup(), key.getNonce(), key.getWriteTime());</span> | 
 | <span class="source-line-no">5717</span><span id="line-5717">          }</span> | 
 | <span class="source-line-no">5718</span><span id="line-5718"></span> | 
 | <span class="source-line-no">5719</span><span id="line-5719">          if (reporter != null) {</span> | 
 | <span class="source-line-no">5720</span><span id="line-5720">            intervalEdits += val.size();</span> | 
 | <span class="source-line-no">5721</span><span id="line-5721">            if (intervalEdits >= interval) {</span> | 
 | <span class="source-line-no">5722</span><span id="line-5722">              // Number of edits interval reached</span> | 
 | <span class="source-line-no">5723</span><span id="line-5723">              intervalEdits = 0;</span> | 
 | <span class="source-line-no">5724</span><span id="line-5724">              long cur = EnvironmentEdgeManager.currentTime();</span> | 
 | <span class="source-line-no">5725</span><span id="line-5725">              if (lastReport + period <= cur) {</span> | 
 | <span class="source-line-no">5726</span><span id="line-5726">                status.setStatus(</span> | 
 | <span class="source-line-no">5727</span><span id="line-5727">                  "Replaying edits..." + " skipped=" + skippedEdits + " edits=" + editsCount);</span> | 
 | <span class="source-line-no">5728</span><span id="line-5728">                // Timeout reached</span> | 
 | <span class="source-line-no">5729</span><span id="line-5729">                if (!reporter.progress()) {</span> | 
 | <span class="source-line-no">5730</span><span id="line-5730">                  msg = "Progressable reporter failed, stopping replay for region " + this;</span> | 
 | <span class="source-line-no">5731</span><span id="line-5731">                  LOG.warn(msg);</span> | 
 | <span class="source-line-no">5732</span><span id="line-5732">                  status.abort(msg);</span> | 
 | <span class="source-line-no">5733</span><span id="line-5733">                  throw new IOException(msg);</span> | 
 | <span class="source-line-no">5734</span><span id="line-5734">                }</span> | 
 | <span class="source-line-no">5735</span><span id="line-5735">                reported_once = true;</span> | 
 | <span class="source-line-no">5736</span><span id="line-5736">                lastReport = cur;</span> | 
 | <span class="source-line-no">5737</span><span id="line-5737">              }</span> | 
 | <span class="source-line-no">5738</span><span id="line-5738">            }</span> | 
 | <span class="source-line-no">5739</span><span id="line-5739">          }</span> | 
 | <span class="source-line-no">5740</span><span id="line-5740"></span> | 
 | <span class="source-line-no">5741</span><span id="line-5741">          if (firstSeqIdInLog == -1) {</span> | 
 | <span class="source-line-no">5742</span><span id="line-5742">            firstSeqIdInLog = key.getSequenceId();</span> | 
 | <span class="source-line-no">5743</span><span id="line-5743">          }</span> | 
 | <span class="source-line-no">5744</span><span id="line-5744">          if (currentEditSeqId > key.getSequenceId()) {</span> | 
 | <span class="source-line-no">5745</span><span id="line-5745">            // when this condition is true, it means we have a serious defect because we need to</span> | 
 | <span class="source-line-no">5746</span><span id="line-5746">            // maintain increasing SeqId for WAL edits per region</span> | 
 | <span class="source-line-no">5747</span><span id="line-5747">            LOG.error(getRegionInfo().getEncodedName() + " : " + "Found decreasing SeqId. PreId="</span> | 
 | <span class="source-line-no">5748</span><span id="line-5748">              + currentEditSeqId + " key=" + key + "; edit=" + val);</span> | 
 | <span class="source-line-no">5749</span><span id="line-5749">          } else {</span> | 
 | <span class="source-line-no">5750</span><span id="line-5750">            currentEditSeqId = key.getSequenceId();</span> | 
 | <span class="source-line-no">5751</span><span id="line-5751">          }</span> | 
 | <span class="source-line-no">5752</span><span id="line-5752">          currentReplaySeqId =</span> | 
 | <span class="source-line-no">5753</span><span id="line-5753">            (key.getOrigLogSeqNum() > 0) ? key.getOrigLogSeqNum() : currentEditSeqId;</span> | 
 | <span class="source-line-no">5754</span><span id="line-5754"></span> | 
 | <span class="source-line-no">5755</span><span id="line-5755">          // Start coprocessor replay here. The coprocessor is for each WALEdit</span> | 
 | <span class="source-line-no">5756</span><span id="line-5756">          // instead of a KeyValue.</span> | 
 | <span class="source-line-no">5757</span><span id="line-5757">          if (coprocessorHost != null) {</span> | 
 | <span class="source-line-no">5758</span><span id="line-5758">            status.setStatus("Running pre-WAL-restore hook in coprocessors");</span> | 
 | <span class="source-line-no">5759</span><span id="line-5759">            if (coprocessorHost.preWALRestore(this.getRegionInfo(), key, val)) {</span> | 
 | <span class="source-line-no">5760</span><span id="line-5760">              // if bypass this wal entry, ignore it ...</span> | 
 | <span class="source-line-no">5761</span><span id="line-5761">              continue;</span> | 
 | <span class="source-line-no">5762</span><span id="line-5762">            }</span> | 
 | <span class="source-line-no">5763</span><span id="line-5763">          }</span> | 
 | <span class="source-line-no">5764</span><span id="line-5764">          boolean checkRowWithinBoundary = false;</span> | 
 | <span class="source-line-no">5765</span><span id="line-5765">          // Check this edit is for this region.</span> | 
 | <span class="source-line-no">5766</span><span id="line-5766">          if (</span> | 
 | <span class="source-line-no">5767</span><span id="line-5767">            !Bytes.equals(key.getEncodedRegionName(), this.getRegionInfo().getEncodedNameAsBytes())</span> | 
 | <span class="source-line-no">5768</span><span id="line-5768">          ) {</span> | 
 | <span class="source-line-no">5769</span><span id="line-5769">            checkRowWithinBoundary = true;</span> | 
 | <span class="source-line-no">5770</span><span id="line-5770">          }</span> | 
 | <span class="source-line-no">5771</span><span id="line-5771"></span> | 
 | <span class="source-line-no">5772</span><span id="line-5772">          boolean flush = false;</span> | 
 | <span class="source-line-no">5773</span><span id="line-5773">          MemStoreSizing memStoreSizing = new NonThreadSafeMemStoreSizing();</span> | 
 | <span class="source-line-no">5774</span><span id="line-5774">          for (Cell c : val.getCells()) {</span> | 
 | <span class="source-line-no">5775</span><span id="line-5775">            assert c instanceof ExtendedCell;</span> | 
 | <span class="source-line-no">5776</span><span id="line-5776">            ExtendedCell cell = (ExtendedCell) c;</span> | 
 | <span class="source-line-no">5777</span><span id="line-5777">            // Check this edit is for me. Also, guard against writing the special</span> | 
 | <span class="source-line-no">5778</span><span id="line-5778">            // METACOLUMN info such as HBASE::CACHEFLUSH entries</span> | 
 | <span class="source-line-no">5779</span><span id="line-5779">            if (WALEdit.isMetaEditFamily(cell)) {</span> | 
 | <span class="source-line-no">5780</span><span id="line-5780">              // if region names don't match, skipp replaying compaction marker</span> | 
 | <span class="source-line-no">5781</span><span id="line-5781">              if (!checkRowWithinBoundary) {</span> | 
 | <span class="source-line-no">5782</span><span id="line-5782">                // this is a special edit, we should handle it</span> | 
 | <span class="source-line-no">5783</span><span id="line-5783">                CompactionDescriptor compaction = WALEdit.getCompaction(cell);</span> | 
 | <span class="source-line-no">5784</span><span id="line-5784">                if (compaction != null) {</span> | 
 | <span class="source-line-no">5785</span><span id="line-5785">                  // replay the compaction</span> | 
 | <span class="source-line-no">5786</span><span id="line-5786">                  replayWALCompactionMarker(compaction, false, true, Long.MAX_VALUE);</span> | 
 | <span class="source-line-no">5787</span><span id="line-5787">                }</span> | 
 | <span class="source-line-no">5788</span><span id="line-5788">              }</span> | 
 | <span class="source-line-no">5789</span><span id="line-5789">              skippedEdits++;</span> | 
 | <span class="source-line-no">5790</span><span id="line-5790">              continue;</span> | 
 | <span class="source-line-no">5791</span><span id="line-5791">            }</span> | 
 | <span class="source-line-no">5792</span><span id="line-5792">            // Figure which store the edit is meant for.</span> | 
 | <span class="source-line-no">5793</span><span id="line-5793">            if (</span> | 
 | <span class="source-line-no">5794</span><span id="line-5794">              store == null</span> | 
 | <span class="source-line-no">5795</span><span id="line-5795">                || !CellUtil.matchingFamily(cell, store.getColumnFamilyDescriptor().getName())</span> | 
 | <span class="source-line-no">5796</span><span id="line-5796">            ) {</span> | 
 | <span class="source-line-no">5797</span><span id="line-5797">              store = getStore(cell);</span> | 
 | <span class="source-line-no">5798</span><span id="line-5798">            }</span> | 
 | <span class="source-line-no">5799</span><span id="line-5799">            if (store == null) {</span> | 
 | <span class="source-line-no">5800</span><span id="line-5800">              // This should never happen. Perhaps schema was changed between</span> | 
 | <span class="source-line-no">5801</span><span id="line-5801">              // crash and redeploy?</span> | 
 | <span class="source-line-no">5802</span><span id="line-5802">              LOG.warn("No family for cell {} in region {}", cell, this);</span> | 
 | <span class="source-line-no">5803</span><span id="line-5803">              skippedEdits++;</span> | 
 | <span class="source-line-no">5804</span><span id="line-5804">              continue;</span> | 
 | <span class="source-line-no">5805</span><span id="line-5805">            }</span> | 
 | <span class="source-line-no">5806</span><span id="line-5806">            if (</span> | 
 | <span class="source-line-no">5807</span><span id="line-5807">              checkRowWithinBoundary && !rowIsInRange(this.getRegionInfo(), cell.getRowArray(),</span> | 
 | <span class="source-line-no">5808</span><span id="line-5808">                cell.getRowOffset(), cell.getRowLength())</span> | 
 | <span class="source-line-no">5809</span><span id="line-5809">            ) {</span> | 
 | <span class="source-line-no">5810</span><span id="line-5810">              LOG.warn("Row of {} is not within region boundary for region {}", cell, this);</span> | 
 | <span class="source-line-no">5811</span><span id="line-5811">              skippedEdits++;</span> | 
 | <span class="source-line-no">5812</span><span id="line-5812">              continue;</span> | 
 | <span class="source-line-no">5813</span><span id="line-5813">            }</span> | 
 | <span class="source-line-no">5814</span><span id="line-5814">            // Now, figure if we should skip this edit.</span> | 
 | <span class="source-line-no">5815</span><span id="line-5815">            if (</span> | 
 | <span class="source-line-no">5816</span><span id="line-5816">              key.getSequenceId()</span> | 
 | <span class="source-line-no">5817</span><span id="line-5817">                  <= maxSeqIdInStores.get(store.getColumnFamilyDescriptor().getName())</span> | 
 | <span class="source-line-no">5818</span><span id="line-5818">            ) {</span> | 
 | <span class="source-line-no">5819</span><span id="line-5819">              skippedEdits++;</span> | 
 | <span class="source-line-no">5820</span><span id="line-5820">              continue;</span> | 
 | <span class="source-line-no">5821</span><span id="line-5821">            }</span> | 
 | <span class="source-line-no">5822</span><span id="line-5822">            PrivateCellUtil.setSequenceId(cell, currentReplaySeqId);</span> | 
 | <span class="source-line-no">5823</span><span id="line-5823"></span> | 
 | <span class="source-line-no">5824</span><span id="line-5824">            restoreEdit(store, cell, memStoreSizing);</span> | 
 | <span class="source-line-no">5825</span><span id="line-5825">            editsCount++;</span> | 
 | <span class="source-line-no">5826</span><span id="line-5826">          }</span> | 
 | <span class="source-line-no">5827</span><span id="line-5827">          MemStoreSize mss = memStoreSizing.getMemStoreSize();</span> | 
 | <span class="source-line-no">5828</span><span id="line-5828">          incMemStoreSize(mss);</span> | 
 | <span class="source-line-no">5829</span><span id="line-5829">          flush = isFlushSize(this.memStoreSizing.getMemStoreSize());</span> | 
 | <span class="source-line-no">5830</span><span id="line-5830">          if (flush) {</span> | 
 | <span class="source-line-no">5831</span><span id="line-5831">            internalFlushcache(null, currentEditSeqId, stores.values(), status, false,</span> | 
 | <span class="source-line-no">5832</span><span id="line-5832">              FlushLifeCycleTracker.DUMMY);</span> | 
 | <span class="source-line-no">5833</span><span id="line-5833">          }</span> | 
 | <span class="source-line-no">5834</span><span id="line-5834"></span> | 
 | <span class="source-line-no">5835</span><span id="line-5835">          if (coprocessorHost != null) {</span> | 
 | <span class="source-line-no">5836</span><span id="line-5836">            coprocessorHost.postWALRestore(this.getRegionInfo(), key, val);</span> | 
 | <span class="source-line-no">5837</span><span id="line-5837">          }</span> | 
 | <span class="source-line-no">5838</span><span id="line-5838">        }</span> | 
 | <span class="source-line-no">5839</span><span id="line-5839"></span> | 
 | <span class="source-line-no">5840</span><span id="line-5840">        if (coprocessorHost != null) {</span> | 
 | <span class="source-line-no">5841</span><span id="line-5841">          coprocessorHost.postReplayWALs(this.getRegionInfo(), edits);</span> | 
 | <span class="source-line-no">5842</span><span id="line-5842">        }</span> | 
 | <span class="source-line-no">5843</span><span id="line-5843">      } catch (EOFException eof) {</span> | 
 | <span class="source-line-no">5844</span><span id="line-5844">        if (!conf.getBoolean(RECOVERED_EDITS_IGNORE_EOF, false)) {</span> | 
 | <span class="source-line-no">5845</span><span id="line-5845">          Path p = WALSplitUtil.moveAsideBadEditsFile(fs, edits);</span> | 
 | <span class="source-line-no">5846</span><span id="line-5846">          msg = "EnLongAddered EOF. Most likely due to Master failure during "</span> | 
 | <span class="source-line-no">5847</span><span id="line-5847">            + "wal splitting, so we have this data in another edit. Continuing, but renaming "</span> | 
 | <span class="source-line-no">5848</span><span id="line-5848">            + edits + " as " + p + " for region " + this;</span> | 
 | <span class="source-line-no">5849</span><span id="line-5849">          LOG.warn(msg, eof);</span> | 
 | <span class="source-line-no">5850</span><span id="line-5850">          status.abort(msg);</span> | 
 | <span class="source-line-no">5851</span><span id="line-5851">        } else {</span> | 
 | <span class="source-line-no">5852</span><span id="line-5852">          LOG.warn("EOF while replaying recover edits and config '{}' is true so "</span> | 
 | <span class="source-line-no">5853</span><span id="line-5853">            + "we will ignore it and continue", RECOVERED_EDITS_IGNORE_EOF, eof);</span> | 
 | <span class="source-line-no">5854</span><span id="line-5854">        }</span> | 
 | <span class="source-line-no">5855</span><span id="line-5855">      } catch (IOException ioe) {</span> | 
 | <span class="source-line-no">5856</span><span id="line-5856">        // If the IOE resulted from bad file format,</span> | 
 | <span class="source-line-no">5857</span><span id="line-5857">        // then this problem is idempotent and retrying won't help</span> | 
 | <span class="source-line-no">5858</span><span id="line-5858">        if (ioe.getCause() instanceof ParseException) {</span> | 
 | <span class="source-line-no">5859</span><span id="line-5859">          Path p = WALSplitUtil.moveAsideBadEditsFile(fs, edits);</span> | 
 | <span class="source-line-no">5860</span><span id="line-5860">          msg =</span> | 
 | <span class="source-line-no">5861</span><span id="line-5861">            "File corruption enLongAddered!  " + "Continuing, but renaming " + edits + " as " + p;</span> | 
 | <span class="source-line-no">5862</span><span id="line-5862">          LOG.warn(msg, ioe);</span> | 
 | <span class="source-line-no">5863</span><span id="line-5863">          status.setStatus(msg);</span> | 
 | <span class="source-line-no">5864</span><span id="line-5864">        } else {</span> | 
 | <span class="source-line-no">5865</span><span id="line-5865">          status.abort(StringUtils.stringifyException(ioe));</span> | 
 | <span class="source-line-no">5866</span><span id="line-5866">          // other IO errors may be transient (bad network connection,</span> | 
 | <span class="source-line-no">5867</span><span id="line-5867">          // checksum exception on one datanode, etc). throw & retry</span> | 
 | <span class="source-line-no">5868</span><span id="line-5868">          throw ioe;</span> | 
 | <span class="source-line-no">5869</span><span id="line-5869">        }</span> | 
 | <span class="source-line-no">5870</span><span id="line-5870">      }</span> | 
 | <span class="source-line-no">5871</span><span id="line-5871">      if (reporter != null && !reported_once) {</span> | 
 | <span class="source-line-no">5872</span><span id="line-5872">        reporter.progress();</span> | 
 | <span class="source-line-no">5873</span><span id="line-5873">      }</span> | 
 | <span class="source-line-no">5874</span><span id="line-5874">      msg = "Applied " + editsCount + ", skipped " + skippedEdits + ", firstSequenceIdInLog="</span> | 
 | <span class="source-line-no">5875</span><span id="line-5875">        + firstSeqIdInLog + ", maxSequenceIdInLog=" + currentEditSeqId + ", path=" + edits;</span> | 
 | <span class="source-line-no">5876</span><span id="line-5876">      status.markComplete(msg);</span> | 
 | <span class="source-line-no">5877</span><span id="line-5877">      LOG.debug(msg);</span> | 
 | <span class="source-line-no">5878</span><span id="line-5878">      return currentEditSeqId;</span> | 
 | <span class="source-line-no">5879</span><span id="line-5879">    } finally {</span> | 
 | <span class="source-line-no">5880</span><span id="line-5880">      status.cleanup();</span> | 
 | <span class="source-line-no">5881</span><span id="line-5881">    }</span> | 
 | <span class="source-line-no">5882</span><span id="line-5882">  }</span> | 
 | <span class="source-line-no">5883</span><span id="line-5883"></span> | 
 | <span class="source-line-no">5884</span><span id="line-5884">  /**</span> | 
 | <span class="source-line-no">5885</span><span id="line-5885">   * Call to complete a compaction. Its for the case where we find in the WAL a compaction that was</span> | 
 | <span class="source-line-no">5886</span><span id="line-5886">   * not finished. We could find one recovering a WAL after a regionserver crash. See HBASE-2331.</span> | 
 | <span class="source-line-no">5887</span><span id="line-5887">   */</span> | 
 | <span class="source-line-no">5888</span><span id="line-5888">  void replayWALCompactionMarker(CompactionDescriptor compaction, boolean pickCompactionFiles,</span> | 
 | <span class="source-line-no">5889</span><span id="line-5889">    boolean removeFiles, long replaySeqId) throws IOException {</span> | 
 | <span class="source-line-no">5890</span><span id="line-5890">    try {</span> | 
 | <span class="source-line-no">5891</span><span id="line-5891">      checkTargetRegion(compaction.getEncodedRegionName().toByteArray(),</span> | 
 | <span class="source-line-no">5892</span><span id="line-5892">        "Compaction marker from WAL ", compaction);</span> | 
 | <span class="source-line-no">5893</span><span id="line-5893">    } catch (WrongRegionException wre) {</span> | 
 | <span class="source-line-no">5894</span><span id="line-5894">      if (RegionReplicaUtil.isDefaultReplica(this.getRegionInfo())) {</span> | 
 | <span class="source-line-no">5895</span><span id="line-5895">        // skip the compaction marker since it is not for this region</span> | 
 | <span class="source-line-no">5896</span><span id="line-5896">        return;</span> | 
 | <span class="source-line-no">5897</span><span id="line-5897">      }</span> | 
 | <span class="source-line-no">5898</span><span id="line-5898">      throw wre;</span> | 
 | <span class="source-line-no">5899</span><span id="line-5899">    }</span> | 
 | <span class="source-line-no">5900</span><span id="line-5900"></span> | 
 | <span class="source-line-no">5901</span><span id="line-5901">    synchronized (writestate) {</span> | 
 | <span class="source-line-no">5902</span><span id="line-5902">      if (replaySeqId < lastReplayedOpenRegionSeqId) {</span> | 
 | <span class="source-line-no">5903</span><span id="line-5903">        LOG.warn(getRegionInfo().getEncodedName() + " : " + "Skipping replaying compaction event :"</span> | 
 | <span class="source-line-no">5904</span><span id="line-5904">          + TextFormat.shortDebugString(compaction) + " because its sequence id " + replaySeqId</span> | 
 | <span class="source-line-no">5905</span><span id="line-5905">          + " is smaller than this regions " + "lastReplayedOpenRegionSeqId of "</span> | 
 | <span class="source-line-no">5906</span><span id="line-5906">          + lastReplayedOpenRegionSeqId);</span> | 
 | <span class="source-line-no">5907</span><span id="line-5907">        return;</span> | 
 | <span class="source-line-no">5908</span><span id="line-5908">      }</span> | 
 | <span class="source-line-no">5909</span><span id="line-5909">      if (replaySeqId < lastReplayedCompactionSeqId) {</span> | 
 | <span class="source-line-no">5910</span><span id="line-5910">        LOG.warn(getRegionInfo().getEncodedName() + " : " + "Skipping replaying compaction event :"</span> | 
 | <span class="source-line-no">5911</span><span id="line-5911">          + TextFormat.shortDebugString(compaction) + " because its sequence id " + replaySeqId</span> | 
 | <span class="source-line-no">5912</span><span id="line-5912">          + " is smaller than this regions " + "lastReplayedCompactionSeqId of "</span> | 
 | <span class="source-line-no">5913</span><span id="line-5913">          + lastReplayedCompactionSeqId);</span> | 
 | <span class="source-line-no">5914</span><span id="line-5914">        return;</span> | 
 | <span class="source-line-no">5915</span><span id="line-5915">      } else {</span> | 
 | <span class="source-line-no">5916</span><span id="line-5916">        lastReplayedCompactionSeqId = replaySeqId;</span> | 
 | <span class="source-line-no">5917</span><span id="line-5917">      }</span> | 
 | <span class="source-line-no">5918</span><span id="line-5918"></span> | 
 | <span class="source-line-no">5919</span><span id="line-5919">      if (LOG.isDebugEnabled()) {</span> | 
 | <span class="source-line-no">5920</span><span id="line-5920">        LOG.debug(getRegionInfo().getEncodedName() + " : " + "Replaying compaction marker "</span> | 
 | <span class="source-line-no">5921</span><span id="line-5921">          + TextFormat.shortDebugString(compaction) + " with seqId=" + replaySeqId</span> | 
 | <span class="source-line-no">5922</span><span id="line-5922">          + " and lastReplayedOpenRegionSeqId=" + lastReplayedOpenRegionSeqId);</span> | 
 | <span class="source-line-no">5923</span><span id="line-5923">      }</span> | 
 | <span class="source-line-no">5924</span><span id="line-5924"></span> | 
 | <span class="source-line-no">5925</span><span id="line-5925">      startRegionOperation(Operation.REPLAY_EVENT);</span> | 
 | <span class="source-line-no">5926</span><span id="line-5926">      try {</span> | 
 | <span class="source-line-no">5927</span><span id="line-5927">        HStore store = this.getStore(compaction.getFamilyName().toByteArray());</span> | 
 | <span class="source-line-no">5928</span><span id="line-5928">        if (store == null) {</span> | 
 | <span class="source-line-no">5929</span><span id="line-5929">          LOG.warn(getRegionInfo().getEncodedName() + " : "</span> | 
 | <span class="source-line-no">5930</span><span id="line-5930">            + "Found Compaction WAL edit for deleted family:"</span> | 
 | <span class="source-line-no">5931</span><span id="line-5931">            + Bytes.toString(compaction.getFamilyName().toByteArray()));</span> | 
 | <span class="source-line-no">5932</span><span id="line-5932">          return;</span> | 
 | <span class="source-line-no">5933</span><span id="line-5933">        }</span> | 
 | <span class="source-line-no">5934</span><span id="line-5934">        store.replayCompactionMarker(compaction, pickCompactionFiles, removeFiles);</span> | 
 | <span class="source-line-no">5935</span><span id="line-5935">        logRegionFiles();</span> | 
 | <span class="source-line-no">5936</span><span id="line-5936">      } catch (FileNotFoundException ex) {</span> | 
 | <span class="source-line-no">5937</span><span id="line-5937">        LOG.warn(getRegionInfo().getEncodedName() + " : "</span> | 
 | <span class="source-line-no">5938</span><span id="line-5938">          + "At least one of the store files in compaction: "</span> | 
 | <span class="source-line-no">5939</span><span id="line-5939">          + TextFormat.shortDebugString(compaction)</span> | 
 | <span class="source-line-no">5940</span><span id="line-5940">          + " doesn't exist any more. Skip loading the file(s)", ex);</span> | 
 | <span class="source-line-no">5941</span><span id="line-5941">      } finally {</span> | 
 | <span class="source-line-no">5942</span><span id="line-5942">        closeRegionOperation(Operation.REPLAY_EVENT);</span> | 
 | <span class="source-line-no">5943</span><span id="line-5943">      }</span> | 
 | <span class="source-line-no">5944</span><span id="line-5944">    }</span> | 
 | <span class="source-line-no">5945</span><span id="line-5945">  }</span> | 
 | <span class="source-line-no">5946</span><span id="line-5946"></span> | 
 | <span class="source-line-no">5947</span><span id="line-5947">  /**</span> | 
 | <span class="source-line-no">5948</span><span id="line-5948">   * @deprecated Since 3.0.0, will be removed in 4.0.0. Only for keep compatibility for old region</span> | 
 | <span class="source-line-no">5949</span><span id="line-5949">   *             replica implementation.</span> | 
 | <span class="source-line-no">5950</span><span id="line-5950">   */</span> | 
 | <span class="source-line-no">5951</span><span id="line-5951">  @Deprecated</span> | 
 | <span class="source-line-no">5952</span><span id="line-5952">  void replayWALFlushMarker(FlushDescriptor flush, long replaySeqId) throws IOException {</span> | 
 | <span class="source-line-no">5953</span><span id="line-5953">    checkTargetRegion(flush.getEncodedRegionName().toByteArray(), "Flush marker from WAL ", flush);</span> | 
 | <span class="source-line-no">5954</span><span id="line-5954"></span> | 
 | <span class="source-line-no">5955</span><span id="line-5955">    if (ServerRegionReplicaUtil.isDefaultReplica(this.getRegionInfo())) {</span> | 
 | <span class="source-line-no">5956</span><span id="line-5956">      return; // if primary nothing to do</span> | 
 | <span class="source-line-no">5957</span><span id="line-5957">    }</span> | 
 | <span class="source-line-no">5958</span><span id="line-5958"></span> | 
 | <span class="source-line-no">5959</span><span id="line-5959">    if (LOG.isDebugEnabled()) {</span> | 
 | <span class="source-line-no">5960</span><span id="line-5960">      LOG.debug(getRegionInfo().getEncodedName() + " : " + "Replaying flush marker "</span> | 
 | <span class="source-line-no">5961</span><span id="line-5961">        + TextFormat.shortDebugString(flush));</span> | 
 | <span class="source-line-no">5962</span><span id="line-5962">    }</span> | 
 | <span class="source-line-no">5963</span><span id="line-5963"></span> | 
 | <span class="source-line-no">5964</span><span id="line-5964">    startRegionOperation(Operation.REPLAY_EVENT); // use region close lock to guard against close</span> | 
 | <span class="source-line-no">5965</span><span id="line-5965">    try {</span> | 
 | <span class="source-line-no">5966</span><span id="line-5966">      FlushAction action = flush.getAction();</span> | 
 | <span class="source-line-no">5967</span><span id="line-5967">      switch (action) {</span> | 
 | <span class="source-line-no">5968</span><span id="line-5968">        case START_FLUSH:</span> | 
 | <span class="source-line-no">5969</span><span id="line-5969">          replayWALFlushStartMarker(flush);</span> | 
 | <span class="source-line-no">5970</span><span id="line-5970">          break;</span> | 
 | <span class="source-line-no">5971</span><span id="line-5971">        case COMMIT_FLUSH:</span> | 
 | <span class="source-line-no">5972</span><span id="line-5972">          replayWALFlushCommitMarker(flush);</span> | 
 | <span class="source-line-no">5973</span><span id="line-5973">          break;</span> | 
 | <span class="source-line-no">5974</span><span id="line-5974">        case ABORT_FLUSH:</span> | 
 | <span class="source-line-no">5975</span><span id="line-5975">          replayWALFlushAbortMarker(flush);</span> | 
 | <span class="source-line-no">5976</span><span id="line-5976">          break;</span> | 
 | <span class="source-line-no">5977</span><span id="line-5977">        case CANNOT_FLUSH:</span> | 
 | <span class="source-line-no">5978</span><span id="line-5978">          replayWALFlushCannotFlushMarker(flush, replaySeqId);</span> | 
 | <span class="source-line-no">5979</span><span id="line-5979">          break;</span> | 
 | <span class="source-line-no">5980</span><span id="line-5980">        default:</span> | 
 | <span class="source-line-no">5981</span><span id="line-5981">          LOG.warn(getRegionInfo().getEncodedName() + " : "</span> | 
 | <span class="source-line-no">5982</span><span id="line-5982">            + "Received a flush event with unknown action, ignoring. "</span> | 
 | <span class="source-line-no">5983</span><span id="line-5983">            + TextFormat.shortDebugString(flush));</span> | 
 | <span class="source-line-no">5984</span><span id="line-5984">          break;</span> | 
 | <span class="source-line-no">5985</span><span id="line-5985">      }</span> | 
 | <span class="source-line-no">5986</span><span id="line-5986"></span> | 
 | <span class="source-line-no">5987</span><span id="line-5987">      logRegionFiles();</span> | 
 | <span class="source-line-no">5988</span><span id="line-5988">    } finally {</span> | 
 | <span class="source-line-no">5989</span><span id="line-5989">      closeRegionOperation(Operation.REPLAY_EVENT);</span> | 
 | <span class="source-line-no">5990</span><span id="line-5990">    }</span> | 
 | <span class="source-line-no">5991</span><span id="line-5991">  }</span> | 
 | <span class="source-line-no">5992</span><span id="line-5992"></span> | 
 | <span class="source-line-no">5993</span><span id="line-5993">  private Collection<HStore> getStoresToFlush(FlushDescriptor flushDesc) {</span> | 
 | <span class="source-line-no">5994</span><span id="line-5994">    List<HStore> storesToFlush = new ArrayList<>();</span> | 
 | <span class="source-line-no">5995</span><span id="line-5995">    for (StoreFlushDescriptor storeFlush : flushDesc.getStoreFlushesList()) {</span> | 
 | <span class="source-line-no">5996</span><span id="line-5996">      byte[] family = storeFlush.getFamilyName().toByteArray();</span> | 
 | <span class="source-line-no">5997</span><span id="line-5997">      HStore store = getStore(family);</span> | 
 | <span class="source-line-no">5998</span><span id="line-5998">      if (store == null) {</span> | 
 | <span class="source-line-no">5999</span><span id="line-5999">        LOG.warn(getRegionInfo().getEncodedName() + " : "</span> | 
 | <span class="source-line-no">6000</span><span id="line-6000">          + "Received a flush start marker from primary, but the family is not found. Ignoring"</span> | 
 | <span class="source-line-no">6001</span><span id="line-6001">          + " StoreFlushDescriptor:" + TextFormat.shortDebugString(storeFlush));</span> | 
 | <span class="source-line-no">6002</span><span id="line-6002">        continue;</span> | 
 | <span class="source-line-no">6003</span><span id="line-6003">      }</span> | 
 | <span class="source-line-no">6004</span><span id="line-6004">      storesToFlush.add(store);</span> | 
 | <span class="source-line-no">6005</span><span id="line-6005">    }</span> | 
 | <span class="source-line-no">6006</span><span id="line-6006">    return storesToFlush;</span> | 
 | <span class="source-line-no">6007</span><span id="line-6007">  }</span> | 
 | <span class="source-line-no">6008</span><span id="line-6008"></span> | 
 | <span class="source-line-no">6009</span><span id="line-6009">  /**</span> | 
 | <span class="source-line-no">6010</span><span id="line-6010">   * Replay the flush marker from primary region by creating a corresponding snapshot of the store</span> | 
 | <span class="source-line-no">6011</span><span id="line-6011">   * memstores, only if the memstores do not have a higher seqId from an earlier wal edit (because</span> | 
 | <span class="source-line-no">6012</span><span id="line-6012">   * the events may be coming out of order).</span> | 
 | <span class="source-line-no">6013</span><span id="line-6013">   * @deprecated Since 3.0.0, will be removed in 4.0.0. Only for keep compatibility for old region</span> | 
 | <span class="source-line-no">6014</span><span id="line-6014">   *             replica implementation.</span> | 
 | <span class="source-line-no">6015</span><span id="line-6015">   */</span> | 
 | <span class="source-line-no">6016</span><span id="line-6016">  @Deprecated</span> | 
 | <span class="source-line-no">6017</span><span id="line-6017">  PrepareFlushResult replayWALFlushStartMarker(FlushDescriptor flush) throws IOException {</span> | 
 | <span class="source-line-no">6018</span><span id="line-6018">    long flushSeqId = flush.getFlushSequenceNumber();</span> | 
 | <span class="source-line-no">6019</span><span id="line-6019"></span> | 
 | <span class="source-line-no">6020</span><span id="line-6020">    Collection<HStore> storesToFlush = getStoresToFlush(flush);</span> | 
 | <span class="source-line-no">6021</span><span id="line-6021"></span> | 
 | <span class="source-line-no">6022</span><span id="line-6022">    MonitoredTask status = TaskMonitor.get().createStatus("Preparing flush " + this);</span> | 
 | <span class="source-line-no">6023</span><span id="line-6023"></span> | 
 | <span class="source-line-no">6024</span><span id="line-6024">    // we will use writestate as a coarse-grain lock for all the replay events</span> | 
 | <span class="source-line-no">6025</span><span id="line-6025">    // (flush, compaction, region open etc)</span> | 
 | <span class="source-line-no">6026</span><span id="line-6026">    synchronized (writestate) {</span> | 
 | <span class="source-line-no">6027</span><span id="line-6027">      try {</span> | 
 | <span class="source-line-no">6028</span><span id="line-6028">        if (flush.getFlushSequenceNumber() < lastReplayedOpenRegionSeqId) {</span> | 
 | <span class="source-line-no">6029</span><span id="line-6029">          LOG.warn(getRegionInfo().getEncodedName() + " : " + "Skipping replaying flush event :"</span> | 
 | <span class="source-line-no">6030</span><span id="line-6030">            + TextFormat.shortDebugString(flush)</span> | 
 | <span class="source-line-no">6031</span><span id="line-6031">            + " because its sequence id is smaller than this regions lastReplayedOpenRegionSeqId "</span> | 
 | <span class="source-line-no">6032</span><span id="line-6032">            + " of " + lastReplayedOpenRegionSeqId);</span> | 
 | <span class="source-line-no">6033</span><span id="line-6033">          return null;</span> | 
 | <span class="source-line-no">6034</span><span id="line-6034">        }</span> | 
 | <span class="source-line-no">6035</span><span id="line-6035">        if (numMutationsWithoutWAL.sum() > 0) {</span> | 
 | <span class="source-line-no">6036</span><span id="line-6036">          numMutationsWithoutWAL.reset();</span> | 
 | <span class="source-line-no">6037</span><span id="line-6037">          dataInMemoryWithoutWAL.reset();</span> | 
 | <span class="source-line-no">6038</span><span id="line-6038">        }</span> | 
 | <span class="source-line-no">6039</span><span id="line-6039"></span> | 
 | <span class="source-line-no">6040</span><span id="line-6040">        if (!writestate.flushing) {</span> | 
 | <span class="source-line-no">6041</span><span id="line-6041">          // we do not have an active snapshot and corresponding this.prepareResult. This means</span> | 
 | <span class="source-line-no">6042</span><span id="line-6042">          // we can just snapshot our memstores and continue as normal.</span> | 
 | <span class="source-line-no">6043</span><span id="line-6043"></span> | 
 | <span class="source-line-no">6044</span><span id="line-6044">          // invoke prepareFlushCache. Send null as wal since we do not want the flush events in wal</span> | 
 | <span class="source-line-no">6045</span><span id="line-6045">          PrepareFlushResult prepareResult = internalPrepareFlushCache(null, flushSeqId,</span> | 
 | <span class="source-line-no">6046</span><span id="line-6046">            storesToFlush, status, false, FlushLifeCycleTracker.DUMMY);</span> | 
 | <span class="source-line-no">6047</span><span id="line-6047">          if (prepareResult.result == null) {</span> | 
 | <span class="source-line-no">6048</span><span id="line-6048">            // save the PrepareFlushResult so that we can use it later from commit flush</span> | 
 | <span class="source-line-no">6049</span><span id="line-6049">            this.writestate.flushing = true;</span> | 
 | <span class="source-line-no">6050</span><span id="line-6050">            this.prepareFlushResult = prepareResult;</span> | 
 | <span class="source-line-no">6051</span><span id="line-6051">            status.markComplete("Flush prepare successful");</span> | 
 | <span class="source-line-no">6052</span><span id="line-6052">            if (LOG.isDebugEnabled()) {</span> | 
 | <span class="source-line-no">6053</span><span id="line-6053">              LOG.debug(getRegionInfo().getEncodedName() + " : " + " Prepared flush with seqId:"</span> | 
 | <span class="source-line-no">6054</span><span id="line-6054">                + flush.getFlushSequenceNumber());</span> | 
 | <span class="source-line-no">6055</span><span id="line-6055">            }</span> | 
 | <span class="source-line-no">6056</span><span id="line-6056">          } else {</span> | 
 | <span class="source-line-no">6057</span><span id="line-6057">            // special case empty memstore. We will still save the flush result in this case, since</span> | 
 | <span class="source-line-no">6058</span><span id="line-6058">            // our memstore ie empty, but the primary is still flushing</span> | 
 | <span class="source-line-no">6059</span><span id="line-6059">            if (</span> | 
 | <span class="source-line-no">6060</span><span id="line-6060">              prepareResult.getResult().getResult()</span> | 
 | <span class="source-line-no">6061</span><span id="line-6061">                  == FlushResult.Result.CANNOT_FLUSH_MEMSTORE_EMPTY</span> | 
 | <span class="source-line-no">6062</span><span id="line-6062">            ) {</span> | 
 | <span class="source-line-no">6063</span><span id="line-6063">              this.writestate.flushing = true;</span> | 
 | <span class="source-line-no">6064</span><span id="line-6064">              this.prepareFlushResult = prepareResult;</span> | 
 | <span class="source-line-no">6065</span><span id="line-6065">              if (LOG.isDebugEnabled()) {</span> | 
 | <span class="source-line-no">6066</span><span id="line-6066">                LOG.debug(getRegionInfo().getEncodedName() + " : "</span> | 
 | <span class="source-line-no">6067</span><span id="line-6067">                  + " Prepared empty flush with seqId:" + flush.getFlushSequenceNumber());</span> | 
 | <span class="source-line-no">6068</span><span id="line-6068">              }</span> | 
 | <span class="source-line-no">6069</span><span id="line-6069">            }</span> | 
 | <span class="source-line-no">6070</span><span id="line-6070">            status.abort("Flush prepare failed with " + prepareResult.result);</span> | 
 | <span class="source-line-no">6071</span><span id="line-6071">            // nothing much to do. prepare flush failed because of some reason.</span> | 
 | <span class="source-line-no">6072</span><span id="line-6072">          }</span> | 
 | <span class="source-line-no">6073</span><span id="line-6073">          return prepareResult;</span> | 
 | <span class="source-line-no">6074</span><span id="line-6074">        } else {</span> | 
 | <span class="source-line-no">6075</span><span id="line-6075">          // we already have an active snapshot.</span> | 
 | <span class="source-line-no">6076</span><span id="line-6076">          if (flush.getFlushSequenceNumber() == this.prepareFlushResult.flushOpSeqId) {</span> | 
 | <span class="source-line-no">6077</span><span id="line-6077">            // They define the same flush. Log and continue.</span> | 
 | <span class="source-line-no">6078</span><span id="line-6078">            LOG.warn(getRegionInfo().getEncodedName() + " : "</span> | 
 | <span class="source-line-no">6079</span><span id="line-6079">              + "Received a flush prepare marker with the same seqId: "</span> | 
 | <span class="source-line-no">6080</span><span id="line-6080">              + +flush.getFlushSequenceNumber() + " before clearing the previous one with seqId: "</span> | 
 | <span class="source-line-no">6081</span><span id="line-6081">              + prepareFlushResult.flushOpSeqId + ". Ignoring");</span> | 
 | <span class="source-line-no">6082</span><span id="line-6082">            // ignore</span> | 
 | <span class="source-line-no">6083</span><span id="line-6083">          } else if (flush.getFlushSequenceNumber() < this.prepareFlushResult.flushOpSeqId) {</span> | 
 | <span class="source-line-no">6084</span><span id="line-6084">            // We received a flush with a smaller seqNum than what we have prepared. We can only</span> | 
 | <span class="source-line-no">6085</span><span id="line-6085">            // ignore this prepare flush request.</span> | 
 | <span class="source-line-no">6086</span><span id="line-6086">            LOG.warn(getRegionInfo().getEncodedName() + " : "</span> | 
 | <span class="source-line-no">6087</span><span id="line-6087">              + "Received a flush prepare marker with a smaller seqId: "</span> | 
 | <span class="source-line-no">6088</span><span id="line-6088">              + +flush.getFlushSequenceNumber() + " before clearing the previous one with seqId: "</span> | 
 | <span class="source-line-no">6089</span><span id="line-6089">              + prepareFlushResult.flushOpSeqId + ". Ignoring");</span> | 
 | <span class="source-line-no">6090</span><span id="line-6090">            // ignore</span> | 
 | <span class="source-line-no">6091</span><span id="line-6091">          } else {</span> | 
 | <span class="source-line-no">6092</span><span id="line-6092">            // We received a flush with a larger seqNum than what we have prepared</span> | 
 | <span class="source-line-no">6093</span><span id="line-6093">            LOG.warn(getRegionInfo().getEncodedName() + " : "</span> | 
 | <span class="source-line-no">6094</span><span id="line-6094">              + "Received a flush prepare marker with a larger seqId: "</span> | 
 | <span class="source-line-no">6095</span><span id="line-6095">              + +flush.getFlushSequenceNumber() + " before clearing the previous one with seqId: "</span> | 
 | <span class="source-line-no">6096</span><span id="line-6096">              + prepareFlushResult.flushOpSeqId + ". Ignoring");</span> | 
 | <span class="source-line-no">6097</span><span id="line-6097">            // We do not have multiple active snapshots in the memstore or a way to merge current</span> | 
 | <span class="source-line-no">6098</span><span id="line-6098">            // memstore snapshot with the contents and resnapshot for now. We cannot take</span> | 
 | <span class="source-line-no">6099</span><span id="line-6099">            // another snapshot and drop the previous one because that will cause temporary</span> | 
 | <span class="source-line-no">6100</span><span id="line-6100">            // data loss in the secondary. So we ignore this for now, deferring the resolution</span> | 
 | <span class="source-line-no">6101</span><span id="line-6101">            // to happen when we see the corresponding flush commit marker. If we have a memstore</span> | 
 | <span class="source-line-no">6102</span><span id="line-6102">            // snapshot with x, and later received another prepare snapshot with y (where x < y),</span> | 
 | <span class="source-line-no">6103</span><span id="line-6103">            // when we see flush commit for y, we will drop snapshot for x, and can also drop all</span> | 
 | <span class="source-line-no">6104</span><span id="line-6104">            // the memstore edits if everything in memstore is < y. This is the usual case for</span> | 
 | <span class="source-line-no">6105</span><span id="line-6105">            // RS crash + recovery where we might see consequtive prepare flush wal markers.</span> | 
 | <span class="source-line-no">6106</span><span id="line-6106">            // Otherwise, this will cause more memory to be used in secondary replica until a</span> | 
 | <span class="source-line-no">6107</span><span id="line-6107">            // further prapare + commit flush is seen and replayed.</span> | 
 | <span class="source-line-no">6108</span><span id="line-6108">          }</span> | 
 | <span class="source-line-no">6109</span><span id="line-6109">        }</span> | 
 | <span class="source-line-no">6110</span><span id="line-6110">      } finally {</span> | 
 | <span class="source-line-no">6111</span><span id="line-6111">        status.cleanup();</span> | 
 | <span class="source-line-no">6112</span><span id="line-6112">        writestate.notifyAll();</span> | 
 | <span class="source-line-no">6113</span><span id="line-6113">      }</span> | 
 | <span class="source-line-no">6114</span><span id="line-6114">    }</span> | 
 | <span class="source-line-no">6115</span><span id="line-6115">    return null;</span> | 
 | <span class="source-line-no">6116</span><span id="line-6116">  }</span> | 
 | <span class="source-line-no">6117</span><span id="line-6117"></span> | 
 | <span class="source-line-no">6118</span><span id="line-6118">  /**</span> | 
 | <span class="source-line-no">6119</span><span id="line-6119">   * @deprecated Since 3.0.0, will be removed in 4.0.0. Only for keep compatibility for old region</span> | 
 | <span class="source-line-no">6120</span><span id="line-6120">   *             replica implementation.</span> | 
 | <span class="source-line-no">6121</span><span id="line-6121">   */</span> | 
 | <span class="source-line-no">6122</span><span id="line-6122">  @Deprecated</span> | 
 | <span class="source-line-no">6123</span><span id="line-6123">  @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "NN_NAKED_NOTIFY",</span> | 
 | <span class="source-line-no">6124</span><span id="line-6124">      justification = "Intentional; post memstore flush")</span> | 
 | <span class="source-line-no">6125</span><span id="line-6125">  void replayWALFlushCommitMarker(FlushDescriptor flush) throws IOException {</span> | 
 | <span class="source-line-no">6126</span><span id="line-6126">    MonitoredTask status = TaskMonitor.get().createStatus("Committing flush " + this);</span> | 
 | <span class="source-line-no">6127</span><span id="line-6127"></span> | 
 | <span class="source-line-no">6128</span><span id="line-6128">    // check whether we have the memstore snapshot with the corresponding seqId. Replay to</span> | 
 | <span class="source-line-no">6129</span><span id="line-6129">    // secondary region replicas are in order, except for when the region moves or then the</span> | 
 | <span class="source-line-no">6130</span><span id="line-6130">    // region server crashes. In those cases, we may receive replay requests out of order from</span> | 
 | <span class="source-line-no">6131</span><span id="line-6131">    // the original seqIds.</span> | 
 | <span class="source-line-no">6132</span><span id="line-6132">    synchronized (writestate) {</span> | 
 | <span class="source-line-no">6133</span><span id="line-6133">      try {</span> | 
 | <span class="source-line-no">6134</span><span id="line-6134">        if (flush.getFlushSequenceNumber() < lastReplayedOpenRegionSeqId) {</span> | 
 | <span class="source-line-no">6135</span><span id="line-6135">          LOG.warn(getRegionInfo().getEncodedName() + " : " + "Skipping replaying flush event :"</span> | 
 | <span class="source-line-no">6136</span><span id="line-6136">            + TextFormat.shortDebugString(flush)</span> | 
 | <span class="source-line-no">6137</span><span id="line-6137">            + " because its sequence id is smaller than this regions lastReplayedOpenRegionSeqId "</span> | 
 | <span class="source-line-no">6138</span><span id="line-6138">            + " of " + lastReplayedOpenRegionSeqId);</span> | 
 | <span class="source-line-no">6139</span><span id="line-6139">          return;</span> | 
 | <span class="source-line-no">6140</span><span id="line-6140">        }</span> | 
 | <span class="source-line-no">6141</span><span id="line-6141"></span> | 
 | <span class="source-line-no">6142</span><span id="line-6142">        if (writestate.flushing) {</span> | 
 | <span class="source-line-no">6143</span><span id="line-6143">          PrepareFlushResult prepareFlushResult = this.prepareFlushResult;</span> | 
 | <span class="source-line-no">6144</span><span id="line-6144">          if (flush.getFlushSequenceNumber() == prepareFlushResult.flushOpSeqId) {</span> | 
 | <span class="source-line-no">6145</span><span id="line-6145">            if (LOG.isDebugEnabled()) {</span> | 
 | <span class="source-line-no">6146</span><span id="line-6146">              LOG.debug(getRegionInfo().getEncodedName() + " : "</span> | 
 | <span class="source-line-no">6147</span><span id="line-6147">                + "Received a flush commit marker with seqId:" + flush.getFlushSequenceNumber()</span> | 
 | <span class="source-line-no">6148</span><span id="line-6148">                + " and a previous prepared snapshot was found");</span> | 
 | <span class="source-line-no">6149</span><span id="line-6149">            }</span> | 
 | <span class="source-line-no">6150</span><span id="line-6150">            // This is the regular case where we received commit flush after prepare flush</span> | 
 | <span class="source-line-no">6151</span><span id="line-6151">            // corresponding to the same seqId.</span> | 
 | <span class="source-line-no">6152</span><span id="line-6152">            replayFlushInStores(flush, prepareFlushResult, true);</span> | 
 | <span class="source-line-no">6153</span><span id="line-6153"></span> | 
 | <span class="source-line-no">6154</span><span id="line-6154">            // Set down the memstore size by amount of flush.</span> | 
 | <span class="source-line-no">6155</span><span id="line-6155">            this.decrMemStoreSize(prepareFlushResult.totalFlushableSize.getMemStoreSize());</span> | 
 | <span class="source-line-no">6156</span><span id="line-6156">            this.prepareFlushResult = null;</span> | 
 | <span class="source-line-no">6157</span><span id="line-6157">            writestate.flushing = false;</span> | 
 | <span class="source-line-no">6158</span><span id="line-6158">          } else if (flush.getFlushSequenceNumber() < prepareFlushResult.flushOpSeqId) {</span> | 
 | <span class="source-line-no">6159</span><span id="line-6159">            // This should not happen normally. However, lets be safe and guard against these cases</span> | 
 | <span class="source-line-no">6160</span><span id="line-6160">            // we received a flush commit with a smaller seqId than what we have prepared</span> | 
 | <span class="source-line-no">6161</span><span id="line-6161">            // we will pick the flush file up from this commit (if we have not seen it), but we</span> | 
 | <span class="source-line-no">6162</span><span id="line-6162">            // will not drop the memstore</span> | 
 | <span class="source-line-no">6163</span><span id="line-6163">            LOG.warn(getRegionInfo().getEncodedName() + " : "</span> | 
 | <span class="source-line-no">6164</span><span id="line-6164">              + "Received a flush commit marker with smaller seqId: "</span> | 
 | <span class="source-line-no">6165</span><span id="line-6165">              + flush.getFlushSequenceNumber() + " than what we have prepared with seqId: "</span> | 
 | <span class="source-line-no">6166</span><span id="line-6166">              + prepareFlushResult.flushOpSeqId + ". Picking up new file, but not dropping"</span> | 
 | <span class="source-line-no">6167</span><span id="line-6167">              + "  prepared memstore snapshot");</span> | 
 | <span class="source-line-no">6168</span><span id="line-6168">            replayFlushInStores(flush, prepareFlushResult, false);</span> | 
 | <span class="source-line-no">6169</span><span id="line-6169"></span> | 
 | <span class="source-line-no">6170</span><span id="line-6170">            // snapshot is not dropped, so memstore sizes should not be decremented</span> | 
 | <span class="source-line-no">6171</span><span id="line-6171">            // we still have the prepared snapshot, flushing should still be true</span> | 
 | <span class="source-line-no">6172</span><span id="line-6172">          } else {</span> | 
 | <span class="source-line-no">6173</span><span id="line-6173">            // This should not happen normally. However, lets be safe and guard against these cases</span> | 
 | <span class="source-line-no">6174</span><span id="line-6174">            // we received a flush commit with a larger seqId than what we have prepared</span> | 
 | <span class="source-line-no">6175</span><span id="line-6175">            // we will pick the flush file for this. We will also obtain the updates lock and</span> | 
 | <span class="source-line-no">6176</span><span id="line-6176">            // look for contents of the memstore to see whether we have edits after this seqId.</span> | 
 | <span class="source-line-no">6177</span><span id="line-6177">            // If not, we will drop all the memstore edits and the snapshot as well.</span> | 
 | <span class="source-line-no">6178</span><span id="line-6178">            LOG.warn(getRegionInfo().getEncodedName() + " : "</span> | 
 | <span class="source-line-no">6179</span><span id="line-6179">              + "Received a flush commit marker with larger seqId: "</span> | 
 | <span class="source-line-no">6180</span><span id="line-6180">              + flush.getFlushSequenceNumber() + " than what we have prepared with seqId: "</span> | 
 | <span class="source-line-no">6181</span><span id="line-6181">              + prepareFlushResult.flushOpSeqId + ". Picking up new file and dropping prepared"</span> | 
 | <span class="source-line-no">6182</span><span id="line-6182">              + " memstore snapshot");</span> | 
 | <span class="source-line-no">6183</span><span id="line-6183"></span> | 
 | <span class="source-line-no">6184</span><span id="line-6184">            replayFlushInStores(flush, prepareFlushResult, true);</span> | 
 | <span class="source-line-no">6185</span><span id="line-6185"></span> | 
 | <span class="source-line-no">6186</span><span id="line-6186">            // Set down the memstore size by amount of flush.</span> | 
 | <span class="source-line-no">6187</span><span id="line-6187">            this.decrMemStoreSize(prepareFlushResult.totalFlushableSize.getMemStoreSize());</span> | 
 | <span class="source-line-no">6188</span><span id="line-6188"></span> | 
 | <span class="source-line-no">6189</span><span id="line-6189">            // Inspect the memstore contents to see whether the memstore contains only edits</span> | 
 | <span class="source-line-no">6190</span><span id="line-6190">            // with seqId smaller than the flush seqId. If so, we can discard those edits.</span> | 
 | <span class="source-line-no">6191</span><span id="line-6191">            dropMemStoreContentsForSeqId(flush.getFlushSequenceNumber(), null);</span> | 
 | <span class="source-line-no">6192</span><span id="line-6192"></span> | 
 | <span class="source-line-no">6193</span><span id="line-6193">            this.prepareFlushResult = null;</span> | 
 | <span class="source-line-no">6194</span><span id="line-6194">            writestate.flushing = false;</span> | 
 | <span class="source-line-no">6195</span><span id="line-6195">          }</span> | 
 | <span class="source-line-no">6196</span><span id="line-6196">          // If we were waiting for observing a flush or region opening event for not showing</span> | 
 | <span class="source-line-no">6197</span><span id="line-6197">          // partial data after a secondary region crash, we can allow reads now. We can only make</span> | 
 | <span class="source-line-no">6198</span><span id="line-6198">          // sure that we are not showing partial data (for example skipping some previous edits)</span> | 
 | <span class="source-line-no">6199</span><span id="line-6199">          // until we observe a full flush start and flush commit. So if we were not able to find</span> | 
 | <span class="source-line-no">6200</span><span id="line-6200">          // a previous flush we will not enable reads now.</span> | 
 | <span class="source-line-no">6201</span><span id="line-6201">          this.setReadsEnabled(true);</span> | 
 | <span class="source-line-no">6202</span><span id="line-6202">        } else {</span> | 
 | <span class="source-line-no">6203</span><span id="line-6203">          LOG.warn(</span> | 
 | <span class="source-line-no">6204</span><span id="line-6204">            getRegionInfo().getEncodedName() + " : " + "Received a flush commit marker with seqId:"</span> | 
 | <span class="source-line-no">6205</span><span id="line-6205">              + flush.getFlushSequenceNumber() + ", but no previous prepared snapshot was found");</span> | 
 | <span class="source-line-no">6206</span><span id="line-6206">          // There is no corresponding prepare snapshot from before.</span> | 
 | <span class="source-line-no">6207</span><span id="line-6207">          // We will pick up the new flushed file</span> | 
 | <span class="source-line-no">6208</span><span id="line-6208">          replayFlushInStores(flush, null, false);</span> | 
 | <span class="source-line-no">6209</span><span id="line-6209"></span> | 
 | <span class="source-line-no">6210</span><span id="line-6210">          // Inspect the memstore contents to see whether the memstore contains only edits</span> | 
 | <span class="source-line-no">6211</span><span id="line-6211">          // with seqId smaller than the flush seqId. If so, we can discard those edits.</span> | 
 | <span class="source-line-no">6212</span><span id="line-6212">          dropMemStoreContentsForSeqId(flush.getFlushSequenceNumber(), null);</span> | 
 | <span class="source-line-no">6213</span><span id="line-6213">        }</span> | 
 | <span class="source-line-no">6214</span><span id="line-6214"></span> | 
 | <span class="source-line-no">6215</span><span id="line-6215">        status.markComplete("Flush commit successful");</span> | 
 | <span class="source-line-no">6216</span><span id="line-6216"></span> | 
 | <span class="source-line-no">6217</span><span id="line-6217">        // Update the last flushed sequence id for region.</span> | 
 | <span class="source-line-no">6218</span><span id="line-6218">        this.maxFlushedSeqId = flush.getFlushSequenceNumber();</span> | 
 | <span class="source-line-no">6219</span><span id="line-6219"></span> | 
 | <span class="source-line-no">6220</span><span id="line-6220">        // advance the mvcc read point so that the new flushed file is visible.</span> | 
 | <span class="source-line-no">6221</span><span id="line-6221">        mvcc.advanceTo(flush.getFlushSequenceNumber());</span> | 
 | <span class="source-line-no">6222</span><span id="line-6222"></span> | 
 | <span class="source-line-no">6223</span><span id="line-6223">      } catch (FileNotFoundException ex) {</span> | 
 | <span class="source-line-no">6224</span><span id="line-6224">        LOG.warn(getRegionInfo().getEncodedName() + " : "</span> | 
 | <span class="source-line-no">6225</span><span id="line-6225">          + "At least one of the store files in flush: " + TextFormat.shortDebugString(flush)</span> | 
 | <span class="source-line-no">6226</span><span id="line-6226">          + " doesn't exist any more. Skip loading the file(s)", ex);</span> | 
 | <span class="source-line-no">6227</span><span id="line-6227">      } finally {</span> | 
 | <span class="source-line-no">6228</span><span id="line-6228">        status.cleanup();</span> | 
 | <span class="source-line-no">6229</span><span id="line-6229">        writestate.notifyAll();</span> | 
 | <span class="source-line-no">6230</span><span id="line-6230">      }</span> | 
 | <span class="source-line-no">6231</span><span id="line-6231">    }</span> | 
 | <span class="source-line-no">6232</span><span id="line-6232"></span> | 
 | <span class="source-line-no">6233</span><span id="line-6233">    // C. Finally notify anyone waiting on memstore to clear:</span> | 
 | <span class="source-line-no">6234</span><span id="line-6234">    // e.g. checkResources().</span> | 
 | <span class="source-line-no">6235</span><span id="line-6235">    synchronized (this) {</span> | 
 | <span class="source-line-no">6236</span><span id="line-6236">      notifyAll(); // FindBugs NN_NAKED_NOTIFY</span> | 
 | <span class="source-line-no">6237</span><span id="line-6237">    }</span> | 
 | <span class="source-line-no">6238</span><span id="line-6238">  }</span> | 
 | <span class="source-line-no">6239</span><span id="line-6239"></span> | 
 | <span class="source-line-no">6240</span><span id="line-6240">  /**</span> | 
 | <span class="source-line-no">6241</span><span id="line-6241">   * Replays the given flush descriptor by opening the flush files in stores and dropping the</span> | 
 | <span class="source-line-no">6242</span><span id="line-6242">   * memstore snapshots if requested.</span> | 
 | <span class="source-line-no">6243</span><span id="line-6243">   * @deprecated Since 3.0.0, will be removed in 4.0.0. Only for keep compatibility for old region</span> | 
 | <span class="source-line-no">6244</span><span id="line-6244">   *             replica implementation.</span> | 
 | <span class="source-line-no">6245</span><span id="line-6245">   */</span> | 
 | <span class="source-line-no">6246</span><span id="line-6246">  @Deprecated</span> | 
 | <span class="source-line-no">6247</span><span id="line-6247">  private void replayFlushInStores(FlushDescriptor flush, PrepareFlushResult prepareFlushResult,</span> | 
 | <span class="source-line-no">6248</span><span id="line-6248">    boolean dropMemstoreSnapshot) throws IOException {</span> | 
 | <span class="source-line-no">6249</span><span id="line-6249">    for (StoreFlushDescriptor storeFlush : flush.getStoreFlushesList()) {</span> | 
 | <span class="source-line-no">6250</span><span id="line-6250">      byte[] family = storeFlush.getFamilyName().toByteArray();</span> | 
 | <span class="source-line-no">6251</span><span id="line-6251">      HStore store = getStore(family);</span> | 
 | <span class="source-line-no">6252</span><span id="line-6252">      if (store == null) {</span> | 
 | <span class="source-line-no">6253</span><span id="line-6253">        LOG.warn(getRegionInfo().getEncodedName() + " : "</span> | 
 | <span class="source-line-no">6254</span><span id="line-6254">          + "Received a flush commit marker from primary, but the family is not found."</span> | 
 | <span class="source-line-no">6255</span><span id="line-6255">          + "Ignoring StoreFlushDescriptor:" + storeFlush);</span> | 
 | <span class="source-line-no">6256</span><span id="line-6256">        continue;</span> | 
 | <span class="source-line-no">6257</span><span id="line-6257">      }</span> | 
 | <span class="source-line-no">6258</span><span id="line-6258">      List<String> flushFiles = storeFlush.getFlushOutputList();</span> | 
 | <span class="source-line-no">6259</span><span id="line-6259">      StoreFlushContext ctx = null;</span> | 
 | <span class="source-line-no">6260</span><span id="line-6260">      long startTime = EnvironmentEdgeManager.currentTime();</span> | 
 | <span class="source-line-no">6261</span><span id="line-6261">      if (prepareFlushResult == null || prepareFlushResult.storeFlushCtxs == null) {</span> | 
 | <span class="source-line-no">6262</span><span id="line-6262">        ctx = store.createFlushContext(flush.getFlushSequenceNumber(), FlushLifeCycleTracker.DUMMY);</span> | 
 | <span class="source-line-no">6263</span><span id="line-6263">      } else {</span> | 
 | <span class="source-line-no">6264</span><span id="line-6264">        ctx = prepareFlushResult.storeFlushCtxs.get(family);</span> | 
 | <span class="source-line-no">6265</span><span id="line-6265">        startTime = prepareFlushResult.startTime;</span> | 
 | <span class="source-line-no">6266</span><span id="line-6266">      }</span> | 
 | <span class="source-line-no">6267</span><span id="line-6267"></span> | 
 | <span class="source-line-no">6268</span><span id="line-6268">      if (ctx == null) {</span> | 
 | <span class="source-line-no">6269</span><span id="line-6269">        LOG.warn(getRegionInfo().getEncodedName() + " : "</span> | 
 | <span class="source-line-no">6270</span><span id="line-6270">          + "Unexpected: flush commit marker received from store " + Bytes.toString(family)</span> | 
 | <span class="source-line-no">6271</span><span id="line-6271">          + " but no associated flush context. Ignoring");</span> | 
 | <span class="source-line-no">6272</span><span id="line-6272">        continue;</span> | 
 | <span class="source-line-no">6273</span><span id="line-6273">      }</span> | 
 | <span class="source-line-no">6274</span><span id="line-6274"></span> | 
 | <span class="source-line-no">6275</span><span id="line-6275">      ctx.replayFlush(flushFiles, dropMemstoreSnapshot); // replay the flush</span> | 
 | <span class="source-line-no">6276</span><span id="line-6276"></span> | 
 | <span class="source-line-no">6277</span><span id="line-6277">      // Record latest flush time</span> | 
 | <span class="source-line-no">6278</span><span id="line-6278">      this.lastStoreFlushTimeMap.put(store, startTime);</span> | 
 | <span class="source-line-no">6279</span><span id="line-6279">    }</span> | 
 | <span class="source-line-no">6280</span><span id="line-6280">  }</span> | 
 | <span class="source-line-no">6281</span><span id="line-6281"></span> | 
 | <span class="source-line-no">6282</span><span id="line-6282">  private long loadRecoveredHFilesIfAny(Collection<HStore> stores) throws IOException {</span> | 
 | <span class="source-line-no">6283</span><span id="line-6283">    Path regionDir = fs.getRegionDir();</span> | 
 | <span class="source-line-no">6284</span><span id="line-6284">    long maxSeqId = -1;</span> | 
 | <span class="source-line-no">6285</span><span id="line-6285">    for (HStore store : stores) {</span> | 
 | <span class="source-line-no">6286</span><span id="line-6286">      String familyName = store.getColumnFamilyName();</span> | 
 | <span class="source-line-no">6287</span><span id="line-6287">      FileStatus[] files =</span> | 
 | <span class="source-line-no">6288</span><span id="line-6288">        WALSplitUtil.getRecoveredHFiles(fs.getFileSystem(), regionDir, familyName);</span> | 
 | <span class="source-line-no">6289</span><span id="line-6289">      if (files != null && files.length != 0) {</span> | 
 | <span class="source-line-no">6290</span><span id="line-6290">        for (FileStatus file : files) {</span> | 
 | <span class="source-line-no">6291</span><span id="line-6291">          Path filePath = file.getPath();</span> | 
 | <span class="source-line-no">6292</span><span id="line-6292">          // If file length is zero then delete it</span> | 
 | <span class="source-line-no">6293</span><span id="line-6293">          if (isZeroLengthThenDelete(fs.getFileSystem(), file, filePath)) {</span> | 
 | <span class="source-line-no">6294</span><span id="line-6294">            continue;</span> | 
 | <span class="source-line-no">6295</span><span id="line-6295">          }</span> | 
 | <span class="source-line-no">6296</span><span id="line-6296">          try {</span> | 
 | <span class="source-line-no">6297</span><span id="line-6297">            HStoreFile storefile = store.tryCommitRecoveredHFile(file.getPath());</span> | 
 | <span class="source-line-no">6298</span><span id="line-6298">            maxSeqId = Math.max(maxSeqId, storefile.getReader().getSequenceID());</span> | 
 | <span class="source-line-no">6299</span><span id="line-6299">          } catch (IOException e) {</span> | 
 | <span class="source-line-no">6300</span><span id="line-6300">            handleException(fs.getFileSystem(), filePath, e);</span> | 
 | <span class="source-line-no">6301</span><span id="line-6301">            continue;</span> | 
 | <span class="source-line-no">6302</span><span id="line-6302">          }</span> | 
 | <span class="source-line-no">6303</span><span id="line-6303">        }</span> | 
 | <span class="source-line-no">6304</span><span id="line-6304">        if (this.rsServices != null && store.needsCompaction()) {</span> | 
 | <span class="source-line-no">6305</span><span id="line-6305">          this.rsServices.getCompactionRequestor().requestCompaction(this, store,</span> | 
 | <span class="source-line-no">6306</span><span id="line-6306">            "load recovered hfiles request compaction", Store.PRIORITY_USER + 1,</span> | 
 | <span class="source-line-no">6307</span><span id="line-6307">            CompactionLifeCycleTracker.DUMMY, null);</span> | 
 | <span class="source-line-no">6308</span><span id="line-6308">        }</span> | 
 | <span class="source-line-no">6309</span><span id="line-6309">      }</span> | 
 | <span class="source-line-no">6310</span><span id="line-6310">    }</span> | 
 | <span class="source-line-no">6311</span><span id="line-6311">    return maxSeqId;</span> | 
 | <span class="source-line-no">6312</span><span id="line-6312">  }</span> | 
 | <span class="source-line-no">6313</span><span id="line-6313"></span> | 
 | <span class="source-line-no">6314</span><span id="line-6314">  /**</span> | 
 | <span class="source-line-no">6315</span><span id="line-6315">   * Be careful, this method will drop all data in the memstore of this region. Currently, this</span> | 
 | <span class="source-line-no">6316</span><span id="line-6316">   * method is used to drop memstore to prevent memory leak when replaying recovered.edits while</span> | 
 | <span class="source-line-no">6317</span><span id="line-6317">   * opening region.</span> | 
 | <span class="source-line-no">6318</span><span id="line-6318">   */</span> | 
 | <span class="source-line-no">6319</span><span id="line-6319">  private MemStoreSize dropMemStoreContents() throws IOException {</span> | 
 | <span class="source-line-no">6320</span><span id="line-6320">    MemStoreSizing totalFreedSize = new NonThreadSafeMemStoreSizing();</span> | 
 | <span class="source-line-no">6321</span><span id="line-6321">    this.updatesLock.writeLock().lock();</span> | 
 | <span class="source-line-no">6322</span><span id="line-6322">    try {</span> | 
 | <span class="source-line-no">6323</span><span id="line-6323">      for (HStore s : stores.values()) {</span> | 
 | <span class="source-line-no">6324</span><span id="line-6324">        MemStoreSize memStoreSize = doDropStoreMemStoreContentsForSeqId(s, HConstants.NO_SEQNUM);</span> | 
 | <span class="source-line-no">6325</span><span id="line-6325">        LOG.info("Drop memstore for Store " + s.getColumnFamilyName() + " in region "</span> | 
 | <span class="source-line-no">6326</span><span id="line-6326">          + this.getRegionInfo().getRegionNameAsString() + " , dropped memstoresize: ["</span> | 
 | <span class="source-line-no">6327</span><span id="line-6327">          + memStoreSize + " }");</span> | 
 | <span class="source-line-no">6328</span><span id="line-6328">        totalFreedSize.incMemStoreSize(memStoreSize);</span> | 
 | <span class="source-line-no">6329</span><span id="line-6329">      }</span> | 
 | <span class="source-line-no">6330</span><span id="line-6330">      return totalFreedSize.getMemStoreSize();</span> | 
 | <span class="source-line-no">6331</span><span id="line-6331">    } finally {</span> | 
 | <span class="source-line-no">6332</span><span id="line-6332">      this.updatesLock.writeLock().unlock();</span> | 
 | <span class="source-line-no">6333</span><span id="line-6333">    }</span> | 
 | <span class="source-line-no">6334</span><span id="line-6334">  }</span> | 
 | <span class="source-line-no">6335</span><span id="line-6335"></span> | 
 | <span class="source-line-no">6336</span><span id="line-6336">  /**</span> | 
 | <span class="source-line-no">6337</span><span id="line-6337">   * Drops the memstore contents after replaying a flush descriptor or region open event replay if</span> | 
 | <span class="source-line-no">6338</span><span id="line-6338">   * the memstore edits have seqNums smaller than the given seq id</span> | 
 | <span class="source-line-no">6339</span><span id="line-6339">   */</span> | 
 | <span class="source-line-no">6340</span><span id="line-6340">  private MemStoreSize dropMemStoreContentsForSeqId(long seqId, HStore store) throws IOException {</span> | 
 | <span class="source-line-no">6341</span><span id="line-6341">    MemStoreSizing totalFreedSize = new NonThreadSafeMemStoreSizing();</span> | 
 | <span class="source-line-no">6342</span><span id="line-6342">    this.updatesLock.writeLock().lock();</span> | 
 | <span class="source-line-no">6343</span><span id="line-6343">    try {</span> | 
 | <span class="source-line-no">6344</span><span id="line-6344"></span> | 
 | <span class="source-line-no">6345</span><span id="line-6345">      long currentSeqId = mvcc.getReadPoint();</span> | 
 | <span class="source-line-no">6346</span><span id="line-6346">      if (seqId >= currentSeqId) {</span> | 
 | <span class="source-line-no">6347</span><span id="line-6347">        // then we can drop the memstore contents since everything is below this seqId</span> | 
 | <span class="source-line-no">6348</span><span id="line-6348">        LOG.info(getRegionInfo().getEncodedName() + " : "</span> | 
 | <span class="source-line-no">6349</span><span id="line-6349">          + "Dropping memstore contents as well since replayed flush seqId: " + seqId</span> | 
 | <span class="source-line-no">6350</span><span id="line-6350">          + " is greater than current seqId:" + currentSeqId);</span> | 
 | <span class="source-line-no">6351</span><span id="line-6351"></span> | 
 | <span class="source-line-no">6352</span><span id="line-6352">        // Prepare flush (take a snapshot) and then abort (drop the snapshot)</span> | 
 | <span class="source-line-no">6353</span><span id="line-6353">        if (store == null) {</span> | 
 | <span class="source-line-no">6354</span><span id="line-6354">          for (HStore s : stores.values()) {</span> | 
 | <span class="source-line-no">6355</span><span id="line-6355">            totalFreedSize.incMemStoreSize(doDropStoreMemStoreContentsForSeqId(s, currentSeqId));</span> | 
 | <span class="source-line-no">6356</span><span id="line-6356">          }</span> | 
 | <span class="source-line-no">6357</span><span id="line-6357">        } else {</span> | 
 | <span class="source-line-no">6358</span><span id="line-6358">          totalFreedSize.incMemStoreSize(doDropStoreMemStoreContentsForSeqId(store, currentSeqId));</span> | 
 | <span class="source-line-no">6359</span><span id="line-6359">        }</span> | 
 | <span class="source-line-no">6360</span><span id="line-6360">      } else {</span> | 
 | <span class="source-line-no">6361</span><span id="line-6361">        LOG.info(getRegionInfo().getEncodedName() + " : "</span> | 
 | <span class="source-line-no">6362</span><span id="line-6362">          + "Not dropping memstore contents since replayed flush seqId: " + seqId</span> | 
 | <span class="source-line-no">6363</span><span id="line-6363">          + " is smaller than current seqId:" + currentSeqId);</span> | 
 | <span class="source-line-no">6364</span><span id="line-6364">      }</span> | 
 | <span class="source-line-no">6365</span><span id="line-6365">    } finally {</span> | 
 | <span class="source-line-no">6366</span><span id="line-6366">      this.updatesLock.writeLock().unlock();</span> | 
 | <span class="source-line-no">6367</span><span id="line-6367">    }</span> | 
 | <span class="source-line-no">6368</span><span id="line-6368">    return totalFreedSize.getMemStoreSize();</span> | 
 | <span class="source-line-no">6369</span><span id="line-6369">  }</span> | 
 | <span class="source-line-no">6370</span><span id="line-6370"></span> | 
 | <span class="source-line-no">6371</span><span id="line-6371">  private MemStoreSize doDropStoreMemStoreContentsForSeqId(HStore s, long currentSeqId)</span> | 
 | <span class="source-line-no">6372</span><span id="line-6372">    throws IOException {</span> | 
 | <span class="source-line-no">6373</span><span id="line-6373">    MemStoreSize flushableSize = s.getFlushableSize();</span> | 
 | <span class="source-line-no">6374</span><span id="line-6374">    this.decrMemStoreSize(flushableSize);</span> | 
 | <span class="source-line-no">6375</span><span id="line-6375">    StoreFlushContext ctx = s.createFlushContext(currentSeqId, FlushLifeCycleTracker.DUMMY);</span> | 
 | <span class="source-line-no">6376</span><span id="line-6376">    ctx.prepare();</span> | 
 | <span class="source-line-no">6377</span><span id="line-6377">    ctx.abort();</span> | 
 | <span class="source-line-no">6378</span><span id="line-6378">    return flushableSize;</span> | 
 | <span class="source-line-no">6379</span><span id="line-6379">  }</span> | 
 | <span class="source-line-no">6380</span><span id="line-6380"></span> | 
 | <span class="source-line-no">6381</span><span id="line-6381">  private void replayWALFlushAbortMarker(FlushDescriptor flush) {</span> | 
 | <span class="source-line-no">6382</span><span id="line-6382">    // nothing to do for now. A flush abort will cause a RS abort which means that the region</span> | 
 | <span class="source-line-no">6383</span><span id="line-6383">    // will be opened somewhere else later. We will see the region open event soon, and replaying</span> | 
 | <span class="source-line-no">6384</span><span id="line-6384">    // that will drop the snapshot</span> | 
 | <span class="source-line-no">6385</span><span id="line-6385">  }</span> | 
 | <span class="source-line-no">6386</span><span id="line-6386"></span> | 
 | <span class="source-line-no">6387</span><span id="line-6387">  private void replayWALFlushCannotFlushMarker(FlushDescriptor flush, long replaySeqId) {</span> | 
 | <span class="source-line-no">6388</span><span id="line-6388">    synchronized (writestate) {</span> | 
 | <span class="source-line-no">6389</span><span id="line-6389">      if (this.lastReplayedOpenRegionSeqId > replaySeqId) {</span> | 
 | <span class="source-line-no">6390</span><span id="line-6390">        LOG.warn(getRegionInfo().getEncodedName() + " : " + "Skipping replaying flush event :"</span> | 
 | <span class="source-line-no">6391</span><span id="line-6391">          + TextFormat.shortDebugString(flush) + " because its sequence id " + replaySeqId</span> | 
 | <span class="source-line-no">6392</span><span id="line-6392">          + " is smaller than this regions " + "lastReplayedOpenRegionSeqId of "</span> | 
 | <span class="source-line-no">6393</span><span id="line-6393">          + lastReplayedOpenRegionSeqId);</span> | 
 | <span class="source-line-no">6394</span><span id="line-6394">        return;</span> | 
 | <span class="source-line-no">6395</span><span id="line-6395">      }</span> | 
 | <span class="source-line-no">6396</span><span id="line-6396"></span> | 
 | <span class="source-line-no">6397</span><span id="line-6397">      // If we were waiting for observing a flush or region opening event for not showing partial</span> | 
 | <span class="source-line-no">6398</span><span id="line-6398">      // data after a secondary region crash, we can allow reads now. This event means that the</span> | 
 | <span class="source-line-no">6399</span><span id="line-6399">      // primary was not able to flush because memstore is empty when we requested flush. By the</span> | 
 | <span class="source-line-no">6400</span><span id="line-6400">      // time we observe this, we are guaranteed to have up to date seqId with our previous</span> | 
 | <span class="source-line-no">6401</span><span id="line-6401">      // assignment.</span> | 
 | <span class="source-line-no">6402</span><span id="line-6402">      this.setReadsEnabled(true);</span> | 
 | <span class="source-line-no">6403</span><span id="line-6403">    }</span> | 
 | <span class="source-line-no">6404</span><span id="line-6404">  }</span> | 
 | <span class="source-line-no">6405</span><span id="line-6405"></span> | 
 | <span class="source-line-no">6406</span><span id="line-6406">  PrepareFlushResult getPrepareFlushResult() {</span> | 
 | <span class="source-line-no">6407</span><span id="line-6407">    return prepareFlushResult;</span> | 
 | <span class="source-line-no">6408</span><span id="line-6408">  }</span> | 
 | <span class="source-line-no">6409</span><span id="line-6409"></span> | 
 | <span class="source-line-no">6410</span><span id="line-6410">  /**</span> | 
 | <span class="source-line-no">6411</span><span id="line-6411">   * @deprecated Since 3.0.0, will be removed in 4.0.0. Only for keep compatibility for old region</span> | 
 | <span class="source-line-no">6412</span><span id="line-6412">   *             replica implementation.</span> | 
 | <span class="source-line-no">6413</span><span id="line-6413">   */</span> | 
 | <span class="source-line-no">6414</span><span id="line-6414">  @Deprecated</span> | 
 | <span class="source-line-no">6415</span><span id="line-6415">  @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "NN_NAKED_NOTIFY",</span> | 
 | <span class="source-line-no">6416</span><span id="line-6416">      justification = "Intentional; cleared the memstore")</span> | 
 | <span class="source-line-no">6417</span><span id="line-6417">  void replayWALRegionEventMarker(RegionEventDescriptor regionEvent) throws IOException {</span> | 
 | <span class="source-line-no">6418</span><span id="line-6418">    checkTargetRegion(regionEvent.getEncodedRegionName().toByteArray(),</span> | 
 | <span class="source-line-no">6419</span><span id="line-6419">      "RegionEvent marker from WAL ", regionEvent);</span> | 
 | <span class="source-line-no">6420</span><span id="line-6420"></span> | 
 | <span class="source-line-no">6421</span><span id="line-6421">    startRegionOperation(Operation.REPLAY_EVENT);</span> | 
 | <span class="source-line-no">6422</span><span id="line-6422">    try {</span> | 
 | <span class="source-line-no">6423</span><span id="line-6423">      if (ServerRegionReplicaUtil.isDefaultReplica(this.getRegionInfo())) {</span> | 
 | <span class="source-line-no">6424</span><span id="line-6424">        return; // if primary nothing to do</span> | 
 | <span class="source-line-no">6425</span><span id="line-6425">      }</span> | 
 | <span class="source-line-no">6426</span><span id="line-6426"></span> | 
 | <span class="source-line-no">6427</span><span id="line-6427">      if (regionEvent.getEventType() == EventType.REGION_CLOSE) {</span> | 
 | <span class="source-line-no">6428</span><span id="line-6428">        // nothing to do on REGION_CLOSE for now.</span> | 
 | <span class="source-line-no">6429</span><span id="line-6429">        return;</span> | 
 | <span class="source-line-no">6430</span><span id="line-6430">      }</span> | 
 | <span class="source-line-no">6431</span><span id="line-6431">      if (regionEvent.getEventType() != EventType.REGION_OPEN) {</span> | 
 | <span class="source-line-no">6432</span><span id="line-6432">        LOG.warn(getRegionInfo().getEncodedName() + " : "</span> | 
 | <span class="source-line-no">6433</span><span id="line-6433">          + "Unknown region event received, ignoring :" + TextFormat.shortDebugString(regionEvent));</span> | 
 | <span class="source-line-no">6434</span><span id="line-6434">        return;</span> | 
 | <span class="source-line-no">6435</span><span id="line-6435">      }</span> | 
 | <span class="source-line-no">6436</span><span id="line-6436"></span> | 
 | <span class="source-line-no">6437</span><span id="line-6437">      if (LOG.isDebugEnabled()) {</span> | 
 | <span class="source-line-no">6438</span><span id="line-6438">        LOG.debug(getRegionInfo().getEncodedName() + " : " + "Replaying region open event marker "</span> | 
 | <span class="source-line-no">6439</span><span id="line-6439">          + TextFormat.shortDebugString(regionEvent));</span> | 
 | <span class="source-line-no">6440</span><span id="line-6440">      }</span> | 
 | <span class="source-line-no">6441</span><span id="line-6441"></span> | 
 | <span class="source-line-no">6442</span><span id="line-6442">      // we will use writestate as a coarse-grain lock for all the replay events</span> | 
 | <span class="source-line-no">6443</span><span id="line-6443">      synchronized (writestate) {</span> | 
 | <span class="source-line-no">6444</span><span id="line-6444">        // Replication can deliver events out of order when primary region moves or the region</span> | 
 | <span class="source-line-no">6445</span><span id="line-6445">        // server crashes, since there is no coordination between replication of different wal files</span> | 
 | <span class="source-line-no">6446</span><span id="line-6446">        // belonging to different region servers. We have to safe guard against this case by using</span> | 
 | <span class="source-line-no">6447</span><span id="line-6447">        // region open event's seqid. Since this is the first event that the region puts (after</span> | 
 | <span class="source-line-no">6448</span><span id="line-6448">        // possibly flushing recovered.edits), after seeing this event, we can ignore every edit</span> | 
 | <span class="source-line-no">6449</span><span id="line-6449">        // smaller than this seqId</span> | 
 | <span class="source-line-no">6450</span><span id="line-6450">        if (this.lastReplayedOpenRegionSeqId <= regionEvent.getLogSequenceNumber()) {</span> | 
 | <span class="source-line-no">6451</span><span id="line-6451">          this.lastReplayedOpenRegionSeqId = regionEvent.getLogSequenceNumber();</span> | 
 | <span class="source-line-no">6452</span><span id="line-6452">        } else {</span> | 
 | <span class="source-line-no">6453</span><span id="line-6453">          LOG.warn(getRegionInfo().getEncodedName() + " : " + "Skipping replaying region event :"</span> | 
 | <span class="source-line-no">6454</span><span id="line-6454">            + TextFormat.shortDebugString(regionEvent)</span> | 
 | <span class="source-line-no">6455</span><span id="line-6455">            + " because its sequence id is smaller than this regions lastReplayedOpenRegionSeqId "</span> | 
 | <span class="source-line-no">6456</span><span id="line-6456">            + " of " + lastReplayedOpenRegionSeqId);</span> | 
 | <span class="source-line-no">6457</span><span id="line-6457">          return;</span> | 
 | <span class="source-line-no">6458</span><span id="line-6458">        }</span> | 
 | <span class="source-line-no">6459</span><span id="line-6459"></span> | 
 | <span class="source-line-no">6460</span><span id="line-6460">        // region open lists all the files that the region has at the time of the opening. Just pick</span> | 
 | <span class="source-line-no">6461</span><span id="line-6461">        // all the files and drop prepared flushes and empty memstores</span> | 
 | <span class="source-line-no">6462</span><span id="line-6462">        for (StoreDescriptor storeDescriptor : regionEvent.getStoresList()) {</span> | 
 | <span class="source-line-no">6463</span><span id="line-6463">          // stores of primary may be different now</span> | 
 | <span class="source-line-no">6464</span><span id="line-6464">          byte[] family = storeDescriptor.getFamilyName().toByteArray();</span> | 
 | <span class="source-line-no">6465</span><span id="line-6465">          HStore store = getStore(family);</span> | 
 | <span class="source-line-no">6466</span><span id="line-6466">          if (store == null) {</span> | 
 | <span class="source-line-no">6467</span><span id="line-6467">            LOG.warn(getRegionInfo().getEncodedName() + " : "</span> | 
 | <span class="source-line-no">6468</span><span id="line-6468">              + "Received a region open marker from primary, but the family is not found. "</span> | 
 | <span class="source-line-no">6469</span><span id="line-6469">              + "Ignoring. StoreDescriptor:" + storeDescriptor);</span> | 
 | <span class="source-line-no">6470</span><span id="line-6470">            continue;</span> | 
 | <span class="source-line-no">6471</span><span id="line-6471">          }</span> | 
 | <span class="source-line-no">6472</span><span id="line-6472"></span> | 
 | <span class="source-line-no">6473</span><span id="line-6473">          long storeSeqId = store.getMaxSequenceId().orElse(0L);</span> | 
 | <span class="source-line-no">6474</span><span id="line-6474">          List<String> storeFiles = storeDescriptor.getStoreFileList();</span> | 
 | <span class="source-line-no">6475</span><span id="line-6475">          try {</span> | 
 | <span class="source-line-no">6476</span><span id="line-6476">            store.refreshStoreFiles(storeFiles); // replace the files with the new ones</span> | 
 | <span class="source-line-no">6477</span><span id="line-6477">          } catch (FileNotFoundException ex) {</span> | 
 | <span class="source-line-no">6478</span><span id="line-6478">            LOG.warn(getRegionInfo().getEncodedName() + " : " + "At least one of the store files: "</span> | 
 | <span class="source-line-no">6479</span><span id="line-6479">              + storeFiles + " doesn't exist any more. Skip loading the file(s)", ex);</span> | 
 | <span class="source-line-no">6480</span><span id="line-6480">            continue;</span> | 
 | <span class="source-line-no">6481</span><span id="line-6481">          }</span> | 
 | <span class="source-line-no">6482</span><span id="line-6482">          if (store.getMaxSequenceId().orElse(0L) != storeSeqId) {</span> | 
 | <span class="source-line-no">6483</span><span id="line-6483">            // Record latest flush time if we picked up new files</span> | 
 | <span class="source-line-no">6484</span><span id="line-6484">            lastStoreFlushTimeMap.put(store, EnvironmentEdgeManager.currentTime());</span> | 
 | <span class="source-line-no">6485</span><span id="line-6485">          }</span> | 
 | <span class="source-line-no">6486</span><span id="line-6486"></span> | 
 | <span class="source-line-no">6487</span><span id="line-6487">          if (writestate.flushing) {</span> | 
 | <span class="source-line-no">6488</span><span id="line-6488">            // only drop memstore snapshots if they are smaller than last flush for the store</span> | 
 | <span class="source-line-no">6489</span><span id="line-6489">            if (this.prepareFlushResult.flushOpSeqId <= regionEvent.getLogSequenceNumber()) {</span> | 
 | <span class="source-line-no">6490</span><span id="line-6490">              StoreFlushContext ctx = this.prepareFlushResult.storeFlushCtxs == null</span> | 
 | <span class="source-line-no">6491</span><span id="line-6491">                ? null</span> | 
 | <span class="source-line-no">6492</span><span id="line-6492">                : this.prepareFlushResult.storeFlushCtxs.get(family);</span> | 
 | <span class="source-line-no">6493</span><span id="line-6493">              if (ctx != null) {</span> | 
 | <span class="source-line-no">6494</span><span id="line-6494">                MemStoreSize mss = store.getFlushableSize();</span> | 
 | <span class="source-line-no">6495</span><span id="line-6495">                ctx.abort();</span> | 
 | <span class="source-line-no">6496</span><span id="line-6496">                this.decrMemStoreSize(mss);</span> | 
 | <span class="source-line-no">6497</span><span id="line-6497">                this.prepareFlushResult.storeFlushCtxs.remove(family);</span> | 
 | <span class="source-line-no">6498</span><span id="line-6498">              }</span> | 
 | <span class="source-line-no">6499</span><span id="line-6499">            }</span> | 
 | <span class="source-line-no">6500</span><span id="line-6500">          }</span> | 
 | <span class="source-line-no">6501</span><span id="line-6501"></span> | 
 | <span class="source-line-no">6502</span><span id="line-6502">          // Drop the memstore contents if they are now smaller than the latest seen flushed file</span> | 
 | <span class="source-line-no">6503</span><span id="line-6503">          dropMemStoreContentsForSeqId(regionEvent.getLogSequenceNumber(), store);</span> | 
 | <span class="source-line-no">6504</span><span id="line-6504">          if (storeSeqId > this.maxFlushedSeqId) {</span> | 
 | <span class="source-line-no">6505</span><span id="line-6505">            this.maxFlushedSeqId = storeSeqId;</span> | 
 | <span class="source-line-no">6506</span><span id="line-6506">          }</span> | 
 | <span class="source-line-no">6507</span><span id="line-6507">        }</span> | 
 | <span class="source-line-no">6508</span><span id="line-6508"></span> | 
 | <span class="source-line-no">6509</span><span id="line-6509">        // if all stores ended up dropping their snapshots, we can safely drop the</span> | 
 | <span class="source-line-no">6510</span><span id="line-6510">        // prepareFlushResult</span> | 
 | <span class="source-line-no">6511</span><span id="line-6511">        dropPrepareFlushIfPossible();</span> | 
 | <span class="source-line-no">6512</span><span id="line-6512"></span> | 
 | <span class="source-line-no">6513</span><span id="line-6513">        // advance the mvcc read point so that the new flushed file is visible.</span> | 
 | <span class="source-line-no">6514</span><span id="line-6514">        mvcc.await();</span> | 
 | <span class="source-line-no">6515</span><span id="line-6515"></span> | 
 | <span class="source-line-no">6516</span><span id="line-6516">        // If we were waiting for observing a flush or region opening event for not showing partial</span> | 
 | <span class="source-line-no">6517</span><span id="line-6517">        // data after a secondary region crash, we can allow reads now.</span> | 
 | <span class="source-line-no">6518</span><span id="line-6518">        this.setReadsEnabled(true);</span> | 
 | <span class="source-line-no">6519</span><span id="line-6519"></span> | 
 | <span class="source-line-no">6520</span><span id="line-6520">        // C. Finally notify anyone waiting on memstore to clear:</span> | 
 | <span class="source-line-no">6521</span><span id="line-6521">        // e.g. checkResources().</span> | 
 | <span class="source-line-no">6522</span><span id="line-6522">        synchronized (this) {</span> | 
 | <span class="source-line-no">6523</span><span id="line-6523">          notifyAll(); // FindBugs NN_NAKED_NOTIFY</span> | 
 | <span class="source-line-no">6524</span><span id="line-6524">        }</span> | 
 | <span class="source-line-no">6525</span><span id="line-6525">      }</span> | 
 | <span class="source-line-no">6526</span><span id="line-6526">      logRegionFiles();</span> | 
 | <span class="source-line-no">6527</span><span id="line-6527">    } finally {</span> | 
 | <span class="source-line-no">6528</span><span id="line-6528">      closeRegionOperation(Operation.REPLAY_EVENT);</span> | 
 | <span class="source-line-no">6529</span><span id="line-6529">    }</span> | 
 | <span class="source-line-no">6530</span><span id="line-6530">  }</span> | 
 | <span class="source-line-no">6531</span><span id="line-6531"></span> | 
 | <span class="source-line-no">6532</span><span id="line-6532">  /**</span> | 
 | <span class="source-line-no">6533</span><span id="line-6533">   * @deprecated Since 3.0.0, will be removed in 4.0.0. Only for keep compatibility for old region</span> | 
 | <span class="source-line-no">6534</span><span id="line-6534">   *             replica implementation.</span> | 
 | <span class="source-line-no">6535</span><span id="line-6535">   */</span> | 
 | <span class="source-line-no">6536</span><span id="line-6536">  @Deprecated</span> | 
 | <span class="source-line-no">6537</span><span id="line-6537">  void replayWALBulkLoadEventMarker(WALProtos.BulkLoadDescriptor bulkLoadEvent) throws IOException {</span> | 
 | <span class="source-line-no">6538</span><span id="line-6538">    checkTargetRegion(bulkLoadEvent.getEncodedRegionName().toByteArray(),</span> | 
 | <span class="source-line-no">6539</span><span id="line-6539">      "BulkLoad marker from WAL ", bulkLoadEvent);</span> | 
 | <span class="source-line-no">6540</span><span id="line-6540"></span> | 
 | <span class="source-line-no">6541</span><span id="line-6541">    if (ServerRegionReplicaUtil.isDefaultReplica(this.getRegionInfo())) {</span> | 
 | <span class="source-line-no">6542</span><span id="line-6542">      return; // if primary nothing to do</span> | 
 | <span class="source-line-no">6543</span><span id="line-6543">    }</span> | 
 | <span class="source-line-no">6544</span><span id="line-6544"></span> | 
 | <span class="source-line-no">6545</span><span id="line-6545">    if (LOG.isDebugEnabled()) {</span> | 
 | <span class="source-line-no">6546</span><span id="line-6546">      LOG.debug(getRegionInfo().getEncodedName() + " : " + "Replaying bulkload event marker "</span> | 
 | <span class="source-line-no">6547</span><span id="line-6547">        + TextFormat.shortDebugString(bulkLoadEvent));</span> | 
 | <span class="source-line-no">6548</span><span id="line-6548">    }</span> | 
 | <span class="source-line-no">6549</span><span id="line-6549">    // check if multiple families involved</span> | 
 | <span class="source-line-no">6550</span><span id="line-6550">    boolean multipleFamilies = false;</span> | 
 | <span class="source-line-no">6551</span><span id="line-6551">    byte[] family = null;</span> | 
 | <span class="source-line-no">6552</span><span id="line-6552">    for (StoreDescriptor storeDescriptor : bulkLoadEvent.getStoresList()) {</span> | 
 | <span class="source-line-no">6553</span><span id="line-6553">      byte[] fam = storeDescriptor.getFamilyName().toByteArray();</span> | 
 | <span class="source-line-no">6554</span><span id="line-6554">      if (family == null) {</span> | 
 | <span class="source-line-no">6555</span><span id="line-6555">        family = fam;</span> | 
 | <span class="source-line-no">6556</span><span id="line-6556">      } else if (!Bytes.equals(family, fam)) {</span> | 
 | <span class="source-line-no">6557</span><span id="line-6557">        multipleFamilies = true;</span> | 
 | <span class="source-line-no">6558</span><span id="line-6558">        break;</span> | 
 | <span class="source-line-no">6559</span><span id="line-6559">      }</span> | 
 | <span class="source-line-no">6560</span><span id="line-6560">    }</span> | 
 | <span class="source-line-no">6561</span><span id="line-6561"></span> | 
 | <span class="source-line-no">6562</span><span id="line-6562">    startBulkRegionOperation(multipleFamilies);</span> | 
 | <span class="source-line-no">6563</span><span id="line-6563">    try {</span> | 
 | <span class="source-line-no">6564</span><span id="line-6564">      // we will use writestate as a coarse-grain lock for all the replay events</span> | 
 | <span class="source-line-no">6565</span><span id="line-6565">      synchronized (writestate) {</span> | 
 | <span class="source-line-no">6566</span><span id="line-6566">        // Replication can deliver events out of order when primary region moves or the region</span> | 
 | <span class="source-line-no">6567</span><span id="line-6567">        // server crashes, since there is no coordination between replication of different wal files</span> | 
 | <span class="source-line-no">6568</span><span id="line-6568">        // belonging to different region servers. We have to safe guard against this case by using</span> | 
 | <span class="source-line-no">6569</span><span id="line-6569">        // region open event's seqid. Since this is the first event that the region puts (after</span> | 
 | <span class="source-line-no">6570</span><span id="line-6570">        // possibly flushing recovered.edits), after seeing this event, we can ignore every edit</span> | 
 | <span class="source-line-no">6571</span><span id="line-6571">        // smaller than this seqId</span> | 
 | <span class="source-line-no">6572</span><span id="line-6572">        if (</span> | 
 | <span class="source-line-no">6573</span><span id="line-6573">          bulkLoadEvent.getBulkloadSeqNum() >= 0</span> | 
 | <span class="source-line-no">6574</span><span id="line-6574">            && this.lastReplayedOpenRegionSeqId >= bulkLoadEvent.getBulkloadSeqNum()</span> | 
 | <span class="source-line-no">6575</span><span id="line-6575">        ) {</span> | 
 | <span class="source-line-no">6576</span><span id="line-6576">          LOG.warn(getRegionInfo().getEncodedName() + " : " + "Skipping replaying bulkload event :"</span> | 
 | <span class="source-line-no">6577</span><span id="line-6577">            + TextFormat.shortDebugString(bulkLoadEvent)</span> | 
 | <span class="source-line-no">6578</span><span id="line-6578">            + " because its sequence id is smaller than this region's lastReplayedOpenRegionSeqId"</span> | 
 | <span class="source-line-no">6579</span><span id="line-6579">            + " =" + lastReplayedOpenRegionSeqId);</span> | 
 | <span class="source-line-no">6580</span><span id="line-6580"></span> | 
 | <span class="source-line-no">6581</span><span id="line-6581">          return;</span> | 
 | <span class="source-line-no">6582</span><span id="line-6582">        }</span> | 
 | <span class="source-line-no">6583</span><span id="line-6583"></span> | 
 | <span class="source-line-no">6584</span><span id="line-6584">        for (StoreDescriptor storeDescriptor : bulkLoadEvent.getStoresList()) {</span> | 
 | <span class="source-line-no">6585</span><span id="line-6585">          // stores of primary may be different now</span> | 
 | <span class="source-line-no">6586</span><span id="line-6586">          family = storeDescriptor.getFamilyName().toByteArray();</span> | 
 | <span class="source-line-no">6587</span><span id="line-6587">          HStore store = getStore(family);</span> | 
 | <span class="source-line-no">6588</span><span id="line-6588">          if (store == null) {</span> | 
 | <span class="source-line-no">6589</span><span id="line-6589">            LOG.warn(getRegionInfo().getEncodedName() + " : "</span> | 
 | <span class="source-line-no">6590</span><span id="line-6590">              + "Received a bulk load marker from primary, but the family is not found. "</span> | 
 | <span class="source-line-no">6591</span><span id="line-6591">              + "Ignoring. StoreDescriptor:" + storeDescriptor);</span> | 
 | <span class="source-line-no">6592</span><span id="line-6592">            continue;</span> | 
 | <span class="source-line-no">6593</span><span id="line-6593">          }</span> | 
 | <span class="source-line-no">6594</span><span id="line-6594"></span> | 
 | <span class="source-line-no">6595</span><span id="line-6595">          StoreContext storeContext = store.getStoreContext();</span> | 
 | <span class="source-line-no">6596</span><span id="line-6596">          StoreFileTracker sft = StoreFileTrackerFactory.create(conf, false, storeContext);</span> | 
 | <span class="source-line-no">6597</span><span id="line-6597"></span> | 
 | <span class="source-line-no">6598</span><span id="line-6598">          List<StoreFileInfo> storeFiles = sft.load();</span> | 
 | <span class="source-line-no">6599</span><span id="line-6599">          for (StoreFileInfo storeFileInfo : storeFiles) {</span> | 
 | <span class="source-line-no">6600</span><span id="line-6600">            try {</span> | 
 | <span class="source-line-no">6601</span><span id="line-6601">              store.bulkLoadHFile(storeFileInfo);</span> | 
 | <span class="source-line-no">6602</span><span id="line-6602">            } catch (FileNotFoundException ex) {</span> | 
 | <span class="source-line-no">6603</span><span id="line-6603">              LOG.warn(getRegionInfo().getEncodedName() + " : " + storeFileInfo.toString()</span> | 
 | <span class="source-line-no">6604</span><span id="line-6604">                + " doesn't exist any more. Skip loading the file");</span> | 
 | <span class="source-line-no">6605</span><span id="line-6605">            }</span> | 
 | <span class="source-line-no">6606</span><span id="line-6606">          }</span> | 
 | <span class="source-line-no">6607</span><span id="line-6607">        }</span> | 
 | <span class="source-line-no">6608</span><span id="line-6608">      }</span> | 
 | <span class="source-line-no">6609</span><span id="line-6609">      if (bulkLoadEvent.getBulkloadSeqNum() > 0) {</span> | 
 | <span class="source-line-no">6610</span><span id="line-6610">        mvcc.advanceTo(bulkLoadEvent.getBulkloadSeqNum());</span> | 
 | <span class="source-line-no">6611</span><span id="line-6611">      }</span> | 
 | <span class="source-line-no">6612</span><span id="line-6612">    } finally {</span> | 
 | <span class="source-line-no">6613</span><span id="line-6613">      closeBulkRegionOperation();</span> | 
 | <span class="source-line-no">6614</span><span id="line-6614">    }</span> | 
 | <span class="source-line-no">6615</span><span id="line-6615">  }</span> | 
 | <span class="source-line-no">6616</span><span id="line-6616"></span> | 
 | <span class="source-line-no">6617</span><span id="line-6617">  /**</span> | 
 | <span class="source-line-no">6618</span><span id="line-6618">   * Replay the batch mutate for secondary replica.</span> | 
 | <span class="source-line-no">6619</span><span id="line-6619">   * <p/></span> | 
 | <span class="source-line-no">6620</span><span id="line-6620">   * We will directly apply the cells to the memstore. This is because:</span> | 
 | <span class="source-line-no">6621</span><span id="line-6621">   * <ol></span> | 
 | <span class="source-line-no">6622</span><span id="line-6622">   * <li>All the cells are gotten from {@link WALEdit}, so we only have {@link Put} and</span> | 
 | <span class="source-line-no">6623</span><span id="line-6623">   * {@link Delete} here</li></span> | 
 | <span class="source-line-no">6624</span><span id="line-6624">   * <li>The replay is single threaded, we do not need to acquire row lock, as the region is read</span> | 
 | <span class="source-line-no">6625</span><span id="line-6625">   * only so no one else can write it.</li></span> | 
 | <span class="source-line-no">6626</span><span id="line-6626">   * <li>We do not need to write WAL.</li></span> | 
 | <span class="source-line-no">6627</span><span id="line-6627">   * <li>We will advance MVCC in the caller directly.</li></span> | 
 | <span class="source-line-no">6628</span><span id="line-6628">   * </ol></span> | 
 | <span class="source-line-no">6629</span><span id="line-6629">   */</span> | 
 | <span class="source-line-no">6630</span><span id="line-6630">  private void replayWALBatchMutate(Map<byte[], List<ExtendedCell>> family2Cells)</span> | 
 | <span class="source-line-no">6631</span><span id="line-6631">    throws IOException {</span> | 
 | <span class="source-line-no">6632</span><span id="line-6632">    startRegionOperation(Operation.REPLAY_BATCH_MUTATE);</span> | 
 | <span class="source-line-no">6633</span><span id="line-6633">    try {</span> | 
 | <span class="source-line-no">6634</span><span id="line-6634">      for (Map.Entry<byte[], List<ExtendedCell>> entry : family2Cells.entrySet()) {</span> | 
 | <span class="source-line-no">6635</span><span id="line-6635">        applyToMemStore(getStore(entry.getKey()), entry.getValue(), false, memStoreSizing);</span> | 
 | <span class="source-line-no">6636</span><span id="line-6636">      }</span> | 
 | <span class="source-line-no">6637</span><span id="line-6637">    } finally {</span> | 
 | <span class="source-line-no">6638</span><span id="line-6638">      closeRegionOperation(Operation.REPLAY_BATCH_MUTATE);</span> | 
 | <span class="source-line-no">6639</span><span id="line-6639">    }</span> | 
 | <span class="source-line-no">6640</span><span id="line-6640">  }</span> | 
 | <span class="source-line-no">6641</span><span id="line-6641"></span> | 
 | <span class="source-line-no">6642</span><span id="line-6642">  /**</span> | 
 | <span class="source-line-no">6643</span><span id="line-6643">   * Replay the meta edits, i.e, flush marker, compaction marker, bulk load marker, region event</span> | 
 | <span class="source-line-no">6644</span><span id="line-6644">   * marker, etc.</span> | 
 | <span class="source-line-no">6645</span><span id="line-6645">   * <p/></span> | 
 | <span class="source-line-no">6646</span><span id="line-6646">   * For all events other than start flush, we will just call {@link #refreshStoreFiles()} as the</span> | 
 | <span class="source-line-no">6647</span><span id="line-6647">   * logic is straight-forward and robust. For start flush, we need to snapshot the memstore, so</span> | 
 | <span class="source-line-no">6648</span><span id="line-6648">   * later {@link #refreshStoreFiles()} call could drop the snapshot, otherwise we may run out of</span> | 
 | <span class="source-line-no">6649</span><span id="line-6649">   * memory.</span> | 
 | <span class="source-line-no">6650</span><span id="line-6650">   */</span> | 
 | <span class="source-line-no">6651</span><span id="line-6651">  private void replayWALMetaEdit(Cell cell) throws IOException {</span> | 
 | <span class="source-line-no">6652</span><span id="line-6652">    startRegionOperation(Operation.REPLAY_EVENT);</span> | 
 | <span class="source-line-no">6653</span><span id="line-6653">    try {</span> | 
 | <span class="source-line-no">6654</span><span id="line-6654">      FlushDescriptor flushDesc = WALEdit.getFlushDescriptor(cell);</span> | 
 | <span class="source-line-no">6655</span><span id="line-6655">      if (flushDesc != null) {</span> | 
 | <span class="source-line-no">6656</span><span id="line-6656">        switch (flushDesc.getAction()) {</span> | 
 | <span class="source-line-no">6657</span><span id="line-6657">          case START_FLUSH:</span> | 
 | <span class="source-line-no">6658</span><span id="line-6658">            // for start flush, we need to take a snapshot of the current memstore</span> | 
 | <span class="source-line-no">6659</span><span id="line-6659">            synchronized (writestate) {</span> | 
 | <span class="source-line-no">6660</span><span id="line-6660">              if (!writestate.flushing) {</span> | 
 | <span class="source-line-no">6661</span><span id="line-6661">                this.writestate.flushing = true;</span> | 
 | <span class="source-line-no">6662</span><span id="line-6662">              } else {</span> | 
 | <span class="source-line-no">6663</span><span id="line-6663">                // usually this should not happen but let's make the code more robust, it is not a</span> | 
 | <span class="source-line-no">6664</span><span id="line-6664">                // big deal to just ignore it, the refreshStoreFiles call should have the ability to</span> | 
 | <span class="source-line-no">6665</span><span id="line-6665">                // clean up the inconsistent state.</span> | 
 | <span class="source-line-no">6666</span><span id="line-6666">                LOG.debug("NOT flushing {} as already flushing", getRegionInfo());</span> | 
 | <span class="source-line-no">6667</span><span id="line-6667">                break;</span> | 
 | <span class="source-line-no">6668</span><span id="line-6668">              }</span> | 
 | <span class="source-line-no">6669</span><span id="line-6669">            }</span> | 
 | <span class="source-line-no">6670</span><span id="line-6670">            MonitoredTask status =</span> | 
 | <span class="source-line-no">6671</span><span id="line-6671">              TaskMonitor.get().createStatus("Preparing flush " + getRegionInfo());</span> | 
 | <span class="source-line-no">6672</span><span id="line-6672">            Collection<HStore> storesToFlush = getStoresToFlush(flushDesc);</span> | 
 | <span class="source-line-no">6673</span><span id="line-6673">            try {</span> | 
 | <span class="source-line-no">6674</span><span id="line-6674">              PrepareFlushResult prepareResult =</span> | 
 | <span class="source-line-no">6675</span><span id="line-6675">                internalPrepareFlushCache(null, flushDesc.getFlushSequenceNumber(), storesToFlush,</span> | 
 | <span class="source-line-no">6676</span><span id="line-6676">                  status, false, FlushLifeCycleTracker.DUMMY);</span> | 
 | <span class="source-line-no">6677</span><span id="line-6677">              if (prepareResult.result == null) {</span> | 
 | <span class="source-line-no">6678</span><span id="line-6678">                // save the PrepareFlushResult so that we can use it later from commit flush</span> | 
 | <span class="source-line-no">6679</span><span id="line-6679">                this.prepareFlushResult = prepareResult;</span> | 
 | <span class="source-line-no">6680</span><span id="line-6680">                status.markComplete("Flush prepare successful");</span> | 
 | <span class="source-line-no">6681</span><span id="line-6681">                if (LOG.isDebugEnabled()) {</span> | 
 | <span class="source-line-no">6682</span><span id="line-6682">                  LOG.debug("{} prepared flush with seqId: {}", getRegionInfo(),</span> | 
 | <span class="source-line-no">6683</span><span id="line-6683">                    flushDesc.getFlushSequenceNumber());</span> | 
 | <span class="source-line-no">6684</span><span id="line-6684">                }</span> | 
 | <span class="source-line-no">6685</span><span id="line-6685">              } else {</span> | 
 | <span class="source-line-no">6686</span><span id="line-6686">                // special case empty memstore. We will still save the flush result in this case,</span> | 
 | <span class="source-line-no">6687</span><span id="line-6687">                // since our memstore is empty, but the primary is still flushing</span> | 
 | <span class="source-line-no">6688</span><span id="line-6688">                if (</span> | 
 | <span class="source-line-no">6689</span><span id="line-6689">                  prepareResult.getResult().getResult()</span> | 
 | <span class="source-line-no">6690</span><span id="line-6690">                      == FlushResult.Result.CANNOT_FLUSH_MEMSTORE_EMPTY</span> | 
 | <span class="source-line-no">6691</span><span id="line-6691">                ) {</span> | 
 | <span class="source-line-no">6692</span><span id="line-6692">                  this.prepareFlushResult = prepareResult;</span> | 
 | <span class="source-line-no">6693</span><span id="line-6693">                  if (LOG.isDebugEnabled()) {</span> | 
 | <span class="source-line-no">6694</span><span id="line-6694">                    LOG.debug("{} prepared empty flush with seqId: {}", getRegionInfo(),</span> | 
 | <span class="source-line-no">6695</span><span id="line-6695">                      flushDesc.getFlushSequenceNumber());</span> | 
 | <span class="source-line-no">6696</span><span id="line-6696">                  }</span> | 
 | <span class="source-line-no">6697</span><span id="line-6697">                }</span> | 
 | <span class="source-line-no">6698</span><span id="line-6698">                status.abort("Flush prepare failed with " + prepareResult.result);</span> | 
 | <span class="source-line-no">6699</span><span id="line-6699">                // nothing much to do. prepare flush failed because of some reason.</span> | 
 | <span class="source-line-no">6700</span><span id="line-6700">              }</span> | 
 | <span class="source-line-no">6701</span><span id="line-6701">            } finally {</span> | 
 | <span class="source-line-no">6702</span><span id="line-6702">              status.cleanup();</span> | 
 | <span class="source-line-no">6703</span><span id="line-6703">            }</span> | 
 | <span class="source-line-no">6704</span><span id="line-6704">            break;</span> | 
 | <span class="source-line-no">6705</span><span id="line-6705">          case ABORT_FLUSH:</span> | 
 | <span class="source-line-no">6706</span><span id="line-6706">            // do nothing, an abort flush means the source region server will crash itself, after</span> | 
 | <span class="source-line-no">6707</span><span id="line-6707">            // the primary region online, it will send us an open region marker, then we can clean</span> | 
 | <span class="source-line-no">6708</span><span id="line-6708">            // up the memstore.</span> | 
 | <span class="source-line-no">6709</span><span id="line-6709">            synchronized (writestate) {</span> | 
 | <span class="source-line-no">6710</span><span id="line-6710">              writestate.flushing = false;</span> | 
 | <span class="source-line-no">6711</span><span id="line-6711">            }</span> | 
 | <span class="source-line-no">6712</span><span id="line-6712">            break;</span> | 
 | <span class="source-line-no">6713</span><span id="line-6713">          case COMMIT_FLUSH:</span> | 
 | <span class="source-line-no">6714</span><span id="line-6714">          case CANNOT_FLUSH:</span> | 
 | <span class="source-line-no">6715</span><span id="line-6715">            // just call refreshStoreFiles</span> | 
 | <span class="source-line-no">6716</span><span id="line-6716">            refreshStoreFiles();</span> | 
 | <span class="source-line-no">6717</span><span id="line-6717">            logRegionFiles();</span> | 
 | <span class="source-line-no">6718</span><span id="line-6718">            synchronized (writestate) {</span> | 
 | <span class="source-line-no">6719</span><span id="line-6719">              writestate.flushing = false;</span> | 
 | <span class="source-line-no">6720</span><span id="line-6720">            }</span> | 
 | <span class="source-line-no">6721</span><span id="line-6721">            break;</span> | 
 | <span class="source-line-no">6722</span><span id="line-6722">          default:</span> | 
 | <span class="source-line-no">6723</span><span id="line-6723">            LOG.warn("{} received a flush event with unknown action: {}", getRegionInfo(),</span> | 
 | <span class="source-line-no">6724</span><span id="line-6724">              TextFormat.shortDebugString(flushDesc));</span> | 
 | <span class="source-line-no">6725</span><span id="line-6725">        }</span> | 
 | <span class="source-line-no">6726</span><span id="line-6726">      } else {</span> | 
 | <span class="source-line-no">6727</span><span id="line-6727">        // for all other region events, we will do a refreshStoreFiles</span> | 
 | <span class="source-line-no">6728</span><span id="line-6728">        refreshStoreFiles();</span> | 
 | <span class="source-line-no">6729</span><span id="line-6729">        logRegionFiles();</span> | 
 | <span class="source-line-no">6730</span><span id="line-6730">      }</span> | 
 | <span class="source-line-no">6731</span><span id="line-6731">    } finally {</span> | 
 | <span class="source-line-no">6732</span><span id="line-6732">      closeRegionOperation(Operation.REPLAY_EVENT);</span> | 
 | <span class="source-line-no">6733</span><span id="line-6733">    }</span> | 
 | <span class="source-line-no">6734</span><span id="line-6734">  }</span> | 
 | <span class="source-line-no">6735</span><span id="line-6735"></span> | 
 | <span class="source-line-no">6736</span><span id="line-6736">  /**</span> | 
 | <span class="source-line-no">6737</span><span id="line-6737">   * Replay remote wal entry sent by primary replica.</span> | 
 | <span class="source-line-no">6738</span><span id="line-6738">   * <p/></span> | 
 | <span class="source-line-no">6739</span><span id="line-6739">   * Should only call this method on secondary replicas.</span> | 
 | <span class="source-line-no">6740</span><span id="line-6740">   */</span> | 
 | <span class="source-line-no">6741</span><span id="line-6741">  void replayWALEntry(WALEntry entry, CellScanner cells) throws IOException {</span> | 
 | <span class="source-line-no">6742</span><span id="line-6742">    long timeout = -1L;</span> | 
 | <span class="source-line-no">6743</span><span id="line-6743">    Optional<RpcCall> call = RpcServer.getCurrentCall();</span> | 
 | <span class="source-line-no">6744</span><span id="line-6744">    if (call.isPresent()) {</span> | 
 | <span class="source-line-no">6745</span><span id="line-6745">      long deadline = call.get().getDeadline();</span> | 
 | <span class="source-line-no">6746</span><span id="line-6746">      if (deadline < Long.MAX_VALUE) {</span> | 
 | <span class="source-line-no">6747</span><span id="line-6747">        timeout = deadline - EnvironmentEdgeManager.currentTime();</span> | 
 | <span class="source-line-no">6748</span><span id="line-6748">        if (timeout <= 0) {</span> | 
 | <span class="source-line-no">6749</span><span id="line-6749">          throw new TimeoutIOException("Timeout while replaying edits for " + getRegionInfo());</span> | 
 | <span class="source-line-no">6750</span><span id="line-6750">        }</span> | 
 | <span class="source-line-no">6751</span><span id="line-6751">      }</span> | 
 | <span class="source-line-no">6752</span><span id="line-6752">    }</span> | 
 | <span class="source-line-no">6753</span><span id="line-6753">    if (timeout > 0) {</span> | 
 | <span class="source-line-no">6754</span><span id="line-6754">      try {</span> | 
 | <span class="source-line-no">6755</span><span id="line-6755">        if (!replayLock.tryLock(timeout, TimeUnit.MILLISECONDS)) {</span> | 
 | <span class="source-line-no">6756</span><span id="line-6756">          throw new TimeoutIOException(</span> | 
 | <span class="source-line-no">6757</span><span id="line-6757">            "Timeout while waiting for lock when replaying edits for " + getRegionInfo());</span> | 
 | <span class="source-line-no">6758</span><span id="line-6758">        }</span> | 
 | <span class="source-line-no">6759</span><span id="line-6759">      } catch (InterruptedException e) {</span> | 
 | <span class="source-line-no">6760</span><span id="line-6760">        throw throwOnInterrupt(e);</span> | 
 | <span class="source-line-no">6761</span><span id="line-6761">      }</span> | 
 | <span class="source-line-no">6762</span><span id="line-6762">    } else {</span> | 
 | <span class="source-line-no">6763</span><span id="line-6763">      replayLock.lock();</span> | 
 | <span class="source-line-no">6764</span><span id="line-6764">    }</span> | 
 | <span class="source-line-no">6765</span><span id="line-6765">    try {</span> | 
 | <span class="source-line-no">6766</span><span id="line-6766">      int count = entry.getAssociatedCellCount();</span> | 
 | <span class="source-line-no">6767</span><span id="line-6767">      long sequenceId = entry.getKey().getLogSequenceNumber();</span> | 
 | <span class="source-line-no">6768</span><span id="line-6768">      if (lastReplayedSequenceId >= sequenceId) {</span> | 
 | <span class="source-line-no">6769</span><span id="line-6769">        // we have already replayed this edit, skip</span> | 
 | <span class="source-line-no">6770</span><span id="line-6770">        // remember to advance the CellScanner, as we may have multiple WALEntries, we may still</span> | 
 | <span class="source-line-no">6771</span><span id="line-6771">        // need apply later WALEntries</span> | 
 | <span class="source-line-no">6772</span><span id="line-6772">        for (int i = 0; i < count; i++) {</span> | 
 | <span class="source-line-no">6773</span><span id="line-6773">          // Throw index out of bounds if our cell count is off</span> | 
 | <span class="source-line-no">6774</span><span id="line-6774">          if (!cells.advance()) {</span> | 
 | <span class="source-line-no">6775</span><span id="line-6775">            throw new ArrayIndexOutOfBoundsException("Expected=" + count + ", index=" + i);</span> | 
 | <span class="source-line-no">6776</span><span id="line-6776">          }</span> | 
 | <span class="source-line-no">6777</span><span id="line-6777">        }</span> | 
 | <span class="source-line-no">6778</span><span id="line-6778">        return;</span> | 
 | <span class="source-line-no">6779</span><span id="line-6779">      }</span> | 
 | <span class="source-line-no">6780</span><span id="line-6780">      Map<byte[], List<ExtendedCell>> family2Cells = new TreeMap<>(Bytes.BYTES_COMPARATOR);</span> | 
 | <span class="source-line-no">6781</span><span id="line-6781">      for (int i = 0; i < count; i++) {</span> | 
 | <span class="source-line-no">6782</span><span id="line-6782">        // Throw index out of bounds if our cell count is off</span> | 
 | <span class="source-line-no">6783</span><span id="line-6783">        if (!cells.advance()) {</span> | 
 | <span class="source-line-no">6784</span><span id="line-6784">          throw new ArrayIndexOutOfBoundsException("Expected=" + count + ", index=" + i);</span> | 
 | <span class="source-line-no">6785</span><span id="line-6785">        }</span> | 
 | <span class="source-line-no">6786</span><span id="line-6786">        Cell c = cells.current();</span> | 
 | <span class="source-line-no">6787</span><span id="line-6787">        assert c instanceof ExtendedCell;</span> | 
 | <span class="source-line-no">6788</span><span id="line-6788">        ExtendedCell cell = (ExtendedCell) c;</span> | 
 | <span class="source-line-no">6789</span><span id="line-6789">        if (WALEdit.isMetaEditFamily(cell)) {</span> | 
 | <span class="source-line-no">6790</span><span id="line-6790">          // If there is meta edit, i.e, we have done flush/compaction/open, then we need to apply</span> | 
 | <span class="source-line-no">6791</span><span id="line-6791">          // the previous cells first, and then replay the special meta edit. The meta edit is like</span> | 
 | <span class="source-line-no">6792</span><span id="line-6792">          // a barrier, We need to keep the order. For example, the flush marker will contain a</span> | 
 | <span class="source-line-no">6793</span><span id="line-6793">          // flush sequence number, which makes us possible to drop memstore content, but if we</span> | 
 | <span class="source-line-no">6794</span><span id="line-6794">          // apply some edits which have greater sequence id first, then we can not drop the</span> | 
 | <span class="source-line-no">6795</span><span id="line-6795">          // memstore content when replaying the flush marker, which is not good as we could run out</span> | 
 | <span class="source-line-no">6796</span><span id="line-6796">          // of memory.</span> | 
 | <span class="source-line-no">6797</span><span id="line-6797">          // And usually, a meta edit will have a special WALEntry for it, so this is just a safe</span> | 
 | <span class="source-line-no">6798</span><span id="line-6798">          // guard logic to make sure we do not break things in the worst case.</span> | 
 | <span class="source-line-no">6799</span><span id="line-6799">          if (!family2Cells.isEmpty()) {</span> | 
 | <span class="source-line-no">6800</span><span id="line-6800">            replayWALBatchMutate(family2Cells);</span> | 
 | <span class="source-line-no">6801</span><span id="line-6801">            family2Cells.clear();</span> | 
 | <span class="source-line-no">6802</span><span id="line-6802">          }</span> | 
 | <span class="source-line-no">6803</span><span id="line-6803">          replayWALMetaEdit(cell);</span> | 
 | <span class="source-line-no">6804</span><span id="line-6804">        } else {</span> | 
 | <span class="source-line-no">6805</span><span id="line-6805">          family2Cells.computeIfAbsent(CellUtil.cloneFamily(cell), k -> new ArrayList<>())</span> | 
 | <span class="source-line-no">6806</span><span id="line-6806">            .add(cell);</span> | 
 | <span class="source-line-no">6807</span><span id="line-6807">        }</span> | 
 | <span class="source-line-no">6808</span><span id="line-6808">      }</span> | 
 | <span class="source-line-no">6809</span><span id="line-6809">      // do not forget to apply the remaining cells</span> | 
 | <span class="source-line-no">6810</span><span id="line-6810">      if (!family2Cells.isEmpty()) {</span> | 
 | <span class="source-line-no">6811</span><span id="line-6811">        replayWALBatchMutate(family2Cells);</span> | 
 | <span class="source-line-no">6812</span><span id="line-6812">      }</span> | 
 | <span class="source-line-no">6813</span><span id="line-6813">      mvcc.advanceTo(sequenceId);</span> | 
 | <span class="source-line-no">6814</span><span id="line-6814">      lastReplayedSequenceId = sequenceId;</span> | 
 | <span class="source-line-no">6815</span><span id="line-6815">    } finally {</span> | 
 | <span class="source-line-no">6816</span><span id="line-6816">      replayLock.unlock();</span> | 
 | <span class="source-line-no">6817</span><span id="line-6817">    }</span> | 
 | <span class="source-line-no">6818</span><span id="line-6818">  }</span> | 
 | <span class="source-line-no">6819</span><span id="line-6819"></span> | 
 | <span class="source-line-no">6820</span><span id="line-6820">  /**</span> | 
 | <span class="source-line-no">6821</span><span id="line-6821">   * If all stores ended up dropping their snapshots, we can safely drop the prepareFlushResult</span> | 
 | <span class="source-line-no">6822</span><span id="line-6822">   */</span> | 
 | <span class="source-line-no">6823</span><span id="line-6823">  private void dropPrepareFlushIfPossible() {</span> | 
 | <span class="source-line-no">6824</span><span id="line-6824">    if (writestate.flushing) {</span> | 
 | <span class="source-line-no">6825</span><span id="line-6825">      boolean canDrop = true;</span> | 
 | <span class="source-line-no">6826</span><span id="line-6826">      if (prepareFlushResult.storeFlushCtxs != null) {</span> | 
 | <span class="source-line-no">6827</span><span id="line-6827">        for (Entry<byte[], StoreFlushContext> entry : prepareFlushResult.storeFlushCtxs</span> | 
 | <span class="source-line-no">6828</span><span id="line-6828">          .entrySet()) {</span> | 
 | <span class="source-line-no">6829</span><span id="line-6829">          HStore store = getStore(entry.getKey());</span> | 
 | <span class="source-line-no">6830</span><span id="line-6830">          if (store == null) {</span> | 
 | <span class="source-line-no">6831</span><span id="line-6831">            continue;</span> | 
 | <span class="source-line-no">6832</span><span id="line-6832">          }</span> | 
 | <span class="source-line-no">6833</span><span id="line-6833">          if (store.getSnapshotSize().getDataSize() > 0) {</span> | 
 | <span class="source-line-no">6834</span><span id="line-6834">            canDrop = false;</span> | 
 | <span class="source-line-no">6835</span><span id="line-6835">            break;</span> | 
 | <span class="source-line-no">6836</span><span id="line-6836">          }</span> | 
 | <span class="source-line-no">6837</span><span id="line-6837">        }</span> | 
 | <span class="source-line-no">6838</span><span id="line-6838">      }</span> | 
 | <span class="source-line-no">6839</span><span id="line-6839"></span> | 
 | <span class="source-line-no">6840</span><span id="line-6840">      // this means that all the stores in the region has finished flushing, but the WAL marker</span> | 
 | <span class="source-line-no">6841</span><span id="line-6841">      // may not have been written or we did not receive it yet.</span> | 
 | <span class="source-line-no">6842</span><span id="line-6842">      if (canDrop) {</span> | 
 | <span class="source-line-no">6843</span><span id="line-6843">        writestate.flushing = false;</span> | 
 | <span class="source-line-no">6844</span><span id="line-6844">        this.prepareFlushResult = null;</span> | 
 | <span class="source-line-no">6845</span><span id="line-6845">      }</span> | 
 | <span class="source-line-no">6846</span><span id="line-6846">    }</span> | 
 | <span class="source-line-no">6847</span><span id="line-6847">  }</span> | 
 | <span class="source-line-no">6848</span><span id="line-6848"></span> | 
 | <span class="source-line-no">6849</span><span id="line-6849">  @Override</span> | 
 | <span class="source-line-no">6850</span><span id="line-6850">  public boolean refreshStoreFiles() throws IOException {</span> | 
 | <span class="source-line-no">6851</span><span id="line-6851">    return refreshStoreFiles(false);</span> | 
 | <span class="source-line-no">6852</span><span id="line-6852">  }</span> | 
 | <span class="source-line-no">6853</span><span id="line-6853"></span> | 
 | <span class="source-line-no">6854</span><span id="line-6854">  @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "NN_NAKED_NOTIFY",</span> | 
 | <span class="source-line-no">6855</span><span id="line-6855">      justification = "Notify is about post replay. Intentional")</span> | 
 | <span class="source-line-no">6856</span><span id="line-6856">  protected boolean refreshStoreFiles(boolean force) throws IOException {</span> | 
 | <span class="source-line-no">6857</span><span id="line-6857">    if (!force && ServerRegionReplicaUtil.isDefaultReplica(this.getRegionInfo())) {</span> | 
 | <span class="source-line-no">6858</span><span id="line-6858">      return false; // if primary nothing to do</span> | 
 | <span class="source-line-no">6859</span><span id="line-6859">    }</span> | 
 | <span class="source-line-no">6860</span><span id="line-6860"></span> | 
 | <span class="source-line-no">6861</span><span id="line-6861">    if (LOG.isDebugEnabled()) {</span> | 
 | <span class="source-line-no">6862</span><span id="line-6862">      LOG.debug(getRegionInfo().getEncodedName() + " : "</span> | 
 | <span class="source-line-no">6863</span><span id="line-6863">        + "Refreshing store files to see whether we can free up memstore");</span> | 
 | <span class="source-line-no">6864</span><span id="line-6864">    }</span> | 
 | <span class="source-line-no">6865</span><span id="line-6865"></span> | 
 | <span class="source-line-no">6866</span><span id="line-6866">    long totalFreedDataSize = 0;</span> | 
 | <span class="source-line-no">6867</span><span id="line-6867"></span> | 
 | <span class="source-line-no">6868</span><span id="line-6868">    long smallestSeqIdInStores = Long.MAX_VALUE;</span> | 
 | <span class="source-line-no">6869</span><span id="line-6869"></span> | 
 | <span class="source-line-no">6870</span><span id="line-6870">    startRegionOperation(); // obtain region close lock</span> | 
 | <span class="source-line-no">6871</span><span id="line-6871">    try {</span> | 
 | <span class="source-line-no">6872</span><span id="line-6872">      Map<HStore, Long> map = new HashMap<>();</span> | 
 | <span class="source-line-no">6873</span><span id="line-6873">      synchronized (writestate) {</span> | 
 | <span class="source-line-no">6874</span><span id="line-6874">        for (HStore store : stores.values()) {</span> | 
 | <span class="source-line-no">6875</span><span id="line-6875">          // TODO: some stores might see new data from flush, while others do not which</span> | 
 | <span class="source-line-no">6876</span><span id="line-6876">          // MIGHT break atomic edits across column families.</span> | 
 | <span class="source-line-no">6877</span><span id="line-6877">          long maxSeqIdBefore = store.getMaxSequenceId().orElse(0L);</span> | 
 | <span class="source-line-no">6878</span><span id="line-6878"></span> | 
 | <span class="source-line-no">6879</span><span id="line-6879">          // refresh the store files. This is similar to observing a region open wal marker.</span> | 
 | <span class="source-line-no">6880</span><span id="line-6880">          store.refreshStoreFiles();</span> | 
 | <span class="source-line-no">6881</span><span id="line-6881"></span> | 
 | <span class="source-line-no">6882</span><span id="line-6882">          long storeSeqId = store.getMaxSequenceId().orElse(0L);</span> | 
 | <span class="source-line-no">6883</span><span id="line-6883">          if (storeSeqId < smallestSeqIdInStores) {</span> | 
 | <span class="source-line-no">6884</span><span id="line-6884">            smallestSeqIdInStores = storeSeqId;</span> | 
 | <span class="source-line-no">6885</span><span id="line-6885">          }</span> | 
 | <span class="source-line-no">6886</span><span id="line-6886"></span> | 
 | <span class="source-line-no">6887</span><span id="line-6887">          // see whether we can drop the memstore or the snapshot</span> | 
 | <span class="source-line-no">6888</span><span id="line-6888">          if (storeSeqId > maxSeqIdBefore) {</span> | 
 | <span class="source-line-no">6889</span><span id="line-6889">            if (writestate.flushing) {</span> | 
 | <span class="source-line-no">6890</span><span id="line-6890">              // only drop memstore snapshots if they are smaller than last flush for the store</span> | 
 | <span class="source-line-no">6891</span><span id="line-6891">              if (this.prepareFlushResult.flushOpSeqId <= storeSeqId) {</span> | 
 | <span class="source-line-no">6892</span><span id="line-6892">                StoreFlushContext ctx = this.prepareFlushResult.storeFlushCtxs == null</span> | 
 | <span class="source-line-no">6893</span><span id="line-6893">                  ? null</span> | 
 | <span class="source-line-no">6894</span><span id="line-6894">                  : this.prepareFlushResult.storeFlushCtxs</span> | 
 | <span class="source-line-no">6895</span><span id="line-6895">                    .get(store.getColumnFamilyDescriptor().getName());</span> | 
 | <span class="source-line-no">6896</span><span id="line-6896">                if (ctx != null) {</span> | 
 | <span class="source-line-no">6897</span><span id="line-6897">                  MemStoreSize mss = store.getFlushableSize();</span> | 
 | <span class="source-line-no">6898</span><span id="line-6898">                  ctx.abort();</span> | 
 | <span class="source-line-no">6899</span><span id="line-6899">                  this.decrMemStoreSize(mss);</span> | 
 | <span class="source-line-no">6900</span><span id="line-6900">                  this.prepareFlushResult.storeFlushCtxs</span> | 
 | <span class="source-line-no">6901</span><span id="line-6901">                    .remove(store.getColumnFamilyDescriptor().getName());</span> | 
 | <span class="source-line-no">6902</span><span id="line-6902">                  totalFreedDataSize += mss.getDataSize();</span> | 
 | <span class="source-line-no">6903</span><span id="line-6903">                }</span> | 
 | <span class="source-line-no">6904</span><span id="line-6904">              }</span> | 
 | <span class="source-line-no">6905</span><span id="line-6905">            }</span> | 
 | <span class="source-line-no">6906</span><span id="line-6906"></span> | 
 | <span class="source-line-no">6907</span><span id="line-6907">            map.put(store, storeSeqId);</span> | 
 | <span class="source-line-no">6908</span><span id="line-6908">          }</span> | 
 | <span class="source-line-no">6909</span><span id="line-6909">        }</span> | 
 | <span class="source-line-no">6910</span><span id="line-6910"></span> | 
 | <span class="source-line-no">6911</span><span id="line-6911">        // if all stores ended up dropping their snapshots, we can safely drop the</span> | 
 | <span class="source-line-no">6912</span><span id="line-6912">        // prepareFlushResult</span> | 
 | <span class="source-line-no">6913</span><span id="line-6913">        dropPrepareFlushIfPossible();</span> | 
 | <span class="source-line-no">6914</span><span id="line-6914"></span> | 
 | <span class="source-line-no">6915</span><span id="line-6915">        // advance the mvcc read point so that the new flushed files are visible.</span> | 
 | <span class="source-line-no">6916</span><span id="line-6916">        // either greater than flush seq number or they were already picked up via flush.</span> | 
 | <span class="source-line-no">6917</span><span id="line-6917">        for (HStore s : stores.values()) {</span> | 
 | <span class="source-line-no">6918</span><span id="line-6918">          mvcc.advanceTo(s.getMaxMemStoreTS().orElse(0L));</span> | 
 | <span class="source-line-no">6919</span><span id="line-6919">        }</span> | 
 | <span class="source-line-no">6920</span><span id="line-6920"></span> | 
 | <span class="source-line-no">6921</span><span id="line-6921">        // smallestSeqIdInStores is the seqId that we have a corresponding hfile for. We can safely</span> | 
 | <span class="source-line-no">6922</span><span id="line-6922">        // skip all edits that are to be replayed in the future with that has a smaller seqId</span> | 
 | <span class="source-line-no">6923</span><span id="line-6923">        // than this. We are updating lastReplayedOpenRegionSeqId so that we can skip all edits</span> | 
 | <span class="source-line-no">6924</span><span id="line-6924">        // that we have picked the flush files for</span> | 
 | <span class="source-line-no">6925</span><span id="line-6925">        if (this.lastReplayedOpenRegionSeqId < smallestSeqIdInStores) {</span> | 
 | <span class="source-line-no">6926</span><span id="line-6926">          this.lastReplayedOpenRegionSeqId = smallestSeqIdInStores;</span> | 
 | <span class="source-line-no">6927</span><span id="line-6927">        }</span> | 
 | <span class="source-line-no">6928</span><span id="line-6928">      }</span> | 
 | <span class="source-line-no">6929</span><span id="line-6929">      if (!map.isEmpty()) {</span> | 
 | <span class="source-line-no">6930</span><span id="line-6930">        for (Map.Entry<HStore, Long> entry : map.entrySet()) {</span> | 
 | <span class="source-line-no">6931</span><span id="line-6931">          // Drop the memstore contents if they are now smaller than the latest seen flushed file</span> | 
 | <span class="source-line-no">6932</span><span id="line-6932">          totalFreedDataSize +=</span> | 
 | <span class="source-line-no">6933</span><span id="line-6933">            dropMemStoreContentsForSeqId(entry.getValue(), entry.getKey()).getDataSize();</span> | 
 | <span class="source-line-no">6934</span><span id="line-6934">        }</span> | 
 | <span class="source-line-no">6935</span><span id="line-6935">      }</span> | 
 | <span class="source-line-no">6936</span><span id="line-6936">      // C. Finally notify anyone waiting on memstore to clear:</span> | 
 | <span class="source-line-no">6937</span><span id="line-6937">      // e.g. checkResources().</span> | 
 | <span class="source-line-no">6938</span><span id="line-6938">      synchronized (this) {</span> | 
 | <span class="source-line-no">6939</span><span id="line-6939">        notifyAll(); // FindBugs NN_NAKED_NOTIFY</span> | 
 | <span class="source-line-no">6940</span><span id="line-6940">      }</span> | 
 | <span class="source-line-no">6941</span><span id="line-6941">      return totalFreedDataSize > 0;</span> | 
 | <span class="source-line-no">6942</span><span id="line-6942">    } finally {</span> | 
 | <span class="source-line-no">6943</span><span id="line-6943">      closeRegionOperation();</span> | 
 | <span class="source-line-no">6944</span><span id="line-6944">    }</span> | 
 | <span class="source-line-no">6945</span><span id="line-6945">  }</span> | 
 | <span class="source-line-no">6946</span><span id="line-6946"></span> | 
 | <span class="source-line-no">6947</span><span id="line-6947">  private void logRegionFiles() {</span> | 
 | <span class="source-line-no">6948</span><span id="line-6948">    if (LOG.isTraceEnabled()) {</span> | 
 | <span class="source-line-no">6949</span><span id="line-6949">      LOG.trace(getRegionInfo().getEncodedName() + " : Store files for region: ");</span> | 
 | <span class="source-line-no">6950</span><span id="line-6950">      stores.values().stream().filter(s -> s.getStorefiles() != null)</span> | 
 | <span class="source-line-no">6951</span><span id="line-6951">        .flatMap(s -> s.getStorefiles().stream())</span> | 
 | <span class="source-line-no">6952</span><span id="line-6952">        .forEachOrdered(sf -> LOG.trace(getRegionInfo().getEncodedName() + " : " + sf));</span> | 
 | <span class="source-line-no">6953</span><span id="line-6953">    }</span> | 
 | <span class="source-line-no">6954</span><span id="line-6954">  }</span> | 
 | <span class="source-line-no">6955</span><span id="line-6955"></span> | 
 | <span class="source-line-no">6956</span><span id="line-6956">  /**</span> | 
 | <span class="source-line-no">6957</span><span id="line-6957">   * Checks whether the given regionName is either equal to our region, or that the regionName is</span> | 
 | <span class="source-line-no">6958</span><span id="line-6958">   * the primary region to our corresponding range for the secondary replica.</span> | 
 | <span class="source-line-no">6959</span><span id="line-6959">   */</span> | 
 | <span class="source-line-no">6960</span><span id="line-6960">  private void checkTargetRegion(byte[] encodedRegionName, String exceptionMsg, Object payload)</span> | 
 | <span class="source-line-no">6961</span><span id="line-6961">    throws WrongRegionException {</span> | 
 | <span class="source-line-no">6962</span><span id="line-6962">    if (Bytes.equals(this.getRegionInfo().getEncodedNameAsBytes(), encodedRegionName)) {</span> | 
 | <span class="source-line-no">6963</span><span id="line-6963">      return;</span> | 
 | <span class="source-line-no">6964</span><span id="line-6964">    }</span> | 
 | <span class="source-line-no">6965</span><span id="line-6965"></span> | 
 | <span class="source-line-no">6966</span><span id="line-6966">    if (</span> | 
 | <span class="source-line-no">6967</span><span id="line-6967">      !RegionReplicaUtil.isDefaultReplica(this.getRegionInfo())</span> | 
 | <span class="source-line-no">6968</span><span id="line-6968">        && Bytes.equals(encodedRegionName, this.fs.getRegionInfoForFS().getEncodedNameAsBytes())</span> | 
 | <span class="source-line-no">6969</span><span id="line-6969">    ) {</span> | 
 | <span class="source-line-no">6970</span><span id="line-6970">      return;</span> | 
 | <span class="source-line-no">6971</span><span id="line-6971">    }</span> | 
 | <span class="source-line-no">6972</span><span id="line-6972"></span> | 
 | <span class="source-line-no">6973</span><span id="line-6973">    throw new WrongRegionException(</span> | 
 | <span class="source-line-no">6974</span><span id="line-6974">      exceptionMsg + payload + " targetted for region " + Bytes.toStringBinary(encodedRegionName)</span> | 
 | <span class="source-line-no">6975</span><span id="line-6975">        + " does not match this region: " + this.getRegionInfo());</span> | 
 | <span class="source-line-no">6976</span><span id="line-6976">  }</span> | 
 | <span class="source-line-no">6977</span><span id="line-6977"></span> | 
 | <span class="source-line-no">6978</span><span id="line-6978">  /**</span> | 
 | <span class="source-line-no">6979</span><span id="line-6979">   * Used by tests</span> | 
 | <span class="source-line-no">6980</span><span id="line-6980">   * @param s    Store to add edit too.</span> | 
 | <span class="source-line-no">6981</span><span id="line-6981">   * @param cell Cell to add.</span> | 
 | <span class="source-line-no">6982</span><span id="line-6982">   */</span> | 
 | <span class="source-line-no">6983</span><span id="line-6983">  protected void restoreEdit(HStore s, ExtendedCell cell, MemStoreSizing memstoreAccounting) {</span> | 
 | <span class="source-line-no">6984</span><span id="line-6984">    s.add(cell, memstoreAccounting);</span> | 
 | <span class="source-line-no">6985</span><span id="line-6985">  }</span> | 
 | <span class="source-line-no">6986</span><span id="line-6986"></span> | 
 | <span class="source-line-no">6987</span><span id="line-6987">  /**</span> | 
 | <span class="source-line-no">6988</span><span id="line-6988">   * make sure have been through lease recovery before get file status, so the file length can be</span> | 
 | <span class="source-line-no">6989</span><span id="line-6989">   * trusted.</span> | 
 | <span class="source-line-no">6990</span><span id="line-6990">   * @param p File to check.</span> | 
 | <span class="source-line-no">6991</span><span id="line-6991">   * @return True if file was zero-length (and if so, we'll delete it in here).</span> | 
 | <span class="source-line-no">6992</span><span id="line-6992">   */</span> | 
 | <span class="source-line-no">6993</span><span id="line-6993">  private static boolean isZeroLengthThenDelete(final FileSystem fs, final FileStatus stat,</span> | 
 | <span class="source-line-no">6994</span><span id="line-6994">    final Path p) throws IOException {</span> | 
 | <span class="source-line-no">6995</span><span id="line-6995">    if (stat.getLen() > 0) {</span> | 
 | <span class="source-line-no">6996</span><span id="line-6996">      return false;</span> | 
 | <span class="source-line-no">6997</span><span id="line-6997">    }</span> | 
 | <span class="source-line-no">6998</span><span id="line-6998">    LOG.warn("File " + p + " is zero-length, deleting.");</span> | 
 | <span class="source-line-no">6999</span><span id="line-6999">    fs.delete(p, false);</span> | 
 | <span class="source-line-no">7000</span><span id="line-7000">    return true;</span> | 
 | <span class="source-line-no">7001</span><span id="line-7001">  }</span> | 
 | <span class="source-line-no">7002</span><span id="line-7002"></span> | 
 | <span class="source-line-no">7003</span><span id="line-7003">  protected HStore instantiateHStore(final ColumnFamilyDescriptor family, boolean warmup)</span> | 
 | <span class="source-line-no">7004</span><span id="line-7004">    throws IOException {</span> | 
 | <span class="source-line-no">7005</span><span id="line-7005">    if (family.isMobEnabled()) {</span> | 
 | <span class="source-line-no">7006</span><span id="line-7006">      if (HFile.getFormatVersion(this.conf) < HFile.MIN_FORMAT_VERSION_WITH_TAGS) {</span> | 
 | <span class="source-line-no">7007</span><span id="line-7007">        throw new IOException("A minimum HFile version of " + HFile.MIN_FORMAT_VERSION_WITH_TAGS</span> | 
 | <span class="source-line-no">7008</span><span id="line-7008">          + " is required for MOB feature. Consider setting " + HFile.FORMAT_VERSION_KEY</span> | 
 | <span class="source-line-no">7009</span><span id="line-7009">          + " accordingly.");</span> | 
 | <span class="source-line-no">7010</span><span id="line-7010">      }</span> | 
 | <span class="source-line-no">7011</span><span id="line-7011">      return new HMobStore(this, family, this.conf, warmup);</span> | 
 | <span class="source-line-no">7012</span><span id="line-7012">    }</span> | 
 | <span class="source-line-no">7013</span><span id="line-7013">    return new HStore(this, family, this.conf, warmup);</span> | 
 | <span class="source-line-no">7014</span><span id="line-7014">  }</span> | 
 | <span class="source-line-no">7015</span><span id="line-7015"></span> | 
 | <span class="source-line-no">7016</span><span id="line-7016">  @Override</span> | 
 | <span class="source-line-no">7017</span><span id="line-7017">  public HStore getStore(byte[] column) {</span> | 
 | <span class="source-line-no">7018</span><span id="line-7018">    return this.stores.get(column);</span> | 
 | <span class="source-line-no">7019</span><span id="line-7019">  }</span> | 
 | <span class="source-line-no">7020</span><span id="line-7020"></span> | 
 | <span class="source-line-no">7021</span><span id="line-7021">  /**</span> | 
 | <span class="source-line-no">7022</span><span id="line-7022">   * Return HStore instance. Does not do any copy: as the number of store is limited, we iterate on</span> | 
 | <span class="source-line-no">7023</span><span id="line-7023">   * the list.</span> | 
 | <span class="source-line-no">7024</span><span id="line-7024">   */</span> | 
 | <span class="source-line-no">7025</span><span id="line-7025">  private HStore getStore(Cell cell) {</span> | 
 | <span class="source-line-no">7026</span><span id="line-7026">    return stores.entrySet().stream().filter(e -> CellUtil.matchingFamily(cell, e.getKey()))</span> | 
 | <span class="source-line-no">7027</span><span id="line-7027">      .map(e -> e.getValue()).findFirst().orElse(null);</span> | 
 | <span class="source-line-no">7028</span><span id="line-7028">  }</span> | 
 | <span class="source-line-no">7029</span><span id="line-7029"></span> | 
 | <span class="source-line-no">7030</span><span id="line-7030">  @Override</span> | 
 | <span class="source-line-no">7031</span><span id="line-7031">  public List<HStore> getStores() {</span> | 
 | <span class="source-line-no">7032</span><span id="line-7032">    return new ArrayList<>(stores.values());</span> | 
 | <span class="source-line-no">7033</span><span id="line-7033">  }</span> | 
 | <span class="source-line-no">7034</span><span id="line-7034"></span> | 
 | <span class="source-line-no">7035</span><span id="line-7035">  @Override</span> | 
 | <span class="source-line-no">7036</span><span id="line-7036">  public List<String> getStoreFileList(byte[][] columns) throws IllegalArgumentException {</span> | 
 | <span class="source-line-no">7037</span><span id="line-7037">    List<String> storeFileNames = new ArrayList<>();</span> | 
 | <span class="source-line-no">7038</span><span id="line-7038">    synchronized (closeLock) {</span> | 
 | <span class="source-line-no">7039</span><span id="line-7039">      for (byte[] column : columns) {</span> | 
 | <span class="source-line-no">7040</span><span id="line-7040">        HStore store = this.stores.get(column);</span> | 
 | <span class="source-line-no">7041</span><span id="line-7041">        if (store == null) {</span> | 
 | <span class="source-line-no">7042</span><span id="line-7042">          throw new IllegalArgumentException(</span> | 
 | <span class="source-line-no">7043</span><span id="line-7043">            "No column family : " + new String(column, StandardCharsets.UTF_8) + " available");</span> | 
 | <span class="source-line-no">7044</span><span id="line-7044">        }</span> | 
 | <span class="source-line-no">7045</span><span id="line-7045">        Collection<HStoreFile> storeFiles = store.getStorefiles();</span> | 
 | <span class="source-line-no">7046</span><span id="line-7046">        if (storeFiles == null) {</span> | 
 | <span class="source-line-no">7047</span><span id="line-7047">          continue;</span> | 
 | <span class="source-line-no">7048</span><span id="line-7048">        }</span> | 
 | <span class="source-line-no">7049</span><span id="line-7049">        for (HStoreFile storeFile : storeFiles) {</span> | 
 | <span class="source-line-no">7050</span><span id="line-7050">          storeFileNames.add(storeFile.getPath().toString());</span> | 
 | <span class="source-line-no">7051</span><span id="line-7051">        }</span> | 
 | <span class="source-line-no">7052</span><span id="line-7052"></span> | 
 | <span class="source-line-no">7053</span><span id="line-7053">        logRegionFiles();</span> | 
 | <span class="source-line-no">7054</span><span id="line-7054">      }</span> | 
 | <span class="source-line-no">7055</span><span id="line-7055">    }</span> | 
 | <span class="source-line-no">7056</span><span id="line-7056">    return storeFileNames;</span> | 
 | <span class="source-line-no">7057</span><span id="line-7057">  }</span> | 
 | <span class="source-line-no">7058</span><span id="line-7058"></span> | 
 | <span class="source-line-no">7059</span><span id="line-7059">  //////////////////////////////////////////////////////////////////////////////</span> | 
 | <span class="source-line-no">7060</span><span id="line-7060">  // Support code</span> | 
 | <span class="source-line-no">7061</span><span id="line-7061">  //////////////////////////////////////////////////////////////////////////////</span> | 
 | <span class="source-line-no">7062</span><span id="line-7062"></span> | 
 | <span class="source-line-no">7063</span><span id="line-7063">  /** Make sure this is a valid row for the HRegion */</span> | 
 | <span class="source-line-no">7064</span><span id="line-7064">  void checkRow(byte[] row, String op) throws IOException {</span> | 
 | <span class="source-line-no">7065</span><span id="line-7065">    if (!rowIsInRange(getRegionInfo(), row)) {</span> | 
 | <span class="source-line-no">7066</span><span id="line-7066">      throw new WrongRegionException("Requested row out of range for " + op + " on HRegion " + this</span> | 
 | <span class="source-line-no">7067</span><span id="line-7067">        + ", startKey='" + Bytes.toStringBinary(getRegionInfo().getStartKey()) + "', getEndKey()='"</span> | 
 | <span class="source-line-no">7068</span><span id="line-7068">        + Bytes.toStringBinary(getRegionInfo().getEndKey()) + "', row='" + Bytes.toStringBinary(row)</span> | 
 | <span class="source-line-no">7069</span><span id="line-7069">        + "'");</span> | 
 | <span class="source-line-no">7070</span><span id="line-7070">    }</span> | 
 | <span class="source-line-no">7071</span><span id="line-7071">  }</span> | 
 | <span class="source-line-no">7072</span><span id="line-7072"></span> | 
 | <span class="source-line-no">7073</span><span id="line-7073">  /**</span> | 
 | <span class="source-line-no">7074</span><span id="line-7074">   * Get an exclusive ( write lock ) lock on a given row.</span> | 
 | <span class="source-line-no">7075</span><span id="line-7075">   * @param row Which row to lock.</span> | 
 | <span class="source-line-no">7076</span><span id="line-7076">   * @return A locked RowLock. The lock is exclusive and already aqquired.</span> | 
 | <span class="source-line-no">7077</span><span id="line-7077">   */</span> | 
 | <span class="source-line-no">7078</span><span id="line-7078">  public RowLock getRowLock(byte[] row) throws IOException {</span> | 
 | <span class="source-line-no">7079</span><span id="line-7079">    return getRowLock(row, false);</span> | 
 | <span class="source-line-no">7080</span><span id="line-7080">  }</span> | 
 | <span class="source-line-no">7081</span><span id="line-7081"></span> | 
 | <span class="source-line-no">7082</span><span id="line-7082">  @Override</span> | 
 | <span class="source-line-no">7083</span><span id="line-7083">  public RowLock getRowLock(byte[] row, boolean readLock) throws IOException {</span> | 
 | <span class="source-line-no">7084</span><span id="line-7084">    checkRow(row, "row lock");</span> | 
 | <span class="source-line-no">7085</span><span id="line-7085">    return getRowLock(row, readLock, null);</span> | 
 | <span class="source-line-no">7086</span><span id="line-7086">  }</span> | 
 | <span class="source-line-no">7087</span><span id="line-7087"></span> | 
 | <span class="source-line-no">7088</span><span id="line-7088">  Span createRegionSpan(String name) {</span> | 
 | <span class="source-line-no">7089</span><span id="line-7089">    return TraceUtil.createSpan(name).setAttribute(REGION_NAMES_KEY,</span> | 
 | <span class="source-line-no">7090</span><span id="line-7090">      Collections.singletonList(getRegionInfo().getRegionNameAsString()));</span> | 
 | <span class="source-line-no">7091</span><span id="line-7091">  }</span> | 
 | <span class="source-line-no">7092</span><span id="line-7092"></span> | 
 | <span class="source-line-no">7093</span><span id="line-7093">  // will be override in tests</span> | 
 | <span class="source-line-no">7094</span><span id="line-7094">  protected RowLock getRowLockInternal(byte[] row, boolean readLock, RowLock prevRowLock)</span> | 
 | <span class="source-line-no">7095</span><span id="line-7095">    throws IOException {</span> | 
 | <span class="source-line-no">7096</span><span id="line-7096">    // create an object to use a a key in the row lock map</span> | 
 | <span class="source-line-no">7097</span><span id="line-7097">    HashedBytes rowKey = new HashedBytes(row);</span> | 
 | <span class="source-line-no">7098</span><span id="line-7098"></span> | 
 | <span class="source-line-no">7099</span><span id="line-7099">    RowLockContext rowLockContext = null;</span> | 
 | <span class="source-line-no">7100</span><span id="line-7100">    RowLockImpl result = null;</span> | 
 | <span class="source-line-no">7101</span><span id="line-7101"></span> | 
 | <span class="source-line-no">7102</span><span id="line-7102">    boolean success = false;</span> | 
 | <span class="source-line-no">7103</span><span id="line-7103">    try {</span> | 
 | <span class="source-line-no">7104</span><span id="line-7104">      // Keep trying until we have a lock or error out.</span> | 
 | <span class="source-line-no">7105</span><span id="line-7105">      // TODO: do we need to add a time component here?</span> | 
 | <span class="source-line-no">7106</span><span id="line-7106">      while (result == null) {</span> | 
 | <span class="source-line-no">7107</span><span id="line-7107">        rowLockContext = computeIfAbsent(lockedRows, rowKey, () -> new RowLockContext(rowKey));</span> | 
 | <span class="source-line-no">7108</span><span id="line-7108">        // Now try an get the lock.</span> | 
 | <span class="source-line-no">7109</span><span id="line-7109">        // This can fail as</span> | 
 | <span class="source-line-no">7110</span><span id="line-7110">        if (readLock) {</span> | 
 | <span class="source-line-no">7111</span><span id="line-7111">          // For read lock, if the caller has locked the same row previously, it will not try</span> | 
 | <span class="source-line-no">7112</span><span id="line-7112">          // to acquire the same read lock. It simply returns the previous row lock.</span> | 
 | <span class="source-line-no">7113</span><span id="line-7113">          RowLockImpl prevRowLockImpl = (RowLockImpl) prevRowLock;</span> | 
 | <span class="source-line-no">7114</span><span id="line-7114">          if (</span> | 
 | <span class="source-line-no">7115</span><span id="line-7115">            (prevRowLockImpl != null)</span> | 
 | <span class="source-line-no">7116</span><span id="line-7116">              && (prevRowLockImpl.getLock() == rowLockContext.readWriteLock.readLock())</span> | 
 | <span class="source-line-no">7117</span><span id="line-7117">          ) {</span> | 
 | <span class="source-line-no">7118</span><span id="line-7118">            success = true;</span> | 
 | <span class="source-line-no">7119</span><span id="line-7119">            return prevRowLock;</span> | 
 | <span class="source-line-no">7120</span><span id="line-7120">          }</span> | 
 | <span class="source-line-no">7121</span><span id="line-7121">          result = rowLockContext.newReadLock();</span> | 
 | <span class="source-line-no">7122</span><span id="line-7122">        } else {</span> | 
 | <span class="source-line-no">7123</span><span id="line-7123">          result = rowLockContext.newWriteLock();</span> | 
 | <span class="source-line-no">7124</span><span id="line-7124">        }</span> | 
 | <span class="source-line-no">7125</span><span id="line-7125">      }</span> | 
 | <span class="source-line-no">7126</span><span id="line-7126"></span> | 
 | <span class="source-line-no">7127</span><span id="line-7127">      int timeout = rowLockWaitDuration;</span> | 
 | <span class="source-line-no">7128</span><span id="line-7128">      boolean reachDeadlineFirst = false;</span> | 
 | <span class="source-line-no">7129</span><span id="line-7129">      Optional<RpcCall> call = RpcServer.getCurrentCall();</span> | 
 | <span class="source-line-no">7130</span><span id="line-7130">      if (call.isPresent()) {</span> | 
 | <span class="source-line-no">7131</span><span id="line-7131">        long deadline = call.get().getDeadline();</span> | 
 | <span class="source-line-no">7132</span><span id="line-7132">        if (deadline < Long.MAX_VALUE) {</span> | 
 | <span class="source-line-no">7133</span><span id="line-7133">          int timeToDeadline = (int) (deadline - EnvironmentEdgeManager.currentTime());</span> | 
 | <span class="source-line-no">7134</span><span id="line-7134">          if (timeToDeadline <= this.rowLockWaitDuration) {</span> | 
 | <span class="source-line-no">7135</span><span id="line-7135">            reachDeadlineFirst = true;</span> | 
 | <span class="source-line-no">7136</span><span id="line-7136">            timeout = timeToDeadline;</span> | 
 | <span class="source-line-no">7137</span><span id="line-7137">          }</span> | 
 | <span class="source-line-no">7138</span><span id="line-7138">        }</span> | 
 | <span class="source-line-no">7139</span><span id="line-7139">      }</span> | 
 | <span class="source-line-no">7140</span><span id="line-7140"></span> | 
 | <span class="source-line-no">7141</span><span id="line-7141">      if (timeout <= 0 || !result.getLock().tryLock(timeout, TimeUnit.MILLISECONDS)) {</span> | 
 | <span class="source-line-no">7142</span><span id="line-7142">        String message = "Timed out waiting for lock for row: " + rowKey + " in region "</span> | 
 | <span class="source-line-no">7143</span><span id="line-7143">          + getRegionInfo().getEncodedName();</span> | 
 | <span class="source-line-no">7144</span><span id="line-7144">        if (reachDeadlineFirst) {</span> | 
 | <span class="source-line-no">7145</span><span id="line-7145">          throw new TimeoutIOException(message);</span> | 
 | <span class="source-line-no">7146</span><span id="line-7146">        } else {</span> | 
 | <span class="source-line-no">7147</span><span id="line-7147">          // If timeToDeadline is larger than rowLockWaitDuration, we can not drop the request.</span> | 
 | <span class="source-line-no">7148</span><span id="line-7148">          throw new IOException(message);</span> | 
 | <span class="source-line-no">7149</span><span id="line-7149">        }</span> | 
 | <span class="source-line-no">7150</span><span id="line-7150">      }</span> | 
 | <span class="source-line-no">7151</span><span id="line-7151">      rowLockContext.setThreadName(Thread.currentThread().getName());</span> | 
 | <span class="source-line-no">7152</span><span id="line-7152">      success = true;</span> | 
 | <span class="source-line-no">7153</span><span id="line-7153">      return result;</span> | 
 | <span class="source-line-no">7154</span><span id="line-7154">    } catch (InterruptedException ie) {</span> | 
 | <span class="source-line-no">7155</span><span id="line-7155">      if (LOG.isDebugEnabled()) {</span> | 
 | <span class="source-line-no">7156</span><span id="line-7156">        LOG.debug("Thread interrupted waiting for lock on row: {}, in region {}", rowKey,</span> | 
 | <span class="source-line-no">7157</span><span id="line-7157">          getRegionInfo().getRegionNameAsString());</span> | 
 | <span class="source-line-no">7158</span><span id="line-7158">      }</span> | 
 | <span class="source-line-no">7159</span><span id="line-7159">      throw throwOnInterrupt(ie);</span> | 
 | <span class="source-line-no">7160</span><span id="line-7160">    } catch (Error error) {</span> | 
 | <span class="source-line-no">7161</span><span id="line-7161">      // The maximum lock count for read lock is 64K (hardcoded), when this maximum count</span> | 
 | <span class="source-line-no">7162</span><span id="line-7162">      // is reached, it will throw out an Error. This Error needs to be caught so it can</span> | 
 | <span class="source-line-no">7163</span><span id="line-7163">      // go ahead to process the minibatch with lock acquired.</span> | 
 | <span class="source-line-no">7164</span><span id="line-7164">      LOG.warn("Error to get row lock for {}, in region {}, cause: {}", Bytes.toStringBinary(row),</span> | 
 | <span class="source-line-no">7165</span><span id="line-7165">        getRegionInfo().getRegionNameAsString(), error);</span> | 
 | <span class="source-line-no">7166</span><span id="line-7166">      IOException ioe = new IOException(error);</span> | 
 | <span class="source-line-no">7167</span><span id="line-7167">      throw ioe;</span> | 
 | <span class="source-line-no">7168</span><span id="line-7168">    } finally {</span> | 
 | <span class="source-line-no">7169</span><span id="line-7169">      // Clean up the counts just in case this was the thing keeping the context alive.</span> | 
 | <span class="source-line-no">7170</span><span id="line-7170">      if (!success && rowLockContext != null) {</span> | 
 | <span class="source-line-no">7171</span><span id="line-7171">        rowLockContext.cleanUp();</span> | 
 | <span class="source-line-no">7172</span><span id="line-7172">      }</span> | 
 | <span class="source-line-no">7173</span><span id="line-7173">    }</span> | 
 | <span class="source-line-no">7174</span><span id="line-7174">  }</span> | 
 | <span class="source-line-no">7175</span><span id="line-7175"></span> | 
 | <span class="source-line-no">7176</span><span id="line-7176">  private RowLock getRowLock(byte[] row, boolean readLock, final RowLock prevRowLock)</span> | 
 | <span class="source-line-no">7177</span><span id="line-7177">    throws IOException {</span> | 
 | <span class="source-line-no">7178</span><span id="line-7178">    return TraceUtil.trace(() -> getRowLockInternal(row, readLock, prevRowLock),</span> | 
 | <span class="source-line-no">7179</span><span id="line-7179">      () -> createRegionSpan("Region.getRowLock").setAttribute(ROW_LOCK_READ_LOCK_KEY, readLock));</span> | 
 | <span class="source-line-no">7180</span><span id="line-7180">  }</span> | 
 | <span class="source-line-no">7181</span><span id="line-7181"></span> | 
 | <span class="source-line-no">7182</span><span id="line-7182">  private void releaseRowLocks(List<RowLock> rowLocks) {</span> | 
 | <span class="source-line-no">7183</span><span id="line-7183">    if (rowLocks != null) {</span> | 
 | <span class="source-line-no">7184</span><span id="line-7184">      for (RowLock rowLock : rowLocks) {</span> | 
 | <span class="source-line-no">7185</span><span id="line-7185">        rowLock.release();</span> | 
 | <span class="source-line-no">7186</span><span id="line-7186">      }</span> | 
 | <span class="source-line-no">7187</span><span id="line-7187">      rowLocks.clear();</span> | 
 | <span class="source-line-no">7188</span><span id="line-7188">    }</span> | 
 | <span class="source-line-no">7189</span><span id="line-7189">  }</span> | 
 | <span class="source-line-no">7190</span><span id="line-7190"></span> | 
 | <span class="source-line-no">7191</span><span id="line-7191">  public int getReadLockCount() {</span> | 
 | <span class="source-line-no">7192</span><span id="line-7192">    return lock.getReadLockCount();</span> | 
 | <span class="source-line-no">7193</span><span id="line-7193">  }</span> | 
 | <span class="source-line-no">7194</span><span id="line-7194"></span> | 
 | <span class="source-line-no">7195</span><span id="line-7195">  public ConcurrentHashMap<HashedBytes, RowLockContext> getLockedRows() {</span> | 
 | <span class="source-line-no">7196</span><span id="line-7196">    return lockedRows;</span> | 
 | <span class="source-line-no">7197</span><span id="line-7197">  }</span> | 
 | <span class="source-line-no">7198</span><span id="line-7198"></span> | 
 | <span class="source-line-no">7199</span><span id="line-7199">  class RowLockContext {</span> | 
 | <span class="source-line-no">7200</span><span id="line-7200">    private final HashedBytes row;</span> | 
 | <span class="source-line-no">7201</span><span id="line-7201">    final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true);</span> | 
 | <span class="source-line-no">7202</span><span id="line-7202">    final AtomicBoolean usable = new AtomicBoolean(true);</span> | 
 | <span class="source-line-no">7203</span><span id="line-7203">    final AtomicInteger count = new AtomicInteger(0);</span> | 
 | <span class="source-line-no">7204</span><span id="line-7204">    final Object lock = new Object();</span> | 
 | <span class="source-line-no">7205</span><span id="line-7205">    private String threadName;</span> | 
 | <span class="source-line-no">7206</span><span id="line-7206"></span> | 
 | <span class="source-line-no">7207</span><span id="line-7207">    RowLockContext(HashedBytes row) {</span> | 
 | <span class="source-line-no">7208</span><span id="line-7208">      this.row = row;</span> | 
 | <span class="source-line-no">7209</span><span id="line-7209">    }</span> | 
 | <span class="source-line-no">7210</span><span id="line-7210"></span> | 
 | <span class="source-line-no">7211</span><span id="line-7211">    RowLockImpl newWriteLock() {</span> | 
 | <span class="source-line-no">7212</span><span id="line-7212">      Lock l = readWriteLock.writeLock();</span> | 
 | <span class="source-line-no">7213</span><span id="line-7213">      return getRowLock(l);</span> | 
 | <span class="source-line-no">7214</span><span id="line-7214">    }</span> | 
 | <span class="source-line-no">7215</span><span id="line-7215"></span> | 
 | <span class="source-line-no">7216</span><span id="line-7216">    RowLockImpl newReadLock() {</span> | 
 | <span class="source-line-no">7217</span><span id="line-7217">      Lock l = readWriteLock.readLock();</span> | 
 | <span class="source-line-no">7218</span><span id="line-7218">      return getRowLock(l);</span> | 
 | <span class="source-line-no">7219</span><span id="line-7219">    }</span> | 
 | <span class="source-line-no">7220</span><span id="line-7220"></span> | 
 | <span class="source-line-no">7221</span><span id="line-7221">    private RowLockImpl getRowLock(Lock l) {</span> | 
 | <span class="source-line-no">7222</span><span id="line-7222">      count.incrementAndGet();</span> | 
 | <span class="source-line-no">7223</span><span id="line-7223">      synchronized (lock) {</span> | 
 | <span class="source-line-no">7224</span><span id="line-7224">        if (usable.get()) {</span> | 
 | <span class="source-line-no">7225</span><span id="line-7225">          return new RowLockImpl(this, l);</span> | 
 | <span class="source-line-no">7226</span><span id="line-7226">        } else {</span> | 
 | <span class="source-line-no">7227</span><span id="line-7227">          return null;</span> | 
 | <span class="source-line-no">7228</span><span id="line-7228">        }</span> | 
 | <span class="source-line-no">7229</span><span id="line-7229">      }</span> | 
 | <span class="source-line-no">7230</span><span id="line-7230">    }</span> | 
 | <span class="source-line-no">7231</span><span id="line-7231"></span> | 
 | <span class="source-line-no">7232</span><span id="line-7232">    void cleanUp() {</span> | 
 | <span class="source-line-no">7233</span><span id="line-7233">      long c = count.decrementAndGet();</span> | 
 | <span class="source-line-no">7234</span><span id="line-7234">      if (c <= 0) {</span> | 
 | <span class="source-line-no">7235</span><span id="line-7235">        synchronized (lock) {</span> | 
 | <span class="source-line-no">7236</span><span id="line-7236">          if (count.get() <= 0 && usable.get()) { // Don't attempt to remove row if already removed</span> | 
 | <span class="source-line-no">7237</span><span id="line-7237">            usable.set(false);</span> | 
 | <span class="source-line-no">7238</span><span id="line-7238">            RowLockContext removed = lockedRows.remove(row);</span> | 
 | <span class="source-line-no">7239</span><span id="line-7239">            assert removed == this : "we should never remove a different context";</span> | 
 | <span class="source-line-no">7240</span><span id="line-7240">          }</span> | 
 | <span class="source-line-no">7241</span><span id="line-7241">        }</span> | 
 | <span class="source-line-no">7242</span><span id="line-7242">      }</span> | 
 | <span class="source-line-no">7243</span><span id="line-7243">    }</span> | 
 | <span class="source-line-no">7244</span><span id="line-7244"></span> | 
 | <span class="source-line-no">7245</span><span id="line-7245">    public void setThreadName(String threadName) {</span> | 
 | <span class="source-line-no">7246</span><span id="line-7246">      this.threadName = threadName;</span> | 
 | <span class="source-line-no">7247</span><span id="line-7247">    }</span> | 
 | <span class="source-line-no">7248</span><span id="line-7248"></span> | 
 | <span class="source-line-no">7249</span><span id="line-7249">    @Override</span> | 
 | <span class="source-line-no">7250</span><span id="line-7250">    public String toString() {</span> | 
 | <span class="source-line-no">7251</span><span id="line-7251">      return "RowLockContext{" + "row=" + row + ", readWriteLock=" + readWriteLock + ", count="</span> | 
 | <span class="source-line-no">7252</span><span id="line-7252">        + count + ", threadName=" + threadName + '}';</span> | 
 | <span class="source-line-no">7253</span><span id="line-7253">    }</span> | 
 | <span class="source-line-no">7254</span><span id="line-7254">  }</span> | 
 | <span class="source-line-no">7255</span><span id="line-7255"></span> | 
 | <span class="source-line-no">7256</span><span id="line-7256">  /**</span> | 
 | <span class="source-line-no">7257</span><span id="line-7257">   * Class used to represent a lock on a row.</span> | 
 | <span class="source-line-no">7258</span><span id="line-7258">   */</span> | 
 | <span class="source-line-no">7259</span><span id="line-7259">  public static class RowLockImpl implements RowLock {</span> | 
 | <span class="source-line-no">7260</span><span id="line-7260">    private final RowLockContext context;</span> | 
 | <span class="source-line-no">7261</span><span id="line-7261">    private final Lock lock;</span> | 
 | <span class="source-line-no">7262</span><span id="line-7262"></span> | 
 | <span class="source-line-no">7263</span><span id="line-7263">    public RowLockImpl(RowLockContext context, Lock lock) {</span> | 
 | <span class="source-line-no">7264</span><span id="line-7264">      this.context = context;</span> | 
 | <span class="source-line-no">7265</span><span id="line-7265">      this.lock = lock;</span> | 
 | <span class="source-line-no">7266</span><span id="line-7266">    }</span> | 
 | <span class="source-line-no">7267</span><span id="line-7267"></span> | 
 | <span class="source-line-no">7268</span><span id="line-7268">    public Lock getLock() {</span> | 
 | <span class="source-line-no">7269</span><span id="line-7269">      return lock;</span> | 
 | <span class="source-line-no">7270</span><span id="line-7270">    }</span> | 
 | <span class="source-line-no">7271</span><span id="line-7271"></span> | 
 | <span class="source-line-no">7272</span><span id="line-7272">    public RowLockContext getContext() {</span> | 
 | <span class="source-line-no">7273</span><span id="line-7273">      return context;</span> | 
 | <span class="source-line-no">7274</span><span id="line-7274">    }</span> | 
 | <span class="source-line-no">7275</span><span id="line-7275"></span> | 
 | <span class="source-line-no">7276</span><span id="line-7276">    @Override</span> | 
 | <span class="source-line-no">7277</span><span id="line-7277">    public void release() {</span> | 
 | <span class="source-line-no">7278</span><span id="line-7278">      lock.unlock();</span> | 
 | <span class="source-line-no">7279</span><span id="line-7279">      context.cleanUp();</span> | 
 | <span class="source-line-no">7280</span><span id="line-7280">    }</span> | 
 | <span class="source-line-no">7281</span><span id="line-7281"></span> | 
 | <span class="source-line-no">7282</span><span id="line-7282">    @Override</span> | 
 | <span class="source-line-no">7283</span><span id="line-7283">    public String toString() {</span> | 
 | <span class="source-line-no">7284</span><span id="line-7284">      return "RowLockImpl{" + "context=" + context + ", lock=" + lock + '}';</span> | 
 | <span class="source-line-no">7285</span><span id="line-7285">    }</span> | 
 | <span class="source-line-no">7286</span><span id="line-7286">  }</span> | 
 | <span class="source-line-no">7287</span><span id="line-7287"></span> | 
 | <span class="source-line-no">7288</span><span id="line-7288">  /**</span> | 
 | <span class="source-line-no">7289</span><span id="line-7289">   * Determines whether multiple column families are present Precondition: familyPaths is not null</span> | 
 | <span class="source-line-no">7290</span><span id="line-7290">   * @param familyPaths List of (column family, hfilePath)</span> | 
 | <span class="source-line-no">7291</span><span id="line-7291">   */</span> | 
 | <span class="source-line-no">7292</span><span id="line-7292">  private static boolean hasMultipleColumnFamilies(Collection<Pair<byte[], String>> familyPaths) {</span> | 
 | <span class="source-line-no">7293</span><span id="line-7293">    boolean multipleFamilies = false;</span> | 
 | <span class="source-line-no">7294</span><span id="line-7294">    byte[] family = null;</span> | 
 | <span class="source-line-no">7295</span><span id="line-7295">    for (Pair<byte[], String> pair : familyPaths) {</span> | 
 | <span class="source-line-no">7296</span><span id="line-7296">      byte[] fam = pair.getFirst();</span> | 
 | <span class="source-line-no">7297</span><span id="line-7297">      if (family == null) {</span> | 
 | <span class="source-line-no">7298</span><span id="line-7298">        family = fam;</span> | 
 | <span class="source-line-no">7299</span><span id="line-7299">      } else if (!Bytes.equals(family, fam)) {</span> | 
 | <span class="source-line-no">7300</span><span id="line-7300">        multipleFamilies = true;</span> | 
 | <span class="source-line-no">7301</span><span id="line-7301">        break;</span> | 
 | <span class="source-line-no">7302</span><span id="line-7302">      }</span> | 
 | <span class="source-line-no">7303</span><span id="line-7303">    }</span> | 
 | <span class="source-line-no">7304</span><span id="line-7304">    return multipleFamilies;</span> | 
 | <span class="source-line-no">7305</span><span id="line-7305">  }</span> | 
 | <span class="source-line-no">7306</span><span id="line-7306"></span> | 
 | <span class="source-line-no">7307</span><span id="line-7307">  /**</span> | 
 | <span class="source-line-no">7308</span><span id="line-7308">   * Attempts to atomically load a group of hfiles. This is critical for loading rows with multiple</span> | 
 | <span class="source-line-no">7309</span><span id="line-7309">   * column families atomically.</span> | 
 | <span class="source-line-no">7310</span><span id="line-7310">   * @param familyPaths      List of Pair&lt;byte[] column family, String hfilePath&gt;</span> | 
 | <span class="source-line-no">7311</span><span id="line-7311">   * @param bulkLoadListener Internal hooks enabling massaging/preparation of a file about to be</span> | 
 | <span class="source-line-no">7312</span><span id="line-7312">   *                         bulk loaded</span> | 
 | <span class="source-line-no">7313</span><span id="line-7313">   * @return Map from family to List of store file paths if successful, null if failed recoverably</span> | 
 | <span class="source-line-no">7314</span><span id="line-7314">   * @throws IOException if failed unrecoverably.</span> | 
 | <span class="source-line-no">7315</span><span id="line-7315">   */</span> | 
 | <span class="source-line-no">7316</span><span id="line-7316">  public Map<byte[], List<Path>> bulkLoadHFiles(Collection<Pair<byte[], String>> familyPaths,</span> | 
 | <span class="source-line-no">7317</span><span id="line-7317">    boolean assignSeqId, BulkLoadListener bulkLoadListener) throws IOException {</span> | 
 | <span class="source-line-no">7318</span><span id="line-7318">    return bulkLoadHFiles(familyPaths, assignSeqId, bulkLoadListener, false, null, true);</span> | 
 | <span class="source-line-no">7319</span><span id="line-7319">  }</span> | 
 | <span class="source-line-no">7320</span><span id="line-7320"></span> | 
 | <span class="source-line-no">7321</span><span id="line-7321">  /**</span> | 
 | <span class="source-line-no">7322</span><span id="line-7322">   * Listener class to enable callers of bulkLoadHFile() to perform any necessary pre/post</span> | 
 | <span class="source-line-no">7323</span><span id="line-7323">   * processing of a given bulkload call</span> | 
 | <span class="source-line-no">7324</span><span id="line-7324">   */</span> | 
 | <span class="source-line-no">7325</span><span id="line-7325">  public interface BulkLoadListener {</span> | 
 | <span class="source-line-no">7326</span><span id="line-7326">    /**</span> | 
 | <span class="source-line-no">7327</span><span id="line-7327">     * Called before an HFile is actually loaded</span> | 
 | <span class="source-line-no">7328</span><span id="line-7328">     * @param family  family being loaded to</span> | 
 | <span class="source-line-no">7329</span><span id="line-7329">     * @param srcPath path of HFile</span> | 
 | <span class="source-line-no">7330</span><span id="line-7330">     * @return final path to be used for actual loading</span> | 
 | <span class="source-line-no">7331</span><span id="line-7331">     */</span> | 
 | <span class="source-line-no">7332</span><span id="line-7332">    String prepareBulkLoad(byte[] family, String srcPath, boolean copyFile, String customStaging)</span> | 
 | <span class="source-line-no">7333</span><span id="line-7333">      throws IOException;</span> | 
 | <span class="source-line-no">7334</span><span id="line-7334"></span> | 
 | <span class="source-line-no">7335</span><span id="line-7335">    /**</span> | 
 | <span class="source-line-no">7336</span><span id="line-7336">     * Called after a successful HFile load</span> | 
 | <span class="source-line-no">7337</span><span id="line-7337">     * @param family  family being loaded to</span> | 
 | <span class="source-line-no">7338</span><span id="line-7338">     * @param srcPath path of HFile</span> | 
 | <span class="source-line-no">7339</span><span id="line-7339">     */</span> | 
 | <span class="source-line-no">7340</span><span id="line-7340">    void doneBulkLoad(byte[] family, String srcPath) throws IOException;</span> | 
 | <span class="source-line-no">7341</span><span id="line-7341"></span> | 
 | <span class="source-line-no">7342</span><span id="line-7342">    /**</span> | 
 | <span class="source-line-no">7343</span><span id="line-7343">     * Called after a failed HFile load</span> | 
 | <span class="source-line-no">7344</span><span id="line-7344">     * @param family  family being loaded to</span> | 
 | <span class="source-line-no">7345</span><span id="line-7345">     * @param srcPath path of HFile</span> | 
 | <span class="source-line-no">7346</span><span id="line-7346">     */</span> | 
 | <span class="source-line-no">7347</span><span id="line-7347">    void failedBulkLoad(byte[] family, String srcPath) throws IOException;</span> | 
 | <span class="source-line-no">7348</span><span id="line-7348">  }</span> | 
 | <span class="source-line-no">7349</span><span id="line-7349"></span> | 
 | <span class="source-line-no">7350</span><span id="line-7350">  /**</span> | 
 | <span class="source-line-no">7351</span><span id="line-7351">   * Attempts to atomically load a group of hfiles. This is critical for loading rows with multiple</span> | 
 | <span class="source-line-no">7352</span><span id="line-7352">   * column families atomically.</span> | 
 | <span class="source-line-no">7353</span><span id="line-7353">   * @param familyPaths      List of Pair&lt;byte[] column family, String hfilePath&gt;</span> | 
 | <span class="source-line-no">7354</span><span id="line-7354">   * @param bulkLoadListener Internal hooks enabling massaging/preparation of a file about to be</span> | 
 | <span class="source-line-no">7355</span><span id="line-7355">   *                         bulk loaded</span> | 
 | <span class="source-line-no">7356</span><span id="line-7356">   * @param copyFile         always copy hfiles if true</span> | 
 | <span class="source-line-no">7357</span><span id="line-7357">   * @param clusterIds       ids from clusters that had already handled the given bulkload event.</span> | 
 | <span class="source-line-no">7358</span><span id="line-7358">   * @return Map from family to List of store file paths if successful, null if failed recoverably</span> | 
 | <span class="source-line-no">7359</span><span id="line-7359">   * @throws IOException if failed unrecoverably.</span> | 
 | <span class="source-line-no">7360</span><span id="line-7360">   */</span> | 
 | <span class="source-line-no">7361</span><span id="line-7361">  public Map<byte[], List<Path>> bulkLoadHFiles(Collection<Pair<byte[], String>> familyPaths,</span> | 
 | <span class="source-line-no">7362</span><span id="line-7362">    boolean assignSeqId, BulkLoadListener bulkLoadListener, boolean copyFile,</span> | 
 | <span class="source-line-no">7363</span><span id="line-7363">    List<String> clusterIds, boolean replicate) throws IOException {</span> | 
 | <span class="source-line-no">7364</span><span id="line-7364">    long seqId = -1;</span> | 
 | <span class="source-line-no">7365</span><span id="line-7365">    Map<byte[], List<Path>> storeFiles = new TreeMap<>(Bytes.BYTES_COMPARATOR);</span> | 
 | <span class="source-line-no">7366</span><span id="line-7366">    Map<String, Long> storeFilesSizes = new HashMap<>();</span> | 
 | <span class="source-line-no">7367</span><span id="line-7367">    Preconditions.checkNotNull(familyPaths);</span> | 
 | <span class="source-line-no">7368</span><span id="line-7368">    // we need writeLock for multi-family bulk load</span> | 
 | <span class="source-line-no">7369</span><span id="line-7369">    startBulkRegionOperation(hasMultipleColumnFamilies(familyPaths));</span> | 
 | <span class="source-line-no">7370</span><span id="line-7370">    boolean isSuccessful = false;</span> | 
 | <span class="source-line-no">7371</span><span id="line-7371">    try {</span> | 
 | <span class="source-line-no">7372</span><span id="line-7372">      this.writeRequestsCount.increment();</span> | 
 | <span class="source-line-no">7373</span><span id="line-7373"></span> | 
 | <span class="source-line-no">7374</span><span id="line-7374">      // There possibly was a split that happened between when the split keys</span> | 
 | <span class="source-line-no">7375</span><span id="line-7375">      // were gathered and before the HRegion's write lock was taken. We need</span> | 
 | <span class="source-line-no">7376</span><span id="line-7376">      // to validate the HFile region before attempting to bulk load all of them</span> | 
 | <span class="source-line-no">7377</span><span id="line-7377">      IOException ioException = null;</span> | 
 | <span class="source-line-no">7378</span><span id="line-7378">      List<Pair<byte[], String>> failures = new ArrayList<>();</span> | 
 | <span class="source-line-no">7379</span><span id="line-7379">      for (Pair<byte[], String> p : familyPaths) {</span> | 
 | <span class="source-line-no">7380</span><span id="line-7380">        byte[] familyName = p.getFirst();</span> | 
 | <span class="source-line-no">7381</span><span id="line-7381">        String path = p.getSecond();</span> | 
 | <span class="source-line-no">7382</span><span id="line-7382"></span> | 
 | <span class="source-line-no">7383</span><span id="line-7383">        HStore store = getStore(familyName);</span> | 
 | <span class="source-line-no">7384</span><span id="line-7384">        if (store == null) {</span> | 
 | <span class="source-line-no">7385</span><span id="line-7385">          ioException = new org.apache.hadoop.hbase.DoNotRetryIOException(</span> | 
 | <span class="source-line-no">7386</span><span id="line-7386">            "No such column family " + Bytes.toStringBinary(familyName));</span> | 
 | <span class="source-line-no">7387</span><span id="line-7387">        } else {</span> | 
 | <span class="source-line-no">7388</span><span id="line-7388">          try {</span> | 
 | <span class="source-line-no">7389</span><span id="line-7389">            store.assertBulkLoadHFileOk(new Path(path));</span> | 
 | <span class="source-line-no">7390</span><span id="line-7390">          } catch (WrongRegionException wre) {</span> | 
 | <span class="source-line-no">7391</span><span id="line-7391">            // recoverable (file doesn't fit in region)</span> | 
 | <span class="source-line-no">7392</span><span id="line-7392">            failures.add(p);</span> | 
 | <span class="source-line-no">7393</span><span id="line-7393">          } catch (IOException ioe) {</span> | 
 | <span class="source-line-no">7394</span><span id="line-7394">            // unrecoverable (hdfs problem)</span> | 
 | <span class="source-line-no">7395</span><span id="line-7395">            ioException = ioe;</span> | 
 | <span class="source-line-no">7396</span><span id="line-7396">          }</span> | 
 | <span class="source-line-no">7397</span><span id="line-7397">        }</span> | 
 | <span class="source-line-no">7398</span><span id="line-7398"></span> | 
 | <span class="source-line-no">7399</span><span id="line-7399">        // validation failed because of some sort of IO problem.</span> | 
 | <span class="source-line-no">7400</span><span id="line-7400">        if (ioException != null) {</span> | 
 | <span class="source-line-no">7401</span><span id="line-7401">          LOG.error("There was IO error when checking if the bulk load is ok in region {}.", this,</span> | 
 | <span class="source-line-no">7402</span><span id="line-7402">            ioException);</span> | 
 | <span class="source-line-no">7403</span><span id="line-7403">          throw ioException;</span> | 
 | <span class="source-line-no">7404</span><span id="line-7404">        }</span> | 
 | <span class="source-line-no">7405</span><span id="line-7405">      }</span> | 
 | <span class="source-line-no">7406</span><span id="line-7406">      // validation failed, bail out before doing anything permanent.</span> | 
 | <span class="source-line-no">7407</span><span id="line-7407">      if (failures.size() != 0) {</span> | 
 | <span class="source-line-no">7408</span><span id="line-7408">        StringBuilder list = new StringBuilder();</span> | 
 | <span class="source-line-no">7409</span><span id="line-7409">        for (Pair<byte[], String> p : failures) {</span> | 
 | <span class="source-line-no">7410</span><span id="line-7410">          list.append("\n").append(Bytes.toString(p.getFirst())).append(" : ")</span> | 
 | <span class="source-line-no">7411</span><span id="line-7411">            .append(p.getSecond());</span> | 
 | <span class="source-line-no">7412</span><span id="line-7412">        }</span> | 
 | <span class="source-line-no">7413</span><span id="line-7413">        // problem when validating</span> | 
 | <span class="source-line-no">7414</span><span id="line-7414">        LOG.warn("There was a recoverable bulk load failure likely due to a split. These (family,"</span> | 
 | <span class="source-line-no">7415</span><span id="line-7415">          + " HFile) pairs were not loaded: {}, in region {}", list.toString(), this);</span> | 
 | <span class="source-line-no">7416</span><span id="line-7416">        return null;</span> | 
 | <span class="source-line-no">7417</span><span id="line-7417">      }</span> | 
 | <span class="source-line-no">7418</span><span id="line-7418"></span> | 
 | <span class="source-line-no">7419</span><span id="line-7419">      // We need to assign a sequential ID that's in between two memstores in order to preserve</span> | 
 | <span class="source-line-no">7420</span><span id="line-7420">      // the guarantee that all the edits lower than the highest sequential ID from all the</span> | 
 | <span class="source-line-no">7421</span><span id="line-7421">      // HFiles are flushed on disk. See HBASE-10958. The sequence id returned when we flush is</span> | 
 | <span class="source-line-no">7422</span><span id="line-7422">      // guaranteed to be one beyond the file made when we flushed (or if nothing to flush, it is</span> | 
 | <span class="source-line-no">7423</span><span id="line-7423">      // a sequence id that we can be sure is beyond the last hfile written).</span> | 
 | <span class="source-line-no">7424</span><span id="line-7424">      if (assignSeqId) {</span> | 
 | <span class="source-line-no">7425</span><span id="line-7425">        FlushResult fs = flushcache(true, false, FlushLifeCycleTracker.DUMMY);</span> | 
 | <span class="source-line-no">7426</span><span id="line-7426">        if (fs.isFlushSucceeded()) {</span> | 
 | <span class="source-line-no">7427</span><span id="line-7427">          seqId = ((FlushResultImpl) fs).flushSequenceId;</span> | 
 | <span class="source-line-no">7428</span><span id="line-7428">        } else if (fs.getResult() == FlushResult.Result.CANNOT_FLUSH_MEMSTORE_EMPTY) {</span> | 
 | <span class="source-line-no">7429</span><span id="line-7429">          seqId = ((FlushResultImpl) fs).flushSequenceId;</span> | 
 | <span class="source-line-no">7430</span><span id="line-7430">        } else if (fs.getResult() == FlushResult.Result.CANNOT_FLUSH) {</span> | 
 | <span class="source-line-no">7431</span><span id="line-7431">          // CANNOT_FLUSH may mean that a flush is already on-going</span> | 
 | <span class="source-line-no">7432</span><span id="line-7432">          // we need to wait for that flush to complete</span> | 
 | <span class="source-line-no">7433</span><span id="line-7433">          waitForFlushes();</span> | 
 | <span class="source-line-no">7434</span><span id="line-7434">        } else {</span> | 
 | <span class="source-line-no">7435</span><span id="line-7435">          throw new IOException("Could not bulk load with an assigned sequential ID because the "</span> | 
 | <span class="source-line-no">7436</span><span id="line-7436">            + "flush didn't run. Reason for not flushing: " + ((FlushResultImpl) fs).failureReason);</span> | 
 | <span class="source-line-no">7437</span><span id="line-7437">        }</span> | 
 | <span class="source-line-no">7438</span><span id="line-7438">      }</span> | 
 | <span class="source-line-no">7439</span><span id="line-7439"></span> | 
 | <span class="source-line-no">7440</span><span id="line-7440">      Map<byte[], List<Pair<Path, Path>>> familyWithFinalPath =</span> | 
 | <span class="source-line-no">7441</span><span id="line-7441">        new TreeMap<>(Bytes.BYTES_COMPARATOR);</span> | 
 | <span class="source-line-no">7442</span><span id="line-7442">      for (Pair<byte[], String> p : familyPaths) {</span> | 
 | <span class="source-line-no">7443</span><span id="line-7443">        byte[] familyName = p.getFirst();</span> | 
 | <span class="source-line-no">7444</span><span id="line-7444">        String path = p.getSecond();</span> | 
 | <span class="source-line-no">7445</span><span id="line-7445">        HStore store = getStore(familyName);</span> | 
 | <span class="source-line-no">7446</span><span id="line-7446">        if (!familyWithFinalPath.containsKey(familyName)) {</span> | 
 | <span class="source-line-no">7447</span><span id="line-7447">          familyWithFinalPath.put(familyName, new ArrayList<>());</span> | 
 | <span class="source-line-no">7448</span><span id="line-7448">        }</span> | 
 | <span class="source-line-no">7449</span><span id="line-7449">        List<Pair<Path, Path>> lst = familyWithFinalPath.get(familyName);</span> | 
 | <span class="source-line-no">7450</span><span id="line-7450">        String finalPath = path;</span> | 
 | <span class="source-line-no">7451</span><span id="line-7451">        try {</span> | 
 | <span class="source-line-no">7452</span><span id="line-7452">          boolean reqTmp = store.storeEngine.requireWritingToTmpDirFirst();</span> | 
 | <span class="source-line-no">7453</span><span id="line-7453">          if (bulkLoadListener != null) {</span> | 
 | <span class="source-line-no">7454</span><span id="line-7454">            finalPath = bulkLoadListener.prepareBulkLoad(familyName, path, copyFile,</span> | 
 | <span class="source-line-no">7455</span><span id="line-7455">              reqTmp ? null : fs.getRegionDir().toString());</span> | 
 | <span class="source-line-no">7456</span><span id="line-7456">          }</span> | 
 | <span class="source-line-no">7457</span><span id="line-7457">          Pair<Path, Path> pair = null;</span> | 
 | <span class="source-line-no">7458</span><span id="line-7458">          if (reqTmp || !StoreFileInfo.isHFile(finalPath)) {</span> | 
 | <span class="source-line-no">7459</span><span id="line-7459">            pair = store.preBulkLoadHFile(finalPath, seqId);</span> | 
 | <span class="source-line-no">7460</span><span id="line-7460">          } else {</span> | 
 | <span class="source-line-no">7461</span><span id="line-7461">            Path livePath = new Path(finalPath);</span> | 
 | <span class="source-line-no">7462</span><span id="line-7462">            pair = new Pair<>(livePath, livePath);</span> | 
 | <span class="source-line-no">7463</span><span id="line-7463">          }</span> | 
 | <span class="source-line-no">7464</span><span id="line-7464">          lst.add(pair);</span> | 
 | <span class="source-line-no">7465</span><span id="line-7465">        } catch (IOException ioe) {</span> | 
 | <span class="source-line-no">7466</span><span id="line-7466">          // A failure here can cause an atomicity violation that we currently</span> | 
 | <span class="source-line-no">7467</span><span id="line-7467">          // cannot recover from since it is likely a failed HDFS operation.</span> | 
 | <span class="source-line-no">7468</span><span id="line-7468"></span> | 
 | <span class="source-line-no">7469</span><span id="line-7469">          LOG.error("There was a partial failure due to IO when attempting to" + " load "</span> | 
 | <span class="source-line-no">7470</span><span id="line-7470">            + Bytes.toString(p.getFirst()) + " : " + p.getSecond(), ioe);</span> | 
 | <span class="source-line-no">7471</span><span id="line-7471">          if (bulkLoadListener != null) {</span> | 
 | <span class="source-line-no">7472</span><span id="line-7472">            try {</span> | 
 | <span class="source-line-no">7473</span><span id="line-7473">              bulkLoadListener.failedBulkLoad(familyName, finalPath);</span> | 
 | <span class="source-line-no">7474</span><span id="line-7474">            } catch (Exception ex) {</span> | 
 | <span class="source-line-no">7475</span><span id="line-7475">              LOG.error("Error while calling failedBulkLoad for family "</span> | 
 | <span class="source-line-no">7476</span><span id="line-7476">                + Bytes.toString(familyName) + " with path " + path, ex);</span> | 
 | <span class="source-line-no">7477</span><span id="line-7477">            }</span> | 
 | <span class="source-line-no">7478</span><span id="line-7478">          }</span> | 
 | <span class="source-line-no">7479</span><span id="line-7479">          throw ioe;</span> | 
 | <span class="source-line-no">7480</span><span id="line-7480">        }</span> | 
 | <span class="source-line-no">7481</span><span id="line-7481">      }</span> | 
 | <span class="source-line-no">7482</span><span id="line-7482"></span> | 
 | <span class="source-line-no">7483</span><span id="line-7483">      if (this.getCoprocessorHost() != null) {</span> | 
 | <span class="source-line-no">7484</span><span id="line-7484">        for (Map.Entry<byte[], List<Pair<Path, Path>>> entry : familyWithFinalPath.entrySet()) {</span> | 
 | <span class="source-line-no">7485</span><span id="line-7485">          this.getCoprocessorHost().preCommitStoreFile(entry.getKey(), entry.getValue());</span> | 
 | <span class="source-line-no">7486</span><span id="line-7486">        }</span> | 
 | <span class="source-line-no">7487</span><span id="line-7487">      }</span> | 
 | <span class="source-line-no">7488</span><span id="line-7488">      for (Map.Entry<byte[], List<Pair<Path, Path>>> entry : familyWithFinalPath.entrySet()) {</span> | 
 | <span class="source-line-no">7489</span><span id="line-7489">        byte[] familyName = entry.getKey();</span> | 
 | <span class="source-line-no">7490</span><span id="line-7490">        for (Pair<Path, Path> p : entry.getValue()) {</span> | 
 | <span class="source-line-no">7491</span><span id="line-7491">          String path = p.getFirst().toString();</span> | 
 | <span class="source-line-no">7492</span><span id="line-7492">          Path commitedStoreFile = p.getSecond();</span> | 
 | <span class="source-line-no">7493</span><span id="line-7493">          HStore store = getStore(familyName);</span> | 
 | <span class="source-line-no">7494</span><span id="line-7494">          try {</span> | 
 | <span class="source-line-no">7495</span><span id="line-7495">            store.bulkLoadHFile(familyName, path, commitedStoreFile);</span> | 
 | <span class="source-line-no">7496</span><span id="line-7496">            // Note the size of the store file</span> | 
 | <span class="source-line-no">7497</span><span id="line-7497">            try {</span> | 
 | <span class="source-line-no">7498</span><span id="line-7498">              FileSystem fs = commitedStoreFile.getFileSystem(baseConf);</span> | 
 | <span class="source-line-no">7499</span><span id="line-7499">              storeFilesSizes.put(commitedStoreFile.getName(),</span> | 
 | <span class="source-line-no">7500</span><span id="line-7500">                fs.getFileStatus(commitedStoreFile).getLen());</span> | 
 | <span class="source-line-no">7501</span><span id="line-7501">            } catch (IOException e) {</span> | 
 | <span class="source-line-no">7502</span><span id="line-7502">              LOG.warn("Failed to find the size of hfile " + commitedStoreFile, e);</span> | 
 | <span class="source-line-no">7503</span><span id="line-7503">              storeFilesSizes.put(commitedStoreFile.getName(), 0L);</span> | 
 | <span class="source-line-no">7504</span><span id="line-7504">            }</span> | 
 | <span class="source-line-no">7505</span><span id="line-7505"></span> | 
 | <span class="source-line-no">7506</span><span id="line-7506">            if (storeFiles.containsKey(familyName)) {</span> | 
 | <span class="source-line-no">7507</span><span id="line-7507">              storeFiles.get(familyName).add(commitedStoreFile);</span> | 
 | <span class="source-line-no">7508</span><span id="line-7508">            } else {</span> | 
 | <span class="source-line-no">7509</span><span id="line-7509">              List<Path> storeFileNames = new ArrayList<>();</span> | 
 | <span class="source-line-no">7510</span><span id="line-7510">              storeFileNames.add(commitedStoreFile);</span> | 
 | <span class="source-line-no">7511</span><span id="line-7511">              storeFiles.put(familyName, storeFileNames);</span> | 
 | <span class="source-line-no">7512</span><span id="line-7512">            }</span> | 
 | <span class="source-line-no">7513</span><span id="line-7513">            if (bulkLoadListener != null) {</span> | 
 | <span class="source-line-no">7514</span><span id="line-7514">              bulkLoadListener.doneBulkLoad(familyName, path);</span> | 
 | <span class="source-line-no">7515</span><span id="line-7515">            }</span> | 
 | <span class="source-line-no">7516</span><span id="line-7516">          } catch (IOException ioe) {</span> | 
 | <span class="source-line-no">7517</span><span id="line-7517">            // A failure here can cause an atomicity violation that we currently</span> | 
 | <span class="source-line-no">7518</span><span id="line-7518">            // cannot recover from since it is likely a failed HDFS operation.</span> | 
 | <span class="source-line-no">7519</span><span id="line-7519"></span> | 
 | <span class="source-line-no">7520</span><span id="line-7520">            // TODO Need a better story for reverting partial failures due to HDFS.</span> | 
 | <span class="source-line-no">7521</span><span id="line-7521">            LOG.error("There was a partial failure due to IO when attempting to" + " load "</span> | 
 | <span class="source-line-no">7522</span><span id="line-7522">              + Bytes.toString(familyName) + " : " + p.getSecond(), ioe);</span> | 
 | <span class="source-line-no">7523</span><span id="line-7523">            if (bulkLoadListener != null) {</span> | 
 | <span class="source-line-no">7524</span><span id="line-7524">              try {</span> | 
 | <span class="source-line-no">7525</span><span id="line-7525">                bulkLoadListener.failedBulkLoad(familyName, path);</span> | 
 | <span class="source-line-no">7526</span><span id="line-7526">              } catch (Exception ex) {</span> | 
 | <span class="source-line-no">7527</span><span id="line-7527">                LOG.error("Error while calling failedBulkLoad for family "</span> | 
 | <span class="source-line-no">7528</span><span id="line-7528">                  + Bytes.toString(familyName) + " with path " + path, ex);</span> | 
 | <span class="source-line-no">7529</span><span id="line-7529">              }</span> | 
 | <span class="source-line-no">7530</span><span id="line-7530">            }</span> | 
 | <span class="source-line-no">7531</span><span id="line-7531">            throw ioe;</span> | 
 | <span class="source-line-no">7532</span><span id="line-7532">          }</span> | 
 | <span class="source-line-no">7533</span><span id="line-7533">        }</span> | 
 | <span class="source-line-no">7534</span><span id="line-7534">      }</span> | 
 | <span class="source-line-no">7535</span><span id="line-7535"></span> | 
 | <span class="source-line-no">7536</span><span id="line-7536">      isSuccessful = true;</span> | 
 | <span class="source-line-no">7537</span><span id="line-7537">      if (conf.getBoolean(COMPACTION_AFTER_BULKLOAD_ENABLE, false)) {</span> | 
 | <span class="source-line-no">7538</span><span id="line-7538">        // request compaction</span> | 
 | <span class="source-line-no">7539</span><span id="line-7539">        familyWithFinalPath.keySet().forEach(family -> {</span> | 
 | <span class="source-line-no">7540</span><span id="line-7540">          HStore store = getStore(family);</span> | 
 | <span class="source-line-no">7541</span><span id="line-7541">          try {</span> | 
 | <span class="source-line-no">7542</span><span id="line-7542">            if (this.rsServices != null && store.needsCompaction()) {</span> | 
 | <span class="source-line-no">7543</span><span id="line-7543">              this.rsServices.getCompactionRequestor().requestSystemCompaction(this, store,</span> | 
 | <span class="source-line-no">7544</span><span id="line-7544">                "bulkload hfiles request compaction", true);</span> | 
 | <span class="source-line-no">7545</span><span id="line-7545">              LOG.info("Request compaction for region {} family {} after bulk load",</span> | 
 | <span class="source-line-no">7546</span><span id="line-7546">                this.getRegionInfo().getEncodedName(), store.getColumnFamilyName());</span> | 
 | <span class="source-line-no">7547</span><span id="line-7547">            }</span> | 
 | <span class="source-line-no">7548</span><span id="line-7548">          } catch (IOException e) {</span> | 
 | <span class="source-line-no">7549</span><span id="line-7549">            LOG.error("bulkload hfiles request compaction error ", e);</span> | 
 | <span class="source-line-no">7550</span><span id="line-7550">          }</span> | 
 | <span class="source-line-no">7551</span><span id="line-7551">        });</span> | 
 | <span class="source-line-no">7552</span><span id="line-7552">      }</span> | 
 | <span class="source-line-no">7553</span><span id="line-7553">    } finally {</span> | 
 | <span class="source-line-no">7554</span><span id="line-7554">      if (wal != null && !storeFiles.isEmpty()) {</span> | 
 | <span class="source-line-no">7555</span><span id="line-7555">        // Write a bulk load event for hfiles that are loaded</span> | 
 | <span class="source-line-no">7556</span><span id="line-7556">        try {</span> | 
 | <span class="source-line-no">7557</span><span id="line-7557">          WALProtos.BulkLoadDescriptor loadDescriptor =</span> | 
 | <span class="source-line-no">7558</span><span id="line-7558">            ProtobufUtil.toBulkLoadDescriptor(this.getRegionInfo().getTable(),</span> | 
 | <span class="source-line-no">7559</span><span id="line-7559">              UnsafeByteOperations.unsafeWrap(this.getRegionInfo().getEncodedNameAsBytes()),</span> | 
 | <span class="source-line-no">7560</span><span id="line-7560">              storeFiles, storeFilesSizes, seqId, clusterIds, replicate);</span> | 
 | <span class="source-line-no">7561</span><span id="line-7561">          WALUtil.writeBulkLoadMarkerAndSync(this.wal, this.getReplicationScope(), getRegionInfo(),</span> | 
 | <span class="source-line-no">7562</span><span id="line-7562">            loadDescriptor, mvcc, regionReplicationSink.orElse(null));</span> | 
 | <span class="source-line-no">7563</span><span id="line-7563">        } catch (IOException ioe) {</span> | 
 | <span class="source-line-no">7564</span><span id="line-7564">          if (this.rsServices != null) {</span> | 
 | <span class="source-line-no">7565</span><span id="line-7565">            // Have to abort region server because some hfiles has been loaded but we can't write</span> | 
 | <span class="source-line-no">7566</span><span id="line-7566">            // the event into WAL</span> | 
 | <span class="source-line-no">7567</span><span id="line-7567">            isSuccessful = false;</span> | 
 | <span class="source-line-no">7568</span><span id="line-7568">            this.rsServices.abort("Failed to write bulk load event into WAL.", ioe);</span> | 
 | <span class="source-line-no">7569</span><span id="line-7569">          }</span> | 
 | <span class="source-line-no">7570</span><span id="line-7570">        }</span> | 
 | <span class="source-line-no">7571</span><span id="line-7571">      }</span> | 
 | <span class="source-line-no">7572</span><span id="line-7572"></span> | 
 | <span class="source-line-no">7573</span><span id="line-7573">      closeBulkRegionOperation();</span> | 
 | <span class="source-line-no">7574</span><span id="line-7574">    }</span> | 
 | <span class="source-line-no">7575</span><span id="line-7575">    return isSuccessful ? storeFiles : null;</span> | 
 | <span class="source-line-no">7576</span><span id="line-7576">  }</span> | 
 | <span class="source-line-no">7577</span><span id="line-7577"></span> | 
 | <span class="source-line-no">7578</span><span id="line-7578">  @Override</span> | 
 | <span class="source-line-no">7579</span><span id="line-7579">  public boolean equals(Object o) {</span> | 
 | <span class="source-line-no">7580</span><span id="line-7580">    return o instanceof HRegion && Bytes.equals(getRegionInfo().getRegionName(),</span> | 
 | <span class="source-line-no">7581</span><span id="line-7581">      ((HRegion) o).getRegionInfo().getRegionName());</span> | 
 | <span class="source-line-no">7582</span><span id="line-7582">  }</span> | 
 | <span class="source-line-no">7583</span><span id="line-7583"></span> | 
 | <span class="source-line-no">7584</span><span id="line-7584">  @Override</span> | 
 | <span class="source-line-no">7585</span><span id="line-7585">  public int hashCode() {</span> | 
 | <span class="source-line-no">7586</span><span id="line-7586">    return Bytes.hashCode(getRegionInfo().getRegionName());</span> | 
 | <span class="source-line-no">7587</span><span id="line-7587">  }</span> | 
 | <span class="source-line-no">7588</span><span id="line-7588"></span> | 
 | <span class="source-line-no">7589</span><span id="line-7589">  @Override</span> | 
 | <span class="source-line-no">7590</span><span id="line-7590">  public String toString() {</span> | 
 | <span class="source-line-no">7591</span><span id="line-7591">    return getRegionInfo().getRegionNameAsString();</span> | 
 | <span class="source-line-no">7592</span><span id="line-7592">  }</span> | 
 | <span class="source-line-no">7593</span><span id="line-7593"></span> | 
 | <span class="source-line-no">7594</span><span id="line-7594">  // Utility methods</span> | 
 | <span class="source-line-no">7595</span><span id="line-7595">  /**</span> | 
 | <span class="source-line-no">7596</span><span id="line-7596">   * A utility method to create new instances of HRegion based on the {@link HConstants#REGION_IMPL}</span> | 
 | <span class="source-line-no">7597</span><span id="line-7597">   * configuration property.</span> | 
 | <span class="source-line-no">7598</span><span id="line-7598">   * @param tableDir   qualified path of directory where region should be located, usually the table</span> | 
 | <span class="source-line-no">7599</span><span id="line-7599">   *                   directory.</span> | 
 | <span class="source-line-no">7600</span><span id="line-7600">   * @param wal        The WAL is the outbound log for any updates to the HRegion The wal file is a</span> | 
 | <span class="source-line-no">7601</span><span id="line-7601">   *                   logfile from the previous execution that's custom-computed for this HRegion.</span> | 
 | <span class="source-line-no">7602</span><span id="line-7602">   *                   The HRegionServer computes and sorts the appropriate wal info for this</span> | 
 | <span class="source-line-no">7603</span><span id="line-7603">   *                   HRegion. If there is a previous file (implying that the HRegion has been</span> | 
 | <span class="source-line-no">7604</span><span id="line-7604">   *                   written-to before), then read it from the supplied path.</span> | 
 | <span class="source-line-no">7605</span><span id="line-7605">   * @param fs         is the filesystem.</span> | 
 | <span class="source-line-no">7606</span><span id="line-7606">   * @param conf       is global configuration settings.</span> | 
 | <span class="source-line-no">7607</span><span id="line-7607">   * @param regionInfo - RegionInfo that describes the region is new), then read them from the</span> | 
 | <span class="source-line-no">7608</span><span id="line-7608">   *                   supplied path.</span> | 
 | <span class="source-line-no">7609</span><span id="line-7609">   * @param htd        the table descriptor</span> | 
 | <span class="source-line-no">7610</span><span id="line-7610">   * @return the new instance</span> | 
 | <span class="source-line-no">7611</span><span id="line-7611">   */</span> | 
 | <span class="source-line-no">7612</span><span id="line-7612">  public static HRegion newHRegion(Path tableDir, WAL wal, FileSystem fs, Configuration conf,</span> | 
 | <span class="source-line-no">7613</span><span id="line-7613">    RegionInfo regionInfo, final TableDescriptor htd, RegionServerServices rsServices) {</span> | 
 | <span class="source-line-no">7614</span><span id="line-7614">    try {</span> | 
 | <span class="source-line-no">7615</span><span id="line-7615">      @SuppressWarnings("unchecked")</span> | 
 | <span class="source-line-no">7616</span><span id="line-7616">      Class<? extends HRegion> regionClass =</span> | 
 | <span class="source-line-no">7617</span><span id="line-7617">        (Class<? extends HRegion>) conf.getClass(HConstants.REGION_IMPL, HRegion.class);</span> | 
 | <span class="source-line-no">7618</span><span id="line-7618"></span> | 
 | <span class="source-line-no">7619</span><span id="line-7619">      Constructor<? extends HRegion> c =</span> | 
 | <span class="source-line-no">7620</span><span id="line-7620">        regionClass.getConstructor(Path.class, WAL.class, FileSystem.class, Configuration.class,</span> | 
 | <span class="source-line-no">7621</span><span id="line-7621">          RegionInfo.class, TableDescriptor.class, RegionServerServices.class);</span> | 
 | <span class="source-line-no">7622</span><span id="line-7622"></span> | 
 | <span class="source-line-no">7623</span><span id="line-7623">      return c.newInstance(tableDir, wal, fs, conf, regionInfo, htd, rsServices);</span> | 
 | <span class="source-line-no">7624</span><span id="line-7624">    } catch (Throwable e) {</span> | 
 | <span class="source-line-no">7625</span><span id="line-7625">      // todo: what should I throw here?</span> | 
 | <span class="source-line-no">7626</span><span id="line-7626">      throw new IllegalStateException("Could not instantiate a region instance.", e);</span> | 
 | <span class="source-line-no">7627</span><span id="line-7627">    }</span> | 
 | <span class="source-line-no">7628</span><span id="line-7628">  }</span> | 
 | <span class="source-line-no">7629</span><span id="line-7629"></span> | 
 | <span class="source-line-no">7630</span><span id="line-7630">  /**</span> | 
 | <span class="source-line-no">7631</span><span id="line-7631">   * Convenience method creating new HRegions. Used by createTable.</span> | 
 | <span class="source-line-no">7632</span><span id="line-7632">   * @param info       Info for region to create.</span> | 
 | <span class="source-line-no">7633</span><span id="line-7633">   * @param rootDir    Root directory for HBase instance</span> | 
 | <span class="source-line-no">7634</span><span id="line-7634">   * @param wal        shared WAL</span> | 
 | <span class="source-line-no">7635</span><span id="line-7635">   * @param initialize - true to initialize the region</span> | 
 | <span class="source-line-no">7636</span><span id="line-7636">   * @return new HRegion</span> | 
 | <span class="source-line-no">7637</span><span id="line-7637">   */</span> | 
 | <span class="source-line-no">7638</span><span id="line-7638">  public static HRegion createHRegion(final RegionInfo info, final Path rootDir,</span> | 
 | <span class="source-line-no">7639</span><span id="line-7639">    final Configuration conf, final TableDescriptor hTableDescriptor, final WAL wal,</span> | 
 | <span class="source-line-no">7640</span><span id="line-7640">    final boolean initialize) throws IOException {</span> | 
 | <span class="source-line-no">7641</span><span id="line-7641">    return createHRegion(info, rootDir, conf, hTableDescriptor, wal, initialize, null);</span> | 
 | <span class="source-line-no">7642</span><span id="line-7642">  }</span> | 
 | <span class="source-line-no">7643</span><span id="line-7643"></span> | 
 | <span class="source-line-no">7644</span><span id="line-7644">  /**</span> | 
 | <span class="source-line-no">7645</span><span id="line-7645">   * Convenience method creating new HRegions. Used by createTable.</span> | 
 | <span class="source-line-no">7646</span><span id="line-7646">   * @param info          Info for region to create.</span> | 
 | <span class="source-line-no">7647</span><span id="line-7647">   * @param rootDir       Root directory for HBase instance</span> | 
 | <span class="source-line-no">7648</span><span id="line-7648">   * @param wal           shared WAL</span> | 
 | <span class="source-line-no">7649</span><span id="line-7649">   * @param initialize    - true to initialize the region</span> | 
 | <span class="source-line-no">7650</span><span id="line-7650">   * @param rsRpcServices An interface we can request flushes against.</span> | 
 | <span class="source-line-no">7651</span><span id="line-7651">   * @return new HRegion</span> | 
 | <span class="source-line-no">7652</span><span id="line-7652">   */</span> | 
 | <span class="source-line-no">7653</span><span id="line-7653">  public static HRegion createHRegion(final RegionInfo info, final Path rootDir,</span> | 
 | <span class="source-line-no">7654</span><span id="line-7654">    final Configuration conf, final TableDescriptor hTableDescriptor, final WAL wal,</span> | 
 | <span class="source-line-no">7655</span><span id="line-7655">    final boolean initialize, RegionServerServices rsRpcServices) throws IOException {</span> | 
 | <span class="source-line-no">7656</span><span id="line-7656">    LOG.info("creating " + info + ", tableDescriptor="</span> | 
 | <span class="source-line-no">7657</span><span id="line-7657">      + (hTableDescriptor == null ? "null" : hTableDescriptor) + ", regionDir=" + rootDir);</span> | 
 | <span class="source-line-no">7658</span><span id="line-7658">    createRegionDir(conf, info, rootDir);</span> | 
 | <span class="source-line-no">7659</span><span id="line-7659">    FileSystem fs = rootDir.getFileSystem(conf);</span> | 
 | <span class="source-line-no">7660</span><span id="line-7660">    Path tableDir = CommonFSUtils.getTableDir(rootDir, info.getTable());</span> | 
 | <span class="source-line-no">7661</span><span id="line-7661">    HRegion region =</span> | 
 | <span class="source-line-no">7662</span><span id="line-7662">      HRegion.newHRegion(tableDir, wal, fs, conf, info, hTableDescriptor, rsRpcServices);</span> | 
 | <span class="source-line-no">7663</span><span id="line-7663">    if (initialize) {</span> | 
 | <span class="source-line-no">7664</span><span id="line-7664">      region.initialize(null);</span> | 
 | <span class="source-line-no">7665</span><span id="line-7665">    }</span> | 
 | <span class="source-line-no">7666</span><span id="line-7666">    return region;</span> | 
 | <span class="source-line-no">7667</span><span id="line-7667">  }</span> | 
 | <span class="source-line-no">7668</span><span id="line-7668"></span> | 
 | <span class="source-line-no">7669</span><span id="line-7669">  /**</span> | 
 | <span class="source-line-no">7670</span><span id="line-7670">   * Create a region under the given table directory.</span> | 
 | <span class="source-line-no">7671</span><span id="line-7671">   */</span> | 
 | <span class="source-line-no">7672</span><span id="line-7672">  public static HRegion createHRegion(Configuration conf, RegionInfo regionInfo, FileSystem fs,</span> | 
 | <span class="source-line-no">7673</span><span id="line-7673">    Path tableDir, TableDescriptor tableDesc) throws IOException {</span> | 
 | <span class="source-line-no">7674</span><span id="line-7674">    LOG.info("Creating {}, tableDescriptor={}, under table dir {}", regionInfo, tableDesc,</span> | 
 | <span class="source-line-no">7675</span><span id="line-7675">      tableDir);</span> | 
 | <span class="source-line-no">7676</span><span id="line-7676">    HRegionFileSystem.createRegionOnFileSystem(conf, fs, tableDir, regionInfo);</span> | 
 | <span class="source-line-no">7677</span><span id="line-7677">    HRegion region = HRegion.newHRegion(tableDir, null, fs, conf, regionInfo, tableDesc, null);</span> | 
 | <span class="source-line-no">7678</span><span id="line-7678">    return region;</span> | 
 | <span class="source-line-no">7679</span><span id="line-7679">  }</span> | 
 | <span class="source-line-no">7680</span><span id="line-7680"></span> | 
 | <span class="source-line-no">7681</span><span id="line-7681">  /**</span> | 
 | <span class="source-line-no">7682</span><span id="line-7682">   * Create the region directory in the filesystem.</span> | 
 | <span class="source-line-no">7683</span><span id="line-7683">   */</span> | 
 | <span class="source-line-no">7684</span><span id="line-7684">  public static HRegionFileSystem createRegionDir(Configuration configuration, RegionInfo ri,</span> | 
 | <span class="source-line-no">7685</span><span id="line-7685">    Path rootDir) throws IOException {</span> | 
 | <span class="source-line-no">7686</span><span id="line-7686">    FileSystem fs = rootDir.getFileSystem(configuration);</span> | 
 | <span class="source-line-no">7687</span><span id="line-7687">    Path tableDir = CommonFSUtils.getTableDir(rootDir, ri.getTable());</span> | 
 | <span class="source-line-no">7688</span><span id="line-7688">    // If directory already exists, will log warning and keep going. Will try to create</span> | 
 | <span class="source-line-no">7689</span><span id="line-7689">    // .regioninfo. If one exists, will overwrite.</span> | 
 | <span class="source-line-no">7690</span><span id="line-7690">    return HRegionFileSystem.createRegionOnFileSystem(configuration, fs, tableDir, ri);</span> | 
 | <span class="source-line-no">7691</span><span id="line-7691">  }</span> | 
 | <span class="source-line-no">7692</span><span id="line-7692"></span> | 
 | <span class="source-line-no">7693</span><span id="line-7693">  public static HRegion createHRegion(final RegionInfo info, final Path rootDir,</span> | 
 | <span class="source-line-no">7694</span><span id="line-7694">    final Configuration conf, final TableDescriptor hTableDescriptor, final WAL wal)</span> | 
 | <span class="source-line-no">7695</span><span id="line-7695">    throws IOException {</span> | 
 | <span class="source-line-no">7696</span><span id="line-7696">    return createHRegion(info, rootDir, conf, hTableDescriptor, wal, true);</span> | 
 | <span class="source-line-no">7697</span><span id="line-7697">  }</span> | 
 | <span class="source-line-no">7698</span><span id="line-7698"></span> | 
 | <span class="source-line-no">7699</span><span id="line-7699">  /**</span> | 
 | <span class="source-line-no">7700</span><span id="line-7700">   * Open a Region.</span> | 
 | <span class="source-line-no">7701</span><span id="line-7701">   * @param info Info for region to be opened.</span> | 
 | <span class="source-line-no">7702</span><span id="line-7702">   * @param wal  WAL for region to use. This method will call WAL#setSequenceNumber(long) passing</span> | 
 | <span class="source-line-no">7703</span><span id="line-7703">   *             the result of the call to HRegion#getMinSequenceId() to ensure the wal id is</span> | 
 | <span class="source-line-no">7704</span><span id="line-7704">   *             properly kept up. HRegionStore does this every time it opens a new region.</span> | 
 | <span class="source-line-no">7705</span><span id="line-7705">   * @return new HRegion</span> | 
 | <span class="source-line-no">7706</span><span id="line-7706">   */</span> | 
 | <span class="source-line-no">7707</span><span id="line-7707">  public static HRegion openHRegion(final RegionInfo info, final TableDescriptor htd, final WAL wal,</span> | 
 | <span class="source-line-no">7708</span><span id="line-7708">    final Configuration conf) throws IOException {</span> | 
 | <span class="source-line-no">7709</span><span id="line-7709">    return openHRegion(info, htd, wal, conf, null, null);</span> | 
 | <span class="source-line-no">7710</span><span id="line-7710">  }</span> | 
 | <span class="source-line-no">7711</span><span id="line-7711"></span> | 
 | <span class="source-line-no">7712</span><span id="line-7712">  /**</span> | 
 | <span class="source-line-no">7713</span><span id="line-7713">   * Open a Region.</span> | 
 | <span class="source-line-no">7714</span><span id="line-7714">   * @param info       Info for region to be opened</span> | 
 | <span class="source-line-no">7715</span><span id="line-7715">   * @param htd        the table descriptor</span> | 
 | <span class="source-line-no">7716</span><span id="line-7716">   * @param wal        WAL for region to use. This method will call WAL#setSequenceNumber(long)</span> | 
 | <span class="source-line-no">7717</span><span id="line-7717">   *                   passing the result of the call to HRegion#getMinSequenceId() to ensure the</span> | 
 | <span class="source-line-no">7718</span><span id="line-7718">   *                   wal id is properly kept up. HRegionStore does this every time it opens a new</span> | 
 | <span class="source-line-no">7719</span><span id="line-7719">   *                   region.</span> | 
 | <span class="source-line-no">7720</span><span id="line-7720">   * @param conf       The Configuration object to use.</span> | 
 | <span class="source-line-no">7721</span><span id="line-7721">   * @param rsServices An interface we can request flushes against.</span> | 
 | <span class="source-line-no">7722</span><span id="line-7722">   * @param reporter   An interface we can report progress against.</span> | 
 | <span class="source-line-no">7723</span><span id="line-7723">   * @return new HRegion</span> | 
 | <span class="source-line-no">7724</span><span id="line-7724">   */</span> | 
 | <span class="source-line-no">7725</span><span id="line-7725">  public static HRegion openHRegion(final RegionInfo info, final TableDescriptor htd, final WAL wal,</span> | 
 | <span class="source-line-no">7726</span><span id="line-7726">    final Configuration conf, final RegionServerServices rsServices,</span> | 
 | <span class="source-line-no">7727</span><span id="line-7727">    final CancelableProgressable reporter) throws IOException {</span> | 
 | <span class="source-line-no">7728</span><span id="line-7728">    return openHRegion(CommonFSUtils.getRootDir(conf), info, htd, wal, conf, rsServices, reporter);</span> | 
 | <span class="source-line-no">7729</span><span id="line-7729">  }</span> | 
 | <span class="source-line-no">7730</span><span id="line-7730"></span> | 
 | <span class="source-line-no">7731</span><span id="line-7731">  /**</span> | 
 | <span class="source-line-no">7732</span><span id="line-7732">   * Open a Region.</span> | 
 | <span class="source-line-no">7733</span><span id="line-7733">   * @param rootDir Root directory for HBase instance</span> | 
 | <span class="source-line-no">7734</span><span id="line-7734">   * @param info    Info for region to be opened.</span> | 
 | <span class="source-line-no">7735</span><span id="line-7735">   * @param htd     the table descriptor</span> | 
 | <span class="source-line-no">7736</span><span id="line-7736">   * @param wal     WAL for region to use. This method will call WAL#setSequenceNumber(long) passing</span> | 
 | <span class="source-line-no">7737</span><span id="line-7737">   *                the result of the call to HRegion#getMinSequenceId() to ensure the wal id is</span> | 
 | <span class="source-line-no">7738</span><span id="line-7738">   *                properly kept up. HRegionStore does this every time it opens a new region.</span> | 
 | <span class="source-line-no">7739</span><span id="line-7739">   * @param conf    The Configuration object to use.</span> | 
 | <span class="source-line-no">7740</span><span id="line-7740">   * @return new HRegion</span> | 
 | <span class="source-line-no">7741</span><span id="line-7741">   */</span> | 
 | <span class="source-line-no">7742</span><span id="line-7742">  public static HRegion openHRegion(Path rootDir, final RegionInfo info, final TableDescriptor htd,</span> | 
 | <span class="source-line-no">7743</span><span id="line-7743">    final WAL wal, final Configuration conf) throws IOException {</span> | 
 | <span class="source-line-no">7744</span><span id="line-7744">    return openHRegion(rootDir, info, htd, wal, conf, null, null);</span> | 
 | <span class="source-line-no">7745</span><span id="line-7745">  }</span> | 
 | <span class="source-line-no">7746</span><span id="line-7746"></span> | 
 | <span class="source-line-no">7747</span><span id="line-7747">  /**</span> | 
 | <span class="source-line-no">7748</span><span id="line-7748">   * Open a Region.</span> | 
 | <span class="source-line-no">7749</span><span id="line-7749">   * @param rootDir    Root directory for HBase instance</span> | 
 | <span class="source-line-no">7750</span><span id="line-7750">   * @param info       Info for region to be opened.</span> | 
 | <span class="source-line-no">7751</span><span id="line-7751">   * @param htd        the table descriptor</span> | 
 | <span class="source-line-no">7752</span><span id="line-7752">   * @param wal        WAL for region to use. This method will call WAL#setSequenceNumber(long)</span> | 
 | <span class="source-line-no">7753</span><span id="line-7753">   *                   passing the result of the call to HRegion#getMinSequenceId() to ensure the</span> | 
 | <span class="source-line-no">7754</span><span id="line-7754">   *                   wal id is properly kept up. HRegionStore does this every time it opens a new</span> | 
 | <span class="source-line-no">7755</span><span id="line-7755">   *                   region.</span> | 
 | <span class="source-line-no">7756</span><span id="line-7756">   * @param conf       The Configuration object to use.</span> | 
 | <span class="source-line-no">7757</span><span id="line-7757">   * @param rsServices An interface we can request flushes against.</span> | 
 | <span class="source-line-no">7758</span><span id="line-7758">   * @param reporter   An interface we can report progress against.</span> | 
 | <span class="source-line-no">7759</span><span id="line-7759">   * @return new HRegion</span> | 
 | <span class="source-line-no">7760</span><span id="line-7760">   */</span> | 
 | <span class="source-line-no">7761</span><span id="line-7761">  public static HRegion openHRegion(final Path rootDir, final RegionInfo info,</span> | 
 | <span class="source-line-no">7762</span><span id="line-7762">    final TableDescriptor htd, final WAL wal, final Configuration conf,</span> | 
 | <span class="source-line-no">7763</span><span id="line-7763">    final RegionServerServices rsServices, final CancelableProgressable reporter)</span> | 
 | <span class="source-line-no">7764</span><span id="line-7764">    throws IOException {</span> | 
 | <span class="source-line-no">7765</span><span id="line-7765">    FileSystem fs = null;</span> | 
 | <span class="source-line-no">7766</span><span id="line-7766">    if (rsServices != null) {</span> | 
 | <span class="source-line-no">7767</span><span id="line-7767">      fs = rsServices.getFileSystem();</span> | 
 | <span class="source-line-no">7768</span><span id="line-7768">    }</span> | 
 | <span class="source-line-no">7769</span><span id="line-7769">    if (fs == null) {</span> | 
 | <span class="source-line-no">7770</span><span id="line-7770">      fs = rootDir.getFileSystem(conf);</span> | 
 | <span class="source-line-no">7771</span><span id="line-7771">    }</span> | 
 | <span class="source-line-no">7772</span><span id="line-7772">    return openHRegion(conf, fs, rootDir, info, htd, wal, rsServices, reporter);</span> | 
 | <span class="source-line-no">7773</span><span id="line-7773">  }</span> | 
 | <span class="source-line-no">7774</span><span id="line-7774"></span> | 
 | <span class="source-line-no">7775</span><span id="line-7775">  /**</span> | 
 | <span class="source-line-no">7776</span><span id="line-7776">   * Open a Region.</span> | 
 | <span class="source-line-no">7777</span><span id="line-7777">   * @param conf    The Configuration object to use.</span> | 
 | <span class="source-line-no">7778</span><span id="line-7778">   * @param fs      Filesystem to use</span> | 
 | <span class="source-line-no">7779</span><span id="line-7779">   * @param rootDir Root directory for HBase instance</span> | 
 | <span class="source-line-no">7780</span><span id="line-7780">   * @param info    Info for region to be opened.</span> | 
 | <span class="source-line-no">7781</span><span id="line-7781">   * @param htd     the table descriptor</span> | 
 | <span class="source-line-no">7782</span><span id="line-7782">   * @param wal     WAL for region to use. This method will call WAL#setSequenceNumber(long) passing</span> | 
 | <span class="source-line-no">7783</span><span id="line-7783">   *                the result of the call to HRegion#getMinSequenceId() to ensure the wal id is</span> | 
 | <span class="source-line-no">7784</span><span id="line-7784">   *                properly kept up. HRegionStore does this every time it opens a new region.</span> | 
 | <span class="source-line-no">7785</span><span id="line-7785">   * @return new HRegion</span> | 
 | <span class="source-line-no">7786</span><span id="line-7786">   */</span> | 
 | <span class="source-line-no">7787</span><span id="line-7787">  public static HRegion openHRegion(final Configuration conf, final FileSystem fs,</span> | 
 | <span class="source-line-no">7788</span><span id="line-7788">    final Path rootDir, final RegionInfo info, final TableDescriptor htd, final WAL wal)</span> | 
 | <span class="source-line-no">7789</span><span id="line-7789">    throws IOException {</span> | 
 | <span class="source-line-no">7790</span><span id="line-7790">    return openHRegion(conf, fs, rootDir, info, htd, wal, null, null);</span> | 
 | <span class="source-line-no">7791</span><span id="line-7791">  }</span> | 
 | <span class="source-line-no">7792</span><span id="line-7792"></span> | 
 | <span class="source-line-no">7793</span><span id="line-7793">  /**</span> | 
 | <span class="source-line-no">7794</span><span id="line-7794">   * Open a Region.</span> | 
 | <span class="source-line-no">7795</span><span id="line-7795">   * @param conf       The Configuration object to use.</span> | 
 | <span class="source-line-no">7796</span><span id="line-7796">   * @param fs         Filesystem to use</span> | 
 | <span class="source-line-no">7797</span><span id="line-7797">   * @param rootDir    Root directory for HBase instance</span> | 
 | <span class="source-line-no">7798</span><span id="line-7798">   * @param info       Info for region to be opened.</span> | 
 | <span class="source-line-no">7799</span><span id="line-7799">   * @param htd        the table descriptor</span> | 
 | <span class="source-line-no">7800</span><span id="line-7800">   * @param wal        WAL for region to use. This method will call WAL#setSequenceNumber(long)</span> | 
 | <span class="source-line-no">7801</span><span id="line-7801">   *                   passing the result of the call to HRegion#getMinSequenceId() to ensure the</span> | 
 | <span class="source-line-no">7802</span><span id="line-7802">   *                   wal id is properly kept up. HRegionStore does this every time it opens a new</span> | 
 | <span class="source-line-no">7803</span><span id="line-7803">   *                   region.</span> | 
 | <span class="source-line-no">7804</span><span id="line-7804">   * @param rsServices An interface we can request flushes against.</span> | 
 | <span class="source-line-no">7805</span><span id="line-7805">   * @param reporter   An interface we can report progress against.</span> | 
 | <span class="source-line-no">7806</span><span id="line-7806">   * @return new HRegion</span> | 
 | <span class="source-line-no">7807</span><span id="line-7807">   */</span> | 
 | <span class="source-line-no">7808</span><span id="line-7808">  public static HRegion openHRegion(final Configuration conf, final FileSystem fs,</span> | 
 | <span class="source-line-no">7809</span><span id="line-7809">    final Path rootDir, final RegionInfo info, final TableDescriptor htd, final WAL wal,</span> | 
 | <span class="source-line-no">7810</span><span id="line-7810">    final RegionServerServices rsServices, final CancelableProgressable reporter)</span> | 
 | <span class="source-line-no">7811</span><span id="line-7811">    throws IOException {</span> | 
 | <span class="source-line-no">7812</span><span id="line-7812">    Path tableDir = CommonFSUtils.getTableDir(rootDir, info.getTable());</span> | 
 | <span class="source-line-no">7813</span><span id="line-7813">    return openHRegionFromTableDir(conf, fs, tableDir, info, htd, wal, rsServices, reporter);</span> | 
 | <span class="source-line-no">7814</span><span id="line-7814">  }</span> | 
 | <span class="source-line-no">7815</span><span id="line-7815"></span> | 
 | <span class="source-line-no">7816</span><span id="line-7816">  /**</span> | 
 | <span class="source-line-no">7817</span><span id="line-7817">   * Open a Region.</span> | 
 | <span class="source-line-no">7818</span><span id="line-7818">   * @param conf       The Configuration object to use.</span> | 
 | <span class="source-line-no">7819</span><span id="line-7819">   * @param fs         Filesystem to use</span> | 
 | <span class="source-line-no">7820</span><span id="line-7820">   * @param info       Info for region to be opened.</span> | 
 | <span class="source-line-no">7821</span><span id="line-7821">   * @param htd        the table descriptor</span> | 
 | <span class="source-line-no">7822</span><span id="line-7822">   * @param wal        WAL for region to use. This method will call WAL#setSequenceNumber(long)</span> | 
 | <span class="source-line-no">7823</span><span id="line-7823">   *                   passing the result of the call to HRegion#getMinSequenceId() to ensure the</span> | 
 | <span class="source-line-no">7824</span><span id="line-7824">   *                   wal id is properly kept up. HRegionStore does this every time it opens a new</span> | 
 | <span class="source-line-no">7825</span><span id="line-7825">   *                   region.</span> | 
 | <span class="source-line-no">7826</span><span id="line-7826">   * @param rsServices An interface we can request flushes against.</span> | 
 | <span class="source-line-no">7827</span><span id="line-7827">   * @param reporter   An interface we can report progress against.</span> | 
 | <span class="source-line-no">7828</span><span id="line-7828">   * @return new HRegion</span> | 
 | <span class="source-line-no">7829</span><span id="line-7829">   * @throws NullPointerException if {@code info} is {@code null}</span> | 
 | <span class="source-line-no">7830</span><span id="line-7830">   */</span> | 
 | <span class="source-line-no">7831</span><span id="line-7831">  public static HRegion openHRegionFromTableDir(final Configuration conf, final FileSystem fs,</span> | 
 | <span class="source-line-no">7832</span><span id="line-7832">    final Path tableDir, final RegionInfo info, final TableDescriptor htd, final WAL wal,</span> | 
 | <span class="source-line-no">7833</span><span id="line-7833">    final RegionServerServices rsServices, final CancelableProgressable reporter)</span> | 
 | <span class="source-line-no">7834</span><span id="line-7834">    throws IOException {</span> | 
 | <span class="source-line-no">7835</span><span id="line-7835">    Objects.requireNonNull(info, "RegionInfo cannot be null");</span> | 
 | <span class="source-line-no">7836</span><span id="line-7836">    LOG.debug("Opening region: {}", info);</span> | 
 | <span class="source-line-no">7837</span><span id="line-7837">    HRegion r = HRegion.newHRegion(tableDir, wal, fs, conf, info, htd, rsServices);</span> | 
 | <span class="source-line-no">7838</span><span id="line-7838">    return r.openHRegion(reporter);</span> | 
 | <span class="source-line-no">7839</span><span id="line-7839">  }</span> | 
 | <span class="source-line-no">7840</span><span id="line-7840"></span> | 
 | <span class="source-line-no">7841</span><span id="line-7841">  public NavigableMap<byte[], Integer> getReplicationScope() {</span> | 
 | <span class="source-line-no">7842</span><span id="line-7842">    return this.replicationScope;</span> | 
 | <span class="source-line-no">7843</span><span id="line-7843">  }</span> | 
 | <span class="source-line-no">7844</span><span id="line-7844"></span> | 
 | <span class="source-line-no">7845</span><span id="line-7845">  /**</span> | 
 | <span class="source-line-no">7846</span><span id="line-7846">   * Useful when reopening a closed region (normally for unit tests)</span> | 
 | <span class="source-line-no">7847</span><span id="line-7847">   * @param other    original object</span> | 
 | <span class="source-line-no">7848</span><span id="line-7848">   * @param reporter An interface we can report progress against.</span> | 
 | <span class="source-line-no">7849</span><span id="line-7849">   * @return new HRegion</span> | 
 | <span class="source-line-no">7850</span><span id="line-7850">   */</span> | 
 | <span class="source-line-no">7851</span><span id="line-7851">  public static HRegion openHRegion(final HRegion other, final CancelableProgressable reporter)</span> | 
 | <span class="source-line-no">7852</span><span id="line-7852">    throws IOException {</span> | 
 | <span class="source-line-no">7853</span><span id="line-7853">    HRegionFileSystem regionFs = other.getRegionFileSystem();</span> | 
 | <span class="source-line-no">7854</span><span id="line-7854">    HRegion r = newHRegion(regionFs.getTableDir(), other.getWAL(), regionFs.getFileSystem(),</span> | 
 | <span class="source-line-no">7855</span><span id="line-7855">      other.baseConf, other.getRegionInfo(), other.getTableDescriptor(), null);</span> | 
 | <span class="source-line-no">7856</span><span id="line-7856">    return r.openHRegion(reporter);</span> | 
 | <span class="source-line-no">7857</span><span id="line-7857">  }</span> | 
 | <span class="source-line-no">7858</span><span id="line-7858"></span> | 
 | <span class="source-line-no">7859</span><span id="line-7859">  public static Region openHRegion(final Region other, final CancelableProgressable reporter)</span> | 
 | <span class="source-line-no">7860</span><span id="line-7860">    throws IOException {</span> | 
 | <span class="source-line-no">7861</span><span id="line-7861">    return openHRegion((HRegion) other, reporter);</span> | 
 | <span class="source-line-no">7862</span><span id="line-7862">  }</span> | 
 | <span class="source-line-no">7863</span><span id="line-7863"></span> | 
 | <span class="source-line-no">7864</span><span id="line-7864">  /**</span> | 
 | <span class="source-line-no">7865</span><span id="line-7865">   * Open HRegion.</span> | 
 | <span class="source-line-no">7866</span><span id="line-7866">   * <p/></span> | 
 | <span class="source-line-no">7867</span><span id="line-7867">   * Calls initialize and sets sequenceId.</span> | 
 | <span class="source-line-no">7868</span><span id="line-7868">   * @return Returns <code>this</code></span> | 
 | <span class="source-line-no">7869</span><span id="line-7869">   */</span> | 
 | <span class="source-line-no">7870</span><span id="line-7870">  private HRegion openHRegion(final CancelableProgressable reporter) throws IOException {</span> | 
 | <span class="source-line-no">7871</span><span id="line-7871">    try {</span> | 
 | <span class="source-line-no">7872</span><span id="line-7872">      CompoundConfiguration cConfig =</span> | 
 | <span class="source-line-no">7873</span><span id="line-7873">        new CompoundConfiguration().add(conf).addBytesMap(htableDescriptor.getValues());</span> | 
 | <span class="source-line-no">7874</span><span id="line-7874">      // Refuse to open the region if we are missing local compression support</span> | 
 | <span class="source-line-no">7875</span><span id="line-7875">      TableDescriptorChecker.checkCompression(cConfig, htableDescriptor);</span> | 
 | <span class="source-line-no">7876</span><span id="line-7876">      // Refuse to open the region if encryption configuration is incorrect or</span> | 
 | <span class="source-line-no">7877</span><span id="line-7877">      // codec support is missing</span> | 
 | <span class="source-line-no">7878</span><span id="line-7878">      LOG.debug("checking encryption for " + this.getRegionInfo().getEncodedName());</span> | 
 | <span class="source-line-no">7879</span><span id="line-7879">      TableDescriptorChecker.checkEncryption(cConfig, htableDescriptor);</span> | 
 | <span class="source-line-no">7880</span><span id="line-7880">      // Refuse to open the region if a required class cannot be loaded</span> | 
 | <span class="source-line-no">7881</span><span id="line-7881">      LOG.debug("checking classloading for " + this.getRegionInfo().getEncodedName());</span> | 
 | <span class="source-line-no">7882</span><span id="line-7882">      TableDescriptorChecker.checkClassLoading(cConfig, htableDescriptor);</span> | 
 | <span class="source-line-no">7883</span><span id="line-7883">      this.openSeqNum = initialize(reporter);</span> | 
 | <span class="source-line-no">7884</span><span id="line-7884">      this.mvcc.advanceTo(openSeqNum);</span> | 
 | <span class="source-line-no">7885</span><span id="line-7885">      // The openSeqNum must be increased every time when a region is assigned, as we rely on it to</span> | 
 | <span class="source-line-no">7886</span><span id="line-7886">      // determine whether a region has been successfully reopened. So here we always write open</span> | 
 | <span class="source-line-no">7887</span><span id="line-7887">      // marker, even if the table is read only.</span> | 
 | <span class="source-line-no">7888</span><span id="line-7888">      if (</span> | 
 | <span class="source-line-no">7889</span><span id="line-7889">        wal != null && getRegionServerServices() != null</span> | 
 | <span class="source-line-no">7890</span><span id="line-7890">          && RegionReplicaUtil.isDefaultReplica(getRegionInfo())</span> | 
 | <span class="source-line-no">7891</span><span id="line-7891">      ) {</span> | 
 | <span class="source-line-no">7892</span><span id="line-7892">        writeRegionOpenMarker(wal, openSeqNum);</span> | 
 | <span class="source-line-no">7893</span><span id="line-7893">      }</span> | 
 | <span class="source-line-no">7894</span><span id="line-7894">    } catch (Throwable t) {</span> | 
 | <span class="source-line-no">7895</span><span id="line-7895">      // By coprocessor path wrong region will open failed,</span> | 
 | <span class="source-line-no">7896</span><span id="line-7896">      // MetricsRegionWrapperImpl is already init and not close,</span> | 
 | <span class="source-line-no">7897</span><span id="line-7897">      // add region close when open failed</span> | 
 | <span class="source-line-no">7898</span><span id="line-7898">      try {</span> | 
 | <span class="source-line-no">7899</span><span id="line-7899">        // It is not required to write sequence id file when region open is failed.</span> | 
 | <span class="source-line-no">7900</span><span id="line-7900">        // Passing true to skip the sequence id file write.</span> | 
 | <span class="source-line-no">7901</span><span id="line-7901">        this.close(true);</span> | 
 | <span class="source-line-no">7902</span><span id="line-7902">      } catch (Throwable e) {</span> | 
 | <span class="source-line-no">7903</span><span id="line-7903">        LOG.warn("Open region: {} failed. Try close region but got exception ",</span> | 
 | <span class="source-line-no">7904</span><span id="line-7904">          this.getRegionInfo(), e);</span> | 
 | <span class="source-line-no">7905</span><span id="line-7905">      }</span> | 
 | <span class="source-line-no">7906</span><span id="line-7906">      throw t;</span> | 
 | <span class="source-line-no">7907</span><span id="line-7907">    }</span> | 
 | <span class="source-line-no">7908</span><span id="line-7908">    return this;</span> | 
 | <span class="source-line-no">7909</span><span id="line-7909">  }</span> | 
 | <span class="source-line-no">7910</span><span id="line-7910"></span> | 
 | <span class="source-line-no">7911</span><span id="line-7911">  /**</span> | 
 | <span class="source-line-no">7912</span><span id="line-7912">   * Open a Region on a read-only file-system (like hdfs snapshots)</span> | 
 | <span class="source-line-no">7913</span><span id="line-7913">   * @param conf The Configuration object to use.</span> | 
 | <span class="source-line-no">7914</span><span id="line-7914">   * @param fs   Filesystem to use</span> | 
 | <span class="source-line-no">7915</span><span id="line-7915">   * @param info Info for region to be opened.</span> | 
 | <span class="source-line-no">7916</span><span id="line-7916">   * @param htd  the table descriptor</span> | 
 | <span class="source-line-no">7917</span><span id="line-7917">   * @return new HRegion</span> | 
 | <span class="source-line-no">7918</span><span id="line-7918">   * @throws NullPointerException if {@code info} is {@code null}</span> | 
 | <span class="source-line-no">7919</span><span id="line-7919">   */</span> | 
 | <span class="source-line-no">7920</span><span id="line-7920">  public static HRegion openReadOnlyFileSystemHRegion(final Configuration conf, final FileSystem fs,</span> | 
 | <span class="source-line-no">7921</span><span id="line-7921">    final Path tableDir, RegionInfo info, final TableDescriptor htd) throws IOException {</span> | 
 | <span class="source-line-no">7922</span><span id="line-7922">    Objects.requireNonNull(info, "RegionInfo cannot be null");</span> | 
 | <span class="source-line-no">7923</span><span id="line-7923">    if (LOG.isDebugEnabled()) {</span> | 
 | <span class="source-line-no">7924</span><span id="line-7924">      LOG.debug("Opening region (readOnly filesystem): " + info);</span> | 
 | <span class="source-line-no">7925</span><span id="line-7925">    }</span> | 
 | <span class="source-line-no">7926</span><span id="line-7926">    if (info.getReplicaId() <= 0) {</span> | 
 | <span class="source-line-no">7927</span><span id="line-7927">      info = RegionReplicaUtil.getRegionInfoForReplica(info, 1);</span> | 
 | <span class="source-line-no">7928</span><span id="line-7928">    }</span> | 
 | <span class="source-line-no">7929</span><span id="line-7929">    HRegion r = HRegion.newHRegion(tableDir, null, fs, conf, info, htd, null);</span> | 
 | <span class="source-line-no">7930</span><span id="line-7930">    r.writestate.setReadOnly(true);</span> | 
 | <span class="source-line-no">7931</span><span id="line-7931">    return r.openHRegion(null);</span> | 
 | <span class="source-line-no">7932</span><span id="line-7932">  }</span> | 
 | <span class="source-line-no">7933</span><span id="line-7933"></span> | 
 | <span class="source-line-no">7934</span><span id="line-7934">  public static HRegion warmupHRegion(final RegionInfo info, final TableDescriptor htd,</span> | 
 | <span class="source-line-no">7935</span><span id="line-7935">    final WAL wal, final Configuration conf, final RegionServerServices rsServices,</span> | 
 | <span class="source-line-no">7936</span><span id="line-7936">    final CancelableProgressable reporter) throws IOException {</span> | 
 | <span class="source-line-no">7937</span><span id="line-7937"></span> | 
 | <span class="source-line-no">7938</span><span id="line-7938">    Objects.requireNonNull(info, "RegionInfo cannot be null");</span> | 
 | <span class="source-line-no">7939</span><span id="line-7939">    LOG.debug("Warmup {}", info);</span> | 
 | <span class="source-line-no">7940</span><span id="line-7940">    Path rootDir = CommonFSUtils.getRootDir(conf);</span> | 
 | <span class="source-line-no">7941</span><span id="line-7941">    Path tableDir = CommonFSUtils.getTableDir(rootDir, info.getTable());</span> | 
 | <span class="source-line-no">7942</span><span id="line-7942">    FileSystem fs = null;</span> | 
 | <span class="source-line-no">7943</span><span id="line-7943">    if (rsServices != null) {</span> | 
 | <span class="source-line-no">7944</span><span id="line-7944">      fs = rsServices.getFileSystem();</span> | 
 | <span class="source-line-no">7945</span><span id="line-7945">    }</span> | 
 | <span class="source-line-no">7946</span><span id="line-7946">    if (fs == null) {</span> | 
 | <span class="source-line-no">7947</span><span id="line-7947">      fs = rootDir.getFileSystem(conf);</span> | 
 | <span class="source-line-no">7948</span><span id="line-7948">    }</span> | 
 | <span class="source-line-no">7949</span><span id="line-7949">    HRegion r = HRegion.newHRegion(tableDir, wal, fs, conf, info, htd, null);</span> | 
 | <span class="source-line-no">7950</span><span id="line-7950">    r.initializeWarmup(reporter);</span> | 
 | <span class="source-line-no">7951</span><span id="line-7951">    r.close();</span> | 
 | <span class="source-line-no">7952</span><span id="line-7952">    return r;</span> | 
 | <span class="source-line-no">7953</span><span id="line-7953">  }</span> | 
 | <span class="source-line-no">7954</span><span id="line-7954"></span> | 
 | <span class="source-line-no">7955</span><span id="line-7955">  /**</span> | 
 | <span class="source-line-no">7956</span><span id="line-7956">   * Computes the Path of the HRegion</span> | 
 | <span class="source-line-no">7957</span><span id="line-7957">   * @param tabledir qualified path for table</span> | 
 | <span class="source-line-no">7958</span><span id="line-7958">   * @param name     ENCODED region name</span> | 
 | <span class="source-line-no">7959</span><span id="line-7959">   * @return Path of HRegion directory</span> | 
 | <span class="source-line-no">7960</span><span id="line-7960">   * @deprecated For tests only; to be removed.</span> | 
 | <span class="source-line-no">7961</span><span id="line-7961">   */</span> | 
 | <span class="source-line-no">7962</span><span id="line-7962">  @Deprecated</span> | 
 | <span class="source-line-no">7963</span><span id="line-7963">  public static Path getRegionDir(final Path tabledir, final String name) {</span> | 
 | <span class="source-line-no">7964</span><span id="line-7964">    return new Path(tabledir, name);</span> | 
 | <span class="source-line-no">7965</span><span id="line-7965">  }</span> | 
 | <span class="source-line-no">7966</span><span id="line-7966"></span> | 
 | <span class="source-line-no">7967</span><span id="line-7967">  /**</span> | 
 | <span class="source-line-no">7968</span><span id="line-7968">   * Determines if the specified row is within the row range specified by the specified RegionInfo</span> | 
 | <span class="source-line-no">7969</span><span id="line-7969">   * @param info RegionInfo that specifies the row range</span> | 
 | <span class="source-line-no">7970</span><span id="line-7970">   * @param row  row to be checked</span> | 
 | <span class="source-line-no">7971</span><span id="line-7971">   * @return true if the row is within the range specified by the RegionInfo</span> | 
 | <span class="source-line-no">7972</span><span id="line-7972">   */</span> | 
 | <span class="source-line-no">7973</span><span id="line-7973">  public static boolean rowIsInRange(RegionInfo info, final byte[] row) {</span> | 
 | <span class="source-line-no">7974</span><span id="line-7974">    return ((info.getStartKey().length == 0) || (Bytes.compareTo(info.getStartKey(), row) <= 0))</span> | 
 | <span class="source-line-no">7975</span><span id="line-7975">      && ((info.getEndKey().length == 0) || (Bytes.compareTo(info.getEndKey(), row) > 0));</span> | 
 | <span class="source-line-no">7976</span><span id="line-7976">  }</span> | 
 | <span class="source-line-no">7977</span><span id="line-7977"></span> | 
 | <span class="source-line-no">7978</span><span id="line-7978">  public static boolean rowIsInRange(RegionInfo info, final byte[] row, final int offset,</span> | 
 | <span class="source-line-no">7979</span><span id="line-7979">    final short length) {</span> | 
 | <span class="source-line-no">7980</span><span id="line-7980">    return ((info.getStartKey().length == 0)</span> | 
 | <span class="source-line-no">7981</span><span id="line-7981">      || (Bytes.compareTo(info.getStartKey(), 0, info.getStartKey().length, row, offset, length)</span> | 
 | <span class="source-line-no">7982</span><span id="line-7982">          <= 0))</span> | 
 | <span class="source-line-no">7983</span><span id="line-7983">      && ((info.getEndKey().length == 0)</span> | 
 | <span class="source-line-no">7984</span><span id="line-7984">        || (Bytes.compareTo(info.getEndKey(), 0, info.getEndKey().length, row, offset, length)</span> | 
 | <span class="source-line-no">7985</span><span id="line-7985">            > 0));</span> | 
 | <span class="source-line-no">7986</span><span id="line-7986">  }</span> | 
 | <span class="source-line-no">7987</span><span id="line-7987"></span> | 
 | <span class="source-line-no">7988</span><span id="line-7988">  @Override</span> | 
 | <span class="source-line-no">7989</span><span id="line-7989">  public Result get(final Get get) throws IOException {</span> | 
 | <span class="source-line-no">7990</span><span id="line-7990">    prepareGet(get);</span> | 
 | <span class="source-line-no">7991</span><span id="line-7991">    List<Cell> results = get(get, true);</span> | 
 | <span class="source-line-no">7992</span><span id="line-7992">    boolean stale = this.getRegionInfo().getReplicaId() != 0;</span> | 
 | <span class="source-line-no">7993</span><span id="line-7993">    return Result.create(results, get.isCheckExistenceOnly() ? !results.isEmpty() : null, stale);</span> | 
 | <span class="source-line-no">7994</span><span id="line-7994">  }</span> | 
 | <span class="source-line-no">7995</span><span id="line-7995"></span> | 
 | <span class="source-line-no">7996</span><span id="line-7996">  void prepareGet(final Get get) throws IOException {</span> | 
 | <span class="source-line-no">7997</span><span id="line-7997">    checkRow(get.getRow(), "Get");</span> | 
 | <span class="source-line-no">7998</span><span id="line-7998">    // Verify families are all valid</span> | 
 | <span class="source-line-no">7999</span><span id="line-7999">    if (get.hasFamilies()) {</span> | 
 | <span class="source-line-no">8000</span><span id="line-8000">      for (byte[] family : get.familySet()) {</span> | 
 | <span class="source-line-no">8001</span><span id="line-8001">        checkFamily(family);</span> | 
 | <span class="source-line-no">8002</span><span id="line-8002">      }</span> | 
 | <span class="source-line-no">8003</span><span id="line-8003">    } else { // Adding all families to scanner</span> | 
 | <span class="source-line-no">8004</span><span id="line-8004">      for (byte[] family : this.htableDescriptor.getColumnFamilyNames()) {</span> | 
 | <span class="source-line-no">8005</span><span id="line-8005">        get.addFamily(family);</span> | 
 | <span class="source-line-no">8006</span><span id="line-8006">      }</span> | 
 | <span class="source-line-no">8007</span><span id="line-8007">    }</span> | 
 | <span class="source-line-no">8008</span><span id="line-8008">  }</span> | 
 | <span class="source-line-no">8009</span><span id="line-8009"></span> | 
 | <span class="source-line-no">8010</span><span id="line-8010">  @Override</span> | 
 | <span class="source-line-no">8011</span><span id="line-8011">  public List<Cell> get(Get get, boolean withCoprocessor) throws IOException {</span> | 
 | <span class="source-line-no">8012</span><span id="line-8012">    return get(get, withCoprocessor, HConstants.NO_NONCE, HConstants.NO_NONCE);</span> | 
 | <span class="source-line-no">8013</span><span id="line-8013">  }</span> | 
 | <span class="source-line-no">8014</span><span id="line-8014"></span> | 
 | <span class="source-line-no">8015</span><span id="line-8015">  private List<Cell> get(Get get, boolean withCoprocessor, long nonceGroup, long nonce)</span> | 
 | <span class="source-line-no">8016</span><span id="line-8016">    throws IOException {</span> | 
 | <span class="source-line-no">8017</span><span id="line-8017">    return TraceUtil.trace(() -> getInternal(get, withCoprocessor, nonceGroup, nonce),</span> | 
 | <span class="source-line-no">8018</span><span id="line-8018">      () -> createRegionSpan("Region.get"));</span> | 
 | <span class="source-line-no">8019</span><span id="line-8019">  }</span> | 
 | <span class="source-line-no">8020</span><span id="line-8020"></span> | 
 | <span class="source-line-no">8021</span><span id="line-8021">  private List<Cell> getInternal(Get get, boolean withCoprocessor, long nonceGroup, long nonce)</span> | 
 | <span class="source-line-no">8022</span><span id="line-8022">    throws IOException {</span> | 
 | <span class="source-line-no">8023</span><span id="line-8023">    List<Cell> results = new ArrayList<>();</span> | 
 | <span class="source-line-no">8024</span><span id="line-8024"></span> | 
 | <span class="source-line-no">8025</span><span id="line-8025">    // pre-get CP hook</span> | 
 | <span class="source-line-no">8026</span><span id="line-8026">    if (withCoprocessor && (coprocessorHost != null)) {</span> | 
 | <span class="source-line-no">8027</span><span id="line-8027">      if (coprocessorHost.preGet(get, results)) {</span> | 
 | <span class="source-line-no">8028</span><span id="line-8028">        metricsUpdateForGet();</span> | 
 | <span class="source-line-no">8029</span><span id="line-8029">        return results;</span> | 
 | <span class="source-line-no">8030</span><span id="line-8030">      }</span> | 
 | <span class="source-line-no">8031</span><span id="line-8031">    }</span> | 
 | <span class="source-line-no">8032</span><span id="line-8032">    Scan scan = new Scan(get);</span> | 
 | <span class="source-line-no">8033</span><span id="line-8033">    if (scan.getLoadColumnFamiliesOnDemandValue() == null) {</span> | 
 | <span class="source-line-no">8034</span><span id="line-8034">      scan.setLoadColumnFamiliesOnDemand(isLoadingCfsOnDemandDefault());</span> | 
 | <span class="source-line-no">8035</span><span id="line-8035">    }</span> | 
 | <span class="source-line-no">8036</span><span id="line-8036">    try (RegionScanner scanner = getScanner(scan, null, nonceGroup, nonce)) {</span> | 
 | <span class="source-line-no">8037</span><span id="line-8037">      List<Cell> tmp = new ArrayList<>();</span> | 
 | <span class="source-line-no">8038</span><span id="line-8038">      scanner.next(tmp);</span> | 
 | <span class="source-line-no">8039</span><span id="line-8039">      // Copy EC to heap, then close the scanner.</span> | 
 | <span class="source-line-no">8040</span><span id="line-8040">      // This can be an EXPENSIVE call. It may make an extra copy from offheap to onheap buffers.</span> | 
 | <span class="source-line-no">8041</span><span id="line-8041">      // See more details in HBASE-26036.</span> | 
 | <span class="source-line-no">8042</span><span id="line-8042">      for (Cell cell : tmp) {</span> | 
 | <span class="source-line-no">8043</span><span id="line-8043">        results.add(CellUtil.cloneIfNecessary(cell));</span> | 
 | <span class="source-line-no">8044</span><span id="line-8044">      }</span> | 
 | <span class="source-line-no">8045</span><span id="line-8045">    }</span> | 
 | <span class="source-line-no">8046</span><span id="line-8046"></span> | 
 | <span class="source-line-no">8047</span><span id="line-8047">    // post-get CP hook</span> | 
 | <span class="source-line-no">8048</span><span id="line-8048">    if (withCoprocessor && (coprocessorHost != null)) {</span> | 
 | <span class="source-line-no">8049</span><span id="line-8049">      coprocessorHost.postGet(get, results);</span> | 
 | <span class="source-line-no">8050</span><span id="line-8050">    }</span> | 
 | <span class="source-line-no">8051</span><span id="line-8051"></span> | 
 | <span class="source-line-no">8052</span><span id="line-8052">    metricsUpdateForGet();</span> | 
 | <span class="source-line-no">8053</span><span id="line-8053"></span> | 
 | <span class="source-line-no">8054</span><span id="line-8054">    return results;</span> | 
 | <span class="source-line-no">8055</span><span id="line-8055">  }</span> | 
 | <span class="source-line-no">8056</span><span id="line-8056"></span> | 
 | <span class="source-line-no">8057</span><span id="line-8057">  void metricsUpdateForGet() {</span> | 
 | <span class="source-line-no">8058</span><span id="line-8058">    if (this.metricsRegion != null) {</span> | 
 | <span class="source-line-no">8059</span><span id="line-8059">      this.metricsRegion.updateGet();</span> | 
 | <span class="source-line-no">8060</span><span id="line-8060">    }</span> | 
 | <span class="source-line-no">8061</span><span id="line-8061">    if (this.rsServices != null && this.rsServices.getMetrics() != null) {</span> | 
 | <span class="source-line-no">8062</span><span id="line-8062">      rsServices.getMetrics().updateReadQueryMeter(this, 1);</span> | 
 | <span class="source-line-no">8063</span><span id="line-8063">    }</span> | 
 | <span class="source-line-no">8064</span><span id="line-8064"></span> | 
 | <span class="source-line-no">8065</span><span id="line-8065">  }</span> | 
 | <span class="source-line-no">8066</span><span id="line-8066"></span> | 
 | <span class="source-line-no">8067</span><span id="line-8067">  @Override</span> | 
 | <span class="source-line-no">8068</span><span id="line-8068">  public Result mutateRow(RowMutations rm) throws IOException {</span> | 
 | <span class="source-line-no">8069</span><span id="line-8069">    return mutateRow(rm, HConstants.NO_NONCE, HConstants.NO_NONCE);</span> | 
 | <span class="source-line-no">8070</span><span id="line-8070">  }</span> | 
 | <span class="source-line-no">8071</span><span id="line-8071"></span> | 
 | <span class="source-line-no">8072</span><span id="line-8072">  public Result mutateRow(RowMutations rm, long nonceGroup, long nonce) throws IOException {</span> | 
 | <span class="source-line-no">8073</span><span id="line-8073">    final List<Mutation> m = rm.getMutations();</span> | 
 | <span class="source-line-no">8074</span><span id="line-8074">    OperationStatus[] statuses = batchMutate(m.toArray(new Mutation[0]), true, nonceGroup, nonce);</span> | 
 | <span class="source-line-no">8075</span><span id="line-8075"></span> | 
 | <span class="source-line-no">8076</span><span id="line-8076">    List<Result> results = new ArrayList<>();</span> | 
 | <span class="source-line-no">8077</span><span id="line-8077">    for (OperationStatus status : statuses) {</span> | 
 | <span class="source-line-no">8078</span><span id="line-8078">      if (status.getResult() != null) {</span> | 
 | <span class="source-line-no">8079</span><span id="line-8079">        results.add(status.getResult());</span> | 
 | <span class="source-line-no">8080</span><span id="line-8080">      }</span> | 
 | <span class="source-line-no">8081</span><span id="line-8081">    }</span> | 
 | <span class="source-line-no">8082</span><span id="line-8082"></span> | 
 | <span class="source-line-no">8083</span><span id="line-8083">    if (results.isEmpty()) {</span> | 
 | <span class="source-line-no">8084</span><span id="line-8084">      return null;</span> | 
 | <span class="source-line-no">8085</span><span id="line-8085">    }</span> | 
 | <span class="source-line-no">8086</span><span id="line-8086"></span> | 
 | <span class="source-line-no">8087</span><span id="line-8087">    // Merge the results of the Increment/Append operations</span> | 
 | <span class="source-line-no">8088</span><span id="line-8088">    List<Cell> cells = new ArrayList<>();</span> | 
 | <span class="source-line-no">8089</span><span id="line-8089">    for (Result result : results) {</span> | 
 | <span class="source-line-no">8090</span><span id="line-8090">      if (result.rawCells() != null) {</span> | 
 | <span class="source-line-no">8091</span><span id="line-8091">        cells.addAll(Arrays.asList(result.rawCells()));</span> | 
 | <span class="source-line-no">8092</span><span id="line-8092">      }</span> | 
 | <span class="source-line-no">8093</span><span id="line-8093">    }</span> | 
 | <span class="source-line-no">8094</span><span id="line-8094">    return Result.create(cells);</span> | 
 | <span class="source-line-no">8095</span><span id="line-8095">  }</span> | 
 | <span class="source-line-no">8096</span><span id="line-8096"></span> | 
 | <span class="source-line-no">8097</span><span id="line-8097">  /**</span> | 
 | <span class="source-line-no">8098</span><span id="line-8098">   * Perform atomic (all or none) mutations within the region.</span> | 
 | <span class="source-line-no">8099</span><span id="line-8099">   * @param mutations  The list of mutations to perform. <code>mutations</code> can contain</span> | 
 | <span class="source-line-no">8100</span><span id="line-8100">   *                   operations for multiple rows. Caller has to ensure that all rows are</span> | 
 | <span class="source-line-no">8101</span><span id="line-8101">   *                   contained in this region.</span> | 
 | <span class="source-line-no">8102</span><span id="line-8102">   * @param rowsToLock Rows to lock</span> | 
 | <span class="source-line-no">8103</span><span id="line-8103">   * @param nonceGroup Optional nonce group of the operation (client Id)</span> | 
 | <span class="source-line-no">8104</span><span id="line-8104">   * @param nonce      Optional nonce of the operation (unique random id to ensure "more</span> | 
 | <span class="source-line-no">8105</span><span id="line-8105">   *                   idempotence") If multiple rows are locked care should be taken that</span> | 
 | <span class="source-line-no">8106</span><span id="line-8106">   *                   <code>rowsToLock</code> is sorted in order to avoid deadlocks.</span> | 
 | <span class="source-line-no">8107</span><span id="line-8107">   */</span> | 
 | <span class="source-line-no">8108</span><span id="line-8108">  @Override</span> | 
 | <span class="source-line-no">8109</span><span id="line-8109">  public void mutateRowsWithLocks(Collection<Mutation> mutations, Collection<byte[]> rowsToLock,</span> | 
 | <span class="source-line-no">8110</span><span id="line-8110">    long nonceGroup, long nonce) throws IOException {</span> | 
 | <span class="source-line-no">8111</span><span id="line-8111">    batchMutate(new MutationBatchOperation(this, mutations.toArray(new Mutation[mutations.size()]),</span> | 
 | <span class="source-line-no">8112</span><span id="line-8112">      true, nonceGroup, nonce) {</span> | 
 | <span class="source-line-no">8113</span><span id="line-8113">      @Override</span> | 
 | <span class="source-line-no">8114</span><span id="line-8114">      public MiniBatchOperationInProgress<Mutation></span> | 
 | <span class="source-line-no">8115</span><span id="line-8115">        lockRowsAndBuildMiniBatch(List<RowLock> acquiredRowLocks) throws IOException {</span> | 
 | <span class="source-line-no">8116</span><span id="line-8116">        RowLock prevRowLock = null;</span> | 
 | <span class="source-line-no">8117</span><span id="line-8117">        for (byte[] row : rowsToLock) {</span> | 
 | <span class="source-line-no">8118</span><span id="line-8118">          try {</span> | 
 | <span class="source-line-no">8119</span><span id="line-8119">            RowLock rowLock = region.getRowLock(row, false, prevRowLock); // write lock</span> | 
 | <span class="source-line-no">8120</span><span id="line-8120">            if (rowLock != prevRowLock) {</span> | 
 | <span class="source-line-no">8121</span><span id="line-8121">              acquiredRowLocks.add(rowLock);</span> | 
 | <span class="source-line-no">8122</span><span id="line-8122">              prevRowLock = rowLock;</span> | 
 | <span class="source-line-no">8123</span><span id="line-8123">            }</span> | 
 | <span class="source-line-no">8124</span><span id="line-8124">          } catch (IOException ioe) {</span> | 
 | <span class="source-line-no">8125</span><span id="line-8125">            LOG.warn("Failed getting lock, row={}, in region {}", Bytes.toStringBinary(row), this,</span> | 
 | <span class="source-line-no">8126</span><span id="line-8126">              ioe);</span> | 
 | <span class="source-line-no">8127</span><span id="line-8127">            throw ioe;</span> | 
 | <span class="source-line-no">8128</span><span id="line-8128">          }</span> | 
 | <span class="source-line-no">8129</span><span id="line-8129">        }</span> | 
 | <span class="source-line-no">8130</span><span id="line-8130">        return createMiniBatch(size(), size());</span> | 
 | <span class="source-line-no">8131</span><span id="line-8131">      }</span> | 
 | <span class="source-line-no">8132</span><span id="line-8132">    });</span> | 
 | <span class="source-line-no">8133</span><span id="line-8133">  }</span> | 
 | <span class="source-line-no">8134</span><span id="line-8134"></span> | 
 | <span class="source-line-no">8135</span><span id="line-8135">  /** Returns statistics about the current load of the region */</span> | 
 | <span class="source-line-no">8136</span><span id="line-8136">  public ClientProtos.RegionLoadStats getLoadStatistics() {</span> | 
 | <span class="source-line-no">8137</span><span id="line-8137">    if (!regionStatsEnabled) {</span> | 
 | <span class="source-line-no">8138</span><span id="line-8138">      return null;</span> | 
 | <span class="source-line-no">8139</span><span id="line-8139">    }</span> | 
 | <span class="source-line-no">8140</span><span id="line-8140">    ClientProtos.RegionLoadStats.Builder stats = ClientProtos.RegionLoadStats.newBuilder();</span> | 
 | <span class="source-line-no">8141</span><span id="line-8141">    stats.setMemStoreLoad((int) (Math.min(100,</span> | 
 | <span class="source-line-no">8142</span><span id="line-8142">      (this.memStoreSizing.getMemStoreSize().getHeapSize() * 100) / this.memstoreFlushSize)));</span> | 
 | <span class="source-line-no">8143</span><span id="line-8143">    if (rsServices.getHeapMemoryManager() != null) {</span> | 
 | <span class="source-line-no">8144</span><span id="line-8144">      // the HeapMemoryManager uses -0.0 to signal a problem asking the JVM,</span> | 
 | <span class="source-line-no">8145</span><span id="line-8145">      // so we could just do the calculation below and we'll get a 0.</span> | 
 | <span class="source-line-no">8146</span><span id="line-8146">      // treating it as a special case analogous to no HMM instead so that it can be</span> | 
 | <span class="source-line-no">8147</span><span id="line-8147">      // programatically treated different from using <1% of heap.</span> | 
 | <span class="source-line-no">8148</span><span id="line-8148">      final float occupancy = rsServices.getHeapMemoryManager().getHeapOccupancyPercent();</span> | 
 | <span class="source-line-no">8149</span><span id="line-8149">      if (occupancy != HeapMemoryManager.HEAP_OCCUPANCY_ERROR_VALUE) {</span> | 
 | <span class="source-line-no">8150</span><span id="line-8150">        stats.setHeapOccupancy((int) (occupancy * 100));</span> | 
 | <span class="source-line-no">8151</span><span id="line-8151">      }</span> | 
 | <span class="source-line-no">8152</span><span id="line-8152">    }</span> | 
 | <span class="source-line-no">8153</span><span id="line-8153">    stats.setCompactionPressure((int) (rsServices.getCompactionPressure() * 100 > 100</span> | 
 | <span class="source-line-no">8154</span><span id="line-8154">      ? 100</span> | 
 | <span class="source-line-no">8155</span><span id="line-8155">      : rsServices.getCompactionPressure() * 100));</span> | 
 | <span class="source-line-no">8156</span><span id="line-8156">    return stats.build();</span> | 
 | <span class="source-line-no">8157</span><span id="line-8157">  }</span> | 
 | <span class="source-line-no">8158</span><span id="line-8158"></span> | 
 | <span class="source-line-no">8159</span><span id="line-8159">  @Override</span> | 
 | <span class="source-line-no">8160</span><span id="line-8160">  public Result append(Append append) throws IOException {</span> | 
 | <span class="source-line-no">8161</span><span id="line-8161">    return append(append, HConstants.NO_NONCE, HConstants.NO_NONCE);</span> | 
 | <span class="source-line-no">8162</span><span id="line-8162">  }</span> | 
 | <span class="source-line-no">8163</span><span id="line-8163"></span> | 
 | <span class="source-line-no">8164</span><span id="line-8164">  public Result append(Append append, long nonceGroup, long nonce) throws IOException {</span> | 
 | <span class="source-line-no">8165</span><span id="line-8165">    return TraceUtil.trace(() -> {</span> | 
 | <span class="source-line-no">8166</span><span id="line-8166">      checkReadOnly();</span> | 
 | <span class="source-line-no">8167</span><span id="line-8167">      checkResources();</span> | 
 | <span class="source-line-no">8168</span><span id="line-8168">      startRegionOperation(Operation.APPEND);</span> | 
 | <span class="source-line-no">8169</span><span id="line-8169">      try {</span> | 
 | <span class="source-line-no">8170</span><span id="line-8170">        // All edits for the given row (across all column families) must happen atomically.</span> | 
 | <span class="source-line-no">8171</span><span id="line-8171">        return mutate(append, true, nonceGroup, nonce).getResult();</span> | 
 | <span class="source-line-no">8172</span><span id="line-8172">      } finally {</span> | 
 | <span class="source-line-no">8173</span><span id="line-8173">        closeRegionOperation(Operation.APPEND);</span> | 
 | <span class="source-line-no">8174</span><span id="line-8174">      }</span> | 
 | <span class="source-line-no">8175</span><span id="line-8175">    }, () -> createRegionSpan("Region.append"));</span> | 
 | <span class="source-line-no">8176</span><span id="line-8176">  }</span> | 
 | <span class="source-line-no">8177</span><span id="line-8177"></span> | 
 | <span class="source-line-no">8178</span><span id="line-8178">  @Override</span> | 
 | <span class="source-line-no">8179</span><span id="line-8179">  public Result increment(Increment increment) throws IOException {</span> | 
 | <span class="source-line-no">8180</span><span id="line-8180">    return increment(increment, HConstants.NO_NONCE, HConstants.NO_NONCE);</span> | 
 | <span class="source-line-no">8181</span><span id="line-8181">  }</span> | 
 | <span class="source-line-no">8182</span><span id="line-8182"></span> | 
 | <span class="source-line-no">8183</span><span id="line-8183">  public Result increment(Increment increment, long nonceGroup, long nonce) throws IOException {</span> | 
 | <span class="source-line-no">8184</span><span id="line-8184">    return TraceUtil.trace(() -> {</span> | 
 | <span class="source-line-no">8185</span><span id="line-8185">      checkReadOnly();</span> | 
 | <span class="source-line-no">8186</span><span id="line-8186">      checkResources();</span> | 
 | <span class="source-line-no">8187</span><span id="line-8187">      startRegionOperation(Operation.INCREMENT);</span> | 
 | <span class="source-line-no">8188</span><span id="line-8188">      try {</span> | 
 | <span class="source-line-no">8189</span><span id="line-8189">        // All edits for the given row (across all column families) must happen atomically.</span> | 
 | <span class="source-line-no">8190</span><span id="line-8190">        return mutate(increment, true, nonceGroup, nonce).getResult();</span> | 
 | <span class="source-line-no">8191</span><span id="line-8191">      } finally {</span> | 
 | <span class="source-line-no">8192</span><span id="line-8192">        closeRegionOperation(Operation.INCREMENT);</span> | 
 | <span class="source-line-no">8193</span><span id="line-8193">      }</span> | 
 | <span class="source-line-no">8194</span><span id="line-8194">    }, () -> createRegionSpan("Region.increment"));</span> | 
 | <span class="source-line-no">8195</span><span id="line-8195">  }</span> | 
 | <span class="source-line-no">8196</span><span id="line-8196"></span> | 
 | <span class="source-line-no">8197</span><span id="line-8197">  private WALKeyImpl createWALKeyForWALAppend(boolean isReplay, BatchOperation<?> batchOp, long now,</span> | 
 | <span class="source-line-no">8198</span><span id="line-8198">    long nonceGroup, long nonce) {</span> | 
 | <span class="source-line-no">8199</span><span id="line-8199">    WALKeyImpl walKey = isReplay</span> | 
 | <span class="source-line-no">8200</span><span id="line-8200">      ? new WALKeyImpl(this.getRegionInfo().getEncodedNameAsBytes(),</span> | 
 | <span class="source-line-no">8201</span><span id="line-8201">        this.htableDescriptor.getTableName(), SequenceId.NO_SEQUENCE_ID, now,</span> | 
 | <span class="source-line-no">8202</span><span id="line-8202">        batchOp.getClusterIds(), nonceGroup, nonce, mvcc)</span> | 
 | <span class="source-line-no">8203</span><span id="line-8203">      : new WALKeyImpl(this.getRegionInfo().getEncodedNameAsBytes(),</span> | 
 | <span class="source-line-no">8204</span><span id="line-8204">        this.htableDescriptor.getTableName(), SequenceId.NO_SEQUENCE_ID, now,</span> | 
 | <span class="source-line-no">8205</span><span id="line-8205">        batchOp.getClusterIds(), nonceGroup, nonce, mvcc, this.getReplicationScope());</span> | 
 | <span class="source-line-no">8206</span><span id="line-8206">    if (isReplay) {</span> | 
 | <span class="source-line-no">8207</span><span id="line-8207">      walKey.setOrigLogSeqNum(batchOp.getOrigLogSeqNum());</span> | 
 | <span class="source-line-no">8208</span><span id="line-8208">    }</span> | 
 | <span class="source-line-no">8209</span><span id="line-8209">    return walKey;</span> | 
 | <span class="source-line-no">8210</span><span id="line-8210">  }</span> | 
 | <span class="source-line-no">8211</span><span id="line-8211"></span> | 
 | <span class="source-line-no">8212</span><span id="line-8212">  /** Returns writeEntry associated with this append */</span> | 
 | <span class="source-line-no">8213</span><span id="line-8213">  private WriteEntry doWALAppend(WALEdit walEdit, BatchOperation<?> batchOp,</span> | 
 | <span class="source-line-no">8214</span><span id="line-8214">    MiniBatchOperationInProgress<Mutation> miniBatchOp, long now, NonceKey nonceKey)</span> | 
 | <span class="source-line-no">8215</span><span id="line-8215">    throws IOException {</span> | 
 | <span class="source-line-no">8216</span><span id="line-8216">    Preconditions.checkArgument(walEdit != null && !walEdit.isEmpty(), "WALEdit is null or empty!");</span> | 
 | <span class="source-line-no">8217</span><span id="line-8217">    Preconditions.checkArgument(</span> | 
 | <span class="source-line-no">8218</span><span id="line-8218">      !walEdit.isReplay() || batchOp.getOrigLogSeqNum() != SequenceId.NO_SEQUENCE_ID,</span> | 
 | <span class="source-line-no">8219</span><span id="line-8219">      "Invalid replay sequence Id for replay WALEdit!");</span> | 
 | <span class="source-line-no">8220</span><span id="line-8220"></span> | 
 | <span class="source-line-no">8221</span><span id="line-8221">    WALKeyImpl walKey = createWALKeyForWALAppend(walEdit.isReplay(), batchOp, now,</span> | 
 | <span class="source-line-no">8222</span><span id="line-8222">      nonceKey.getNonceGroup(), nonceKey.getNonce());</span> | 
 | <span class="source-line-no">8223</span><span id="line-8223">    // don't call the coproc hook for writes to the WAL caused by</span> | 
 | <span class="source-line-no">8224</span><span id="line-8224">    // system lifecycle events like flushes or compactions</span> | 
 | <span class="source-line-no">8225</span><span id="line-8225">    if (this.coprocessorHost != null && !walEdit.isMetaEdit()) {</span> | 
 | <span class="source-line-no">8226</span><span id="line-8226">      this.coprocessorHost.preWALAppend(walKey, walEdit);</span> | 
 | <span class="source-line-no">8227</span><span id="line-8227">    }</span> | 
 | <span class="source-line-no">8228</span><span id="line-8228">    try {</span> | 
 | <span class="source-line-no">8229</span><span id="line-8229">      long txid = this.wal.appendData(this.getRegionInfo(), walKey, walEdit);</span> | 
 | <span class="source-line-no">8230</span><span id="line-8230">      WriteEntry writeEntry = walKey.getWriteEntry();</span> | 
 | <span class="source-line-no">8231</span><span id="line-8231">      // Call sync on our edit.</span> | 
 | <span class="source-line-no">8232</span><span id="line-8232">      if (txid != 0) {</span> | 
 | <span class="source-line-no">8233</span><span id="line-8233">        sync(txid, batchOp.durability);</span> | 
 | <span class="source-line-no">8234</span><span id="line-8234">      }</span> | 
 | <span class="source-line-no">8235</span><span id="line-8235">      /**</span> | 
 | <span class="source-line-no">8236</span><span id="line-8236">       * If above {@link HRegion#sync} throws Exception, the RegionServer should be aborted and</span> | 
 | <span class="source-line-no">8237</span><span id="line-8237">       * following {@link BatchOperation#writeMiniBatchOperationsToMemStore} will not be executed,</span> | 
 | <span class="source-line-no">8238</span><span id="line-8238">       * so there is no need to replicate to secondary replica, for this reason here we attach the</span> | 
 | <span class="source-line-no">8239</span><span id="line-8239">       * region replication action after the {@link HRegion#sync} is successful.</span> | 
 | <span class="source-line-no">8240</span><span id="line-8240">       */</span> | 
 | <span class="source-line-no">8241</span><span id="line-8241">      this.attachRegionReplicationInWALAppend(batchOp, miniBatchOp, walKey, walEdit, writeEntry);</span> | 
 | <span class="source-line-no">8242</span><span id="line-8242">      return writeEntry;</span> | 
 | <span class="source-line-no">8243</span><span id="line-8243">    } catch (IOException ioe) {</span> | 
 | <span class="source-line-no">8244</span><span id="line-8244">      if (walKey.getWriteEntry() != null) {</span> | 
 | <span class="source-line-no">8245</span><span id="line-8245">        mvcc.complete(walKey.getWriteEntry());</span> | 
 | <span class="source-line-no">8246</span><span id="line-8246">      }</span> | 
 | <span class="source-line-no">8247</span><span id="line-8247"></span> | 
 | <span class="source-line-no">8248</span><span id="line-8248">      /**</span> | 
 | <span class="source-line-no">8249</span><span id="line-8249">       * If {@link WAL#sync} get a timeout exception, the only correct way is to abort the region</span> | 
 | <span class="source-line-no">8250</span><span id="line-8250">       * server, as the design of {@link WAL#sync}, is to succeed or die, there is no 'failure'. It</span> | 
 | <span class="source-line-no">8251</span><span id="line-8251">       * is usually not a big deal is because we set a very large default value(5 minutes) for</span> | 
 | <span class="source-line-no">8252</span><span id="line-8252">       * {@link AbstractFSWAL#WAL_SYNC_TIMEOUT_MS}, usually the WAL system will abort the region</span> | 
 | <span class="source-line-no">8253</span><span id="line-8253">       * server if it can not finish the sync within 5 minutes.</span> | 
 | <span class="source-line-no">8254</span><span id="line-8254">       */</span> | 
 | <span class="source-line-no">8255</span><span id="line-8255">      if (ioe instanceof WALSyncTimeoutIOException) {</span> | 
 | <span class="source-line-no">8256</span><span id="line-8256">        if (rsServices != null) {</span> | 
 | <span class="source-line-no">8257</span><span id="line-8257">          rsServices.abort("WAL sync timeout,forcing server shutdown", ioe);</span> | 
 | <span class="source-line-no">8258</span><span id="line-8258">        }</span> | 
 | <span class="source-line-no">8259</span><span id="line-8259">      }</span> | 
 | <span class="source-line-no">8260</span><span id="line-8260">      throw ioe;</span> | 
 | <span class="source-line-no">8261</span><span id="line-8261">    }</span> | 
 | <span class="source-line-no">8262</span><span id="line-8262">  }</span> | 
 | <span class="source-line-no">8263</span><span id="line-8263"></span> | 
 | <span class="source-line-no">8264</span><span id="line-8264">  /**</span> | 
 | <span class="source-line-no">8265</span><span id="line-8265">   * Attach {@link RegionReplicationSink#add} to the mvcc writeEntry for replicating to region</span> | 
 | <span class="source-line-no">8266</span><span id="line-8266">   * replica.</span> | 
 | <span class="source-line-no">8267</span><span id="line-8267">   */</span> | 
 | <span class="source-line-no">8268</span><span id="line-8268">  private void attachRegionReplicationInWALAppend(BatchOperation<?> batchOp,</span> | 
 | <span class="source-line-no">8269</span><span id="line-8269">    MiniBatchOperationInProgress<Mutation> miniBatchOp, WALKeyImpl walKey, WALEdit walEdit,</span> | 
 | <span class="source-line-no">8270</span><span id="line-8270">    WriteEntry writeEntry) {</span> | 
 | <span class="source-line-no">8271</span><span id="line-8271">    if (!regionReplicationSink.isPresent()) {</span> | 
 | <span class="source-line-no">8272</span><span id="line-8272">      return;</span> | 
 | <span class="source-line-no">8273</span><span id="line-8273">    }</span> | 
 | <span class="source-line-no">8274</span><span id="line-8274">    /**</span> | 
 | <span class="source-line-no">8275</span><span id="line-8275">     * If {@link HRegion#regionReplicationSink} is present,only {@link MutationBatchOperation} is</span> | 
 | <span class="source-line-no">8276</span><span id="line-8276">     * used and {@link NonceKey} is all the same for {@link Mutation}s in</span> | 
 | <span class="source-line-no">8277</span><span id="line-8277">     * {@link MutationBatchOperation},so for HBASE-26993 case 1,if</span> | 
 | <span class="source-line-no">8278</span><span id="line-8278">     * {@link MiniBatchOperationInProgress#getWalEditForReplicateSkipWAL} is not null and we could</span> | 
 | <span class="source-line-no">8279</span><span id="line-8279">     * enter {@link HRegion#doWALAppend},that means partial {@link Mutation}s are</span> | 
 | <span class="source-line-no">8280</span><span id="line-8280">     * {@link Durability#SKIP_WAL}, we use</span> | 
 | <span class="source-line-no">8281</span><span id="line-8281">     * {@link MiniBatchOperationInProgress#getWalEditForReplicateSkipWAL} to replicate to region</span> | 
 | <span class="source-line-no">8282</span><span id="line-8282">     * replica,but if {@link MiniBatchOperationInProgress#getWalEditForReplicateSkipWAL} is</span> | 
 | <span class="source-line-no">8283</span><span id="line-8283">     * null,that means there is no {@link Mutation} is {@link Durability#SKIP_WAL},so we just use</span> | 
 | <span class="source-line-no">8284</span><span id="line-8284">     * walEdit to replicate.</span> | 
 | <span class="source-line-no">8285</span><span id="line-8285">     */</span> | 
 | <span class="source-line-no">8286</span><span id="line-8286">    assert batchOp instanceof MutationBatchOperation;</span> | 
 | <span class="source-line-no">8287</span><span id="line-8287">    WALEdit walEditToUse = miniBatchOp.getWalEditForReplicateIfExistsSkipWAL();</span> | 
 | <span class="source-line-no">8288</span><span id="line-8288">    if (walEditToUse == null) {</span> | 
 | <span class="source-line-no">8289</span><span id="line-8289">      walEditToUse = walEdit;</span> | 
 | <span class="source-line-no">8290</span><span id="line-8290">    }</span> | 
 | <span class="source-line-no">8291</span><span id="line-8291">    doAttachReplicateRegionReplicaAction(walKey, walEditToUse, writeEntry);</span> | 
 | <span class="source-line-no">8292</span><span id="line-8292">  }</span> | 
 | <span class="source-line-no">8293</span><span id="line-8293"></span> | 
 | <span class="source-line-no">8294</span><span id="line-8294">  /**</span> | 
 | <span class="source-line-no">8295</span><span id="line-8295">   * Attach {@link RegionReplicationSink#add} to the mvcc writeEntry for replicating to region</span> | 
 | <span class="source-line-no">8296</span><span id="line-8296">   * replica.</span> | 
 | <span class="source-line-no">8297</span><span id="line-8297">   */</span> | 
 | <span class="source-line-no">8298</span><span id="line-8298">  private void doAttachReplicateRegionReplicaAction(WALKeyImpl walKey, WALEdit walEdit,</span> | 
 | <span class="source-line-no">8299</span><span id="line-8299">    WriteEntry writeEntry) {</span> | 
 | <span class="source-line-no">8300</span><span id="line-8300">    if (walEdit == null || walEdit.isEmpty()) {</span> | 
 | <span class="source-line-no">8301</span><span id="line-8301">      return;</span> | 
 | <span class="source-line-no">8302</span><span id="line-8302">    }</span> | 
 | <span class="source-line-no">8303</span><span id="line-8303">    final ServerCall<?> rpcCall = RpcServer.getCurrentServerCallWithCellScanner().orElse(null);</span> | 
 | <span class="source-line-no">8304</span><span id="line-8304">    regionReplicationSink.ifPresent(sink -> writeEntry.attachCompletionAction(() -> {</span> | 
 | <span class="source-line-no">8305</span><span id="line-8305">      sink.add(walKey, walEdit, rpcCall);</span> | 
 | <span class="source-line-no">8306</span><span id="line-8306">    }));</span> | 
 | <span class="source-line-no">8307</span><span id="line-8307">  }</span> | 
 | <span class="source-line-no">8308</span><span id="line-8308"></span> | 
 | <span class="source-line-no">8309</span><span id="line-8309">  public static final long FIXED_OVERHEAD = ClassSize.estimateBase(HRegion.class, false);</span> | 
 | <span class="source-line-no">8310</span><span id="line-8310"></span> | 
 | <span class="source-line-no">8311</span><span id="line-8311">  // woefully out of date - currently missing:</span> | 
 | <span class="source-line-no">8312</span><span id="line-8312">  // 1 x HashMap - coprocessorServiceHandlers</span> | 
 | <span class="source-line-no">8313</span><span id="line-8313">  // 6 x LongAdder - numMutationsWithoutWAL, dataInMemoryWithoutWAL,</span> | 
 | <span class="source-line-no">8314</span><span id="line-8314">  // checkAndMutateChecksPassed, checkAndMutateChecksFailed, readRequestsCount,</span> | 
 | <span class="source-line-no">8315</span><span id="line-8315">  // writeRequestsCount, cpRequestsCount</span> | 
 | <span class="source-line-no">8316</span><span id="line-8316">  // 1 x HRegion$WriteState - writestate</span> | 
 | <span class="source-line-no">8317</span><span id="line-8317">  // 1 x RegionCoprocessorHost - coprocessorHost</span> | 
 | <span class="source-line-no">8318</span><span id="line-8318">  // 1 x RegionSplitPolicy - splitPolicy</span> | 
 | <span class="source-line-no">8319</span><span id="line-8319">  // 1 x MetricsRegion - metricsRegion</span> | 
 | <span class="source-line-no">8320</span><span id="line-8320">  // 1 x MetricsRegionWrapperImpl - metricsRegionWrapper</span> | 
 | <span class="source-line-no">8321</span><span id="line-8321">  // 1 x ReadPointCalculationLock - smallestReadPointCalcLock</span> | 
 | <span class="source-line-no">8322</span><span id="line-8322">  public static final long DEEP_OVERHEAD = FIXED_OVERHEAD + ClassSize.OBJECT + // closeLock</span> | 
 | <span class="source-line-no">8323</span><span id="line-8323">    (2 * ClassSize.ATOMIC_BOOLEAN) + // closed, closing</span> | 
 | <span class="source-line-no">8324</span><span id="line-8324">    (3 * ClassSize.ATOMIC_LONG) + // numPutsWithoutWAL, dataInMemoryWithoutWAL,</span> | 
 | <span class="source-line-no">8325</span><span id="line-8325">                                  // compactionsFailed</span> | 
 | <span class="source-line-no">8326</span><span id="line-8326">    (3 * ClassSize.CONCURRENT_HASHMAP) + // lockedRows, scannerReadPoints, regionLockHolders</span> | 
 | <span class="source-line-no">8327</span><span id="line-8327">    WriteState.HEAP_SIZE + // writestate</span> | 
 | <span class="source-line-no">8328</span><span id="line-8328">    ClassSize.CONCURRENT_SKIPLISTMAP + ClassSize.CONCURRENT_SKIPLISTMAP_ENTRY + // stores</span> | 
 | <span class="source-line-no">8329</span><span id="line-8329">    (2 * ClassSize.REENTRANT_LOCK) + // lock, updatesLock</span> | 
 | <span class="source-line-no">8330</span><span id="line-8330">    MultiVersionConcurrencyControl.FIXED_SIZE // mvcc</span> | 
 | <span class="source-line-no">8331</span><span id="line-8331">    + 2 * ClassSize.TREEMAP // maxSeqIdInStores, replicationScopes</span> | 
 | <span class="source-line-no">8332</span><span id="line-8332">    + 2 * ClassSize.ATOMIC_INTEGER // majorInProgress, minorInProgress</span> | 
 | <span class="source-line-no">8333</span><span id="line-8333">    + ClassSize.STORE_SERVICES // store services</span> | 
 | <span class="source-line-no">8334</span><span id="line-8334">    + StoreHotnessProtector.FIXED_SIZE;</span> | 
 | <span class="source-line-no">8335</span><span id="line-8335"></span> | 
 | <span class="source-line-no">8336</span><span id="line-8336">  @Override</span> | 
 | <span class="source-line-no">8337</span><span id="line-8337">  public long heapSize() {</span> | 
 | <span class="source-line-no">8338</span><span id="line-8338">    // this does not take into account row locks, recent flushes, mvcc entries, and more</span> | 
 | <span class="source-line-no">8339</span><span id="line-8339">    return DEEP_OVERHEAD + stores.values().stream().mapToLong(HStore::heapSize).sum();</span> | 
 | <span class="source-line-no">8340</span><span id="line-8340">  }</span> | 
 | <span class="source-line-no">8341</span><span id="line-8341"></span> | 
 | <span class="source-line-no">8342</span><span id="line-8342">  /**</span> | 
 | <span class="source-line-no">8343</span><span id="line-8343">   * Registers a new protocol buffer {@link Service} subclass as a coprocessor endpoint to be</span> | 
 | <span class="source-line-no">8344</span><span id="line-8344">   * available for handling {@link #execService(RpcController, CoprocessorServiceCall)} calls.</span> | 
 | <span class="source-line-no">8345</span><span id="line-8345">   * <p/></span> | 
 | <span class="source-line-no">8346</span><span id="line-8346">   * Only a single instance may be registered per region for a given {@link Service} subclass (the</span> | 
 | <span class="source-line-no">8347</span><span id="line-8347">   * instances are keyed on {@link ServiceDescriptor#getFullName()}.. After the first registration,</span> | 
 | <span class="source-line-no">8348</span><span id="line-8348">   * subsequent calls with the same service name will fail with a return value of {@code false}.</span> | 
 | <span class="source-line-no">8349</span><span id="line-8349">   * @param instance the {@code Service} subclass instance to expose as a coprocessor endpoint</span> | 
 | <span class="source-line-no">8350</span><span id="line-8350">   * @return {@code true} if the registration was successful, {@code false} otherwise</span> | 
 | <span class="source-line-no">8351</span><span id="line-8351">   */</span> | 
 | <span class="source-line-no">8352</span><span id="line-8352">  public boolean registerService(Service instance) {</span> | 
 | <span class="source-line-no">8353</span><span id="line-8353">    // No stacking of instances is allowed for a single service name</span> | 
 | <span class="source-line-no">8354</span><span id="line-8354">    ServiceDescriptor serviceDesc = instance.getDescriptorForType();</span> | 
 | <span class="source-line-no">8355</span><span id="line-8355">    String serviceName = CoprocessorRpcUtils.getServiceName(serviceDesc);</span> | 
 | <span class="source-line-no">8356</span><span id="line-8356">    if (coprocessorServiceHandlers.containsKey(serviceName)) {</span> | 
 | <span class="source-line-no">8357</span><span id="line-8357">      LOG.error("Coprocessor service {} already registered, rejecting request from {} in region {}",</span> | 
 | <span class="source-line-no">8358</span><span id="line-8358">        serviceName, instance, this);</span> | 
 | <span class="source-line-no">8359</span><span id="line-8359">      return false;</span> | 
 | <span class="source-line-no">8360</span><span id="line-8360">    }</span> | 
 | <span class="source-line-no">8361</span><span id="line-8361"></span> | 
 | <span class="source-line-no">8362</span><span id="line-8362">    coprocessorServiceHandlers.put(serviceName, instance);</span> | 
 | <span class="source-line-no">8363</span><span id="line-8363">    if (LOG.isDebugEnabled()) {</span> | 
 | <span class="source-line-no">8364</span><span id="line-8364">      LOG.debug("Registered coprocessor service: region="</span> | 
 | <span class="source-line-no">8365</span><span id="line-8365">        + Bytes.toStringBinary(getRegionInfo().getRegionName()) + " service=" + serviceName);</span> | 
 | <span class="source-line-no">8366</span><span id="line-8366">    }</span> | 
 | <span class="source-line-no">8367</span><span id="line-8367">    return true;</span> | 
 | <span class="source-line-no">8368</span><span id="line-8368">  }</span> | 
 | <span class="source-line-no">8369</span><span id="line-8369"></span> | 
 | <span class="source-line-no">8370</span><span id="line-8370">  /**</span> | 
 | <span class="source-line-no">8371</span><span id="line-8371">   * Executes a single protocol buffer coprocessor endpoint {@link Service} method using the</span> | 
 | <span class="source-line-no">8372</span><span id="line-8372">   * registered protocol handlers. {@link Service} implementations must be registered via the</span> | 
 | <span class="source-line-no">8373</span><span id="line-8373">   * {@link #registerService(Service)} method before they are available.</span> | 
 | <span class="source-line-no">8374</span><span id="line-8374">   * @param controller an {@code RpcContoller} implementation to pass to the invoked service</span> | 
 | <span class="source-line-no">8375</span><span id="line-8375">   * @param call       a {@code CoprocessorServiceCall} instance identifying the service, method,</span> | 
 | <span class="source-line-no">8376</span><span id="line-8376">   *                   and parameters for the method invocation</span> | 
 | <span class="source-line-no">8377</span><span id="line-8377">   * @return a protocol buffer {@code Message} instance containing the method's result</span> | 
 | <span class="source-line-no">8378</span><span id="line-8378">   * @throws IOException if no registered service handler is found or an error occurs during the</span> | 
 | <span class="source-line-no">8379</span><span id="line-8379">   *                     invocation</span> | 
 | <span class="source-line-no">8380</span><span id="line-8380">   * @see #registerService(Service)</span> | 
 | <span class="source-line-no">8381</span><span id="line-8381">   */</span> | 
 | <span class="source-line-no">8382</span><span id="line-8382">  public Message execService(RpcController controller, CoprocessorServiceCall call)</span> | 
 | <span class="source-line-no">8383</span><span id="line-8383">    throws IOException {</span> | 
 | <span class="source-line-no">8384</span><span id="line-8384">    String serviceName = call.getServiceName();</span> | 
 | <span class="source-line-no">8385</span><span id="line-8385">    Service service = coprocessorServiceHandlers.get(serviceName);</span> | 
 | <span class="source-line-no">8386</span><span id="line-8386">    if (service == null) {</span> | 
 | <span class="source-line-no">8387</span><span id="line-8387">      throw new UnknownProtocolException(null, "No registered coprocessor service found for "</span> | 
 | <span class="source-line-no">8388</span><span id="line-8388">        + serviceName + " in region " + Bytes.toStringBinary(getRegionInfo().getRegionName()));</span> | 
 | <span class="source-line-no">8389</span><span id="line-8389">    }</span> | 
 | <span class="source-line-no">8390</span><span id="line-8390">    ServiceDescriptor serviceDesc = service.getDescriptorForType();</span> | 
 | <span class="source-line-no">8391</span><span id="line-8391"></span> | 
 | <span class="source-line-no">8392</span><span id="line-8392">    cpRequestsCount.increment();</span> | 
 | <span class="source-line-no">8393</span><span id="line-8393">    String methodName = call.getMethodName();</span> | 
 | <span class="source-line-no">8394</span><span id="line-8394">    MethodDescriptor methodDesc = CoprocessorRpcUtils.getMethodDescriptor(methodName, serviceDesc);</span> | 
 | <span class="source-line-no">8395</span><span id="line-8395"></span> | 
 | <span class="source-line-no">8396</span><span id="line-8396">    Message.Builder builder = service.getRequestPrototype(methodDesc).newBuilderForType();</span> | 
 | <span class="source-line-no">8397</span><span id="line-8397"></span> | 
 | <span class="source-line-no">8398</span><span id="line-8398">    ProtobufUtil.mergeFrom(builder, call.getRequest().toByteArray());</span> | 
 | <span class="source-line-no">8399</span><span id="line-8399">    Message request = CoprocessorRpcUtils.getRequest(service, methodDesc, call.getRequest());</span> | 
 | <span class="source-line-no">8400</span><span id="line-8400"></span> | 
 | <span class="source-line-no">8401</span><span id="line-8401">    if (coprocessorHost != null) {</span> | 
 | <span class="source-line-no">8402</span><span id="line-8402">      request = coprocessorHost.preEndpointInvocation(service, methodName, request);</span> | 
 | <span class="source-line-no">8403</span><span id="line-8403">    }</span> | 
 | <span class="source-line-no">8404</span><span id="line-8404"></span> | 
 | <span class="source-line-no">8405</span><span id="line-8405">    final Message.Builder responseBuilder =</span> | 
 | <span class="source-line-no">8406</span><span id="line-8406">      service.getResponsePrototype(methodDesc).newBuilderForType();</span> | 
 | <span class="source-line-no">8407</span><span id="line-8407">    service.callMethod(methodDesc, controller, request, new RpcCallback<Message>() {</span> | 
 | <span class="source-line-no">8408</span><span id="line-8408">      @Override</span> | 
 | <span class="source-line-no">8409</span><span id="line-8409">      public void run(Message message) {</span> | 
 | <span class="source-line-no">8410</span><span id="line-8410">        if (message != null) {</span> | 
 | <span class="source-line-no">8411</span><span id="line-8411">          responseBuilder.mergeFrom(message);</span> | 
 | <span class="source-line-no">8412</span><span id="line-8412">        }</span> | 
 | <span class="source-line-no">8413</span><span id="line-8413">      }</span> | 
 | <span class="source-line-no">8414</span><span id="line-8414">    });</span> | 
 | <span class="source-line-no">8415</span><span id="line-8415"></span> | 
 | <span class="source-line-no">8416</span><span id="line-8416">    if (coprocessorHost != null) {</span> | 
 | <span class="source-line-no">8417</span><span id="line-8417">      coprocessorHost.postEndpointInvocation(service, methodName, request, responseBuilder);</span> | 
 | <span class="source-line-no">8418</span><span id="line-8418">    }</span> | 
 | <span class="source-line-no">8419</span><span id="line-8419">    IOException exception =</span> | 
 | <span class="source-line-no">8420</span><span id="line-8420">      org.apache.hadoop.hbase.ipc.CoprocessorRpcUtils.getControllerException(controller);</span> | 
 | <span class="source-line-no">8421</span><span id="line-8421">    if (exception != null) {</span> | 
 | <span class="source-line-no">8422</span><span id="line-8422">      throw exception;</span> | 
 | <span class="source-line-no">8423</span><span id="line-8423">    }</span> | 
 | <span class="source-line-no">8424</span><span id="line-8424"></span> | 
 | <span class="source-line-no">8425</span><span id="line-8425">    return responseBuilder.build();</span> | 
 | <span class="source-line-no">8426</span><span id="line-8426">  }</span> | 
 | <span class="source-line-no">8427</span><span id="line-8427"></span> | 
 | <span class="source-line-no">8428</span><span id="line-8428">  public Optional<byte[]> checkSplit() {</span> | 
 | <span class="source-line-no">8429</span><span id="line-8429">    return checkSplit(false);</span> | 
 | <span class="source-line-no">8430</span><span id="line-8430">  }</span> | 
 | <span class="source-line-no">8431</span><span id="line-8431"></span> | 
 | <span class="source-line-no">8432</span><span id="line-8432">  /**</span> | 
 | <span class="source-line-no">8433</span><span id="line-8433">   * Return the split point. An empty result indicates the region isn't splittable.</span> | 
 | <span class="source-line-no">8434</span><span id="line-8434">   */</span> | 
 | <span class="source-line-no">8435</span><span id="line-8435">  public Optional<byte[]> checkSplit(boolean force) {</span> | 
 | <span class="source-line-no">8436</span><span id="line-8436">    // Can't split META</span> | 
 | <span class="source-line-no">8437</span><span id="line-8437">    if (this.getRegionInfo().isMetaRegion()) {</span> | 
 | <span class="source-line-no">8438</span><span id="line-8438">      return Optional.empty();</span> | 
 | <span class="source-line-no">8439</span><span id="line-8439">    }</span> | 
 | <span class="source-line-no">8440</span><span id="line-8440"></span> | 
 | <span class="source-line-no">8441</span><span id="line-8441">    // Can't split a region that is closing.</span> | 
 | <span class="source-line-no">8442</span><span id="line-8442">    if (this.isClosing()) {</span> | 
 | <span class="source-line-no">8443</span><span id="line-8443">      return Optional.empty();</span> | 
 | <span class="source-line-no">8444</span><span id="line-8444">    }</span> | 
 | <span class="source-line-no">8445</span><span id="line-8445"></span> | 
 | <span class="source-line-no">8446</span><span id="line-8446">    if (!force && !splitPolicy.shouldSplit()) {</span> | 
 | <span class="source-line-no">8447</span><span id="line-8447">      return Optional.empty();</span> | 
 | <span class="source-line-no">8448</span><span id="line-8448">    }</span> | 
 | <span class="source-line-no">8449</span><span id="line-8449"></span> | 
 | <span class="source-line-no">8450</span><span id="line-8450">    byte[] ret = splitPolicy.getSplitPoint();</span> | 
 | <span class="source-line-no">8451</span><span id="line-8451">    if (ret != null && ret.length > 0) {</span> | 
 | <span class="source-line-no">8452</span><span id="line-8452">      ret = splitRestriction.getRestrictedSplitPoint(ret);</span> | 
 | <span class="source-line-no">8453</span><span id="line-8453">    }</span> | 
 | <span class="source-line-no">8454</span><span id="line-8454"></span> | 
 | <span class="source-line-no">8455</span><span id="line-8455">    if (ret != null) {</span> | 
 | <span class="source-line-no">8456</span><span id="line-8456">      try {</span> | 
 | <span class="source-line-no">8457</span><span id="line-8457">        checkRow(ret, "calculated split");</span> | 
 | <span class="source-line-no">8458</span><span id="line-8458">      } catch (IOException e) {</span> | 
 | <span class="source-line-no">8459</span><span id="line-8459">        LOG.error("Ignoring invalid split for region {}", this, e);</span> | 
 | <span class="source-line-no">8460</span><span id="line-8460">        return Optional.empty();</span> | 
 | <span class="source-line-no">8461</span><span id="line-8461">      }</span> | 
 | <span class="source-line-no">8462</span><span id="line-8462">      return Optional.of(ret);</span> | 
 | <span class="source-line-no">8463</span><span id="line-8463">    } else {</span> | 
 | <span class="source-line-no">8464</span><span id="line-8464">      return Optional.empty();</span> | 
 | <span class="source-line-no">8465</span><span id="line-8465">    }</span> | 
 | <span class="source-line-no">8466</span><span id="line-8466">  }</span> | 
 | <span class="source-line-no">8467</span><span id="line-8467"></span> | 
 | <span class="source-line-no">8468</span><span id="line-8468">  /** Returns The priority that this region should have in the compaction queue */</span> | 
 | <span class="source-line-no">8469</span><span id="line-8469">  public int getCompactPriority() {</span> | 
 | <span class="source-line-no">8470</span><span id="line-8470">    if (checkSplit().isPresent() && conf.getBoolean(SPLIT_IGNORE_BLOCKING_ENABLED_KEY, false)) {</span> | 
 | <span class="source-line-no">8471</span><span id="line-8471">      // if a region should split, split it before compact</span> | 
 | <span class="source-line-no">8472</span><span id="line-8472">      return Store.PRIORITY_USER;</span> | 
 | <span class="source-line-no">8473</span><span id="line-8473">    }</span> | 
 | <span class="source-line-no">8474</span><span id="line-8474">    return stores.values().stream().mapToInt(HStore::getCompactPriority).min()</span> | 
 | <span class="source-line-no">8475</span><span id="line-8475">      .orElse(Store.NO_PRIORITY);</span> | 
 | <span class="source-line-no">8476</span><span id="line-8476">  }</span> | 
 | <span class="source-line-no">8477</span><span id="line-8477"></span> | 
 | <span class="source-line-no">8478</span><span id="line-8478">  /** Returns the coprocessor host */</span> | 
 | <span class="source-line-no">8479</span><span id="line-8479">  public RegionCoprocessorHost getCoprocessorHost() {</span> | 
 | <span class="source-line-no">8480</span><span id="line-8480">    return coprocessorHost;</span> | 
 | <span class="source-line-no">8481</span><span id="line-8481">  }</span> | 
 | <span class="source-line-no">8482</span><span id="line-8482"></span> | 
 | <span class="source-line-no">8483</span><span id="line-8483">  /** @param coprocessorHost the new coprocessor host */</span> | 
 | <span class="source-line-no">8484</span><span id="line-8484">  public void setCoprocessorHost(final RegionCoprocessorHost coprocessorHost) {</span> | 
 | <span class="source-line-no">8485</span><span id="line-8485">    this.coprocessorHost = coprocessorHost;</span> | 
 | <span class="source-line-no">8486</span><span id="line-8486">  }</span> | 
 | <span class="source-line-no">8487</span><span id="line-8487"></span> | 
 | <span class="source-line-no">8488</span><span id="line-8488">  @Override</span> | 
 | <span class="source-line-no">8489</span><span id="line-8489">  public void startRegionOperation() throws IOException {</span> | 
 | <span class="source-line-no">8490</span><span id="line-8490">    startRegionOperation(Operation.ANY);</span> | 
 | <span class="source-line-no">8491</span><span id="line-8491">  }</span> | 
 | <span class="source-line-no">8492</span><span id="line-8492"></span> | 
 | <span class="source-line-no">8493</span><span id="line-8493">  @Override</span> | 
 | <span class="source-line-no">8494</span><span id="line-8494">  public void startRegionOperation(Operation op) throws IOException {</span> | 
 | <span class="source-line-no">8495</span><span id="line-8495">    boolean isInterruptableOp = false;</span> | 
 | <span class="source-line-no">8496</span><span id="line-8496">    switch (op) {</span> | 
 | <span class="source-line-no">8497</span><span id="line-8497">      case GET: // interruptible read operations</span> | 
 | <span class="source-line-no">8498</span><span id="line-8498">      case SCAN:</span> | 
 | <span class="source-line-no">8499</span><span id="line-8499">        isInterruptableOp = true;</span> | 
 | <span class="source-line-no">8500</span><span id="line-8500">        checkReadsEnabled();</span> | 
 | <span class="source-line-no">8501</span><span id="line-8501">        break;</span> | 
 | <span class="source-line-no">8502</span><span id="line-8502">      case INCREMENT: // interruptible write operations</span> | 
 | <span class="source-line-no">8503</span><span id="line-8503">      case APPEND:</span> | 
 | <span class="source-line-no">8504</span><span id="line-8504">      case PUT:</span> | 
 | <span class="source-line-no">8505</span><span id="line-8505">      case DELETE:</span> | 
 | <span class="source-line-no">8506</span><span id="line-8506">      case BATCH_MUTATE:</span> | 
 | <span class="source-line-no">8507</span><span id="line-8507">      case CHECK_AND_MUTATE:</span> | 
 | <span class="source-line-no">8508</span><span id="line-8508">        isInterruptableOp = true;</span> | 
 | <span class="source-line-no">8509</span><span id="line-8509">        break;</span> | 
 | <span class="source-line-no">8510</span><span id="line-8510">      default: // all others</span> | 
 | <span class="source-line-no">8511</span><span id="line-8511">        break;</span> | 
 | <span class="source-line-no">8512</span><span id="line-8512">    }</span> | 
 | <span class="source-line-no">8513</span><span id="line-8513">    if (</span> | 
 | <span class="source-line-no">8514</span><span id="line-8514">      op == Operation.MERGE_REGION || op == Operation.SPLIT_REGION || op == Operation.COMPACT_REGION</span> | 
 | <span class="source-line-no">8515</span><span id="line-8515">        || op == Operation.COMPACT_SWITCH</span> | 
 | <span class="source-line-no">8516</span><span id="line-8516">    ) {</span> | 
 | <span class="source-line-no">8517</span><span id="line-8517">      // split, merge or compact region doesn't need to check the closing/closed state or lock the</span> | 
 | <span class="source-line-no">8518</span><span id="line-8518">      // region</span> | 
 | <span class="source-line-no">8519</span><span id="line-8519">      return;</span> | 
 | <span class="source-line-no">8520</span><span id="line-8520">    }</span> | 
 | <span class="source-line-no">8521</span><span id="line-8521">    if (this.closing.get()) {</span> | 
 | <span class="source-line-no">8522</span><span id="line-8522">      throw new NotServingRegionException(getRegionInfo().getRegionNameAsString() + " is closing");</span> | 
 | <span class="source-line-no">8523</span><span id="line-8523">    }</span> | 
 | <span class="source-line-no">8524</span><span id="line-8524">    lock(lock.readLock());</span> | 
 | <span class="source-line-no">8525</span><span id="line-8525">    // Update regionLockHolders ONLY for any startRegionOperation call that is invoked from</span> | 
 | <span class="source-line-no">8526</span><span id="line-8526">    // an RPC handler</span> | 
 | <span class="source-line-no">8527</span><span id="line-8527">    Thread thisThread = Thread.currentThread();</span> | 
 | <span class="source-line-no">8528</span><span id="line-8528">    if (isInterruptableOp) {</span> | 
 | <span class="source-line-no">8529</span><span id="line-8529">      regionLockHolders.put(thisThread, true);</span> | 
 | <span class="source-line-no">8530</span><span id="line-8530">    }</span> | 
 | <span class="source-line-no">8531</span><span id="line-8531">    if (this.closed.get()) {</span> | 
 | <span class="source-line-no">8532</span><span id="line-8532">      lock.readLock().unlock();</span> | 
 | <span class="source-line-no">8533</span><span id="line-8533">      throw new NotServingRegionException(getRegionInfo().getRegionNameAsString() + " is closed");</span> | 
 | <span class="source-line-no">8534</span><span id="line-8534">    }</span> | 
 | <span class="source-line-no">8535</span><span id="line-8535">    // The unit for snapshot is a region. So, all stores for this region must be</span> | 
 | <span class="source-line-no">8536</span><span id="line-8536">    // prepared for snapshot operation before proceeding.</span> | 
 | <span class="source-line-no">8537</span><span id="line-8537">    if (op == Operation.SNAPSHOT) {</span> | 
 | <span class="source-line-no">8538</span><span id="line-8538">      stores.values().forEach(HStore::preSnapshotOperation);</span> | 
 | <span class="source-line-no">8539</span><span id="line-8539">    }</span> | 
 | <span class="source-line-no">8540</span><span id="line-8540">    try {</span> | 
 | <span class="source-line-no">8541</span><span id="line-8541">      if (coprocessorHost != null) {</span> | 
 | <span class="source-line-no">8542</span><span id="line-8542">        coprocessorHost.postStartRegionOperation(op);</span> | 
 | <span class="source-line-no">8543</span><span id="line-8543">      }</span> | 
 | <span class="source-line-no">8544</span><span id="line-8544">    } catch (Exception e) {</span> | 
 | <span class="source-line-no">8545</span><span id="line-8545">      if (isInterruptableOp) {</span> | 
 | <span class="source-line-no">8546</span><span id="line-8546">        // would be harmless to remove what we didn't add but we know by 'isInterruptableOp'</span> | 
 | <span class="source-line-no">8547</span><span id="line-8547">        // if we added this thread to regionLockHolders</span> | 
 | <span class="source-line-no">8548</span><span id="line-8548">        regionLockHolders.remove(thisThread);</span> | 
 | <span class="source-line-no">8549</span><span id="line-8549">      }</span> | 
 | <span class="source-line-no">8550</span><span id="line-8550">      lock.readLock().unlock();</span> | 
 | <span class="source-line-no">8551</span><span id="line-8551">      throw new IOException(e);</span> | 
 | <span class="source-line-no">8552</span><span id="line-8552">    }</span> | 
 | <span class="source-line-no">8553</span><span id="line-8553">  }</span> | 
 | <span class="source-line-no">8554</span><span id="line-8554"></span> | 
 | <span class="source-line-no">8555</span><span id="line-8555">  @Override</span> | 
 | <span class="source-line-no">8556</span><span id="line-8556">  public void closeRegionOperation() throws IOException {</span> | 
 | <span class="source-line-no">8557</span><span id="line-8557">    closeRegionOperation(Operation.ANY);</span> | 
 | <span class="source-line-no">8558</span><span id="line-8558">  }</span> | 
 | <span class="source-line-no">8559</span><span id="line-8559"></span> | 
 | <span class="source-line-no">8560</span><span id="line-8560">  @Override</span> | 
 | <span class="source-line-no">8561</span><span id="line-8561">  public void closeRegionOperation(Operation operation) throws IOException {</span> | 
 | <span class="source-line-no">8562</span><span id="line-8562">    if (operation == Operation.SNAPSHOT) {</span> | 
 | <span class="source-line-no">8563</span><span id="line-8563">      stores.values().forEach(HStore::postSnapshotOperation);</span> | 
 | <span class="source-line-no">8564</span><span id="line-8564">    }</span> | 
 | <span class="source-line-no">8565</span><span id="line-8565">    Thread thisThread = Thread.currentThread();</span> | 
 | <span class="source-line-no">8566</span><span id="line-8566">    regionLockHolders.remove(thisThread);</span> | 
 | <span class="source-line-no">8567</span><span id="line-8567">    lock.readLock().unlock();</span> | 
 | <span class="source-line-no">8568</span><span id="line-8568">    if (coprocessorHost != null) {</span> | 
 | <span class="source-line-no">8569</span><span id="line-8569">      coprocessorHost.postCloseRegionOperation(operation);</span> | 
 | <span class="source-line-no">8570</span><span id="line-8570">    }</span> | 
 | <span class="source-line-no">8571</span><span id="line-8571">  }</span> | 
 | <span class="source-line-no">8572</span><span id="line-8572"></span> | 
 | <span class="source-line-no">8573</span><span id="line-8573">  /**</span> | 
 | <span class="source-line-no">8574</span><span id="line-8574">   * This method needs to be called before any public call that reads or modifies stores in bulk. It</span> | 
 | <span class="source-line-no">8575</span><span id="line-8575">   * has to be called just before a try. #closeBulkRegionOperation needs to be called in the try's</span> | 
 | <span class="source-line-no">8576</span><span id="line-8576">   * finally block Acquires a writelock and checks if the region is closing or closed.</span> | 
 | <span class="source-line-no">8577</span><span id="line-8577">   * @throws NotServingRegionException when the region is closing or closed</span> | 
 | <span class="source-line-no">8578</span><span id="line-8578">   * @throws RegionTooBusyException    if failed to get the lock in time</span> | 
 | <span class="source-line-no">8579</span><span id="line-8579">   * @throws InterruptedIOException    if interrupted while waiting for a lock</span> | 
 | <span class="source-line-no">8580</span><span id="line-8580">   */</span> | 
 | <span class="source-line-no">8581</span><span id="line-8581">  private void startBulkRegionOperation(boolean writeLockNeeded) throws IOException {</span> | 
 | <span class="source-line-no">8582</span><span id="line-8582">    if (this.closing.get()) {</span> | 
 | <span class="source-line-no">8583</span><span id="line-8583">      throw new NotServingRegionException(getRegionInfo().getRegionNameAsString() + " is closing");</span> | 
 | <span class="source-line-no">8584</span><span id="line-8584">    }</span> | 
 | <span class="source-line-no">8585</span><span id="line-8585">    if (writeLockNeeded) lock(lock.writeLock());</span> | 
 | <span class="source-line-no">8586</span><span id="line-8586">    else lock(lock.readLock());</span> | 
 | <span class="source-line-no">8587</span><span id="line-8587">    if (this.closed.get()) {</span> | 
 | <span class="source-line-no">8588</span><span id="line-8588">      if (writeLockNeeded) lock.writeLock().unlock();</span> | 
 | <span class="source-line-no">8589</span><span id="line-8589">      else lock.readLock().unlock();</span> | 
 | <span class="source-line-no">8590</span><span id="line-8590">      throw new NotServingRegionException(getRegionInfo().getRegionNameAsString() + " is closed");</span> | 
 | <span class="source-line-no">8591</span><span id="line-8591">    }</span> | 
 | <span class="source-line-no">8592</span><span id="line-8592">    regionLockHolders.put(Thread.currentThread(), true);</span> | 
 | <span class="source-line-no">8593</span><span id="line-8593">  }</span> | 
 | <span class="source-line-no">8594</span><span id="line-8594"></span> | 
 | <span class="source-line-no">8595</span><span id="line-8595">  /**</span> | 
 | <span class="source-line-no">8596</span><span id="line-8596">   * Closes the lock. This needs to be called in the finally block corresponding to the try block of</span> | 
 | <span class="source-line-no">8597</span><span id="line-8597">   * #startRegionOperation</span> | 
 | <span class="source-line-no">8598</span><span id="line-8598">   */</span> | 
 | <span class="source-line-no">8599</span><span id="line-8599">  private void closeBulkRegionOperation() {</span> | 
 | <span class="source-line-no">8600</span><span id="line-8600">    regionLockHolders.remove(Thread.currentThread());</span> | 
 | <span class="source-line-no">8601</span><span id="line-8601">    if (lock.writeLock().isHeldByCurrentThread()) lock.writeLock().unlock();</span> | 
 | <span class="source-line-no">8602</span><span id="line-8602">    else lock.readLock().unlock();</span> | 
 | <span class="source-line-no">8603</span><span id="line-8603">  }</span> | 
 | <span class="source-line-no">8604</span><span id="line-8604"></span> | 
 | <span class="source-line-no">8605</span><span id="line-8605">  /**</span> | 
 | <span class="source-line-no">8606</span><span id="line-8606">   * Update LongAdders for number of puts without wal and the size of possible data loss. These</span> | 
 | <span class="source-line-no">8607</span><span id="line-8607">   * information are exposed by the region server metrics.</span> | 
 | <span class="source-line-no">8608</span><span id="line-8608">   */</span> | 
 | <span class="source-line-no">8609</span><span id="line-8609">  private void recordMutationWithoutWal(final Map<byte[], List<Cell>> familyMap) {</span> | 
 | <span class="source-line-no">8610</span><span id="line-8610">    numMutationsWithoutWAL.increment();</span> | 
 | <span class="source-line-no">8611</span><span id="line-8611">    if (numMutationsWithoutWAL.sum() <= 1) {</span> | 
 | <span class="source-line-no">8612</span><span id="line-8612">      LOG.info("writing data to region " + this</span> | 
 | <span class="source-line-no">8613</span><span id="line-8613">        + " with WAL disabled. Data may be lost in the event of a crash.");</span> | 
 | <span class="source-line-no">8614</span><span id="line-8614">    }</span> | 
 | <span class="source-line-no">8615</span><span id="line-8615"></span> | 
 | <span class="source-line-no">8616</span><span id="line-8616">    long mutationSize = 0;</span> | 
 | <span class="source-line-no">8617</span><span id="line-8617">    for (List<Cell> cells : familyMap.values()) {</span> | 
 | <span class="source-line-no">8618</span><span id="line-8618">      // Optimization: 'foreach' loop is not used. See:</span> | 
 | <span class="source-line-no">8619</span><span id="line-8619">      // HBASE-12023 HRegion.applyFamilyMapToMemstore creates too many iterator objects</span> | 
 | <span class="source-line-no">8620</span><span id="line-8620">      assert cells instanceof RandomAccess;</span> | 
 | <span class="source-line-no">8621</span><span id="line-8621">      int listSize = cells.size();</span> | 
 | <span class="source-line-no">8622</span><span id="line-8622">      for (int i = 0; i < listSize; i++) {</span> | 
 | <span class="source-line-no">8623</span><span id="line-8623">        Cell cell = cells.get(i);</span> | 
 | <span class="source-line-no">8624</span><span id="line-8624">        mutationSize += cell.getSerializedSize();</span> | 
 | <span class="source-line-no">8625</span><span id="line-8625">      }</span> | 
 | <span class="source-line-no">8626</span><span id="line-8626">    }</span> | 
 | <span class="source-line-no">8627</span><span id="line-8627"></span> | 
 | <span class="source-line-no">8628</span><span id="line-8628">    dataInMemoryWithoutWAL.add(mutationSize);</span> | 
 | <span class="source-line-no">8629</span><span id="line-8629">  }</span> | 
 | <span class="source-line-no">8630</span><span id="line-8630"></span> | 
 | <span class="source-line-no">8631</span><span id="line-8631">  private void lock(final Lock lock) throws IOException {</span> | 
 | <span class="source-line-no">8632</span><span id="line-8632">    lock(lock, 1);</span> | 
 | <span class="source-line-no">8633</span><span id="line-8633">  }</span> | 
 | <span class="source-line-no">8634</span><span id="line-8634"></span> | 
 | <span class="source-line-no">8635</span><span id="line-8635">  /**</span> | 
 | <span class="source-line-no">8636</span><span id="line-8636">   * Try to acquire a lock. Throw RegionTooBusyException if failed to get the lock in time. Throw</span> | 
 | <span class="source-line-no">8637</span><span id="line-8637">   * InterruptedIOException if interrupted while waiting for the lock.</span> | 
 | <span class="source-line-no">8638</span><span id="line-8638">   */</span> | 
 | <span class="source-line-no">8639</span><span id="line-8639">  private void lock(final Lock lock, final int multiplier) throws IOException {</span> | 
 | <span class="source-line-no">8640</span><span id="line-8640">    try {</span> | 
 | <span class="source-line-no">8641</span><span id="line-8641">      final long waitTime = Math.min(maxBusyWaitDuration,</span> | 
 | <span class="source-line-no">8642</span><span id="line-8642">        busyWaitDuration * Math.min(multiplier, maxBusyWaitMultiplier));</span> | 
 | <span class="source-line-no">8643</span><span id="line-8643">      if (!lock.tryLock(waitTime, TimeUnit.MILLISECONDS)) {</span> | 
 | <span class="source-line-no">8644</span><span id="line-8644">        // Don't print millis. Message is used as a key over in</span> | 
 | <span class="source-line-no">8645</span><span id="line-8645">        // RetriesExhaustedWithDetailsException processing.</span> | 
 | <span class="source-line-no">8646</span><span id="line-8646">        final String regionName =</span> | 
 | <span class="source-line-no">8647</span><span id="line-8647">          this.getRegionInfo() == null ? "unknown" : this.getRegionInfo().getRegionNameAsString();</span> | 
 | <span class="source-line-no">8648</span><span id="line-8648">        final String serverName = this.getRegionServerServices() == null</span> | 
 | <span class="source-line-no">8649</span><span id="line-8649">          ? "unknown"</span> | 
 | <span class="source-line-no">8650</span><span id="line-8650">          : (this.getRegionServerServices().getServerName() == null</span> | 
 | <span class="source-line-no">8651</span><span id="line-8651">            ? "unknown"</span> | 
 | <span class="source-line-no">8652</span><span id="line-8652">            : this.getRegionServerServices().getServerName().toString());</span> | 
 | <span class="source-line-no">8653</span><span id="line-8653">        RegionTooBusyException rtbe = new RegionTooBusyException(</span> | 
 | <span class="source-line-no">8654</span><span id="line-8654">          "Failed to obtain lock; regionName=" + regionName + ", server=" + serverName);</span> | 
 | <span class="source-line-no">8655</span><span id="line-8655">        LOG.warn("Region is too busy to allow lock acquisition.", rtbe);</span> | 
 | <span class="source-line-no">8656</span><span id="line-8656">        throw rtbe;</span> | 
 | <span class="source-line-no">8657</span><span id="line-8657">      }</span> | 
 | <span class="source-line-no">8658</span><span id="line-8658">    } catch (InterruptedException ie) {</span> | 
 | <span class="source-line-no">8659</span><span id="line-8659">      if (LOG.isDebugEnabled()) {</span> | 
 | <span class="source-line-no">8660</span><span id="line-8660">        LOG.debug("Interrupted while waiting for a lock in region {}", this);</span> | 
 | <span class="source-line-no">8661</span><span id="line-8661">      }</span> | 
 | <span class="source-line-no">8662</span><span id="line-8662">      throw throwOnInterrupt(ie);</span> | 
 | <span class="source-line-no">8663</span><span id="line-8663">    }</span> | 
 | <span class="source-line-no">8664</span><span id="line-8664">  }</span> | 
 | <span class="source-line-no">8665</span><span id="line-8665"></span> | 
 | <span class="source-line-no">8666</span><span id="line-8666">  /**</span> | 
 | <span class="source-line-no">8667</span><span id="line-8667">   * Calls sync with the given transaction ID</span> | 
 | <span class="source-line-no">8668</span><span id="line-8668">   * @param txid should sync up to which transaction</span> | 
 | <span class="source-line-no">8669</span><span id="line-8669">   * @throws IOException If anything goes wrong with DFS</span> | 
 | <span class="source-line-no">8670</span><span id="line-8670">   */</span> | 
 | <span class="source-line-no">8671</span><span id="line-8671">  private void sync(long txid, Durability durability) throws IOException {</span> | 
 | <span class="source-line-no">8672</span><span id="line-8672">    if (this.getRegionInfo().isMetaRegion()) {</span> | 
 | <span class="source-line-no">8673</span><span id="line-8673">      this.wal.sync(txid);</span> | 
 | <span class="source-line-no">8674</span><span id="line-8674">    } else {</span> | 
 | <span class="source-line-no">8675</span><span id="line-8675">      switch (durability) {</span> | 
 | <span class="source-line-no">8676</span><span id="line-8676">        case USE_DEFAULT:</span> | 
 | <span class="source-line-no">8677</span><span id="line-8677">          // do what table defaults to</span> | 
 | <span class="source-line-no">8678</span><span id="line-8678">          if (shouldSyncWAL()) {</span> | 
 | <span class="source-line-no">8679</span><span id="line-8679">            this.wal.sync(txid);</span> | 
 | <span class="source-line-no">8680</span><span id="line-8680">          }</span> | 
 | <span class="source-line-no">8681</span><span id="line-8681">          break;</span> | 
 | <span class="source-line-no">8682</span><span id="line-8682">        case SKIP_WAL:</span> | 
 | <span class="source-line-no">8683</span><span id="line-8683">          // nothing do to</span> | 
 | <span class="source-line-no">8684</span><span id="line-8684">          break;</span> | 
 | <span class="source-line-no">8685</span><span id="line-8685">        case ASYNC_WAL:</span> | 
 | <span class="source-line-no">8686</span><span id="line-8686">          // nothing do to</span> | 
 | <span class="source-line-no">8687</span><span id="line-8687">          break;</span> | 
 | <span class="source-line-no">8688</span><span id="line-8688">        case SYNC_WAL:</span> | 
 | <span class="source-line-no">8689</span><span id="line-8689">          this.wal.sync(txid, false);</span> | 
 | <span class="source-line-no">8690</span><span id="line-8690">          break;</span> | 
 | <span class="source-line-no">8691</span><span id="line-8691">        case FSYNC_WAL:</span> | 
 | <span class="source-line-no">8692</span><span id="line-8692">          this.wal.sync(txid, true);</span> | 
 | <span class="source-line-no">8693</span><span id="line-8693">          break;</span> | 
 | <span class="source-line-no">8694</span><span id="line-8694">        default:</span> | 
 | <span class="source-line-no">8695</span><span id="line-8695">          throw new RuntimeException("Unknown durability " + durability);</span> | 
 | <span class="source-line-no">8696</span><span id="line-8696">      }</span> | 
 | <span class="source-line-no">8697</span><span id="line-8697">    }</span> | 
 | <span class="source-line-no">8698</span><span id="line-8698">  }</span> | 
 | <span class="source-line-no">8699</span><span id="line-8699"></span> | 
 | <span class="source-line-no">8700</span><span id="line-8700">  /**</span> | 
 | <span class="source-line-no">8701</span><span id="line-8701">   * Check whether we should sync the wal from the table's durability settings</span> | 
 | <span class="source-line-no">8702</span><span id="line-8702">   */</span> | 
 | <span class="source-line-no">8703</span><span id="line-8703">  private boolean shouldSyncWAL() {</span> | 
 | <span class="source-line-no">8704</span><span id="line-8704">    return regionDurability.ordinal() > Durability.ASYNC_WAL.ordinal();</span> | 
 | <span class="source-line-no">8705</span><span id="line-8705">  }</span> | 
 | <span class="source-line-no">8706</span><span id="line-8706"></span> | 
 | <span class="source-line-no">8707</span><span id="line-8707">  /** Returns the latest sequence number that was read from storage when this region was opened */</span> | 
 | <span class="source-line-no">8708</span><span id="line-8708">  public long getOpenSeqNum() {</span> | 
 | <span class="source-line-no">8709</span><span id="line-8709">    return this.openSeqNum;</span> | 
 | <span class="source-line-no">8710</span><span id="line-8710">  }</span> | 
 | <span class="source-line-no">8711</span><span id="line-8711"></span> | 
 | <span class="source-line-no">8712</span><span id="line-8712">  @Override</span> | 
 | <span class="source-line-no">8713</span><span id="line-8713">  public Map<byte[], Long> getMaxStoreSeqId() {</span> | 
 | <span class="source-line-no">8714</span><span id="line-8714">    return this.maxSeqIdInStores;</span> | 
 | <span class="source-line-no">8715</span><span id="line-8715">  }</span> | 
 | <span class="source-line-no">8716</span><span id="line-8716"></span> | 
 | <span class="source-line-no">8717</span><span id="line-8717">  public long getOldestSeqIdOfStore(byte[] familyName) {</span> | 
 | <span class="source-line-no">8718</span><span id="line-8718">    return wal.getEarliestMemStoreSeqNum(getRegionInfo().getEncodedNameAsBytes(), familyName);</span> | 
 | <span class="source-line-no">8719</span><span id="line-8719">  }</span> | 
 | <span class="source-line-no">8720</span><span id="line-8720"></span> | 
 | <span class="source-line-no">8721</span><span id="line-8721">  @Override</span> | 
 | <span class="source-line-no">8722</span><span id="line-8722">  public CompactionState getCompactionState() {</span> | 
 | <span class="source-line-no">8723</span><span id="line-8723">    boolean hasMajor = majorInProgress.get() > 0, hasMinor = minorInProgress.get() > 0;</span> | 
 | <span class="source-line-no">8724</span><span id="line-8724">    return (hasMajor</span> | 
 | <span class="source-line-no">8725</span><span id="line-8725">      ? (hasMinor ? CompactionState.MAJOR_AND_MINOR : CompactionState.MAJOR)</span> | 
 | <span class="source-line-no">8726</span><span id="line-8726">      : (hasMinor ? CompactionState.MINOR : CompactionState.NONE));</span> | 
 | <span class="source-line-no">8727</span><span id="line-8727">  }</span> | 
 | <span class="source-line-no">8728</span><span id="line-8728"></span> | 
 | <span class="source-line-no">8729</span><span id="line-8729">  public void reportCompactionRequestStart(boolean isMajor) {</span> | 
 | <span class="source-line-no">8730</span><span id="line-8730">    (isMajor ? majorInProgress : minorInProgress).incrementAndGet();</span> | 
 | <span class="source-line-no">8731</span><span id="line-8731">  }</span> | 
 | <span class="source-line-no">8732</span><span id="line-8732"></span> | 
 | <span class="source-line-no">8733</span><span id="line-8733">  public void reportCompactionRequestEnd(boolean isMajor, int numFiles, long filesSizeCompacted) {</span> | 
 | <span class="source-line-no">8734</span><span id="line-8734">    int newValue = (isMajor ? majorInProgress : minorInProgress).decrementAndGet();</span> | 
 | <span class="source-line-no">8735</span><span id="line-8735"></span> | 
 | <span class="source-line-no">8736</span><span id="line-8736">    // metrics</span> | 
 | <span class="source-line-no">8737</span><span id="line-8737">    compactionsFinished.increment();</span> | 
 | <span class="source-line-no">8738</span><span id="line-8738">    compactionNumFilesCompacted.add(numFiles);</span> | 
 | <span class="source-line-no">8739</span><span id="line-8739">    compactionNumBytesCompacted.add(filesSizeCompacted);</span> | 
 | <span class="source-line-no">8740</span><span id="line-8740"></span> | 
 | <span class="source-line-no">8741</span><span id="line-8741">    assert newValue >= 0;</span> | 
 | <span class="source-line-no">8742</span><span id="line-8742">  }</span> | 
 | <span class="source-line-no">8743</span><span id="line-8743"></span> | 
 | <span class="source-line-no">8744</span><span id="line-8744">  public void reportCompactionRequestFailure() {</span> | 
 | <span class="source-line-no">8745</span><span id="line-8745">    compactionsFailed.increment();</span> | 
 | <span class="source-line-no">8746</span><span id="line-8746">  }</span> | 
 | <span class="source-line-no">8747</span><span id="line-8747"></span> | 
 | <span class="source-line-no">8748</span><span id="line-8748">  public void incrementCompactionsQueuedCount() {</span> | 
 | <span class="source-line-no">8749</span><span id="line-8749">    compactionsQueued.increment();</span> | 
 | <span class="source-line-no">8750</span><span id="line-8750">  }</span> | 
 | <span class="source-line-no">8751</span><span id="line-8751"></span> | 
 | <span class="source-line-no">8752</span><span id="line-8752">  public void decrementCompactionsQueuedCount() {</span> | 
 | <span class="source-line-no">8753</span><span id="line-8753">    compactionsQueued.decrement();</span> | 
 | <span class="source-line-no">8754</span><span id="line-8754">  }</span> | 
 | <span class="source-line-no">8755</span><span id="line-8755"></span> | 
 | <span class="source-line-no">8756</span><span id="line-8756">  public void incrementFlushesQueuedCount() {</span> | 
 | <span class="source-line-no">8757</span><span id="line-8757">    flushesQueued.increment();</span> | 
 | <span class="source-line-no">8758</span><span id="line-8758">  }</span> | 
 | <span class="source-line-no">8759</span><span id="line-8759"></span> | 
 | <span class="source-line-no">8760</span><span id="line-8760">  protected void decrementFlushesQueuedCount() {</span> | 
 | <span class="source-line-no">8761</span><span id="line-8761">    flushesQueued.decrement();</span> | 
 | <span class="source-line-no">8762</span><span id="line-8762">  }</span> | 
 | <span class="source-line-no">8763</span><span id="line-8763"></span> | 
 | <span class="source-line-no">8764</span><span id="line-8764">  /**</span> | 
 | <span class="source-line-no">8765</span><span id="line-8765">   * If a handler thread is eligible for interrupt, make it ineligible. Should be paired with</span> | 
 | <span class="source-line-no">8766</span><span id="line-8766">   * {{@link #enableInterrupts()}.</span> | 
 | <span class="source-line-no">8767</span><span id="line-8767">   */</span> | 
 | <span class="source-line-no">8768</span><span id="line-8768">  void disableInterrupts() {</span> | 
 | <span class="source-line-no">8769</span><span id="line-8769">    regionLockHolders.computeIfPresent(Thread.currentThread(), (t, b) -> false);</span> | 
 | <span class="source-line-no">8770</span><span id="line-8770">  }</span> | 
 | <span class="source-line-no">8771</span><span id="line-8771"></span> | 
 | <span class="source-line-no">8772</span><span id="line-8772">  /**</span> | 
 | <span class="source-line-no">8773</span><span id="line-8773">   * If a handler thread was made ineligible for interrupt via {{@link #disableInterrupts()}, make</span> | 
 | <span class="source-line-no">8774</span><span id="line-8774">   * it eligible again. No-op if interrupts are already enabled.</span> | 
 | <span class="source-line-no">8775</span><span id="line-8775">   */</span> | 
 | <span class="source-line-no">8776</span><span id="line-8776">  void enableInterrupts() {</span> | 
 | <span class="source-line-no">8777</span><span id="line-8777">    regionLockHolders.computeIfPresent(Thread.currentThread(), (t, b) -> true);</span> | 
 | <span class="source-line-no">8778</span><span id="line-8778">  }</span> | 
 | <span class="source-line-no">8779</span><span id="line-8779"></span> | 
 | <span class="source-line-no">8780</span><span id="line-8780">  /**</span> | 
 | <span class="source-line-no">8781</span><span id="line-8781">   * Interrupt any region options that have acquired the region lock via</span> | 
 | <span class="source-line-no">8782</span><span id="line-8782">   * {@link #startRegionOperation(org.apache.hadoop.hbase.regionserver.Region.Operation)}, or</span> | 
 | <span class="source-line-no">8783</span><span id="line-8783">   * {@link #startBulkRegionOperation(boolean)}.</span> | 
 | <span class="source-line-no">8784</span><span id="line-8784">   */</span> | 
 | <span class="source-line-no">8785</span><span id="line-8785">  private void interruptRegionOperations() {</span> | 
 | <span class="source-line-no">8786</span><span id="line-8786">    for (Map.Entry<Thread, Boolean> entry : regionLockHolders.entrySet()) {</span> | 
 | <span class="source-line-no">8787</span><span id="line-8787">      // An entry in this map will have a boolean value indicating if it is currently</span> | 
 | <span class="source-line-no">8788</span><span id="line-8788">      // eligible for interrupt; if so, we should interrupt it.</span> | 
 | <span class="source-line-no">8789</span><span id="line-8789">      if (entry.getValue().booleanValue()) {</span> | 
 | <span class="source-line-no">8790</span><span id="line-8790">        entry.getKey().interrupt();</span> | 
 | <span class="source-line-no">8791</span><span id="line-8791">      }</span> | 
 | <span class="source-line-no">8792</span><span id="line-8792">    }</span> | 
 | <span class="source-line-no">8793</span><span id="line-8793">  }</span> | 
 | <span class="source-line-no">8794</span><span id="line-8794"></span> | 
 | <span class="source-line-no">8795</span><span id="line-8795">  /**</span> | 
 | <span class="source-line-no">8796</span><span id="line-8796">   * Check thread interrupt status and throw an exception if interrupted.</span> | 
 | <span class="source-line-no">8797</span><span id="line-8797">   * @throws NotServingRegionException if region is closing</span> | 
 | <span class="source-line-no">8798</span><span id="line-8798">   * @throws InterruptedIOException    if interrupted but region is not closing</span> | 
 | <span class="source-line-no">8799</span><span id="line-8799">   */</span> | 
 | <span class="source-line-no">8800</span><span id="line-8800">  // Package scope for tests</span> | 
 | <span class="source-line-no">8801</span><span id="line-8801">  void checkInterrupt() throws NotServingRegionException, InterruptedIOException {</span> | 
 | <span class="source-line-no">8802</span><span id="line-8802">    if (Thread.interrupted()) {</span> | 
 | <span class="source-line-no">8803</span><span id="line-8803">      if (this.closing.get()) {</span> | 
 | <span class="source-line-no">8804</span><span id="line-8804">        throw new NotServingRegionException(</span> | 
 | <span class="source-line-no">8805</span><span id="line-8805">          getRegionInfo().getRegionNameAsString() + " is closing");</span> | 
 | <span class="source-line-no">8806</span><span id="line-8806">      }</span> | 
 | <span class="source-line-no">8807</span><span id="line-8807">      throw new InterruptedIOException();</span> | 
 | <span class="source-line-no">8808</span><span id="line-8808">    }</span> | 
 | <span class="source-line-no">8809</span><span id="line-8809">  }</span> | 
 | <span class="source-line-no">8810</span><span id="line-8810"></span> | 
 | <span class="source-line-no">8811</span><span id="line-8811">  /**</span> | 
 | <span class="source-line-no">8812</span><span id="line-8812">   * Throw the correct exception upon interrupt</span> | 
 | <span class="source-line-no">8813</span><span id="line-8813">   * @param t cause</span> | 
 | <span class="source-line-no">8814</span><span id="line-8814">   */</span> | 
 | <span class="source-line-no">8815</span><span id="line-8815">  // Package scope for tests</span> | 
 | <span class="source-line-no">8816</span><span id="line-8816">  IOException throwOnInterrupt(Throwable t) {</span> | 
 | <span class="source-line-no">8817</span><span id="line-8817">    if (this.closing.get()) {</span> | 
 | <span class="source-line-no">8818</span><span id="line-8818">      return (NotServingRegionException) new NotServingRegionException(</span> | 
 | <span class="source-line-no">8819</span><span id="line-8819">        getRegionInfo().getRegionNameAsString() + " is closing").initCause(t);</span> | 
 | <span class="source-line-no">8820</span><span id="line-8820">    }</span> | 
 | <span class="source-line-no">8821</span><span id="line-8821">    return (InterruptedIOException) new InterruptedIOException().initCause(t);</span> | 
 | <span class="source-line-no">8822</span><span id="line-8822">  }</span> | 
 | <span class="source-line-no">8823</span><span id="line-8823"></span> | 
 | <span class="source-line-no">8824</span><span id="line-8824">  /**</span> | 
 | <span class="source-line-no">8825</span><span id="line-8825">   * {@inheritDoc}</span> | 
 | <span class="source-line-no">8826</span><span id="line-8826">   */</span> | 
 | <span class="source-line-no">8827</span><span id="line-8827">  @Override</span> | 
 | <span class="source-line-no">8828</span><span id="line-8828">  public void onConfigurationChange(Configuration conf) {</span> | 
 | <span class="source-line-no">8829</span><span id="line-8829">    this.storeHotnessProtector.update(conf);</span> | 
 | <span class="source-line-no">8830</span><span id="line-8830">    // update coprocessorHost if the configuration has changed.</span> | 
 | <span class="source-line-no">8831</span><span id="line-8831">    if (</span> | 
 | <span class="source-line-no">8832</span><span id="line-8832">      CoprocessorConfigurationUtil.checkConfigurationChange(getReadOnlyConfiguration(), conf,</span> | 
 | <span class="source-line-no">8833</span><span id="line-8833">        CoprocessorHost.REGION_COPROCESSOR_CONF_KEY,</span> | 
 | <span class="source-line-no">8834</span><span id="line-8834">        CoprocessorHost.USER_REGION_COPROCESSOR_CONF_KEY)</span> | 
 | <span class="source-line-no">8835</span><span id="line-8835">    ) {</span> | 
 | <span class="source-line-no">8836</span><span id="line-8836">      LOG.info("Update the system coprocessors because the configuration has changed");</span> | 
 | <span class="source-line-no">8837</span><span id="line-8837">      decorateRegionConfiguration(conf);</span> | 
 | <span class="source-line-no">8838</span><span id="line-8838">      this.coprocessorHost = new RegionCoprocessorHost(this, rsServices, conf);</span> | 
 | <span class="source-line-no">8839</span><span id="line-8839">    }</span> | 
 | <span class="source-line-no">8840</span><span id="line-8840">  }</span> | 
 | <span class="source-line-no">8841</span><span id="line-8841"></span> | 
 | <span class="source-line-no">8842</span><span id="line-8842">  /**</span> | 
 | <span class="source-line-no">8843</span><span id="line-8843">   * {@inheritDoc}</span> | 
 | <span class="source-line-no">8844</span><span id="line-8844">   */</span> | 
 | <span class="source-line-no">8845</span><span id="line-8845">  @Override</span> | 
 | <span class="source-line-no">8846</span><span id="line-8846">  public void registerChildren(ConfigurationManager manager) {</span> | 
 | <span class="source-line-no">8847</span><span id="line-8847">    configurationManager = manager;</span> | 
 | <span class="source-line-no">8848</span><span id="line-8848">    stores.values().forEach(manager::registerObserver);</span> | 
 | <span class="source-line-no">8849</span><span id="line-8849">  }</span> | 
 | <span class="source-line-no">8850</span><span id="line-8850"></span> | 
 | <span class="source-line-no">8851</span><span id="line-8851">  /**</span> | 
 | <span class="source-line-no">8852</span><span id="line-8852">   * {@inheritDoc}</span> | 
 | <span class="source-line-no">8853</span><span id="line-8853">   */</span> | 
 | <span class="source-line-no">8854</span><span id="line-8854">  @Override</span> | 
 | <span class="source-line-no">8855</span><span id="line-8855">  public void deregisterChildren(ConfigurationManager manager) {</span> | 
 | <span class="source-line-no">8856</span><span id="line-8856">    stores.values().forEach(configurationManager::deregisterObserver);</span> | 
 | <span class="source-line-no">8857</span><span id="line-8857">  }</span> | 
 | <span class="source-line-no">8858</span><span id="line-8858"></span> | 
 | <span class="source-line-no">8859</span><span id="line-8859">  @Override</span> | 
 | <span class="source-line-no">8860</span><span id="line-8860">  public CellComparator getCellComparator() {</span> | 
 | <span class="source-line-no">8861</span><span id="line-8861">    return cellComparator;</span> | 
 | <span class="source-line-no">8862</span><span id="line-8862">  }</span> | 
 | <span class="source-line-no">8863</span><span id="line-8863"></span> | 
 | <span class="source-line-no">8864</span><span id="line-8864">  public long getMemStoreFlushSize() {</span> | 
 | <span class="source-line-no">8865</span><span id="line-8865">    return this.memstoreFlushSize;</span> | 
 | <span class="source-line-no">8866</span><span id="line-8866">  }</span> | 
 | <span class="source-line-no">8867</span><span id="line-8867"></span> | 
 | <span class="source-line-no">8868</span><span id="line-8868">  //// method for debugging tests</span> | 
 | <span class="source-line-no">8869</span><span id="line-8869">  void throwException(String title, String regionName) {</span> | 
 | <span class="source-line-no">8870</span><span id="line-8870">    StringBuilder buf = new StringBuilder();</span> | 
 | <span class="source-line-no">8871</span><span id="line-8871">    buf.append(title + ", ");</span> | 
 | <span class="source-line-no">8872</span><span id="line-8872">    buf.append(getRegionInfo().toString());</span> | 
 | <span class="source-line-no">8873</span><span id="line-8873">    buf.append(getRegionInfo().isMetaRegion() ? " meta region " : " ");</span> | 
 | <span class="source-line-no">8874</span><span id="line-8874">    buf.append("stores: ");</span> | 
 | <span class="source-line-no">8875</span><span id="line-8875">    for (HStore s : stores.values()) {</span> | 
 | <span class="source-line-no">8876</span><span id="line-8876">      buf.append(s.getColumnFamilyDescriptor().getNameAsString());</span> | 
 | <span class="source-line-no">8877</span><span id="line-8877">      buf.append(" size: ");</span> | 
 | <span class="source-line-no">8878</span><span id="line-8878">      buf.append(s.getMemStoreSize().getDataSize());</span> | 
 | <span class="source-line-no">8879</span><span id="line-8879">      buf.append(" ");</span> | 
 | <span class="source-line-no">8880</span><span id="line-8880">    }</span> | 
 | <span class="source-line-no">8881</span><span id="line-8881">    buf.append("end-of-stores");</span> | 
 | <span class="source-line-no">8882</span><span id="line-8882">    buf.append(", memstore size ");</span> | 
 | <span class="source-line-no">8883</span><span id="line-8883">    buf.append(getMemStoreDataSize());</span> | 
 | <span class="source-line-no">8884</span><span id="line-8884">    if (getRegionInfo().getRegionNameAsString().startsWith(regionName)) {</span> | 
 | <span class="source-line-no">8885</span><span id="line-8885">      throw new RuntimeException(buf.toString());</span> | 
 | <span class="source-line-no">8886</span><span id="line-8886">    }</span> | 
 | <span class="source-line-no">8887</span><span id="line-8887">  }</span> | 
 | <span class="source-line-no">8888</span><span id="line-8888"></span> | 
 | <span class="source-line-no">8889</span><span id="line-8889">  @Override</span> | 
 | <span class="source-line-no">8890</span><span id="line-8890">  public void requestCompaction(String why, int priority, boolean major,</span> | 
 | <span class="source-line-no">8891</span><span id="line-8891">    CompactionLifeCycleTracker tracker) throws IOException {</span> | 
 | <span class="source-line-no">8892</span><span id="line-8892">    if (major) {</span> | 
 | <span class="source-line-no">8893</span><span id="line-8893">      stores.values().forEach(HStore::triggerMajorCompaction);</span> | 
 | <span class="source-line-no">8894</span><span id="line-8894">    }</span> | 
 | <span class="source-line-no">8895</span><span id="line-8895">    rsServices.getCompactionRequestor().requestCompaction(this, why, priority, tracker,</span> | 
 | <span class="source-line-no">8896</span><span id="line-8896">      RpcServer.getRequestUser().orElse(null));</span> | 
 | <span class="source-line-no">8897</span><span id="line-8897">  }</span> | 
 | <span class="source-line-no">8898</span><span id="line-8898"></span> | 
 | <span class="source-line-no">8899</span><span id="line-8899">  @Override</span> | 
 | <span class="source-line-no">8900</span><span id="line-8900">  public void requestCompaction(byte[] family, String why, int priority, boolean major,</span> | 
 | <span class="source-line-no">8901</span><span id="line-8901">    CompactionLifeCycleTracker tracker) throws IOException {</span> | 
 | <span class="source-line-no">8902</span><span id="line-8902">    HStore store = stores.get(family);</span> | 
 | <span class="source-line-no">8903</span><span id="line-8903">    if (store == null) {</span> | 
 | <span class="source-line-no">8904</span><span id="line-8904">      throw new NoSuchColumnFamilyException("column family " + Bytes.toString(family)</span> | 
 | <span class="source-line-no">8905</span><span id="line-8905">        + " does not exist in region " + getRegionInfo().getRegionNameAsString());</span> | 
 | <span class="source-line-no">8906</span><span id="line-8906">    }</span> | 
 | <span class="source-line-no">8907</span><span id="line-8907">    if (major) {</span> | 
 | <span class="source-line-no">8908</span><span id="line-8908">      store.triggerMajorCompaction();</span> | 
 | <span class="source-line-no">8909</span><span id="line-8909">    }</span> | 
 | <span class="source-line-no">8910</span><span id="line-8910">    rsServices.getCompactionRequestor().requestCompaction(this, store, why, priority, tracker,</span> | 
 | <span class="source-line-no">8911</span><span id="line-8911">      RpcServer.getRequestUser().orElse(null));</span> | 
 | <span class="source-line-no">8912</span><span id="line-8912">  }</span> | 
 | <span class="source-line-no">8913</span><span id="line-8913"></span> | 
 | <span class="source-line-no">8914</span><span id="line-8914">  private void requestFlushIfNeeded() throws RegionTooBusyException {</span> | 
 | <span class="source-line-no">8915</span><span id="line-8915">    if (isFlushSize(this.memStoreSizing.getMemStoreSize())) {</span> | 
 | <span class="source-line-no">8916</span><span id="line-8916">      requestFlush();</span> | 
 | <span class="source-line-no">8917</span><span id="line-8917">    }</span> | 
 | <span class="source-line-no">8918</span><span id="line-8918">  }</span> | 
 | <span class="source-line-no">8919</span><span id="line-8919"></span> | 
 | <span class="source-line-no">8920</span><span id="line-8920">  private void requestFlush() {</span> | 
 | <span class="source-line-no">8921</span><span id="line-8921">    if (this.rsServices == null) {</span> | 
 | <span class="source-line-no">8922</span><span id="line-8922">      return;</span> | 
 | <span class="source-line-no">8923</span><span id="line-8923">    }</span> | 
 | <span class="source-line-no">8924</span><span id="line-8924">    requestFlush0(FlushLifeCycleTracker.DUMMY);</span> | 
 | <span class="source-line-no">8925</span><span id="line-8925">  }</span> | 
 | <span class="source-line-no">8926</span><span id="line-8926"></span> | 
 | <span class="source-line-no">8927</span><span id="line-8927">  private void requestFlush0(FlushLifeCycleTracker tracker) {</span> | 
 | <span class="source-line-no">8928</span><span id="line-8928">    boolean shouldFlush = false;</span> | 
 | <span class="source-line-no">8929</span><span id="line-8929">    synchronized (writestate) {</span> | 
 | <span class="source-line-no">8930</span><span id="line-8930">      if (!this.writestate.isFlushRequested()) {</span> | 
 | <span class="source-line-no">8931</span><span id="line-8931">        shouldFlush = true;</span> | 
 | <span class="source-line-no">8932</span><span id="line-8932">        writestate.flushRequested = true;</span> | 
 | <span class="source-line-no">8933</span><span id="line-8933">      }</span> | 
 | <span class="source-line-no">8934</span><span id="line-8934">    }</span> | 
 | <span class="source-line-no">8935</span><span id="line-8935">    if (shouldFlush) {</span> | 
 | <span class="source-line-no">8936</span><span id="line-8936">      // Make request outside of synchronize block; HBASE-818.</span> | 
 | <span class="source-line-no">8937</span><span id="line-8937">      this.rsServices.getFlushRequester().requestFlush(this, tracker);</span> | 
 | <span class="source-line-no">8938</span><span id="line-8938">      if (LOG.isDebugEnabled()) {</span> | 
 | <span class="source-line-no">8939</span><span id="line-8939">        LOG.debug("Flush requested on " + this.getRegionInfo().getEncodedName());</span> | 
 | <span class="source-line-no">8940</span><span id="line-8940">      }</span> | 
 | <span class="source-line-no">8941</span><span id="line-8941">    } else {</span> | 
 | <span class="source-line-no">8942</span><span id="line-8942">      tracker.notExecuted("Flush already requested on " + this);</span> | 
 | <span class="source-line-no">8943</span><span id="line-8943">    }</span> | 
 | <span class="source-line-no">8944</span><span id="line-8944">  }</span> | 
 | <span class="source-line-no">8945</span><span id="line-8945"></span> | 
 | <span class="source-line-no">8946</span><span id="line-8946">  @Override</span> | 
 | <span class="source-line-no">8947</span><span id="line-8947">  public void requestFlush(FlushLifeCycleTracker tracker) throws IOException {</span> | 
 | <span class="source-line-no">8948</span><span id="line-8948">    requestFlush0(tracker);</span> | 
 | <span class="source-line-no">8949</span><span id="line-8949">  }</span> | 
 | <span class="source-line-no">8950</span><span id="line-8950"></span> | 
 | <span class="source-line-no">8951</span><span id="line-8951">  /**</span> | 
 | <span class="source-line-no">8952</span><span id="line-8952">   * This method modifies the region's configuration in order to inject replication-related features</span> | 
 | <span class="source-line-no">8953</span><span id="line-8953">   * @param conf region configurations</span> | 
 | <span class="source-line-no">8954</span><span id="line-8954">   */</span> | 
 | <span class="source-line-no">8955</span><span id="line-8955">  private static void decorateRegionConfiguration(Configuration conf) {</span> | 
 | <span class="source-line-no">8956</span><span id="line-8956">    if (ReplicationUtils.isReplicationForBulkLoadDataEnabled(conf)) {</span> | 
 | <span class="source-line-no">8957</span><span id="line-8957">      String plugins = conf.get(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY, "");</span> | 
 | <span class="source-line-no">8958</span><span id="line-8958">      String replicationCoprocessorClass = ReplicationObserver.class.getCanonicalName();</span> | 
 | <span class="source-line-no">8959</span><span id="line-8959">      if (!plugins.contains(replicationCoprocessorClass)) {</span> | 
 | <span class="source-line-no">8960</span><span id="line-8960">        conf.set(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY,</span> | 
 | <span class="source-line-no">8961</span><span id="line-8961">          (plugins.equals("") ? "" : (plugins + ",")) + replicationCoprocessorClass);</span> | 
 | <span class="source-line-no">8962</span><span id="line-8962">      }</span> | 
 | <span class="source-line-no">8963</span><span id="line-8963">    }</span> | 
 | <span class="source-line-no">8964</span><span id="line-8964">  }</span> | 
 | <span class="source-line-no">8965</span><span id="line-8965"></span> | 
 | <span class="source-line-no">8966</span><span id="line-8966">  public Optional<RegionReplicationSink> getRegionReplicationSink() {</span> | 
 | <span class="source-line-no">8967</span><span id="line-8967">    return regionReplicationSink;</span> | 
 | <span class="source-line-no">8968</span><span id="line-8968">  }</span> | 
 | <span class="source-line-no">8969</span><span id="line-8969"></span> | 
 | <span class="source-line-no">8970</span><span id="line-8970">  public void addReadRequestsCount(long readRequestsCount) {</span> | 
 | <span class="source-line-no">8971</span><span id="line-8971">    this.readRequestsCount.add(readRequestsCount);</span> | 
 | <span class="source-line-no">8972</span><span id="line-8972">  }</span> | 
 | <span class="source-line-no">8973</span><span id="line-8973"></span> | 
 | <span class="source-line-no">8974</span><span id="line-8974">  public void addWriteRequestsCount(long writeRequestsCount) {</span> | 
 | <span class="source-line-no">8975</span><span id="line-8975">    this.writeRequestsCount.add(writeRequestsCount);</span> | 
 | <span class="source-line-no">8976</span><span id="line-8976">  }</span> | 
 | <span class="source-line-no">8977</span><span id="line-8977"></span> | 
 | <span class="source-line-no">8978</span><span id="line-8978">  @RestrictedApi(explanation = "Should only be called in tests", link = "",</span> | 
 | <span class="source-line-no">8979</span><span id="line-8979">      allowedOnPath = ".*/src/test/.*")</span> | 
 | <span class="source-line-no">8980</span><span id="line-8980">  boolean isReadsEnabled() {</span> | 
 | <span class="source-line-no">8981</span><span id="line-8981">    return this.writestate.readsEnabled;</span> | 
 | <span class="source-line-no">8982</span><span id="line-8982">  }</span> | 
 | <span class="source-line-no">8983</span><span id="line-8983">}</span> | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 | </pre> | 
 | </div> | 
 | </main> | 
 | </body> | 
 | </html> |