From: Dave B. <bla...@us...> - 2011-12-13 18:45:24
|
Update of /cvsroot/sblim/jsr48-client/src/org/sblim/cimclient/internal/wbem/indications In directory vz-cvs-3.sog:/tmp/cvs-serv25801/src/org/sblim/cimclient/internal/wbem/indications Modified Files: Tag: Experimental CIMIndicationHandler.java Log Message: 3459036 - Linked list for RI queue not efficient for many LDs Index: CIMIndicationHandler.java =================================================================== RCS file: /cvsroot/sblim/jsr48-client/src/org/sblim/cimclient/internal/wbem/indications/CIMIndicationHandler.java,v retrieving revision 1.10.2.17 retrieving revision 1.10.2.18 diff -u -d -r1.10.2.17 -r1.10.2.18 --- CIMIndicationHandler.java 12 Aug 2011 20:43:15 -0000 1.10.2.17 +++ CIMIndicationHandler.java 13 Dec 2011 18:45:22 -0000 1.10.2.18 @@ -36,6 +36,7 @@ * 3374206 2011-07-22 blaschke-oss NullPointerException caused by Indication * 3376657 2011-07-24 blaschke-oss Get reliable indication properties once * 3390724 2011-08-12 blaschke-oss Problem with Reliable Indication support in the Listener + * 3459036 2011-12-13 blaschke-oss Linked list for RI queue not efficient for many LDs */ package org.sblim.cimclient.internal.wbem.indications; @@ -44,6 +45,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.net.InetAddress; +import java.util.Hashtable; import java.util.Iterator; import java.util.LinkedList; import java.util.Vector; @@ -83,11 +85,12 @@ public class CIMIndicationHandler extends HttpContentHandler { /** - * <code>IndicationServer</code> represents an entry in the linked list of - * servers handled by this <code>CIMIndicationHandler</code> instance. Each - * entry in the list will have a unique serverIP/destinationURL pair along - * with its own <code>ReliableIndicationHandler</code>. This is done to - * handle multiple contexts from the same server. + * <code>IndicationServer</code> represents an entry in the linked list or + * hash table of servers handled by this <code>CIMIndicationHandler</code> + * instance. Each entry in the list/table will have a unique + * serverIP/destinationURL pair along with its own + * <code>ReliableIndicationHandler</code>. This is done to handle multiple + * contexts from the same server. * * NOTE: Multiple contexts from the same server will not be handled * correctly if the user creates multiple @@ -105,15 +108,10 @@ private boolean iRISupported = false; - private InetAddress iInetAddress; - - private String iDestinationUrl; - private ReliableIndicationHandler iRIHandler; - public IndicationServer(InetAddress pInetAddress, String pDestinationUrl) { - this.iInetAddress = pInetAddress; - this.iDestinationUrl = pDestinationUrl; + public IndicationServer() { + // initialize() does the work } public void initialize(boolean pRISupported, ReliableIndicationHandler pRIHandler) { @@ -130,6 +128,31 @@ return this.iRISupported; } + public ReliableIndicationHandler getRIHandler() { + return this.iRIHandler; + } + } + + /** + * <code>ServerListEntry</code> represents a physical entry within the + * linked list. An <code>IndicationServer</code> instance is extracted from + * the linked list by proceeding through each entry in the linked list + * looking for the corresponding server IP and destination URL. + */ + private class ServerListEntry { + + private InetAddress iInetAddress; + + private String iDestinationUrl; + + private IndicationServer iIndicationServer; + + public ServerListEntry(InetAddress pInetAddress, String pDestinationUrl) { + this.iInetAddress = pInetAddress; + this.iDestinationUrl = pDestinationUrl; + this.iIndicationServer = new IndicationServer(); + } + public InetAddress getInetAddress() { return this.iInetAddress; } @@ -138,8 +161,48 @@ return this.iDestinationUrl; } - public ReliableIndicationHandler getRIHandler() { - return this.iRIHandler; + public IndicationServer getIndicationServer() { + return this.iIndicationServer; + } + } + + /** + * <code>ServerTableEntry</code> represents a physical key within the hash + * table while the corresponding <code>IndicationServer</code> is the value + * associated with the key. The hash table key is comprised of a server IP + * and destination URL. + */ + private class ServerTableEntry { + + private InetAddress iInetAddress; + + private String iDestinationUrl; + + public ServerTableEntry(InetAddress pInetAddress, String pDestinationUrl) { + this.iInetAddress = pInetAddress; + this.iDestinationUrl = pDestinationUrl; + } + + public InetAddress getInetAddress() { + return this.iInetAddress; + } + + public String getDestinationUrl() { + return this.iDestinationUrl; + } + + @Override + public boolean equals(Object pObj) { + if (!(pObj instanceof ServerTableEntry)) return false; + ServerTableEntry that = (ServerTableEntry) pObj; + if (this.iInetAddress.equals(that.getInetAddress()) + && this.iDestinationUrl.equalsIgnoreCase(that.getDestinationUrl())) return true; + return false; + } + + @Override + public int hashCode() { + return (this.iInetAddress.hashCode()) ^ (this.iDestinationUrl.hashCode()); } } @@ -153,7 +216,11 @@ private boolean iReliableIndicationsDisabled = true; - private LinkedList<IndicationServer> iServerList = new LinkedList<IndicationServer>(); + private int iHashtableCapacity = 0; // 0 -> linked list, >0 -> hash table + + private LinkedList<ServerListEntry> iServerList; + + private Hashtable<ServerTableEntry, IndicationServer> iServerTable; /** * Ctor. @@ -175,6 +242,29 @@ this.iSessionProperties = (pProperties != null) ? pProperties : WBEMConfiguration .getGlobalConfiguration(); this.iReliableIndicationsDisabled = !this.iSessionProperties.isReliableIndicationEnabled(); + + // Initialize reliable indication support + if (!this.iReliableIndicationsDisabled) { + this.iHashtableCapacity = this.iSessionProperties + .getReliableIndicationHashtableCapacity(); + + // Validate ReliableIndicationHashtableCapacity property + if (this.iHashtableCapacity < 0 || this.iHashtableCapacity > 25000) { + this.iLogger.trace(Level.FINE, "ReliableIndicationHashtableCapacity of " + + this.iHashtableCapacity + " outside range, using default value"); + + this.iHashtableCapacity = Integer.valueOf( + WBEMConfigurationDefaults.LISTENER_RELIABLE_INDICATION_HASHTABLE_CAPACITY) + .intValue(); + } + + if (this.iHashtableCapacity == 0) { + this.iServerList = new LinkedList<ServerListEntry>(); + } else { + this.iServerTable = new Hashtable<ServerTableEntry, IndicationServer>( + this.iHashtableCapacity); + } + } } @Override @@ -292,20 +382,50 @@ * Destination URL of indication. * @return <code>IndicationServer</code> with given address. */ - private IndicationServer getIndicationServer(InetAddress pInetAddress, String pDestinationUrl) { - IndicationServer server; - Iterator<IndicationServer> iterator = this.iServerList.iterator(); + private IndicationServer getIndicationServerFromList(InetAddress pInetAddress, + String pDestinationUrl) { + ServerListEntry entry; + Iterator<ServerListEntry> iterator = this.iServerList.iterator(); while (iterator.hasNext()) { - server = iterator.next(); - if (server.getInetAddress().equals(pInetAddress) - && server.getDestinationUrl().equalsIgnoreCase(pDestinationUrl)) return server; + entry = iterator.next(); + if (entry.getInetAddress().equals(pInetAddress) + && entry.getDestinationUrl().equalsIgnoreCase(pDestinationUrl)) return entry + .getIndicationServer(); } - server = new IndicationServer(pInetAddress, pDestinationUrl); - this.iServerList.add(server); + entry = new ServerListEntry(pInetAddress, pDestinationUrl); + this.iServerList.add(entry); this.iLogger.trace(Level.FINE, "Creating reliable indication handler for server IP " - + server.getInetAddress().toString() + ", destination URL " - + server.getDestinationUrl()); + + entry.getInetAddress().toString() + ", destination URL " + + entry.getDestinationUrl() + " in linked list"); + + return entry.getIndicationServer(); + } + + /** + * Returns the corresponding indication server if the server is already + * present in the hash table, otherwise adds the server to the hash table + * and returns the new entry. + * + * @param pInetAddress + * Address of indication server. + * @param pDestinationUrl + * Destination URL of indication. + * @return <code>IndicationServer</code> with given address. + */ + private IndicationServer getIndicationServerFromTable(InetAddress pInetAddress, + String pDestinationUrl) { + ServerTableEntry key; + IndicationServer server; + key = new ServerTableEntry(pInetAddress, pDestinationUrl); + server = this.iServerTable.get(key); + if (server == null) { + server = new IndicationServer(); + this.iServerTable.put(key, server); + this.iLogger.trace(Level.FINE, "Creating reliable indication handler for server IP " + + key.getInetAddress().toString() + ", destination URL " + + key.getDestinationUrl() + " in hash table"); + } return server; } @@ -325,11 +445,18 @@ */ private synchronized boolean deliverIndication(CIMInstance pIndication, String pId, InetAddress pInetAddress) { + IndicationServer server; + // Each serverIP/destinationURL pair needs its own // ReliableIndicationHandler in order to handle multiple contexts - IndicationServer server = getIndicationServer(pInetAddress, pId); + if (this.iHashtableCapacity == 0) { + server = getIndicationServerFromList(pInetAddress, pId); + } else { + server = getIndicationServerFromTable(pInetAddress, pId); + } - // Nothing to do if reliable indications initialized but not supported, + // Nothing to do if reliable indications initialized but not + // supported, // go ahead and deliver if (server.isInitialized() && !server.isRISupported()) return true; @@ -337,7 +464,8 @@ CIMProperty<?> seqCtxProp = pIndication.getProperty("SequenceContext"); CIMProperty<?> seqNumProp = pIndication.getProperty("SequenceNumber"); - // Initialize (if not yet done so) to check if indication is reliable + // Initialize (if not yet done so) to check if indication is + // reliable if (!server.isInitialized()) { // Initial indication does not contain reliable indication // properties, disable support and go ahead and deliver @@ -374,7 +502,6 @@ attempts = Long.valueOf(WBEMConfigurationDefaults.LISTENER_DELIVERY_RETRY_ATTEMPTS) .longValue(); - } // Validate DeliveryRetryInterval property @@ -413,7 +540,8 @@ } // Reliable indication support is enabled but indication does not - // contain both properties with non-null values, go ahead and deliver + // contain both properties with non-null values, go ahead and + // deliver if (seqCtxProp.getValue() == null || seqNumProp.getValue() == null) { this.iLogger.trace(Level.FINE, "Reliable indication support enabled but sequence property has null value:\n" |