1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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
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
47
48 private final long maxTierAgeCutoff;
49
50
51
52
53 private final long windowMillis;
54
55
56
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
82
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 }