Imported Upstream version 4.6.0.125

Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2016-08-03 10:59:49 +00:00
parent a569aebcfd
commit e79aa3c0ed
17047 changed files with 3137615 additions and 392334 deletions

View File

@@ -0,0 +1,159 @@
//-----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
namespace System.Activities.Tracking
{
using System;
using System.Runtime.Serialization;
using System.Runtime;
using System.Globalization;
[Fx.Tag.XamlVisible(false)]
[DataContract]
public sealed class ActivityInfo
{
string name;
string id;
string instanceId;
long instanceIdInternal;
string typeName;
public ActivityInfo(string name, string id, string instanceId, string typeName)
{
if (string.IsNullOrEmpty(name))
{
throw FxTrace.Exception.ArgumentNullOrEmpty("name");
}
if (string.IsNullOrEmpty(id))
{
throw FxTrace.Exception.ArgumentNullOrEmpty("id");
}
if (string.IsNullOrEmpty(instanceId))
{
throw FxTrace.Exception.ArgumentNullOrEmpty("instanceId");
}
if (string.IsNullOrEmpty(typeName))
{
throw FxTrace.Exception.ArgumentNullOrEmpty("typeName");
}
this.Name = name;
this.Id = id;
this.InstanceId = instanceId;
this.TypeName = typeName;
}
internal ActivityInfo(ActivityInstance instance)
: this(instance.Activity, instance.InternalId)
{
this.Instance = instance;
}
internal ActivityInfo(Activity activity, long instanceId)
{
this.Activity = activity;
this.instanceIdInternal = instanceId;
}
internal ActivityInstance Instance
{
get;
private set;
}
[DataMember]
public string Name
{
get
{
if (string.IsNullOrEmpty(this.name))
{
Fx.Assert(this.Activity != null, "Activity not set");
this.name = this.Activity.DisplayName;
}
return this.name;
}
// Internal visibility for partial trust serialization purposes only.
internal set
{
Fx.Assert(!string.IsNullOrEmpty(value), "Name cannot be null or empty");
this.name = value;
}
}
[DataMember]
public string Id
{
get
{
if (String.IsNullOrEmpty(this.id))
{
Fx.Assert(this.Activity != null, "Activity not set");
this.id = this.Activity.Id;
}
return this.id;
}
// Internal visibility for partial trust serialization purposes only.
internal set
{
Fx.Assert(!string.IsNullOrEmpty(value), "Id cannot be null or empty");
this.id = value;
}
}
[DataMember]
public string InstanceId
{
get
{
if (string.IsNullOrEmpty(this.instanceId))
{
this.instanceId = this.instanceIdInternal.ToString(CultureInfo.InvariantCulture);
}
return this.instanceId;
}
// Internal visibility for partial trust serialization purposes only.
internal set
{
Fx.Assert(!string.IsNullOrEmpty(value), "InstanceId cannot be null or empty");
this.instanceId = value;
}
}
[DataMember]
public string TypeName
{
get
{
if (string.IsNullOrEmpty(this.typeName))
{
Fx.Assert(this.Activity != null, "Activity not set");
this.typeName = this.Activity.GetType().FullName;
}
return this.typeName;
}
// Internal visibility for partial trust serialization purposes only.
internal set
{
Fx.Assert(!string.IsNullOrEmpty(value), "TypeName cannot be null or empty");
this.typeName = value;
}
}
public override string ToString()
{
return string.Format(CultureInfo.CurrentCulture,
"Name={0}, ActivityId = {1}, ActivityInstanceId = {2}, TypeName={3}",
this.Name,
this.Id,
this.InstanceId,
this.TypeName);
}
internal Activity Activity
{
get;
private set;
}
}
}

View File

@@ -0,0 +1,19 @@
//-----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
namespace System.Activities.Tracking
{
public sealed class ActivityScheduledQuery : TrackingQuery
{
public ActivityScheduledQuery()
{
this.ActivityName = "*";
this.ChildActivityName = "*";
}
public string ActivityName { get; set; }
public string ChildActivityName { get; set; }
}
}

View File

@@ -0,0 +1,112 @@
//-----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
namespace System.Activities.Tracking
{
using System;
using System.Runtime.Serialization;
using System.Runtime;
using System.Globalization;
[Fx.Tag.XamlVisible(false)]
[DataContract]
public sealed class ActivityScheduledRecord : TrackingRecord
{
ActivityInfo activity;
ActivityInfo child;
internal ActivityScheduledRecord(Guid instanceId, ActivityInstance instance, ActivityInstance child)
: this(instanceId, instance, new ActivityInfo(child))
{
}
internal ActivityScheduledRecord(Guid instanceId, ActivityInstance instance, ActivityInfo child)
: base(instanceId)
{
Fx.Assert(child != null, "Child activity cannot be null.");
if (instance != null)
{
this.Activity = new ActivityInfo(instance);
}
this.Child = child;
}
//parameter activity is null if the root activity is being scheduled.
public ActivityScheduledRecord(
Guid instanceId,
long recordNumber,
ActivityInfo activity,
ActivityInfo child)
: base(instanceId, recordNumber)
{
if (child == null)
{
throw FxTrace.Exception.ArgumentNull("child");
}
this.Activity = activity;
this.Child = child;
}
ActivityScheduledRecord(ActivityScheduledRecord record)
: base(record)
{
this.Activity = record.Activity;
this.Child = record.Child;
}
public ActivityInfo Activity
{
get
{
return this.activity;
}
private set
{
this.activity = value;
}
}
public ActivityInfo Child
{
get
{
return this.child;
}
private set
{
this.child = value;
}
}
[DataMember(Name = "Activity")]
internal ActivityInfo SerializedActivity
{
get { return this.Activity; }
set { this.Activity = value; }
}
[DataMember(Name = "Child")]
internal ActivityInfo SerializedChild
{
get { return this.Child; }
set { this.Child = value; }
}
protected internal override TrackingRecord Clone()
{
return new ActivityScheduledRecord(this);
}
public override string ToString()
{
return string.Format(CultureInfo.CurrentCulture,
"ActivityScheduledRecord {{ {0}, Activity {{ {1} }}, ChildActivity {{ {2} }} }}",
base.ToString(),
this.Activity == null ? "<null>" : this.Activity.ToString(),
this.Child.ToString());
}
}
}

