1. /*
  2. * @(#)CorbaConnectionCacheBase.java 1.25 04/06/21
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package com.sun.corba.se.impl.transport;
  8. import java.util.Collection;
  9. import java.util.Iterator;
  10. import com.sun.corba.se.pept.broker.Broker;
  11. import com.sun.corba.se.pept.transport.Connection;
  12. import com.sun.corba.se.pept.transport.ConnectionCache;
  13. import com.sun.corba.se.spi.logging.CORBALogDomains;
  14. import com.sun.corba.se.spi.orb.ORB;
  15. import com.sun.corba.se.spi.transport.CorbaConnectionCache;
  16. import com.sun.corba.se.impl.logging.ORBUtilSystemException;
  17. import com.sun.corba.se.impl.orbutil.ORBUtility;
  18. /**
  19. * @author Harold Carr
  20. */
  21. public abstract class CorbaConnectionCacheBase
  22. implements
  23. ConnectionCache,
  24. CorbaConnectionCache
  25. {
  26. protected ORB orb;
  27. protected long timestamp = 0;
  28. protected String cacheType;
  29. protected String monitoringName;
  30. protected ORBUtilSystemException wrapper;
  31. protected CorbaConnectionCacheBase(ORB orb, String cacheType,
  32. String monitoringName)
  33. {
  34. this.orb = orb;
  35. this.cacheType = cacheType;
  36. this.monitoringName = monitoringName;
  37. wrapper =ORBUtilSystemException.get(orb,CORBALogDomains.RPC_TRANSPORT);
  38. registerWithMonitoring();
  39. dprintCreation();
  40. }
  41. ////////////////////////////////////////////////////
  42. //
  43. // pept.transport.ConnectionCache
  44. //
  45. public String getCacheType()
  46. {
  47. return cacheType;
  48. }
  49. public synchronized void stampTime(Connection c)
  50. {
  51. // _REVISIT_ Need to worry about wrap around some day
  52. c.setTimeStamp(timestamp++);
  53. }
  54. public long numberOfConnections()
  55. {
  56. synchronized (backingStore()) {
  57. return values().size();
  58. }
  59. }
  60. public long numberOfIdleConnections()
  61. {
  62. long count = 0;
  63. synchronized (backingStore()) {
  64. Iterator connections = values().iterator();
  65. while (connections.hasNext()) {
  66. if (! ((Connection)connections.next()).isBusy()) {
  67. count++;
  68. }
  69. }
  70. }
  71. return count;
  72. }
  73. public long numberOfBusyConnections()
  74. {
  75. long count = 0;
  76. synchronized (backingStore()) {
  77. Iterator connections = values().iterator();
  78. while (connections.hasNext()) {
  79. if (((Connection)connections.next()).isBusy()) {
  80. count++;
  81. }
  82. }
  83. }
  84. return count;
  85. }
  86. /**
  87. * Discarding least recently used Connections that are not busy
  88. *
  89. * This method must be synchronized since one WorkerThread could
  90. * be reclaming connections inside the synchronized backingStore
  91. * block and a second WorkerThread (or a SelectorThread) could have
  92. * already executed the if (numberOfConnections <= .... ). As a
  93. * result the second thread would also attempt to reclaim connections.
  94. *
  95. * If connection reclamation becomes a performance issue, the connection
  96. * reclamation could make its own task and consequently executed in
  97. * a separate thread.
  98. * Currently, the accept & reclaim are done in the same thread, WorkerThread
  99. * by default. It could be changed such that the SelectorThread would do
  100. * it for SocketChannels and WorkerThreads for Sockets by updating the
  101. * ParserTable.
  102. */
  103. synchronized public boolean reclaim()
  104. {
  105. try {
  106. long numberOfConnections = numberOfConnections();
  107. if (orb.transportDebugFlag) {
  108. dprint(".reclaim->: " + numberOfConnections
  109. + " ("
  110. + orb.getORBData().getHighWaterMark()
  111. + "/"
  112. + orb.getORBData().getLowWaterMark()
  113. + "/"
  114. + orb.getORBData().getNumberToReclaim()
  115. + ")");
  116. }
  117. if (numberOfConnections <= orb.getORBData().getHighWaterMark() ||
  118. numberOfConnections < orb.getORBData().getLowWaterMark()) {
  119. return false;
  120. }
  121. Object backingStore = backingStore();
  122. synchronized (backingStore) {
  123. // REVISIT - A less expensive alternative connection reclaiming
  124. // algorithm could be investigated.
  125. for (int i=0; i < orb.getORBData().getNumberToReclaim(); i++) {
  126. Connection toClose = null;
  127. long lru = java.lang.Long.MAX_VALUE;
  128. Iterator iterator = values().iterator();
  129. // Find least recently used and not busy connection in cache
  130. while ( iterator.hasNext() ) {
  131. Connection c = (Connection) iterator.next();
  132. if ( !c.isBusy() && c.getTimeStamp() < lru ) {
  133. toClose = c;
  134. lru = c.getTimeStamp();
  135. }
  136. }
  137. if ( toClose == null ) {
  138. return false;
  139. }
  140. try {
  141. if (orb.transportDebugFlag) {
  142. dprint(".reclaim: closing: " + toClose);
  143. }
  144. toClose.close();
  145. } catch (Exception ex) {
  146. // REVISIT - log
  147. }
  148. }
  149. if (orb.transportDebugFlag) {
  150. dprint(".reclaim: connections reclaimed ("
  151. + (numberOfConnections - numberOfConnections()) + ")");
  152. }
  153. }
  154. // XXX is necessary to do a GC to reclaim
  155. // closed network connections ??
  156. // java.lang.System.gc();
  157. return true;
  158. } finally {
  159. if (orb.transportDebugFlag) {
  160. dprint(".reclaim<-: " + numberOfConnections());
  161. }
  162. }
  163. }
  164. ////////////////////////////////////////////////////
  165. //
  166. // spi.transport.ConnectionCache
  167. //
  168. public String getMonitoringName()
  169. {
  170. return monitoringName;
  171. }
  172. ////////////////////////////////////////////////////
  173. //
  174. // Implementation
  175. //
  176. // This is public so folb.Server test can access it.
  177. public abstract Collection values();
  178. protected abstract Object backingStore();
  179. protected abstract void registerWithMonitoring();
  180. protected void dprintCreation()
  181. {
  182. if (orb.transportDebugFlag) {
  183. dprint(".constructor: cacheType: " + getCacheType()
  184. + " monitoringName: " + getMonitoringName());
  185. }
  186. }
  187. protected void dprintStatistics()
  188. {
  189. if (orb.transportDebugFlag) {
  190. dprint(".stats: "
  191. + numberOfConnections() + "/total "
  192. + numberOfBusyConnections() + "/busy "
  193. + numberOfIdleConnections() + "/idle"
  194. + " ("
  195. + orb.getORBData().getHighWaterMark() + "/"
  196. + orb.getORBData().getLowWaterMark() + "/"
  197. + orb.getORBData().getNumberToReclaim()
  198. + ")");
  199. }
  200. }
  201. protected void dprint(String msg)
  202. {
  203. ORBUtility.dprint("CorbaConnectionCacheBase", msg);
  204. }
  205. }
  206. // End of file.