001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.regionserver.compactions; 019 020import org.apache.hadoop.conf.Configuration; 021import org.apache.hadoop.hbase.HBaseInterfaceAudience; 022import org.apache.yetus.audience.InterfaceAudience; 023import org.slf4j.Logger; 024import org.slf4j.LoggerFactory; 025 026import org.apache.hbase.thirdparty.com.google.common.math.LongMath; 027 028/** 029 * Exponential compaction window implementation. 030 */ 031@InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.CONFIG) 032public class ExponentialCompactionWindowFactory extends CompactionWindowFactory { 033 private static final Logger LOG = 034 LoggerFactory.getLogger(ExponentialCompactionWindowFactory.class); 035 036 public static final String BASE_WINDOW_MILLIS_KEY = 037 "hbase.hstore.compaction.date.tiered.base.window.millis"; 038 public static final String WINDOWS_PER_TIER_KEY = 039 "hbase.hstore.compaction.date.tiered.windows.per.tier"; 040 public static final String MAX_TIER_AGE_MILLIS_KEY = 041 "hbase.hstore.compaction.date.tiered.max.tier.age.millis"; 042 043 private final class Window extends CompactionWindow { 044 045 /** 046 * Will not promote to next tier for window before it. 047 */ 048 private final long maxTierAgeCutoff; 049 050 /** 051 * How big a range of timestamps fit inside the window in milliseconds. 052 */ 053 private final long windowMillis; 054 055 /** 056 * A timestamp t is within the window iff t / size == divPosition. 057 */ 058 private final long divPosition; 059 060 public Window(long baseWindowMillis, long divPosition, long maxTierAgeCutoff) { 061 this.windowMillis = baseWindowMillis; 062 this.divPosition = divPosition; 063 this.maxTierAgeCutoff = maxTierAgeCutoff; 064 } 065 066 @Override 067 public int compareToTimestamp(long timestamp) { 068 if (timestamp < 0) { 069 try { 070 timestamp = LongMath.checkedSubtract(timestamp, windowMillis - 1); 071 } catch (ArithmeticException ae) { 072 timestamp = Long.MIN_VALUE; 073 } 074 } 075 long pos = timestamp / windowMillis; 076 return divPosition == pos ? 0 : divPosition < pos ? -1 : 1; 077 } 078 079 @Override 080 public Window nextEarlierWindow() { 081 // Don't promote to the next tier if there is not even 1 window at current tier 082 // or if the next window crosses the max age. 083 if (divPosition % windowsPerTier > 0 084 || startMillis() - windowMillis * windowsPerTier < maxTierAgeCutoff) { 085 return new Window(windowMillis, divPosition - 1, maxTierAgeCutoff); 086 } else { 087 return new Window(windowMillis * windowsPerTier, divPosition / windowsPerTier - 1, 088 maxTierAgeCutoff); 089 } 090 } 091 092 @Override 093 public long startMillis() { 094 try { 095 return LongMath.checkedMultiply(windowMillis, divPosition); 096 } catch (ArithmeticException ae) { 097 return Long.MIN_VALUE; 098 } 099 } 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(toString()); 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}