001/**
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements.  See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership.  The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License.  You may obtain a copy of the License at
010 *
011 *     http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 */
019package org.apache.hadoop.hbase.mob.compactions;
020
021import java.util.ArrayList;
022import java.util.Collection;
023import java.util.Collections;
024import java.util.List;
025
026import org.apache.hadoop.fs.FileStatus;
027import org.apache.hadoop.fs.Path;
028import org.apache.hadoop.hbase.regionserver.HStoreFile;
029import org.apache.hadoop.hbase.util.Bytes;
030import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
031import org.apache.yetus.audience.InterfaceAudience;
032
033/**
034 * An implementation of {@link MobCompactionRequest} that is used in
035 * {@link PartitionedMobCompactor}.
036 * The mob files that have the same start key and date in their names belong to
037 * the same partition.
038 */
039@InterfaceAudience.Private
040public class PartitionedMobCompactionRequest extends MobCompactionRequest {
041
042  protected List<CompactionDelPartition> delPartitions;
043  protected Collection<CompactionPartition> compactionPartitions;
044
045  public PartitionedMobCompactionRequest(Collection<CompactionPartition> compactionPartitions,
046    List<CompactionDelPartition> delPartitions) {
047    this.selectionTime = EnvironmentEdgeManager.currentTime();
048    this.compactionPartitions = compactionPartitions;
049    this.delPartitions = delPartitions;
050  }
051
052  /**
053   * Gets the compaction partitions.
054   * @return The compaction partitions.
055   */
056  public Collection<CompactionPartition> getCompactionPartitions() {
057    return this.compactionPartitions;
058  }
059
060  /**
061   * Gets the del files.
062   * @return The del files.
063   */
064  public List<CompactionDelPartition> getDelPartitions() {
065    return this.delPartitions;
066  }
067
068  /**
069   * The partition in the mob compaction.
070   * The mob files that have the same start key and date in their names belong to
071   * the same partition.
072   */
073  protected static class CompactionPartition {
074    private List<FileStatus> files = new ArrayList<>();
075    private CompactionPartitionId partitionId;
076
077    // The startKey and endKey of this partition, both are inclusive.
078    private byte[] startKey;
079    private byte[] endKey;
080
081    public CompactionPartition(CompactionPartitionId partitionId) {
082      this.partitionId = partitionId;
083    }
084
085    public CompactionPartitionId getPartitionId() {
086      return this.partitionId;
087    }
088
089    public void addFile(FileStatus file) {
090      files.add(file);
091    }
092
093    public List<FileStatus> listFiles() {
094      return Collections.unmodifiableList(files);
095    }
096
097    public int getFileCount () {
098      return files.size();
099    }
100
101    public byte[] getStartKey() {
102      return startKey;
103    }
104
105    /**
106     * Set start key of this partition, only if the input startKey is less than
107     * the current start key.
108     */
109    public void setStartKey(final byte[] startKey) {
110      if ((this.startKey == null) || (Bytes.compareTo(startKey, this.startKey) < 0)) {
111        this.startKey = startKey;
112      }
113    }
114
115    public byte[] getEndKey() {
116      return endKey;
117    }
118
119    /**
120     * Set end key of this partition, only if the input endKey is greater than
121     * the current end key.
122     */
123    public void setEndKey(final byte[] endKey) {
124      if ((this.endKey == null) || (Bytes.compareTo(endKey, this.endKey) > 0)) {
125        this.endKey = endKey;
126      }
127    }
128  }
129
130  /**
131   * The partition id that consists of start key and date of the mob file name.
132   */
133  public static class CompactionPartitionId {
134    private String startKey;
135    private String date;
136    private String latestDate;
137    private long threshold;
138
139    public CompactionPartitionId() {
140      // initialize these fields to empty string
141      this.startKey = "";
142      this.date = "";
143      this.latestDate = "";
144      this.threshold = 0;
145    }
146
147    public CompactionPartitionId(String startKey, String date) {
148      if (startKey == null || date == null) {
149        throw new IllegalArgumentException("Neither of start key and date could be null");
150      }
151      this.startKey = startKey;
152      this.date = date;
153      this.latestDate = "";
154      this.threshold = 0;
155    }
156
157    public void setThreshold (final long threshold) {
158      this.threshold = threshold;
159    }
160
161    public long getThreshold () {
162      return this.threshold;
163    }
164
165    public String getStartKey() {
166      return this.startKey;
167    }
168
169    public void setStartKey(final String startKey) {
170      this.startKey = startKey;
171    }
172
173    public String getDate() {
174      return this.date;
175    }
176
177    public void setDate(final String date) {
178      this.date = date;
179    }
180
181    public String getLatestDate () { return this.latestDate; }
182
183    public void updateLatestDate(final String latestDate) {
184      if (this.latestDate.compareTo(latestDate) < 0) {
185        this.latestDate = latestDate;
186      }
187    }
188
189    @Override
190    public int hashCode() {
191      int result = 17;
192      result = 31 * result + startKey.hashCode();
193      result = 31 * result + date.hashCode();
194      return result;
195    }
196
197    @Override
198    public boolean equals(Object obj) {
199      if (this == obj) {
200        return true;
201      }
202      if (!(obj instanceof CompactionPartitionId)) {
203        return false;
204      }
205      CompactionPartitionId another = (CompactionPartitionId) obj;
206      if (!this.startKey.equals(another.startKey)) {
207        return false;
208      }
209      if (!this.date.equals(another.date)) {
210        return false;
211      }
212      return true;
213    }
214
215    @Override
216    public String toString() {
217      return new StringBuilder(startKey).append(date).toString();
218    }
219  }
220
221  /**
222   * The delete file partition in the mob compaction.
223   * The delete partition is defined as [startKey, endKey] pair.
224   * The mob delete files that have the same start key and end key belong to
225   * the same partition.
226   */
227  protected static class CompactionDelPartition {
228    private List<Path> delFiles = new ArrayList<Path>();
229    private List<HStoreFile> storeFiles = new ArrayList<>();
230    private CompactionDelPartitionId id;
231
232    public CompactionDelPartition(CompactionDelPartitionId id) {
233      this.id = id;
234    }
235
236    public CompactionDelPartitionId getId() {
237      return this.id;
238    }
239
240    void addDelFile(FileStatus file) {
241      delFiles.add(file.getPath());
242    }
243    public void addStoreFile(HStoreFile file) {
244      storeFiles.add(file);
245    }
246
247    public List<HStoreFile> getStoreFiles() {
248      return storeFiles;
249    }
250
251    List<Path> listDelFiles() {
252      return Collections.unmodifiableList(delFiles);
253    }
254
255    void addDelFileList(final Collection<Path> list) {
256      delFiles.addAll(list);
257    }
258
259    int getDelFileCount () {
260      return delFiles.size();
261    }
262
263    void cleanDelFiles() {
264      delFiles.clear();
265    }
266  }
267
268  /**
269   * The delete partition id that consists of start key and end key
270   */
271  public static class CompactionDelPartitionId implements Comparable<CompactionDelPartitionId> {
272    private byte[] startKey;
273    private byte[] endKey;
274
275    public CompactionDelPartitionId() {
276    }
277
278    public CompactionDelPartitionId(final byte[] startKey, final byte[] endKey) {
279      this.startKey = startKey;
280      this.endKey = endKey;
281    }
282
283    public byte[] getStartKey() {
284      return this.startKey;
285    }
286    public void setStartKey(final byte[] startKey) {
287      this.startKey = startKey;
288    }
289
290    public byte[] getEndKey() {
291      return this.endKey;
292    }
293    public void setEndKey(final byte[] endKey) {
294      this.endKey = endKey;
295    }
296
297    @Override
298    public int compareTo(CompactionDelPartitionId o) {
299      /*
300       * 1). Compare the start key, if the k1 < k2, then k1 is less
301       * 2). If start Key is same, check endKey, k1 < k2, k1 is less
302       *     If both are same, then they are equal.
303       */
304      int result = Bytes.compareTo(this.startKey, o.getStartKey());
305      if (result != 0) {
306        return result;
307      }
308
309      return Bytes.compareTo(this.endKey, o.getEndKey());
310    }
311
312    @Override
313    public int hashCode() {
314      int result = 17;
315      result = 31 * result + java.util.Arrays.hashCode(startKey);
316      result = 31 * result + java.util.Arrays.hashCode(endKey);
317      return result;
318    }
319
320    @Override
321    public boolean equals(Object obj) {
322      if (this == obj) {
323        return true;
324      }
325      if (!(obj instanceof CompactionDelPartitionId)) {
326        return false;
327      }
328      CompactionDelPartitionId another = (CompactionDelPartitionId) obj;
329
330      return (this.compareTo(another) == 0);
331    }
332  }
333}