View File

@@ -0,0 +1,88 @@
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace System.Activities.Tracking
{
using System.Collections.ObjectModel;
public class ActivityStateQuery : TrackingQuery
{
Collection<string> arguments;
Collection<string> states;
Collection<string> variables;
public ActivityStateQuery()
{
this.ActivityName = "*";
}
public string ActivityName
{
get;
set;
}
public Collection<string> Arguments
{
get
{
if (this.arguments == null)
{
this.arguments = new Collection<string>();
}
return this.arguments;
}
}
public Collection<string> Variables
{
get
{
if (this.variables == null)
{
this.variables = new Collection<string>();
}
return this.variables;
}
}
public Collection<string> States
{
get
{
if (this.states == null)
{
this.states = new Collection<string>();
}
return this.states;
}
}
internal bool HasStates
{
get
{
return this.states != null && this.states.Count > 0;
}
}
internal bool HasArguments
{
get
{
return this.arguments != null && this.arguments.Count > 0;
}
}
internal bool HasVariables
{
get
{
return this.variables != null && this.variables.Count > 0;
}
}
}
}

View File

@@ -0,0 +1,349 @@
//-----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
namespace System.Activities.Tracking
{
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Runtime;
using System.Runtime.Serialization;
using System.Collections;
using System.Reflection;
using System.Runtime.Diagnostics;
[Fx.Tag.XamlVisible(false)]
[DataContract]
public sealed class ActivityStateRecord : TrackingRecord
{
IDictionary<string, object> variables;
IDictionary<string, object> arguments;
ActivityInfo activity;
string state;
static ReadOnlyCollection<string> wildcardCollection = new ReadOnlyCollection<string>(new List<string>(1) { "*" });
internal ActivityStateRecord(Guid instanceId, ActivityInstance instance, ActivityInstanceState state)
: this(instanceId, new ActivityInfo(instance), state)
{
}
internal ActivityStateRecord(Guid instanceId, ActivityInfo activity, ActivityInstanceState state)
: base(instanceId)
{
this.Activity = activity;
switch (state)
{
case ActivityInstanceState.Executing:
this.State = ActivityStates.Executing;
break;
case ActivityInstanceState.Closed:
this.State = ActivityStates.Closed;
break;
case ActivityInstanceState.Canceled:
this.State = ActivityStates.Canceled;
break;
case ActivityInstanceState.Faulted:
this.State = ActivityStates.Faulted;
break;
default:
throw Fx.AssertAndThrow("Invalid state value");
}
}
public ActivityStateRecord(
Guid instanceId,
long recordNumber,
ActivityInfo activity,
string state)
: base(instanceId, recordNumber)
{
if (activity == null)
{
throw FxTrace.Exception.ArgumentNull("activity");
}
if (string.IsNullOrEmpty(state))
{
throw FxTrace.Exception.ArgumentNullOrEmpty("state");
}
this.Activity = activity;
this.State = state;
}
ActivityStateRecord(ActivityStateRecord record)
: base(record)
{
this.Activity = record.Activity;
this.State = record.State;
if (record.variables != null)
{
if (record.variables == ActivityUtilities.EmptyParameters)
{
this.variables = ActivityUtilities.EmptyParameters;
}
else
{
this.variables = new Dictionary<string, object>(record.variables);
}
}
if (record.arguments != null)
{
if (record.arguments == ActivityUtilities.EmptyParameters)
{
this.arguments = ActivityUtilities.EmptyParameters;
}
else
{
this.arguments = new Dictionary<string, object>(record.arguments);
}
}
}
public ActivityInfo Activity
{
get
{
return this.activity;
}
private set
{
this.activity = value;
}
}
public string State
{
get
{
return this.state;
}
private set
{
this.state = value;
}
}
public IDictionary<string, object> Variables
{
get
{
if (this.variables == null)
{
this.variables = GetVariables(wildcardCollection);
Fx.Assert(this.variables.IsReadOnly, "only readonly dictionary can be set for variables");
}
return this.variables;
}
internal set
{
Fx.Assert(value.IsReadOnly, "only readonly dictionary can be set for variables");
this.variables = value;
}
}
public IDictionary<string, object> Arguments
{
get
{
if (this.arguments == null)
{
this.arguments = GetArguments(wildcardCollection);
Fx.Assert(this.arguments.IsReadOnly, "only readonly dictionary can be set for arguments");
}
return this.arguments;
}
internal set
{
Fx.Assert(value.IsReadOnly, "only readonly dictionary can be set for arguments");
this.arguments = value;
}
}
[DataMember(EmitDefaultValue = false, Name = "variables")]
internal IDictionary<string, object> SerializedVariables
{
get { return this.variables; }
set { this.variables = value; }
}
[DataMember(EmitDefaultValue = false, Name = "arguments")]
internal IDictionary<string, object> SerializedArguments
{
get { return this.arguments; }
set { this.arguments = value; }
}
[DataMember(Name = "Activity")]
internal ActivityInfo SerializedActivity
{
get { return this.Activity; }
set { this.Activity = value; }
}
[DataMember(Name = "State")]
internal string SerializedState
{
get { return this.State; }
set { this.State = value; }
}
protected internal override TrackingRecord Clone()
{
return new ActivityStateRecord(this);
}
public override string ToString()
{
return string.Format(CultureInfo.CurrentCulture,
"ActivityStateRecord {{ {0}, Activity {{ {1} }}, State = {2} }}",
base.ToString(),
this.Activity.ToString(),
this.State);
}
internal IDictionary<string, object> GetVariables(ICollection<string> variables)
{
Dictionary<string, object> trackedVariables = null; // delay allocated through TrackData
ActivityInstance currentInstance = this.Activity.Instance;
if (currentInstance != null)
{
Activity currentElement = currentInstance.Activity;
Activity startActivity = currentInstance.Activity;
bool containsWildcard = variables.Contains("*");
//count defines how many items we can get in this lookup. It represents the maximum number of items that can be extracted,
//if * is specified, any other names specified are expected to be variables defined in scope, not in the activity itself.
//if a variable name in the activity is specified, the lookup continues through the variables in scope.
int count = containsWildcard ? currentElement.RuntimeVariables.Count + variables.Count - 1 : variables.Count;
IdSpace activityIdSpace = currentElement.MemberOf;
while (currentInstance != null)
{
//* only extracts variables of the current Activity and not variables in scope.
bool useWildCard = containsWildcard && startActivity == currentElement;
// we only track public Variables, not ImplementationVariables
for (int i = 0; i < currentElement.RuntimeVariables.Count; i++)
{
Variable variable = currentElement.RuntimeVariables[i];
if (TrackData(variable.Name, variable.Id, currentInstance, variables, useWildCard, ref trackedVariables))
{
if (trackedVariables.Count == count)
{
return new ReadOnlyDictionaryInternal<string, object>(trackedVariables);
}
}
}
bool foundNext = false;
while (!foundNext)
{
currentInstance = currentInstance.Parent;
if (currentInstance != null)
{
currentElement = currentInstance.Activity;
foundNext = currentElement.MemberOf.Equals(activityIdSpace);
}
else
{
// We set foundNext to true to get out of our loop.
foundNext = true;
}
}
}
}
if (trackedVariables == null)
{
return ActivityUtilities.EmptyParameters;
}
else
{
Fx.Assert(trackedVariables.Count > 0, "we should only allocate the dictionary if we're putting data in it");
return new ReadOnlyDictionaryInternal<string, object>(trackedVariables);
}
}
internal IDictionary<string, object> GetArguments(ICollection<string> arguments)
{
Dictionary<string, object> trackedArguments = null; // delay allocated through TrackData
ActivityInstance currentInstance = this.Activity.Instance;
if (currentInstance != null)
{
Activity currentElement = currentInstance.Activity;
bool containsWildcard = arguments.Contains("*");
int count = containsWildcard ? currentElement.RuntimeArguments.Count : arguments.Count;
bool isActivityStateExecuting = ActivityStates.Executing.Equals(this.State, StringComparison.Ordinal);
//look at arguments for this element.
for (int i = 0; i < currentElement.RuntimeArguments.Count; i++)
{
RuntimeArgument argument = currentElement.RuntimeArguments[i];
// OutArguments will always start with default(T), so there is no need to track them when state == Executing
if (isActivityStateExecuting && argument.Direction == ArgumentDirection.Out)
{
continue;
}
if (TrackData(argument.Name, argument.Id, currentInstance, arguments, containsWildcard, ref trackedArguments))
{
if (trackedArguments.Count == count)
{
break;
}
}
}
}
if (trackedArguments == null)
{
return ActivityUtilities.EmptyParameters;
}
else
{
Fx.Assert(trackedArguments.Count > 0, "we should only allocate the dictionary if we're putting data in it");
return new ReadOnlyDictionaryInternal<string, object>(trackedArguments);
}
}
bool TrackData(string name, int id, ActivityInstance currentInstance, ICollection<string> data, bool wildcard, ref Dictionary<string, object> trackedData)
{
if (wildcard || data.Contains(name))
{
Location location = currentInstance.Environment.GetSpecificLocation(id);
if (location != null)
{
if (trackedData == null)
{
trackedData = new Dictionary<string, object>(10);
}
string dataName = name ?? NameGenerator.Next();
trackedData[dataName] = location.Value;
if (TD.TrackingDataExtractedIsEnabled())
{
TD.TrackingDataExtracted(dataName, this.Activity.Name);
}
return true;
}
}
return false;
}
}
}

