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; 024import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; 025import org.apache.yetus.audience.InterfaceAudience; 026import org.apache.yetus.audience.InterfaceStability; 027 028// FIX namings. TODO. 029@InterfaceAudience.Private 030@InterfaceStability.Evolving 031public final class DelayedUtil { 032 private DelayedUtil() { 033 } 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 /** Returns null (if an interrupt) or an instance of E; resets interrupt on calling thread. */ 078 public static <E extends Delayed> E takeWithoutInterrupt(final DelayQueue<E> queue, 079 final long timeout, final TimeUnit timeUnit) { 080 try { 081 return queue.poll(timeout, timeUnit); 082 } catch (InterruptedException e) { 083 Thread.currentThread().interrupt(); 084 return null; 085 } 086 } 087 088 /** Returns Time remaining as milliseconds. */ 089 public static long getRemainingTime(final TimeUnit resultUnit, final long timeout) { 090 final long currentTime = EnvironmentEdgeManager.currentTime(); 091 if (currentTime >= timeout) { 092 return 0; 093 } 094 return resultUnit.convert(timeout - currentTime, TimeUnit.MILLISECONDS); 095 } 096 097 public static int compareDelayed(final Delayed o1, final Delayed o2) { 098 return Long.compare(getTimeout(o1), getTimeout(o2)); 099 } 100 101 private static long getTimeout(final Delayed o) { 102 assert o instanceof DelayedWithTimeout : "expected DelayedWithTimeout instance, got " + o; 103 return ((DelayedWithTimeout) o).getTimeout(); 104 } 105 106 public static abstract class DelayedObject implements DelayedWithTimeout { 107 @Override 108 public long getDelay(final TimeUnit unit) { 109 return DelayedUtil.getRemainingTime(unit, getTimeout()); 110 } 111 112 @Override 113 public int compareTo(final Delayed other) { 114 return DelayedUtil.compareDelayed(this, other); 115 } 116 117 @Override 118 public String toString() { 119 long timeout = getTimeout(); 120 return "timeout=" + timeout + ", delay=" + getDelay(TimeUnit.MILLISECONDS); 121 } 122 } 123 124 public static abstract class DelayedContainer<T> extends DelayedObject { 125 private final T object; 126 127 public DelayedContainer(final T object) { 128 this.object = object; 129 } 130 131 public T getObject() { 132 return this.object; 133 } 134 135 @Override 136 public boolean equals(final Object other) { 137 if (other == this) { 138 return true; 139 } 140 141 if (!(other instanceof DelayedContainer)) { 142 return false; 143 } 144 145 return Objects.equals(getObject(), ((DelayedContainer) other).getObject()); 146 } 147 148 @Override 149 public int hashCode() { 150 return object != null ? object.hashCode() : 0; 151 } 152 153 @Override 154 public String toString() { 155 return "containedObject=" + getObject() + ", " + super.toString(); 156 } 157 } 158 159 /** 160 * Has a timeout. 161 */ 162 public static class DelayedContainerWithTimestamp<T> extends DelayedContainer<T> { 163 private long timeout; 164 165 public DelayedContainerWithTimestamp(final T object, final long timeout) { 166 super(object); 167 setTimeout(timeout); 168 } 169 170 @Override 171 public long getTimeout() { 172 return timeout; 173 } 174 175 public void setTimeout(final long timeout) { 176 this.timeout = timeout; 177 } 178 } 179}