1 24 25 package org.objectweb.dream.channel; 26 27 import java.io.IOException ; 28 import java.net.InetAddress ; 29 import java.util.HashMap ; 30 import java.util.Map ; 31 32 import org.objectweb.dream.AbstractComponent; 33 import org.objectweb.dream.util.Error; 34 import org.objectweb.fractal.api.NoSuchInterfaceException; 35 import org.objectweb.fractal.api.control.IllegalBindingException; 36 import org.objectweb.fractal.api.control.IllegalLifeCycleException; 37 import org.objectweb.util.monolog.api.BasicLevel; 38 39 42 public class IPSocketManagerCachingImpl extends AbstractComponent 43 implements 44 IPSocketManager, 45 IPSocketManagerCachingAttributeController 46 { 47 48 52 public static final String DELEGATE_IP_SOCKET_MANAGER = "delegate-ip-socket-manager"; 53 54 protected CacheEntry reusableKey = new CacheEntry(); 55 protected Map cache = new HashMap (); 56 protected Map reversCache = new HashMap (); 57 protected CacheEntry lruHead = null; 58 protected CacheEntry lruTail = null; 59 60 protected boolean blocking = true; 61 62 66 protected int nbMaxSocket; 67 68 72 protected IPSocketManager delegateSocketManagerItf; 73 74 78 81 public SocketState getSocket(InetAddress address, int port) 82 throws IOException , InterruptedException 83 { 84 CacheEntry ce; 85 synchronized (cache) 86 { 87 if (logger.isLoggable(BasicLevel.DEBUG)) 88 { 89 logger.log(BasicLevel.DEBUG, "Get socket in cache for " + address + ":" 90 + port); 91 } 92 reusableKey.inetAddress = address; 93 reusableKey.port = port; 94 ce = (CacheEntry) cache.get(reusableKey); 95 if (ce != null) 96 { 97 logger.log(BasicLevel.DEBUG, "Socket found in cache"); 98 while (ce.inUse) 99 { 100 if (blocking) 101 { 102 cache.wait(); 103 } 104 else 105 { 106 throw new IOException ("Socket already in use"); 107 } 108 } 109 if (ce.socketState != null) 110 { 111 if (ce.socketState.isClosed()) 112 { 113 logger.log(BasicLevel.DEBUG, "Socket is closed"); 114 ce.cacheRemove(); 115 } 116 else 117 { 118 ce.inUse = true; 119 ce.lruSetAtfirst(); 120 return ce.socketState; 121 } 122 } 123 } 124 125 if (cache.size() >= nbMaxSocket) 127 { 128 if (lruTail.inUse) 130 { 131 throw new IOException ( 132 "Can't add new socket, cache full and every sockets are in use."); 133 } 134 135 lruTail.cacheRemove(); 136 } 137 138 ce = new CacheEntry(); 139 ce.inetAddress = address; 140 ce.port = port; 141 ce.inUse = true; 142 cache.put(ce, ce); 143 } 144 if (logger.isLoggable(BasicLevel.DEBUG)) 146 { 147 logger.log(BasicLevel.DEBUG, "Create new socket for " + address + ":" 148 + port); 149 } 150 SocketState socketState = delegateSocketManagerItf.getSocket(address, port); 151 synchronized (cache) 152 { 153 logger.log(BasicLevel.DEBUG, "new socket created."); 154 ce.socketState = socketState; 155 reversCache.put(socketState, ce); 156 return socketState; 157 } 158 } 159 160 163 public void releaseSocket(SocketState socketState, boolean error) 164 { 165 synchronized (cache) 166 { 167 CacheEntry ce = (CacheEntry) reversCache.get(socketState); 168 if (ce == null) 169 { 170 throw new IllegalArgumentException ("Unknown SocketState"); 171 } 172 if (error) 173 { 174 ce.cacheRemove(); 175 ce.socketState = null; 176 } 177 else 178 { 179 ce.inUse = false; 180 } 181 cache.notifyAll(); 182 } 183 } 184 185 189 192 public int getNbMaxSocket() 193 { 194 return nbMaxSocket; 195 } 196 197 200 public void setNbMaxSocket(int nbMaxSocket) 201 { 202 this.nbMaxSocket = nbMaxSocket; 203 } 204 205 208 public void setBlocking(boolean blocking) 209 { 210 this.blocking = blocking; 211 } 212 213 216 public boolean getBlocking() 217 { 218 return blocking; 219 } 220 221 225 228 public String [] listFc() 229 { 230 return new String []{DELEGATE_IP_SOCKET_MANAGER}; 231 } 232 233 237 public void bindFc(String clientItfName, Object serverItf) 238 throws NoSuchInterfaceException, IllegalBindingException, 239 IllegalLifeCycleException 240 { 241 super.bindFc(clientItfName, serverItf); 242 if (clientItfName.equals(DELEGATE_IP_SOCKET_MANAGER)) 243 { 244 delegateSocketManagerItf = (IPSocketManager) serverItf; 245 } 246 } 247 248 252 protected class CacheEntry 253 { 254 255 protected InetAddress inetAddress; 256 protected int port; 257 protected SocketState socketState; 258 259 protected CacheEntry next = null; 260 protected CacheEntry prev = null; 261 protected boolean inUse = false; 262 263 protected void cacheRemove() 264 { 265 if (cache.remove(this) == null) 266 { 267 Error.bug(logger); 268 } 269 if (reversCache.remove(socketState) == null) 270 { 271 Error.bug(logger); 272 } 273 lruRemove(); 274 } 275 276 protected void lruRemove() 277 { 278 if (next == null) 279 { 280 if (prev == null) 282 { 283 lruHead = null; 285 lruTail = null; 286 } 287 else 288 { 289 lruTail = prev; 290 lruTail.next = null; 291 } 292 } 293 else 294 { 295 next.prev = prev; 297 if (prev == null) 298 { 299 lruHead = next; 301 } 302 else 303 { 304 prev.next = next; 305 } 306 } 307 next = null; 308 prev = null; 309 } 310 311 protected void lruSetAtfirst() 312 { 313 if (prev == null) 314 { 315 return; 317 } 318 prev.next = next; 319 if (next == null) 320 { 321 lruTail = prev; 323 } 324 else 325 { 326 next.prev = prev; 327 } 328 lruHead.prev = this; 329 next = lruHead; 330 prev = null; 331 lruHead = this; 332 } 333 334 protected void lruAddAtFirst() 335 { 336 if (lruHead == null) 337 { 338 lruHead = this; 340 lruTail = this; 341 return; 342 } 343 lruHead.prev = this; 344 next = lruHead; 345 prev = null; 346 lruHead = this; 347 } 348 349 352 public boolean equals(Object obj) 353 { 354 final CacheEntry key = (CacheEntry) obj; 355 return (inetAddress == null ? key.inetAddress == null : inetAddress 356 .equals(key.inetAddress)) 357 && port == key.port; 358 } 359 360 363 public int hashCode() 364 { 365 return inetAddress == null ? inetAddress.hashCode() + port : port; 366 } 367 } 368 369 } | Popular Tags |