View File

@@ -0,0 +1,14 @@
//-----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
namespace System.Activities.Tracking
{
public static class ActivityStates
{
public const string Canceled = "Canceled";
public const string Closed = "Closed";
public const string Executing = "Executing";
public const string Faulted = "Faulted";
}
}

View File

@@ -0,0 +1,12 @@
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace System.Activities.Tracking
{
public sealed class BookmarkResumptionQuery : TrackingQuery
{
public string Name { get; set; }
}
}

View File

@@ -0,0 +1,145 @@
//-----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
namespace System.Activities.Tracking
{
using System;
using System.Globalization;
using System.Runtime.Serialization;
using System.Runtime;
[Fx.Tag.XamlVisible(false)]
[DataContract]
public sealed class BookmarkResumptionRecord : TrackingRecord
{
Guid bookmarkScope;
string bookmarkName;
object payload;
ActivityInfo owner;
internal BookmarkResumptionRecord(Guid instanceId, Bookmark bookmark, ActivityInstance ownerInstance, object payload)
: base(instanceId)
{
if (bookmark.Scope != null)
{
this.BookmarkScope = bookmark.Scope.Id;
}
if (bookmark.IsNamed)
{
this.BookmarkName = bookmark.Name;
}
this.Owner = new ActivityInfo(ownerInstance);
this.Payload = payload;
}
public BookmarkResumptionRecord(Guid instanceId, long recordNumber, Guid bookmarkScope, string bookmarkName, ActivityInfo owner)
: base(instanceId, recordNumber)
{
if (owner == null)
{
throw FxTrace.Exception.ArgumentNull("owner");
}
this.BookmarkScope = bookmarkScope;
this.BookmarkName = bookmarkName;
this.Owner = owner;
}
BookmarkResumptionRecord(BookmarkResumptionRecord record)
: base(record)
{
this.BookmarkScope = record.BookmarkScope;
this.Owner = record.Owner;
this.BookmarkName = record.BookmarkName;
this.Payload = record.Payload;
}
public Guid BookmarkScope
{
get
{
return bookmarkScope;
}
private set
{
this.bookmarkScope = value;
}
}
public string BookmarkName
{
get
{
return this.bookmarkName;
}
private set
{
this.bookmarkName = value;
}
}
public object Payload
{
get { return this.payload; }
internal set { this.payload = value; }
}
public ActivityInfo Owner
{
get
{
return this.owner;
}
private set
{
this.owner = value;
}
}
[DataMember(EmitDefaultValue = false, Name = "BookmarkScope")]
internal Guid SerializedBookmarkScope
{
get { return this.BookmarkScope; }
set { this.BookmarkScope = value; }
}
[DataMember(EmitDefaultValue = false, Name = "BookmarkName")]
internal string SerializedBookmarkName
{
get { return this.BookmarkName; }
set { this.BookmarkName = value; }
}
[DataMember(Name = "Payload")]
internal object SerializedPayload
{
get { return this.Payload; }
set { this.Payload = value; }
}
[DataMember(Name = "Owner")]
internal ActivityInfo SerializedOwner
{
get { return this.Owner; }
set { this.Owner = value; }
}
protected internal override TrackingRecord Clone()
{
return new BookmarkResumptionRecord(this);
}
public override string ToString()
{
return string.Format(CultureInfo.CurrentCulture,
"BookmarkResumptionRecord {{ {0}, BookmarkName = {1}, BookmarkScope = {2}, OwnerActivity {{ {3} }} }}",
base.ToString(),
this.BookmarkName ?? "<null>",
this.BookmarkScope,
this.Owner.ToString());
}
}
}

