1 package body WF_OBJECT_CACHE as
2 /* $Header: WFOBCACB.pls 120.0.12010000.2 2008/08/09 13:36:23 sstomar ship $ */
3
4 /*-------------------+
5 | Caching strutures |
6 +-------------------*/
7
8 g_Object WF_OBJECTS_T;
9 g_Object_List WF_OBJECTS_TAB_T;
10
11 /*------------+
12 | Procedures |
13 +------------*/
14
15 -- SetCacheSize
16 -- Procedure to set the maximum size of the cache.
17 procedure SetCacheSize(p_size in number)
18 is
19 begin
20 g_cacheMaxSize := p_size;
21 end SetCacheSize;
22
23 -- GetHashValue (PRIVATE)
24 -- This function generates hash value for a given name
25 function getHashValue(p_hash_name in varchar2)
26 return number
27 is
28 begin
29 return dbms_utility.get_hash_value(p_hash_name, g_hashBase, g_hashSize);
30 end getHashValue;
31
32 -- CreateCache
33 -- Procedure to create a new cache to store an object type.
34 -- For example,
35 -- in BES if Events, Agents and Systems are the objects to be cached,
36 -- each of these object types would be referenced with an unique
37 -- identifier and this API called with that identifier. The identifier
38 -- would be used to store and retrieve that object type in cache.
39 procedure CreateCache(p_cache_index in varchar2)
40 is
41 begin
42
43 -- if already created, donot create. it will overwrite the cached
44 -- objects
45 if (g_Object_List.EXISTS(p_cache_index)) then
46 return;
47 end if;
48
49 -- Initialize the cache list and its related variables
50 g_Object_List(p_cache_index).Cache_Objs := g_Object;
51 g_Object_List(p_cache_index).Hash_Val(1) := null;
52 g_Object_List(p_cache_index).Curr_Idx := 1;
53 g_Object_List(p_cache_index).Overflow := false;
54
55 exception
56 when others then
57 wf_core.context('WF_OBJECT_CACHE', 'CreateCache', p_cache_index);
58 raise;
59 end CreateCache;
60
61 -- IsCacheCreated
62 -- Function that checks if cache is already created for a given cache index
63 -- If cache is already created, it need not be created again.
64 function IsCacheCreated(p_cache_index in number)
65 return boolean
66 is
67 begin
68 -- Check if cache is available for this object in the cache list
69 if (g_Object_List.COUNT = 0) then
70 return false;
71 else
72 return g_Object_List.EXISTS(p_cache_index);
73 end if;
74 end IsCacheCreated;
75
76 --
77 -- Check_Size (PRIVATE)
78 -- Checks the size of the cache object. If the cache has exceeded the
79 -- max size specified, removes the oldest record in that cache.
80 --
81 procedure Check_Size(p_cache_key in number,
82 p_object_key in number)
83 is
84 l_oldest number;
85 l_currIdx number;
86 begin
87 l_currIdx := g_Object_List(p_cache_key).Curr_Idx;
88
89 if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
90 wf_log_pkg.string(wf_log_pkg.level_statement,
91 'wf.plsql.WF_OBJECT_CACHE.Check_Size.Begin',
92 'Checking size of Cache. CurrIdx {'||l_currIdx||'}');
93 end if;
94
95 -- Check the current age pointer against max cache size
96 if (l_currIdx > g_cacheMaxSize) then
97 -- Reset the current index pointing to the hash value
98 l_currIdx := mod(l_currIdx, g_cacheMaxSize);
99 g_Object_List(p_cache_key).Curr_Idx := l_currIdx;
100
101 g_Object_List(p_cache_key).Overflow := true;
102 if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
103 wf_log_pkg.string(wf_log_pkg.level_statement,
104 'wf.plsql.WF_OBJECT_CACHE.Check_Size.Begin',
105 'Curr Idx exceeded Max Cache size, reseting CurrIdx. '||
106 ' Max Cache Size {'||g_cacheMaxSize||'}');
107 end if;
108 end if;
109
110 -- If the cache has reached it's max size, remove the oldest record
111 if (g_Object_List(p_cache_key).Overflow) then
112 l_oldest := g_Object_List(p_cache_key).Hash_Val(l_currIdx);
113 if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
114 wf_log_pkg.string(wf_log_pkg.level_statement,
115 'wf.plsql.WF_OBJECT_CACHE.Check_Size.Begin',
116 'Removing oldest record {'||l_oldest||'} from cache');
117 end if;
118 g_Object_List(p_cache_key).Cache_Objs.DELETE(l_oldest);
119 end if;
120 end Check_Size;
121
122 function isDuplicate(p_cache_key in number,
123 p_object_key in number)
124 return boolean
125 is
126 begin
127 return g_Object_List(p_cache_key).Cache_Objs.EXISTS(p_object_key);
128 end isDuplicate;
129
130 procedure Assign_Object(p_object in anydata,
131 p_cache_key in number,
132 p_object_key in number)
133 is
134 l_object anyData;
135 l_exists boolean;
136 l_currIdx number;
137
138 l_event wf_event_obj;
139 dummy pls_integer;
140 l_anyData sys.anyData;
141 begin
142 -- Set object would be called only if the required object was not already
143 -- in the cache.
144 if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
145 wf_log_pkg.string(wf_log_pkg.level_procedure,
146 'wf.plsql.WF_OBJECT_CACHE.Assign_Object.Begin',
147 'Assigning object at {'||p_object_key||'} in cache {'||p_cache_key||'}');
148 end if;
149
150 g_Object_List(p_cache_key).Cache_Objs(p_object_key) := p_object;
151
152 l_currIdx := g_Object_List(p_cache_key).Curr_Idx;
153 g_Object_List(p_cache_key).Hash_Val(l_currIdx) := p_object_key;
154 if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
155 wf_log_pkg.string(wf_log_pkg.level_statement,
156 'wf.plsql.WF_OBJECT_CACHE.Assign_Object.Begin',
157 'Current Idx for age table is {'||l_currIdx||'}');
158 end if;
159
160 l_currIdx := l_currIdx + 1;
161 g_Object_List(p_cache_key).Curr_Idx := l_currIdx;
162
163 if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
164 wf_log_pkg.string(wf_log_pkg.level_procedure,
165 'wf.plsql.WF_OBJECT_CACHE.Assign_Object.End',
166 'Assigned object to cache. Next Idx {'||l_currIdx||'}');
167 end if;
168 end Assign_Object;
169
170 -- SetObject
171 -- This procedure helps to store an object of type ANYDATA within a cache
172 -- that was previously created with CreateCache. The object is stored
173 -- within a PLSQL table under a subscript that is a hash value generated
174 -- from the object key.
175 -- For example,
176 -- If an event object is to be cached whose name is oracle.apps.vj.test,
177 -- a hash value is generated for event name oracle.apps.vj.test and the object
178 -- is stored under that location within the PLSQL table.
179 procedure SetObject(p_cache_index in number,
180 p_object in anydata,
181 p_object_key in varchar2)
182 is
183 l_cacheLoc number;
184 l_objHashVal number;
185
186 begin
187
188 if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
189 wf_log_pkg.string(wf_log_pkg.level_procedure,
190 'wf.plsql.WF_OBJECT_CACHE.SetObject.Begin',
191 'Setting object {'||p_object_key||'} in cache {'||p_cache_index||'}');
192 end if;
193
194 l_cacheLoc := p_cache_index;
195 l_objHashVal := getHashValue(p_object_key);
196
197 if (isDuplicate(l_cacheLoc, l_objHashVal)) then
198 if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
199 wf_log_pkg.string(wf_log_pkg.level_statement,
200 'wf.plsql.WF_OBJECT_CACHE.SetObject.Overwrite',
201 'Object already in cache. Overwriting.');
202 end if;
203 -- If the object is already in cache, overwrite it. The new one might be an
204 -- updated one with more information
205 g_Object_List(l_cacheLoc).Cache_Objs(l_objHashVal) := p_object;
206 else
207 if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
208 wf_log_pkg.string(wf_log_pkg.level_statement,
209 'wf.plsql.WF_OBJECT_CACHE.SetObject.Assign',
210 'Checking cache size and storing object in cache');
211 end if;
212 -- Checks if cache reached max size. If size reached, the oldest
213 -- record in that cache is removed to give space for the new one
214 Check_Size(l_cacheLoc, l_objHashVal);
215
216 -- Assign the new object to the location as per hash value
217 Assign_Object(p_object, l_cacheLoc, l_objHashVal);
218 end if;
219
220 exception
221 when others then
222 wf_core.context('WF_OBJECT_CACHE', 'SetObject', p_object_key);
223 raise;
224 end SetObject;
225
226 -- GetObject
227 -- This procedure returns ANYDATA object from a given cache for a given
228 -- object cache.
229 function GetObject(p_cache_index in number,
230 p_object_key in varchar2)
231 return anyData
232 is
233 l_cacheLoc number;
234 l_objHashVal number;
235 l_idx number;
236 l_anyData sys.anyData;
237 dummy pls_integer;
238 l_event wf_event_obj;
239 begin
240
241 if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
242 wf_log_pkg.string(wf_log_pkg.level_procedure,
243 'wf.plsql.WF_OBJECT_CACHE.GetObject.Begin',
244 'Getting {'||p_object_key||'} from cache {'||p_cache_index||'}');
245 end if;
246
247 l_cacheLoc := p_cache_index;
248 l_objHashVal := getHashValue(p_object_key);
249
250 if (g_Object_List.EXISTS(l_cacheLoc) and
251 g_Object_List(l_cacheLoc).Cache_Objs.EXISTS(l_objHashVal)) then
252 if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
253 wf_log_pkg.string(wf_log_pkg.level_statement,
254 'wf.plsql.WF_OBJECT_CACHE.GetObject.Cache_Hit',
255 'Object found in cache for {'||p_object_key||'}');
256 end if;
257 return g_Object_List(l_cacheLoc).Cache_Objs(l_objHashVal);
258 else
259 if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
260 wf_log_pkg.string(wf_log_pkg.level_statement,
261 'wf.plsql.WF_OBJECT_CACHE.GetObject.Cache_Hit',
262 'Object not found in cache for {'||p_object_key||'}');
263 end if;
264 return null;
265 end if;
266
267 exception
268 when others then
269 wf_core.context('WF_OBJECT_CACHE', 'GetObject', p_object_key);
270 raise;
271 end GetObject;
272
273 -- GetAllObjects
274 -- This procedure returns all the ANYDATA objects cached under a given cache
275 function GetAllObjects(p_cache_index in number)
276 return wf_objects_t
277 is
278 l_objs wf_objects_t;
279 begin
280 if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
281 wf_log_pkg.string(wf_log_pkg.level_statement,
282 'wf.plsql.WF_OBJECT_CACHE.GetAllObjects.Begin',
283 'Returning all cached objects for {'||p_cache_index||'}');
284 end if;
285 return g_Object_List(p_cache_index).Cache_Objs;
286 end GetAllObjects;
287
288 -- Clear
289 -- This procedure deletes all the caches from memory. This is done in case
290 -- cache is found to be invalid.
291 procedure Clear(p_cache_index in varchar2)
292 is
293 l_cacheLoc number;
294 begin
295
296 if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
297 wf_log_pkg.string(wf_log_pkg.level_procedure,
298 'wf.plsql.WF_OBJECT_CACHE.Clear.Begin',
299 'Clearing object at cache index {'||p_cache_index||'}');
300 end if;
301 -- If cache index is specified, delete only that specified cache
302 if (p_cache_index is not null) then
303 g_Object_List.DELETE(p_cache_index);
304 else
305 -- Since no name is specified, delete the complete cache
306 l_cacheLoc := g_Object_List.FIRST;
307
308 while (l_cacheLoc is not null) loop
309 g_Object_List.DELETE(l_cacheLoc);
310 l_cacheLoc := g_Object_List.NEXT(l_cacheLoc);
311 end loop;
312 end if;
313
314 end Clear;
315
316 end WF_OBJECT_CACHE;