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 ( 084 divPosition % windowsPerTier > 0 085 || startMillis() - windowMillis * windowsPerTier < maxTierAgeCutoff 086 ) { 087 return new Window(windowMillis, divPosition - 1, maxTierAgeCutoff); 088 } else { 089 return new Window(windowMillis * windowsPerTier, divPosition / windowsPerTier - 1, 090 maxTierAgeCutoff); 091 } 092 } 093 094 @Override 095 public long startMillis() { 096 try { 097 return LongMath.checkedMultiply(windowMillis, divPosition); 098 } catch (ArithmeticException ae) { 099 return Long.MIN_VALUE; 100 } 101 } 102 103 @Override 104 public long endMillis() { 105 try { 106 return LongMath.checkedMultiply(windowMillis, (divPosition + 1)); 107 } catch (ArithmeticException ae) { 108 return Long.MAX_VALUE; 109 } 110 } 111 } 112 113 private final long baseWindowMillis; 114 private final int windowsPerTier; 115 private final long maxTierAgeMillis; 116 117 private long getMaxTierAgeCutoff(long now) { 118 try { 119 return LongMath.checkedSubtract(now, maxTierAgeMillis); 120 } catch (ArithmeticException ae) { 121 LOG.warn("Value for " + MAX_TIER_AGE_MILLIS_KEY + ": " + maxTierAgeMillis 122 + ". Will always promote to next tier."); 123 return Long.MIN_VALUE; 124 } 125 } 126 127 public ExponentialCompactionWindowFactory(CompactionConfiguration comConf) { 128 Configuration conf = comConf.conf; 129 baseWindowMillis = conf.getLong(BASE_WINDOW_MILLIS_KEY, 3600000 * 6); 130 windowsPerTier = conf.getInt(WINDOWS_PER_TIER_KEY, 4); 131 maxTierAgeMillis = 132 conf.getLong(MAX_TIER_AGE_MILLIS_KEY, comConf.getDateTieredMaxStoreFileAgeMillis()); 133 LOG.info(toString()); 134 } 135 136 @Override 137 public CompactionWindow newIncomingWindow(long now) { 138 return new Window(baseWindowMillis, now / baseWindowMillis, getMaxTierAgeCutoff(now)); 139 } 140 141 @Override 142 public String toString() { 143 return String.format( 144 "%s [base window in milliseconds %d, windows per tier %d, max tier age in milliseconds %d]", 145 getClass().getSimpleName(), baseWindowMillis, windowsPerTier, maxTierAgeMillis); 146 } 147 148}