Wednesday, June 30, 2010

EBS PL/SQL multithreading example

Here are some good examples of multi-threading Concurrent Program from within a PL/SQL Program.

Example1:
http://sbllc3.solutionbeacon.net/pls/a159vis2/fndgfm/fnd_help.get/US@PSA_US/fnd/@concglob

OR

Example2:

PROCEDURE CONC_MULTI_THREAD_PRG (
Errbuf OUT NOCOPY VARCHAR2
,Retcode OUT NOCOPY VARCHAR2
)
IS
ln_thread_count NUMBER;
ls_smtp_server VARCHAR2(240);
ln_smtp_server_port PLS_INTEGER;
ls_from_name VARCHAR2(240);
ls_subject VARCHAR2(240);
ls_message VARCHAR2(240);
ls_message_html VARCHAR2(240);
ln_conc_request_id NUMBER := NULL;
ls_req_data VARCHAR2(240);
ln_request_id NUMBER; -- parent request id
cnt_warnings INTEGER := 0;
cnt_errors INTEGER := 0;
request_status BOOLEAN;
BEGIN
ls_req_data := fnd_conc_global.request_data;
ln_request_id := fnd_global.conc_request_id;

IF ls_req_data IS NOT NULL THEN
put_log_line( ' Back at beginning after spawing ' ls_req_data ' threads.');
ln_thread_count := ls_req_data;

IF ln_thread_count > 0 THEN
put_log_line ( 'Checking child threads...');

-- Check all child requests to see how they finished...
FOR child_request_rec IN (SELECT request_id, status_code
FROM fnd_concurrent_requests
WHERE parent_request_id = ln_request_id)
LOOP
check_child_request(child_request_rec.request_id);
IF ( child_request_rec.status_code = 'G' OR child_request_rec.status_code = 'X'
OR child_request_rec.status_code ='D' OR child_request_rec.status_code ='T' ) THEN
cnt_warnings := cnt_warnings + 1;
ELSIF ( child_request_rec.status_code = 'E' ) THEN
cnt_errors := cnt_errors + 1;
END IF;
END LOOP; -- FOR child_request_rec

IF cnt_errors > 0 THEN
put_log_line( 'Setting completion status to ERROR.');
request_status := fnd_concurrent.set_completion_status('ERROR', '');
ELSIF cnt_warnings > 0 THEN
put_log_line( 'Setting completion status to WARNING.');
request_status := fnd_concurrent.set_completion_status('WARNING', '');
ELSE
put_log_line( 'Setting completion status to NORMAL.');
request_status := fnd_concurrent.set_completion_status('NORMAL', '');
END IF;
END IF;

RETURN; -- end of parent
END IF;

get_translations('AR_EBL_EMAIL_CONFIG','RESEND',ls_smtp_server, ln_smtp_server_port, ls_from_name, ls_subject, ls_message, ls_message_html);
get_translation('AR_EBL_CONFIG','TRANSMIT_EMAIL','N_THREADS',ln_thread_count);

put_log_line('spawning ' ln_thread_count ' thread(s)');

FOR i IN 1..ln_thread_count LOOP
put_log_line('thread: ' i);
-- TRANSMIT_EMAIL_C(Errbuf,Retcode, i, ln_thread_count, ls_smtp_server, ln_smtp_server_port, ls_from_name);

n_conc_request_id :=
FND_REQUEST.submit_request
( application => 'XXFIN' -- application short name
,program => 'XX_AR_EBL_TRANSMIT_EMAIL_C' -- concurrent program name
,sub_request => TRUE -- is this a sub-request?
,argument1 => i -- thread_id
,argument2 => ln_thread_count
,argument3 => ls_smtp_server
,argument4 => ln_smtp_server_port
,argument5 => ls_from_name);

-- ===========================================================================
-- if request was successful
-- ===========================================================================
IF (n_conc_request_id > 0) THEN
-- ===========================================================================
-- if a child request, then update it for concurrent mgr to process
-- ===========================================================================
/* -- Instead of doing the following Update, use FND_CONC_GLOBAL.SET_REQ_GLOBALS(conc_status => 'PAUSED', request_data => to_char(ln_thread_count)) -- See below
-- This program will then restart when the child programs are done, so if fnd_conc_global.request_data is NOT NULL at start of proc, check child statuses & end.
-- If either this Update, or the set_req_globals approach, is not done, the child programs will hang in Invalid, No Manager status.

UPDATE fnd_concurrent_requests
SET phase_code = 'P',
status_code = 'I'
WHERE request_id = n_conc_request_id;
*/
-- ===========================================================================
-- must commit work so that the concurrent manager polls the request
-- ===========================================================================
COMMIT;

put_log_line( ' Concurrent Request ID: ' n_conc_request_id '.' );

-- ===========================================================================
-- else errors have occured for request
-- ===========================================================================
ELSE
-- ===========================================================================
-- retrieve and raise any errors
-- ===========================================================================
FND_MESSAGE.raise_error;
END IF;

END LOOP;

FND_CONC_GLOBAL.SET_REQ_GLOBALS(conc_status => 'PAUSED', request_data => to_char(ln_thread_count));

END CONC_MULTI_THREAD_PRG;