You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
@@ -0,0 +1,329 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace System.Activities.Runtime
|
||||
{
|
||||
using System;
|
||||
using System.Activities.Hosting;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
[DataContract(Name = XD.Runtime.BookmarkManager, Namespace = XD.Runtime.Namespace)]
|
||||
class BookmarkManager
|
||||
{
|
||||
long nextId;
|
||||
|
||||
Dictionary<Bookmark, BookmarkCallbackWrapper> bookmarks;
|
||||
|
||||
BookmarkScope scope;
|
||||
|
||||
BookmarkScopeHandle scopeHandle;
|
||||
|
||||
public BookmarkManager()
|
||||
{
|
||||
this.nextId = 1;
|
||||
}
|
||||
|
||||
internal BookmarkManager(BookmarkScope scope, BookmarkScopeHandle scopeHandle)
|
||||
: this()
|
||||
{
|
||||
this.scope = scope;
|
||||
this.scopeHandle = scopeHandle;
|
||||
}
|
||||
|
||||
|
||||
public bool HasBookmarks
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.bookmarks != null && this.bookmarks.Count > 0;
|
||||
}
|
||||
}
|
||||
|
||||
[DataMember(Name = "nextId")]
|
||||
internal long SerializedNextId
|
||||
{
|
||||
get { return this.nextId; }
|
||||
set { this.nextId = value; }
|
||||
}
|
||||
|
||||
[DataMember(EmitDefaultValue = false, Name = "bookmarks")]
|
||||
internal Dictionary<Bookmark, BookmarkCallbackWrapper> SerializedBookmarks
|
||||
{
|
||||
get { return this.bookmarks; }
|
||||
set { this.bookmarks = value; }
|
||||
}
|
||||
|
||||
[DataMember(EmitDefaultValue = false, Name = "scope")]
|
||||
internal BookmarkScope SerializedScope
|
||||
{
|
||||
get { return this.scope; }
|
||||
set { this.scope = value; }
|
||||
}
|
||||
|
||||
[DataMember(EmitDefaultValue = false, Name = "scopeHandle")]
|
||||
internal BookmarkScopeHandle SerializedScopeHandle
|
||||
{
|
||||
get { return this.scopeHandle; }
|
||||
set { this.scopeHandle = value; }
|
||||
}
|
||||
|
||||
public Bookmark CreateBookmark(string name, BookmarkCallback callback, ActivityInstance owningInstance, BookmarkOptions options)
|
||||
{
|
||||
Bookmark toAdd = new Bookmark(name);
|
||||
|
||||
if (this.bookmarks != null && this.bookmarks.ContainsKey(toAdd))
|
||||
{
|
||||
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.BookmarkAlreadyExists(name)));
|
||||
}
|
||||
|
||||
AddBookmark(toAdd, callback, owningInstance, options);
|
||||
//Regular bookmarks are never important
|
||||
UpdateAllExclusiveHandles(toAdd, owningInstance);
|
||||
|
||||
return toAdd;
|
||||
}
|
||||
|
||||
public Bookmark CreateBookmark(BookmarkCallback callback, ActivityInstance owningInstance, BookmarkOptions options)
|
||||
{
|
||||
Fx.Assert(this.scope == null, "We only support named bookmarks within bookmark scopes right now.");
|
||||
|
||||
Bookmark bookmark = Bookmark.Create(GetNextBookmarkId());
|
||||
AddBookmark(bookmark, callback, owningInstance, options);
|
||||
//Regular bookmarks are never important
|
||||
UpdateAllExclusiveHandles(bookmark, owningInstance);
|
||||
|
||||
return bookmark;
|
||||
}
|
||||
|
||||
void UpdateAllExclusiveHandles(Bookmark bookmark, ActivityInstance owningInstance)
|
||||
{
|
||||
Fx.Assert(bookmark != null, "Invalid call to UpdateAllExclusiveHandles. Bookmark was null");
|
||||
Fx.Assert(owningInstance != null, "Invalid call to UpdateAllExclusiveHandles. ActivityInstance was null");
|
||||
|
||||
if (owningInstance.PropertyManager == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!owningInstance.PropertyManager.HasExclusiveHandlesInScope)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List<ExclusiveHandle> handles = owningInstance.PropertyManager.FindAll<ExclusiveHandle>();
|
||||
|
||||
if (handles == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < handles.Count; i++)
|
||||
{
|
||||
ExclusiveHandle handle = handles[i];
|
||||
if (handle != null)
|
||||
{
|
||||
if (this.scopeHandle != null)
|
||||
{
|
||||
bool found = false;
|
||||
foreach (BookmarkScopeHandle bookmarkScopeHandle in handle.RegisteredBookmarkScopes)
|
||||
{
|
||||
if (bookmarkScopeHandle == this.scopeHandle)
|
||||
{
|
||||
handle.AddToImportantBookmarks(bookmark);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
handle.AddToUnimportantBookmarks(bookmark);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
handle.AddToUnimportantBookmarks(bookmark);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Bookmark GenerateTempBookmark()
|
||||
{
|
||||
return Bookmark.Create(GetNextBookmarkId());
|
||||
}
|
||||
|
||||
void AddBookmark(Bookmark bookmark, BookmarkCallback callback, ActivityInstance owningInstance, BookmarkOptions options)
|
||||
{
|
||||
if (this.bookmarks == null)
|
||||
{
|
||||
this.bookmarks = new Dictionary<Bookmark, BookmarkCallbackWrapper>(Bookmark.Comparer);
|
||||
}
|
||||
|
||||
bookmark.Scope = this.scope;
|
||||
|
||||
BookmarkCallbackWrapper bookmarkCallbackWrapper = new BookmarkCallbackWrapper(callback, owningInstance, options)
|
||||
{
|
||||
Bookmark = bookmark
|
||||
};
|
||||
this.bookmarks.Add(bookmark, bookmarkCallbackWrapper);
|
||||
|
||||
owningInstance.AddBookmark(bookmark, options);
|
||||
|
||||
if (TD.CreateBookmarkIsEnabled())
|
||||
{
|
||||
TD.CreateBookmark(owningInstance.Activity.GetType().ToString(), owningInstance.Activity.DisplayName, owningInstance.Id, ActivityUtilities.GetTraceString(bookmark), ActivityUtilities.GetTraceString((BookmarkScope)bookmark.Scope));
|
||||
}
|
||||
}
|
||||
|
||||
long GetNextBookmarkId()
|
||||
{
|
||||
if (this.nextId == long.MaxValue)
|
||||
{
|
||||
throw FxTrace.Exception.AsError(new NotSupportedException(SR.OutOfInternalBookmarks));
|
||||
}
|
||||
|
||||
long result = this.nextId;
|
||||
this.nextId++;
|
||||
return result;
|
||||
}
|
||||
|
||||
// This method translates from a bookmark that we may have received from the outside world (IE - new Bookmark(someName))
|
||||
// to our internal Bookmark object. This is necessary because we use bookmark objects as the key to our dictionary
|
||||
// (hence our ability to resolve an externally created one), but we keep a lot of important information on our internal
|
||||
// instance of that bookmark. We must always perform this translation when doing exclusive handle housekeeping.
|
||||
public bool TryGetBookmarkFromInternalList(Bookmark bookmark, out Bookmark internalBookmark, out BookmarkCallbackWrapper callbackWrapper)
|
||||
{
|
||||
internalBookmark = null;
|
||||
callbackWrapper = null;
|
||||
if (this.bookmarks == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
BookmarkCallbackWrapper wrapper;
|
||||
if (this.bookmarks.TryGetValue(bookmark, out wrapper))
|
||||
{
|
||||
internalBookmark = wrapper.Bookmark;
|
||||
callbackWrapper = wrapper;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public BookmarkResumptionResult TryGenerateWorkItem(ActivityExecutor executor, bool isExternal, ref Bookmark bookmark, object value, ActivityInstance isolationInstance, out ActivityExecutionWorkItem workItem)
|
||||
{
|
||||
Bookmark internalBookmark = null;
|
||||
BookmarkCallbackWrapper callbackWrapper = null;
|
||||
if (!this.TryGetBookmarkFromInternalList(bookmark, out internalBookmark, out callbackWrapper))
|
||||
{
|
||||
workItem = null;
|
||||
return BookmarkResumptionResult.NotFound;
|
||||
}
|
||||
|
||||
bookmark = internalBookmark;
|
||||
if (!ActivityUtilities.IsInScope(callbackWrapper.ActivityInstance, isolationInstance))
|
||||
{
|
||||
workItem = null;
|
||||
|
||||
// We know about the bookmark, but we can't resume it yet
|
||||
return BookmarkResumptionResult.NotReady;
|
||||
}
|
||||
|
||||
workItem = callbackWrapper.CreateWorkItem(executor, isExternal, bookmark, value);
|
||||
|
||||
if (!BookmarkOptionsHelper.SupportsMultipleResumes(callbackWrapper.Options))
|
||||
{
|
||||
// cleanup bookmark on resumption unless the user opts into multi-resume
|
||||
Remove(bookmark, callbackWrapper);
|
||||
}
|
||||
|
||||
return BookmarkResumptionResult.Success;
|
||||
}
|
||||
|
||||
public void PopulateBookmarkInfo(List<BookmarkInfo> bookmarks)
|
||||
{
|
||||
Fx.Assert(this.HasBookmarks, "Should only be called if this actually has bookmarks.");
|
||||
|
||||
foreach (KeyValuePair<Bookmark, BookmarkCallbackWrapper> bookmarkEntry in this.bookmarks)
|
||||
{
|
||||
if (bookmarkEntry.Key.IsNamed)
|
||||
{
|
||||
bookmarks.Add(bookmarkEntry.Key.GenerateBookmarkInfo(bookmarkEntry.Value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No need to translate using TryGetBookmarkFromInternalList because we already have
|
||||
// internal instances since this call comes from bookmarks hanging off of the
|
||||
// ActivityInstance and not from an external source
|
||||
public void PurgeBookmarks(Bookmark singleBookmark, IList<Bookmark> multipleBookmarks)
|
||||
{
|
||||
if (singleBookmark != null)
|
||||
{
|
||||
PurgeSingleBookmark(singleBookmark);
|
||||
}
|
||||
else
|
||||
{
|
||||
Fx.Assert(multipleBookmarks != null, "caller should never pass null");
|
||||
for (int i = 0; i < multipleBookmarks.Count; i++)
|
||||
{
|
||||
Bookmark bookmark = multipleBookmarks[i];
|
||||
PurgeSingleBookmark(bookmark);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void PurgeSingleBookmark(Bookmark bookmark)
|
||||
{
|
||||
Fx.Assert(this.bookmarks.ContainsKey(bookmark) && object.ReferenceEquals(bookmark, this.bookmarks[bookmark].Bookmark), "Something went wrong with our housekeeping - it must exist and must be our intenral reference");
|
||||
UpdateExclusiveHandleList(bookmark);
|
||||
this.bookmarks.Remove(bookmark);
|
||||
}
|
||||
|
||||
public bool Remove(Bookmark bookmark, ActivityInstance instanceAttemptingRemove)
|
||||
{
|
||||
// We need to translate to our internal instance of the bookmark. See TryGetBookmarkFromInternalList
|
||||
// for more details.
|
||||
BookmarkCallbackWrapper callbackWrapper;
|
||||
Bookmark internalBookmark;
|
||||
if (TryGetBookmarkFromInternalList(bookmark, out internalBookmark, out callbackWrapper))
|
||||
{
|
||||
if (callbackWrapper.ActivityInstance != instanceAttemptingRemove)
|
||||
{
|
||||
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.OnlyBookmarkOwnerCanRemove));
|
||||
}
|
||||
|
||||
Remove(internalBookmark, callbackWrapper);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Remove(Bookmark bookmark, BookmarkCallbackWrapper callbackWrapper)
|
||||
{
|
||||
callbackWrapper.ActivityInstance.RemoveBookmark(bookmark, callbackWrapper.Options);
|
||||
UpdateExclusiveHandleList(bookmark);
|
||||
this.bookmarks.Remove(bookmark);
|
||||
}
|
||||
|
||||
void UpdateExclusiveHandleList(Bookmark bookmark)
|
||||
{
|
||||
if (bookmark.ExclusiveHandles != null)
|
||||
{
|
||||
for (int i = 0; i < bookmark.ExclusiveHandles.Count; i++)
|
||||
{
|
||||
ExclusiveHandle handle = bookmark.ExclusiveHandles[i];
|
||||
Fx.Assert(handle != null, "Internal error.. ExclusiveHandle was null");
|
||||
handle.RemoveBookmark(bookmark);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user