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