Edit Add a file or picture Printable page Raw Text Page change history More options

Cache Connector

Data migrations taking days to complete? Tired of waiting for sluggish systems to service iterations or lookups? Then the Cache Connector may be just what the doctor ordered.

Simply add it to your arsenal, point it at the Connector you already have for reading the data and violá your AL will never be the same. This component was initially built to help in a case where the initial data population of Lotus Connections was taking several days to process around 100K users. This was due to a slow, but vital lookup to a less-than-responsive LDAP directory. We modified the AL to use the Cache Connector (which in turn used the original Connector to fill the cache) and the load completed in 90 minutes instead.

In addition to accelerating lookup operations, the Cache Connector also provides blazing Iterator mode with the data sorted on the specified key Attribute.

To use this scripted Connector, follow the instructions below to copy it into your Config. Then edit three variables in the Config tab script (at the top of the edit window, just after the comments):

As with the HashMap Connector, simply mark the text below (including the start and end tags) and bring it into your copy buffer. Once copied, right-click on the Connectors folder in the Config Editor and select Paste.

<MetamergeConfig created="Tue Aug 28 13:13:21 CEST 2007" createdBy="NO010196" version="1.2">
<Folder name="AssemblyLines"/>
<Folder name="Connectors">
<Connector name="CacheConnector">
<InheritFrom>system:/Connectors/ibmdi.ScriptConnector</InheritFrom>
<ConnectorMode>Iterator</ConnectorMode>
<ConnectorState>Enabled</ConnectorState>
<Configuration>
<InheritFrom>[parent]</InheritFrom>
<parameter name="connectorType">com.ibm.di.connector.ScriptConnector</parameter>
<parameter name="debug">false</parameter>
<parameter name="includeFiles"/>
<parameter name="parserOption">Useless</parameter>
<parameter name="script"><![CDATA[// Cache Connector v. 1.0
//
// This Connector pre-reads the data references by the Iterator
// named in the connectorName variable into a java.util.HashMap
// and allows searches (lookup). Good for making files randomly
// accessible or sorting them quickly.
//
// Note that all Entries in the Iterator's result set are loaded into
// memory. Note also that this implementation does not support
// duplicates with the same key value -- these are lost.
//

var connectorName = "BuffaloLDAP";  // Connector to use
var keyAttribute = "cn";          // Attribute to provide search key for
var keyIsCaseSensitive = false;      // Controls if search/sort is case sensitive

var tree = new java.util.TreeMap();
var keyset = null;
var itr = null;                   // for the set Iterator

var fileConn = system.loadConnector("Connectors/" + connectorName);

if (fileConn == null)
   throw "Connector specified for caching not found: Connectors/" + connectorName;

function selectEntries()
{
   var e;       // local Entry variable.
   var cnt = 0; // cnt used to ensure uniqueness for the key Attribute

   try { // try-catch used in case connector not initialized
      fileConn.terminate();
   } catch (ignoreException) {  
      // Do nothing
   } 

   main.logmsg("* Initializing Cache Connector using Connectors/" + connectorName);

   fileConn.initialize(null);
   fileConn.selectEntries();

   tree.clear(); // Clear the Hastable.

   try {
      // Load entries from the Iterator into the HashMap
      while ((e = fileConn.getNextEntry()) != null) {
         keyval = e.getString(keyAttribute);

         if (keyval == null)
            break; // skip this one since it has no key value

         if (!keyIsCaseSensitive)
            keyval = keyval.toLowerCase();

         tree.put(keyval, e);
         cnt++;
      }
   } catch (ex) {
      main.logmsg("ERROR", "* Cache Connector - Error occurred during iteration with Connectors/" + 
                     connectorName);
      main.logmsg("ERROR", "* Exception: " + ex);
   }

   // Set up an Iterator for Iterator Mode
   itr = tree.keySet().iterator();
   
   main.logmsg("* " + tree.size() + " of " + cnt + " entries cached.");
   if (cnt != tree.size())
      main.logmsg("WARN", "* Not all data has been cached. Some entries either lacked or had duplicate key values.");
}


function getNextEntry ()
{
   if (!itr.hasNext()) {
      result.setStatus (0);
      return;
   }

   nxt = itr.next();

   entry.merge(tree.get(nxt));
   result.setStatus (1); // Set status to "entry returned"
}


function findEntry ()
{
   var e; // entry
   var crit_vector = search.getCriteria();
   var crit = crit_vector.get(0);
   var cval = crit.value;

   if (!keyIsCaseSensitive)
      cval = cval.toLowerCase();

   // First I have to make sure the data has been cached
   try {
      tree.size();
   } catch (exc) {
      selectEntries(); // If not, then cache it now
   }

   var e = tree.get(cval);

   if (e != null) {
      entry.merge(e);
      result.setStatus (1); // Set status to "entry(s) returned"
   } else 
      result.setStatus (0); // Status = "none found"
}

]]></parameter>
</Configuration>
<ComputeChanges>true</ComputeChanges>
<DeltaBehavior>0</DeltaBehavior>
<DeltaStrict>true</DeltaStrict>
<Parser>
<InheritFrom>[parent]</InheritFrom>
</Parser>
<AttributeMap name="Input">
<InheritFrom>[parent]</InheritFrom>
</AttributeMap>
<AttributeMap name="Output">
<InheritFrom>[parent]</InheritFrom>
</AttributeMap>
<DeltaSettings>
<WhenToCommit>After every database operation</WhenToCommit>
<Driver>CloudScape</Driver>
</DeltaSettings>
<Schema name="Input">
<InheritFrom>[parent]</InheritFrom>
</Schema>
<Schema name="Output">
<InheritFrom>[parent]</InheritFrom>
</Schema>
<LinkCriteria>
<InheritFrom>[parent]</InheritFrom>
<AdvancedLinkMode>false</AdvancedLinkMode>
</LinkCriteria>
<Hooks>
<InheritFrom>[parent]</InheritFrom>
</Hooks>
<CheckpointConfig/>
<SandboxConfig/>
<Reconnect>
<InheritFrom>[parent]</InheritFrom>
<parameter name="initreconnect">false</parameter>
<parameter name="numberOfRetries">1</parameter>
<parameter name="retryDelay">10</parameter>
</Reconnect>
<Operations/>
<OperationCarrierIsProperty>false</OperationCarrierIsProperty>
<PoolDefinition>
<InheritFrom>[parent]</InheritFrom>
<Enabled>false</Enabled>
<MinPoolSize>0</MinPoolSize>
<PurgeInterval>0</PurgeInterval>
<InitializeAttempts>1</InitializeAttempts>
</PoolDefinition>
<PoolInstance/>
<InitializeOption>0</InitializeOption>
</Connector>
</Folder>
<Folder name="Parsers"/>
<Folder name="EventHandlers"/>
<Folder name="Scripts"/>
<JavaLibraries/>
<JavaProperties/>
<Folder name="Includes"/>
<Folder name="Config">
<LogConfig name="Logging"/>
<InstanceProperties name="AutoStart">
<AutoStart/>
</InstanceProperties>
<TombstonesConfig name="Tombstones"/>
<SolutionInterface name="SolutionInterface"/>
</Folder>
<Folder name="Functions"/>
<Folder name="AttributeMaps"/>
<Properties name="Properties">
<Stores/>
</Properties>
</MetamergeConfig>

-- EddieHartman - 28 Aug 2007