1 PACKAGE BODY FND_OAM_DSCRAM_TASKS_PKG as
2 /* $Header: AFOAMDSTASKB.pls 120.4 2006/05/04 15:16 ilawler noship $ */
3
4 ----------------------------------------
5 -- Private Body Constants
6 ----------------------------------------
7 PKG_NAME CONSTANT VARCHAR2(20) := 'DSCRAM_TASKS_PKG.';
8
9 ----------------------------------------
10 -- Private Body Variables
11 ----------------------------------------
12 -- Includes a non-authoritative check that the task has valid units with worker spots to keep
13 -- from constantly assigning workers to full tasks before open ones. Unit will verify
14 -- during its assign that the available unit is valid and in phase. Since work cannot be created
15 -- during execution, this optimizes fetching without skipping work since we override the check when
16 -- no workers are assigned.
17 CURSOR B_TASKS
18 IS
19 SELECT /*+ FIRST_ROWS(1) */ T.task_id, T.task_status
20 FROM fnd_oam_dscram_tasks T
21 WHERE T.bundle_id = FND_OAM_DSCRAM_BUNDLES_PKG.GET_BUNDLE_ID
22 AND T.task_status in (FND_OAM_DSCRAM_UTILS_PKG.G_STATUS_UNPROCESSED,
23 FND_OAM_DSCRAM_UTILS_PKG.G_STATUS_PROCESSING,
24 FND_OAM_DSCRAM_UTILS_PKG.G_STATUS_RESTARTABLE)
25 AND (EXISTS (SELECT unit_id
26 FROM fnd_oam_dscram_units U
27 WHERE U.task_id = T.task_id
28 AND U.unit_status IN (FND_OAM_DSCRAM_UTILS_PKG.G_STATUS_UNPROCESSED,
29 FND_OAM_DSCRAM_UTILS_PKG.G_STATUS_PROCESSING,
30 FND_OAM_DSCRAM_UTILS_PKG.G_STATUS_RESTARTABLE)
31 AND U.concurrent_group_unit_id IS NULL
32 AND (U.actual_workers_allowed IS NULL OR U.actual_workers_allowed > U.workers_assigned)) OR
33 T.workers_assigned = 0)
34 ORDER BY priority ASC, weight DESC;
35
36 --package cache of currently executing task
37 TYPE b_task_cache_type IS RECORD
38 (
39 initialized BOOLEAN := FALSE,
40 task_id NUMBER := NULL,
41 last_validated DATE := NULL,
42 last_validation_ret_sts VARCHAR2(6) := NULL
43 );
44 b_task_info b_task_cache_type;
45
46 --not part of state because stored before assign
47 b_last_fetched_task_id NUMBER(15) := NULL;
48
49 ----------------------------------------
50 -- Public/Private Procedures/Functions
51 ----------------------------------------
52
53 -- Public
54 FUNCTION GET_TASK_ID
55 RETURN NUMBER
56 IS
57 BEGIN
58 IF NOT b_task_info.initialized THEN
59 RAISE NO_DATA_FOUND;
60 END IF;
61
62 RETURN b_task_info.task_id;
63 END;
64
65 -- Public
66 -- Return Statuses:
67 -- SUCCESS, ERROR, ERROR_UNEXP, EMPTY
68 PROCEDURE FETCH_NEXT_TASK(p_requery IN BOOLEAN,
69 x_task_id OUT NOCOPY NUMBER,
70 x_return_status OUT NOCOPY VARCHAR2,
71 x_return_msg OUT NOCOPY VARCHAR2)
72 IS
73 l_ctxt VARCHAR2(60) := PKG_NAME||'FETCH_NEXT_TASK';
74
75 l_task_id NUMBER(15);
76 l_status VARCHAR2(30);
77 BEGIN
78 fnd_oam_debug.log(2, l_ctxt, 'ENTER');
79 x_return_status := FND_API.G_RET_STS_ERROR;
80 x_return_msg := '';
81
82 --handle closing/opening the cursor as necessary depending on p_requery
83 IF p_requery OR
84 NOT B_TASKS%ISOPEN THEN
85 --reset the last vars when doing a requery
86 b_last_fetched_task_id := NULL;
87
88 IF p_requery AND
89 B_TASKS%ISOPEN THEN
90 CLOSE B_TASKS;
91 END IF;
92 OPEN B_TASKS;
93 END IF;
94
95 --FETCH the next row
96 FETCH B_TASKS INTO l_task_id, l_status;
97
98 -- no rows is an empty
99 IF B_TASKS%NOTFOUND THEN
100 fnd_oam_debug.log(1, l_ctxt, 'B_TASKS empty');
101 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
102 x_return_status := FND_OAM_DSCRAM_UTILS_PKG.G_RET_STS_EMPTY;
103 CLOSE B_TASKS;
104 RETURN;
105 END IF;
106
107 --cache the last task fetched to allow a quick validation later
108 fnd_oam_debug.log(1, l_ctxt, 'Task ID(Status): '||l_task_id||'('||l_status||')');
109 x_task_id := l_task_id;
110 b_last_fetched_task_id := l_task_id;
111
112 --success
113 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
114 x_return_status := FND_API.G_RET_STS_SUCCESS;
115 EXCEPTION
116 WHEN OTHERS THEN
117 IF B_TASKS%ISOPEN THEN
118 CLOSE B_TASKS;
119 END IF;
120 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
121 x_return_msg := 'Unhandled Exception: (Code('||SQLCODE||'), Message("'||SQLERRM||'"))';
122 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
123 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
124 END;
125
126 -- Private
127 -- Called by execute_task before assigning the worker to sanity check
128 -- the input args.
129 -- Return Statuses:
130 -- SUCCESS, ERROR, ERROR_UNEXP
131 -- -Converted- : SKIP, PROCESSED, STOPPED, ERROR_FATAL, ERROR_UNKNOWN
132 FUNCTION VALIDATE_START_EXECUTION(p_task_id IN NUMBER,
133 x_return_status OUT NOCOPY VARCHAR2,
134 x_return_msg OUT NOCOPY VARCHAR2)
135 RETURN BOOLEAN
136 IS
137 l_ctxt VARCHAR2(60) := PKG_NAME||'VALIDATE_START_EXECUTION';
138
139 l_status VARCHAR2(30);
140
141 l_return_status VARCHAR2(6);
142 l_return_msg VARCHAR2(2048);
143
144 CURSOR C1
145 IS
146 SELECT task_status
147 FROM fnd_oam_dscram_tasks
148 WHERE task_id = p_task_id;
149 BEGIN
150 fnd_oam_debug.log(2, l_ctxt, 'ENTER');
151 x_return_status := FND_API.G_RET_STS_ERROR;
152 x_return_msg := '';
153
154 -- automatically valid if task_id same as last fetched, if status has changed
155 -- then assign will catch it.
156 IF p_task_id = b_last_fetched_task_id THEN
157 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
158 x_return_status := FND_API.G_RET_STS_SUCCESS;
159 RETURN TRUE;
160 END IF;
161
162 --fetch necessary task attributes
163 OPEN C1;
164 FETCH C1 INTO l_status;
165 IF C1%NOTFOUND THEN
166 x_return_msg := 'Invalid task_id: ('||p_task_id||')';
167 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
168 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
169 RETURN FALSE;
170 END IF;
171 CLOSE C1;
172
173 --make sure the task has been marked as started by the controller
174 IF NOT FND_OAM_DSCRAM_UTILS_PKG.STATUS_IS_EXECUTABLE(l_status) THEN
175 -- report the true status of the task to execute to pass on to execute's caller
176 x_return_status := FND_OAM_DSCRAM_UTILS_PKG.CONV_VALIDATE_START_STS_TO_RET(l_status);
177 IF FND_OAM_DSCRAM_UTILS_PKG.RET_STS_IS_ERROR(x_return_status) THEN
178 x_return_msg := 'Invalid task status('||l_status||')';
179 fnd_oam_debug.log(1, l_ctxt, x_return_msg);
180 END IF;
181 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
182 RETURN FALSE;
183 END IF;
184
185 --success
186 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
187 x_return_status := FND_API.G_RET_STS_SUCCESS;
188 RETURN TRUE;
189 EXCEPTION
190 WHEN OTHERS THEN
191 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
192 x_return_msg := 'Unhandled Exception: (Code('||SQLCODE||'), Message("'||SQLERRM||'"))';
193 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
194 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
195 RETURN FALSE;
196 END;
197
198 -- Public
199 -- Return Statuses:
200 -- SUCCESS, ERROR, ERROR_UNEXP, STOPPED
201 -- -Converted- : PROCESSED, STOPPED, ERROR_FATAL, ERROR_UNKNOWN
202 FUNCTION VALIDATE_CONTINUED_EXECUTION(p_force_query IN BOOLEAN,
203 p_recurse IN BOOLEAN,
204 x_return_status OUT NOCOPY VARCHAR2,
205 x_return_msg OUT NOCOPY VARCHAR2)
206 RETURN BOOLEAN
207 IS
208 l_ctxt VARCHAR2(60) := PKG_NAME||'VALIDATE_CONTINUED_EXECUTION';
209
210 l_status VARCHAR2(30) := NULL;
211 l_return_status VARCHAR2(6);
212 l_return_msg VARCHAR2(2048);
213
214 CURSOR C1
215 IS
216 SELECT task_status
217 FROM fnd_oam_dscram_tasks
218 WHERE task_id = b_task_info.task_id;
219 BEGIN
220 x_return_status := FND_API.G_RET_STS_ERROR;
221 x_return_msg := '';
222
223 -- make sure the state's initialized
224 IF NOT b_task_info.initialized THEN
225 RAISE NO_DATA_FOUND;
226 END IF;
227
228 -- check if we should do work or if we can presume the cached status
229 IF (p_force_query OR
230 FND_OAM_DSCRAM_UTILS_PKG.VALIDATION_DUE(b_task_info.last_validated)) THEN
231
232 fnd_oam_debug.log(1, l_ctxt, '>RE-QUERYING<');
233
234 -- re-init the cached fields to allow easy exit
235 b_task_info.last_validation_ret_sts := x_return_status;
236 b_task_info.last_validated := SYSDATE;
237
238 --otherwise, fetch necessary run attributes and evaluate
239 OPEN C1;
240 FETCH C1 INTO l_status;
241 IF C1%NOTFOUND THEN
242 --shouldn't happen since we're using the cache
243 x_return_msg := 'Invalid cached task_id: '||b_task_info.task_id;
244 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
245 RETURN FALSE;
246 END IF;
247 CLOSE C1;
248
249 --make sure the task has been marked as processing
250 IF NOT FND_OAM_DSCRAM_UTILS_PKG.STATUS_IS_PROCESSING(l_status) THEN
251 x_return_status := FND_OAM_DSCRAM_UTILS_PKG.CONV_VALIDATE_CONT_STS_TO_RET(l_status);
252 b_task_info.last_validation_ret_sts := x_return_status;
253 IF x_return_status <> FND_OAM_DSCRAM_UTILS_PKG.G_RET_STS_PROCESSED THEN
254 x_return_msg := 'Invalid task status('||l_status||')';
255 fnd_oam_debug.log(1, l_ctxt, x_return_msg);
256 END IF;
257 RETURN FALSE;
258 END IF;
259 x_return_status := FND_API.G_RET_STS_SUCCESS;
260 ELSE
261 x_return_status := b_task_info.last_validation_ret_sts;
262 END IF;
263
264 -- make a recursive call to the bundle if required
265 IF p_recurse THEN
266 IF NOT FND_OAM_DSCRAM_BUNDLES_PKG.VALIDATE_CONTINUED_EXECUTION(p_force_query,
267 TRUE,
268 l_return_status,
269 l_return_msg) THEN
270 -- the run/bundle has an invalid status, tell the execute to stop the task
271 x_return_status := FND_OAM_DSCRAM_UTILS_PKG.G_RET_STS_STOPPED;
272 x_return_msg := '[Continued Validation Parent(s) Failed]:(Status('||l_return_status||'), Msg('||l_return_msg||'))';
273 fnd_oam_debug.log(1, l_ctxt, x_return_msg);
274 RETURN FALSE;
275 END IF;
276 END IF;
277
278 --success
279 b_task_info.last_validation_ret_sts := x_return_status;
280 b_task_info.last_validated := SYSDATE;
281 RETURN (x_return_status = FND_API.G_RET_STS_SUCCESS);
282 EXCEPTION
283 WHEN OTHERS THEN
284 x_return_msg := 'Unhandled Exception: (Code('||SQLCODE||'), Message("'||SQLERRM||'"))';
285 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
286 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
287 b_task_info.last_validation_ret_sts := x_return_status;
288 b_task_info.last_validated := SYSDATE;
289 RETURN FALSE;
290 END;
291
292 -- Private: Autonomous Txn
293 -- Invariant:
294 -- Validate_statr must preceed this call so we can assume the p_task_id has a valid
295 -- database row.
296 -- Before a call to execute_task can start doing work, it needs to call this procedure
297 -- to make sure the status is set to processing and a stats row is created for it.
298 -- Return Statuses:
299 -- SUCCESS, ERROR, ERROR_UNEXP
300 -- -Conv Validate_start statuses-
301 PROCEDURE ASSIGN_WORKER_TO_TASK(p_task_id IN NUMBER,
302 x_return_status OUT NOCOPY VARCHAR2,
303 x_return_msg OUT NOCOPY VARCHAR2)
304 IS
305 PRAGMA AUTONOMOUS_TRANSACTION;
306
307 l_ctxt VARCHAR2(60) := PKG_NAME||'ASSIGN_WORKER_TO_TASK';
308
309 l_stat_id NUMBER;
310 l_status VARCHAR2(30) := NULL;
311 l_workers_assigned NUMBER(15);
312
313 BEGIN
314 fnd_oam_debug.log(2, l_ctxt, 'ENTER');
315 x_return_status := FND_API.G_RET_STS_ERROR;
316 x_return_msg := '';
317
318 -- Do a locking select without a pre-select since we always have to update the
319 -- row to add to the # of workers assigned. Also updates the status to started if it
320 -- hasn't been set yet.
321 SELECT task_status, workers_assigned
322 INTO l_status, l_workers_assigned
323 FROM fnd_oam_dscram_tasks
324 WHERE task_id = p_task_id
325 FOR UPDATE;
326
327 fnd_oam_debug.log(1, l_ctxt, 'Task Status(Workers): '||l_status||'('||l_workers_assigned||')');
328
329 -- make sure the status is runnable after the lock
330 IF NOT FND_OAM_DSCRAM_UTILS_PKG.STATUS_IS_EXECUTABLE(l_status) THEN
331 x_return_status := FND_OAM_DSCRAM_UTILS_PKG.CONV_VALIDATE_START_STS_TO_RET(l_status);
332 IF FND_OAM_DSCRAM_UTILS_PKG.RET_STS_IS_ERROR(x_return_status) THEN
333 x_return_msg := 'Invalid task in assign, status('||l_status||')';
334 fnd_oam_debug.log(1, l_ctxt, x_return_msg);
335 END IF;
336 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
337 ROLLBACK;
338 RETURN;
339 END IF;
340
341 -- if we're executable but not processing we should start the entry
342 IF l_status <> FND_OAM_DSCRAM_UTILS_PKG.G_STATUS_PROCESSING THEN
343 IF l_workers_assigned = 0 THEN
344 --create a new stats entry for the task
345 FND_OAM_DSCRAM_STATS_PKG.CREATE_ENTRY(p_source_object_type => FND_OAM_DSCRAM_UTILS_PKG.G_TYPE_TASK,
346 p_source_object_id => p_task_id,
347 p_start_time => SYSDATE,
348 p_prestart_status => l_status,
349 x_stat_id => l_stat_id);
350 UPDATE fnd_oam_dscram_tasks
351 SET task_status = FND_OAM_DSCRAM_UTILS_PKG.G_STATUS_PROCESSING,
352 STATS_FINISHED = FND_API.G_FALSE
353 WHERE task_id = p_task_id;
354 ELSE
355 --the bundle isn't processing but the worker count's nonzero, this shouldn't happen
356 x_return_msg := 'Task Status ('||l_status||') is not in-progress but the number of workers assigned('||l_workers_assigned||') is nonzero.';
357 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
358 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
359 ROLLBACK;
360 RETURN;
361 END IF;
362 END IF;
363
364 --update the task's # of workers assigned
365 UPDATE fnd_oam_dscram_tasks
366 SET workers_assigned = workers_assigned + 1,
367 last_updated_by = fnd_global.user_id,
368 last_update_login = fnd_global.user_id,
369 last_update_date = SYSDATE
370 WHERE task_id = p_task_id;
371
372 --commit the changes and release the lock
373 COMMIT;
374
375 --populate the task state
376 b_task_info.task_id := p_task_id;
377 b_task_info.last_validated := NULL;
378 b_task_info.initialized := TRUE;
379
380 -- invalidate the last_fetched vars since we've changed things
381 b_last_fetched_task_id := NULL;
382
383 x_return_status := FND_API.G_RET_STS_SUCCESS;
384 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
385 EXCEPTION
386 WHEN OTHERS THEN
387 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
388 x_return_msg := 'Unhandled Exception: (Code('||SQLCODE||'), Message("'||SQLERRM||'"))';
389 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
390 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
391 ROLLBACK;
392 END;
393
394 -- Private: Autonomous Txn
395 -- Called when a task is completed in some way, usually when there are no more
396 -- processable units to fetch. Duties include updating the task's status and completing
397 -- the stats record.
398 PROCEDURE COMPLETE_TASK(p_proposed_status IN VARCHAR2,
399 p_proposed_ret_sts IN VARCHAR2,
400 x_final_status OUT NOCOPY VARCHAR2,
401 x_final_ret_sts OUT NOCOPY VARCHAR2)
402 IS
403 PRAGMA AUTONOMOUS_TRANSACTION;
404
405 l_ctxt VARCHAR2(60) := PKG_NAME||'COMPLETE_TASK';
406
407 l_final_status VARCHAR2(30);
408 l_final_ret_sts VARCHAR2(6);
409
410 l_status VARCHAR2(30);
411 l_workers_assigned NUMBER(15);
412 BEGIN
413 fnd_oam_debug.log(2, l_ctxt, 'ENTER');
414
415 -- always lock the task since we have to decrement the worker count
416 SELECT task_status, workers_assigned
417 INTO l_status, l_workers_assigned
418 FROM fnd_oam_dscram_tasks
419 WHERE task_id = b_task_info.task_id
420 FOR UPDATE;
421
422 -- translate the new_status into a valid final status
423 FND_OAM_DSCRAM_UTILS_PKG.TRANSLATE_COMPLETED_STATUS(l_status,
424 l_workers_assigned,
425 p_proposed_status,
426 p_proposed_ret_sts,
427 l_final_status,
428 l_final_ret_sts);
429 fnd_oam_debug.log(1, l_ctxt, 'Translated status "'||p_proposed_status||'" into "'||l_final_status||'"');
430 fnd_oam_debug.log(1, l_ctxt, 'Translated Execute Ret Sts "'||p_proposed_ret_sts||'" into "'||l_final_ret_sts||'"');
431
432 --if we discovered that we're full, possibly temporarily, just decrement the worker count and leave as long as we're not the last worker
433 IF l_final_ret_sts = FND_OAM_DSCRAM_UTILS_PKG.G_RET_STS_FULL AND l_workers_assigned > 1 THEN
434 UPDATE fnd_oam_dscram_tasks
435 SET workers_assigned = workers_assigned - 1,
436 last_updated_by = fnd_global.user_id,
437 last_update_login = fnd_global.user_id,
438 last_update_date = SYSDATE
439 WHERE task_id = b_task_info.task_id;
440 ELSE
441 -- otherwise, update the status and workers_assigned
442 UPDATE fnd_oam_dscram_tasks
443 SET task_status = l_final_status,
444 workers_assigned = workers_assigned - 1,
445 last_updated_by = fnd_global.user_id,
446 last_update_login = fnd_global.user_id,
447 last_update_date = SYSDATE
448 WHERE task_id = b_task_info.task_id;
449
450 --only complete stats if we changed state
451 IF l_final_status <> l_status AND
452 FND_OAM_DSCRAM_UTILS_PKG.STATUS_IS_FINAL(l_final_status) THEN
453
454 FND_OAM_DSCRAM_STATS_PKG.COMPLETE_ENTRY(p_source_object_type => FND_OAM_DSCRAM_UTILS_PKG.G_TYPE_TASK,
455 p_source_object_id => b_task_info.task_id,
456 p_end_time => SYSDATE,
457 p_postend_status => l_final_status);
458 END IF;
459 END IF;
460
461 -- push the changes and release the lock
462 COMMIT;
463
464 x_final_status := l_final_status;
465 x_final_ret_sts := l_final_ret_sts;
466
467 --after completing the task, kill the state
468 b_task_info.initialized := FALSE;
469
470 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
471 EXCEPTION
472 WHEN OTHERS THEN
473 x_final_status := FND_OAM_DSCRAM_UTILS_PKG.G_STATUS_ERROR_UNKNOWN;
474 x_final_ret_sts := FND_API.G_RET_STS_UNEXP_ERROR;
475 fnd_oam_debug.log(6, l_ctxt, 'Unhandled Exception: (Code('||SQLCODE||'), Message("'||SQLERRM||'"))');
476 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
477 ROLLBACK;
478 END;
479
480 -- Public
481 PROCEDURE EXECUTE_TASK(p_task_id IN NUMBER,
482 x_return_status OUT NOCOPY VARCHAR2,
483 x_return_msg OUT NOCOPY VARCHAR2)
484 IS
485 l_ctxt VARCHAR2(60) := PKG_NAME||'EXECUTE_TASK';
486
487 l_unit_id NUMBER;
488 l_completed_status VARCHAR2(30);
489
490 l_return_status VARCHAR2(6);
491 l_return_msg VARCHAR2(2048);
492 l_temp VARCHAR2(30);
493 BEGIN
494 fnd_oam_debug.log(2, l_ctxt, 'ENTER');
495 x_return_status := FND_API.G_RET_STS_ERROR;
496 x_return_msg := '';
497
498 -- do an initial validation of the task
499 IF NOT VALIDATE_START_EXECUTION(p_task_id,
500 l_return_status,
501 l_return_msg) THEN
502 x_return_status := l_return_status;
503 x_return_msg := '[Task Validation Failed]:('||l_return_msg||')';
504 fnd_oam_debug.log(1, l_ctxt, x_return_msg);
505 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
506 RETURN;
507 END IF;
508
509 -- attempt to assign this invocation as a worker for the bundle
510 ASSIGN_WORKER_TO_TASK(p_task_id,
511 l_return_status,
512 l_return_msg);
513 IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
514 x_return_status := l_return_status;
515 x_return_msg := '[Task Worker Assignment Failed]:('||l_return_msg||')';
516 fnd_oam_debug.log(1, l_ctxt, x_return_msg);
517 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
518 RETURN;
519 END IF;
520
521 --before proceeding after the assign, check our parent objects to make sure
522 --their state suggests we should continue
523 IF NOT FND_OAM_DSCRAM_BUNDLES_PKG.VALIDATE_CONTINUED_EXECUTION(FALSE,
524 TRUE,
525 l_return_status,
526 l_return_msg) THEN
527 --we don't care why a parent is invalid, just knowing so forces us to
528 --stop our work
529 COMPLETE_TASK(FND_OAM_DSCRAM_UTILS_PKG.G_STATUS_STOPPED,
530 FND_OAM_DSCRAM_UTILS_PKG.G_RET_STS_STOPPED,
531 l_completed_status,
532 x_return_status);
533 x_return_msg := '[Post-Assignment Parent Validation Failed]:('||l_return_msg||')';
534 fnd_oam_debug.log(1, l_ctxt, x_return_msg);
535 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
536 RETURN;
537 END IF;
538
539 --at this point, we're assigned so we need to issue a complete before returning.
540 --this means no quick returns, so we hit the complete after the loop.
541 l_completed_status := FND_OAM_DSCRAM_UTILS_PKG.G_STATUS_PROCESSED;
542 l_return_status := FND_API.G_RET_STS_SUCCESS;
543
544 -- we're in, start pulling units and executing them.
545 <<outer>>
546 LOOP
547 --get the next available task
548 FND_OAM_DSCRAM_UNITS_PKG.FETCH_NEXT_UNIT(TRUE,
549 l_unit_id,
550 l_return_status,
551 l_return_msg);
552 IF l_return_status = FND_OAM_DSCRAM_UTILS_PKG.G_RET_STS_EMPTY THEN
553 -- empty means no units left, independent of phase
554 l_return_status := FND_API.G_RET_STS_SUCCESS;
555 EXIT outer;
556 ELSIF l_return_status = FND_OAM_DSCRAM_UTILS_PKG.G_RET_STS_FULL THEN
557 -- full means nothing available right now so return and find another task.
558 EXIT outer;
559 ELSIF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
560 l_completed_status := FND_OAM_DSCRAM_UTILS_PKG.G_STATUS_ERROR_UNKNOWN;
561 x_return_msg := '[Fetch Next Unit Failed]:('||l_return_msg||')';
562 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
563 EXIT outer;
564 END IF;
565
566 --execute the unit
567 FND_OAM_DSCRAM_UNITS_PKG.EXECUTE_UNIT(l_unit_id,
568 l_return_status,
569 l_return_msg);
570 IF l_return_status = FND_OAM_DSCRAM_UTILS_PKG.G_RET_STS_FULL THEN
571 --If we got past the fetch but the execute found it full, continue
572 --fetching.
573 <<inner>>
574 LOOP
575 FND_OAM_DSCRAM_UNITS_PKG.FETCH_NEXT_UNIT(FALSE,
576 l_unit_id,
577 l_return_status,
578 l_return_msg);
579 IF l_return_status IN (FND_OAM_DSCRAM_UTILS_PKG.G_RET_STS_EMPTY,
580 FND_OAM_DSCRAM_UTILS_PKG.G_RET_STS_FULL) THEN
581 -- seeing an empty or full here doesn't mean the task's done, just that it's busy.
582 -- return full to the bundle_pkg to pick another task.
583 l_return_status := FND_OAM_DSCRAM_UTILS_PKG.G_RET_STS_FULL;
584 EXIT outer;
585 ELSIF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
586 l_completed_status := FND_OAM_DSCRAM_UTILS_PKG.G_STATUS_ERROR_UNKNOWN;
587 x_return_msg := '[Inner Fetch Next Unit Failed]:('||l_return_msg||')';
588 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
589 EXIT outer;
590 END IF;
591
592 -- try to execute this unit
593 FND_OAM_DSCRAM_UNITS_PKG.EXECUTE_UNIT(l_unit_id,
594 l_return_status,
595 l_return_msg);
596 IF l_return_status = FND_OAM_DSCRAM_UTILS_PKG.G_RET_STS_FULL THEN
597 --continue to the next inner loop iteration for the next fetch
598 null;
599 ELSIF l_return_status = FND_API.G_RET_STS_SUCCESS THEN
600 --on success break out of the loop so we can requery the units table from scratch
601 EXIT inner;
602 ELSIF l_return_status <> FND_OAM_DSCRAM_UTILS_PKG.G_RET_STS_PROCESSED AND
603 l_return_status <> FND_OAM_DSCRAM_UTILS_PKG.G_RET_STS_SKIPPED THEN
604 -- unexpected execution failure, since units have phases, there may be dependencies between
605 -- units which will break if we continue with the task. To handle this, we'll stop the task and
606 -- allow the user to choose whether to ignore the failed unit or retry them when restarting the task.
607 x_return_msg := '[Inner Execute Unit Failed]:(Status('||l_return_status||'), Msg('||l_return_msg||')). Stopping task.';
608 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
609 l_return_status := FND_OAM_DSCRAM_UTILS_PKG.G_RET_STS_STOPPED;
610 l_completed_status := FND_OAM_DSCRAM_UTILS_PKG.G_STATUS_STOPPED;
611 EXIT outer;
612 END IF;
613 END LOOP inner;
614 ELSIF l_return_status <> FND_API.G_RET_STS_SUCCESS AND
615 l_return_status <> FND_OAM_DSCRAM_UTILS_PKG.G_RET_STS_PROCESSED AND
616 l_return_status <> FND_OAM_DSCRAM_UTILS_PKG.G_RET_STS_SKIPPED THEN
617 -- take the same actions as when the inner execute fails
618 x_return_msg := '[Outer Execute Unit Failed]:(Status('||l_return_status||'), Msg('||l_return_msg||')). Stopping task.';
619 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
620 l_return_status := FND_OAM_DSCRAM_UTILS_PKG.G_RET_STS_STOPPED;
621 l_completed_status := FND_OAM_DSCRAM_UTILS_PKG.G_STATUS_STOPPED;
622 EXIT outer;
623 END IF;
624
625 --after every unit evaluation, check on the task and its parents.
626 --tell it to requery if the child's execution came back non-successful since this should
627 --be pretty uncommon and will help detect when a child has seen a stop in a parent.
628 IF NOT VALIDATE_CONTINUED_EXECUTION((l_return_status <> FND_API.G_RET_STS_SUCCESS),
629 TRUE,
630 l_return_status,
631 l_return_msg) THEN
632 --complete the task based on what validate found
633 l_completed_status := FND_OAM_DSCRAM_UTILS_PKG.CONV_RET_STS_TO_COMPL_STATUS(l_return_status);
634 IF FND_OAM_DSCRAM_UTILS_PKG.STATUS_IS_ERROR(l_return_status) THEN
635 x_return_msg := '[End-of-Loop Validate Failed]:('||l_return_msg||')';
636 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
637 END IF;
638 EXIT outer;
639 END IF;
640
641 END LOOP outer;
642
643 --finished processing the bundle
644 fnd_oam_debug.log(1, l_ctxt, 'Finished Task with status: '||l_completed_status||'('||l_return_status||')');
645 COMPLETE_TASK(l_completed_status,
646 l_return_status,
647 l_temp,
648 x_return_status);
649
650 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
651 EXCEPTION
652 WHEN OTHERS THEN
653 COMPLETE_TASK(FND_OAM_DSCRAM_UTILS_PKG.G_STATUS_ERROR_UNKNOWN,
654 FND_API.G_RET_STS_UNEXP_ERROR,
655 l_completed_status,
656 x_return_status);
657 x_return_msg := 'Unhandled Exception: [Code('||SQLCODE||'), Message("'||SQLERRM||'")]';
658 fnd_oam_debug.log(6, l_ctxt, x_return_msg);
659 fnd_oam_debug.log(2, l_ctxt, 'EXIT');
660 END;
661
662 END FND_OAM_DSCRAM_TASKS_PKG;