Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,18 @@
*/
package org.apache.hadoop.hbase.regionserver.compactions;

import com.google.errorprone.annotations.RestrictedApi;
import java.util.Calendar;
import java.util.GregorianCalendar;

import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
import org.apache.yetus.audience.InterfaceAudience;

@InterfaceAudience.Private
public class CurrentHourProvider {
private CurrentHourProvider() { throw new AssertionError(); }

private CurrentHourProvider() {
throw new AssertionError();
}

private static final class Tick {
final int currentHour;
Expand All @@ -37,7 +40,7 @@ private static final class Tick {
}
}

static Tick nextTick() {
private static Tick nextTick() {
Calendar calendar = new GregorianCalendar();
calendar.setTimeInMillis(EnvironmentEdgeManager.currentTime());
int currentHour = calendar.get(Calendar.HOUR_OF_DAY);
Expand All @@ -52,15 +55,21 @@ private static void moveToNextHour(Calendar calendar) {
calendar.set(Calendar.MILLISECOND, 0);
}

static volatile Tick tick = nextTick();
private static volatile Tick tick = nextTick();

public static int getCurrentHour() {
Tick tick = CurrentHourProvider.tick;
if (EnvironmentEdgeManager.currentTime() < tick.expirationTimeInMillis) {
return tick.currentHour;
}

CurrentHourProvider.tick = tick = nextTick();
tick = nextTick();
CurrentHourProvider.tick = tick;
return tick.currentHour;
}

@RestrictedApi(explanation = "Should only be called in tests", link = "",
allowedOnPath = ".*/src/test/.*")
static void advanceTick() {
tick = nextTick();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,63 +20,61 @@
import static org.junit.Assert.assertEquals;

import java.util.Date;
import java.util.List;
import java.util.TimeZone;
import org.apache.hadoop.hbase.HBaseClassTestRule;
import org.apache.hadoop.hbase.testclassification.RegionServerTests;
import org.apache.hadoop.hbase.testclassification.SmallTests;
import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
import org.junit.ClassRule;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.experimental.categories.Category;

@Category({RegionServerTests.class, SmallTests.class})
@Ignore("See HBASE-25385")
import org.apache.hbase.thirdparty.com.google.common.collect.Lists;

@Category({ RegionServerTests.class, SmallTests.class })
public class TestCurrentHourProvider {

@ClassRule
public static final HBaseClassTestRule CLASS_RULE =
HBaseClassTestRule.forClass(TestCurrentHourProvider.class);
HBaseClassTestRule.forClass(TestCurrentHourProvider.class);

private static final List<String> ZONE_IDS = Lists.newArrayList("UTC", "US/Pacific", "Etc/GMT+8");

/**
* In timezone GMT+08:00, the unix time of 2020-08-20 11:52:41 is 1597895561000
* and the unix time of 2020-08-20 15:04:00 is 1597907081000,
* by calculating the delta time to get expected time in current timezone,
* then we can get special hour no matter which timezone it runs.
*
* In addition, we should consider the Daylight Saving Time.
* 1. If in DaylightTime, we need reduce one hour.
* 2. If in DaylightTime and timezone is "Antarctica/Troll", we need reduce two hours.
* In timezone GMT+08:00, the unix time of 2020-08-20 11:52:41 is 1597895561000 and the unix time
* of 2020-08-20 15:04:00 is 1597907081000, by calculating the delta time to get expected time in
* current timezone, then we can get special hour no matter which timezone it runs.
* <p/>
* In addition, we should consider the Daylight Saving Time. If in DaylightTime, we need reduce
* one hour.
*/
@Test
public void testWithEnvironmentEdge() {
// test for all available zoneID
for (String zoneID : TimeZone.getAvailableIDs()) {
for (String zoneID : ZONE_IDS) {
TimeZone timezone = TimeZone.getTimeZone(zoneID);
TimeZone.setDefault(timezone);

// set a time represent hour 11
long deltaFor11 = TimeZone.getDefault().getRawOffset() - 28800000;
long timeFor11 = 1597895561000L - deltaFor11;
EnvironmentEdgeManager.injectEdge(() -> timeFor11);
CurrentHourProvider.tick = CurrentHourProvider.nextTick();
CurrentHourProvider.advanceTick();
int hour11 = CurrentHourProvider.getCurrentHour();
if (TimeZone.getDefault().inDaylightTime(new Date(timeFor11))) {
hour11 = "Antarctica/Troll".equals(zoneID) ?
CurrentHourProvider.getCurrentHour() - 2 :
CurrentHourProvider.getCurrentHour() - 1;
hour11 = CurrentHourProvider.getCurrentHour() - 1;
}
assertEquals(11, hour11);

// set a time represent hour 15
long deltaFor15 = TimeZone.getDefault().getRawOffset() - 28800000;
long timeFor15 = 1597907081000L - deltaFor15;
EnvironmentEdgeManager.injectEdge(() -> timeFor15);
CurrentHourProvider.tick = CurrentHourProvider.nextTick();
CurrentHourProvider.advanceTick();
int hour15 = CurrentHourProvider.getCurrentHour();
if (TimeZone.getDefault().inDaylightTime(new Date(timeFor15))) {
hour15 = "Antarctica/Troll".equals(zoneID) ?
CurrentHourProvider.getCurrentHour() - 2 :
CurrentHourProvider.getCurrentHour() - 1;
hour15 = CurrentHourProvider.getCurrentHour() - 1;
}
assertEquals(15, hour15);
}
Expand Down