View File

@@ -0,0 +1,19 @@
//-----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
namespace System.Activities.Tracking
{
public sealed class CancelRequestedQuery : TrackingQuery
{
public CancelRequestedQuery()
{
this.ActivityName = "*";
this.ChildActivityName = "*";
}
public string ActivityName { get; set; }
public string ChildActivityName { get; set; }
}
}

View File

@@ -0,0 +1,107 @@
//-----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
namespace System.Activities.Tracking
{
using System;
using System.Runtime.Serialization;
using System.Runtime;
using System.Globalization;
[Fx.Tag.XamlVisible(false)]
[DataContract]
public sealed class CancelRequestedRecord : TrackingRecord
{
ActivityInfo activity;
ActivityInfo child;
internal CancelRequestedRecord(Guid instanceId, ActivityInstance instance, ActivityInstance child)
: base(instanceId)
{
Fx.Assert(child != null, "Child activity instance cannot be null.");
if (instance != null)
{
this.Activity = new ActivityInfo(instance);
}
this.Child = new ActivityInfo(child);
}
//parameter activity is null if the root activity is being cancelled.
public CancelRequestedRecord(
Guid instanceId,
long recordNumber,
ActivityInfo activity,
ActivityInfo child)
: base(instanceId, recordNumber)
{
if (child == null)
{
throw FxTrace.Exception.ArgumentNullOrEmpty("child");
}
this.Activity = activity;
this.Child = child;
}
CancelRequestedRecord(CancelRequestedRecord record)
: base(record)
{
this.Activity = record.Activity;
this.Child = record.Child;
}
public ActivityInfo Activity
{
get
{
return this.activity;
}
private set
{
this.activity = value;
}
}
public ActivityInfo Child
{
get
{
return this.child;
}
private set
{
this.child = value;
}
}
[DataMember(Name = "Activity")]
internal ActivityInfo SerializedActivity
{
get { return this.Activity; }
set { this.Activity = value; }
}
[DataMember(Name = "Child")]
internal ActivityInfo SerializedChild
{
get { return this.Child; }
set { this.Child = value; }
}
protected internal override TrackingRecord Clone()
{
return new CancelRequestedRecord(this);
}
public override string ToString()
{
return string.Format(CultureInfo.CurrentCulture,
"CancelRequestedRecord {{ {0}, Activity {{ {1} }}, ChildActivity {{ {2} }} }}",
base.ToString(),
this.Activity != null ? this.Activity.ToString() : "<null>",
this.Child.ToString());
}
}
}

