1 package body fnd_adg_support as
2 /* $Header: AFDGSUPB.pls 120.11 2010/08/13 15:22:16 rsanders noship $ */
3
4 G_IS_STANDBY boolean := null;
5 G_IS_PRIMARY boolean := null;
6 G_IS_NO_DML boolean := null;
7 G_IS_TRUE_STANDBY boolean := null;
8 G_HANDLE_REQUEST_ROW_ALL boolean := null;
9 G_HANDLE_REQUEST_ROW_PRIMARY boolean := null;
10
11 C_OPEN_READ_ONLY constant varchar2(30) := 'READ ONLY';
12 C_OPEN_READ_WRITE constant varchar2(30) := 'READ WRITE';
13 C_STANDBY_ROLE constant varchar2(30) := 'PHYSICAL STANDBY';
14 C_PRIMARY_ROLE constant varchar2(30) := 'PRIMARY';
15
16 C_REPORTWRITER constant varchar2(30) := 'P';
17 C_STATUS_NORMAL constant varchar2(10) := 'C';
18 C_PHASE_COMPLETE constant varchar2(10) := 'C';
19
20 -- use real CR to get passed arcs!
21
22 LF constant varchar2(10) := '
23 ';
24
25 /*==========================================================================*/
26
27 procedure set_is_no_dml
28 as
29 begin
30
31 -- This routine currently does nothing but separates is_standby
32 -- from dml.
33
34 G_IS_NO_DML := true;
35
36 end;
37
38 /*==========================================================================*/
39
40 procedure set_handle_request_row_change
41 as
42 begin
43
44 G_HANDLE_REQUEST_ROW_ALL := false;
45 G_HANDLE_REQUEST_ROW_PRIMARY := false;
46
47 if ( fnd_adg_utility.is_standby_access_supported )
48 then
49 if ( fnd_adg_utility.is_adg_support_enabled )
50 then
51 G_HANDLE_REQUEST_ROW_ALL := true;
52 end if;
53
54 if ( fnd_adg_utility.is_always_collect_primary_data )
55 then
56 G_HANDLE_REQUEST_ROW_PRIMARY := true;
57 end if;
58 end if;
59
60 end;
61
62 /*==========================================================================*/
63
64 -- Currently unused and removed from spec.
65
66 function is_standby_no_dml return boolean
67 as
68 begin
69
70 if ( not is_standby )
71 then
72 return false;
73 end if;
74
75 if ( G_IS_NO_DML is null )
76 then
77 set_is_no_dml;
78 end if;
79
80 return G_IS_NO_DML;
81
82 end;
83
84 /*==========================================================================*/
85
86 procedure set_is_standby
87 as
88 cursor c1 is select a.open_mode,a.database_role
89 from v$database a;
90 begin
91
92 G_IS_STANDBY := false;
93
94 -- To keep in sync with RPC usage and to avoid redundant checks
95 -- always return false unless compile directive is in force.
96
97 $if fnd_adg_compile_directive.enable_rpc
98 $then
99
100 if ( fnd_adg_utility.is_standby_access_supported and
101 fnd_adg_utility.is_adg_support_enabled )
102 then
103
104 for f_rec in c1 loop
105
106 if ( f_rec.open_mode = C_OPEN_READ_ONLY and
107 f_rec.database_role= C_STANDBY_ROLE )
108 then
109 G_IS_STANDBY := true;
110 end if;
111 end loop;
112
113 if ( not G_IS_STANDBY )
114 then
115 -- Allow for simulated standby if running on primary.
116
117 if ( fnd_adg_utility.is_session_simulated_standby and is_primary )
118 then
119 if ( not is_rpc_from_standby ) -- only true when slave rpc
120 then
121 G_IS_STANDBY := true; -- rpc client is now simulated as standby.
122 end if;
123 end if;
124 end if;
125
126 end if;
127
128 $else
129 null;
130 $end
131
132 end;
133
134 /*==========================================================================*/
135
136 procedure set_is_true_standby
137 as
138 cursor c1 is select a.open_mode,a.database_role
139 from v$database a;
140 begin
141
142 G_IS_TRUE_STANDBY := false;
143
144 if ( fnd_adg_utility.is_standby_access_supported )
145 then
146 for f_rec in c1 loop
147
148 if ( f_rec.open_mode = C_OPEN_READ_ONLY and
149 f_rec.database_role= C_STANDBY_ROLE )
150 then
151 G_IS_TRUE_STANDBY := true;
152 end if;
153 end loop;
154 end if;
155
156 end;
157
158 /*==========================================================================*/
159
160 procedure set_is_primary
161 as
162 cursor c1 is select a.open_mode,a.database_role
163 from v$database a;
164 begin
165
166 G_IS_PRIMARY := false;
167
168 for f_rec in c1 loop
169
170 if ( f_rec.open_mode = C_OPEN_READ_WRITE and
171 f_rec.database_role= C_PRIMARY_ROLE )
172 then
173 G_IS_PRIMARY := true;
174 end if;
175 end loop;
176
177 end;
178
179 /*==========================================================================*/
180
181 function boolean_to_yn(p_bool boolean) return varchar2
182 as
183 begin
184
185 if ( p_bool is null )
186 then
187 return null;
188 end if;
189
190 if ( p_bool )
191 then
192 return 'Y';
193 else
194 return 'N';
195 end if;
196
197 end;
198
199 /*==========================================================================*/
200
201 function boolean_to_ynu(p_bool boolean) return varchar2
202 as
203 begin
204
205 if ( p_bool is null )
206 then
207 return 'U';
208 end if;
209
210 if ( p_bool )
211 then
212 return 'Y';
213 else
214 return 'N';
215 end if;
216
217 end;
218
219 /*==========================================================================*/
220
221 function yn_to_boolean(p_yn varchar2) return boolean
222 as
223 begin
224
225 if ( upper(p_yn) = 'Y' )
226 then
227 return true;
228 else
229 return false;
230 end if;
231
232 end;
233
234 /*==========================================================================*/
235
236 function ynu_to_boolean(p_yn varchar2) return boolean
237 as
238 begin
239
240 if ( upper(p_yn) = 'Y' )
241 then
242 return true;
243 else
244 if ( upper(p_yn) = 'N' )
245 then
246 return false;
247 else
248 return null;
249 end if;
250 end if;
251
252 end;
253
254 /*==========================================================================*/
255 /*==================== Start of concurrent program methods =================*/
256 /*==========================================================================*/
257
258 /*==========================================================================*/
259
260 function init_program_change_rec return fnd_adg_concurrent_program%rowtype
261 as
262 l_cp_rec fnd_adg_concurrent_program%rowtype;
263 begin
264
265 l_cp_rec.Application_Id := null;
266 l_cp_rec.Concurrent_Program_Id := null;
267 l_cp_rec.Supported_Executable_Type := null;
268 l_cp_rec.Has_Run_On_Primary := null;
269 l_cp_rec.Has_Run_In_Simulated_Standby := null;
270 l_cp_rec.Run_On_Standby := null;
271 l_cp_rec.No_Standby_Failures := null;
272 l_cp_rec.Max_Standby_Failures := null;
273 l_cp_rec.No_Simulated_Standby_Failures := null;
274 l_cp_rec.Max_Simulated_Standby_Failures := null;
275 l_cp_rec.always_redirect_if_valid := null;
276 l_cp_rec.use_automatic_redirection := null;
277
278 return l_cp_rec;
279
280 end;
281
282 /*==========================================================================*/
283
284 procedure update_conc_program_rec(p_cp_rec fnd_adg_concurrent_program%rowtype,
285 p_cp_chng_rec
286 fnd_adg_concurrent_program%rowtype,
287 p_util_caller boolean default false)
288 as
289 PRAGMA AUTONOMOUS_TRANSACTION;
290 l_curr_cp_rec fnd_adg_concurrent_program%rowtype;
291 begin
292
293 select a.*
294 into l_curr_cp_rec
295 from fnd_adg_concurrent_program a
296 where a.Application_Id = p_cp_rec.Application_Id
297 and a.Concurrent_Program_Id = p_cp_rec.Concurrent_Program_Id
298 for update of a.Application_Id;
299
300 if ( p_cp_chng_rec.Supported_Executable_Type is not null )
301 then
302 l_curr_cp_rec.Supported_Executable_Type :=
303 p_cp_chng_rec.Supported_Executable_Type;
304 end if;
305
306 if ( p_cp_chng_rec.Has_Run_On_Primary is not null )
307 then
308 l_curr_cp_rec.Has_Run_On_Primary := p_cp_chng_rec.Has_Run_On_Primary;
309 end if;
310
311 if ( p_cp_chng_rec.Has_Run_In_Simulated_Standby is not null )
312 then
313 l_curr_cp_rec.Has_Run_In_Simulated_Standby :=
314 p_cp_chng_rec.Has_Run_In_Simulated_Standby;
315 end if;
316
317 if ( p_cp_chng_rec.Run_On_Standby is not null )
318 then
319 if ( l_curr_cp_rec.Run_On_Standby <> p_cp_chng_rec.Run_On_Standby )
320 then
321 if ( ynu_to_boolean(l_curr_cp_rec.Run_On_Standby) is null or
322 ynu_to_boolean(l_curr_cp_rec.Run_On_Standby) or p_util_caller )
323 then
324 l_curr_cp_rec.Run_On_Standby := p_cp_chng_rec.Run_On_Standby;
325 end if;
326 end if;
327 end if;
328
329 if ( p_cp_chng_rec.No_Standby_Failures is not null )
330 then
331 l_curr_cp_rec.No_Standby_Failures := p_cp_chng_rec.No_Standby_Failures;
332 end if;
333
334 if ( p_cp_chng_rec.Max_Standby_Failures is not null )
335 then
336 l_curr_cp_rec.Max_Standby_Failures := p_cp_chng_rec.Max_Standby_Failures;
337 end if;
338
339 if ( p_cp_chng_rec.No_Simulated_Standby_Failures is not null )
340 then
341 l_curr_cp_rec.No_Simulated_Standby_Failures :=
342 p_cp_chng_rec.No_Simulated_Standby_Failures;
343 end if;
344
345 if ( p_cp_chng_rec.Max_Simulated_Standby_Failures is not null )
346 then
347 l_curr_cp_rec.Max_Simulated_Standby_Failures :=
348 p_cp_chng_rec.Max_Simulated_Standby_Failures;
349 end if;
350
351 if ( p_cp_chng_rec.always_redirect_if_valid is not null )
352 then
353 l_curr_cp_rec.always_redirect_if_valid :=
354 p_cp_chng_rec.always_redirect_if_valid;
355 end if;
356
357 if ( p_cp_chng_rec.use_automatic_redirection is not null )
358 then
359 l_curr_cp_rec.use_automatic_redirection :=
360 p_cp_chng_rec.use_automatic_redirection;
361 end if;
362
363 update fnd_adg_concurrent_program a
364 set row = l_curr_cp_rec
365 where a.Application_Id = p_cp_rec.Application_Id
366 and a.Concurrent_Program_Id = p_cp_rec.Concurrent_Program_Id;
367
368 commit;
369
370 end;
371
372 /*==========================================================================*/
373
374 function is_standalone_executable(p_cp_rec fnd_adg_concurrent_program%rowtype)
375 return boolean
376 as
377 begin
378
379 -- We currently only support standalone executables. If this
380 -- ever changes this function needs to be changed. Why? Because with
381 -- standalone we update simulation stats on logoff whereas
382 -- for embedded stats are done under the update trigger.
383 -- This only applies to simulation stats.
384
385 return true;
386
387 end;
388
389 /*==========================================================================*/
390
391 function is_conc_program_supported(p_program_application_id number,
392 p_concurrent_program_id number)
393 return boolean
394 as
395 l_Execution_Method_Code varchar2(10);
396 begin
397
398 begin
399
400 select a.Execution_Method_Code
401 into l_Execution_Method_Code
402 from fnd_concurrent_programs a
403 where a.APPLICATION_ID = p_program_application_id
404 and a.CONCURRENT_PROGRAM_ID = p_concurrent_program_id;
405
406 if ( l_Execution_Method_Code = C_REPORTWRITER )
407 then
408 return true;
409 else
410 return false;
411 end if;
412
413 exception
414 when no_data_found then
415 return null;
416 end;
417
418 end;
419
420 /*==========================================================================*/
421
422 function create_conc_program_rec(p_program_application_id number,
423 p_concurrent_program_id number)
424 return fnd_adg_concurrent_program%rowtype
425 as
426 PRAGMA AUTONOMOUS_TRANSACTION;
427 l_new_cp_rec fnd_adg_concurrent_program%rowtype;
428 l_is_supported_exe_type boolean;
429 begin
430
431 l_is_supported_exe_type :=
432 is_conc_program_supported(p_program_application_id,
433 p_concurrent_program_id);
434
435 if ( l_is_supported_exe_type is null ) -- conc. program doesn't exist!
436 then
437 l_new_cp_rec.Application_Id := null;
438 l_new_cp_rec.Concurrent_Program_Id := null;
439 commit;
440 return l_new_cp_rec;
441 end if;
442
443 l_new_cp_rec.Application_Id := p_program_application_id;
444 l_new_cp_rec.Concurrent_Program_Id := p_concurrent_program_id;
445 l_new_cp_rec.Supported_Executable_Type :=
446 boolean_to_yn(l_is_supported_exe_type);
447 l_new_cp_rec.Has_Run_On_Primary := boolean_to_yn(false);
448 l_new_cp_rec.Has_Run_In_Simulated_Standby := boolean_to_yn(false);
449 l_new_cp_rec.Run_On_Standby := boolean_to_ynu(null);
450 l_new_cp_rec.No_Standby_Failures := 0;
451 l_new_cp_rec.Max_Standby_Failures := 0;
452 l_new_cp_rec.No_Simulated_Standby_Failures := 0;
453 l_new_cp_rec.Max_Simulated_Standby_Failures := 0;
454 l_new_cp_rec.always_redirect_if_valid := boolean_to_yn(true);
455 l_new_cp_rec.use_automatic_redirection := boolean_to_yn(false);
456
457 begin
458
459 insert into fnd_adg_concurrent_program values l_new_cp_rec ;
460
461 commit;
462
463 exception
464
465 when DUP_VAL_ON_INDEX then -- somebody got there first
466
467 select a.*
468 into l_new_cp_rec
469 from fnd_adg_concurrent_program a
470 where a.Application_Id = p_program_application_id
471 and a.Concurrent_Program_Id = p_concurrent_program_id;
472
473 end;
474
475 return l_new_cp_rec;
476
477 end;
478
479 /*==========================================================================*/
480
481 function get_conc_program_rec(p_program_application_id number,
482 p_concurrent_program_id number)
483 return fnd_adg_concurrent_program%rowtype
484 as
485 l_cp_rec fnd_adg_concurrent_program%rowtype;
486 begin
487
488 begin
489
490 select a.*
491 into l_cp_rec
492 from fnd_adg_concurrent_program a
493 where a.Application_Id = p_program_application_id
494 and a.Concurrent_Program_Id = p_concurrent_program_id;
495
496 exception
497
498 when no_data_found then
499
500 l_cp_rec := create_conc_program_rec(p_program_application_id,
501 p_concurrent_program_id);
502 end;
503
504 return l_cp_rec;
505
506 end;
507
508 /*==========================================================================*/
509
510 function is_conc_program_changes(p_cp_chng_rec
511 fnd_adg_concurrent_program%rowtype)
512 return boolean
513 as
514 begin
515
516 if (
517 p_cp_chng_rec.Application_Id is not null or
518 p_cp_chng_rec.Concurrent_Program_Id is not null or
519 p_cp_chng_rec.Supported_Executable_Type is not null or
520 p_cp_chng_rec.Has_Run_On_Primary is not null or
521 p_cp_chng_rec.Has_Run_In_Simulated_Standby is not null or
522 p_cp_chng_rec.Run_On_Standby is not null or
523 p_cp_chng_rec.No_Standby_Failures is not null or
524 p_cp_chng_rec.Max_Standby_Failures is not null or
525 p_cp_chng_rec.No_Simulated_Standby_Failures is not null or
526 p_cp_chng_rec.Max_Simulated_Standby_Failures is not null or
527 p_cp_chng_rec.always_redirect_if_valid is not null or
528 p_cp_chng_rec.use_automatic_redirection is not null
529 )
530 then
531 return true;
532 else
533 return false;
534 end if;
535
536 end;
537
538 /*==========================================================================*/
539
540 procedure do_handle_request_row_update(p_cp_rec
541 fnd_adg_concurrent_program%rowtype,
542 p_cp_chng_rec in out nocopy
543 fnd_adg_concurrent_program%rowtype,
544 p_connstr1 in out nocopy varchar2,
545 p_phase_code varchar2,
546 p_status_code varchar2
547 )
548 as
549 l_request_success boolean;
550 l_standby_exists boolean;
551 l_standby_valid boolean;
552 l_simulation_connstr varchar2(255);
553 l_simulation_valid boolean;
554 l_mgr_stndby_req_class_app_id number;
555 l_mgr_stndby_req_class_id number;
556 begin
557
558 if ( p_status_code = C_STATUS_NORMAL and
559 p_phase_code = C_PHASE_COMPLETE )
560 then
561 l_request_success := true;
562 else
563 l_request_success := false;
564 end if;
565
566 -- Handle PRIMARY only functions first.
567
568 if ( l_request_success and is_primary and
569 not yn_to_boolean(p_cp_rec.Has_Run_On_Primary))
570 then
571 p_cp_chng_rec.Has_Run_On_Primary := boolean_to_yn(true);
572 end if;
573
574 if ( not G_HANDLE_REQUEST_ROW_ALL )
575 then
576 return;
577 end if;
578
579 -- Nothing to do if connstr is null;
580
581 if ( p_connstr1 is null )
582 then
583 return;
584 end if;
585
586 fnd_adg_utility.find_registered_standby
587 (p_connstr1,l_standby_exists,l_standby_valid,
588 l_mgr_stndby_req_class_app_id,l_mgr_stndby_req_class_id);
589
590 fnd_adg_utility.get_connection_data
591 (fnd_adg_utility.C_CONNECT_TO_SIMULATED_STANDBY,
592 l_simulation_valid, l_simulation_connstr);
593
594 if ( not l_standby_exists )
595 then
596 if ( l_simulation_valid and l_simulation_connstr = p_connstr1 )
597 then
598 null;
599 else
600 return;
601 end if;
602 end if;
603
604 if ( l_request_success )
605 then
606 if ( l_simulation_valid and p_connstr1 = l_simulation_connstr )
607 then
608 if ( not yn_to_boolean(p_cp_rec.Has_Run_In_Simulated_Standby) )
609 then
610 p_cp_chng_rec.Has_Run_In_Simulated_Standby := boolean_to_yn(true);
611 end if;
612
613 if ( p_cp_rec.No_Standby_Failures <= p_cp_rec.Max_Standby_Failures and
614 p_cp_rec.No_Simulated_Standby_Failures <=
615 p_cp_rec.Max_Simulated_Standby_Failures )
616 then
617
618 if ( fnd_adg_utility.is_simulated_standby_enabled and
619 fnd_adg_utility.is_auto_simulation_enabled )
620 then
621 p_cp_chng_rec.Run_On_Standby := boolean_to_ynu(true);
622 end if;
623 end if;
624 end if;
625 else
626
627 if ( l_standby_valid )
628 then
629 if ( p_cp_rec.No_Standby_Failures > p_cp_rec.Max_Standby_Failures )
630 then
631 if ( ynu_to_boolean(p_cp_rec.Run_On_Standby) is null or
632 ynu_to_boolean(p_cp_rec.Run_On_Standby) )
633 then
634 p_cp_chng_rec.Run_On_Standby := boolean_to_ynu(false);
635 end if;
636 end if;
637 else
638 if ( p_cp_rec.No_Simulated_Standby_Failures >
639 p_cp_rec.Max_Simulated_Standby_Failures )
640 then
641 if ( ynu_to_boolean(p_cp_rec.Run_On_Standby) is null or
642 ynu_to_boolean(p_cp_rec.Run_On_Standby) )
643 then
644 p_cp_chng_rec.Run_On_Standby := boolean_to_ynu(false);
645 end if;
646 end if;
647 end if;
648
649 end if;
650
651 end;
652
653 /*==========================================================================*/
654
655 procedure do_handle_request_row_insert(p_cp_rec
656 fnd_adg_concurrent_program%rowtype,
657 p_cp_chng_rec in out nocopy
658 fnd_adg_concurrent_program%rowtype,
659 p_connstr1 in out nocopy varchar2,
660 p_nodename1 in out nocopy varchar2,
661 p_request_class_application_id
662 in out nocopy number,
663 p_concurrent_request_class_id
664 in out nocopy number
665 )
666 as
667 l_mgr_stndby_req_class_app_id number;
668 l_mgr_stndby_req_class_id number;
669 l_auto_stndby_req_class_app_id number;
670 l_auto_stndby_req_class_id number;
671 l_standby_exists boolean;
672 l_standby_valid boolean;
673 l_simulation_connstr varchar2(255);
674 l_simulation_valid boolean;
675 l_manager_must_be_running boolean;
676 l_auto_valid boolean;
677 l_auto_connstr1 varchar(255);
678 l_known_adg_connection boolean;
679 l_is_standby_mgr_defined boolean;
680
681 begin
682
683 -- Must be ALL processing for INSERT.
684
685 if ( not G_HANDLE_REQUEST_ROW_ALL )
686 then
687 return;
688 end if;
689
690 l_auto_valid := false;
691
692 -- Special handling when automatic redirection is enabled.
693
694
695 if ( fnd_adg_utility.is_automatic_redirection and
696 yn_to_boolean(p_cp_rec.use_automatic_redirection ) )
697 then
698 for i in 1..fnd_adg_utility.get_max_standby_systems loop
699
700 fnd_adg_utility.get_connection_data
701 (fnd_adg_utility.C_CONNECT_PRIMARY_TO_STANDBY,
702 l_auto_valid,l_auto_connstr1,i);
703
704 if ( l_auto_valid )
705 then
706 fnd_adg_utility.get_standby_cm_class(i,l_auto_stndby_req_class_app_id,
707 l_auto_stndby_req_class_id);
708 exit;
709 end if;
710 end loop;
711 end if;
712
713 -- Nothing to do if connstr is null and no automatic redirection;
714
715 if ( p_connstr1 is null and not l_auto_valid )
716 then
717 return;
718 end if;
719
720 -- Connstr could be standby or simulation
721
722 fnd_adg_utility.find_registered_standby
723 (p_connstr1,l_standby_exists,l_standby_valid,
724 l_mgr_stndby_req_class_app_id,l_mgr_stndby_req_class_id);
725
726 fnd_adg_utility.get_connection_data
727 (fnd_adg_utility.C_CONNECT_TO_SIMULATED_STANDBY,
728 l_simulation_valid,l_simulation_connstr);
729
730 -- If supplied connstr exists then we use it and ignore
731 -- automatic redirection even if it turns out to be invalid. After
732 -- all user supplied it.
733
734 if ( l_standby_exists )
735 then
736 l_auto_valid := false;
737 end if;
738
739 -- Now determine whether supplied connect string is known by
740 -- ADG. At the same time set the on-validation return string - i.e.
741 -- if we're using automatic redirection but the report is not a
742 -- candidate we need to return string as is - it could be an instance
743 -- connect string.
744
745 l_known_adg_connection := false;
746
747 if ( p_connstr1 is not null )
748 then
749 if ( l_standby_exists )
750 then
751 -- Doesn't matter whether valid or not we always return null
752 -- except for the final switch.
753
754 l_known_adg_connection := true;
755 else
756 if ( l_simulation_connstr is not null and
757 l_simulation_connstr = p_connstr1 )
758 then
759 l_known_adg_connection := true;
760 end if;
761 end if;
762 end if;
763
764 -- If connstr not standby or simulation and not
765 -- auto redirection enabled then nothing to do with us.
766
767 if ( not l_auto_valid )
768 then
769 if ( l_known_adg_connection )
770 then
771 if ( l_standby_exists )
772 then
773 if ( not l_standby_valid )
774 then
775 p_connstr1 := null;
776 return;
777 end if;
778 else
779 if ( not l_simulation_valid )
780 then
781 p_connstr1 := null;
782 return;
783 end if;
784 end if;
785 else
786 return;
787 end if;
788 end if;
789
790 -- Only allow supported program types.
791
792 if ( not yn_to_boolean(p_cp_rec.Supported_Executable_Type) )
793 then
794 if ( l_known_adg_connection )
795 then
796 p_connstr1 := null;
797 end if;
798
799 return;
800 end if;
801
802 -- Need to first run on primary before being a standby candidate.
803
804 if ( not yn_to_boolean(p_cp_rec.Has_Run_On_Primary) )
805 then
806 if ( l_known_adg_connection )
807 then
808 p_connstr1 := null;
809 end if;
810
811 return;
812 end if;
813
814 -- If connect string is known and not standby then must be simulated
815 -- standby.
816
817 if ( l_known_adg_connection and not l_standby_exists )
818 then
819 if ( not l_auto_valid ) -- use simulation only if auto-redirect not in effect
820 then
821 if ( l_simulation_valid )
822 then
823 p_connstr1 := l_simulation_connstr;
824 else
825 p_connstr1 := null;
826 end if;
827
828 return;
829 end if;
830 end if;
831
832 -- Need to have run on simulated standby before real standby.
833
834 if ( not yn_to_boolean(p_cp_rec.Has_Run_In_Simulated_Standby) )
835 then
836 -- If auto simulation enabled and valid, then use simulation
837 -- connect string.
838
839 -- This will redirect for null and instance strings. It's not clear
840 -- we really want this happen but we can just disable auto-simulation.
841
842 if ( fnd_adg_utility.is_simulated_standby_enabled and
843 fnd_adg_utility.is_auto_simulation_enabled and l_simulation_valid )
844 then
845 p_connstr1 := l_simulation_connstr;
846 return;
847 end if;
848
849 if ( l_known_adg_connection )
850 then
851 p_connstr1 := null;
852 end if;
853
854 return;
855 end if;
856
857 -- If Run_On_Standby not set then return.
858
859 if ( ynu_to_boolean(p_cp_rec.Run_On_Standby) is null or
860 not ynu_to_boolean(p_cp_rec.Run_On_Standby) )
861 then
862 if ( l_known_adg_connection )
863 then
864 p_connstr1 := null;
865 end if;
866
867 return;
868 end if;
869
870 -- Ready to go - make sure manager is running for class id.
871
872 -- Does manager have to be running - can be put in queue for later.
873
874 if ( fnd_adg_utility.is_enable_redirect_if_valid and
875 yn_to_boolean(p_cp_rec.always_redirect_if_valid) )
876 then
877 l_manager_must_be_running := false;
878 else
879 l_manager_must_be_running := true;
880 end if;
881
882 if ( not l_auto_valid )
883 then
884 l_is_standby_mgr_defined :=
885 fnd_adg_utility.is_standby_manager_defined
886 (l_mgr_stndby_req_class_app_id,
887 l_mgr_stndby_req_class_id,
888 l_manager_must_be_running);
889 else
890 l_is_standby_mgr_defined :=
891 fnd_adg_utility.is_standby_manager_defined
892 (l_auto_stndby_req_class_app_id,
893 l_auto_stndby_req_class_id,
894 l_manager_must_be_running);
895 end if;
896
897 if ( l_is_standby_mgr_defined )
898 then
899
900 -- Redirect to ADG manager.
901
902 -- Auto-redirection will not be valid if connstr was standby
903
904 if ( not l_auto_valid )
905 then
906
907 p_request_class_application_id := l_mgr_stndby_req_class_app_id;
908 p_concurrent_request_class_id := l_mgr_stndby_req_class_id;
909
910 else
911
912 p_connstr1 := l_auto_connstr1;
913 p_request_class_application_id := l_auto_stndby_req_class_app_id;
914 p_concurrent_request_class_id := l_auto_stndby_req_class_id;
915
916 end if;
917
918 if ( p_nodename1 is not null )
919 then
920 p_nodename1 := null; -- use class not node for standby control.
921 end if;
922
923 return;
924
925 else
926 if ( l_known_adg_connection )
927 then
928 p_connstr1 := null;
929 end if;
930
931 return;
932 end if;
933
934 end;
935
936 /*==========================================================================*/
937
938 -- Private method - no access code check
939
940 procedure do_handle_concurrent_program
941 (p_application_id number,
942 p_concurrent_program_id number,
943 p_has_run_on_primary boolean default null,
944 p_has_run_on_simulated_standby boolean default null,
945 p_run_on_standby boolean default null,
946 p_no_standby_failures number default null,
947 p_max_standby_failures number default null,
948 p_no_simulated_stdby_failures number default null,
949 p_max_simulated_stdby_failures number default null,
950 p_always_redirect_if_valid boolean default null,
951 p_use_automatic_redirection boolean default null
952 )
953 as
954 l_cp_chng_rec fnd_adg_concurrent_program%rowtype;
955 l_cp_rec fnd_adg_concurrent_program%rowtype;
956 begin
957
958 l_cp_rec := get_conc_program_rec(p_application_id,
959 p_concurrent_program_id);
960
961 -- Does concurrent program exist
962
963 if ( l_cp_rec.Application_Id is null and
964 l_cp_rec.Concurrent_Program_Id is null )
965 then
966 fnd_adg_exception.raise_error(
967 fnd_adg_exception.C_SUPERR_INVALID_CONC_PROGRAM);
968 end if;
969
970 l_cp_chng_rec := init_program_change_rec;
971
972 l_cp_chng_rec.Has_Run_On_Primary := boolean_to_yn(p_has_run_on_primary);
973 l_cp_chng_rec.Has_Run_In_Simulated_Standby :=
974 boolean_to_yn(p_has_run_on_simulated_standby);
975
976 if ( p_run_on_standby is not null )
977 then
978 l_cp_chng_rec.Run_On_Standby := boolean_to_ynu(p_run_on_standby);
979 end if;
980
981 l_cp_chng_rec.No_Standby_Failures := p_no_standby_failures;
982 l_cp_chng_rec.Max_Standby_Failures := p_max_standby_failures;
983 l_cp_chng_rec.No_Simulated_Standby_Failures := p_no_simulated_stdby_failures;
984 l_cp_chng_rec.Max_Simulated_Standby_Failures:= p_max_simulated_stdby_failures;
985
986 l_cp_chng_rec.always_redirect_if_valid
987 := boolean_to_yn(p_always_redirect_if_valid);
988
989 l_cp_chng_rec.use_automatic_redirection
990 := boolean_to_yn(p_use_automatic_redirection);
991
992 if ( is_conc_program_changes(l_cp_chng_rec) )
993 then
994 update_conc_program_rec(l_cp_rec,l_cp_chng_rec,true);
995 end if;
996
997 end;
998
999 /*==========================================================================*/
1000 /*==================== Start of public methods =============================*/
1001 /*==========================================================================*/
1002
1003 /*==========================================================================*/
1004
1005 function is_standby return boolean
1006 as
1007 l_err number;
1008 l_msg varchar2(255);
1009
1010 begin
1011
1012 if ( G_IS_STANDBY is null )
1013 then
1014 set_is_standby;
1015
1016 -- check that we're using the right primary.
1017
1018 if ( G_IS_STANDBY )
1019 then
1020
1021 -- validate will call back into is_standby. That's ok as G_IS_STANDBY
1022 -- will be not null and this code path will not be reached.
1023 -- Otherwise we'd recurse into oblivion...
1024
1025 fnd_adg_manage.validate_standby_to_primary(l_err,l_msg,true);
1026
1027 if ( l_err <> 0 )
1028 then
1029 G_IS_STANDBY := false;
1030
1031 fnd_adg_exception.raise_error(
1032 fnd_adg_exception.C_SUPERR_VALIDATE_PRIMARY,l_msg);
1033 end if;
1034
1035 fnd_adg_manage.handle_rpc_debug(true); -- enable debug trace.
1036
1037 end if;
1038 end if;
1039
1040 return G_IS_STANDBY;
1041
1042 end;
1043
1044 /*==========================================================================*/
1045
1046 function is_true_standby return boolean
1047 as
1048 begin
1049
1050 if ( G_IS_TRUE_STANDBY is null )
1051 then
1052 set_is_true_standby;
1053 end if;
1054
1055 return G_IS_TRUE_STANDBY;
1056
1057 end;
1058
1059 /*==========================================================================*/
1060
1061 function is_rpc_from_standby return boolean
1062 as
1063 begin
1064
1065 return fnd_adg_manage.is_session_slave_to_standby;
1066
1067 end;
1068
1069 /*==========================================================================*/
1070
1071 function is_primary return boolean
1072 as
1073 begin
1074
1075 if ( G_IS_PRIMARY is null )
1076 then
1077 set_is_primary;
1078 end if;
1079
1080 return G_IS_PRIMARY;
1081
1082 end;
1083
1084 /*==========================================================================*/
1085
1086 procedure log_unhandled_exception(p_location varchar2,p_sqlerr varchar2)
1087 as
1088 begin
1089
1090 dbms_system.ksdwrt(1,'ADGEBS: Unhandled Exception : ' ||p_location||
1091 ' SQLERRM='||p_sqlerr);
1092
1093 dbms_system.ksdwrt(1,'ADGEBS: Backtrace : ' ||p_location||LF||
1094 dbms_utility.format_error_backtrace);
1095
1096 end;
1097
1098 /*==========================================================================*/
1099
1100 function is_connstr_registered(p_connstr varchar2,
1101 p_check_valid boolean default false,
1102 p_check_available boolean default false)
1103 return boolean
1104 as
1105 begin
1106
1107 return fnd_adg_utility.is_connection_registered(p_connstr,p_check_valid,
1108 p_check_available);
1109
1110 end;
1111
1112 /*==========================================================================*/
1113
1114 function is_connstr_registered(p_connstr varchar2,
1115 p_check_valid number,
1116 p_check_available number)
1117 return number
1118 as
1119 l_bool_check_valid boolean := false;
1120 l_bool_check_available boolean := false;
1121 begin
1122
1123 if ( p_check_valid = 1 )
1124 then
1125 l_bool_check_valid := true;
1126 end if;
1127
1128 if ( p_check_available = 1 )
1129 then
1130 l_bool_check_available := true;
1131 end if;
1132
1133 if ( fnd_adg_utility.is_connection_registered(p_connstr,
1134 l_bool_check_valid,
1135 l_bool_check_available) )
1136 then
1137 return 1;
1138 else
1139 return 0;
1140 end if;
1141
1142 end;
1143
1144 /*==========================================================================*/
1145
1146 procedure handle_request_row_change(p_is_inserting boolean,
1147 p_program_application_id number,
1148 p_concurrent_program_id number,
1149 p_connstr1 in out nocopy varchar2,
1150 p_nodename1 in out nocopy varchar2,
1151 p_request_class_application_id
1152 in out nocopy number,
1153 p_concurrent_request_class_id
1154 in out nocopy number,
1155 p_phase_code varchar2,
1156 p_status_code varchar2
1157 )
1158 as
1159 l_cp_chng_rec fnd_adg_concurrent_program%rowtype;
1160 l_cp_rec fnd_adg_concurrent_program%rowtype;
1161 l_cache_state boolean := null;
1162 begin
1163
1164 -- Use the control cache to avoid repeated reads.
1165
1166 l_cache_state := fnd_adg_utility.enable_control_cache;
1167
1168 -- Always check state
1169
1170 set_handle_request_row_change;
1171
1172 if ( G_HANDLE_REQUEST_ROW_ALL or G_HANDLE_REQUEST_ROW_PRIMARY )
1173 then
1174 null;
1175 else
1176 fnd_adg_utility.disable_control_cache(l_cache_state);
1177 return;
1178 end if;
1179
1180 -- If someone tries to insert nulls we just ignore the row as
1181 -- cols are defined as not null!
1182
1183 if ( p_program_application_id is null or
1184 p_concurrent_program_id is null )
1185 then
1186 fnd_adg_utility.disable_control_cache(l_cache_state);
1187 return;
1188 end if;
1189
1190 l_cp_rec := get_conc_program_rec(p_program_application_id,
1191 p_concurrent_program_id);
1192
1193 if ( l_cp_rec.Application_Id is null and
1194 l_cp_rec.Concurrent_Program_Id is null ) -- concurrent program doesn't
1195 -- exist - can't happen!
1196 then
1197 fnd_adg_utility.disable_control_cache(l_cache_state);
1198 return;
1199 end if;
1200
1201 -- Now the real processing starts.
1202
1203 l_cp_chng_rec := init_program_change_rec;
1204
1205 if ( p_is_inserting )
1206 then
1207 do_handle_request_row_insert(l_cp_rec,l_cp_chng_rec,
1208 p_connstr1, p_nodename1,
1209 p_request_class_application_id,
1210 p_concurrent_request_class_id);
1211 else
1212
1213 -- If embedded then we need to calculate simulation errors now.
1214 -- Currently we only support standalone so this code path is
1215 -- never executed.
1216
1217 if ( not is_standalone_executable(l_cp_rec) )
1218 then
1219 fnd_adg_utility.process_adg_violations(false,
1220 p_program_application_id,
1221 p_concurrent_program_id);
1222
1223 l_cp_rec := get_conc_program_rec(p_program_application_id,
1224 p_concurrent_program_id);
1225 end if;
1226
1227 do_handle_request_row_update(l_cp_rec,l_cp_chng_rec,
1228 p_connstr1,p_phase_code,p_status_code);
1229 end if;
1230
1231 if ( is_conc_program_changes(l_cp_chng_rec) )
1232 then
1233 update_conc_program_rec(l_cp_rec,l_cp_chng_rec);
1234 end if;
1235
1236 fnd_adg_utility.disable_control_cache(l_cache_state);
1237
1238 exception
1239 when others then
1240 fnd_adg_utility.disable_control_cache(l_cache_state);
1241 raise;
1242
1243 end;
1244
1245 /*==========================================================================*/
1246
1247 procedure handle_concurrent_program
1248 (p_code number,
1249 p_application_id number,
1250 p_concurrent_program_id number,
1251 p_has_run_on_primary boolean default null,
1252 p_has_run_on_simulated_standby boolean default null,
1253 p_run_on_standby boolean default null,
1254 p_no_standby_failures number default null,
1255 p_max_standby_failures number default null,
1256 p_no_simulated_stdby_failures number default null,
1257 p_max_simulated_stdby_failures number default null,
1258 p_always_redirect_if_valid boolean default null,
1259 p_use_automatic_redirection boolean default null
1260 )
1261 as
1262 l_access_code number;
1263 l_cp_chng_rec fnd_adg_concurrent_program%rowtype;
1264 l_cp_rec fnd_adg_concurrent_program%rowtype;
1265 begin
1266
1267 l_access_code := fnd_adg_utility.get_program_access_code;
1268
1269 if ( p_code is null or l_access_code is null or p_code <> l_access_code )
1270 then
1271 fnd_adg_exception.raise_error(
1272 fnd_adg_exception.C_SUPERR_PROGRAM_ACCESS_CODE);
1273 end if;
1274
1275 do_handle_concurrent_program(p_application_id ,
1276 p_concurrent_program_id ,
1277 p_has_run_on_primary ,
1278 p_has_run_on_simulated_standby,
1279 p_run_on_standby ,
1280 p_no_standby_failures ,
1281 p_max_standby_failures ,
1282 p_no_simulated_stdby_failures ,
1283 p_max_simulated_stdby_failures,
1284 p_always_redirect_if_valid,
1285 p_use_automatic_redirection
1286 );
1287
1288 end;
1289
1290 /*==========================================================================*/
1291
1292 procedure handle_standby_error ( p_program_application_id number,
1293 p_concurrent_program_id number,
1294 p_simulation boolean,
1295 p_logoff boolean,
1296 p_error_count number)
1297 as
1298 l_cp_rec fnd_adg_concurrent_program%rowtype;
1299 l_run_on_standby boolean;
1300 l_No_Standby_Failures number;
1301 l_No_Simulated_Failures number;
1302 begin
1303
1304 if ( p_program_application_id is null or p_concurrent_program_id is null or
1305 p_simulation is null or p_error_count is null or
1306 p_error_count <= 0 or p_logoff is null )
1307 then
1308 return;
1309 end if;
1310
1311 -- All the error checking has already taken place so
1312 -- just update the run flag.
1313
1314 l_run_on_standby := null;
1315 l_No_Standby_Failures := null;
1316 l_No_Simulated_Failures := null;
1317
1318 l_cp_rec := get_conc_program_rec(p_program_application_id,
1319 p_concurrent_program_id);
1320
1321 if ( not p_simulation )
1322 then
1323 l_No_Standby_Failures := l_cp_rec.No_Standby_Failures + p_error_count;
1324
1325 if ( l_No_Standby_Failures >= l_cp_rec.Max_Standby_Failures )
1326 then
1327 l_run_on_standby := false;
1328 end if;
1329 else
1330 if ( ( is_standalone_executable(l_cp_rec) and p_logoff ) or
1331 ( not is_standalone_executable(l_cp_rec) and not p_logoff ) )
1332 then
1333 l_No_Simulated_Failures :=
1334 l_cp_rec.No_Simulated_Standby_Failures + p_error_count;
1335 end if;
1336 end if;
1337
1338 do_handle_concurrent_program
1339 (
1340 p_application_id => p_program_application_id,
1341 p_concurrent_program_id=> p_concurrent_program_id,
1342 p_run_on_standby => l_run_on_standby,
1343 p_No_Standby_Failures => l_No_Standby_Failures,
1344 p_no_simulated_stdby_failures =>
1345 l_No_Simulated_Failures
1346 );
1347
1348 exception
1349 when others then
1350 null; -- called from error handler so nothing we can do!
1351
1352 end;
1353
1354 /*==========================================================================*/
1355
1356 -- This entry point is only valid outside of trigger code
1357 -- due to mutating errors.
1358
1359 procedure handle_standby_error ( p_request_id number,
1360 p_simulation boolean,
1361 p_logoff boolean,
1362 p_error_count number)
1363 as
1364 cursor c1 is select R.Program_APPLICATION_ID,R.CONCURRENT_PROGRAM_ID
1365 from FND_CONCURRENT_REQUESTS r
1366 where R.request_id = p_request_id;
1367 begin
1368
1369 if ( p_request_id is null )
1370 then
1371 return;
1372 end if;
1373
1374 for f_rec in c1 loop
1375
1376 handle_standby_error(f_rec.Program_APPLICATION_ID,
1377 f_rec.CONCURRENT_PROGRAM_ID,
1378 p_simulation,
1379 p_logoff,
1380 p_error_count);
1381
1382 exit;
1383
1384 end loop;
1385
1386 exception
1387 when others then
1388 null; -- called from error handler so nothing we can do!
1389
1390 end;
1391
1392 /*==========================================================================*/
1393
1394 begin
1395 null;
1396 end fnd_adg_support;