KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > dream > channel > IPSocketManagerCachingImpl


1 /**
2  * Dream
3  * Copyright (C) 2003-2004 INRIA Rhone-Alpes
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  * Contact: dream@objectweb.org
20  *
21  * Initial developer(s): Matthieu Leclercq
22  * Contributor(s):
23  */

24
25 package org.objectweb.dream.channel;
26
27 import java.io.IOException JavaDoc;
28 import java.net.InetAddress JavaDoc;
29 import java.util.HashMap JavaDoc;
30 import java.util.Map JavaDoc;
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 /**
40  * This component manage a cache of {@link SocketState}.
41  */

42 public class IPSocketManagerCachingImpl extends AbstractComponent
43     implements
44       IPSocketManager,
45       IPSocketManagerCachingAttributeController
46 {
47
48   /**
49    * The name of the client interface used to retreive a socket when it can't be
50    * found in the cache.
51    */

52   public static final String JavaDoc DELEGATE_IP_SOCKET_MANAGER = "delegate-ip-socket-manager";
53
54   protected CacheEntry reusableKey = new CacheEntry();
55   protected Map JavaDoc cache = new HashMap JavaDoc();
56   protected Map JavaDoc reversCache = new HashMap JavaDoc();
57   protected CacheEntry lruHead = null;
58   protected CacheEntry lruTail = null;
59
60   protected boolean blocking = true;
61
62   // ---------------------------------------------------------------------------
63
// Attribute fields
64
// ---------------------------------------------------------------------------
65

66   protected int nbMaxSocket;
67
68   // ---------------------------------------------------------------------------
69
// Client interfaces
70
// ---------------------------------------------------------------------------
71

72   protected IPSocketManager delegateSocketManagerItf;
73
74   // ---------------------------------------------------------------------------
75
// Implementation of the IPSocketManager interface
76
// ---------------------------------------------------------------------------
77

78   /**
79    * @see IPSocketManager#getSocket(InetAddress, int)
80    */

81   public SocketState getSocket(InetAddress JavaDoc address, int port)
82       throws IOException JavaDoc, InterruptedException JavaDoc
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 JavaDoc("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       // open new socket.
126
if (cache.size() >= nbMaxSocket)
127       {
128         // remove last from lru
129
if (lruTail.inUse)
130         {
131           throw new IOException JavaDoc(
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     // get new socket outside from synchronize
145
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   /**
161    * @see IPSocketManager#releaseSocket(SocketState, boolean)
162    */

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 JavaDoc("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   // ---------------------------------------------------------------------------
186
// Implementation of the AttributeController interface
187
// ---------------------------------------------------------------------------
188

189   /**
190    * @see IPSocketManagerCachingAttributeController#getNbMaxSocket()
191    */

192   public int getNbMaxSocket()
193   {
194     return nbMaxSocket;
195   }
196
197   /**
198    * @see IPSocketManagerCachingAttributeController#setNbMaxSocket(int)
199    */

200   public void setNbMaxSocket(int nbMaxSocket)
201   {
202     this.nbMaxSocket = nbMaxSocket;
203   }
204
205   /**
206    * @see org.objectweb.dream.channel.IPSocketManagerCachingAttributeController#setBlocking(boolean)
207    */

208   public void setBlocking(boolean blocking)
209   {
210     this.blocking = blocking;
211   }
212
213   /**
214    * @see org.objectweb.dream.channel.IPSocketManagerCachingAttributeController#getBlocking()
215    */

216   public boolean getBlocking()
217   {
218     return blocking;
219   }
220
221   // ---------------------------------------------------------------------------
222
// Implementation of the BindingController interface
223
// ---------------------------------------------------------------------------
224

225   /**
226    * @see org.objectweb.fractal.api.control.BindingController#listFc()
227    */

228   public String JavaDoc[] listFc()
229   {
230     return new String JavaDoc[]{DELEGATE_IP_SOCKET_MANAGER};
231   }
232
233   /**
234    * @see org.objectweb.fractal.api.control.BindingController#bindFc(String,
235    * Object)
236    */

237   public void bindFc(String JavaDoc clientItfName, Object JavaDoc 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   // ---------------------------------------------------------------------------
249
// Utility inner class
250
// ---------------------------------------------------------------------------
251

252   protected class CacheEntry
253   {
254
255     protected InetAddress JavaDoc 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         // this == lruTail
281
if (prev == null)
282         {
283           // lru contains only this
284
lruHead = null;
285           lruTail = null;
286         }
287         else
288         {
289           lruTail = prev;
290           lruTail.next = null;
291         }
292       }
293       else
294       {
295         // next non null
296
next.prev = prev;
297         if (prev == null)
298         {
299           // this == lruHead
300
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         // already first
316
return;
317       }
318       prev.next = next;
319       if (next == null)
320       {
321         // this == lruTail
322
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         // lru empty
339
lruHead = this;
340         lruTail = this;
341         return;
342       }
343       lruHead.prev = this;
344       next = lruHead;
345       prev = null;
346       lruHead = this;
347     }
348
349     /**
350      * @see Object#equals(Object)
351      */

352     public boolean equals(Object JavaDoc 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     /**
361      * @see Object#hashCode()
362      */

363     public int hashCode()
364     {
365       return inetAddress == null ? inetAddress.hashCode() + port : port;
366     }
367   }
368
369 }
Popular Tags