blob: 8ac2463072671081ff1d8279726c12968defc5a1 [file] [log] [blame]
<!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: StoreFileWriter, class: Builder">
<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.regionserver.DefaultStoreEngine.DEFAULT_COMPACTOR_CLASS_KEY;</span>
<span class="source-line-no">021</span><span id="line-21">import static org.apache.hadoop.hbase.regionserver.HStoreFile.BLOOM_FILTER_PARAM_KEY;</span>
<span class="source-line-no">022</span><span id="line-22">import static org.apache.hadoop.hbase.regionserver.HStoreFile.BLOOM_FILTER_TYPE_KEY;</span>
<span class="source-line-no">023</span><span id="line-23">import static org.apache.hadoop.hbase.regionserver.HStoreFile.COMPACTION_EVENT_KEY;</span>
<span class="source-line-no">024</span><span id="line-24">import static org.apache.hadoop.hbase.regionserver.HStoreFile.DELETE_FAMILY_COUNT;</span>
<span class="source-line-no">025</span><span id="line-25">import static org.apache.hadoop.hbase.regionserver.HStoreFile.EARLIEST_PUT_TS;</span>
<span class="source-line-no">026</span><span id="line-26">import static org.apache.hadoop.hbase.regionserver.HStoreFile.HISTORICAL_KEY;</span>
<span class="source-line-no">027</span><span id="line-27">import static org.apache.hadoop.hbase.regionserver.HStoreFile.MAJOR_COMPACTION_KEY;</span>
<span class="source-line-no">028</span><span id="line-28">import static org.apache.hadoop.hbase.regionserver.HStoreFile.MAX_SEQ_ID_KEY;</span>
<span class="source-line-no">029</span><span id="line-29">import static org.apache.hadoop.hbase.regionserver.HStoreFile.MOB_CELLS_COUNT;</span>
<span class="source-line-no">030</span><span id="line-30">import static org.apache.hadoop.hbase.regionserver.HStoreFile.MOB_FILE_REFS;</span>
<span class="source-line-no">031</span><span id="line-31">import static org.apache.hadoop.hbase.regionserver.HStoreFile.TIMERANGE_KEY;</span>
<span class="source-line-no">032</span><span id="line-32">import static org.apache.hadoop.hbase.regionserver.StoreEngine.STORE_ENGINE_CLASS_KEY;</span>
<span class="source-line-no">033</span><span id="line-33"></span>
<span class="source-line-no">034</span><span id="line-34">import java.io.IOException;</span>
<span class="source-line-no">035</span><span id="line-35">import java.net.InetSocketAddress;</span>
<span class="source-line-no">036</span><span id="line-36">import java.util.ArrayList;</span>
<span class="source-line-no">037</span><span id="line-37">import java.util.Collection;</span>
<span class="source-line-no">038</span><span id="line-38">import java.util.Collections;</span>
<span class="source-line-no">039</span><span id="line-39">import java.util.HashSet;</span>
<span class="source-line-no">040</span><span id="line-40">import java.util.List;</span>
<span class="source-line-no">041</span><span id="line-41">import java.util.Set;</span>
<span class="source-line-no">042</span><span id="line-42">import java.util.UUID;</span>
<span class="source-line-no">043</span><span id="line-43">import java.util.function.Consumer;</span>
<span class="source-line-no">044</span><span id="line-44">import java.util.function.Supplier;</span>
<span class="source-line-no">045</span><span id="line-45">import java.util.regex.Pattern;</span>
<span class="source-line-no">046</span><span id="line-46">import java.util.stream.Collectors;</span>
<span class="source-line-no">047</span><span id="line-47">import org.apache.hadoop.conf.Configuration;</span>
<span class="source-line-no">048</span><span id="line-48">import org.apache.hadoop.fs.FileSystem;</span>
<span class="source-line-no">049</span><span id="line-49">import org.apache.hadoop.fs.Path;</span>
<span class="source-line-no">050</span><span id="line-50">import org.apache.hadoop.hbase.Cell;</span>
<span class="source-line-no">051</span><span id="line-51">import org.apache.hadoop.hbase.CellComparator;</span>
<span class="source-line-no">052</span><span id="line-52">import org.apache.hadoop.hbase.CellUtil;</span>
<span class="source-line-no">053</span><span id="line-53">import org.apache.hadoop.hbase.ExtendedCell;</span>
<span class="source-line-no">054</span><span id="line-54">import org.apache.hadoop.hbase.HConstants;</span>
<span class="source-line-no">055</span><span id="line-55">import org.apache.hadoop.hbase.KeyValue;</span>
<span class="source-line-no">056</span><span id="line-56">import org.apache.hadoop.hbase.PrivateCellUtil;</span>
<span class="source-line-no">057</span><span id="line-57">import org.apache.hadoop.hbase.TableName;</span>
<span class="source-line-no">058</span><span id="line-58">import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;</span>
<span class="source-line-no">059</span><span id="line-59">import org.apache.hadoop.hbase.io.hfile.CacheConfig;</span>
<span class="source-line-no">060</span><span id="line-60">import org.apache.hadoop.hbase.io.hfile.HFile;</span>
<span class="source-line-no">061</span><span id="line-61">import org.apache.hadoop.hbase.io.hfile.HFileContext;</span>
<span class="source-line-no">062</span><span id="line-62">import org.apache.hadoop.hbase.io.hfile.HFileWriterImpl;</span>
<span class="source-line-no">063</span><span id="line-63">import org.apache.hadoop.hbase.mob.MobUtils;</span>
<span class="source-line-no">064</span><span id="line-64">import org.apache.hadoop.hbase.regionserver.compactions.DefaultCompactor;</span>
<span class="source-line-no">065</span><span id="line-65">import org.apache.hadoop.hbase.util.BloomContext;</span>
<span class="source-line-no">066</span><span id="line-66">import org.apache.hadoop.hbase.util.BloomFilterFactory;</span>
<span class="source-line-no">067</span><span id="line-67">import org.apache.hadoop.hbase.util.BloomFilterUtil;</span>
<span class="source-line-no">068</span><span id="line-68">import org.apache.hadoop.hbase.util.BloomFilterWriter;</span>
<span class="source-line-no">069</span><span id="line-69">import org.apache.hadoop.hbase.util.Bytes;</span>
<span class="source-line-no">070</span><span id="line-70">import org.apache.hadoop.hbase.util.CommonFSUtils;</span>
<span class="source-line-no">071</span><span id="line-71">import org.apache.hadoop.hbase.util.RowBloomContext;</span>
<span class="source-line-no">072</span><span id="line-72">import org.apache.hadoop.hbase.util.RowColBloomContext;</span>
<span class="source-line-no">073</span><span id="line-73">import org.apache.hadoop.hbase.util.RowPrefixFixedLengthBloomContext;</span>
<span class="source-line-no">074</span><span id="line-74">import org.apache.yetus.audience.InterfaceAudience;</span>
<span class="source-line-no">075</span><span id="line-75">import org.slf4j.Logger;</span>
<span class="source-line-no">076</span><span id="line-76">import org.slf4j.LoggerFactory;</span>
<span class="source-line-no">077</span><span id="line-77"></span>
<span class="source-line-no">078</span><span id="line-78">import org.apache.hbase.thirdparty.com.google.common.base.Preconditions;</span>
<span class="source-line-no">079</span><span id="line-79">import org.apache.hbase.thirdparty.com.google.common.base.Strings;</span>
<span class="source-line-no">080</span><span id="line-80">import org.apache.hbase.thirdparty.com.google.common.collect.Lists;</span>
<span class="source-line-no">081</span><span id="line-81">import org.apache.hbase.thirdparty.com.google.common.collect.SetMultimap;</span>
<span class="source-line-no">082</span><span id="line-82"></span>
<span class="source-line-no">083</span><span id="line-83">import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;</span>
<span class="source-line-no">084</span><span id="line-84"></span>
<span class="source-line-no">085</span><span id="line-85">/**</span>
<span class="source-line-no">086</span><span id="line-86"> * A StoreFile writer. Use this to read/write HBase Store Files. It is package local because it is</span>
<span class="source-line-no">087</span><span id="line-87"> * an implementation detail of the HBase regionserver.</span>
<span class="source-line-no">088</span><span id="line-88"> */</span>
<span class="source-line-no">089</span><span id="line-89">@InterfaceAudience.Private</span>
<span class="source-line-no">090</span><span id="line-90">public class StoreFileWriter implements CellSink, ShipperListener {</span>
<span class="source-line-no">091</span><span id="line-91"> private static final Logger LOG = LoggerFactory.getLogger(StoreFileWriter.class.getName());</span>
<span class="source-line-no">092</span><span id="line-92"> public static final String ENABLE_HISTORICAL_COMPACTION_FILES =</span>
<span class="source-line-no">093</span><span id="line-93"> "hbase.enable.historical.compaction.files";</span>
<span class="source-line-no">094</span><span id="line-94"> public static final boolean DEFAULT_ENABLE_HISTORICAL_COMPACTION_FILES = false;</span>
<span class="source-line-no">095</span><span id="line-95"> private static final Pattern dash = Pattern.compile("-");</span>
<span class="source-line-no">096</span><span id="line-96"> private SingleStoreFileWriter liveFileWriter;</span>
<span class="source-line-no">097</span><span id="line-97"> private SingleStoreFileWriter historicalFileWriter;</span>
<span class="source-line-no">098</span><span id="line-98"> private final FileSystem fs;</span>
<span class="source-line-no">099</span><span id="line-99"> private final Path historicalFilePath;</span>
<span class="source-line-no">100</span><span id="line-100"> private final Configuration conf;</span>
<span class="source-line-no">101</span><span id="line-101"> private final CacheConfig cacheConf;</span>
<span class="source-line-no">102</span><span id="line-102"> private final BloomType bloomType;</span>
<span class="source-line-no">103</span><span id="line-103"> private final long maxKeys;</span>
<span class="source-line-no">104</span><span id="line-104"> private final InetSocketAddress[] favoredNodes;</span>
<span class="source-line-no">105</span><span id="line-105"> private final HFileContext fileContext;</span>
<span class="source-line-no">106</span><span id="line-106"> private final boolean shouldDropCacheBehind;</span>
<span class="source-line-no">107</span><span id="line-107"> private final Supplier&lt;Collection&lt;HStoreFile&gt;&gt; compactedFilesSupplier;</span>
<span class="source-line-no">108</span><span id="line-108"> private final CellComparator comparator;</span>
<span class="source-line-no">109</span><span id="line-109"> private ExtendedCell lastCell;</span>
<span class="source-line-no">110</span><span id="line-110"> // The first (latest) delete family marker of the current row</span>
<span class="source-line-no">111</span><span id="line-111"> private ExtendedCell deleteFamily;</span>
<span class="source-line-no">112</span><span id="line-112"> // The list of delete family version markers of the current row</span>
<span class="source-line-no">113</span><span id="line-113"> private List&lt;ExtendedCell&gt; deleteFamilyVersionList = new ArrayList&lt;&gt;();</span>
<span class="source-line-no">114</span><span id="line-114"> // The first (latest) delete column marker of the current column</span>
<span class="source-line-no">115</span><span id="line-115"> private ExtendedCell deleteColumn;</span>
<span class="source-line-no">116</span><span id="line-116"> // The list of delete column version markers of the current column</span>
<span class="source-line-no">117</span><span id="line-117"> private List&lt;ExtendedCell&gt; deleteColumnVersionList = new ArrayList&lt;&gt;();</span>
<span class="source-line-no">118</span><span id="line-118"> // The live put cell count for the current column</span>
<span class="source-line-no">119</span><span id="line-119"> private int livePutCellCount;</span>
<span class="source-line-no">120</span><span id="line-120"> private final int maxVersions;</span>
<span class="source-line-no">121</span><span id="line-121"> private final boolean newVersionBehavior;</span>
<span class="source-line-no">122</span><span id="line-122"></span>
<span class="source-line-no">123</span><span id="line-123"> /**</span>
<span class="source-line-no">124</span><span id="line-124"> * Creates an HFile.Writer that also write helpful meta data.</span>
<span class="source-line-no">125</span><span id="line-125"> * @param fs file system to write to</span>
<span class="source-line-no">126</span><span id="line-126"> * @param liveFilePath the name of the live file to create</span>
<span class="source-line-no">127</span><span id="line-127"> * @param historicalFilePath the name of the historical file name to create</span>
<span class="source-line-no">128</span><span id="line-128"> * @param conf user configuration</span>
<span class="source-line-no">129</span><span id="line-129"> * @param bloomType bloom filter setting</span>
<span class="source-line-no">130</span><span id="line-130"> * @param maxKeys the expected maximum number of keys to be added. Was used for</span>
<span class="source-line-no">131</span><span id="line-131"> * Bloom filter size in {@link HFile} format version 1.</span>
<span class="source-line-no">132</span><span id="line-132"> * @param favoredNodes an array of favored nodes or possibly null</span>
<span class="source-line-no">133</span><span id="line-133"> * @param fileContext The HFile context</span>
<span class="source-line-no">134</span><span id="line-134"> * @param shouldDropCacheBehind Drop pages written to page cache after writing the store file.</span>
<span class="source-line-no">135</span><span id="line-135"> * @param compactedFilesSupplier Returns the {@link HStore} compacted files which not archived</span>
<span class="source-line-no">136</span><span id="line-136"> * @param comparator Cell comparator</span>
<span class="source-line-no">137</span><span id="line-137"> * @param maxVersions max cell versions</span>
<span class="source-line-no">138</span><span id="line-138"> * @param newVersionBehavior enable new version behavior</span>
<span class="source-line-no">139</span><span id="line-139"> * @throws IOException problem writing to FS</span>
<span class="source-line-no">140</span><span id="line-140"> */</span>
<span class="source-line-no">141</span><span id="line-141"> private StoreFileWriter(FileSystem fs, Path liveFilePath, Path historicalFilePath,</span>
<span class="source-line-no">142</span><span id="line-142"> final Configuration conf, CacheConfig cacheConf, BloomType bloomType, long maxKeys,</span>
<span class="source-line-no">143</span><span id="line-143"> InetSocketAddress[] favoredNodes, HFileContext fileContext, boolean shouldDropCacheBehind,</span>
<span class="source-line-no">144</span><span id="line-144"> Supplier&lt;Collection&lt;HStoreFile&gt;&gt; compactedFilesSupplier, CellComparator comparator,</span>
<span class="source-line-no">145</span><span id="line-145"> int maxVersions, boolean newVersionBehavior) throws IOException {</span>
<span class="source-line-no">146</span><span id="line-146"> this.fs = fs;</span>
<span class="source-line-no">147</span><span id="line-147"> this.historicalFilePath = historicalFilePath;</span>
<span class="source-line-no">148</span><span id="line-148"> this.conf = conf;</span>
<span class="source-line-no">149</span><span id="line-149"> this.cacheConf = cacheConf;</span>
<span class="source-line-no">150</span><span id="line-150"> this.bloomType = bloomType;</span>
<span class="source-line-no">151</span><span id="line-151"> this.maxKeys = maxKeys;</span>
<span class="source-line-no">152</span><span id="line-152"> this.favoredNodes = favoredNodes;</span>
<span class="source-line-no">153</span><span id="line-153"> this.fileContext = fileContext;</span>
<span class="source-line-no">154</span><span id="line-154"> this.shouldDropCacheBehind = shouldDropCacheBehind;</span>
<span class="source-line-no">155</span><span id="line-155"> this.compactedFilesSupplier = compactedFilesSupplier;</span>
<span class="source-line-no">156</span><span id="line-156"> this.comparator = comparator;</span>
<span class="source-line-no">157</span><span id="line-157"> this.maxVersions = maxVersions;</span>
<span class="source-line-no">158</span><span id="line-158"> this.newVersionBehavior = newVersionBehavior;</span>
<span class="source-line-no">159</span><span id="line-159"> liveFileWriter = new SingleStoreFileWriter(fs, liveFilePath, conf, cacheConf, bloomType,</span>
<span class="source-line-no">160</span><span id="line-160"> maxKeys, favoredNodes, fileContext, shouldDropCacheBehind, compactedFilesSupplier);</span>
<span class="source-line-no">161</span><span id="line-161"> }</span>
<span class="source-line-no">162</span><span id="line-162"></span>
<span class="source-line-no">163</span><span id="line-163"> public static boolean shouldEnableHistoricalCompactionFiles(Configuration conf) {</span>
<span class="source-line-no">164</span><span id="line-164"> if (</span>
<span class="source-line-no">165</span><span id="line-165"> conf.getBoolean(ENABLE_HISTORICAL_COMPACTION_FILES,</span>
<span class="source-line-no">166</span><span id="line-166"> DEFAULT_ENABLE_HISTORICAL_COMPACTION_FILES)</span>
<span class="source-line-no">167</span><span id="line-167"> ) {</span>
<span class="source-line-no">168</span><span id="line-168"> // Historical compaction files are supported only for default store engine with</span>
<span class="source-line-no">169</span><span id="line-169"> // default compactor.</span>
<span class="source-line-no">170</span><span id="line-170"> String storeEngine = conf.get(STORE_ENGINE_CLASS_KEY, DefaultStoreEngine.class.getName());</span>
<span class="source-line-no">171</span><span id="line-171"> if (!storeEngine.equals(DefaultStoreEngine.class.getName())) {</span>
<span class="source-line-no">172</span><span id="line-172"> LOG.warn("Historical compaction file generation is ignored for " + storeEngine</span>
<span class="source-line-no">173</span><span id="line-173"> + ". hbase.enable.historical.compaction.files can be set to true only for the "</span>
<span class="source-line-no">174</span><span id="line-174"> + "default compaction (DefaultStoreEngine and DefaultCompactor)");</span>
<span class="source-line-no">175</span><span id="line-175"> return false;</span>
<span class="source-line-no">176</span><span id="line-176"> }</span>
<span class="source-line-no">177</span><span id="line-177"> String compactor = conf.get(DEFAULT_COMPACTOR_CLASS_KEY, DefaultCompactor.class.getName());</span>
<span class="source-line-no">178</span><span id="line-178"> if (!compactor.equals(DefaultCompactor.class.getName())) {</span>
<span class="source-line-no">179</span><span id="line-179"> LOG.warn("Historical compaction file generation is ignored for " + compactor</span>
<span class="source-line-no">180</span><span id="line-180"> + ". hbase.enable.historical.compaction.files can be set to true only for the "</span>
<span class="source-line-no">181</span><span id="line-181"> + "default compaction (DefaultStoreEngine and DefaultCompactor)");</span>
<span class="source-line-no">182</span><span id="line-182"> return false;</span>
<span class="source-line-no">183</span><span id="line-183"> }</span>
<span class="source-line-no">184</span><span id="line-184"> return true;</span>
<span class="source-line-no">185</span><span id="line-185"> }</span>
<span class="source-line-no">186</span><span id="line-186"> return false;</span>
<span class="source-line-no">187</span><span id="line-187"> }</span>
<span class="source-line-no">188</span><span id="line-188"></span>
<span class="source-line-no">189</span><span id="line-189"> public long getPos() throws IOException {</span>
<span class="source-line-no">190</span><span id="line-190"> return liveFileWriter.getPos();</span>
<span class="source-line-no">191</span><span id="line-191"> }</span>
<span class="source-line-no">192</span><span id="line-192"></span>
<span class="source-line-no">193</span><span id="line-193"> /**</span>
<span class="source-line-no">194</span><span id="line-194"> * Writes meta data. Call before {@link #close()} since its written as meta data to this file.</span>
<span class="source-line-no">195</span><span id="line-195"> * @param maxSequenceId Maximum sequence id.</span>
<span class="source-line-no">196</span><span id="line-196"> * @param majorCompaction True if this file is product of a major compaction</span>
<span class="source-line-no">197</span><span id="line-197"> * @throws IOException problem writing to FS</span>
<span class="source-line-no">198</span><span id="line-198"> */</span>
<span class="source-line-no">199</span><span id="line-199"> public void appendMetadata(final long maxSequenceId, final boolean majorCompaction)</span>
<span class="source-line-no">200</span><span id="line-200"> throws IOException {</span>
<span class="source-line-no">201</span><span id="line-201"> liveFileWriter.appendMetadata(maxSequenceId, majorCompaction);</span>
<span class="source-line-no">202</span><span id="line-202"> if (historicalFileWriter != null) {</span>
<span class="source-line-no">203</span><span id="line-203"> historicalFileWriter.appendMetadata(maxSequenceId, majorCompaction);</span>
<span class="source-line-no">204</span><span id="line-204"> }</span>
<span class="source-line-no">205</span><span id="line-205"> }</span>
<span class="source-line-no">206</span><span id="line-206"></span>
<span class="source-line-no">207</span><span id="line-207"> /**</span>
<span class="source-line-no">208</span><span id="line-208"> * Writes meta data. Call before {@link #close()} since its written as meta data to this file.</span>
<span class="source-line-no">209</span><span id="line-209"> * @param maxSequenceId Maximum sequence id.</span>
<span class="source-line-no">210</span><span id="line-210"> * @param majorCompaction True if this file is product of a major compaction</span>
<span class="source-line-no">211</span><span id="line-211"> * @param storeFiles The compacted store files to generate this new file</span>
<span class="source-line-no">212</span><span id="line-212"> * @throws IOException problem writing to FS</span>
<span class="source-line-no">213</span><span id="line-213"> */</span>
<span class="source-line-no">214</span><span id="line-214"> public void appendMetadata(final long maxSequenceId, final boolean majorCompaction,</span>
<span class="source-line-no">215</span><span id="line-215"> final Collection&lt;HStoreFile&gt; storeFiles) throws IOException {</span>
<span class="source-line-no">216</span><span id="line-216"> liveFileWriter.appendMetadata(maxSequenceId, majorCompaction, storeFiles);</span>
<span class="source-line-no">217</span><span id="line-217"> if (historicalFileWriter != null) {</span>
<span class="source-line-no">218</span><span id="line-218"> historicalFileWriter.appendMetadata(maxSequenceId, majorCompaction, storeFiles);</span>
<span class="source-line-no">219</span><span id="line-219"> }</span>
<span class="source-line-no">220</span><span id="line-220"> }</span>
<span class="source-line-no">221</span><span id="line-221"></span>
<span class="source-line-no">222</span><span id="line-222"> /**</span>
<span class="source-line-no">223</span><span id="line-223"> * Writes meta data. Call before {@link #close()} since its written as meta data to this file.</span>
<span class="source-line-no">224</span><span id="line-224"> * @param maxSequenceId Maximum sequence id.</span>
<span class="source-line-no">225</span><span id="line-225"> * @param majorCompaction True if this file is product of a major compaction</span>
<span class="source-line-no">226</span><span id="line-226"> * @param mobCellsCount The number of mob cells.</span>
<span class="source-line-no">227</span><span id="line-227"> * @throws IOException problem writing to FS</span>
<span class="source-line-no">228</span><span id="line-228"> */</span>
<span class="source-line-no">229</span><span id="line-229"> public void appendMetadata(final long maxSequenceId, final boolean majorCompaction,</span>
<span class="source-line-no">230</span><span id="line-230"> final long mobCellsCount) throws IOException {</span>
<span class="source-line-no">231</span><span id="line-231"> liveFileWriter.appendMetadata(maxSequenceId, majorCompaction, mobCellsCount);</span>
<span class="source-line-no">232</span><span id="line-232"> if (historicalFileWriter != null) {</span>
<span class="source-line-no">233</span><span id="line-233"> historicalFileWriter.appendMetadata(maxSequenceId, majorCompaction, mobCellsCount);</span>
<span class="source-line-no">234</span><span id="line-234"> }</span>
<span class="source-line-no">235</span><span id="line-235"> }</span>
<span class="source-line-no">236</span><span id="line-236"></span>
<span class="source-line-no">237</span><span id="line-237"> /**</span>
<span class="source-line-no">238</span><span id="line-238"> * Appends MOB - specific metadata (even if it is empty)</span>
<span class="source-line-no">239</span><span id="line-239"> * @param mobRefSet - original table -&gt; set of MOB file names</span>
<span class="source-line-no">240</span><span id="line-240"> * @throws IOException problem writing to FS</span>
<span class="source-line-no">241</span><span id="line-241"> */</span>
<span class="source-line-no">242</span><span id="line-242"> public void appendMobMetadata(SetMultimap&lt;TableName, String&gt; mobRefSet) throws IOException {</span>
<span class="source-line-no">243</span><span id="line-243"> liveFileWriter.appendMobMetadata(mobRefSet);</span>
<span class="source-line-no">244</span><span id="line-244"> if (historicalFileWriter != null) {</span>
<span class="source-line-no">245</span><span id="line-245"> historicalFileWriter.appendMobMetadata(mobRefSet);</span>
<span class="source-line-no">246</span><span id="line-246"> }</span>
<span class="source-line-no">247</span><span id="line-247"> }</span>
<span class="source-line-no">248</span><span id="line-248"></span>
<span class="source-line-no">249</span><span id="line-249"> /**</span>
<span class="source-line-no">250</span><span id="line-250"> * Add TimestampRange and earliest put timestamp to Metadata</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 void appendTrackedTimestampsToMetadata() throws IOException {</span>
<span class="source-line-no">253</span><span id="line-253"> // TODO: The StoreFileReader always converts the byte[] to TimeRange</span>
<span class="source-line-no">254</span><span id="line-254"> // via TimeRangeTracker, so we should write the serialization data of TimeRange directly.</span>
<span class="source-line-no">255</span><span id="line-255"> liveFileWriter.appendTrackedTimestampsToMetadata();</span>
<span class="source-line-no">256</span><span id="line-256"> if (historicalFileWriter != null) {</span>
<span class="source-line-no">257</span><span id="line-257"> historicalFileWriter.appendTrackedTimestampsToMetadata();</span>
<span class="source-line-no">258</span><span id="line-258"> }</span>
<span class="source-line-no">259</span><span id="line-259"> }</span>
<span class="source-line-no">260</span><span id="line-260"></span>
<span class="source-line-no">261</span><span id="line-261"> @Override</span>
<span class="source-line-no">262</span><span id="line-262"> public void beforeShipped() throws IOException {</span>
<span class="source-line-no">263</span><span id="line-263"> liveFileWriter.beforeShipped();</span>
<span class="source-line-no">264</span><span id="line-264"> if (historicalFileWriter != null) {</span>
<span class="source-line-no">265</span><span id="line-265"> historicalFileWriter.beforeShipped();</span>
<span class="source-line-no">266</span><span id="line-266"> }</span>
<span class="source-line-no">267</span><span id="line-267"> }</span>
<span class="source-line-no">268</span><span id="line-268"></span>
<span class="source-line-no">269</span><span id="line-269"> public Path getPath() {</span>
<span class="source-line-no">270</span><span id="line-270"> return liveFileWriter.getPath();</span>
<span class="source-line-no">271</span><span id="line-271"> }</span>
<span class="source-line-no">272</span><span id="line-272"></span>
<span class="source-line-no">273</span><span id="line-273"> public List&lt;Path&gt; getPaths() {</span>
<span class="source-line-no">274</span><span id="line-274"> if (historicalFileWriter == null) {</span>
<span class="source-line-no">275</span><span id="line-275"> return Lists.newArrayList(liveFileWriter.getPath());</span>
<span class="source-line-no">276</span><span id="line-276"> }</span>
<span class="source-line-no">277</span><span id="line-277"> return Lists.newArrayList(liveFileWriter.getPath(), historicalFileWriter.getPath());</span>
<span class="source-line-no">278</span><span id="line-278"> }</span>
<span class="source-line-no">279</span><span id="line-279"></span>
<span class="source-line-no">280</span><span id="line-280"> public boolean hasGeneralBloom() {</span>
<span class="source-line-no">281</span><span id="line-281"> return liveFileWriter.hasGeneralBloom();</span>
<span class="source-line-no">282</span><span id="line-282"> }</span>
<span class="source-line-no">283</span><span id="line-283"></span>
<span class="source-line-no">284</span><span id="line-284"> /**</span>
<span class="source-line-no">285</span><span id="line-285"> * For unit testing only.</span>
<span class="source-line-no">286</span><span id="line-286"> * @return the Bloom filter used by this writer.</span>
<span class="source-line-no">287</span><span id="line-287"> */</span>
<span class="source-line-no">288</span><span id="line-288"> BloomFilterWriter getGeneralBloomWriter() {</span>
<span class="source-line-no">289</span><span id="line-289"> return liveFileWriter.generalBloomFilterWriter;</span>
<span class="source-line-no">290</span><span id="line-290"> }</span>
<span class="source-line-no">291</span><span id="line-291"></span>
<span class="source-line-no">292</span><span id="line-292"> public void close() throws IOException {</span>
<span class="source-line-no">293</span><span id="line-293"> liveFileWriter.appendFileInfo(HISTORICAL_KEY, Bytes.toBytes(false));</span>
<span class="source-line-no">294</span><span id="line-294"> liveFileWriter.close();</span>
<span class="source-line-no">295</span><span id="line-295"> if (historicalFileWriter != null) {</span>
<span class="source-line-no">296</span><span id="line-296"> historicalFileWriter.appendFileInfo(HISTORICAL_KEY, Bytes.toBytes(true));</span>
<span class="source-line-no">297</span><span id="line-297"> historicalFileWriter.close();</span>
<span class="source-line-no">298</span><span id="line-298"> }</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"> public void appendFileInfo(byte[] key, byte[] value) throws IOException {</span>
<span class="source-line-no">302</span><span id="line-302"> liveFileWriter.appendFileInfo(key, value);</span>
<span class="source-line-no">303</span><span id="line-303"> if (historicalFileWriter != null) {</span>
<span class="source-line-no">304</span><span id="line-304"> historicalFileWriter.appendFileInfo(key, value);</span>
<span class="source-line-no">305</span><span id="line-305"> }</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"> /**</span>
<span class="source-line-no">309</span><span id="line-309"> * For use in testing.</span>
<span class="source-line-no">310</span><span id="line-310"> */</span>
<span class="source-line-no">311</span><span id="line-311"> HFile.Writer getLiveFileWriter() {</span>
<span class="source-line-no">312</span><span id="line-312"> return liveFileWriter.getHFileWriter();</span>
<span class="source-line-no">313</span><span id="line-313"> }</span>
<span class="source-line-no">314</span><span id="line-314"></span>
<span class="source-line-no">315</span><span id="line-315"> /**</span>
<span class="source-line-no">316</span><span id="line-316"> * @param dir Directory to create file in.</span>
<span class="source-line-no">317</span><span id="line-317"> * @return random filename inside passed &lt;code&gt;dir&lt;/code&gt;</span>
<span class="source-line-no">318</span><span id="line-318"> */</span>
<span class="source-line-no">319</span><span id="line-319"> public static Path getUniqueFile(final FileSystem fs, final Path dir) throws IOException {</span>
<span class="source-line-no">320</span><span id="line-320"> if (!fs.getFileStatus(dir).isDirectory()) {</span>
<span class="source-line-no">321</span><span id="line-321"> throw new IOException("Expecting " + dir.toString() + " to be a directory");</span>
<span class="source-line-no">322</span><span id="line-322"> }</span>
<span class="source-line-no">323</span><span id="line-323"> return new Path(dir, dash.matcher(UUID.randomUUID().toString()).replaceAll(""));</span>
<span class="source-line-no">324</span><span id="line-324"> }</span>
<span class="source-line-no">325</span><span id="line-325"></span>
<span class="source-line-no">326</span><span id="line-326"> private SingleStoreFileWriter getHistoricalFileWriter() throws IOException {</span>
<span class="source-line-no">327</span><span id="line-327"> if (historicalFileWriter == null) {</span>
<span class="source-line-no">328</span><span id="line-328"> historicalFileWriter =</span>
<span class="source-line-no">329</span><span id="line-329"> new SingleStoreFileWriter(fs, historicalFilePath, conf, cacheConf, bloomType, maxKeys,</span>
<span class="source-line-no">330</span><span id="line-330"> favoredNodes, fileContext, shouldDropCacheBehind, compactedFilesSupplier);</span>
<span class="source-line-no">331</span><span id="line-331"> }</span>
<span class="source-line-no">332</span><span id="line-332"> return historicalFileWriter;</span>
<span class="source-line-no">333</span><span id="line-333"> }</span>
<span class="source-line-no">334</span><span id="line-334"></span>
<span class="source-line-no">335</span><span id="line-335"> private void initRowState() {</span>
<span class="source-line-no">336</span><span id="line-336"> deleteFamily = null;</span>
<span class="source-line-no">337</span><span id="line-337"> deleteFamilyVersionList.clear();</span>
<span class="source-line-no">338</span><span id="line-338"> lastCell = null;</span>
<span class="source-line-no">339</span><span id="line-339"> }</span>
<span class="source-line-no">340</span><span id="line-340"></span>
<span class="source-line-no">341</span><span id="line-341"> private void initColumnState() {</span>
<span class="source-line-no">342</span><span id="line-342"> livePutCellCount = 0;</span>
<span class="source-line-no">343</span><span id="line-343"> deleteColumn = null;</span>
<span class="source-line-no">344</span><span id="line-344"> deleteColumnVersionList.clear();</span>
<span class="source-line-no">345</span><span id="line-345"></span>
<span class="source-line-no">346</span><span id="line-346"> }</span>
<span class="source-line-no">347</span><span id="line-347"></span>
<span class="source-line-no">348</span><span id="line-348"> private boolean isDeletedByDeleteFamily(ExtendedCell cell) {</span>
<span class="source-line-no">349</span><span id="line-349"> return deleteFamily != null &amp;&amp; (deleteFamily.getTimestamp() &gt; cell.getTimestamp()</span>
<span class="source-line-no">350</span><span id="line-350"> || (deleteFamily.getTimestamp() == cell.getTimestamp()</span>
<span class="source-line-no">351</span><span id="line-351"> &amp;&amp; (!newVersionBehavior || cell.getSequenceId() &lt; deleteFamily.getSequenceId())));</span>
<span class="source-line-no">352</span><span id="line-352"> }</span>
<span class="source-line-no">353</span><span id="line-353"></span>
<span class="source-line-no">354</span><span id="line-354"> private boolean isDeletedByDeleteFamilyVersion(ExtendedCell cell) {</span>
<span class="source-line-no">355</span><span id="line-355"> for (ExtendedCell deleteFamilyVersion : deleteFamilyVersionList) {</span>
<span class="source-line-no">356</span><span id="line-356"> if (</span>
<span class="source-line-no">357</span><span id="line-357"> deleteFamilyVersion.getTimestamp() == cell.getTimestamp()</span>
<span class="source-line-no">358</span><span id="line-358"> &amp;&amp; (!newVersionBehavior || cell.getSequenceId() &lt; deleteFamilyVersion.getSequenceId())</span>
<span class="source-line-no">359</span><span id="line-359"> ) {</span>
<span class="source-line-no">360</span><span id="line-360"> return true;</span>
<span class="source-line-no">361</span><span id="line-361"> }</span>
<span class="source-line-no">362</span><span id="line-362"> }</span>
<span class="source-line-no">363</span><span id="line-363"> return false;</span>
<span class="source-line-no">364</span><span id="line-364"> }</span>
<span class="source-line-no">365</span><span id="line-365"></span>
<span class="source-line-no">366</span><span id="line-366"> private boolean isDeletedByDeleteColumn(ExtendedCell cell) {</span>
<span class="source-line-no">367</span><span id="line-367"> return deleteColumn != null &amp;&amp; (deleteColumn.getTimestamp() &gt; cell.getTimestamp()</span>
<span class="source-line-no">368</span><span id="line-368"> || (deleteColumn.getTimestamp() == cell.getTimestamp()</span>
<span class="source-line-no">369</span><span id="line-369"> &amp;&amp; (!newVersionBehavior || cell.getSequenceId() &lt; deleteColumn.getSequenceId())));</span>
<span class="source-line-no">370</span><span id="line-370"> }</span>
<span class="source-line-no">371</span><span id="line-371"></span>
<span class="source-line-no">372</span><span id="line-372"> private boolean isDeletedByDeleteColumnVersion(ExtendedCell cell) {</span>
<span class="source-line-no">373</span><span id="line-373"> for (ExtendedCell deleteColumnVersion : deleteColumnVersionList) {</span>
<span class="source-line-no">374</span><span id="line-374"> if (</span>
<span class="source-line-no">375</span><span id="line-375"> deleteColumnVersion.getTimestamp() == cell.getTimestamp()</span>
<span class="source-line-no">376</span><span id="line-376"> &amp;&amp; (!newVersionBehavior || cell.getSequenceId() &lt; deleteColumnVersion.getSequenceId())</span>
<span class="source-line-no">377</span><span id="line-377"> ) {</span>
<span class="source-line-no">378</span><span id="line-378"> return true;</span>
<span class="source-line-no">379</span><span id="line-379"> }</span>
<span class="source-line-no">380</span><span id="line-380"> }</span>
<span class="source-line-no">381</span><span id="line-381"> return false;</span>
<span class="source-line-no">382</span><span id="line-382"> }</span>
<span class="source-line-no">383</span><span id="line-383"></span>
<span class="source-line-no">384</span><span id="line-384"> private boolean isDeleted(ExtendedCell cell) {</span>
<span class="source-line-no">385</span><span id="line-385"> return isDeletedByDeleteFamily(cell) || isDeletedByDeleteColumn(cell)</span>
<span class="source-line-no">386</span><span id="line-386"> || isDeletedByDeleteFamilyVersion(cell) || isDeletedByDeleteColumnVersion(cell);</span>
<span class="source-line-no">387</span><span id="line-387"> }</span>
<span class="source-line-no">388</span><span id="line-388"></span>
<span class="source-line-no">389</span><span id="line-389"> private void appendCell(ExtendedCell cell) throws IOException {</span>
<span class="source-line-no">390</span><span id="line-390"> if ((lastCell == null || !CellUtil.matchingColumn(lastCell, cell))) {</span>
<span class="source-line-no">391</span><span id="line-391"> initColumnState();</span>
<span class="source-line-no">392</span><span id="line-392"> }</span>
<span class="source-line-no">393</span><span id="line-393"> if (cell.getType() == Cell.Type.DeleteFamily) {</span>
<span class="source-line-no">394</span><span id="line-394"> if (deleteFamily == null) {</span>
<span class="source-line-no">395</span><span id="line-395"> deleteFamily = cell;</span>
<span class="source-line-no">396</span><span id="line-396"> liveFileWriter.append(cell);</span>
<span class="source-line-no">397</span><span id="line-397"> } else {</span>
<span class="source-line-no">398</span><span id="line-398"> getHistoricalFileWriter().append(cell);</span>
<span class="source-line-no">399</span><span id="line-399"> }</span>
<span class="source-line-no">400</span><span id="line-400"> } else if (cell.getType() == Cell.Type.DeleteFamilyVersion) {</span>
<span class="source-line-no">401</span><span id="line-401"> if (!isDeletedByDeleteFamily(cell)) {</span>
<span class="source-line-no">402</span><span id="line-402"> deleteFamilyVersionList.add(cell);</span>
<span class="source-line-no">403</span><span id="line-403"> if (deleteFamily != null &amp;&amp; deleteFamily.getTimestamp() == cell.getTimestamp()) {</span>
<span class="source-line-no">404</span><span id="line-404"> // This means both the delete-family and delete-family-version markers have the same</span>
<span class="source-line-no">405</span><span id="line-405"> // timestamp but the sequence id of delete-family-version marker is higher than that of</span>
<span class="source-line-no">406</span><span id="line-406"> // the delete-family marker. In this case, there is no need to add the</span>
<span class="source-line-no">407</span><span id="line-407"> // delete-family-version marker to the live version file. This case happens only with</span>
<span class="source-line-no">408</span><span id="line-408"> // the new version behavior.</span>
<span class="source-line-no">409</span><span id="line-409"> liveFileWriter.append(cell);</span>
<span class="source-line-no">410</span><span id="line-410"> } else {</span>
<span class="source-line-no">411</span><span id="line-411"> liveFileWriter.append(cell);</span>
<span class="source-line-no">412</span><span id="line-412"> }</span>
<span class="source-line-no">413</span><span id="line-413"> } else {</span>
<span class="source-line-no">414</span><span id="line-414"> getHistoricalFileWriter().append(cell);</span>
<span class="source-line-no">415</span><span id="line-415"> }</span>
<span class="source-line-no">416</span><span id="line-416"> } else if (cell.getType() == Cell.Type.DeleteColumn) {</span>
<span class="source-line-no">417</span><span id="line-417"> if (!isDeletedByDeleteFamily(cell) &amp;&amp; deleteColumn == null) {</span>
<span class="source-line-no">418</span><span id="line-418"> deleteColumn = cell;</span>
<span class="source-line-no">419</span><span id="line-419"> liveFileWriter.append(cell);</span>
<span class="source-line-no">420</span><span id="line-420"> } else {</span>
<span class="source-line-no">421</span><span id="line-421"> getHistoricalFileWriter().append(cell);</span>
<span class="source-line-no">422</span><span id="line-422"> }</span>
<span class="source-line-no">423</span><span id="line-423"> } else if (cell.getType() == Cell.Type.Delete) {</span>
<span class="source-line-no">424</span><span id="line-424"> if (!isDeletedByDeleteFamily(cell) &amp;&amp; deleteColumn == null) {</span>
<span class="source-line-no">425</span><span id="line-425"> deleteColumnVersionList.add(cell);</span>
<span class="source-line-no">426</span><span id="line-426"> if (deleteFamily != null &amp;&amp; deleteFamily.getTimestamp() == cell.getTimestamp()) {</span>
<span class="source-line-no">427</span><span id="line-427"> // This means both the delete-family and delete-column-version markers have the same</span>
<span class="source-line-no">428</span><span id="line-428"> // timestamp but the sequence id of delete-column-version marker is higher than that of</span>
<span class="source-line-no">429</span><span id="line-429"> // the delete-family marker. In this case, there is no need to add the</span>
<span class="source-line-no">430</span><span id="line-430"> // delete-column-version marker to the live version file. This case happens only with</span>
<span class="source-line-no">431</span><span id="line-431"> // the new version behavior.</span>
<span class="source-line-no">432</span><span id="line-432"> getHistoricalFileWriter().append(cell);</span>
<span class="source-line-no">433</span><span id="line-433"> } else {</span>
<span class="source-line-no">434</span><span id="line-434"> liveFileWriter.append(cell);</span>
<span class="source-line-no">435</span><span id="line-435"> }</span>
<span class="source-line-no">436</span><span id="line-436"> } else {</span>
<span class="source-line-no">437</span><span id="line-437"> getHistoricalFileWriter().append(cell);</span>
<span class="source-line-no">438</span><span id="line-438"> }</span>
<span class="source-line-no">439</span><span id="line-439"> } else if (cell.getType() == Cell.Type.Put) {</span>
<span class="source-line-no">440</span><span id="line-440"> if (livePutCellCount &lt; maxVersions) {</span>
<span class="source-line-no">441</span><span id="line-441"> // This is a live put cell (i.e., the latest version) of a column. Is it deleted?</span>
<span class="source-line-no">442</span><span id="line-442"> if (!isDeleted(cell)) {</span>
<span class="source-line-no">443</span><span id="line-443"> liveFileWriter.append(cell);</span>
<span class="source-line-no">444</span><span id="line-444"> livePutCellCount++;</span>
<span class="source-line-no">445</span><span id="line-445"> } else {</span>
<span class="source-line-no">446</span><span id="line-446"> // It is deleted</span>
<span class="source-line-no">447</span><span id="line-447"> getHistoricalFileWriter().append(cell);</span>
<span class="source-line-no">448</span><span id="line-448"> if (newVersionBehavior) {</span>
<span class="source-line-no">449</span><span id="line-449"> // Deleted versions are considered toward total version count when newVersionBehavior</span>
<span class="source-line-no">450</span><span id="line-450"> livePutCellCount++;</span>
<span class="source-line-no">451</span><span id="line-451"> }</span>
<span class="source-line-no">452</span><span id="line-452"> }</span>
<span class="source-line-no">453</span><span id="line-453"> } else {</span>
<span class="source-line-no">454</span><span id="line-454"> // It is an older put cell</span>
<span class="source-line-no">455</span><span id="line-455"> getHistoricalFileWriter().append(cell);</span>
<span class="source-line-no">456</span><span id="line-456"> }</span>
<span class="source-line-no">457</span><span id="line-457"> }</span>
<span class="source-line-no">458</span><span id="line-458"> lastCell = cell;</span>
<span class="source-line-no">459</span><span id="line-459"> }</span>
<span class="source-line-no">460</span><span id="line-460"></span>
<span class="source-line-no">461</span><span id="line-461"> @Override</span>
<span class="source-line-no">462</span><span id="line-462"> public void appendAll(List&lt;ExtendedCell&gt; cellList) throws IOException {</span>
<span class="source-line-no">463</span><span id="line-463"> if (historicalFilePath == null) {</span>
<span class="source-line-no">464</span><span id="line-464"> // The dual writing is not enabled and all cells are written to one file. We use</span>
<span class="source-line-no">465</span><span id="line-465"> // the live version file in this case</span>
<span class="source-line-no">466</span><span id="line-466"> for (ExtendedCell cell : cellList) {</span>
<span class="source-line-no">467</span><span id="line-467"> liveFileWriter.append(cell);</span>
<span class="source-line-no">468</span><span id="line-468"> }</span>
<span class="source-line-no">469</span><span id="line-469"> return;</span>
<span class="source-line-no">470</span><span id="line-470"> }</span>
<span class="source-line-no">471</span><span id="line-471"> if (cellList.isEmpty()) {</span>
<span class="source-line-no">472</span><span id="line-472"> return;</span>
<span class="source-line-no">473</span><span id="line-473"> }</span>
<span class="source-line-no">474</span><span id="line-474"> if (lastCell != null &amp;&amp; comparator.compareRows(lastCell, cellList.get(0)) != 0) {</span>
<span class="source-line-no">475</span><span id="line-475"> // It is a new row and thus time to reset the state</span>
<span class="source-line-no">476</span><span id="line-476"> initRowState();</span>
<span class="source-line-no">477</span><span id="line-477"> }</span>
<span class="source-line-no">478</span><span id="line-478"> for (ExtendedCell cell : cellList) {</span>
<span class="source-line-no">479</span><span id="line-479"> appendCell(cell);</span>
<span class="source-line-no">480</span><span id="line-480"> }</span>
<span class="source-line-no">481</span><span id="line-481"> }</span>
<span class="source-line-no">482</span><span id="line-482"></span>
<span class="source-line-no">483</span><span id="line-483"> @Override</span>
<span class="source-line-no">484</span><span id="line-484"> public void append(ExtendedCell cell) throws IOException {</span>
<span class="source-line-no">485</span><span id="line-485"> if (historicalFilePath == null) {</span>
<span class="source-line-no">486</span><span id="line-486"> // The dual writing is not enabled and all cells are written to one file. We use</span>
<span class="source-line-no">487</span><span id="line-487"> // the live version file in this case</span>
<span class="source-line-no">488</span><span id="line-488"> liveFileWriter.append(cell);</span>
<span class="source-line-no">489</span><span id="line-489"> return;</span>
<span class="source-line-no">490</span><span id="line-490"> }</span>
<span class="source-line-no">491</span><span id="line-491"> appendCell(cell);</span>
<span class="source-line-no">492</span><span id="line-492"> }</span>
<span class="source-line-no">493</span><span id="line-493"></span>
<span class="source-line-no">494</span><span id="line-494"> private static class SingleStoreFileWriter {</span>
<span class="source-line-no">495</span><span id="line-495"> private final BloomFilterWriter generalBloomFilterWriter;</span>
<span class="source-line-no">496</span><span id="line-496"> private final BloomFilterWriter deleteFamilyBloomFilterWriter;</span>
<span class="source-line-no">497</span><span id="line-497"> private final BloomType bloomType;</span>
<span class="source-line-no">498</span><span id="line-498"> private byte[] bloomParam = null;</span>
<span class="source-line-no">499</span><span id="line-499"> private long earliestPutTs = HConstants.LATEST_TIMESTAMP;</span>
<span class="source-line-no">500</span><span id="line-500"> private long deleteFamilyCnt = 0;</span>
<span class="source-line-no">501</span><span id="line-501"> private BloomContext bloomContext = null;</span>
<span class="source-line-no">502</span><span id="line-502"> private BloomContext deleteFamilyBloomContext = null;</span>
<span class="source-line-no">503</span><span id="line-503"> private final TimeRangeTracker timeRangeTracker;</span>
<span class="source-line-no">504</span><span id="line-504"> private final Supplier&lt;Collection&lt;HStoreFile&gt;&gt; compactedFilesSupplier;</span>
<span class="source-line-no">505</span><span id="line-505"></span>
<span class="source-line-no">506</span><span id="line-506"> private HFile.Writer writer;</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"> * Creates an HFile.Writer that also write helpful meta data.</span>
<span class="source-line-no">510</span><span id="line-510"> * @param fs file system to write to</span>
<span class="source-line-no">511</span><span id="line-511"> * @param path file name to create</span>
<span class="source-line-no">512</span><span id="line-512"> * @param conf user configuration</span>
<span class="source-line-no">513</span><span id="line-513"> * @param bloomType bloom filter setting</span>
<span class="source-line-no">514</span><span id="line-514"> * @param maxKeys the expected maximum number of keys to be added. Was used for</span>
<span class="source-line-no">515</span><span id="line-515"> * Bloom filter size in {@link HFile} format version 1.</span>
<span class="source-line-no">516</span><span id="line-516"> * @param favoredNodes an array of favored nodes or possibly null</span>
<span class="source-line-no">517</span><span id="line-517"> * @param fileContext The HFile context</span>
<span class="source-line-no">518</span><span id="line-518"> * @param shouldDropCacheBehind Drop pages written to page cache after writing the store file.</span>
<span class="source-line-no">519</span><span id="line-519"> * @param compactedFilesSupplier Returns the {@link HStore} compacted files which not archived</span>
<span class="source-line-no">520</span><span id="line-520"> * @throws IOException problem writing to FS</span>
<span class="source-line-no">521</span><span id="line-521"> */</span>
<span class="source-line-no">522</span><span id="line-522"> private SingleStoreFileWriter(FileSystem fs, Path path, final Configuration conf,</span>
<span class="source-line-no">523</span><span id="line-523"> CacheConfig cacheConf, BloomType bloomType, long maxKeys, InetSocketAddress[] favoredNodes,</span>
<span class="source-line-no">524</span><span id="line-524"> HFileContext fileContext, boolean shouldDropCacheBehind,</span>
<span class="source-line-no">525</span><span id="line-525"> Supplier&lt;Collection&lt;HStoreFile&gt;&gt; compactedFilesSupplier) throws IOException {</span>
<span class="source-line-no">526</span><span id="line-526"> this.compactedFilesSupplier = compactedFilesSupplier;</span>
<span class="source-line-no">527</span><span id="line-527"> this.timeRangeTracker = TimeRangeTracker.create(TimeRangeTracker.Type.NON_SYNC);</span>
<span class="source-line-no">528</span><span id="line-528"> // TODO : Change all writers to be specifically created for compaction context</span>
<span class="source-line-no">529</span><span id="line-529"> writer =</span>
<span class="source-line-no">530</span><span id="line-530"> HFile.getWriterFactory(conf, cacheConf).withPath(fs, path).withFavoredNodes(favoredNodes)</span>
<span class="source-line-no">531</span><span id="line-531"> .withFileContext(fileContext).withShouldDropCacheBehind(shouldDropCacheBehind).create();</span>
<span class="source-line-no">532</span><span id="line-532"></span>
<span class="source-line-no">533</span><span id="line-533"> generalBloomFilterWriter = BloomFilterFactory.createGeneralBloomAtWrite(conf, cacheConf,</span>
<span class="source-line-no">534</span><span id="line-534"> bloomType, (int) Math.min(maxKeys, Integer.MAX_VALUE), writer);</span>
<span class="source-line-no">535</span><span id="line-535"></span>
<span class="source-line-no">536</span><span id="line-536"> if (generalBloomFilterWriter != null) {</span>
<span class="source-line-no">537</span><span id="line-537"> this.bloomType = bloomType;</span>
<span class="source-line-no">538</span><span id="line-538"> this.bloomParam = BloomFilterUtil.getBloomFilterParam(bloomType, conf);</span>
<span class="source-line-no">539</span><span id="line-539"> if (LOG.isTraceEnabled()) {</span>
<span class="source-line-no">540</span><span id="line-540"> LOG.trace("Bloom filter type for " + path + ": " + this.bloomType + ", param: "</span>
<span class="source-line-no">541</span><span id="line-541"> + (bloomType == BloomType.ROWPREFIX_FIXED_LENGTH</span>
<span class="source-line-no">542</span><span id="line-542"> ? Bytes.toInt(bloomParam)</span>
<span class="source-line-no">543</span><span id="line-543"> : Bytes.toStringBinary(bloomParam))</span>
<span class="source-line-no">544</span><span id="line-544"> + ", " + generalBloomFilterWriter.getClass().getSimpleName());</span>
<span class="source-line-no">545</span><span id="line-545"> }</span>
<span class="source-line-no">546</span><span id="line-546"> // init bloom context</span>
<span class="source-line-no">547</span><span id="line-547"> switch (bloomType) {</span>
<span class="source-line-no">548</span><span id="line-548"> case ROW:</span>
<span class="source-line-no">549</span><span id="line-549"> bloomContext =</span>
<span class="source-line-no">550</span><span id="line-550"> new RowBloomContext(generalBloomFilterWriter, fileContext.getCellComparator());</span>
<span class="source-line-no">551</span><span id="line-551"> break;</span>
<span class="source-line-no">552</span><span id="line-552"> case ROWCOL:</span>
<span class="source-line-no">553</span><span id="line-553"> bloomContext =</span>
<span class="source-line-no">554</span><span id="line-554"> new RowColBloomContext(generalBloomFilterWriter, fileContext.getCellComparator());</span>
<span class="source-line-no">555</span><span id="line-555"> break;</span>
<span class="source-line-no">556</span><span id="line-556"> case ROWPREFIX_FIXED_LENGTH:</span>
<span class="source-line-no">557</span><span id="line-557"> bloomContext = new RowPrefixFixedLengthBloomContext(generalBloomFilterWriter,</span>
<span class="source-line-no">558</span><span id="line-558"> fileContext.getCellComparator(), Bytes.toInt(bloomParam));</span>
<span class="source-line-no">559</span><span id="line-559"> break;</span>
<span class="source-line-no">560</span><span id="line-560"> default:</span>
<span class="source-line-no">561</span><span id="line-561"> throw new IOException(</span>
<span class="source-line-no">562</span><span id="line-562"> "Invalid Bloom filter type: " + bloomType + " (ROW or ROWCOL or ROWPREFIX expected)");</span>
<span class="source-line-no">563</span><span id="line-563"> }</span>
<span class="source-line-no">564</span><span id="line-564"> } else {</span>
<span class="source-line-no">565</span><span id="line-565"> // Not using Bloom filters.</span>
<span class="source-line-no">566</span><span id="line-566"> this.bloomType = BloomType.NONE;</span>
<span class="source-line-no">567</span><span id="line-567"> }</span>
<span class="source-line-no">568</span><span id="line-568"></span>
<span class="source-line-no">569</span><span id="line-569"> // initialize delete family Bloom filter when there is NO RowCol Bloom filter</span>
<span class="source-line-no">570</span><span id="line-570"> if (this.bloomType != BloomType.ROWCOL) {</span>
<span class="source-line-no">571</span><span id="line-571"> this.deleteFamilyBloomFilterWriter = BloomFilterFactory.createDeleteBloomAtWrite(conf,</span>
<span class="source-line-no">572</span><span id="line-572"> cacheConf, (int) Math.min(maxKeys, Integer.MAX_VALUE), writer);</span>
<span class="source-line-no">573</span><span id="line-573"> deleteFamilyBloomContext =</span>
<span class="source-line-no">574</span><span id="line-574"> new RowBloomContext(deleteFamilyBloomFilterWriter, fileContext.getCellComparator());</span>
<span class="source-line-no">575</span><span id="line-575"> } else {</span>
<span class="source-line-no">576</span><span id="line-576"> deleteFamilyBloomFilterWriter = null;</span>
<span class="source-line-no">577</span><span id="line-577"> }</span>
<span class="source-line-no">578</span><span id="line-578"> if (deleteFamilyBloomFilterWriter != null &amp;&amp; LOG.isTraceEnabled()) {</span>
<span class="source-line-no">579</span><span id="line-579"> LOG.trace("Delete Family Bloom filter type for " + path + ": "</span>
<span class="source-line-no">580</span><span id="line-580"> + deleteFamilyBloomFilterWriter.getClass().getSimpleName());</span>
<span class="source-line-no">581</span><span id="line-581"> }</span>
<span class="source-line-no">582</span><span id="line-582"> }</span>
<span class="source-line-no">583</span><span id="line-583"></span>
<span class="source-line-no">584</span><span id="line-584"> private long getPos() throws IOException {</span>
<span class="source-line-no">585</span><span id="line-585"> return ((HFileWriterImpl) writer).getPos();</span>
<span class="source-line-no">586</span><span id="line-586"> }</span>
<span class="source-line-no">587</span><span id="line-587"></span>
<span class="source-line-no">588</span><span id="line-588"> /**</span>
<span class="source-line-no">589</span><span id="line-589"> * Writes meta data. Call before {@link #close()} since its written as meta data to this file.</span>
<span class="source-line-no">590</span><span id="line-590"> * @param maxSequenceId Maximum sequence id.</span>
<span class="source-line-no">591</span><span id="line-591"> * @param majorCompaction True if this file is product of a major compaction</span>
<span class="source-line-no">592</span><span id="line-592"> * @throws IOException problem writing to FS</span>
<span class="source-line-no">593</span><span id="line-593"> */</span>
<span class="source-line-no">594</span><span id="line-594"> private void appendMetadata(final long maxSequenceId, final boolean majorCompaction)</span>
<span class="source-line-no">595</span><span id="line-595"> throws IOException {</span>
<span class="source-line-no">596</span><span id="line-596"> appendMetadata(maxSequenceId, majorCompaction, Collections.emptySet());</span>
<span class="source-line-no">597</span><span id="line-597"> }</span>
<span class="source-line-no">598</span><span id="line-598"></span>
<span class="source-line-no">599</span><span id="line-599"> /**</span>
<span class="source-line-no">600</span><span id="line-600"> * Writes meta data. Call before {@link #close()} since its written as meta data to this file.</span>
<span class="source-line-no">601</span><span id="line-601"> * @param maxSequenceId Maximum sequence id.</span>
<span class="source-line-no">602</span><span id="line-602"> * @param majorCompaction True if this file is product of a major compaction</span>
<span class="source-line-no">603</span><span id="line-603"> * @param storeFiles The compacted store files to generate this new file</span>
<span class="source-line-no">604</span><span id="line-604"> * @throws IOException problem writing to FS</span>
<span class="source-line-no">605</span><span id="line-605"> */</span>
<span class="source-line-no">606</span><span id="line-606"> private void appendMetadata(final long maxSequenceId, final boolean majorCompaction,</span>
<span class="source-line-no">607</span><span id="line-607"> final Collection&lt;HStoreFile&gt; storeFiles) throws IOException {</span>
<span class="source-line-no">608</span><span id="line-608"> writer.appendFileInfo(MAX_SEQ_ID_KEY, Bytes.toBytes(maxSequenceId));</span>
<span class="source-line-no">609</span><span id="line-609"> writer.appendFileInfo(MAJOR_COMPACTION_KEY, Bytes.toBytes(majorCompaction));</span>
<span class="source-line-no">610</span><span id="line-610"> writer.appendFileInfo(COMPACTION_EVENT_KEY, toCompactionEventTrackerBytes(storeFiles));</span>
<span class="source-line-no">611</span><span id="line-611"> appendTrackedTimestampsToMetadata();</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"> /**</span>
<span class="source-line-no">615</span><span id="line-615"> * Used when write {@link HStoreFile#COMPACTION_EVENT_KEY} to new file's file info. The</span>
<span class="source-line-no">616</span><span id="line-616"> * compacted store files's name is needed. But if the compacted store file is a result of</span>
<span class="source-line-no">617</span><span id="line-617"> * compaction, it's compacted files which still not archived is needed, too. And don't need to</span>
<span class="source-line-no">618</span><span id="line-618"> * add compacted files recursively. If file A, B, C compacted to new file D, and file D</span>
<span class="source-line-no">619</span><span id="line-619"> * compacted to new file E, will write A, B, C, D to file E's compacted files. So if file E</span>
<span class="source-line-no">620</span><span id="line-620"> * compacted to new file F, will add E to F's compacted files first, then add E's compacted</span>
<span class="source-line-no">621</span><span id="line-621"> * files: A, B, C, D to it. And no need to add D's compacted file, as D's compacted files has</span>
<span class="source-line-no">622</span><span id="line-622"> * been in E's compacted files, too. See HBASE-20724 for more details.</span>
<span class="source-line-no">623</span><span id="line-623"> * @param storeFiles The compacted store files to generate this new file</span>
<span class="source-line-no">624</span><span id="line-624"> * @return bytes of CompactionEventTracker</span>
<span class="source-line-no">625</span><span id="line-625"> */</span>
<span class="source-line-no">626</span><span id="line-626"> private byte[] toCompactionEventTrackerBytes(Collection&lt;HStoreFile&gt; storeFiles) {</span>
<span class="source-line-no">627</span><span id="line-627"> Set&lt;String&gt; notArchivedCompactedStoreFiles = this.compactedFilesSupplier.get().stream()</span>
<span class="source-line-no">628</span><span id="line-628"> .map(sf -&gt; sf.getPath().getName()).collect(Collectors.toSet());</span>
<span class="source-line-no">629</span><span id="line-629"> Set&lt;String&gt; compactedStoreFiles = new HashSet&lt;&gt;();</span>
<span class="source-line-no">630</span><span id="line-630"> for (HStoreFile storeFile : storeFiles) {</span>
<span class="source-line-no">631</span><span id="line-631"> compactedStoreFiles.add(storeFile.getFileInfo().getPath().getName());</span>
<span class="source-line-no">632</span><span id="line-632"> for (String csf : storeFile.getCompactedStoreFiles()) {</span>
<span class="source-line-no">633</span><span id="line-633"> if (notArchivedCompactedStoreFiles.contains(csf)) {</span>
<span class="source-line-no">634</span><span id="line-634"> compactedStoreFiles.add(csf);</span>
<span class="source-line-no">635</span><span id="line-635"> }</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"> return ProtobufUtil.toCompactionEventTrackerBytes(compactedStoreFiles);</span>
<span class="source-line-no">639</span><span id="line-639"> }</span>
<span class="source-line-no">640</span><span id="line-640"></span>
<span class="source-line-no">641</span><span id="line-641"> /**</span>
<span class="source-line-no">642</span><span id="line-642"> * Writes meta data. Call before {@link #close()} since its written as meta data to this file.</span>
<span class="source-line-no">643</span><span id="line-643"> * @param maxSequenceId Maximum sequence id.</span>
<span class="source-line-no">644</span><span id="line-644"> * @param majorCompaction True if this file is product of a major compaction</span>
<span class="source-line-no">645</span><span id="line-645"> * @param mobCellsCount The number of mob cells.</span>
<span class="source-line-no">646</span><span id="line-646"> * @throws IOException problem writing to FS</span>
<span class="source-line-no">647</span><span id="line-647"> */</span>
<span class="source-line-no">648</span><span id="line-648"> private void appendMetadata(final long maxSequenceId, final boolean majorCompaction,</span>
<span class="source-line-no">649</span><span id="line-649"> final long mobCellsCount) throws IOException {</span>
<span class="source-line-no">650</span><span id="line-650"> writer.appendFileInfo(MAX_SEQ_ID_KEY, Bytes.toBytes(maxSequenceId));</span>
<span class="source-line-no">651</span><span id="line-651"> writer.appendFileInfo(MAJOR_COMPACTION_KEY, Bytes.toBytes(majorCompaction));</span>
<span class="source-line-no">652</span><span id="line-652"> writer.appendFileInfo(MOB_CELLS_COUNT, Bytes.toBytes(mobCellsCount));</span>
<span class="source-line-no">653</span><span id="line-653"> appendTrackedTimestampsToMetadata();</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"> * Appends MOB - specific metadata (even if it is empty)</span>
<span class="source-line-no">658</span><span id="line-658"> * @param mobRefSet - original table -&gt; set of MOB file names</span>
<span class="source-line-no">659</span><span id="line-659"> * @throws IOException problem writing to FS</span>
<span class="source-line-no">660</span><span id="line-660"> */</span>
<span class="source-line-no">661</span><span id="line-661"> private void appendMobMetadata(SetMultimap&lt;TableName, String&gt; mobRefSet) throws IOException {</span>
<span class="source-line-no">662</span><span id="line-662"> writer.appendFileInfo(MOB_FILE_REFS, MobUtils.serializeMobFileRefs(mobRefSet));</span>
<span class="source-line-no">663</span><span id="line-663"> }</span>
<span class="source-line-no">664</span><span id="line-664"></span>
<span class="source-line-no">665</span><span id="line-665"> /**</span>
<span class="source-line-no">666</span><span id="line-666"> * Add TimestampRange and earliest put timestamp to Metadata</span>
<span class="source-line-no">667</span><span id="line-667"> */</span>
<span class="source-line-no">668</span><span id="line-668"> private void appendTrackedTimestampsToMetadata() throws IOException {</span>
<span class="source-line-no">669</span><span id="line-669"> // TODO: The StoreFileReader always converts the byte[] to TimeRange</span>
<span class="source-line-no">670</span><span id="line-670"> // via TimeRangeTracker, so we should write the serialization data of TimeRange directly.</span>
<span class="source-line-no">671</span><span id="line-671"> appendFileInfo(TIMERANGE_KEY, TimeRangeTracker.toByteArray(timeRangeTracker));</span>
<span class="source-line-no">672</span><span id="line-672"> appendFileInfo(EARLIEST_PUT_TS, Bytes.toBytes(earliestPutTs));</span>
<span class="source-line-no">673</span><span id="line-673"> }</span>
<span class="source-line-no">674</span><span id="line-674"></span>
<span class="source-line-no">675</span><span id="line-675"> /**</span>
<span class="source-line-no">676</span><span id="line-676"> * Record the earlest Put timestamp. If the timeRangeTracker is not set, update TimeRangeTracker</span>
<span class="source-line-no">677</span><span id="line-677"> * to include the timestamp of this key</span>
<span class="source-line-no">678</span><span id="line-678"> */</span>
<span class="source-line-no">679</span><span id="line-679"> private void trackTimestamps(final ExtendedCell cell) {</span>
<span class="source-line-no">680</span><span id="line-680"> if (KeyValue.Type.Put.getCode() == cell.getTypeByte()) {</span>
<span class="source-line-no">681</span><span id="line-681"> earliestPutTs = Math.min(earliestPutTs, cell.getTimestamp());</span>
<span class="source-line-no">682</span><span id="line-682"> }</span>
<span class="source-line-no">683</span><span id="line-683"> timeRangeTracker.includeTimestamp(cell);</span>
<span class="source-line-no">684</span><span id="line-684"> }</span>
<span class="source-line-no">685</span><span id="line-685"></span>
<span class="source-line-no">686</span><span id="line-686"> private void appendGeneralBloomfilter(final ExtendedCell cell) throws IOException {</span>
<span class="source-line-no">687</span><span id="line-687"> if (this.generalBloomFilterWriter != null) {</span>
<span class="source-line-no">688</span><span id="line-688"> /*</span>
<span class="source-line-no">689</span><span id="line-689"> * http://2.bp.blogspot.com/_Cib_A77V54U/StZMrzaKufI/AAAAAAAAADo/ZhK7bGoJdMQ/s400/KeyValue.</span>
<span class="source-line-no">690</span><span id="line-690"> * png Key = RowLen + Row + FamilyLen + Column [Family + Qualifier] + Timestamp 3 Types of</span>
<span class="source-line-no">691</span><span id="line-691"> * Filtering: 1. Row = Row 2. RowCol = Row + Qualifier 3. RowPrefixFixedLength = Fixed</span>
<span class="source-line-no">692</span><span id="line-692"> * Length Row Prefix</span>
<span class="source-line-no">693</span><span id="line-693"> */</span>
<span class="source-line-no">694</span><span id="line-694"> bloomContext.writeBloom(cell);</span>
<span class="source-line-no">695</span><span id="line-695"> }</span>
<span class="source-line-no">696</span><span id="line-696"> }</span>
<span class="source-line-no">697</span><span id="line-697"></span>
<span class="source-line-no">698</span><span id="line-698"> private void appendDeleteFamilyBloomFilter(final ExtendedCell cell) throws IOException {</span>
<span class="source-line-no">699</span><span id="line-699"> if (!PrivateCellUtil.isDeleteFamily(cell) &amp;&amp; !PrivateCellUtil.isDeleteFamilyVersion(cell)) {</span>
<span class="source-line-no">700</span><span id="line-700"> return;</span>
<span class="source-line-no">701</span><span id="line-701"> }</span>
<span class="source-line-no">702</span><span id="line-702"></span>
<span class="source-line-no">703</span><span id="line-703"> // increase the number of delete family in the store file</span>
<span class="source-line-no">704</span><span id="line-704"> deleteFamilyCnt++;</span>
<span class="source-line-no">705</span><span id="line-705"> if (this.deleteFamilyBloomFilterWriter != null) {</span>
<span class="source-line-no">706</span><span id="line-706"> deleteFamilyBloomContext.writeBloom(cell);</span>
<span class="source-line-no">707</span><span id="line-707"> }</span>
<span class="source-line-no">708</span><span id="line-708"> }</span>
<span class="source-line-no">709</span><span id="line-709"></span>
<span class="source-line-no">710</span><span id="line-710"> private void append(final ExtendedCell cell) throws IOException {</span>
<span class="source-line-no">711</span><span id="line-711"> appendGeneralBloomfilter(cell);</span>
<span class="source-line-no">712</span><span id="line-712"> appendDeleteFamilyBloomFilter(cell);</span>
<span class="source-line-no">713</span><span id="line-713"> writer.append(cell);</span>
<span class="source-line-no">714</span><span id="line-714"> trackTimestamps(cell);</span>
<span class="source-line-no">715</span><span id="line-715"> }</span>
<span class="source-line-no">716</span><span id="line-716"></span>
<span class="source-line-no">717</span><span id="line-717"> private void beforeShipped() throws IOException {</span>
<span class="source-line-no">718</span><span id="line-718"> // For now these writer will always be of type ShipperListener true.</span>
<span class="source-line-no">719</span><span id="line-719"> // TODO : Change all writers to be specifically created for compaction context</span>
<span class="source-line-no">720</span><span id="line-720"> writer.beforeShipped();</span>
<span class="source-line-no">721</span><span id="line-721"> if (generalBloomFilterWriter != null) {</span>
<span class="source-line-no">722</span><span id="line-722"> generalBloomFilterWriter.beforeShipped();</span>
<span class="source-line-no">723</span><span id="line-723"> }</span>
<span class="source-line-no">724</span><span id="line-724"> if (deleteFamilyBloomFilterWriter != null) {</span>
<span class="source-line-no">725</span><span id="line-725"> deleteFamilyBloomFilterWriter.beforeShipped();</span>
<span class="source-line-no">726</span><span id="line-726"> }</span>
<span class="source-line-no">727</span><span id="line-727"> }</span>
<span class="source-line-no">728</span><span id="line-728"></span>
<span class="source-line-no">729</span><span id="line-729"> private Path getPath() {</span>
<span class="source-line-no">730</span><span id="line-730"> return this.writer.getPath();</span>
<span class="source-line-no">731</span><span id="line-731"> }</span>
<span class="source-line-no">732</span><span id="line-732"></span>
<span class="source-line-no">733</span><span id="line-733"> private boolean hasGeneralBloom() {</span>
<span class="source-line-no">734</span><span id="line-734"> return this.generalBloomFilterWriter != null;</span>
<span class="source-line-no">735</span><span id="line-735"> }</span>
<span class="source-line-no">736</span><span id="line-736"></span>
<span class="source-line-no">737</span><span id="line-737"> /**</span>
<span class="source-line-no">738</span><span id="line-738"> * For unit testing only.</span>
<span class="source-line-no">739</span><span id="line-739"> * @return the Bloom filter used by this writer.</span>
<span class="source-line-no">740</span><span id="line-740"> */</span>
<span class="source-line-no">741</span><span id="line-741"> BloomFilterWriter getGeneralBloomWriter() {</span>
<span class="source-line-no">742</span><span id="line-742"> return generalBloomFilterWriter;</span>
<span class="source-line-no">743</span><span id="line-743"> }</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 boolean closeBloomFilter(BloomFilterWriter bfw) throws IOException {</span>
<span class="source-line-no">746</span><span id="line-746"> boolean haveBloom = (bfw != null &amp;&amp; bfw.getKeyCount() &gt; 0);</span>
<span class="source-line-no">747</span><span id="line-747"> if (haveBloom) {</span>
<span class="source-line-no">748</span><span id="line-748"> bfw.compactBloom();</span>
<span class="source-line-no">749</span><span id="line-749"> }</span>
<span class="source-line-no">750</span><span id="line-750"> return haveBloom;</span>
<span class="source-line-no">751</span><span id="line-751"> }</span>
<span class="source-line-no">752</span><span id="line-752"></span>
<span class="source-line-no">753</span><span id="line-753"> private boolean closeGeneralBloomFilter() throws IOException {</span>
<span class="source-line-no">754</span><span id="line-754"> boolean hasGeneralBloom = closeBloomFilter(generalBloomFilterWriter);</span>
<span class="source-line-no">755</span><span id="line-755"></span>
<span class="source-line-no">756</span><span id="line-756"> // add the general Bloom filter writer and append file info</span>
<span class="source-line-no">757</span><span id="line-757"> if (hasGeneralBloom) {</span>
<span class="source-line-no">758</span><span id="line-758"> writer.addGeneralBloomFilter(generalBloomFilterWriter);</span>
<span class="source-line-no">759</span><span id="line-759"> writer.appendFileInfo(BLOOM_FILTER_TYPE_KEY, Bytes.toBytes(bloomType.toString()));</span>
<span class="source-line-no">760</span><span id="line-760"> if (bloomParam != null) {</span>
<span class="source-line-no">761</span><span id="line-761"> writer.appendFileInfo(BLOOM_FILTER_PARAM_KEY, bloomParam);</span>
<span class="source-line-no">762</span><span id="line-762"> }</span>
<span class="source-line-no">763</span><span id="line-763"> bloomContext.addLastBloomKey(writer);</span>
<span class="source-line-no">764</span><span id="line-764"> }</span>
<span class="source-line-no">765</span><span id="line-765"> return hasGeneralBloom;</span>
<span class="source-line-no">766</span><span id="line-766"> }</span>
<span class="source-line-no">767</span><span id="line-767"></span>
<span class="source-line-no">768</span><span id="line-768"> private boolean closeDeleteFamilyBloomFilter() throws IOException {</span>
<span class="source-line-no">769</span><span id="line-769"> boolean hasDeleteFamilyBloom = closeBloomFilter(deleteFamilyBloomFilterWriter);</span>
<span class="source-line-no">770</span><span id="line-770"></span>
<span class="source-line-no">771</span><span id="line-771"> // add the delete family Bloom filter writer</span>
<span class="source-line-no">772</span><span id="line-772"> if (hasDeleteFamilyBloom) {</span>
<span class="source-line-no">773</span><span id="line-773"> writer.addDeleteFamilyBloomFilter(deleteFamilyBloomFilterWriter);</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"> // append file info about the number of delete family kvs</span>
<span class="source-line-no">777</span><span id="line-777"> // even if there is no delete family Bloom.</span>
<span class="source-line-no">778</span><span id="line-778"> writer.appendFileInfo(DELETE_FAMILY_COUNT, Bytes.toBytes(this.deleteFamilyCnt));</span>
<span class="source-line-no">779</span><span id="line-779"></span>
<span class="source-line-no">780</span><span id="line-780"> return hasDeleteFamilyBloom;</span>
<span class="source-line-no">781</span><span id="line-781"> }</span>
<span class="source-line-no">782</span><span id="line-782"></span>
<span class="source-line-no">783</span><span id="line-783"> private void close() throws IOException {</span>
<span class="source-line-no">784</span><span id="line-784"> boolean hasGeneralBloom = this.closeGeneralBloomFilter();</span>
<span class="source-line-no">785</span><span id="line-785"> boolean hasDeleteFamilyBloom = this.closeDeleteFamilyBloomFilter();</span>
<span class="source-line-no">786</span><span id="line-786"></span>
<span class="source-line-no">787</span><span id="line-787"> writer.close();</span>
<span class="source-line-no">788</span><span id="line-788"></span>
<span class="source-line-no">789</span><span id="line-789"> // Log final Bloom filter statistics. This needs to be done after close()</span>
<span class="source-line-no">790</span><span id="line-790"> // because compound Bloom filters might be finalized as part of closing.</span>
<span class="source-line-no">791</span><span id="line-791"> if (LOG.isTraceEnabled()) {</span>
<span class="source-line-no">792</span><span id="line-792"> LOG.trace((hasGeneralBloom ? "" : "NO ") + "General Bloom and "</span>
<span class="source-line-no">793</span><span id="line-793"> + (hasDeleteFamilyBloom ? "" : "NO ") + "DeleteFamily" + " was added to HFile "</span>
<span class="source-line-no">794</span><span id="line-794"> + getPath());</span>
<span class="source-line-no">795</span><span id="line-795"> }</span>
<span class="source-line-no">796</span><span id="line-796"></span>
<span class="source-line-no">797</span><span id="line-797"> }</span>
<span class="source-line-no">798</span><span id="line-798"></span>
<span class="source-line-no">799</span><span id="line-799"> private void appendFileInfo(byte[] key, byte[] value) throws IOException {</span>
<span class="source-line-no">800</span><span id="line-800"> writer.appendFileInfo(key, value);</span>
<span class="source-line-no">801</span><span id="line-801"> }</span>
<span class="source-line-no">802</span><span id="line-802"></span>
<span class="source-line-no">803</span><span id="line-803"> /**</span>
<span class="source-line-no">804</span><span id="line-804"> * For use in testing.</span>
<span class="source-line-no">805</span><span id="line-805"> */</span>
<span class="source-line-no">806</span><span id="line-806"> private HFile.Writer getHFileWriter() {</span>
<span class="source-line-no">807</span><span id="line-807"> return writer;</span>
<span class="source-line-no">808</span><span id="line-808"> }</span>
<span class="source-line-no">809</span><span id="line-809"> }</span>
<span class="source-line-no">810</span><span id="line-810"></span>
<span class="source-line-no">811</span><span id="line-811"> @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "ICAST_INTEGER_MULTIPLY_CAST_TO_LONG",</span>
<span class="source-line-no">812</span><span id="line-812"> justification = "Will not overflow")</span>
<span class="source-line-no">813</span><span id="line-813"> public static class Builder {</span>
<span class="source-line-no">814</span><span id="line-814"> private final Configuration conf;</span>
<span class="source-line-no">815</span><span id="line-815"> private final CacheConfig cacheConf;</span>
<span class="source-line-no">816</span><span id="line-816"> private final FileSystem fs;</span>
<span class="source-line-no">817</span><span id="line-817"></span>
<span class="source-line-no">818</span><span id="line-818"> private BloomType bloomType = BloomType.NONE;</span>
<span class="source-line-no">819</span><span id="line-819"> private long maxKeyCount = 0;</span>
<span class="source-line-no">820</span><span id="line-820"> private Path dir;</span>
<span class="source-line-no">821</span><span id="line-821"> private Path liveFilePath;</span>
<span class="source-line-no">822</span><span id="line-822"> private Path historicalFilePath;</span>
<span class="source-line-no">823</span><span id="line-823"></span>
<span class="source-line-no">824</span><span id="line-824"> private InetSocketAddress[] favoredNodes;</span>
<span class="source-line-no">825</span><span id="line-825"> private HFileContext fileContext;</span>
<span class="source-line-no">826</span><span id="line-826"> private boolean shouldDropCacheBehind;</span>
<span class="source-line-no">827</span><span id="line-827"> private Supplier&lt;Collection&lt;HStoreFile&gt;&gt; compactedFilesSupplier = () -&gt; Collections.emptySet();</span>
<span class="source-line-no">828</span><span id="line-828"> private String fileStoragePolicy;</span>
<span class="source-line-no">829</span><span id="line-829"> // this is used to track the creation of the StoreFileWriter, mainly used for the SFT</span>
<span class="source-line-no">830</span><span id="line-830"> // implementation where we will write store files directly to the final place, instead of</span>
<span class="source-line-no">831</span><span id="line-831"> // writing a tmp file first. Under this scenario, we will have a background task to purge the</span>
<span class="source-line-no">832</span><span id="line-832"> // store files which are not recorded in the SFT, but for the newly created store file writer,</span>
<span class="source-line-no">833</span><span id="line-833"> // they are not tracked in SFT, so here we need to record them and treat them specially.</span>
<span class="source-line-no">834</span><span id="line-834"> private Consumer&lt;Path&gt; writerCreationTracker;</span>
<span class="source-line-no">835</span><span id="line-835"> private int maxVersions;</span>
<span class="source-line-no">836</span><span id="line-836"> private boolean newVersionBehavior;</span>
<span class="source-line-no">837</span><span id="line-837"> private CellComparator comparator;</span>
<span class="source-line-no">838</span><span id="line-838"> private boolean isCompaction;</span>
<span class="source-line-no">839</span><span id="line-839"></span>
<span class="source-line-no">840</span><span id="line-840"> public Builder(Configuration conf, CacheConfig cacheConf, FileSystem fs) {</span>
<span class="source-line-no">841</span><span id="line-841"> this.conf = conf;</span>
<span class="source-line-no">842</span><span id="line-842"> this.cacheConf = cacheConf;</span>
<span class="source-line-no">843</span><span id="line-843"> this.fs = fs;</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"> /**</span>
<span class="source-line-no">847</span><span id="line-847"> * Creates Builder with cache configuration disabled</span>
<span class="source-line-no">848</span><span id="line-848"> */</span>
<span class="source-line-no">849</span><span id="line-849"> public Builder(Configuration conf, FileSystem fs) {</span>
<span class="source-line-no">850</span><span id="line-850"> this.conf = conf;</span>
<span class="source-line-no">851</span><span id="line-851"> this.cacheConf = CacheConfig.DISABLED;</span>
<span class="source-line-no">852</span><span id="line-852"> this.fs = fs;</span>
<span class="source-line-no">853</span><span id="line-853"> }</span>
<span class="source-line-no">854</span><span id="line-854"></span>
<span class="source-line-no">855</span><span id="line-855"> /**</span>
<span class="source-line-no">856</span><span id="line-856"> * Use either this method or {@link #withFilePath}, but not both.</span>
<span class="source-line-no">857</span><span id="line-857"> * @param dir Path to column family directory. The directory is created if does not exist. The</span>
<span class="source-line-no">858</span><span id="line-858"> * file is given a unique name within this directory.</span>
<span class="source-line-no">859</span><span id="line-859"> * @return this (for chained invocation)</span>
<span class="source-line-no">860</span><span id="line-860"> */</span>
<span class="source-line-no">861</span><span id="line-861"> public Builder withOutputDir(Path dir) {</span>
<span class="source-line-no">862</span><span id="line-862"> Preconditions.checkNotNull(dir);</span>
<span class="source-line-no">863</span><span id="line-863"> this.dir = dir;</span>
<span class="source-line-no">864</span><span id="line-864"> return this;</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"> /**</span>
<span class="source-line-no">868</span><span id="line-868"> * Use either this method or {@link #withOutputDir}, but not both.</span>
<span class="source-line-no">869</span><span id="line-869"> * @param filePath the StoreFile path to write</span>
<span class="source-line-no">870</span><span id="line-870"> * @return this (for chained invocation)</span>
<span class="source-line-no">871</span><span id="line-871"> */</span>
<span class="source-line-no">872</span><span id="line-872"> public Builder withFilePath(Path filePath) {</span>
<span class="source-line-no">873</span><span id="line-873"> Preconditions.checkNotNull(filePath);</span>
<span class="source-line-no">874</span><span id="line-874"> this.liveFilePath = filePath;</span>
<span class="source-line-no">875</span><span id="line-875"> return this;</span>
<span class="source-line-no">876</span><span id="line-876"> }</span>
<span class="source-line-no">877</span><span id="line-877"></span>
<span class="source-line-no">878</span><span id="line-878"> /**</span>
<span class="source-line-no">879</span><span id="line-879"> * @param favoredNodes an array of favored nodes or possibly null</span>
<span class="source-line-no">880</span><span id="line-880"> * @return this (for chained invocation)</span>
<span class="source-line-no">881</span><span id="line-881"> */</span>
<span class="source-line-no">882</span><span id="line-882"> public Builder withFavoredNodes(InetSocketAddress[] favoredNodes) {</span>
<span class="source-line-no">883</span><span id="line-883"> this.favoredNodes = favoredNodes;</span>
<span class="source-line-no">884</span><span id="line-884"> return this;</span>
<span class="source-line-no">885</span><span id="line-885"> }</span>
<span class="source-line-no">886</span><span id="line-886"></span>
<span class="source-line-no">887</span><span id="line-887"> public Builder withBloomType(BloomType bloomType) {</span>
<span class="source-line-no">888</span><span id="line-888"> Preconditions.checkNotNull(bloomType);</span>
<span class="source-line-no">889</span><span id="line-889"> this.bloomType = bloomType;</span>
<span class="source-line-no">890</span><span id="line-890"> return this;</span>
<span class="source-line-no">891</span><span id="line-891"> }</span>
<span class="source-line-no">892</span><span id="line-892"></span>
<span class="source-line-no">893</span><span id="line-893"> /**</span>
<span class="source-line-no">894</span><span id="line-894"> * @param maxKeyCount estimated maximum number of keys we expect to add</span>
<span class="source-line-no">895</span><span id="line-895"> * @return this (for chained invocation)</span>
<span class="source-line-no">896</span><span id="line-896"> */</span>
<span class="source-line-no">897</span><span id="line-897"> public Builder withMaxKeyCount(long maxKeyCount) {</span>
<span class="source-line-no">898</span><span id="line-898"> this.maxKeyCount = maxKeyCount;</span>
<span class="source-line-no">899</span><span id="line-899"> return this;</span>
<span class="source-line-no">900</span><span id="line-900"> }</span>
<span class="source-line-no">901</span><span id="line-901"></span>
<span class="source-line-no">902</span><span id="line-902"> public Builder withFileContext(HFileContext fileContext) {</span>
<span class="source-line-no">903</span><span id="line-903"> this.fileContext = fileContext;</span>
<span class="source-line-no">904</span><span id="line-904"> return this;</span>
<span class="source-line-no">905</span><span id="line-905"> }</span>
<span class="source-line-no">906</span><span id="line-906"></span>
<span class="source-line-no">907</span><span id="line-907"> public Builder withShouldDropCacheBehind(boolean shouldDropCacheBehind) {</span>
<span class="source-line-no">908</span><span id="line-908"> this.shouldDropCacheBehind = shouldDropCacheBehind;</span>
<span class="source-line-no">909</span><span id="line-909"> return this;</span>
<span class="source-line-no">910</span><span id="line-910"> }</span>
<span class="source-line-no">911</span><span id="line-911"></span>
<span class="source-line-no">912</span><span id="line-912"> public Builder</span>
<span class="source-line-no">913</span><span id="line-913"> withCompactedFilesSupplier(Supplier&lt;Collection&lt;HStoreFile&gt;&gt; compactedFilesSupplier) {</span>
<span class="source-line-no">914</span><span id="line-914"> this.compactedFilesSupplier = compactedFilesSupplier;</span>
<span class="source-line-no">915</span><span id="line-915"> return this;</span>
<span class="source-line-no">916</span><span id="line-916"> }</span>
<span class="source-line-no">917</span><span id="line-917"></span>
<span class="source-line-no">918</span><span id="line-918"> public Builder withFileStoragePolicy(String fileStoragePolicy) {</span>
<span class="source-line-no">919</span><span id="line-919"> this.fileStoragePolicy = fileStoragePolicy;</span>
<span class="source-line-no">920</span><span id="line-920"> return this;</span>
<span class="source-line-no">921</span><span id="line-921"> }</span>
<span class="source-line-no">922</span><span id="line-922"></span>
<span class="source-line-no">923</span><span id="line-923"> public Builder withWriterCreationTracker(Consumer&lt;Path&gt; writerCreationTracker) {</span>
<span class="source-line-no">924</span><span id="line-924"> this.writerCreationTracker = writerCreationTracker;</span>
<span class="source-line-no">925</span><span id="line-925"> return this;</span>
<span class="source-line-no">926</span><span id="line-926"> }</span>
<span class="source-line-no">927</span><span id="line-927"></span>
<span class="source-line-no">928</span><span id="line-928"> public Builder withMaxVersions(int maxVersions) {</span>
<span class="source-line-no">929</span><span id="line-929"> this.maxVersions = maxVersions;</span>
<span class="source-line-no">930</span><span id="line-930"> return this;</span>
<span class="source-line-no">931</span><span id="line-931"> }</span>
<span class="source-line-no">932</span><span id="line-932"></span>
<span class="source-line-no">933</span><span id="line-933"> public Builder withNewVersionBehavior(boolean newVersionBehavior) {</span>
<span class="source-line-no">934</span><span id="line-934"> this.newVersionBehavior = newVersionBehavior;</span>
<span class="source-line-no">935</span><span id="line-935"> return this;</span>
<span class="source-line-no">936</span><span id="line-936"> }</span>
<span class="source-line-no">937</span><span id="line-937"></span>
<span class="source-line-no">938</span><span id="line-938"> public Builder withCellComparator(CellComparator comparator) {</span>
<span class="source-line-no">939</span><span id="line-939"> this.comparator = comparator;</span>
<span class="source-line-no">940</span><span id="line-940"> return this;</span>
<span class="source-line-no">941</span><span id="line-941"> }</span>
<span class="source-line-no">942</span><span id="line-942"></span>
<span class="source-line-no">943</span><span id="line-943"> public Builder withIsCompaction(boolean isCompaction) {</span>
<span class="source-line-no">944</span><span id="line-944"> this.isCompaction = isCompaction;</span>
<span class="source-line-no">945</span><span id="line-945"> return this;</span>
<span class="source-line-no">946</span><span id="line-946"> }</span>
<span class="source-line-no">947</span><span id="line-947"></span>
<span class="source-line-no">948</span><span id="line-948"> /**</span>
<span class="source-line-no">949</span><span id="line-949"> * Create a store file writer. Client is responsible for closing file when done. If metadata,</span>
<span class="source-line-no">950</span><span id="line-950"> * add BEFORE closing using {@link StoreFileWriter#appendMetadata}.</span>
<span class="source-line-no">951</span><span id="line-951"> */</span>
<span class="source-line-no">952</span><span id="line-952"> public StoreFileWriter build() throws IOException {</span>
<span class="source-line-no">953</span><span id="line-953"> if ((dir == null ? 0 : 1) + (liveFilePath == null ? 0 : 1) != 1) {</span>
<span class="source-line-no">954</span><span id="line-954"> throw new IllegalArgumentException("Either specify parent directory " + "or file path");</span>
<span class="source-line-no">955</span><span id="line-955"> }</span>
<span class="source-line-no">956</span><span id="line-956"></span>
<span class="source-line-no">957</span><span id="line-957"> if (dir == null) {</span>
<span class="source-line-no">958</span><span id="line-958"> dir = liveFilePath.getParent();</span>
<span class="source-line-no">959</span><span id="line-959"> }</span>
<span class="source-line-no">960</span><span id="line-960"></span>
<span class="source-line-no">961</span><span id="line-961"> if (!fs.exists(dir)) {</span>
<span class="source-line-no">962</span><span id="line-962"> // Handle permission for non-HDFS filesystem properly</span>
<span class="source-line-no">963</span><span id="line-963"> // See HBASE-17710</span>
<span class="source-line-no">964</span><span id="line-964"> HRegionFileSystem.mkdirs(fs, conf, dir);</span>
<span class="source-line-no">965</span><span id="line-965"> }</span>
<span class="source-line-no">966</span><span id="line-966"></span>
<span class="source-line-no">967</span><span id="line-967"> // set block storage policy for temp path</span>
<span class="source-line-no">968</span><span id="line-968"> String policyName = this.conf.get(ColumnFamilyDescriptorBuilder.STORAGE_POLICY);</span>
<span class="source-line-no">969</span><span id="line-969"> if (null == policyName) {</span>
<span class="source-line-no">970</span><span id="line-970"> policyName = this.conf.get(HStore.BLOCK_STORAGE_POLICY_KEY);</span>
<span class="source-line-no">971</span><span id="line-971"> }</span>
<span class="source-line-no">972</span><span id="line-972"> CommonFSUtils.setStoragePolicy(this.fs, dir, policyName);</span>
<span class="source-line-no">973</span><span id="line-973"></span>
<span class="source-line-no">974</span><span id="line-974"> if (liveFilePath == null) {</span>
<span class="source-line-no">975</span><span id="line-975"> // The stored file and related blocks will used the directory based StoragePolicy.</span>
<span class="source-line-no">976</span><span id="line-976"> // Because HDFS DistributedFileSystem does not support create files with storage policy</span>
<span class="source-line-no">977</span><span id="line-977"> // before version 3.3.0 (See HDFS-13209). Use child dir here is to make stored files</span>
<span class="source-line-no">978</span><span id="line-978"> // satisfy the specific storage policy when writing. So as to avoid later data movement.</span>
<span class="source-line-no">979</span><span id="line-979"> // We don't want to change whole temp dir to 'fileStoragePolicy'.</span>
<span class="source-line-no">980</span><span id="line-980"> if (!Strings.isNullOrEmpty(fileStoragePolicy)) {</span>
<span class="source-line-no">981</span><span id="line-981"> dir = new Path(dir, HConstants.STORAGE_POLICY_PREFIX + fileStoragePolicy);</span>
<span class="source-line-no">982</span><span id="line-982"> if (!fs.exists(dir)) {</span>
<span class="source-line-no">983</span><span id="line-983"> HRegionFileSystem.mkdirs(fs, conf, dir);</span>
<span class="source-line-no">984</span><span id="line-984"> LOG.info(</span>
<span class="source-line-no">985</span><span id="line-985"> "Create tmp dir " + dir.toString() + " with storage policy: " + fileStoragePolicy);</span>
<span class="source-line-no">986</span><span id="line-986"> }</span>
<span class="source-line-no">987</span><span id="line-987"> CommonFSUtils.setStoragePolicy(this.fs, dir, fileStoragePolicy);</span>
<span class="source-line-no">988</span><span id="line-988"> }</span>
<span class="source-line-no">989</span><span id="line-989"> liveFilePath = getUniqueFile(fs, dir);</span>
<span class="source-line-no">990</span><span id="line-990"> if (!BloomFilterFactory.isGeneralBloomEnabled(conf)) {</span>
<span class="source-line-no">991</span><span id="line-991"> bloomType = BloomType.NONE;</span>
<span class="source-line-no">992</span><span id="line-992"> }</span>
<span class="source-line-no">993</span><span id="line-993"> }</span>
<span class="source-line-no">994</span><span id="line-994"></span>
<span class="source-line-no">995</span><span id="line-995"> if (isCompaction &amp;&amp; shouldEnableHistoricalCompactionFiles(conf)) {</span>
<span class="source-line-no">996</span><span id="line-996"> historicalFilePath = getUniqueFile(fs, dir);</span>
<span class="source-line-no">997</span><span id="line-997"> }</span>
<span class="source-line-no">998</span><span id="line-998"></span>
<span class="source-line-no">999</span><span id="line-999"> // make sure we call this before actually create the writer</span>
<span class="source-line-no">1000</span><span id="line-1000"> // in fact, it is not a big deal to even add an inexistent file to the track, as we will never</span>
<span class="source-line-no">1001</span><span id="line-1001"> // try to delete it and finally we will clean the tracker up after compaction. But if the file</span>
<span class="source-line-no">1002</span><span id="line-1002"> // cleaner find the file but we haven't recorded it yet, it may accidentally delete the file</span>
<span class="source-line-no">1003</span><span id="line-1003"> // and cause problem.</span>
<span class="source-line-no">1004</span><span id="line-1004"> if (writerCreationTracker != null) {</span>
<span class="source-line-no">1005</span><span id="line-1005"> writerCreationTracker.accept(liveFilePath);</span>
<span class="source-line-no">1006</span><span id="line-1006"> if (historicalFilePath != null) {</span>
<span class="source-line-no">1007</span><span id="line-1007"> writerCreationTracker.accept(historicalFilePath);</span>
<span class="source-line-no">1008</span><span id="line-1008"> }</span>
<span class="source-line-no">1009</span><span id="line-1009"> }</span>
<span class="source-line-no">1010</span><span id="line-1010"> return new StoreFileWriter(fs, liveFilePath, historicalFilePath, conf, cacheConf, bloomType,</span>
<span class="source-line-no">1011</span><span id="line-1011"> maxKeyCount, favoredNodes, fileContext, shouldDropCacheBehind, compactedFilesSupplier,</span>
<span class="source-line-no">1012</span><span id="line-1012"> comparator, maxVersions, newVersionBehavior);</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>
</pre>
</div>
</main>
</body>
</html>