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 com.google.errorprone.annotations.RestrictedApi;
021import java.util.Calendar;
022import java.util.GregorianCalendar;
023import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
024import org.apache.yetus.audience.InterfaceAudience;
025
026@InterfaceAudience.Private
027public class CurrentHourProvider {
028
029  private CurrentHourProvider() {
030    throw new AssertionError();
031  }
032
033  private static final class Tick {
034    final int currentHour;
035    final long expirationTimeInMillis;
036
037    Tick(int currentHour, long expirationTimeInMillis) {
038      this.currentHour = currentHour;
039      this.expirationTimeInMillis = expirationTimeInMillis;
040    }
041  }
042
043  private static Tick nextTick() {
044    Calendar calendar = new GregorianCalendar();
045    calendar.setTimeInMillis(EnvironmentEdgeManager.currentTime());
046    int currentHour = calendar.get(Calendar.HOUR_OF_DAY);
047    moveToNextHour(calendar);
048    return new Tick(currentHour, calendar.getTimeInMillis());
049  }
050
051  private static void moveToNextHour(Calendar calendar) {
052    calendar.add(Calendar.HOUR_OF_DAY, 1);
053    calendar.set(Calendar.MINUTE, 0);
054    calendar.set(Calendar.SECOND, 0);
055    calendar.set(Calendar.MILLISECOND, 0);
056  }
057
058  private static volatile Tick tick = nextTick();
059
060  public static int getCurrentHour() {
061    Tick tick = CurrentHourProvider.tick;
062    if (EnvironmentEdgeManager.currentTime() < tick.expirationTimeInMillis) {
063      return tick.currentHour;
064    }
065    tick = nextTick();
066    CurrentHourProvider.tick = tick;
067    return tick.currentHour;
068  }
069
070  @RestrictedApi(explanation = "Should only be called in tests", link = "",
071      allowedOnPath = ".*/src/test/.*")
072  static void advanceTick() {
073    tick = nextTick();
074  }
075}