private static void UpdateKeyData(InstancePersistenceContext context, SaveWorkflowCommand saveWorkflowCommand) { InstanceView instanceView = context.InstanceView; foreach (KeyValuePair <Guid, IDictionary <XName, InstanceValue> > pair in saveWorkflowCommand.InstanceKeysToAssociate) { if (!instanceView.InstanceKeys.ContainsKey(pair.Key)) { context.AssociatedInstanceKey(pair.Key); if (pair.Value != null) { foreach (KeyValuePair <XName, InstanceValue> pair2 in pair.Value) { context.WroteInstanceKeyMetadataValue(pair.Key, pair2.Key, pair2.Value); } } } } foreach (Guid guid in saveWorkflowCommand.InstanceKeysToComplete) { InstanceKeyView view2; if (instanceView.InstanceKeys.TryGetValue(guid, out view2) && (view2.InstanceKeyState != InstanceKeyState.Completed)) { context.CompletedInstanceKey(guid); } } foreach (Guid guid2 in saveWorkflowCommand.InstanceKeysToFree) { InstanceKeyView view3; if (instanceView.InstanceKeys.TryGetValue(guid2, out view3)) { context.UnassociatedInstanceKey(guid2); } } foreach (KeyValuePair <Guid, IDictionary <XName, InstanceValue> > pair3 in saveWorkflowCommand.InstanceKeyMetadataChanges) { if (pair3.Value != null) { foreach (KeyValuePair <XName, InstanceValue> pair4 in pair3.Value) { context.WroteInstanceKeyMetadataValue(pair3.Key, pair4.Key, pair4.Value); } } } if (saveWorkflowCommand.CompleteInstance) { foreach (KeyValuePair <Guid, InstanceKeyView> pair5 in instanceView.InstanceKeys) { if ((pair5.Value != null) && (pair5.Value.InstanceKeyState == InstanceKeyState.Associated)) { context.CompletedInstanceKey(pair5.Key); } } } }
private long ProcessSaveCommand(InstancePersistenceContext context, SaveWorkflowCommand command) { Owner owner = CheckOwner(context, command.Name); Instance instance = PersistenceItemManager.Load <Instance>(context.InstanceView.InstanceId); if (instance == null) { // Checking instance.Owner is like an InstanceLockQueryResult. context.QueriedInstanceStore(new InstanceLockQueryResult(context.InstanceView.InstanceId, Guid.Empty)); if (context.InstanceView.IsBoundToLock) { context.InstanceHandle.Free(); throw new InstanceLockLostException(command.Name, context.InstanceView.InstanceId); } instance = new Instance() { Version = 1, Id = context.InstanceView.InstanceId, Owner = context.InstanceView.InstanceOwner.InstanceOwnerId, Metadata = new PropertyBag() }; PersistenceItemManager.SaveToFile <Instance>(instance); context.BindAcquiredLock(1); } else { // Checking instance.Owner is like an InstanceLockQueryResult. context.QueriedInstanceStore(new InstanceLockQueryResult(context.InstanceView.InstanceId, instance.Owner)); if (instance.State == InstanceState.Completed) { throw new InstanceCompleteException(command.Name, context.InstanceView.InstanceId); } if (instance.Owner == Guid.Empty) { if (context.InstanceView.IsBoundToLock) { context.InstanceHandle.Free(); throw new InstanceLockLostException(command.Name, context.InstanceView.InstanceId); } instance.Version++; instance.Owner = context.InstanceView.InstanceOwner.InstanceOwnerId; PersistenceItemManager.SaveToFile <Instance>(instance); context.BindAcquiredLock(instance.Version); } else { if (instance.Owner != context.InstanceView.InstanceOwner.InstanceOwnerId) { if (context.InstanceView.IsBoundToLock) { context.InstanceHandle.Free(); throw new InstanceLockLostException(command.Name, context.InstanceView.InstanceId); } throw new InstanceLockedException(command.Name, instance.Owner); } if (context.InstanceView.IsBoundToLock) { if (context.InstanceVersion != instance.Version) { if (context.InstanceVersion > instance.Version) { throw new InvalidProgramException("This is a bug, the context should never be bound higher than the lock."); } context.InstanceHandle.Free(); throw new InstanceLockLostException(command.Name, context.InstanceView.InstanceId); } } else { // This is the very interesting parallel-convoy conflicting handle race resolution case. Two handles // can get bound to the same lock, which is necessary to allow parallel convoy to succeed without preventing // zombied locked instances from being reclaimed. return(instance.Version); } } } foreach (KeyValuePair <Guid, IDictionary <XName, InstanceValue> > keyEntry in command.InstanceKeysToAssociate) { Key key = PersistenceItemManager.Load <Key>(keyEntry.Key); if (key != null) { if (key.TargetInstanceId != Guid.Empty && key.TargetInstanceId != context.InstanceView.InstanceId) { throw new InstanceKeyCollisionException(command.Name, context.InstanceView.InstanceId, new InstanceKey(keyEntry.Key), key.TargetInstanceId); } // The SaveWorkflowCommand treats this as a no-op, whether completed or not. } else { key = new Key() { Id = keyEntry.Key, State = InstanceKeyState.Associated, TargetInstanceId = context.InstanceView.InstanceId, Metadata = new PropertyBag(keyEntry.Value) }; PersistenceItemManager.SaveToFile <Key>(key); context.AssociatedInstanceKey(keyEntry.Key); if (keyEntry.Value != null) { foreach (KeyValuePair <XName, InstanceValue> property in keyEntry.Value) { context.WroteInstanceKeyMetadataValue(keyEntry.Key, property.Key, property.Value); } } } } foreach (Guid keyGuid in command.InstanceKeysToComplete) { Key key = PersistenceItemManager.Load <Key>(keyGuid); if (key != null && key.TargetInstanceId == context.InstanceView.InstanceId) { if (key.State == InstanceKeyState.Associated) //if (key.State != InstanceKeyState.Completed) { key.State = InstanceKeyState.Completed; PersistenceItemManager.SaveToFile <Key>(key); context.CompletedInstanceKey(keyGuid); } } else { // The SaveWorkflowCommand does not allow this. (Should it validate against it?) throw new InvalidOperationException("Attempting to complete a key which is not associated."); } } foreach (Guid keyGuid in command.InstanceKeysToFree) { Key key = PersistenceItemManager.Load <Key>(keyGuid); if (key != null && key.TargetInstanceId == context.InstanceView.InstanceId) { if (key.State != InstanceKeyState.Completed) { context.CompletedInstanceKey(keyGuid); } key.State = InstanceKeyState.Unknown; key.TargetInstanceId = Guid.Empty; key.Metadata = null; PersistenceItemManager.SaveToFile <Key>(key); context.UnassociatedInstanceKey(keyGuid); } else { // The SaveWorkflowCommand does not allow this. (Should it validate against it?) throw new InvalidOperationException("Attempting to complete a key which is not associated."); } } foreach (KeyValuePair <Guid, IDictionary <XName, InstanceValue> > keyEntry in command.InstanceKeyMetadataChanges) { Key key = PersistenceItemManager.Load <Key>(keyEntry.Key); if (key != null && key.TargetInstanceId == context.InstanceView.InstanceId && key.State == InstanceKeyState.Associated) { if (keyEntry.Value != null) { foreach (KeyValuePair <XName, InstanceValue> property in keyEntry.Value) { if (property.Value.IsDeletedValue) { key.Metadata.Remove(property.Key); } else { key.Metadata[property.Key] = new InstanceValue(property.Value); } context.WroteInstanceKeyMetadataValue(keyEntry.Key, property.Key, property.Value); } PersistenceItemManager.SaveToFile <Key>(key); } } else { // The SaveWorkflowCommand does not allow this. (Should it validate against it?) throw new InvalidOperationException("Attempting to complete a key which is not associated."); } } foreach (KeyValuePair <XName, InstanceValue> property in command.InstanceMetadataChanges) { if (property.Value.IsDeletedValue) { instance.Metadata.Remove(property.Key); } else { instance.Metadata[property.Key] = new InstanceValue(property.Value); } context.WroteInstanceMetadataValue(property.Key, property.Value); } if (command.InstanceData.Count > 0) { instance.Data = new PropertyBag(command.InstanceData); context.PersistedInstance(command.InstanceData); } PersistenceItemManager.SaveToFile <Instance>(instance); // The command does the implicit advancement of everything into safe completed states. if (command.CompleteInstance) { if (instance.Data == null) { instance.Data = new PropertyBag(); PersistenceItemManager.SaveToFile <Instance>(instance); context.PersistedInstance(new Dictionary <XName, InstanceValue>()); } Queue <Guid> keysToComplete = new Queue <Guid>(); foreach (KeyValuePair <Guid, InstanceKeyView> keyEntry in context.InstanceView.InstanceKeys) { if (keyEntry.Value.InstanceKeyState == InstanceKeyState.Associated) { keysToComplete.Enqueue(keyEntry.Key); } } foreach (Guid keyToComplete in keysToComplete) { Key key = PersistenceItemManager.Load <Key>(keyToComplete); key.State = InstanceKeyState.Completed; PersistenceItemManager.SaveToFile <Key>(key); context.CompletedInstanceKey(keyToComplete); } instance.State = InstanceState.Completed; instance.Owner = Guid.Empty; PersistenceItemManager.SaveToFile <Instance>(instance); context.CompletedInstance(); context.InstanceHandle.Free(); } if (command.UnlockInstance) { instance.Owner = Guid.Empty; PersistenceItemManager.SaveToFile <Instance>(instance); context.InstanceHandle.Free(); } return(0); }
static void UpdateKeyData(InstancePersistenceContext context, SaveWorkflowCommand saveWorkflowCommand) { InstanceView instanceView = context.InstanceView; foreach (KeyValuePair <Guid, IDictionary <XName, InstanceValue> > keyEntry in saveWorkflowCommand.InstanceKeysToAssociate) { if (!instanceView.InstanceKeys.ContainsKey(keyEntry.Key)) { context.AssociatedInstanceKey(keyEntry.Key); if (keyEntry.Value != null) { foreach (KeyValuePair <XName, InstanceValue> property in keyEntry.Value) { context.WroteInstanceKeyMetadataValue(keyEntry.Key, property.Key, property.Value); } } } } foreach (Guid key in saveWorkflowCommand.InstanceKeysToComplete) { InstanceKeyView existingKeyView; if (instanceView.InstanceKeys.TryGetValue(key, out existingKeyView)) { if (existingKeyView.InstanceKeyState != InstanceKeyState.Completed) { context.CompletedInstanceKey(key); } } } foreach (Guid key in saveWorkflowCommand.InstanceKeysToFree) { InstanceKeyView existingKeyView; if (instanceView.InstanceKeys.TryGetValue(key, out existingKeyView)) { context.UnassociatedInstanceKey(key); } } foreach (KeyValuePair <Guid, IDictionary <XName, InstanceValue> > keyEntry in saveWorkflowCommand.InstanceKeyMetadataChanges) { if (keyEntry.Value != null) { foreach (KeyValuePair <XName, InstanceValue> property in keyEntry.Value) { context.WroteInstanceKeyMetadataValue(keyEntry.Key, property.Key, property.Value); } } } if (saveWorkflowCommand.CompleteInstance) { foreach (KeyValuePair <Guid, InstanceKeyView> instanceKeys in instanceView.InstanceKeys) { if (instanceKeys.Value != null) { if (instanceKeys.Value.InstanceKeyState == InstanceKeyState.Associated) { context.CompletedInstanceKey(instanceKeys.Key); } } } } }