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 */ 018 019package org.apache.hadoop.hbase.procedure2.util; 020 021import java.util.Objects; 022import java.util.concurrent.DelayQueue; 023import java.util.concurrent.Delayed; 024import java.util.concurrent.TimeUnit; 025 026import org.apache.yetus.audience.InterfaceAudience; 027import org.apache.yetus.audience.InterfaceStability; 028import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; 029 030// FIX namings. TODO. 031@InterfaceAudience.Private 032@InterfaceStability.Evolving 033public final class DelayedUtil { 034 private DelayedUtil() { } 035 036 /** 037 * Add a timeout to a Delay 038 */ 039 public interface DelayedWithTimeout extends Delayed { 040 long getTimeout(); 041 } 042 043 /** 044 * POISON implementation; used to mark special state: e.g. shutdown. 045 */ 046 public static final DelayedWithTimeout DELAYED_POISON = new DelayedWithTimeout() { 047 @Override 048 public long getTimeout() { 049 return 0; 050 } 051 052 @Override 053 public long getDelay(final TimeUnit unit) { 054 return 0; 055 } 056 057 @Override 058 public int compareTo(final Delayed o) { 059 return Long.compare(0, DelayedUtil.getTimeout(o)); 060 } 061 062 @Override 063 public boolean equals(final Object other) { 064 return this == other; 065 } 066 067 @Override 068 public String toString() { 069 return getClass().getSimpleName() + "(POISON)"; 070 } 071 }; 072 073 /** 074 * @return null (if an interrupt) or an instance of E; resets interrupt on calling thread. 075 */ 076 public static <E extends Delayed> E takeWithoutInterrupt(final DelayQueue<E> queue) { 077 try { 078 return queue.take(); 079 } catch (InterruptedException e) { 080 Thread.currentThread().interrupt(); 081 return null; 082 } 083 } 084 085 /** 086 * @return Time remaining as milliseconds. 087 */ 088 public static long getRemainingTime(final TimeUnit resultUnit, final long timeout) { 089 final long currentTime = EnvironmentEdgeManager.currentTime(); 090 if (currentTime >= timeout) { 091 return 0; 092 } 093 return resultUnit.convert(timeout - currentTime, TimeUnit.MILLISECONDS); 094 } 095 096 public static int compareDelayed(final Delayed o1, final Delayed o2) { 097 return Long.compare(getTimeout(o1), getTimeout(o2)); 098 } 099 100 private static long getTimeout(final Delayed o) { 101 assert o instanceof DelayedWithTimeout : "expected DelayedWithTimeout instance, got " + o; 102 return ((DelayedWithTimeout)o).getTimeout(); 103 } 104 105 public static abstract class DelayedObject implements DelayedWithTimeout { 106 @Override 107 public long getDelay(final TimeUnit unit) { 108 return DelayedUtil.getRemainingTime(unit, getTimeout()); 109 } 110 111 @Override 112 public int compareTo(final Delayed other) { 113 return DelayedUtil.compareDelayed(this, other); 114 } 115 116 @Override 117 public String toString() { 118 long timeout = getTimeout(); 119 return "timeout=" + timeout + ", delay=" + getDelay(TimeUnit.MILLISECONDS); 120 } 121 } 122 123 public static abstract class DelayedContainer<T> extends DelayedObject { 124 private final T object; 125 126 public DelayedContainer(final T object) { 127 this.object = object; 128 } 129 130 public T getObject() { 131 return this.object; 132 } 133 134 @Override 135 public boolean equals(final Object other) { 136 if (other == this) return true; 137 if (!(other instanceof DelayedContainer)) return false; 138 return Objects.equals(getObject(), ((DelayedContainer)other).getObject()); 139 } 140 141 @Override 142 public int hashCode() { 143 return object != null ? object.hashCode() : 0; 144 } 145 146 @Override 147 public String toString() { 148 return "containedObject=" + getObject() + ", " + super.toString(); 149 } 150 } 151 152 /** 153 * Has a timeout. 154 */ 155 public static class DelayedContainerWithTimestamp<T> extends DelayedContainer<T> { 156 private long timeout; 157 158 public DelayedContainerWithTimestamp(final T object, final long timeout) { 159 super(object); 160 setTimeout(timeout); 161 } 162 163 @Override 164 public long getTimeout() { 165 return timeout; 166 } 167 168 public void setTimeout(final long timeout) { 169 this.timeout = timeout; 170 } 171 } 172}