Workflow Parallel Steps

Soady, Phil phil.soady at sap.com
Wed May 26 09:39:52 EDT 2004


Parallel means can occur at the same time, not will occur in parallel.
The idea is to utilize resource in a controlled manner.
See RZ12 and the setting there for more info.
Also why controlled dispatch of events is good.
 
To get the feel for parallel programming in SAP,
here is a simple program.  (no warranty.. just for fun...)
 ========================================================================
report zpara .
 
data t type i.
 
parameters:
            cnt    type i default 1000,
            packet type i default 100,
            para as checkbox default 'X',
            rfcgroup like rzllitab-classname default 'PARALLEL'.
 
data informed.
data  total type f.
data  l_tot type f.
data  splits type i.
data  mod type i.
data: first type i.
data: last type i.
data: this_last type i.
data: this_split type i.
data: ret_splits type i.
data: act_splits type i.
data: taskname(8) type n value '00000000'.
data: begin of task occurs 0,
     taskname(8) type n,
     uzeit like sy-uzeit,
     end of task.
 
data max_pbt_wps type i.
data free_pbt_wps type i.
 
 
start-of-selection.
 
**** TO USE THIS CODE,
* create a parallel(rfc) server group in RZ12.
**************************************************
 
 
* set run time res low, so measurement in milli not microsecs.
* we are measure BIG runs
 
refresh task.
 
set run time clock resolution low.
get run time field t.
total = 0.
 
check cnt > 0.
 
if packet = 0.
   packet = cnt.
endif.
 
* splits calculated based on packet size
* the last split may be a partial packet
splits = (  cnt div packet ) .
mod = ( cnt mod packet ).
 
if mod > 0.
  splits = splits + 1.
endif.
 
* is parallel mode selected
if para = 'X'.
 
* parallel processing MUST be initialized first.
 
  call function 'SPBT_INITIALIZE'
   exporting
      group_name                           = rfcgroup
    importing
      max_pbt_wps                          = max_pbt_wps
      free_pbt_wps                         = free_pbt_wps
    exceptions
      invalid_group_name                   = 1
      internal_error                       = 2
      pbt_env_already_initialized          = 3
      currently_no_resources_avail         = 4
      no_pbt_resources_found               = 5
      cant_init_different_pbt_groups       = 6
      others                               = 7
            .
  if sy-subrc <> 0.
* if our group failed or the available processes was 0,
* we would exit cleanly here.
* for the demo, just bomb out.
 
  endif.
 
 
  last = 0.
  ret_splits = 0.
  act_splits = 0.
 
* so for each split
  do splits times.
 
* make a jobname
    taskname    = taskname + 1.
 
* work out which chunk we are processing
* ie were are we up to ??
    first       = last + 1.
    this_last   = first + packet - 1.
 
* for info purposes record which split
    this_split = sy-index.
 
* just in case we have the last split,
* calculated adjust target end,
    if this_last > cnt.
      this_last = cnt.
    endif.
 
* try a dispatch this split.
* this is where more logic is needed.
* here we set a max of a hundred tries to dispatch
* something. IN VERY LARGE jobs,
* a commit work and a more intelligent wait
* might be appropriate.
* we at least wait, 1 then 2 then 3... secs etc
* until we get a look in.
 
 informed = ' '.
 
   do. "  100 times.
 
 
* inside a parallel ( new ) task
* do a chunk of work.
* NO importing parameters here. The result is returned
* in the receiving function.
* SPECIAL, extra, exceptions are available to control
* sucess or otherwise of the dispatch.
 
 
    call function 'Z_CHUNK' starting new task taskname
        destination in group rfcgroup
        performing finished on end of task
      exporting
 
        from_int       = first
        to_int         = this_last
 
      exceptions
        resource_failure =  1
        others         = 2.
 
     if sy-subrc = 0.
*    dispatch ok, record the fact and march on...
        write: / 'Split ', this_split, 'dispatch at', sy-uzeit.
        act_splits = act_splits + 1.
        last =  first + packet - 1.
        exit. " the retry until dispatched loop.
     else.
      if informed = ' '.
      write: / 'No resource free for split',   this_Split .
      Write: / 'Waits... ',  sy-uzeit.
 
* wait x seconds, each attempt waits successlively longer
*      wait up to sy-index seconds.
*       wait up to 1 seconds.
        wait up to '0.1' seconds.
        informed = 'X'.
      endif.
     endif.
 
   enddo.
 
* Actual failure to dispatch is not captured in this version
* your code should consider this issue.
 
  enddo.
 
*** THE BIG ROUNDUP
* we wait here until ALL splits are returned.
* we do that by waiting until a return counter
* equals the numbers of dispatches.
* this wait does not wait indefinitely if a dispatch above
* fails, since another continue point is NO oustanding
* async tasks.
 
  wait until ret_splits >= act_splits.
 
else.
 
  call function 'Z_CHUNK'
       exporting
            from_int = 1
            to_int   = cnt
       importing
            tot      = total.
 
 
 
 
endif.
 
get run time field t.
t = t / 1000.
loop at task.
 
  write: / 'Received task', task-taskname, ' at ', task-uzeit.
 
endloop.
 
write: / 'Parallel', para.
write: / 'Time ms ', t left-justified.
write: / 'Splits  ', splits left-justified.
write: / 'Total   ', total left-justified.
 
 
*---------------------------------------------------------------------*
*       FORM finished                                                 *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  TASKNAME                                                      *
*---------------------------------------------------------------------*
form finished using taskname.
 
* when receiving a task back, we get out result
* and record that the task returned, by uping a counter.
 
 
  receive results from function 'Z_CHUNK'
     importing
        tot = l_tot.
 
 
  task-taskname =  taskname.
  task-uzeit = sy-uzeit.
  append task.
 
  total = total + l_tot.
 
  ret_splits = ret_splits + 1.
 
endform.
 
 
 
*  Create this function below.
*
*function z_chunk.
*"----------------------------------------------------------------------
*"*"Local interface:
*"  IMPORTING
*"     VALUE(FROM_INT) TYPE  I
*"     VALUE(TO_INT) TYPE  I
*"  EXPORTING
*"     VALUE(TOT) TYPE  F
*"----------------------------------------------------------------------
*
*data l_i type i.
*
*tot = 0.
*
*check to_int > from_int.
*
*l_i = from_int.
*
*while l_i <= to_int.
*   tot = tot + l_i.
*   l_i = l_i + 1.
*endwhile.
*
*
*endfunction.
 
 
 
 ========================================================================
Phil Soady
Senior Consultant
Business Technologies
SAP Australia
M  +61 (0) 412 213 079
E  phil.soady at sap.com
 
 
-----Original Message-----
From: SAP Workflow [mailto:Owner-SAP-WUG at MITVMA.MIT.EDU] On Behalf Of Alon Raskin
Sent: Tuesday,25 May 2004 11:12 PM
To: SAP-WUG at MITVMA.MIT.EDU
Subject: Workflow Parallel Steps
 
Hi Guys,
 
Just some questions about Workflow Parallel steps:
 
1. Does the Workflow engine guarantee that two parallel branches are executed in parallel? What if there are not enough system resources to do this? Does it wait for enough to become available?
 
2. If two branches are executed in parallel (via the use of a fork), does each branch utilise a seperate batch/dialog process?
 
Regards,
 
Alon
 


More information about the SAP-WUG mailing list