| Package: MachII.caching.strategies |
| Inherits from: caching.strategies.AbstractCacheStrategy |
| A caching strategy which uses an LRU eviction policy. |
<!--- License: Copyright 2008 GreatBizTools, LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Copyright: GreatBizTools, LLC Author: Kurt Wiersma (kurt@mach-ii.com) $Id: LRUCache.cfc 1189 2008-12-02 07:27:46Z peterfarrell $ Created version: 1.6.0 Updated version: 1.6.0 Notes: Configuration parameters Size - The size of the LRU cache size. - The default setting for the LRU cache "size" is 100. - Valid numeric value only. Scope - The scope that the cache should be placed in. - The default setting for "scope" is "application". - Valid values are "application", "server" and "session". ScopeKey - The key place the cache in the choosen scope. - Optional and by default the cache will be placed in scope._MachIICache.Hash(appKey & moduleName & cacheName) - Rarely will this need to be used Using all of the default settings will result in caching 100 elements of data in the application scope. <property name="Caching" type="MachII.caching.CachingProperty"> <parameters> <!-- Naming a default cache name is not required, but required if you do not want to specify the 'name' attribute in the cache command --> <parameter name="defaultCacheName" value="default" /> <parameter name="default"> <struct> <key name="type" value="MachII.caching.strategies.LRUCache" /> <key name="size" value="100" /> <key name="scope" value="application" /> </struct> </parameter> </parameters> </property> ---> |
| Method Summary | |
|---|---|
| public void |
configure()
Configures the strategy. |
| public void |
flush()
Flushes the entire cache. |
| public any |
get(string key)
Gets data from the cache by key. Returns null if the key is not in the cache. |
| public struct |
getConfigurationData()
Gets pretty configuration data for this caching strategy. |
| private any |
getCurrentTickCount()
Gets the current tick count. |
| private string |
getNamedLockName(string actionType)
Gets a named lock name based on choosen scope and other factors |
| public string |
getScope()
Returns the scope where the LRU cache is stored. |
| public string |
getScopeKey()
Gets the unique cache key for this cache strategy. |
| public string |
getSize()
Returns the configured maximum size of the LRU cache. |
| public struct |
getStorage()
Gets a reference to the cache data storage. |
| private string |
hashKey(string key)
Creates a hashed version of the passed key. |
| public boolean |
keyExists(string key)
Checkes if a key exists in the cache. |
| public void |
put(string key, any data)
Puts data into the cache by key. |
| public void |
reap()
Looks at the timestamps of the cache pieces and throws out oldest one if the cache has more then the its max size. |
| public void |
remove(string key)
Removes data from the cache by key. |
| private void |
removeHashedKey(string hashedKey)
Removes a cached element by hashed key. |
| private void | setScope(string scope) |
| private void | setScopeKey(string scopeKey) |
| private void | setSize(numeric size) |
| Methods inherited from caching.strategies.AbstractCacheStrategy: getStrategyTypeName , getStrategyType , setParameter , init , setParameters , setCacheEnabled , getLog , getParameterNames , getParameter , isCacheEnabled , getParameters , setLog , getCacheStats , isParameterDefined |
|---|
| Method Detail |
|---|
| configure |
|---|
public void configure( )
Configures the strategy.
Parameters:
Code:
<cffunction name="configure" access="public" returntype="void" output="false"
hint="Configures the strategy.">
<cfif isParameterDefined("size")>
<cfif NOT isNumeric(getParameter("size")) OR getParameter("size") LTE 0>
<cfthrow type="MachII.caching.strategies.LRUCache"
message="Invalid Size of '#getParameter("size")#'."
detail="Size must be numeric and greater than 0." />
<cfelse>
<cfset setSize(getParameter("size")) />
</cfif>
</cfif>
<cfif isParameterDefined("scope")>
<cfif NOT ListFindNoCase("application,server,session", getParameter("scope"))>
<cfthrow type="MachII.caching.strategies.LRUCache"
message="Invalid Scope of '#getParameter("scope")#'."
detail="Use 'application', 'server' or 'session'." />
<cfelse>
<cfset setScope(getParameter("scope")) />
</cfif>
</cfif>
<cfif isParameterDefined("scopeKey")>
<cfif NOT Len(getParameter("scopeKey"))>
<cfthrow type="MachII.caching.strategies.LRUCache"
message="Invalid ScopeKey of '#getParameter("ScopeKey")#'."
detail="ScopeKey must have a length greater than 0 and be a valid struct key." />
<cfelse>
<cfset setScopeKey(getParameter("scopeKey")) />
</cfif>
<cfelseif isParameterDefined("generatedScopeKey")>
<cfset setScopeKey(getParameter("generatedScopeKey")) />
<cfelse>
<cfset setScopeKey(REReplace(CreateUUID(), "[[:punct:]]", "", "ALL")) />
</cfif>
<cfset flush() />
</cffunction>
| flush |
|---|
public void flush( )
Flushes the entire cache.
Parameters:
Code:
<cffunction name="flush" access="public" returntype="void" output="false" hint="Flushes the entire cache."> <cfset var dataStorage = getStorage() /> <cfset StructClear(dataStorage) /> <cfset getCacheStats().reset() /> </cffunction>
| get |
|---|
Gets data from the cache by key. Returns null if the key is not in the cache.
Parameters:
| string key |
Code:
<cffunction name="get" access="public" returntype="any" output="false" hint="Gets data from the cache by key. Returns null if the key is not in the cache."> <cfargument name="key" type="string" required="true" hint="Key does not need to be hashed." /> <cfset var dataStorage = getStorage() /> <cfset var cacheElement = "" /> <cfset var hashedKey = hashKey(arguments.key) /> <cfif keyExists(arguments.key)> <cfset cacheElement = dataStorage[hashedKey] /> <cfset cacheElement.timestamp = getCurrentTickCount() /> <cfset getCacheStats().incrementCacheHits(1) /> <cfreturn cacheElement.data /> <cfelse> <cfset getCacheStats().incrementCacheMisses(1) /> </cfif> </cffunction>
| getConfigurationData |
|---|
public struct getConfigurationData( )
Gets pretty configuration data for this caching strategy.
Parameters:
Code:
<cffunction name="getConfigurationData" access="public" returntype="struct" output="false" hint="Gets pretty configuration data for this caching strategy."> <cfset var data = StructNew() /> <cfset data["Scope"] = getScope() /> <cfset data["Size"] = getSize() /> <cfset data["Cache Enabled"] = YesNoFormat(isCacheEnabled()) /> <cfreturn data /> </cffunction>
| getCurrentTickCount |
|---|
private any getCurrentTickCount( )
Gets the current tick count.
Parameters:
Code:
<cffunction name="getCurrentTickCount" access="private" returntype="any" output="false" hint="Gets the current tick count."> <cfreturn getTickCount() /> </cffunction>
| getNamedLockName |
|---|
private string getNamedLockName( string actionType )
Gets a named lock name based on choosen scope and other factors
Parameters:
| string actionType |
Code:
<cffunction name="getNamedLockName" access="private" returntype="string" output="false"
hint="Gets a named lock name based on choosen scope and other factors">
<cfargument name="actionType" type="string" required="true" />
<cfset var name = "_MachIILRUCache_" & arguments.actionType & "_" & getScopeKey() />
<cfif getScope() EQ "session">
<cfif StructKeyExists(StructGet("session"), "sessionId")>
<cfset name = name & "_" & StructGet("session").sessionId />
</cfif>
</cfif>
<cfreturn name />
</cffunction>
| getScope |
|---|
public string getScope( )
Returns the scope where the LRU cache is stored.
Parameters:
Code:
<cffunction name="getScope" access="public" returntype="string" output="false" hint="Returns the scope where the LRU cache is stored."> <cfreturn variables.instance.scope /> </cffunction>
| getScopeKey |
|---|
public string getScopeKey( )
Gets the unique cache key for this cache strategy.
Parameters:
Code:
<cffunction name="getScopeKey" access="public" returntype="string" output="false" hint="Gets the unique cache key for this cache strategy."> <cfreturn variables.instance.scopeKey /> </cffunction>
| getSize |
|---|
public string getSize( )
Returns the configured maximum size of the LRU cache.
Parameters:
Code:
<cffunction name="getSize" access="public" returntype="string" output="false" hint="Returns the configured maximum size of the LRU cache."> <cfreturn variables.instance.size /> </cffunction>
| getStorage |
|---|
public struct getStorage( )
Gets a reference to the cache data storage.
Parameters:
Code:
<cffunction name="getStorage" access="public" returntype="struct" output="false" hint="Gets a reference to the cache data storage."> <cfreturn StructGet(getScope() & "." & getScopeKey()) /> </cffunction>
| hashKey |
|---|
private string hashKey( string key )
Creates a hashed version of the passed key.
Parameters:
| string key |
Code:
<cffunction name="hashKey" access="private" returntype="string" output="false" hint="Creates a hashed version of the passed key."> <cfargument name="key" type="string" required="true" /> <cfreturn Hash(UCase(Trim(arguments.key))) /> </cffunction>
| keyExists |
|---|
public boolean keyExists( string key )
Checkes if a key exists in the cache.
Parameters:
| string key |
Code:
<cffunction name="keyExists" access="public" returntype="boolean" output="false" hint="Checkes if a key exists in the cache."> <cfargument name="key" type="string" required="true" hint="Key should not be hashed." /> <cfif NOT StructKeyExists(getStorage(), hashKey(arguments.key))> <cfreturn false /> <cfelse> <cfreturn true /> </cfif> </cffunction>
| put |
|---|
public void put( string key, any data )
Puts data into the cache by key.
Parameters:
| string key |
| any data |
Code:
<cffunction name="put" access="public" returntype="void" output="false" hint="Puts data into the cache by key."> <cfargument name="key" type="string" required="true" hint="Key does not need to be hashed." /> <cfargument name="data" type="any" required="true" /> <cfset var dataStorage = getStorage() /> <cfset var cacheElement = StructNew() /> <cfset reap() /> <cfif NOT keyExists(arguments.key)> <cfset getCacheStats().incrementTotalElements(1) /> <cfset getCacheStats().incrementActiveElements(1) /> </cfif> <cfset cacheElement.data = arguments.data /> <cfset cacheElement.timestamp = getCurrentTickCount() /> <cfset dataStorage[hashKey(arguments.key)] = cacheElement /> </cffunction>
| reap |
|---|
public void reap( )
Looks at the timestamps of the cache pieces and throws out oldest one if the cache has more then the its max size.
Parameters:
Code:
<cffunction name="reap" access="public" returntype="void" output="false"
hint="Looks at the timestamps of the cache pieces and throws out oldest one if the cache has more then the its max size.">
<cfset var dataStorage = getStorage() />
<cfset var sortedTimestamps = "" />
<cfset var i = "" />
<cfif (StructCount(dataStorage) + 1) GT getSize()>
<cflock name="#getNamedLockName("cleanup")#" type="exclusive"
timeout="20" throwontimeout="false">
<cfif (StructCount(dataStorage) + 1) GT getSize()>
<cfset sortedTimestamps = StructSort(dataStorage, "numeric", "asc", "timestamp") />
<cfloop from="1" to="#ArrayLen(sortedTimestamps)#" index="i">
<cftry>
<cfif (StructCount(dataStorage) + 1) GT getSize()>
<cfset removeHashedKey(sortedTimestamps[i]) />
<cfelse>
<cfbreak />
</cfif>
<cfcatch type="any">
</cfcatch>
</cftry>
</cfloop>
</cfif>
</cflock>
</cfif>
</cffunction>
| remove |
|---|
public void remove( string key )
Removes data from the cache by key.
Parameters:
| string key |
Code:
<cffunction name="remove" access="public" returntype="void" output="false" hint="Removes data from the cache by key."> <cfargument name="key" type="string" required="true" hint="The key does not need to be hashed." /> <cfset removeHashedKey(hashKey(arguments.key)) /> </cffunction>
| removeHashedKey |
|---|
private void removeHashedKey( string hashedKey )
Removes a cached element by hashed key.
Parameters:
| string hashedKey |
Code:
<cffunction name="removeHashedKey" access="private" returntype="void" output="false" hint="Removes a cached element by hashed key."> <cfargument name="hashedKey" type="string" required="true" hint="The key must be hashed." /> <cfset var dataStorage = getStorage() /> <cfif StructKeyExists(dataStorage, arguments.hashedKey)> <cfset StructDelete(dataStorage, arguments.hashedKey, false) /> <cfset getCacheStats().incrementEvictions(1) /> <cfset getCacheStats().decrementTotalElements(1) /> <cfset getCacheStats().decrementActiveElements(1) /> </cfif> </cffunction>
| setScope |
|---|
private void setScope( string scope )
Parameters:
| string scope |
Code:
<cffunction name="setScope" access="private" returntype="void" output="false"> <cfargument name="scope" type="string" required="true" /> <cfset variables.instance.scope = arguments.scope /> </cffunction>
| setScopeKey |
|---|
private void setScopeKey( string scopeKey )
Parameters:
| string scopeKey |
Code:
<cffunction name="setScopeKey" access="private" returntype="void" output="false"> <cfargument name="scopeKey" type="string" required="true" /> <cfset variables.instance.scopeKey = arguments.scopeKey /> </cffunction>
| setSize |
|---|
private void setSize( numeric size )
Parameters:
| numeric size |
Code:
<cffunction name="setSize" access="private" returntype="void" output="false"> <cfargument name="size" type="numeric" required="true" /> <cfset variables.instance.size = arguments.size /> </cffunction>