root/coldbox/trunk/src/system/cache/cacheManager.cfc @ 867

Revision 867, 16.0 kB (checked in by lmajano, 6 years ago)

updates.

Line 
1<!-----------------------------------------------------------------------
2********************************************************************************
3Copyright 2005-2007 ColdBox Framework by Luis Majano and Ortus Solutions, Corp
4www.coldboxframework.com | www.luismajano.com | www.ortussolutions.com
5********************************************************************************
6
7Author      :   Luis Majano
8Date        :   January 18, 2007
9Description :
10        This is a cfc that handles caching of event handlers.
11
12Modification History:
1301/18/2007 - Created
14
15----------------------------------------------------------------------->
16<cfcomponent name="cacheManager" hint="Manages handler,plugin,custom plugin and object caching. It is thread safe and implements locking for you." output="false">
17
18<!------------------------------------------- CONSTRUCTOR ------------------------------------------->
19
20        <cffunction name="init" access="public" output="false" returntype="cacheManager" hint="Constructor">
21                <cfargument name="controller" type="any" required="true">
22                <cfscript>
23                        variables.instance = structnew();
24                        //Set Controller Injection
25                        instance.controller = arguments.controller;
26                        //Cache Configuration
27                        instance.CacheConfigBean = structnew();
28                        //Object Pool
29                        instance.objectPool = structnew();
30                        //Cache Performance
31                        instance.cachePerformance = structNew();
32                        instance.cachePerformance.Hits = 0;
33                        instance.cachePerformance.Misses = 0;
34                        //Reaping Controll
35                        instance.lastReapDatetime = now();
36                        //Runtime Java object
37                        instance.javaRuntime = CreateObject("java", "java.lang.Runtime");
38                        //Lock Name
39                        instance.lockName = getController().getAppHash() & "_OCM_OPERATION";
40                        //Init the object Pool on instantiation
41                        initPool();
42                        //return Cache Manager reference;
43                        return this;
44                </cfscript>
45        </cffunction>
46
47        <cffunction name="configure" access="public" output="false" returntype="void" hint="Configures the cache for operation.">
48                <cfargument name="cacheConfigBean" type="coldbox.system.beans.cacheConfigBean" required="true">
49                <cfscript>
50                //set the config bean
51                setCacheConfigBean(arguments.cacheConfigBean);
52                //Reset the statistics.
53                resetStatistics();
54                </cfscript>
55        </cffunction>
56
57<!------------------------------------------- PUBLIC ------------------------------------------->
58
59        <!--- ************************************************************* --->
60
61        <cffunction name="lookup" access="public" output="false" returntype="boolean" hint="Check if an object is in cache, if not found it records a miss.">
62                <!--- ************************************************************* --->
63                <cfargument name="objectKey" type="string" required="true" hint="The key of the object to lookup.">
64                <!--- ************************************************************* --->
65                <cfset var ObjectFound = false>
66
67                <cflock type="readonly" name="#getLockName()#" timeout="30">
68                        <cfif getobjectPool().lookup(arguments.objectKey)>
69                                <cfset ObjectFound = true>
70                        <cfelse>
71                                <!--- Log miss --->
72                                <cfset miss()>
73                        </cfif>
74                </cflock>
75
76                <cfreturn ObjectFound>
77        </cffunction>
78
79        <!--- ************************************************************* --->
80
81        <cffunction name="get" access="public" output="false" returntype="any" hint="Get an object from cache. If it doesn't exist it returns a blank structure.">
82                <!--- ************************************************************* --->
83                <cfargument name="objectKey" type="string" required="true" hint="The key of the object to lookup.">
84                <!--- ************************************************************* --->
85                <cfset var ObjectFound = StructNew()>
86
87                <!--- Lookup First --->
88                <cfif lookup(arguments.objectKey)>
89                        <cflock type="exclusive" name="#getLockName()#" timeout="30">
90                                <!--- Record a Hit --->
91                                <cfset hit()>
92                                <cfset ObjectFound = getobjectPool().get(arguments.objectKey)>
93                        </cflock>
94                </cfif>
95                <cfreturn ObjectFound>
96        </cffunction>
97
98        <!--- ************************************************************* --->
99
100        <cffunction name="set" access="public" output="false" returntype="void" hint="sets an object in cache.">
101                <!--- ************************************************************* --->
102                <cfargument name="objectKey"            type="string"  required="true">
103                <cfargument name="MyObject"                     type="any"         required="true">
104                <cfargument name="Timeout"                      type="string"  required="false" default="" hint="Timeout in minutes. If timeout = 0 then object never times out. If timeout is blank, then timeout will be inherited from framework.">
105                <!--- ************************************************************* --->
106                <!---JVM Threshold Checks --->
107                <cfset var isBelowThreshold = ThresholdChecks()>
108                <cfset var ccBean = getCacheConfigBean()>
109
110                <!--- Clean Args --->
111                <cfset arguments.objectKey = trim(arguments.objectKey)>
112                <cfset arguments.Timeout = trim(arguments.Timeout)>
113
114                <!--- Max Objects in Cache Check --->
115                <cfif (ccBean.getCacheMaxObjects() eq 0 or getSize() lt ccBean.getCacheMaxObjects()) and
116                          (ccBean.getCacheFreeMemoryPercentageThreshold() eq 0 or isBelowThreshold)>
117
118                        <!--- Test Timeout Argument, if false, then inherit framework's timeout --->
119                        <cfif arguments.Timeout eq "" or not isNumeric(arguments.Timeout) or arguments.Timeout lt 0>
120                                <cfset arguments.Timeout = ccBean.getCacheObjectDefaultTimeout()>
121                        </cfif>
122
123                        <!--- Set object in Cache --->
124                        <cflock type="exclusive" name="#getLockName()#" timeout="30">
125                                <cfset getobjectPool().set(arguments.objectKey,arguments.MyObject,arguments.Timeout)>
126                        </cflock>
127                </cfif>
128        </cffunction>
129
130        <!--- ************************************************************* --->
131
132        <cffunction name="clearKey" access="public" output="false" returntype="boolean" hint="Clears a key from the cache.">
133                <!--- ************************************************************* --->
134                <cfargument name="objectKey" type="string" required="true">
135                <!--- ************************************************************* --->
136                <cfset var Results = false>
137                <cfif getobjectPool().lookup(arguments.objectKey) >
138                        <cflock type="exclusive" name="#getLockName()#" timeout="30">
139                                <cfset Results = getobjectPool().clearKey(arguments.objectKey)>
140                        </cflock>
141                </cfif>
142                <cfreturn Results>
143        </cffunction>
144
145        <!--- ************************************************************* --->
146
147        <cffunction name="clear" access="public" output="false" returntype="void" hint="Clears the entire object cache. Call from a non-cached object or you will get 500 NULL errors, VERY VERY BAD!!.">
148                <cflock type="exclusive" name="#getLockName()#" timeout="30">
149                        <cfset structDelete(variables,"objectPool")>
150                        <cfset initPool()>
151                        <cfset resetStatistics()>
152                </cflock>
153        </cffunction>
154
155        <!--- ************************************************************* --->
156
157        <cffunction name="resetStatistics" access="public" output="false" returntype="void" hint="Resets the cache statistics.">
158                <cfscript>
159                getcachePerformance().Hits = 0;
160                getcachePerformance().Misses = 0;
161                </cfscript>
162        </cffunction>
163
164        <!--- ************************************************************* --->
165
166        <cffunction name="getCachePerformanceRatio" access="public" output="false" returntype="numeric" hint="Get the cache's performance ratio">
167                <cfscript>
168                var requests = getcachePerformance().hits + getcachePerformance().misses;
169                if ( requests eq 0)
170                        return 0;
171                else
172                        return (getcachePerformance().Hits/requests) * 100;
173                </cfscript>
174        </cffunction>
175
176        <!--- ************************************************************* --->
177
178        <cffunction name="getSize" access="public" output="false" returntype="numeric" hint="Get the cache's size in items">
179                <cfscript>
180                return getObjectPool().getSize();
181                </cfscript>
182        </cffunction>
183
184        <!--- ************************************************************* --->
185
186        <cffunction name="getpool_metadata" access="public" returntype="struct" output="false" hint="Get the pool's metadata structure">
187                <cfreturn getObjectPool().getpool_metadata()>
188        </cffunction>
189
190        <!--- ************************************************************* --->
191
192        <cffunction name="getItemTypes" access="public" output="false" returntype="struct" hint="Get the item types of the cache.">
193                <cfscript>
194                var x = 1;
195                var itemList = getObjectPool().getObjectsKeyList();
196                var itemTypes = Structnew();
197
198                //Init types
199                itemTypes.plugins = 0;
200                itemTypes.handlers = 0;
201                itemTypes.other = 0;
202                itemTypes.ioc_beans = 0;
203
204                //Sort the listing.
205                itemList = listSort(itemList, "textnocase");
206
207                //Count objects
208                for (x=1; x lte listlen(itemList) ; x = x+1){
209                        if ( findnocase("plugin", listGetAt(itemList,x)) )
210                                itemTypes.plugins = itemTypes.plugins + 1;
211                        else if ( findnocase("handler", listGetAt(itemList,x)) )
212                                itemTypes.handlers = itemTypes.handlers + 1;
213                        else if ( findnocase("ioc", listGetAt(itemList,x)) )
214                                itemTypes.ioc_beans = itemTypes.ioc_beans + 1;
215                        else
216                                itemTypes.other = itemTypes.other + 1;
217                }
218                return itemTypes;
219                </cfscript>
220        </cffunction>
221
222        <!--- ************************************************************* --->
223
224        <cffunction name="reap" access="public" output="false" returntype="void" hint="Reap the cache.">
225                <cfscript>
226                        var key = "";
227                        var objStruct = getObjectPool().getpool_metadata();
228                        var ccBean = getCacheConfigBean();
229
230                        //Check if no data in pool
231                        if (not structisEmpty(objStruct)){
232
233                                //Check reaping frequency
234                                if ( dateDiff("n", getlastReapDatetime(), now() ) gte ccBean.getCacheReapFrequency() ){
235
236                                        //Reaping about to start, set new reaping date.
237                                        setlastReapDatetime( now() );
238
239                                        //Loop Through Metadata
240                                        for (key in objStruct){
241                                                //Override Timeout Check
242                                                if ( objStruct[key].Timeout gt 0 ){
243                                                        //Check for creation timeouts and clear
244                                                        if ( dateDiff("n", objStruct[key].created, now() ) gte  objStruct[key].Timeout ){
245                                                                clearKey(key);
246                                                                continue;
247                                                        }
248                                                        //Check for last accessed timeout. If object has not been accessed in the default span
249                                                        if ( dateDiff("n", objStruct[key].lastAccesed, now() ) gte  ccBean.getCacheObjectDefaultLastAccessTimeout() ){
250                                                                clearKey(key);
251                                                                continue;
252                                                        }
253                                                }//end timeout gt 0
254                                        }//end for loop
255                                }// end reaping frequency check
256                        }//end if objects in pool
257                </cfscript>
258        </cffunction>
259
260        <!--- ************************************************************* --->
261
262        <cffunction name="expireAll" access="public" returntype="any" hint="Expire All Objects. Use this instead of clear() from within handlers or any cached object, this sets the metadata for the objects to expire in the next request. Note that this is not an inmmediate expiration. Clear should only be used from outside a cached object" output="false" >
263                <cfscript>
264                        var key = "";
265                        var objStruct = getObjectPool().getpool_metadata();
266                       
267                        //Check if no data in pool
268                        if (not structisEmpty(objStruct)){
269                                //Loop Through Metadata and set expiration timeouts.
270                                for (key in objStruct){
271                                        objStruct[key].Timeout = 1;
272                                        objStruct[key].created = dateadd("n",-5,now());
273                                }
274                        }
275                </cfscript>
276        </cffunction>
277       
278<!------------------------------------------- ACCESSOR/MUTATORS ------------------------------------------->
279
280        <cffunction name="getlastReapDatetime" access="public" output="false" returntype="string" hint="Get the lastReapDatetime">
281                <cfscript>
282                return instance.lastReapDatetime;
283                </cfscript>
284        </cffunction>
285        <cffunction name="setlastReapDatetime" access="public" returntype="void" output="false" hint="Set the lastReapDatetime">
286                <cfargument name="lastReapDatetime" type="string" required="true">
287                <cfset instance.lastReapDatetime = arguments.lastReapDatetime>
288        </cffunction>
289
290        <!--- ************************************************************* --->
291
292        <cffunction name="getcachePerformance" access="public" output="false" returntype="struct" hint="Get the cachePerformance structure">
293                <cfscript>
294                return instance.cachePerformance;
295                </cfscript>
296        </cffunction>
297
298        <!--- ************************************************************* --->
299
300        <cffunction name="setCacheConfigBean" access="public" returntype="void" output="false">
301                <cfargument name="CacheConfigBean" type="coldbox.system.beans.cacheConfigBean" required="true">
302                <cfset instance.CacheConfigBean = arguments.CacheConfigBean>
303        </cffunction>
304        <cffunction name="getCacheConfigBean" access="public" returntype="coldbox.system.beans.cacheConfigBean" output="false">
305                <cfreturn instance.CacheConfigBean >
306        </cffunction>
307
308        <!--- ************************************************************* --->
309
310        <cffunction name="getjavaRuntime" access="public" returntype="any" output="false" hint="Get the java runtime object.">
311                <cfreturn instance.javaRuntime>
312        </cffunction>
313       
314        <!--- ************************************************************* --->
315       
316        <cffunction name="getcontroller" access="public" output="false" returntype="any" hint="Get controller">
317                <cfreturn instance.controller/>
318        </cffunction>
319       
320        <!--- ************************************************************* --->
321       
322        <cffunction name="setcontroller" access="public" output="false" returntype="void" hint="Set controller">
323                <cfargument name="controller" type="any" required="true"/>
324                <cfset instance.controller = arguments.controller/>
325        </cffunction>
326       
327        <!--- ************************************************************* --->
328       
329        <cffunction name="getlockName" access="public" output="false" returntype="string" hint="Get lockName">
330                <cfreturn instance.lockName/>
331        </cffunction>
332       
333        <!--- ************************************************************* --->
334       
335        <cffunction name="setlockName" access="public" output="false" returntype="void" hint="Set lockName">
336                <cfargument name="lockName" type="string" required="true"/>
337                <cfset instance.lockName = arguments.lockName/>
338        </cffunction>
339       
340        <!--- ************************************************************* --->
341       
342        <cffunction name="getObjectPool" access="public" returntype="any" output="false" hint="Get the internal object pool">
343                <cfreturn instance.objectPool >
344        </cffunction>
345       
346        <!--- ************************************************************* --->
347       
348<!------------------------------------------- PRIVATE ------------------------------------------->
349
350        <cffunction name="hit" access="private" output="false" returntype="void" hint="Record a hit">
351                <cfscript>
352                getcachePerformance().Hits = getcachePerformance().Hits + 1;
353                </cfscript>
354        </cffunction>
355
356        <!--- ************************************************************* --->
357
358        <cffunction name="miss" access="private" output="false" returntype="void" hint="Record a miss">
359                <cfscript>
360                getcachePerformance().misses = getcachePerformance().misses + 1;
361                </cfscript>
362        </cffunction>
363
364        <!--- ************************************************************* --->
365
366        <cffunction name="initPool" access="private" output="false" returntype="void" hint="Initialize and set the internal object Pool">
367                <cfscript>
368                instance.objectPool = CreateObject("component","objectPool").init();
369                </cfscript>
370        </cffunction>
371
372        <!--- ************************************************************* --->
373
374        <cffunction name="ThresholdChecks" access="private" output="false" returntype="boolean" hint="JVM Threshold checks">
375                <cfset var check = true>
376                <cfset var jvmThreshold = 0>
377                <cfset var jvmFreeMemory = "">
378                <cfset var jvmTotalMemory = "">
379                <cfset var ccBean = getCacheConfigBean()>
380                <cftry>
381                        <!--- Checks --->
382                        <cfif ccBean.getCacheFreeMemoryPercentageThreshold() neq 0>
383                                <cfset jvmFreeMemory = getJavaRuntime().getRuntime().freeMemory()>
384                                <cfset jvmTotalMemory = getJavaRuntime().getRuntime().totalMemory()>
385                                <cfset jvmThreshold = ((jvmFreeMemory/jvmTotalMemory)*100)>
386                                <cfset check = ccBean.getCacheFreeMemoryPercentageThreshold() lt jvmThreshold>
387                        </cfif>
388                        <cfcatch type="any">
389                                <cfset check = true>
390                        </cfcatch>
391                </cftry>
392                <cfreturn check>
393        </cffunction>
394
395        <!--- ************************************************************* --->
396
397</cfcomponent>
Note: See TracBrowser for help on using the browser.