View File

@@ -0,0 +1,26 @@
//-----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
namespace System.Activities.Tracking
{
public class CustomTrackingQuery : TrackingQuery
{
public CustomTrackingQuery()
{
}
public string Name
{
get;
set;
}
public string ActivityName
{
get;
set;
}
}
}

View File

@@ -0,0 +1,124 @@
//-----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
namespace System.Activities.Tracking
{
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization;
using System.Runtime;
using System.Diagnostics;
using System.Globalization;
[DataContract]
[Fx.Tag.XamlVisible(false)]
public class CustomTrackingRecord : TrackingRecord
{
IDictionary<string, object> data;
string name;
ActivityInfo activity;
public CustomTrackingRecord(string name)
: this(name, TraceLevel.Info)
{
}
public CustomTrackingRecord(string name, TraceLevel level)
: this(Guid.Empty, name, level)
{
}
public CustomTrackingRecord(Guid instanceId, string name, TraceLevel level)
: base(instanceId)
{
if (string.IsNullOrEmpty(name))
{
throw FxTrace.Exception.ArgumentNull("name");
}
this.Name = name;
this.Level = level;
}
protected CustomTrackingRecord(CustomTrackingRecord record)
: base(record)
{
this.Name = record.Name;
this.Activity = record.Activity;
if (record.data != null && record.data.Count > 0)
{
foreach (KeyValuePair<string, object> item in record.data)
{
this.Data.Add(item);
}
}
}
public string Name
{
get
{
return this.name;
}
private set
{
this.name = value;
}
}
public ActivityInfo Activity
{
get { return this.activity; }
internal set { this.activity = value; }
}
public IDictionary<string, object> Data
{
get
{
if (this.data == null)
{
this.data = new Dictionary<string, object>();
}
return this.data;
}
}
[DataMember(EmitDefaultValue = false, Name = "data")]
internal IDictionary<string, object> SerializedData
{
get { return this.data; }
set { this.data = value; }
}
[DataMember(Name = "Name")]
internal string SerializedName
{
get { return this.Name; }
set { this.Name = value; }
}
[DataMember(Name = "Activity")]
internal ActivityInfo SerializedActivity
{
get { return this.Activity; }
set { this.Activity = value; }
}
protected internal override TrackingRecord Clone()
{
return new CustomTrackingRecord(this);
}
public override string ToString()
{
return string.Format(CultureInfo.InvariantCulture,
"CustomTrackingRecord {{ {0}, Name={1}, Activity {{ {2} }}, Level = {3} }}",
base.ToString(),
this.Name,
this.Activity == null ? "<null>" : this.Activity.ToString(),
this.Level);
}
}
}

View File

@@ -0,0 +1,19 @@
//-----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
namespace System.Activities.Tracking
{
public sealed class FaultPropagationQuery : TrackingQuery
{
public FaultPropagationQuery()
{
this.FaultSourceActivityName = "*";
this.FaultHandlerActivityName = "*";
}
public string FaultHandlerActivityName { get; set; }
public string FaultSourceActivityName { get; set; }
}
}

View File

@@ -0,0 +1,160 @@
//-----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
namespace System.Activities.Tracking
{
using System;
using System.Runtime.Serialization;
using System.Runtime;
using System.Diagnostics;
using System.Globalization;
[Fx.Tag.XamlVisible(false)]
[DataContract]
public sealed class FaultPropagationRecord : TrackingRecord
{
ActivityInfo faultSource;
ActivityInfo faultHandler;
bool isFaultSource;
Exception fault;
internal FaultPropagationRecord(Guid instanceId, ActivityInstance source, ActivityInstance faultHandler, bool isFaultSource, Exception fault)
: base(instanceId)
{
Fx.Assert(source != null, "Fault source cannot be null");
this.FaultSource = new ActivityInfo(source);
if (faultHandler != null)
{
this.FaultHandler = new ActivityInfo(faultHandler);
}
this.IsFaultSource = isFaultSource;
this.Fault = fault;
this.Level = TraceLevel.Warning;
}
//parameter faultHandler is null if there are no handlers
public FaultPropagationRecord(
Guid instanceId,
long recordNumber,
ActivityInfo faultSource,
ActivityInfo faultHandler,
bool isFaultSource,
Exception fault)
: base(instanceId, recordNumber)
{
if (faultSource == null)
{
throw FxTrace.Exception.ArgumentNullOrEmpty("faultSource");
}
this.FaultSource = faultSource;
this.FaultHandler = faultHandler;
this.IsFaultSource = isFaultSource;
this.Fault = fault;
this.Level = TraceLevel.Warning;
}
FaultPropagationRecord(FaultPropagationRecord record)
: base(record)
{
this.FaultSource = record.FaultSource;
this.FaultHandler = record.FaultHandler;
this.Fault = record.Fault;
this.IsFaultSource = record.IsFaultSource;
}
public ActivityInfo FaultSource
{
get
{
return this.faultSource;
}
private set
{
this.faultSource = value;
}
}
public ActivityInfo FaultHandler
{
get
{
return this.faultHandler;
}
private set
{
this.faultHandler = value;
}
}
public bool IsFaultSource
{
get
{
return this.isFaultSource;
}
private set
{
this.isFaultSource = value;
}
}
public Exception Fault
{
get
{
return this.fault;
}
private set
{
this.fault = value;
}
}
[DataMember(Name = "FaultSource")]
internal ActivityInfo SerializedFaultSource
{
get { return this.FaultSource; }
set { this.FaultSource = value; }
}
[DataMember(Name = "FaultHandler")]
internal ActivityInfo SerializedFaultHandler
{
get { return this.FaultHandler; }
set { this.FaultHandler = value; }
}
[DataMember(EmitDefaultValue = false, Name = "IsFaultSource")]
internal bool SerializedIsFaultSource
{
get { return this.IsFaultSource; }
set { this.IsFaultSource = value; }
}
[DataMember(Name = "Fault")]
internal Exception SerializedFault
{
get { return this.Fault; }
set { this.Fault = value; }
}
protected internal override TrackingRecord Clone()
{
return new FaultPropagationRecord(this);
}
public override string ToString()
{
return string.Format(CultureInfo.CurrentCulture,
"FaultPropagationRecord {{ {0}, FaultSource {{ {1} }}, FaultHandler {{ {2} }}, IsFaultSource = {3} }}",
base.ToString(),
this.FaultSource.ToString(),
this.FaultHandler != null ? this.FaultHandler.ToString() : "<null>",
this.IsFaultSource);
}
}
}

