DBA Data[Home] [Help]

PACKAGE BODY: APPS.AD_EVENT_REGISTRY_PKG

Source


1 PACKAGE BODY Ad_Event_Registry_Pkg AS
2 -- $Header: adevntrgb.pls 120.0 2005/05/25 12:03:04 appldev noship $
3 
4   -- Event Lock Mode
5   EVENT_LOCK_MODE       CONSTANT NUMBER       := DBMS_LOCK.X_MODE;
6   -- Constant for Relase on commit option for locks.
7   RELEASE_COMMIT_CONST  CONSTANT BOOLEAN      := FALSE ;
8   -- Default value of Event Version
9   DEFAULT_VERSION       CONSTANT NUMBER       := 1;
10 
11   -- Event record type is declared here.
12   TYPE Event_Rec_Type IS RECORD(
13     Owner            ad_events.owner%TYPE,
14     Event_Name       ad_events.event_name%TYPE,
15     Event_Context    ad_events.event_context%TYPE,
16     Event_Id         ad_events.event_id%TYPE,
17     Event_Status     ad_event_versions.status%TYPE,
18     -- worker status will be a string indicating status of all the workers
19     Worker_Status    ad_event_versions.worker_status%TYPE,
20     Event_Version    ad_events.last_version%TYPE,
21     Event_Type       ad_events.event_type%TYPE ,
22     Module_Name      ad_event_transitions.module_name%TYPE,
23     Worker_Id        ad_event_transitions.worker_id%TYPE,
24     Max_Workers      ad_event_versions.num_workers%TYPE );
25 
26   -- Type of table to store the list of events.
27   TYPE Event_Tbl_Type IS TABLE OF Event_Rec_Type INDEX BY BINARY_INTEGER ;
28 
29   -- Lock Record
30   TYPE Lock_Rec_Type IS RECORD (
31     Lock_Name        VARCHAR2 (128),
32     Lock_handle      VARCHAR2 (128) );
33 
34   -- Lock table type.
35   TYPE Lock_Tbl_Type IS TABLE OF Lock_Rec_Type INDEX BY BINARY_INTEGER ;
36 
37   -- Global variables are declared here
38 
39   -- Table to store the list of events already registered is declared below.
40   g_Events_Tbl       Event_Tbl_Type;
41   -- Table to store allocated lock details.
42   g_Lock_Tbl         Lock_Tbl_Type;
43 
44   -- Lock declaration
45   g_Event_LockHandle    VARCHAR2(128);
46   g_Event_LockName      VARCHAR2(128);
47 
48   FUNCTION Get_Event_Index(
49               p_Owner      IN VARCHAR2 ,
50 	      p_Event_Name IN VARCHAR2 ,
51 	      p_Context    IN VARCHAR2 )
52   RETURN NUMBER
53   IS
54   BEGIN
55     --
56     -- The function returns 0 if there are no events registered
57     -- The function returns 0 if there is no matching event registered so far.
58     --
59     IF (  g_Events_Tbl.COUNT = 0 ) THEN
60       RETURN 0;
61     END IF ;
62     --
63     -- Now check in the Global event list whether an event with the same name
64     -- Owner and Context is already registered. If so return the index of the
65     -- same. If not return 0.
66     --
67     FOR i IN g_Events_Tbl.FIRST .. g_Events_Tbl.LAST LOOP
68       IF (  g_Events_Tbl(i).Owner         = p_Owner        AND
69             g_Events_Tbl(i).Event_Name    = p_Event_Name   AND
70 	    g_Events_Tbl(i).Event_Context = p_Context    ) THEN
71 	 RETURN i;
72       END IF ;
73     END LOOP ;
74     -- If there are no matching events return 0.
75     RETURN 0;
76   END Get_Event_Index;
77 
78   PROCEDURE Validate_Globals(
79              p_Owner      IN VARCHAR2 ,
80 	     p_Event_Name IN VARCHAR2 ,
81 	     p_Context    IN VARCHAR2 )
82   IS
83     l_Event_Index   NUMBER ;
84   BEGIN
85    --
86    -- Get the index of the event from the global event list.
87    -- index value 0 means that the event is not registered in the session.
88    --
89    l_Event_Index := Get_Event_Index(
90                       p_Owner      ,
91 		      p_Event_Name ,
92 		      p_Context    );
93 
94    IF ( l_Event_Index = 0 ) THEN
95      raise_application_error(-20010,'Event Not Initialized');
96    END IF ;
97 
98   END Validate_Globals;
99 
100   PROCEDURE Request_Lock(
101               p_Owner       IN VARCHAR2 ,
102 	      p_Event_Name  IN VARCHAR2 )
103   IS
104   l_LockName       VARCHAR2(128);
105   l_Found          BOOLEAN ;
106   l_Temp_Index     BINARY_INTEGER ;
107   BEGIN
108 
109       -- Construct the lock name.
110       l_LockName := p_Owner||'_'||p_Event_Name;
111 
112       l_Found := FALSE ;
113       IF ( g_Lock_Tbl.COUNT <> 0 ) THEN
114       FOR i IN g_Lock_Tbl.FIRST .. g_Lock_Tbl.LAST LOOP
115         IF ( g_Lock_Tbl(i).Lock_Name = l_LockName ) THEN
116 	  g_Event_LockHandle := g_Lock_Tbl(i).Lock_Handle;
117 	  l_Found := TRUE ;
118 	  EXIT ;
119 	END IF ;
120       END LOOP ;
121       END IF ;
122 
123       -- Get the named lock.
124       AD_LOCK_UTILS_PKG.Get_Lock(
125 	             p_LockName          => l_LockName,
126 	             p_LockMode          => EVENT_LOCK_MODE,
127 		     p_Release_On_Commit => RELEASE_COMMIT_CONST,
128 		     x_LockHandle        => g_Event_LockHandle);
129 
130       IF ( l_Found = FALSE ) THEN
131         l_Temp_Index                         := NVL(g_Lock_Tbl.LAST,0) + 1;
132         g_Lock_Tbl(l_Temp_Index).Lock_Name   := l_LockName;
133 	g_Lock_Tbl(l_Temp_Index).Lock_Handle := g_Event_LockHandle;
134       END IF ;
135   END Request_Lock;
136 
137 --------------------------------
138 -- This is the function to initialize the worker status string.
139 -- The string will be initialized to Num_workers number of 'N's
140 --------------------------------
141   FUNCTION Initialize_worker_string(
142               p_Num_Workers IN NUMBER )
143   RETURN VARCHAR2
144   IS
145   BEGIN
146     RETURN LPAD ('N',p_Num_Workers,'N');
147   END Initialize_worker_string;
148 
149 ---------------------------------
150 -- This function will set the worker status string, i.e. it will
151 -- put a 'Y' indicating that the worker has completed
152 ---------------------------------
153   PROCEDURE Set_Worker_Status_String(
154               p_Worker_Id IN NUMBER ,
155 	      p_Worker_Status_String IN OUT NOCOPY VARCHAR2 )
156   IS
157   BEGIN
158     p_Worker_Status_String :=
159          SUBSTR (p_Worker_Status_String, 1, (p_Worker_Id-1)) ||
160          'Y'||
161          SUBSTR (p_Worker_Status_String, (p_Worker_Id+1));
162   END Set_Worker_Status_String;
163 
164 
165 ---------------------------------
166 -- This procedure will insert data into the AD_EVENT_TRANSITIONS table.
167 --
168 ---------------------------------
169   PROCEDURE Insert_Event_Transitions(
170               p_Event_Id    IN NUMBER ,
171 	      p_Version     IN NUMBER ,
172 	      p_New_Status  IN VARCHAR2 ,
173 	      p_Old_Status  IN VARCHAR2 := NULL ,
174 	      p_Module_Name IN VARCHAR2 ,
175 	      p_Worker_Id   IN NUMBER := NULL )
176   AS
177   BEGIN
178     INSERT INTO ad_event_transitions(
179                   transition_id,
180                   event_id,
181                   version,
182                   new_status,
183                   prior_status,
184                   transition_time,
185                   module_name,
186                   worker_id)
187     VALUES (
188                   ad_event_transitions_s.NEXTVAL,
189                   p_Event_Id,
190                   p_Version,
191                   p_New_Status,
192                   p_Old_Status,
193                   SYSDATE ,
194                   p_Module_Name,
195                   p_Worker_Id);
196 
197   END Insert_Event_Transitions;
198 --------------------------------
199 -- This procedure is used to perform Basic validations on the parameters
200 --------------------------------
201   PROCEDURE Validate_Parameters(
202               p_Owner       IN VARCHAR2 ,
203 	      p_Event_Name  IN VARCHAR2 ,
204 	      p_Event_Type  IN VARCHAR2 ,
205 	      p_Num_Workers IN NUMBER )
206   IS
207   BEGIN
208     IF (p_Owner IS NULL ) THEN
209       RAISE_APPLICATION_ERROR(-20010,
210            'Error: Value for Owner is passed as NULL.');
211     END IF ;
212     IF (p_Event_Name IS NULL ) THEN
213       RAISE_APPLICATION_ERROR(-20010,
214            'Error: Value for Evant Name is passed as NULL .');
215     END IF ;
216     IF ( p_Event_Type <> BOOLEAN_TYPE AND p_Event_Type <> MULTI_TYPE ) THEN
217       RAISE_APPLICATION_ERROR(-20010,
218            'Error: Invalid event type : '||p_Event_Type );
219     END IF;
220 
221     --
222     -- If the number of workers is greater than 999 raise an error.
223     --
224     IF ( NVL(p_Num_Workers ,1 ) > MAX_ALLOWED_WORKERS ) THEN
225       RAISE_APPLICATION_ERROR(-20010,
226         'Error: Number of workers exceeds the maximum limit.');
227     END IF ;
228 
229     --
230     -- Check whether a multi worker event is initialized with
231     -- multiple workers. If so raise an error. This block will
232     -- handle all the cases, already registered and new events.
233     --
234     IF ( p_Event_Type = MULTI_TYPE AND nvl(p_Num_Workers,1) > 1 ) THEN
235       RAISE_APPLICATION_ERROR(-20010,'Multi State Events Cannot be '||
236 	                         'Initialized with multiple Workers');
237     END IF;
238 
239   END Validate_Parameters;
240 --------------------------------------------------------------------------
241   PROCEDURE Initialize_Event(
242               p_Owner       IN VARCHAR2,
243               p_Event_Name  IN VARCHAR2,
244               p_Module_Name IN VARCHAR2,
245               p_Event_Type  IN VARCHAR2   := NULL ,
246               p_Context     IN VARCHAR2   := NULL ,
247               p_Version     IN NUMBER     := NULL ,
248               p_Worker_Id   IN NUMBER     := NULL ,
249               p_Num_Workers IN NUMBER     := NULL )
250    IS
251   -- Local variable declarations
252   l_Version               ad_events.last_version%TYPE;
253   l_Event_Id              ad_events.event_id%TYPE;
254   l_Event_Type            ad_events.event_type%TYPE;
255   l_Event_Status          ad_event_versions.status%TYPE;
256   l_Worker_Status_String  ad_event_versions.worker_status%TYPE;
257   l_Event_Index           NUMBER(3) ;
258   l_Commit_Flag           BOOLEAN := FALSE ;
259 
260   -- The following variables will be used to store the IN parameter value
261   l_p_Event_Type          ad_events.event_type%TYPE;
262   l_p_Context             ad_events.event_context%TYPE ;
263   l_p_Version             ad_events.last_version%TYPE;
264 
265   -- The following variable holds the value of number of workers in the last
266   -- call, in case the event fails and restarted this value will be useful.
267   l_Prev_Max_Workers      ad_event_versions.num_workers%TYPE ;
268   l_Error_Message         VARCHAR2 (100);
269 
270   BEGIN  -- Begin Procedure
271     --
272     -- The following block is used to take care of the default values
273     -- Change done for file.sql.35
274     --
275     l_p_Event_Type := nvl(p_Event_Type, BOOLEAN_TYPE);
276     l_p_Context    := nvl(p_Context, DEFAULT_CONTEXT);
277     l_p_Version    := nvl(p_Version, DEFAULT_VERSION);
278 
279     --
280     -- Call the procedure for validating the parameters
281     --
282     Validate_Parameters(
283                  p_Owner       => p_Owner ,
284 		 p_Event_Name  => p_Event_Name ,
285 		 p_Event_Type  => l_p_Event_Type,
286 		 p_Num_Workers => p_Num_Workers);
287 
288     --
289     -- Request for the lock
290     --
291     Request_Lock(p_Owner,
292                    p_Event_Name);
293 
294     BEGIN -- Block 1
295 
296       -- Select the details of the event for the passed parameters.
297       SELECT last_version,
298              event_id,
299              event_type
300       INTO   l_Version,
301              l_Event_Id,
302              l_Event_Type
303       FROM   ad_events
304       WHERE  owner         = p_Owner
305       AND    event_name    = p_Event_Name
306       AND    event_context = l_p_Context;
307 
308       --
309       -- Compare the event type in the database with that in the call.
310       -- If both doesn't match raise an error.
311       --
312       IF ( l_Event_Type <> l_p_Event_Type ) THEN
313         RAISE_APPLICATION_ERROR (-20010,'Event initialized with a '||
314 	                                'wrong Type');
315       END IF ;
316 
317       --
318       -- The following block is to make sure that an already registered
319       -- multi state event is not initialized with multiple workers.
320       --
321       IF ( l_Event_Type = MULTI_TYPE AND nvl(p_Num_Workers,0) > 1 ) THEN
322         RAISE_APPLICATION_ERROR (-20010,'Multi State Event Cannot be '||
323 	                         'Initialized with multiple Workers');
324       END IF;
325 
326       IF ( l_Version < l_p_Version ) THEN -- If 1 to check version
327         --
328 	-- Get the worker status string
329 	--
330 	l_Worker_Status_String := Initialize_Worker_String(p_Num_Workers);
331         --
332         -- I.e. A version with a lesser version number exists.
333         -- A higher version is being registered.
334 	-- It has to be inserted into AD_EVENT_VERSIONS.
335 	--
336         INSERT INTO ad_event_versions(
337 	             event_id,
338 	             version,
339 	             status,
340 		     creation_date,
341 		     last_update_date,
342 		     num_workers,
343 		     worker_status)
344         VALUES(      l_Event_Id,
345 	             l_p_Version,
346 	             INITIALIZED_STATUS,
347                      SYSDATE ,
348 		     SYSDATE,
349 		     p_Num_Workers,
350 		     l_Worker_Status_String)
351 	RETURNING    status
352 	INTO         l_Event_Status ;
353 
354 	--
355 	-- If event with lesser version number exists; version and last
356 	-- update date are updated in AD_EVENTS
357 	--
358 	UPDATE ad_events
359 	SET    last_version     = l_p_Version,
360                last_update_date = SYSDATE
361 	WHERE  event_id         = l_Event_Id;
362 
363 	l_Commit_Flag      := TRUE ; -- Committing the transaction here.
364 	l_Prev_Max_Workers := p_Num_Workers;
365       ELSE -- else to check version
366         BEGIN --Block 2
367  	  --
368 	  -- The control comes here when the event is already
369 	  -- registered and the version is greater than or equal to p_Version
370 	  --
371 	  SELECT status,
372 	         worker_status,
373 		 num_workers
374 	  INTO   l_Event_Status,
375 	         l_Worker_Status_String,
376 		 l_Prev_Max_Workers
377 	  FROM   ad_Event_Versions
378 	  WHERE  event_id = l_Event_Id
379 	  AND    version  = l_p_Version;
380         EXCEPTION
381           WHEN OTHERS THEN
382             RAISE_APPLICATION_ERROR (-20010,'Event with version '||
383 	              l_p_Version||' not registered. ');
384         END; --End of Block2
388      WHEN NO_DATA_FOUND THEN
385       END IF; -- End If 1 to check version
386 
387    EXCEPTION
389        -- No Events with the same Owner,Name,Context are registered so far.
390        -- New Event can be registered Now.
391        INSERT INTO ad_events(
392                     event_id,
393 		    owner,
394                     event_name,
395 		    event_context,
396 		    event_type,
397 		    last_version,
398                     creation_date,
399 		    last_update_date)
400        VALUES(
401                     ad_events_s.NEXTVAL,
402 		    p_Owner,
403                     p_Event_Name,
404 		    l_p_Context,
405 		    l_p_Event_Type,
406 		    l_p_Version,
407                     SYSDATE,
408 		    SYSDATE  )
409        RETURNING   event_id
410        INTO        l_Event_Id;
411 
412        -- Insert the version details into AD_EVENT_VERSIONS
413        --
414        -- Form the worker status string
415        --
416        l_Worker_Status_String := Initialize_Worker_String(p_Num_Workers);
417 
418        INSERT INTO ad_event_versions(
419                     event_id,
420 		    version,
421 		    status,
422                     creation_date,
423 		    last_update_date,
424 		    num_workers,
425 		    worker_status)
426        VALUES(
427                     l_Event_Id,
428 		    l_p_Version,
429 		    INITIALIZED_STATUS,
430                     SYSDATE,
431 		    SYSDATE,
432 		    p_Num_Workers,
433 		    l_Worker_Status_String);
434 
435        l_Commit_Flag      := TRUE ;
436        -- Argument event type will be the type of the new event.
437        l_Event_Type       := l_p_Event_Type;
438        -- For new event, status will be initialized status
439        l_Event_Status     := INITIALIZED_STATUS;
440        l_Prev_Max_Workers := p_Num_Workers;
441      WHEN OTHERS THEN
442        RAISE ;
443     END; -- End of Block 1
444 
445     --
446     -- If the event is already initialized in the session it is not required
447     -- to add the same to the global event list again.
448     -- The below function call gets the index of the event from the
449     -- global event list, if the event is already registered in the session.
450     -- Ideally the function call should return 0.
451     --
452     l_Event_Index   := Get_Event_Index(
453                                         p_Owner      => p_Owner,
454 					p_Event_Name => p_Event_Name ,
455 					p_Context    => l_p_Context);
456 
457     --
458     -- For new events add the event details to the end of
459     -- the global event list. For already registered events update the
460     -- details in the global event list.
461     --
462     -- For new events the index value returned by the above call will be 0
463     IF ( l_Event_Index = 0 ) THEN
464       l_Event_Index := NVL(g_Events_Tbl.LAST,0) + 1;
465       g_Events_Tbl(l_Event_Index).Owner         := p_Owner;
466       g_Events_Tbl(l_Event_Index).Event_Name    := p_Event_Name;
467       g_Events_Tbl(l_Event_Index).Event_Context := l_p_Context;
468       g_Events_Tbl(l_Event_Index).Event_Id      := l_Event_Id;
469       g_Events_Tbl(l_Event_Index).Event_Status  := l_Event_Status;
470       g_Events_Tbl(l_Event_Index).Worker_Status := l_Worker_Status_String;
471       g_Events_Tbl(l_Event_Index).Event_Version := l_p_Version;
472       g_Events_Tbl(l_Event_Index).Event_Type    := l_Event_Type;
473       g_Events_Tbl(l_Event_Index).Module_Name   := p_Module_Name;
474       g_Events_Tbl(l_Event_Index).Worker_Id     := p_Worker_Id;
475       g_Events_Tbl(l_Event_Index).Max_Workers   := p_Num_Workers;
476     ELSE
477       g_Events_Tbl(l_Event_Index).Event_Version := l_p_Version;
478       g_Events_Tbl(l_Event_Index).Event_Status  := l_Event_Status; -- check this
479       g_Events_Tbl(l_Event_Index).Module_Name   := p_Module_Name;
480       g_Events_Tbl(l_Event_Index).Worker_Id     := p_Worker_Id;
481       g_Events_Tbl(l_Event_Index).Max_Workers   := p_Num_Workers;
482     END IF ;
483 
484     --
485     -- If the multi-worker event fails before completion,
486     -- and gets re-started with a different number of workers then
487     -- the worker information in the db and session has to be updated.
488     --
489     IF ( l_Event_Status <> COMPLETED_STATUS -- If worker re-schedule
490     AND NVL (l_Prev_Max_Workers,1) <> NVL (p_Num_Workers,1) ) THEN
491        --
492        -- Form the worker status string
493        --
494        g_Events_Tbl(l_Event_Index).Worker_Status :=
495 			Initialize_Worker_String(p_Num_Workers);
496        -- reset the worker status string and number_workers
497        -- in ad_event_versions
498        UPDATE ad_event_versions
499        SET num_workers      = p_Num_Workers,
500 	   worker_status    = g_Events_Tbl(l_Event_Index).Worker_Status ,
501 	   last_update_date = SYSDATE
502        WHERE event_id = l_Event_Id
503        AND   version  = l_p_Version ;
504 
505        -- Inserting a record into the transition record to show that
506        -- a rescheduling has happened for the event.
507        Insert_Event_Transitions(
508               p_Event_Id    => l_Event_Id,
509 	      p_Version     => l_p_Version,
510 	      p_New_Status  => 'RE-SCHEDULED',
511 	      p_Old_Status  => l_Event_Status,
512 	      p_Module_Name => p_Module_Name,
516 	l_Commit_Flag := TRUE ;
513 	      p_Worker_Id   => p_Worker_Id);
514 
515 	-- Set the commit flag
517     END IF ; -- End If worker re-schedule
518     -- Commit the transaction if the commit flag is set
519     IF ( l_Commit_Flag = TRUE ) THEN
520       COMMIT ;
521     END IF ;
522 
523     --
524     -- Release the lock
525     --
526     AD_LOCK_UTILS_PKG.Release_Lock(
527                      p_LockHandle => g_Event_LockHandle);
528 
529     g_Event_LockHandle := NULL ;
530 
531    EXCEPTION
532     WHEN OTHERS THEN
533      IF ( g_Event_LockHandle IS NOT NULL ) THEN
534        BEGIN -- begin for release lock
535 	    AD_LOCK_UTILS_PKG.Release_Lock(
536 		             p_LockHandle => g_Event_LockHandle);
537 	    g_Event_LockHandle := NULL ;
538        EXCEPTION
539         WHEN OTHERS THEN
540 	 NULL ;
541        END ; -- end for release lock
542      END IF ;
543      RAISE ;
544   END Initialize_Event;
545 --------------------------------------------------------------------------
546 
547   PROCEDURE Start_Event(
548               p_Owner       IN VARCHAR2,
549               p_Event_Name  IN VARCHAR2,
550               p_Context     IN VARCHAR2 := NULL
551   )
552   IS
553     l_Event_Status         ad_event_versions.status%TYPE;
554     l_Event_type           ad_events.event_type%TYPE;
555     l_Event_Id             ad_events.event_id%TYPE;
556     l_Version              ad_event_versions.version%TYPE;
557     l_Worker_Id            ad_event_transitions.worker_id%TYPE ;
558     l_Worker_Status_String ad_event_versions.worker_status%TYPE ;
559     l_Module_Name          ad_event_transitions.module_name%TYPE ;
560     l_Event_Index          NUMBER ;
561     -- this variable is used to hold in the IN parameter
562     l_p_Context            ad_events.event_context%TYPE ;
563   BEGIN
564    --
565    -- The below block checks the value of parameter p_Contect
566    -- if the value is null, it is assumed that the value is default value.
567    -- the change was done for file.sql.35
568    --
569    l_p_Context := nvl(p_Context, DEFAULT_CONTEXT);
570 
571    --
572    -- The following call checks whether the event is initialized
573    -- Compares the global variable values with the values in
574    -- the current call also.
575    --
576    Validate_Globals(p_Owner,
577                     p_Event_Name,
578 		    l_p_Context);
579    --
580    -- Now get the index of the current event from the global event list.
581    -- Use this index value to access the other event details.
582    --
583    l_Event_Index := Get_Event_Index(
584                                      p_Owner,
585 				     p_Event_Name,
586 				     l_p_Context);
587    BEGIN -- Block 1
588      --
589      -- we are not going to select the event details from db.
590      -- get it from the global event list in the session.
591      --
592      l_Event_Status         := g_Events_Tbl(l_Event_Index).Event_Status;
593      l_Event_type           := g_Events_Tbl(l_Event_Index).Event_Type;
594      l_Event_Id             := g_Events_Tbl(l_Event_Index).Event_id;
595      l_Version              := g_Events_Tbl(l_Event_Index).Event_Version;
596      l_Worker_Id            := g_Events_Tbl(l_Event_Index).Worker_Id;
597      l_Worker_Status_String := g_Events_Tbl(l_Event_Index).Worker_Status;
598      l_Module_Name          := g_Events_Tbl(l_Event_Index).Module_Name;
599 
600      IF ( NVL(g_Events_Tbl(l_Event_Index).Max_Workers,1) > 1
601         AND SUBSTR(l_Worker_Status_String, l_Worker_Id,1) = 'Y' ) THEN
602      -- If worker status
603        --
604        -- The worker has already completed.
605        --
606        RAISE_APPLICATION_ERROR(-20010,'Worker has completed already.');
607      END IF ; --end if worker status
608 
609      IF ( l_Event_Status = COMPLETED_STATUS ) THEN -- if event status
610        --
611        -- The Event is already completed, so it is not possible
612        -- to start the same.
613        --
614        RAISE_APPLICATION_ERROR(-20010,'Event is Already Completed');
615      ELSIF ( l_Event_Status = INITIALIZED_STATUS ) THEN --else if event status
616        --
617        -- Update the start time and last update date in AD_EVENT_VERSIONS.
618        --
619        UPDATE ad_event_versions
620        SET start_time       = SYSDATE ,
621            last_update_date = SYSDATE
622        WHERE event_id = l_Event_Id
623        AND   version  = l_Version;
624        --
625        -- Whenver an Event is getting started
626        -- an entry is inserted into AD_EVENT_TRANSITIONS with
627        -- old status NULL and new status as Initialized status.
628        --
629        Insert_Event_Transitions(
630               p_Event_Id    => l_Event_Id,
631 	      p_Version     => l_Version,
632 	      p_New_Status  => INITIALIZED_STATUS,
633 	      p_Module_Name => l_Module_Name,
634 	      p_Worker_Id   => l_Worker_Id);
635 
636      ELSE -- else if event status
637        --
638        -- The event is in some status other than completed and initialized.
639        -- It means that event is already started, so it is not possible to
640        -- start the same once again.
641        --
642        RAISE_APPLICATION_ERROR (-20010,'Invalid Event Status. '||
646    COMMIT ;
643                                        'Not possible to start.');
644      END IF; -- end if event status
645    END; -- End Block 1
647   END Start_Event;
648 
649   ---------------------------------------------------------------------------
650 
651   Procedure End_Event(
652               p_Owner       IN VARCHAR2,
653               p_Event_Name  IN VARCHAR2,
654               p_Context     IN VARCHAR2 := NULL
655   )
656   IS
657     l_Event_Status          ad_event_versions.status%TYPE;
658     l_New_Status            ad_event_versions.status%TYPE;
659     l_Event_type            ad_events.event_type%TYPE;
660     l_Event_Id              ad_events.event_id%TYPE;
661     l_Version               ad_event_versions.version%TYPE;
662     l_Worker_Status_String  ad_event_versions.worker_status%TYPE;
663     l_End_Time              DATE ;
664     l_Max_Workers           ad_event_versions.num_workers%TYPE ;
665     l_Worker_Id             ad_event_transitions.worker_id%TYPE ;
666     l_Module_Name           ad_event_transitions.module_name%TYPE ;
667     -- the following variable stores the index that points to the current
668     -- event's record in the event list
669     l_Event_Index           NUMBER ;
670     -- this variable is used to hold in the IN parameter
671     l_p_Context            ad_events.event_context%TYPE ;
672 
673   BEGIN -- begin procedure
674    --
675    -- The below block checks the value of parameter p_Contect
676    -- if the value is null, it is assumed that the value is default value.
677    -- the change was done for file.sql.35
678    --
679    l_p_Context    := nvl(p_Context, DEFAULT_CONTEXT);
680 
681    --
682    -- The following call checks whether the event is initialized
683    -- in the current session
684    --
685    Validate_Globals(p_Owner,
686                     p_Event_Name,
687 		    l_p_Context);
688    --
689    -- Get the index of the event from the global event list
690    --
691    l_Event_Index := Get_Event_Index(p_Owner,
692                                     p_Event_Name,
693                                     l_p_Context);
694 
695    -- Now get the details from the global event list
696    l_Max_Workers := g_Events_Tbl(l_Event_Index).Max_Workers;
697    l_Worker_Id   := g_Events_Tbl(l_Event_Index).Worker_Id;
698    l_Module_Name := g_Events_Tbl(l_Event_Index).Module_Name;
699 
700    BEGIN -- Block 1
701      --
702      -- Request for the lock.
703      --
704      Request_Lock(p_Owner,
705                   p_Event_Name);
706 
707      --
708      -- Select the details of the event joining AD_EVENTS and
709      -- AD_EVENT_VERSIONS by joining using the version.
710      --
711 
712      SELECT status,
713             event_type,
714 	    ae.event_id,
715 	    av.version,
716 	    worker_status
717      INTO   l_Event_Status,
718             l_Event_type,
719 	    l_Event_Id,
720 	    l_Version,
721 	    l_Worker_Status_String
722      FROM   ad_events ae, ad_event_versions av
723      WHERE  ae.event_id      = av.event_id
724      AND    ae.last_version  = av.version
725      AND    ae.owner         = p_Owner
726      AND    ae.event_name    = p_Event_Name
727      AND    ae.event_context = l_p_Context;
728 
729      IF ( l_Event_Status = COMPLETED_STATUS ) THEN -- if status check
730        --
731        -- The event is already completed so no need to end the same again.
732        --
733        RAISE_APPLICATION_ERROR(-20010,'Event is Already Completed.');
734      ELSE  -- else status check
735        --
736        -- The below if block is for checking multi-worker events.
737        --
738        IF ( NVL(l_Max_Workers,0) > 1 ) THEN  -- if max workers
739 
740          --
741 	 -- Copy the current status of the event to l_New_Status.
742 	 --
743          l_New_Status := l_Event_Status;
744 
745 	 --
746 	 -- Worker status uses positional characters to indicate
747 	 -- status of a worker.
748 	 -- Form the new worker status string by changing 'N' to 'Y'
749 	 -- at the proper position for the worker in the string.
750 	 --
751 	 Set_Worker_Status_String (l_Worker_Id,
752 	                           l_Worker_Status_String);
753 
754 	 --
755 	 -- Check whether all the workers are completed.
756 	 -- If there are no 'N's in the new worker status string it means
757 	 -- that all the workers have completed.
758 	 -- So set the new worker status as completed status.
759 	 -- otherwise status remains as the old status.
760 	 --
761 	 IF ( INSTR(l_Worker_Status_String,'N') = 0 ) THEN
762 	   l_New_Status := COMPLETED_STATUS;
763 	   l_End_Time   := SYSDATE;
764 	 END IF;
765 
766          UPDATE  ad_event_versions
767 	 SET     status           = l_New_Status,
768 	         end_time         = l_End_Time,
769 	         last_update_date = SYSDATE ,
770                  worker_status    = l_Worker_Status_String
771 	 WHERE   event_id   = l_Event_Id
772          AND     version    = l_Version;
773 
774          --
775          -- The below block is for inserting the event transition records
776          -- for multi-worker events.
777          -- The transition records will be inserted only when the event is
781          IF ( l_New_Status = COMPLETED_STATUS )THEN -- if for completed status
778          -- completed. In case of multi-worker events, Event gets completed
779          -- only when all the workers are completed.
780          --
782            Insert_Event_Transitions(
783               p_Event_Id    => l_Event_Id,
784 	      p_Version     => l_Version,
785 	      p_New_Status  => l_New_Status,
786 	      p_Old_Status  => l_Event_Status,
787 	      p_Module_Name => l_Module_Name,
788 	      p_Worker_Id   => l_Worker_Id);
789 
790          END IF; -- end if for completed status
791 
792 	 -- Commit the transaction here
793          COMMIT;
794 
795        ELSE  -- else max workers
796          --
797 	 -- Single worker events.
798 	 -- New status will be - completed status.
799 	 --
800 	 l_New_Status := COMPLETED_STATUS;
801 
802          UPDATE   ad_event_versions
803          SET      status           = l_New_Status,
804                   end_time         = SYSDATE ,
805                   last_update_date = SYSDATE
806          WHERE    event_id   = l_Event_Id
807          AND      version    = l_Version;
808 
809          --
810          -- The below block is for inserting the event transition records
811          -- for single-worker events.
812          -- The transition records will be inserted only when the event is
813          -- completed.
814          --
815            Insert_Event_Transitions(
816               p_Event_Id    => l_Event_Id,
817 	      p_Version     => l_Version,
818 	      p_New_Status  => l_New_Status,
819 	      p_Old_Status  => l_Event_Status,
820 	      p_Module_Name => l_Module_Name);
821 
822 	 -- Commit the transaction here
823          COMMIT;
824 
825        END IF; -- End if max workers
826 
827        --
828        -- Set the global variables
829        --
830        g_Events_Tbl(l_Event_Index).Event_Status  := l_New_Status;
831        g_Events_Tbl(l_Event_Index).Worker_Status := l_Worker_Status_String;
832 
833 
834      END IF;   -- End if status check
835      --
836      -- Release the lock.
837      -- The lock is released only after doing all the DMLs
838      -- and the commit
839      --
840      AD_LOCK_UTILS_PKG.Release_Lock(
841                     p_LockHandle => g_Event_LockHandle);
842 
843     g_Event_LockHandle := NULL ;
844 
845    EXCEPTION
846     WHEN OTHERS THEN
847      RAISE ;
848    END; -- End Block 1
849   EXCEPTION
850     WHEN OTHERS THEN
851      IF ( g_Event_LockHandle IS NOT NULL ) THEN
852        BEGIN -- begin for release lock
853 	    AD_LOCK_UTILS_PKG.Release_Lock(
854 		             p_LockHandle => g_Event_LockHandle);
855 	    g_Event_LockHandle := NULL ;
856        EXCEPTION
857         WHEN OTHERS THEN
858 	 NULL ;
859        END ; -- end for release lock
860      END IF ;
861      RAISE ;
862   END End_Event;
863 --------------------------------------------------------------------------
864   FUNCTION Check_Min_Completed_Version(
865             p_Owner                 IN VARCHAR2 ,
866 	    p_Event_Name            IN VARCHAR2 ,
867 	    p_Min_Completed_Version IN NUMBER ,
868     	    p_Context               IN VARCHAR2 := NULL )
869   RETURN BOOLEAN
870   IS
871     -- Local Variables
872     l_Temp_Var       NUMBER ;
873     l_Return_Status  BOOLEAN ;
874     -- this variable is used to hold in the IN parameter
875     l_p_Context      ad_events.event_context%TYPE ;
876 
877   BEGIN
878     --
879     -- If NULL is passed as the context assume the value to be DEFAULT
880     l_p_Context    := nvl(p_Context, DEFAULT_CONTEXT);
881 
882     --
883     -- Set the return status to false
884     l_Return_Status := FALSE ;
885 
886     --
887     -- Select the status, version of the versions higher than or equal to
888     -- the p_Min_Completed_Version.
889     -- if any of these versions are completed, it means that the event is
890     -- completed to atleast that level. hence return TRUE
891     -- Else return FALSE
892     --
893     SELECT 1
894     INTO   l_Temp_Var
895     FROM   ad_events ae,
896            ad_Event_Versions av
897     WHERE  ae.owner = p_Owner
898     AND    ae.event_name = p_Event_Name
899     AND    ae.event_context = l_p_Context
900     AND    ae.event_id = av.event_id
901     AND    av.version >= p_Min_Completed_Version
902     AND    av.status = COMPLETED_STATUS
903     AND    ROWNUM < 2;
904 
905     l_Return_Status := TRUE ;
906 
907     RETURN l_Return_Status;
908 
909    EXCEPTION
910     --
911     -- When the select returns no rows it means that there are no versions
912     -- matching the IN parameters. Return FALSE
913     --
914     WHEN NO_DATA_FOUND THEN
915      RETURN l_Return_Status ;
916   END Check_Min_Completed_Version;
917 --------------------------------------------------------------------------
918 
919   FUNCTION Is_Event_Done(
920             p_Owner             IN VARCHAR2 ,
921 	    p_Event_Name        IN VARCHAR2 ,
922 	    p_Context           IN VARCHAR2 := NULL ,
923 	    p_Min_Version       IN NUMBER   := NULL ,
927   RETURN   BOOLEAN
924 	    p_Specific_Version  IN NUMBER   := NULL ,
925 	    p_Worker_Id         IN NUMBER   := NULL ,
926 	    p_Num_Workers       IN NUMBER   := NULL )
928   IS
929     -- Local variable declarations.
930     l_Event_Status           ad_event_versions.status%TYPE;
931     l_Worker_Status_String   ad_event_versions.worker_status%TYPE;
932     l_Num_Workers            ad_event_versions.num_workers%TYPE;
933     l_Return_Status          BOOLEAN;
934     l_Event_Version          ad_event_versions.version%TYPE;
935     -- this variable is used to hold in the IN parameter
936     l_p_Context            ad_events.event_context%TYPE ;
937 
938   BEGIN
939     --
940     -- The below block checks the value of parameter p_Contect
941     -- if the value is null, it is assumed that the value is default value.
942     -- the change was done for file.sql.35
943     --
944     l_p_Context    := nvl(p_Context, DEFAULT_CONTEXT);
945 
946     --
947     -- The user can specify either a Minimum version or a Specific version
948     -- only. Both should not be used in the same call.
949     -- Raise an error if both are specified.
950     --
951     IF ( p_Min_Version IS NOT NULL AND p_Specific_Version IS NOT NULL ) THEN
952       RAISE_APPLICATION_ERROR(-20010,'Minimum version and Specific version '||
953                               'should not be used together.');
954     END IF ;
955 
956     --
957     -- Select the details of the event based on the input details.
958     -- Since the event id is available in AD_EVENTS only AD_EVENTS and
959     -- AD_EVENT_VERSIONS are joined on this column.
960     -- If a specific version is supplied use that version in the where
961     -- clause otherwise use the last_version column of ad_events.
962     --
963     SELECT av.status,
964            av.worker_status,
965            av.version,
966 	   av.num_workers
967     INTO   l_Event_Status,
968            l_Worker_Status_String,
969            l_Event_Version,
970 	   l_Num_Workers
971     FROM   ad_events ae,
972            ad_event_versions av
973     WHERE  ae.owner         = p_Owner
974     AND    ae.event_name    = p_Event_Name
975     AND    ae.event_context = l_p_Context
976     AND    av.event_id      = ae.event_id
977     AND    av.version       = NVL(p_Specific_Version,ae.last_version);
978 
979     --
980     -- If the current version of the event is less than
981     -- the min version required, return FLASE.
982     --
983     IF ( l_Event_Version < NVL(p_Min_Version, l_Event_Version) ) THEN
984        RETURN FALSE;
985     END IF;
986 
987     --
988     -- If the event status is completed return TRUE
989     -- for both multi-worker and single worker events.
990     --
991     IF ( l_Event_Status = COMPLETED_STATUS ) THEN -- if event completed
992         l_Return_Status := TRUE;
993     ELSE -- else event completed
994         IF ( NVL(l_Num_Workers,1) > 1 ) THEN -- if num workers
995 	    --
996             -- if number of workers does not match in the current run and
997             -- prior run, return FALSE irrespective of the individual
998             -- worker status.
999             --
1000             IF ( p_Worker_Id IS NOT NULL
1001 	    AND NVL(p_Num_Workers, 1) = NVL(l_Num_Workers, 1)
1002             AND SUBSTR(l_Worker_Status_String,p_Worker_Id,1) = 'Y' ) THEN
1003             -- If worker done
1004                 --
1005                 -- The control comes here when the number of workers is > 1
1006                 -- and the the corresponding worker is completed.
1007                 -- worker status 'Y' indicated that worker is completed.
1008                 --
1009                 l_Return_Status := TRUE;
1010             ELSE -- else worker done
1011                 l_Return_Status := FALSE;
1012             END IF; -- end if worker done
1013         ELSE -- else num workers
1014             --
1015             -- The control comes here when the event is not completed and
1016             -- the number of workers is 1.
1017             -- So return false.
1018             --
1019             l_Return_Status := FALSE;
1020         END IF; -- end if num workers
1021     END IF; -- end if event completed
1022 
1023     RETURN l_Return_Status;
1024 
1025   EXCEPTION
1026     WHEN NO_DATA_FOUND THEN
1027       RETURN FALSE;
1028   END Is_Event_Done ;
1029 
1030 --------------------------------------------------------------------------
1031 
1032   PROCEDURE Assert_Event(
1033               p_Owner            IN VARCHAR2 ,
1034               p_Event_Name       IN VARCHAR2 ,
1035               p_Context          IN VARCHAR2 := NULL ,
1036               p_Min_Version      IN VARCHAR2 := NULL ,
1037               p_Specific_Version IN VARCHAR2 := NULL )
1038   IS
1039     v_Event_Status BOOLEAN ;
1040     -- this variable is used to hold in the IN parameter
1041     l_p_Context            ad_events.event_context%TYPE ;
1042   BEGIN
1043     --
1044     -- The below block checks the value of parameter p_Contect
1045     -- if the value is null, it is assumed that the value is default value.
1046     -- the change was done for file.sql.35
1047     --
1048     l_p_Context    := nvl(p_Context, DEFAULT_CONTEXT);
1049     --
1050     -- Is_Event_Done function is called to check whether the event is done.
1054                         p_Owner,
1051     -- If not raise an error.
1052     --
1053     v_Event_Status := Is_Event_Done(
1055                         p_Event_Name,
1056                         l_p_Context,
1057                         p_Min_Version,
1058                         p_Specific_Version,
1059                         NULL,
1060                         NULL );
1061     IF ( v_Event_Status = FALSE ) THEN
1062       RAISE_APPLICATION_ERROR(-20007,'The event is not completed');
1063     END IF ;
1064   END Assert_Event ;
1065 
1066 --------------------------------------------------------------------------
1067 
1068   FUNCTION Get_Event_Status(
1069              p_Owner            IN VARCHAR2 ,
1070              p_Event_Name       IN VARCHAR2 ,
1071              p_Context          IN VARCHAR2 := NULL ,
1072              p_Min_Version      IN NUMBER   := NULL ,
1073              p_Specific_Version IN NUMBER   := NULL )
1074   RETURN VARCHAR2
1075   IS
1076     l_Status        ad_event_versions.status%TYPE;
1077     l_Event_Version ad_event_versions.version%TYPE;
1078     -- this variable is used to hold in the IN parameter
1079     l_p_Context            ad_events.event_context%TYPE ;
1080   BEGIN
1081     --
1082     -- The below block checks the value of parameter p_Contect
1083     -- if the value is null, it is assumed that the value is default value.
1084     -- the change was done for file.sql.35
1085     --
1086     l_p_Context    := nvl(p_Context, DEFAULT_CONTEXT);
1087 
1088     --
1089     -- The user can specify either a Minimum version or a Specific version
1090     -- only. Both should not be used in the same call.
1091     -- Raise an error if both are specified.
1092     --
1093     IF ( p_Min_Version IS NOT NULL AND p_Specific_Version IS NOT NULL ) THEN
1094       RAISE_APPLICATION_ERROR(-20010,'Minimum version and Specific version '||
1095                               'should not be used together.');
1096     END IF ;
1097 
1098     --
1099     -- Select the details from the db.
1100     -- If a specific version is supplied then select the details foe the same.
1101     -- Otherwise select the details of the version pointed by AD_EVENTS.
1102     --
1103     SELECT av.status,
1104            av.version
1105     INTO   l_Status,
1106            l_Event_Version
1107     FROM
1108            ad_events ae,
1109            ad_event_versions av
1110     WHERE  ae.owner         = p_Owner
1111     AND    ae.event_name    = p_Event_Name
1112     AND    ae.event_context = l_p_Context
1113     AND    av.event_id      = ae.event_id
1114     AND    av.version       = NVL(p_Specific_Version, ae.last_version);
1115 
1116     --
1117     -- If the minimum version of the event required is greater than the
1118     -- current version, then return EVENT_NOT_DEFINED.
1119     -- Else return the current status.
1120     --
1121     IF ( l_Event_Version < p_Min_Version ) THEN
1122       RETURN EVENT_NOT_DEFINED;
1123     ELSE
1124       RETURN l_Status;
1125     END IF;
1126   EXCEPTION
1127     WHEN NO_DATA_FOUND THEN
1128       RETURN EVENT_NOT_DEFINED;
1129   END Get_Event_Status ;
1130 
1131 --------------------------------------------------------------------------
1132 
1133   PROCEDURE Set_Event_Status(
1134               p_Owner      IN VARCHAR2,
1135               p_Event_Name IN VARCHAR2,
1136 	      p_Status     IN VARCHAR2,
1137               p_Context    IN VARCHAR2  := NULL )
1138   IS
1139     l_Event_Status      ad_event_versions.status%TYPE;
1140     l_Num_Workers       ad_event_versions.num_workers%TYPE;
1141     l_Event_Id          ad_event_versions.event_id%TYPE;
1142     l_Version           ad_event_versions.version%TYPE;
1143     l_Event_Index       NUMBER ;
1144     l_Event_Type        ad_events.event_type%TYPE ;
1145     l_Module_Name       ad_event_transitions.module_name%TYPE ;
1146     l_Worker_Id         ad_event_transitions.worker_id%TYPE ;
1147     -- this variable is used to hold in the IN parameter
1148     l_p_Context         ad_events.event_context%TYPE ;
1149   BEGIN
1150     --
1151     -- The below block checks the value of parameter p_Contect
1152     -- if the value is null, it is assumed that the value is default value.
1153     -- the change was done for file.sql.35
1154     --
1155     l_p_Context    := nvl(p_Context, DEFAULT_CONTEXT);
1156 
1157     IF ( p_Status = COMPLETED_STATUS ) THEN
1158       RAISE_APPLICATION_ERROR(-20010,'Set_Event_Status cannot be used to '||
1159                               'complete an Event');
1160     END IF;
1161 
1162    --
1163    -- The following call checks whether the event is initialized
1164    -- and compares the global variable values with the values in
1165    -- the current call also.
1166    --
1167    Validate_Globals(p_Owner,
1168                     p_Event_Name,
1169 		    l_p_Context);
1170     --
1171     -- Now get the index value for the current event from the global
1172     -- event list
1173     --
1174     l_Event_Index := Get_Event_Index( p_Owner,
1175                                       p_Event_Name,
1176 				      l_p_Context);
1177 
1178      --
1179      -- now get the details from the global events table
1180      --
1181      l_Event_Type   := g_Events_Tbl(l_Event_Index).Event_Type;
1182      l_Event_Status := g_Events_Tbl(l_Event_Index).Event_Status;
1186      l_Module_Name  := g_Events_Tbl(l_Event_Index).Module_Name;
1183      l_Num_Workers  := g_Events_Tbl(l_Event_Index).Max_Workers;
1184      l_Event_Id     := g_Events_Tbl(l_Event_Index).Event_Id;
1185      l_Version      := g_Events_Tbl(l_Event_Index).Event_Version;
1187      l_Worker_Id    := g_Events_Tbl(l_Event_Index).Worker_Id;
1188 
1189     --
1190     -- If the type of the event is boolean raise an error.
1191     -- Because for boolean events there are no intermediate states to be set.
1192     --
1193     IF ( l_Event_Type = BOOLEAN_TYPE ) THEN
1194       RAISE_APPLICATION_ERROR (-20010,'Set_Event_Status not applicable to '||
1195                                'boolean events.');
1196     END IF;
1197 
1198     --
1199     -- This block checks whether the event is a multi-worker event.
1200     --
1201     IF ( NVL(l_Num_Workers,1) > 1 ) THEN
1202       RAISE_APPLICATION_ERROR (-20010,'Set_Event_Status not applicable to '||
1203                                       'multi-worker events.');
1204     END IF ;
1205 
1206     --
1207     -- If already the status is completed return error.
1208     --
1209     IF ( l_Event_Status = COMPLETED_STATUS ) THEN
1210       RAISE_APPLICATION_ERROR(-20010,'Event is Already Completed');
1211     END IF;
1212 
1213     --
1214     -- If number of workers is greater then 1 raise an error.
1215     --
1216     IF ( nvl(l_Num_Workers,1) > 1 ) THEN
1217       RAISE_APPLICATION_ERROR (-20010,'Set_Event_Status not applicable to '||
1218                                       'multi-worker events.');
1219     END IF;
1220 
1221     -- Request for the lock
1222     Request_Lock(p_Owner,
1223                  p_Event_Name);
1224     --
1225     -- Validations are thru. Now update the status.
1226     --
1227     UPDATE ad_event_versions
1228     SET    status = p_Status,
1229            last_update_date = SYSDATE
1230     WHERE  event_id = l_Event_Id
1231     AND    version  = l_Version;
1232 
1233     --
1234     -- Insert the event transition entries
1235     --
1236     Insert_Event_Transitions(
1237               p_Event_Id    => l_Event_Id,
1238 	      p_Version     => l_Version,
1239 	      p_New_Status  => p_Status,
1240 	      p_Old_Status  => l_Event_Status,
1241 	      p_Module_Name => l_Module_Name,
1242 	      p_Worker_Id   => l_Worker_Id);
1243 
1244     --Set the global values here
1245     g_Events_Tbl(l_Event_Index).Event_Status := p_Status;
1246 
1247     -- commit the transaction here
1248     COMMIT;
1249     -- Release the lock.
1250     AD_LOCK_UTILS_PKG.Release_Lock(
1251                      p_LockHandle => g_Event_LockHandle);
1252 
1253     g_Event_LockHandle := NULL ;
1254 
1255    EXCEPTION
1256     WHEN OTHERS THEN
1257      IF ( g_Event_LockHandle IS NOT NULL ) THEN
1258        BEGIN -- begin for release lock
1259 	    AD_LOCK_UTILS_PKG.Release_Lock(
1260 		             p_LockHandle => g_Event_LockHandle);
1261 	    g_Event_LockHandle := NULL ;
1262        EXCEPTION
1263         WHEN OTHERS THEN
1264 	 NULL ;
1265        END ; -- end for release lock
1266      END IF ;
1267      RAISE ;
1268   END Set_Event_Status ;
1269 
1270 
1271 --------------------------------------------------------------------------
1272 
1273   PROCEDURE   Reset_Event(
1274               p_Owner       IN VARCHAR2 ,
1275               p_Event_Name  IN VARCHAR2 ,
1276       	      p_Module_Name IN VARCHAR2 ,
1277               p_Context     IN VARCHAR2 := NULL )
1278   IS
1279     l_Event_Id             ad_event_versions.event_id%TYPE;
1280     l_Event_Version        ad_event_versions.version%TYPE;
1281     l_Event_Status         ad_event_versions.status%TYPE;
1282     l_Max_Workers          ad_event_versions.num_workers%TYPE ;
1283     l_Worker_Status_String ad_event_versions.worker_status%TYPE;
1284     l_Worker_Id            ad_event_transitions.worker_id%TYPE ;
1285     l_Module_Name          ad_event_transitions.module_name%TYPE ;
1286     l_Event_Index          NUMBER ;
1287     -- this variable is used to hold in the IN parameter
1288     l_p_Context         ad_events.event_context%TYPE ;
1289 
1290   BEGIN  -- begin procedure
1291     --
1292     -- The below block checks the value of parameter p_Contect
1293     -- if the value is null, it is assumed that the value is default value.
1294     -- the change was done for file.sql.35
1295     --
1296     l_p_Context    := nvl(p_Context, DEFAULT_CONTEXT);
1297 
1298     l_Module_Name := p_Module_Name;
1299     l_Worker_Id   := NULL ;
1300 
1301     --
1302     -- Request the lock.
1303     --
1304     Request_Lock(p_Owner,
1305                  p_Event_Name);
1306 
1307     --
1308     -- Select the event id and the version from AD_EVENTS.
1309     --
1310     SELECT ae.event_id,
1311            ae.last_version,
1312            av.status,
1313 	   av.num_workers
1314     INTO   l_Event_Id,
1315            l_Event_Version,
1316            l_Event_Status,
1317 	   l_Max_Workers
1318     FROM   ad_events ae, ad_event_versions av
1319     WHERE  ae.owner         = p_Owner
1320     AND    ae.event_name    = p_Event_Name
1321     AND    ae.event_context = l_p_Context
1322     AND    av.event_id      = ae.event_id
1323     AND    av.version       = ae.last_version;
1327                                'Initialized status, Not possible to reset');
1324 
1325     IF ( l_Event_Status = INITIALIZED_STATUS ) THEN
1326       RAISE_APPLICATION_ERROR ( -20010,'The event is already in '||
1328     END IF ;
1329     --
1330     -- The validations are through, now reset the event information.
1331     --
1332     -- Form the worker status string
1333     l_Worker_Status_String := Initialize_Worker_String(l_Max_Workers);
1334 
1335     UPDATE ad_event_versions
1336     SET    status           = INITIALIZED_STATUS,
1337            start_time       = NULL ,
1338            end_time         = NULL ,
1339            last_update_date = SYSDATE ,
1340            worker_status    = LPAD('N',l_Max_Workers,'N')
1341     WHERE  event_id = l_Event_Id
1342     AND    version  = l_Event_Version;
1343 
1344     -- Insert the event transition entry.
1345     Insert_Event_Transitions(
1346               p_Event_Id    => l_Event_Id,
1347 	      p_Version     => l_Event_Version,
1348 	      p_New_Status  => INITIALIZED_STATUS,
1349 	      p_Old_Status  => l_Event_Status,
1350 	      p_Module_Name => l_Module_Name,
1351 	      p_Worker_Id   => l_Worker_Id);
1352 
1353     -- Commit the transaction here.
1354     COMMIT;
1355 
1356     --
1357     -- Release the lock.
1358     --
1359     AD_LOCK_UTILS_PKG.Release_Lock(
1360                      p_LockHandle => g_Event_LockHandle);
1361     g_Event_LockHandle := NULL ;
1362 
1363     -- Get the index pointing to the event from the global event list
1364     -- This step will be useful in case an event is reset in the same
1365     -- session which has initialized the event.
1366     l_Event_Index := Get_Event_Index(p_Owner,
1367                                      p_Event_Name,
1368 				     l_p_Context);
1369     -- If the event is initialized in the session the index value
1370     -- will be non-zero.
1371     IF l_Event_Index <> 0 THEN
1372       -- Set the package global event list values
1373       g_Events_Tbl(l_Event_Index).Event_Status  := INITIALIZED_STATUS;
1374       g_Events_Tbl(l_Event_Index).Worker_Status := LPAD('N',l_Max_Workers,'N');
1375     END IF ;
1376  EXCEPTION
1377    WHEN OTHERS THEN
1378      IF ( g_Event_LockHandle IS NOT NULL ) THEN
1379        BEGIN -- begin for release lock
1380 	    AD_LOCK_UTILS_PKG.Release_Lock(
1381 		             p_LockHandle => g_Event_LockHandle);
1382 	    g_Event_LockHandle := NULL ;
1383        EXCEPTION
1384         WHEN OTHERS THEN
1385 	 NULL ;
1386        END ; -- end for release lock
1387      END IF ;
1388      IF SQLCODE = 100 THEN
1389        RAISE_APPLICATION_ERROR(-20010,'Event not registered. '||
1390                                     'Not possible to reset.');
1391      ELSE
1392        RAISE ;
1393      END IF ;
1394   END Reset_Event ;
1395 
1396 --------------------------------------------------------------------------
1397 
1398   PROCEDURE Set_Event_As_Done(
1399              p_Owner       IN VARCHAR2 ,
1400              p_Event_Name  IN VARCHAR2 ,
1401 	     p_Module_Name IN VARCHAR2 ,
1402              p_Context     IN VARCHAR2 := NULL ,
1403              p_Event_Type  IN VARCHAR2 := NULL ,
1404              p_Version     IN NUMBER   := NULL ,
1405              p_Worker_Id   IN NUMBER   := NULL ,
1406              p_Num_Workers IN NUMBER   := NULL )
1407   IS
1408     l_Event_Id             ad_events.event_id%TYPE;
1409     l_Event_Version        ad_event_versions.version%TYPE ;
1410     l_Event_Status         ad_event_versions.status%TYPE ;
1411     l_New_Status           ad_event_versions.status%TYPE ;
1412     l_Worker_Status_String ad_event_versions.worker_status%TYPE ;
1413     l_End_Time             ad_event_versions.end_time%TYPE ;
1414     l_Worker_Id            ad_event_transitions.worker_id%TYPE ;
1415     l_Prev_Max_Workers     ad_event_versions.num_workers%TYPE ;
1416     l_Commit_Flag          BOOLEAN ;
1417     l_event_completed_EXP  EXCEPTION ;
1418     -- these variables are used to hold in the IN parameter
1419     l_p_Context            ad_events.event_context%TYPE ;
1420     l_p_Event_Type         ad_events.event_type%TYPE ;
1421     l_p_Version            ad_events.last_version%TYPE ;
1422   BEGIN
1423     --
1424     -- The below block checks the value of parameter p_Contect
1425     -- if the value is null, it is assumed that the value is default value.
1426     -- the change was done for file.sql.35
1427     --
1428     l_p_Context    := nvl(p_Context,    DEFAULT_CONTEXT);
1429     l_p_Event_Type := nvl(p_Event_Type, BOOLEAN_TYPE);
1430     l_p_Version    := nvl(p_Version,    DEFAULT_VERSION);
1431 
1432     l_Worker_id := p_Worker_Id;
1433     --
1434     -- Call the procedure for validating the parameters
1435     --
1436     Validate_Parameters(
1437                  p_Owner       => p_Owner ,
1438 		 p_Event_Name  => p_Event_Name ,
1439 		 p_Event_Type  => l_p_Event_Type,
1440 		 p_Num_Workers => p_Num_Workers);
1441 
1442    -- Get the lock
1443    Request_Lock(p_Owner,
1444                 p_Event_Name);
1445    BEGIN -- block 1
1446     --
1447     -- Select the details of the event from the registry.
1448     --
1449     SELECT status,
1450            ae.event_id,
1451 	   worker_status,
1452 	   num_workers,
1453 	   av.version
1454     INTO   l_Event_Status,
1455            l_Event_Id,
1459     FROM   ad_events ae, ad_event_versions av
1456 	   l_Worker_Status_String,
1457 	   l_Prev_Max_Workers,
1458 	   l_Event_Version
1460     WHERE  ae.event_id      = av.event_id
1461     AND    ae.last_version  = av.version
1462     AND    ae.owner         = p_Owner
1463     AND    ae.event_name    = p_Event_Name
1464     AND    ae.event_context = l_p_Context;
1465 
1466     --
1467     -- If there is an event in the db with the same version as that
1468     -- of the one being registered, do the following.
1469     --
1470     IF ( l_Event_Version = l_p_Version ) THEN -- if version check
1471       --
1472       -- If the event in the db is already in completed status
1473       --
1474       IF ( l_Event_Status = COMPLETED_STATUS ) THEN
1475 	RAISE l_event_completed_EXP;
1476       END IF ;
1477       --
1478       -- Control goes to the following block, when
1479       -- the event is already registered, and there is a change in the
1480       -- number of workers.
1481       -- Here we compare the number of workers in this call with the number
1482       -- of workers from the registry. If there is any change we assume that
1483       -- the event is re-scheduled among a different set of workers.
1484       -- So, the worker details in ad_event_versions has to be updated
1485       -- and a special transition entry has to be inserted into
1486       -- ad_event_transitions.
1487       --
1488       IF ( NVL (l_Prev_Max_Workers,1) <> NVL (p_Num_Workers,1) ) THEN
1489       -- # if resch check
1490 	-- Set the commit flag
1491 	l_Commit_Flag := TRUE ;
1492 
1493 	-- Inserting a record into the transition record to show that
1494         -- a rescheduling has happened for the event.
1495         Insert_Event_Transitions(
1496               p_Event_Id    => l_Event_Id,
1497 	      p_Version     => l_p_Version,
1498 	      p_New_Status  => 'RE-SCHEDULED',
1499 	      p_Old_Status  => 'RE-SCHEDULED',
1500 	      p_Module_Name => p_Module_Name,
1501 	      p_Worker_Id   => p_Worker_Id);
1502 
1503 	IF ( NVL (p_Num_Workers,1) > 1 ) THEN -- if # resch_worker
1504 	  --
1505 	  -- The control comes here when the event is re-scheduled
1506 	  -- and the number of workers is more than 1. So we have to form
1507 	  -- the worker status string, and the event status will be NULL.
1508 	  --
1509 	  -- form the worker status string
1510 	  l_Worker_Status_String := LPAD('N',p_Num_Workers,'N');
1511 	  --
1512           -- Form the new status string
1513           --
1514 	  Set_Worker_Status_String(l_Worker_Id, l_Worker_Status_String);
1515 
1516 	  l_New_Status := NULL ;
1517 	ELSE -- if # resch_worker ( number of workers = 1)
1518 	  --
1519 	  -- If the number of workers after the re-scheduling is 1, the
1520 	  -- worker status string will be null. And immediately we can
1521 	  -- say that the event has completed, so the event status will
1522 	  -- become COMPLETED_STATUS.
1523 	  --
1524 	  l_Worker_Status_String := NULL ;
1525           l_New_Status           := COMPLETED_STATUS;
1526 	  l_End_Time             := SYSDATE ;
1527 	  --
1528 	  -- Since the event has completed here, we have to insert an
1529 	  -- event transition entry as below.
1530 	  --
1531           Insert_Event_Transitions(
1532               p_Event_Id    => l_Event_Id,
1533 	      p_Version     => l_p_Version,
1534 	      p_New_Status  => l_New_Status,
1538 
1535 	      p_Old_Status  => 'RE-SCHEDULED',
1536 	      p_Module_Name => p_Module_Name,
1537 	      p_Worker_Id   => p_Worker_Id);
1539 	END IF ; -- if # resch_worker
1540         --
1541 	-- Now update ad_Event_Versions to make the changes happened as a
1542 	-- result of the re-scheduling.
1543 	--
1544 	UPDATE ad_event_versions
1545         SET num_workers      = p_Num_Workers,
1546 	    status           = l_New_Status,
1547 	    worker_status    = l_Worker_Status_String,
1548 	    start_time       = DECODE(start_time,null,SYSDATE,
1549 		                             start_time),
1550 	    last_update_date = SYSDATE ,
1551 	    end_time         = l_End_Time
1552         WHERE event_id = l_Event_Id
1553         AND   version  = l_p_Version;
1554 
1555       ELSE -- re-schedule check
1556       --
1557       -- If the event is multi-worker, then do the following.
1558       -- Multi-worker events require all the workers to complete for the
1559       -- event to get completed.
1560       -- So whenever a worker calls this API the corresponding character
1561       -- position in the worker status string will be updated. When the
1562       -- string is updated to all Y's the event status will be updated to
1563       -- completed.
1564       -- The control comes to this block only from the second call to this
1565       -- procedure. i.e from the second worker only. During the first call
1566       -- there wont be any event of the particular name and it will be
1567       -- caught in the exception handling section below.
1568       --
1569       IF ( NVL(p_Num_Workers,1) > 1 ) THEN -- if num workers
1570 
1571         l_Commit_Flag := TRUE ;
1572 
1573         --
1574         -- Form the new status string
1575         --
1576         Set_Worker_Status_String(l_Worker_Id, l_Worker_Status_String);
1577 
1578         --
1579         -- If all the workers have completed update the event status to
1580         -- completed and the event end time to the current time.
1581         --
1582         IF ( INSTR(l_Worker_Status_String,'N') = 0 ) THEN
1583            l_New_Status := COMPLETED_STATUS;
1584            l_End_Time   := SYSDATE;
1585         END IF;
1586 
1587         --
1588         -- Update ad_event_versions with the new status
1589         --
1590         UPDATE  ad_event_versions
1591         SET     status           = l_New_Status,
1592 	        end_time         = l_End_Time,
1593 	        last_update_date = SYSDATE ,
1594                 start_time       = DECODE(start_time,null,SYSDATE,
1595 		                             start_time),
1596                 worker_status    = l_Worker_Status_String
1597         WHERE   event_id   = l_Event_Id
1598         AND     version    = l_p_Version;
1599 
1600         --
1601         -- The below block is for inserting the event transition records
1602         -- for multi-worker events.
1603         -- The transition records will be inserted only when the event is
1604         -- completed. In case of multi-worker events, Event gets completed
1605         -- only when all the workers are completed.
1606         --
1607         IF ( l_New_Status = COMPLETED_STATUS )THEN -- if for completed status
1608           Insert_Event_Transitions(
1609               p_Event_Id    => l_Event_Id,
1610 	      p_Version     => l_p_Version,
1611 	      p_New_Status  => COMPLETED_STATUS,
1612 	      p_Old_Status  => COMPLETED_STATUS,
1613 	      p_Module_Name => p_Module_Name,
1614 	      p_Worker_Id   => p_Worker_Id);
1615 
1616         END IF; -- end if for completed status
1617 
1618       ELSE -- else for num workers
1619         --
1620 	-- Here the number of workers is 1, the event is already registered
1621 	-- and the status is something other than COMPLETED_STATUS
1622 	-- This is for fixing bug no : 4260836
1623 	--
1624 	IF ( l_Event_Status <> COMPLETED_STATUS ) THEN
1628 	  --
1625           l_Commit_Flag := TRUE ;
1626 	  --
1627 	  -- Mark the event as completed here
1629           UPDATE   ad_event_versions
1630           SET      status           = COMPLETED_STATUS,
1631 	           start_time       = DECODE(start_time,null,SYSDATE,
1632 		                             start_time),
1633                    end_time         = SYSDATE ,
1634                    last_update_date = SYSDATE
1635           WHERE    event_id   = l_Event_Id
1636           AND      version    = l_p_Version;
1637           --
1638 	  -- Insert the transition entries here
1639 	  --
1640           Insert_Event_Transitions(
1641              p_Event_Id    => l_Event_Id,
1642 	     p_Version     => l_p_Version,
1643 	     p_New_Status  => COMPLETED_STATUS,
1644 	     p_Old_Status  => l_Event_Status,
1645 	     p_Module_Name => p_Module_Name);
1646 	ELSE
1647 	  RAISE l_event_completed_EXP;
1648 	END IF ;
1649       END IF ; -- end if num workers.
1650 
1651       END IF ; -- re-schedule check
1652 
1653     ELSIF ( l_Event_Version < l_p_Version ) THEN -- else version check
1654       --
1655       -- The following is a multi-worker event.
1656       -- Here an existing event with a higher version is being registered
1657       -- This is the first worker registering it. So set a new worker status
1658       -- string.
1659       --
1660       IF ( NVL(p_Num_Workers,1) > 1 )  THEN -- if num workers 2
1661         l_Worker_Status_String := LPAD('N',p_Num_Workers,'N');
1662         Set_Worker_Status_String(l_Worker_Id, l_Worker_Status_String);
1663 
1664       ELSE
1665         l_Event_Status := COMPLETED_STATUS;
1666 	l_New_Status   := COMPLETED_STATUS;
1667 	l_End_Time     := SYSDATE ;
1668         l_Commit_Flag  := TRUE ;
1669 
1670         -- Insert the transition details.
1671         Insert_Event_Transitions(
1672               p_Event_Id    => l_Event_Id,
1673 	      p_Version     => l_p_Version,
1674 	      p_New_Status  => l_New_Status,
1675 	      p_Old_Status  => l_Event_Status,
1676 	      p_Module_Name => p_Module_Name,
1677 	      p_Worker_Id   => p_Worker_Id);
1678 
1679       END IF ;  -- end if num workers 2
1680         --
1681 	-- The control comes here when the version being registered is
1682 	-- greater than the latest version and the event is single-worker.
1683 	--
1684         l_Commit_Flag := TRUE ;
1685 
1686         UPDATE   ad_events
1687 	SET      last_version     = l_p_Version,
1688 	         last_update_date = SYSDATE
1692 	INSERT INTO ad_event_versions (
1689 	WHERE    event_id         = l_Event_Id;
1690 
1691         -- Insert the version details.
1693 	             event_id,
1694 		     version,
1695 		     status,
1696 		     start_time,
1697 		     end_time,
1698 		     creation_date,
1699 		     last_update_date,
1700 		     num_workers,
1701 		     worker_status)
1702         VALUES (
1703 	             l_Event_Id,
1704 		     l_p_Version,
1705 		     l_New_Status,
1706 		     SYSDATE ,
1707 		     l_End_Time ,
1708 		     SYSDATE ,
1709                      SYSDATE ,
1710 		     p_Num_Workers ,
1711 		     l_Worker_Status_String );
1712     END IF ; -- end if Version check
1713 
1714    EXCEPTION   -- exceptions for block 1
1715 
1716     WHEN l_event_completed_EXP THEN
1717       --
1718       -- It was decided to do nothing for this exception.
1719       --
1720       NULL ;
1721     WHEN NO_DATA_FOUND THEN
1722 
1723       l_Commit_Flag := TRUE ;
1724 
1725       -- For new events control comes here.
1726       INSERT INTO ad_events(
1727                    event_id,
1728 	           owner,
1729                    event_name,
1730 		   event_context,
1731 		   event_type,
1732 		   last_version,
1733                    creation_date,
1734 		   last_update_date)
1735       VALUES(
1736                    ad_events_s.NEXTVAL,
1737 	           p_Owner,
1738                    p_Event_Name,
1739 		   l_p_Context,
1740 		   l_p_Event_Type,
1741 		   l_p_Version,
1742                    SYSDATE,
1743 		   SYSDATE  )
1744       RETURNING    event_id
1745       INTO         l_Event_Id;
1746       --
1747       -- If there is only a single worker it means that the event
1748       -- is completed here itself. So set the status as completed.
1749       --
1750       IF ( NVL(p_Num_Workers,1) > 1 ) THEN  -- if num-workers
1751         --
1752 	-- Form the worker status string for a multi worker event.
1753 	-- The event status will remain as NULL here .
1754 	-- The subsequent workers whoever is updating the event has
1755 	-- to take care of updating the event status.
1756 	--
1757         l_Worker_Status_String := LPAD('N',p_Num_Workers,'N');
1758         Set_Worker_Status_String(l_Worker_Id, l_Worker_Status_String);
1759 
1760       ELSE  -- else num-workers
1761         -- The control comes here for single-worker events.
1762         -- For single-worker event the status can be put as completed
1763         l_Event_Status := COMPLETED_STATUS;
1764 	-- The end time also can be put as the current time.
1765 	l_End_Time     := SYSDATE ;
1766 
1767         --
1768 	-- Insert the transition records for single-worker events.
1769 	--
1770 
1771         Insert_Event_Transitions(
1772               p_Event_Id    => l_Event_Id,
1773 	      p_Version     => l_p_Version,
1774 	      p_New_Status  => COMPLETED_STATUS,
1775 	      p_Old_Status  => COMPLETED_STATUS,
1776 	      p_Module_Name => p_Module_Name,
1777 	      p_Worker_Id   => p_Worker_Id);
1778 
1779       END IF ; -- end if num-workers
1780       --
1781       -- Insert the event version details here
1782       -- This insertion is done for both single-worker and multi-worker cases
1783       -- but only for the first time.
1784       --
1785       INSERT INTO ad_event_versions(
1786                     event_id,
1787 		    version,
1788 		    status,
1789 		    start_time,
1790 		    end_time,
1791                     creation_date,
1792 		    last_update_date,
1793 		    num_workers,
1794 		    worker_status)
1795        VALUES(
1796                     l_Event_Id,
1797 		    l_p_Version,
1798 		    l_Event_Status,
1799 		    SYSDATE,
1800 		    l_End_Time,
1801                     SYSDATE,
1802 		    SYSDATE,
1803 		    p_Num_Workers,
1804 		    l_Worker_Status_String);
1805    END ; -- block 1
1806    --
1807    -- If the commit flag is set commit the txn here
1808    --
1809    IF ( l_Commit_Flag = TRUE ) THEN
1810      COMMIT ;
1811    END IF ;
1812    --
1813    -- Release the lock
1814    --
1815    AD_LOCK_UTILS_PKG.Release_Lock(
1816                       p_LockHandle => g_Event_LockHandle);
1817    g_Event_LockHandle := NULL ;
1818 
1819    EXCEPTION
1820     WHEN OTHERS THEN
1821      IF ( g_Event_LockHandle IS NOT NULL ) THEN
1822        BEGIN -- begin for release lock
1823 	    AD_LOCK_UTILS_PKG.Release_Lock(
1824 		             p_LockHandle => g_Event_LockHandle);
1825 	    g_Event_LockHandle := NULL ;
1826        EXCEPTION
1827         WHEN OTHERS THEN
1828 	 NULL ;
1829        END ; -- end for release lock
1830      END IF ;
1831      RAISE ;
1832   END Set_Event_As_Done ;
1833 --------------------------------------------------------------------------
1834 
1835 END Ad_Event_Registry_Pkg;