示例#1
0
        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);
                    }
                }
            }
        }
示例#2
0
        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);
                        }
                    }
                }
            }
        }