View File

@@ -0,0 +1,12 @@
//------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------
namespace System.Activities.Tracking
{
public enum ImplementationVisibility
{
RootScope,
All
}
}

View File

@@ -0,0 +1,86 @@
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace System.Activities.Tracking
{
using System;
using System.Runtime;
public abstract class TrackingParticipant
{
protected TrackingParticipant()
{
}
public virtual TrackingProfile TrackingProfile
{
get;
set;
}
[Fx.Tag.InheritThrows(From = "Track", FromDeclaringType = typeof(TrackingParticipant))]
protected internal virtual IAsyncResult BeginTrack(TrackingRecord record, TimeSpan timeout, AsyncCallback callback, object state)
{
return new TrackAsyncResult(this, record, timeout, callback, state);
}
[Fx.Tag.InheritThrows(From = "Track", FromDeclaringType = typeof(TrackingParticipant))]
protected internal virtual void EndTrack(IAsyncResult result)
{
TrackAsyncResult.End(result);
}
[Fx.Tag.Throws(typeof(Exception), "extensibility point")]
[Fx.Tag.Throws.Timeout("Tracking data could not be saved before the timeout")]
protected internal abstract void Track(TrackingRecord record, TimeSpan timeout);
class TrackAsyncResult : AsyncResult
{
static Action<object> asyncExecuteTrack = new Action<object>(ExecuteTrack);
TrackingParticipant participant;
TrackingRecord record;
TimeSpan timeout;
public TrackAsyncResult(TrackingParticipant participant, TrackingRecord record, TimeSpan timeout, AsyncCallback callback, object state)
: base(callback, state)
{
this.participant = participant;
this.record = record;
this.timeout = timeout;
ActionItem.Schedule(asyncExecuteTrack, this);
}
public static void End(IAsyncResult result)
{
AsyncResult.End<TrackAsyncResult>(result);
}
static void ExecuteTrack(object state)
{
TrackAsyncResult thisPtr = (TrackAsyncResult)state;
thisPtr.TrackCore();
}
void TrackCore()
{
Exception participantException = null;
try
{
this.participant.Track(this.record, this.timeout);
}
catch (Exception exception)
{
if (Fx.IsFatal(exception))
{
throw;
}
participantException = exception;
}
base.Complete(false, participantException);
}
}
}
}

View File

@@ -0,0 +1,41 @@
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace System.Activities.Tracking
{
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Markup;
[ContentProperty("Queries")]
public class TrackingProfile
{
Collection<TrackingQuery> queries;
public TrackingProfile()
{
}
[DefaultValue(null)]
public string Name { get; set; }
[DefaultValue(ImplementationVisibility.RootScope)]
public ImplementationVisibility ImplementationVisibility { get; set; }
[DefaultValue(null)]
public string ActivityDefinitionId { get; set; }
public Collection<TrackingQuery> Queries
{
get
{
if (this.queries == null)
{
this.queries = new Collection<TrackingQuery>();
}
return this.queries;
}
}
}
}

View File

