View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.regionserver.compactions;
19  
20  import com.google.common.math.LongMath;
21  
22  import org.apache.commons.logging.Log;
23  import org.apache.commons.logging.LogFactory;
24  import org.apache.hadoop.conf.Configuration;
25  import org.apache.hadoop.hbase.HBaseInterfaceAudience;
26  import org.apache.hadoop.hbase.classification.InterfaceAudience;
27  
28  /**
29   * Exponential compaction window implementation.
30   */
31  @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.CONFIG)
32  public class ExponentialCompactionWindowFactory extends CompactionWindowFactory {
33  
34    private static final Log LOG = LogFactory.getLog(ExponentialCompactionWindowFactory.class);
35  
36    public static final String BASE_WINDOW_MILLIS_KEY =
37      "hbase.hstore.compaction.date.tiered.base.window.millis";
38    public static final String WINDOWS_PER_TIER_KEY =
39      "hbase.hstore.compaction.date.tiered.windows.per.tier";
40    public static final String MAX_TIER_AGE_MILLIS_KEY =
41      "hbase.hstore.compaction.date.tiered.max.tier.age.millis";
42  
43    private final class Window extends CompactionWindow {
44  
45      /**
46       * Will not promote to next tier for window before it.
47       */
48      private final long maxTierAgeCutoff;
49  
50      /**
51       * How big a range of timestamps fit inside the window in milliseconds.
52       */
53      private final long windowMillis;
54  
55      /**
56       * A timestamp t is within the window iff t / size == divPosition.
57       */
58      private final long divPosition;
59  
60      public Window(long baseWindowMillis, long divPosition, long maxTierAgeCutoff) {
61        this.windowMillis = baseWindowMillis;
62        this.divPosition = divPosition;
63        this.maxTierAgeCutoff = maxTierAgeCutoff;
64      }
65  
66      @Override
67      public int compareToTimestamp(long timestamp) {
68        if (timestamp < 0) {
69          try {
70            timestamp = LongMath.checkedSubtract(timestamp, windowMillis - 1);
71          } catch (ArithmeticException ae) {
72            timestamp = Long.MIN_VALUE;
73          }
74        }
75        long pos = timestamp / windowMillis;
76        return divPosition == pos ? 0 : divPosition < pos ? -1 : 1;
77      }
78  
79      @Override
80      public Window nextEarlierWindow() {
81        // Don't promote to the next tier if there is not even 1 window at current tier
82        // or if the next window crosses the max age.
83        if (divPosition % windowsPerTier > 0
84            || startMillis() - windowMillis * windowsPerTier < maxTierAgeCutoff) {
85          return new Window(windowMillis, divPosition - 1, maxTierAgeCutoff);
86        } else {
87          return new Window(windowMillis * windowsPerTier, divPosition / windowsPerTier - 1,
88              maxTierAgeCutoff);
89        }
90      }
91  
92      @Override
93      public long startMillis() {
94        try {
95          return LongMath.checkedMultiply(windowMillis, divPosition);
96        } catch (ArithmeticException ae) {
97          return Long.MIN_VALUE;
98        }
99      }
100 
101     @Override
102     public long endMillis() {
103       try {
104         return LongMath.checkedMultiply(windowMillis, (divPosition + 1));
105       } catch (ArithmeticException ae) {
106         return Long.MAX_VALUE;
107       }
108     }
109   }
110 
111   private final long baseWindowMillis;
112   private final int windowsPerTier;
113   private final long maxTierAgeMillis;
114 
115   private long getMaxTierAgeCutoff(long now) {
116     try {
117       return LongMath.checkedSubtract(now, maxTierAgeMillis);
118     } catch (ArithmeticException ae) {
119       LOG.warn("Value for " + MAX_TIER_AGE_MILLIS_KEY + ": " + maxTierAgeMillis
120         + ". Will always promote to next tier.");
121       return Long.MIN_VALUE;
122     }
123   }
124 
125   public ExponentialCompactionWindowFactory(CompactionConfiguration comConf) {
126     Configuration conf = comConf.conf;
127     baseWindowMillis = conf.getLong(BASE_WINDOW_MILLIS_KEY, 3600000 * 6);
128     windowsPerTier = conf.getInt(WINDOWS_PER_TIER_KEY, 4);
129     maxTierAgeMillis = conf.getLong(MAX_TIER_AGE_MILLIS_KEY,
130       comConf.getDateTieredMaxStoreFileAgeMillis());
131     LOG.info(this);
132   }
133 
134   @Override
135   public CompactionWindow newIncomingWindow(long now) {
136     return new Window(baseWindowMillis, now / baseWindowMillis, getMaxTierAgeCutoff(now));
137   }
138 
139   @Override
140   public String toString() {
141     return String.format(
142       "%s [base window in milliseconds %d, windows per tier %d, max tier age in milliseconds %d]",
143       getClass().getSimpleName(), baseWindowMillis, windowsPerTier, maxTierAgeMillis);
144   }
145 
146 }