lazhen
2025-01-07 b3987122cbbc46c5c59d3173f37fca3170b6dc5a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
Quintiq file version 2.0
#parent: #root
StaticMethod DoFinalizeDatasetCopyDelete (LibOpt_Task task, Boolean iserrorhandling) as stream[Void]
{
  Description:
  [*
    This method checks for all datasets that are created by `task` if the `DeleteCondition` of the `LibOpt_DatasetCopyConditional` is satisfied. If so, the dataset is deleted. 
    This method assumes for all newly created datasets that any memory only dataset is online and that any standalone dataset is offline. 
    This method can be called right before an error. Therefore, don't start any reactive transactions in the parts of this method that can be reached when `iserrorhandling` is `true`.
  *]
  TextBody:
  [*
    // evr3 Jun-30-2020 (created)
    previousdeletecondition := stream[Void]::Success();
    snapshots := selectsortedset( task,
                                  SnapshotComponent.Children.astype( LibOpt_SnapshotReplannableCopyDataset ), 
                                  snapshot, 
                                  not snapshot.IsDatasetDeletedByOptimizer() 
                                  and not snapshot.HasFailedToCreateDataset()
                                  and not snapshot.HasExecutedDoFinalizeDatasetCopyDelete(), 
                                  // The DeleteCondition of a LibOpt_DatasetCopyOnAnyDownstreamCopy uses the HasToBeDeleted and IsDatasetDeletedByOptimizer attributes of
                                  // the snapshots that are created after the LibOpt_DatasetCopyOnAnyDownstreamCopy
                                  // By sorting on SequenceNr, it is ensured that the HasToBeDeleted and IsDatasetDeletedByOptimizer attributes of the newest components are updated first. 
                                  -snapshot.SequenceNr()
                                  );
    
    traverse( snapshots, Elements, snapshot )
    {
      datasetcopyconditional := snapshot.DatasetCopyConditional();
      // The AE can modify the DeleteCondition method himself. This means that a user error might occur there. 
      // If there is an error in this method and if DatasetCopyDelete is called with iserrorhandling := false, 
      // then this error will be logged below the dataset copy snapshot and the dataset won't be deleted. 
      // The optimizer will then continue executing as if nothing happened. 
      
      // If an error occurs when DatasetCopyDelete is called with iserrorhandling := true,
      // then this error will be logged below the SnapshotComponent. 
      // The current transaction will then be rolled back and the optimizer iteration will be aborted. 
      if( not isnull( datasetcopyconditional ) ) 
      {
        if( not task.Run().InOneTransaction() and not iserrorhandling )
        {
          hastodeletedataset := previousdeletecondition->|datasetcopyconditional->DeleteCondition( task );
          previousdeletecondition := datasetcopyconditional->DeleteConditionPostProcessing( snapshot, hastodeletedataset )->IgnoreException()
                                     ->|hastodeletedataset->Exception()->LibOpt_SnapshotError::ReadAndThrow( task, snapshot );
        }
        else
        {    
          hastodeletedataset := datasetcopyconditional.DeleteCondition( task );
          datasetcopyconditional.DeleteConditionPostProcessing( snapshot, hastodeletedataset );
        }
      }
    }
    
    // We return a chain of streams.
    // This ensures that stream::Success() will only be emitted when all dataset copies have been handled.
    return previousdeletecondition;
  *]
  InterfaceProperties { Accessibility: 'Module' }
}