@@ -0,0 +1,428 @@
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace System.Activities.Tracking
{
using System;
using System.Activities;
using System.Collections;
using System.Collections.Generic;
using System.Runtime;
class TrackingProvider
{
List<TrackingParticipant> trackingParticipants;
Dictionary<TrackingParticipant, RuntimeTrackingProfile> profileSubscriptions;
IList<TrackingRecord> pendingTrackingRecords;
Activity definition;
bool filterValuesSetExplicitly;
Hashtable activitySubscriptions;
long nextTrackingRecordNumber;
public TrackingProvider(Activity definition)
{
this.definition = definition;
this.ShouldTrack = true;
this.ShouldTrackActivityStateRecords = true;
this.ShouldTrackActivityStateRecordsExecutingState = true;
this.ShouldTrackActivityStateRecordsClosedState = true;
this.ShouldTrackBookmarkResumptionRecords = true;
this.ShouldTrackActivityScheduledRecords = true;
this.ShouldTrackCancelRequestedRecords = true;
this.ShouldTrackFaultPropagationRecords = true;
this.ShouldTrackWorkflowInstanceRecords = true;
}
public bool HasPendingRecords
{
get
{
return (this.pendingTrackingRecords != null && this.pendingTrackingRecords.Count > 0)
|| !this.filterValuesSetExplicitly;
}
}
public long NextTrackingRecordNumber
{
get
{
return this.nextTrackingRecordNumber;
}
}
public bool ShouldTrack
{
get;
private set;
}
public bool ShouldTrackWorkflowInstanceRecords
{
get;
private set;
}
public bool ShouldTrackBookmarkResumptionRecords
{
get;
private set;
}
public bool ShouldTrackActivityScheduledRecords
{
get;
private set;
}
public bool ShouldTrackActivityStateRecords
{
get;
private set;
}
public bool ShouldTrackActivityStateRecordsExecutingState
{
get;
private set;
}
public bool ShouldTrackActivityStateRecordsClosedState
{
get;
private set;
}
public bool ShouldTrackCancelRequestedRecords
{
get;
private set;
}
public bool ShouldTrackFaultPropagationRecords
{
get;
private set;
}
long GetNextRecordNumber()
{
// We blindly do this. On the off chance that a workflow causes it to loop back
// around it shouldn't cause the workflow to fail and the tracking information
// will still be salvagable.
return this.nextTrackingRecordNumber++;
}
public void OnDeserialized(long nextTrackingRecordNumber)
{
this.nextTrackingRecordNumber = nextTrackingRecordNumber;
}
public void AddRecord(TrackingRecord record)
{
if (this.pendingTrackingRecords == null)
{
this.pendingTrackingRecords = new List<TrackingRecord>();
}
record.RecordNumber = GetNextRecordNumber();
this.pendingTrackingRecords.Add(record);
}
public void AddParticipant(TrackingParticipant participant)
{
if (this.trackingParticipants == null)
{
this.trackingParticipants = new List<TrackingParticipant>();
this.profileSubscriptions = new Dictionary<TrackingParticipant, RuntimeTrackingProfile>();
}
this.trackingParticipants.Add(participant);
}
public void ClearParticipants()
{
this.trackingParticipants = null;
this.profileSubscriptions = null;
}
public void FlushPendingRecords(TimeSpan timeout)
{
try
{
if (this.HasPendingRecords)
{
TimeoutHelper helper = new TimeoutHelper(timeout);
for (int i = 0; i < this.trackingParticipants.Count; i++)
{
TrackingParticipant participant = this.trackingParticipants[i];
RuntimeTrackingProfile runtimeProfile = GetRuntimeTrackingProfile(participant);
// HasPendingRecords can be true for the sole purpose of populating our initial profiles, so check again here
if (this.pendingTrackingRecords != null)
{
for (int j = 0; j < this.pendingTrackingRecords.Count; j++)
{
TrackingRecord currentRecord = this.pendingTrackingRecords[j];
Fx.Assert(currentRecord != null, "We should never come across a null context.");
TrackingRecord preparedRecord = null;
bool shouldClone = this.trackingParticipants.Count > 1;
if (runtimeProfile == null)
{
preparedRecord = shouldClone ? currentRecord.Clone() : currentRecord;
}
else
{
preparedRecord = runtimeProfile.Match(currentRecord, shouldClone);
}
if (preparedRecord != null)
{
participant.Track(preparedRecord, helper.RemainingTime());
if (TD.TrackingRecordRaisedIsEnabled())
{
TD.TrackingRecordRaised(preparedRecord.ToString(), participant.GetType().ToString());
}
}
}
}
}
}
}
finally
{
// Note that if we fail to track yet the workflow manages to recover
// we will attempt to track those records again.
ClearPendingRecords();
}
}
public IAsyncResult BeginFlushPendingRecords(TimeSpan timeout, AsyncCallback callback, object state)
{
return new FlushPendingRecordsAsyncResult(this, timeout, callback, state);
}
public void EndFlushPendingRecords(IAsyncResult result)
{
FlushPendingRecordsAsyncResult.End(result);
}
public bool ShouldTrackActivity(string name)
{
return this.activitySubscriptions == null || this.activitySubscriptions.ContainsKey(name) || this.activitySubscriptions.ContainsKey("*");
}
void ClearPendingRecords()
{
if (this.pendingTrackingRecords != null)
{
//since the number of records is small, it is faster to remove from end than to call List.Clear
for (int i = this.pendingTrackingRecords.Count - 1; i >= 0; i--)
{
this.pendingTrackingRecords.RemoveAt(i);
}
}
}
RuntimeTrackingProfile GetRuntimeTrackingProfile(TrackingParticipant participant)
{
TrackingProfile profile;
RuntimeTrackingProfile runtimeProfile;
if (!this.profileSubscriptions.TryGetValue(participant, out runtimeProfile))
{
profile = participant.TrackingProfile;
if (profile != null)
{
runtimeProfile = RuntimeTrackingProfile.GetRuntimeTrackingProfile(profile, this.definition);
Merge(runtimeProfile.Filter);
//Add the names to the list of activities that have subscriptions. This provides a quick lookup
//for the runtime to check if a TrackingRecord has to be created.
IEnumerable<string> activityNames = runtimeProfile.GetSubscribedActivityNames();
if (activityNames != null)
{
if (this.activitySubscriptions == null)
{
this.activitySubscriptions = new Hashtable();
}
foreach (string name in activityNames)
{
if (this.activitySubscriptions[name] == null)
{
this.activitySubscriptions[name] = name;
}
}
}
}
else
{
//for null profiles, set all the filter flags.
Merge(new TrackingRecordPreFilter(true));
}
this.profileSubscriptions.Add(participant, runtimeProfile);
}
return runtimeProfile;
}
void Merge(TrackingRecordPreFilter filter)
{
if (!this.filterValuesSetExplicitly)
{
// This it the first filter we are merging
this.filterValuesSetExplicitly = true;
this.ShouldTrackActivityStateRecordsExecutingState = filter.TrackActivityStateRecordsExecutingState;
this.ShouldTrackActivityScheduledRecords = filter.TrackActivityScheduledRecords;
this.ShouldTrackActivityStateRecords = filter.TrackActivityStateRecords;
this.ShouldTrackActivityStateRecordsClosedState = filter.TrackActivityStateRecordsClosedState;
this.ShouldTrackBookmarkResumptionRecords = filter.TrackBookmarkResumptionRecords;
this.ShouldTrackCancelRequestedRecords = filter.TrackCancelRequestedRecords;
this.ShouldTrackFaultPropagationRecords = filter.TrackFaultPropagationRecords;
this.ShouldTrackWorkflowInstanceRecords = filter.TrackWorkflowInstanceRecords;
}
else
{
this.ShouldTrackActivityStateRecordsExecutingState |= filter.TrackActivityStateRecordsExecutingState;
this.ShouldTrackActivityScheduledRecords |= filter.TrackActivityScheduledRecords;
this.ShouldTrackActivityStateRecords |= filter.TrackActivityStateRecords;
this.ShouldTrackActivityStateRecordsClosedState |= filter.TrackActivityStateRecordsClosedState;
this.ShouldTrackBookmarkResumptionRecords |= filter.TrackBookmarkResumptionRecords;
this.ShouldTrackCancelRequestedRecords |= filter.TrackCancelRequestedRecords;
this.ShouldTrackFaultPropagationRecords |= filter.TrackFaultPropagationRecords;
this.ShouldTrackWorkflowInstanceRecords |= filter.TrackWorkflowInstanceRecords;
}
}
class FlushPendingRecordsAsyncResult : AsyncResult
{
static AsyncCompletion trackingCompleteCallback = new AsyncCompletion(OnTrackingComplete);
int currentRecord;
int currentParticipant;
TrackingProvider provider;
TimeoutHelper timeoutHelper;
public FlushPendingRecordsAsyncResult(TrackingProvider provider, TimeSpan timeout, AsyncCallback callback, object state)
: base(callback, state)
{
this.provider = provider;
this.timeoutHelper = new TimeoutHelper(timeout);
if (RunLoop())
{
Complete(true);
}
}
bool RunLoop()
{
if (this.provider.HasPendingRecords)
{
while (this.currentParticipant < this.provider.trackingParticipants.Count)
{
TrackingParticipant participant = this.provider.trackingParticipants[this.currentParticipant];
RuntimeTrackingProfile runtimeProfile = this.provider.GetRuntimeTrackingProfile(participant);
if (this.provider.pendingTrackingRecords != null)
{
while (this.currentRecord < this.provider.pendingTrackingRecords.Count)
{
bool completedSynchronously = PostTrackingRecord(participant, runtimeProfile);
if (!completedSynchronously)
{
return false;
}
}
}
this.currentRecord = 0;
this.currentParticipant++;
}
}
// We've now tracked all of the records.
this.provider.ClearPendingRecords();
return true;
}
static bool OnTrackingComplete(IAsyncResult result)
{
Fx.Assert(!result.CompletedSynchronously, "TrackingAsyncResult.OnTrackingComplete should not get called with a result that is CompletedSynchronously");
FlushPendingRecordsAsyncResult thisPtr = (FlushPendingRecordsAsyncResult)result.AsyncState;
TrackingParticipant participant = thisPtr.provider.trackingParticipants[thisPtr.currentParticipant];
bool isSuccessful = false;
try
{
participant.EndTrack(result);
isSuccessful = true;
}
finally
{
if (!isSuccessful)
{
thisPtr.provider.ClearPendingRecords();
}
}
return thisPtr.RunLoop();
}
bool PostTrackingRecord(TrackingParticipant participant, RuntimeTrackingProfile runtimeProfile)
{
TrackingRecord originalRecord = this.provider.pendingTrackingRecords[this.currentRecord];
this.currentRecord++;
bool isSuccessful = false;
try
{
TrackingRecord preparedRecord = null;
bool shouldClone = this.provider.trackingParticipants.Count > 1;
if (runtimeProfile == null)
{
preparedRecord = shouldClone ? originalRecord.Clone() : originalRecord;
}
else
{
preparedRecord = runtimeProfile.Match(originalRecord, shouldClone);
}
if (preparedRecord != null)
{
IAsyncResult result = participant.BeginTrack(preparedRecord, this.timeoutHelper.RemainingTime(), PrepareAsyncCompletion(trackingCompleteCallback), this);
if (TD.TrackingRecordRaisedIsEnabled())
{
TD.TrackingRecordRaised(preparedRecord.ToString(), participant.GetType().ToString());
}
if (result.CompletedSynchronously)
{
participant.EndTrack(result);
}
else
{
isSuccessful = true;
return false;
}
}
isSuccessful = true;
}
finally
{
if (!isSuccessful)
{
this.provider.ClearPendingRecords();
}
}
return true;
}
public static void End(IAsyncResult result)
{
AsyncResult.End<FlushPendingRecordsAsyncResult>(result);
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More