Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Van toepassing op:SQL Server
SSIS Integration Runtime in Azure Data Factory
De runtime-engine van de Integration Services maakt het mogelijk om pakketten, taken en andere soorten containers tijdens uitvoering te onderbreken door gebruik te maken van breakpoints. Het gebruik van breakpoints stelt je in staat fouten te beoordelen en te corrigeren die voorkomen dat je applicatie of taken correct draait. De breakpoint-architectuur stelt de client in staat om de runtimewaarde van objecten in het pakket te evalueren op gedefinieerde uitvoeringspunten terwijl taakverwerking wordt onderbroken.
Ontwikkelaars van aangepaste taken kunnen deze architectuur gebruiken om aangepaste breakpointdoelen te creëren door gebruik te maken van de IDTSBreakpointSite interface en de bijbehorende bovenliggende interface, IDTSSuspend. De IDTSBreakpointSite interface definieert de interactie tussen de runtime-engine en de taak voor het creëren en beheren van aangepaste breakpointsites of doelen. De IDTSSuspend interface biedt methoden en eigenschappen die door de runtime-engine worden aangeroepen om de taak te waarschuwen de uitvoering te onderbreken of te hervatten.
Een breakpoint-site of target is een punt in de uitvoering van de taak waar de verwerking kan worden onderbroken. Gebruikers kiezen uit beschikbare breakpointsites in het dialoogvenster 'Breakpoints instellen '. Bijvoorbeeld, naast de standaard breakpoint-opties, biedt de Foreach Loop Container de optie "Break at the beginning of every iteration of the loop".
Wanneer een taak tijdens de uitvoering een breakpointdoel bereikt, evalueert het het breakpointdoel om te bepalen of een breakpoint is ingeschakeld. Dit geeft aan dat de gebruiker wil dat de uitvoering stopt bij dat breekpunt. Als het breakpoint is ingeschakeld, haalt de taak het OnBreakpointHit event naar de run-time engine. De run-time engine reageert op het event door de Suspend-methode aan te roepen van elke taak die momenteel in het pakket draait. De uitvoering van de taak wordt hervat wanneer de runtime de ResumeExek-methode van de onderbroken taak aanroept.
Taken die geen breakpoints gebruiken, zouden nog steeds de interfaces IDTSSuspend moeten implementerenIDTSBreakpointSite. Dit zorgt ervoor dat de taak correct wordt onderbroken wanneer andere objecten in het pakket gebeurtenissen oproepen OnBreakpointHit .
IDTSBreakpointSite Interface en BreakpointManager
Taken creëren breakpoint-doelen door de CreateBreakpointTarget methode van de BreakpointManageraan te roepen, waarbij een geheel getal ID en stringbeschrijving als parameters worden gebruikt. Wanneer de taak het punt in de code bereikt dat een breekpuntdoel bevat, evalueert het het breekpuntdoel door de IsBreakpointTargetEnabled methode te gebruiken om te bepalen of dat breekpunt is ingeschakeld. Als het waar is, meldt de taak de run-time engine door het OnBreakpointHit event te verhogen.
De IDTSBreakpointSite interface definieert één enkele methode, AcceptBreakpointManager, die wordt aangeroepen door de runtime-engine tijdens het aanmaken van taken. Deze methode geeft als parameter het BreakpointManager object, dat vervolgens door de taak wordt gebruikt om zijn breakpoints te creëren en te beheren. Taken moeten de BreakpointManager lokaal opslaan voor gebruik tijdens de Validate- en Execute-methoden .
De volgende voorbeeldcode demonstreert hoe je een breekpuntdoel kunt creëren met behulp van de BreakpointManager. Het voorbeeld roept de OnBreakpointHit methode aan om het event te verhogen.
public void AcceptBreakpointManager( BreakpointManager breakPointManager )
{
// Store the breakpoint manager locally.
this.bpm = breakPointManager;
}
public override DTSExecResult Execute( Connections connections,
Variables variables, IDTSComponentEvents events,
IDTSLogging log, DtsTransaction txn)
{
// Create a breakpoint.
this.bpm.CreateBreakPointTarget( 1 , "A sample breakpoint target." );
...
if( this.bpm.IsBreakpointTargetEnabled( 1 ) == true )
events.OnBreakpointHit( this.bpm.GetBreakpointTarget( 1 ) );
}
Public Sub AcceptBreakpointManager(ByVal breakPointManager As BreakpointManager)
' Store the breakpoint manager locally.
Me.bpm = breakPointManager
End Sub
Public Overrides Function Execute(ByVal connections As Connections, _
ByVal variables As Variables, ByVal events As IDTSComponentEvents, _
ByVal log As IDTSLogging, ByVal txn As DtsTransaction) As DTSExecResult
' Create a breakpoint.
Me.bpm.CreateBreakPointTarget(1 , "A sample breakpoint target.")
If Me.bpm.IsBreakpointTargetEnabled(1) = True Then
events.OnBreakpointHit(Me.bpm.GetBreakpointTarget(1))
End If
End Function
IDTSSuspend Interface
De IDTSSuspend interface definieert de methoden die door de runtime-engine worden aangeroepen wanneer deze een taak pauzeert of hervat. De IDTSSuspend interface wordt geïmplementeerd door de IDTSBreakpointSite interface, en de methoden Suspend en ResumeExecution worden meestal overschreven door de aangepaste taak. Wanneer de run-time engine een OnBreakpointHit-gebeurtenis van een taak ontvangt, roept deze de Suspend-methode van elke lopende taak aan en geeft de taken de melding om te pauzeren. Wanneer de client de uitvoering hervat, roept de runtime-engine de ResumeExecution-methode van de taken die zijn onderbroken.
Het opschorten en hervatten van de taakuitvoering houdt in dat de uitvoeringsdraad van de taak wordt gepauzeerd en hervat. In beheerde code doe je dit met de ManualResetEvent-klasse in de System.Threading-namespace van het .NET Framework.
Het volgende codevoorbeeld toont het opschorten en hervatten van de takenuitvoering. Let op dat de Execute-methode is veranderd ten opzichte van het vorige codevoorbeeld, en de uitvoeringsthread wordt gepauzeerd bij het activeren van het breakpoint.
private ManualResetEvent m_suspended = new ManualResetEvent( true );
private ManualResetEvent m_canExecute = new ManualResetEvent( true );
private int m_suspendRequired = 0;
private int m_debugMode = 0;
public override DTSExecResult Execute( Connections connections, Variables variables, IDTSComponentEvents events, IDTSLogging log, DtsTransaction txn)
{
// While a task is not executing, it is suspended.
// Now that we are executing,
// change to not suspended.
ChangeEvent(m_suspended, false);
// Check for a suspend before doing any work,
// in case the suspend and execute calls
// were initiated at virtually the same time.
CheckAndSuspend();
CheckAndFireBreakpoint( componentEvents, 1);
}
private void CheckAndSuspend()
{
// Loop until we can execute.
// The loop is required rather than a simple If
// because there is a time between the return from WaitOne and the
// reset that we might receive another Suspend call.
// Suspend() will see that we are suspended
// and return. So we need to rewait.
while (!m_canExecute.WaitOne(0, false))
{
ChangeEvent(m_suspended, true);
m_canExecute.WaitOne();
ChangeEvent(m_suspended, false);
}
}
private void CheckAndFireBreakpoint(IDTSComponentEvents events, int breakpointID)
{
// If the breakpoint is enabled, fire it.
if (m_debugMode != 0 && this.bpm.IsBreakpointTargetEnabled(breakpointID))
{
// Enter a suspend mode before firing the breakpoint.
// Firing the breakpoint will cause the runtime
// to call Suspend on this task.
// Because we are blocked on the breakpoint,
// we are suspended.
ChangeEvent(m_suspended, true);
events.OnBreakpointHit(this.bpm.GetBreakpointTarget(breakpointID));
ChangeEvent(m_suspended, false);
}
// Check for a suspension for two reasons:
// 1. If we are at a point where we could fire a breakpoint,
// we are at a valid suspend point. Even if we didn't hit a
// breakpoint, the runtime may have called suspend,
// so check for it.
// 2. Between the return from OnBreakpointHit
// and the reset of the event, it is possible to have
// received a suspend call from which we returned because
// we were already suspended. We need to be sure it is okay
// to continue executing now.
CheckAndSuspend();
}
static void ChangeEvent(ManualResetEvent e, bool shouldSet)
{
bool succeeded;
if (shouldSet)
succeeded = e.Set();
else
succeeded = e.Reset();
if (!succeeded)
throw new Exception("Synchronization object failed.");
}
public bool SuspendRequired
{
get {return m_suspendRequired != 0;}
set
{
// This lock is also taken by Suspend().
// Because it is possible for the package to be
// suspended and resumed in quick succession,
// this property might be set before
// the actual Suspend() call.
// Without the lock, the Suspend() might reset the canExecute
// event after we set it to abort the suspension.
lock (this)
{
Interlocked.Exchange(ref m_suspendRequired, value ? 1 : 0);
if (!value)
ResumeExecution();
}
}
}
public void ResumeExecution()
{
ChangeEvent( m_canExecute,true );
}
public void Suspend()
{
// This lock is also taken by the set SuspendRequired method.
// It prevents this call from overriding an
// aborted suspension. See comments in set SuspendRequired.
lock (this)
{
// If a Suspend is required, do it.
if (m_suspendRequired != 0)
ChangeEvent(m_canExecute, false);
}
// We can't return from Suspend until the task is "suspended".
// This can happen one of two ways:
// the m_suspended event occurs, indicating that the execute thread
// has suspended, or the canExecute flag is set,
// indicating that a suspend is no longer required.
WaitHandle [] suspendOperationComplete = {m_suspended, m_canExecute};
WaitHandle.WaitAny(suspendOperationComplete);
}
Private m_suspended As ManualResetEvent = New ManualResetEvent(True)
Private m_canExecute As ManualResetEvent = New ManualResetEvent(True)
Private m_suspendRequired As Integer = 0
Private m_debugMode As Integer = 0
Public Overrides Function Execute(ByVal connections As Connections, _
ByVal variables As Variables, ByVal events As IDTSComponentEvents, _
ByVal log As IDTSLogging, ByVal txn As DtsTransaction) As DTSExecResult
' While a task is not executing it is suspended.
' Now that we are executing,
' change to not suspended.
ChangeEvent(m_suspended, False)
' Check for a suspend before doing any work,
' in case the suspend and execute calls
' were initiated at virtually the same time.
CheckAndSuspend()
CheckAndFireBreakpoint(componentEvents, 1)
End Function
Private Sub CheckAndSuspend()
' Loop until we can execute.
' The loop is required rather than a simple if
' because there is a time between the return from WaitOne and the
' reset that we might receive another Suspend call.
' Suspend() will see that we are suspended
' and return. So we need to rewait.
Do While Not m_canExecute.WaitOne(0, False)
ChangeEvent(m_suspended, True)
m_canExecute.WaitOne()
ChangeEvent(m_suspended, False)
Loop
End Sub
Private Sub CheckAndFireBreakpoint(ByVal events As IDTSComponentEvents, _
ByVal breakpointID As Integer)
' If the breakpoint is enabled, fire it.
If m_debugMode <> 0 AndAlso Me.bpm.IsBreakpointTargetEnabled(breakpointID) Then
' Enter a suspend mode before firing the breakpoint.
' Firing the breakpoint will cause the runtime
' to call Suspend on this task.
' Because we are blocked on the breakpoint,
' we are suspended.
ChangeEvent(m_suspended, True)
events.OnBreakpointHit(Me.bpm.GetBreakpointTarget(breakpointID))
ChangeEvent(m_suspended, False)
End If
' Check for a suspension for two reasons:
' 1. If we are at a point where we could fire a breakpoint,
' we are at a valid suspend point. Even if we didn't hit a
' breakpoint, the runtime may have called suspend,
' so check for it.
' 2. Between the return from OnBreakpointHit
' and the reset of the event, it is possible to have
' received a suspend call from which we returned because
' we were already suspended. We need to be sure it is okay
' to continue executing now.
CheckAndSuspend()
End Sub
Shared Sub ChangeEvent(ByVal e As ManualResetEvent, ByVal shouldSet As Boolean)
Dim succeeded As Boolean
If shouldSet Then
succeeded = e.Set()
Else
succeeded = e.Reset()
End If
If (Not succeeded) Then
Throw New Exception("Synchronization object failed.")
End If
End Sub
Public Property SuspendRequired() As Boolean
Get
Return m_suspendRequired <> 0
End Get
Set
' This lock is also taken by Suspend().
' Because it is possible for the package to be
' suspended and resumed in quick succession,
' this property might be set before
' the actual Suspend() call.
' Without the lock, the Suspend() might reset the canExecute
' event after we set it to abort the suspension.
SyncLock Me
Interlocked.Exchange(m_suspendRequired,IIf(Value, 1, 0))
If (Not Value) Then
ResumeExecution()
End If
End SyncLock
End Set
End Property
Public Sub ResumeExecution()
ChangeEvent(m_canExecute,True)
End Sub
Public Sub Suspend()
' This lock is also taken by the set SuspendRequired method.
' It prevents this call from overriding an
' aborted suspension. See comments in set SuspendRequired.
SyncLock Me
' If a Suspend is required, do it.
If m_suspendRequired <> 0 Then
ChangeEvent(m_canExecute, False)
End If
End SyncLock
' We can't return from Suspend until the task is "suspended".
' This can happen one of two ways:
' the m_suspended event occurs, indicating that the execute thread
' has suspended, or the canExecute flag is set,
' indicating that a suspend is no longer required.
Dim suspendOperationComplete As WaitHandle() = {m_suspended, m_canExecute}
WaitHandle.WaitAny(suspendOperationComplete)
End Sub