Progress with Stages

Instead of updating the progress of the task stage directly, you can split it into multiple child stages. This provides more detail in the progress report.

Add Stages

Each stage is given a weight and a maximum value:

   Stage stage1 = task.taskStage().addChild("Searching for new Documents", 1, 10);
   Stage stage2 = task.taskStage().addChild("Processing Documents", 8, 80);
   Stage stage3 = task.taskStage().addChild("Deleting unseen documents", 1, 100);

Weight

The first number passed to addChild is the weight. The weights of the child stages are used to split the progress of the parent stage between the children. In the example above this means the first stage accounts for 10% (1/10) of the work, the second for 80% (8/10) and the third for 10% (1/10).

The weights of child stages only have any meaning when compared to each other, because the weights indicate how much of the work the stage is predicted to contain. Instead of using the weights 1, 8 and 1 the example could have used 2, 16 and 2 to achieve exactly the same effect.

Maximum Value

The maximum value for each stage has exactly the same meaning as in the basic progress example. The progress of stage 1 is measured on a scale of 0 to 10, stage 2 on a scale of 0 to 80 and stage 3 on a scale of 0 to 100.

Building Mode

In some situations you might need to modify the specification of a progress stage after progress has started. For example, you might not have enough information to assign accurate weights and maximum values when the stage is created.

In building mode, you can change the properties of a stage. However, this means that the reported progress can potentially be reduced. OpenText therefore recommends that you enable building mode for as short a time as possible at the beginning of the task.

A typical solution is to create an additional thread to build the progress stage, allowing the main thread to being synchronization. Building mode would be enabled for the lifetime of the progress thread.

To enable building mode, get an instance of the SharedBuild object. Building mode is disabled when all of the SharedBuild instances are destroyed.

   {
      SharedBuild build = task.taskStage().progressRoot().build();
      // Update progress stage structure
   }

It is not necessary to enable building mode for any operation that has no effect on the overall progress of the action (for example if a stage has not been started, the maximum value can be modified freely).

Process Stages

When the synchronize action begins, each stage is in the “Pending” state with a progress of 0%. The following code shows how to update the progress for a stage when it is time to process it:

   {
      ActiveStage activeStage(stage1);
      for (int ii = 0; ii < 15; ++ii)
      {
         // Do work
         activeStage->incrementProgress();
      } 
   }

When the ActiveStage is created, stage 1 moves to the "Processing" state. Progress is incremented gradually as work is done and then the stage moves into the "Finished" state when the activeStage destructor is called at the end of the block.

You might notice that although the maximum for stage 1 was set to 10, the loop above increments 15 times. This demonstrates what happens when the maximum is estimated but the actual amount of work ends up being greater. In this case progress is incremented to the maximum in the first 10 iterations, and then stays at 100% for the remaining 5 – progress never exceeds 100%.

Similarly, in the following example there was less work to do than expected:

   {
      ActiveStage activeStage(stage3);
      for (int ii = 0; ii < 30; ++ii)
      {
         // Do work
         activeStage->incrementProgress();
      }
   }

In this case the maximum was set to 100 but there were actually only 30 units of work to complete. In this case, when the stage is finished at the end of the block, the progress of the stage jumps from 30% to 100%.

Progress reporting is most accurate when the stage weights and maximums are accurate, but ConnectorLib C++ ensures that progress does not exceed 100% and does not go backwards. Using ActiveStage also ensures that completed stages are set to 100% even if the progress for the stage was not set to the maximum value.

Code Sample

The SynchronizeWithProgress project in the CodeSamples solution contains an example that shows how to use progress reporting when synchronizing from a file system.

The example does make some assumptions about the weights of the directories, to keep the example simple.

The example could be improved by:

  • propagating file counts up to the parent progress stages.
  • building the progress information on a separate thread (take care to avoid inaccuracies in the progress report).