private Exception ProcessLoadWorkflowByInstanceKey(
     InstancePersistenceContext context,
     LoadWorkflowByInstanceKeyCommand command)
 {
     try
     {
         Guid instanceId = _dataStore.GetInstanceAssociation(
             command.LookupInstanceKey);
         if (instanceId == Guid.Empty)
         {
             throw new InstanceKeyNotReadyException(
                       String.Format("Unable to load instance for key: {0}",
                                     command.LookupInstanceKey));
         }
         SharedLoadWorkflow(context, instanceId);
         return(null);
     }
     catch (InstancePersistenceException exception)
     {
         Console.WriteLine(
             "ProcessLoadWorkflowByInstanceKey exception: {0}",
             exception.Message);
         return(exception);
     }
 }
        private Exception ProcessLoadWorkflowByInstanceKey(
            InstancePersistenceContext context,
            LoadWorkflowByInstanceKeyCommand command)
        {
            try
            {
                Guid instanceId = _dataStore.GetInstanceAssociation(
                    command.LookupInstanceKey);
                if (instanceId == Guid.Empty)
                {
                    throw new InstanceKeyNotReadyException(
                              String.Format(ErrorResource.UnableToLoadInstance,
                                            command.LookupInstanceKey));
                }

                SharedLoadWorkflow(context, instanceId);
                return(null);
            }
            catch (InstancePersistenceException exception)
            {
                Console.WriteLine(
                    // ReSharper disable LocalizableElement
                    "ProcessLoadWorkflowByInstanceKey exception: {0}",
                    // ReSharper restore LocalizableElement
                    exception.Message);
                return(exception);
            }
        }
 private InstancePersistenceCommand CreateLoadCommandHelper(InstanceKey key, out InstanceHandle handle, bool canCreateInstance, Guid suggestedIdOrId, ICollection <InstanceKey> associatedKeys, bool loadAny)
 {
     if (loadAny)
     {
         handle = this.store.CreateInstanceHandle(this.owner);
         return(new TryLoadRunnableWorkflowCommand());
     }
     if (key != null)
     {
         LoadWorkflowByInstanceKeyCommand command;
         handle = this.store.CreateInstanceHandle(this.owner);
         if (canCreateInstance)
         {
             command = new LoadWorkflowByInstanceKeyCommand {
                 LookupInstanceKey = key.Value,
                 AssociateInstanceKeyToInstanceId = (suggestedIdOrId == Guid.Empty) ? Guid.NewGuid() : suggestedIdOrId,
                 AcceptUninitializedInstance      = true
             };
         }
         else
         {
             command = new LoadWorkflowByInstanceKeyCommand {
                 LookupInstanceKey = key.Value
             };
         }
         InstanceKey keyToAdd = ((canCreateInstance && (key.Metadata != null)) && (key.Metadata.Count > 0)) ? key : null;
         if (associatedKeys != null)
         {
             foreach (InstanceKey key3 in associatedKeys)
             {
                 if (key3 == key)
                 {
                     if (!canCreateInstance)
                     {
                         continue;
                     }
                     keyToAdd = null;
                 }
                 TryAddKeyToInstanceKeysCollection(command.InstanceKeysToAssociate, key3);
             }
         }
         if (keyToAdd != null)
         {
             TryAddKeyToInstanceKeysCollection(command.InstanceKeysToAssociate, keyToAdd);
         }
         return(command);
     }
     if (associatedKeys != null)
     {
         throw System.ServiceModel.Activities.FxTrace.Exception.AsError(new InvalidOperationException(System.ServiceModel.Activities.SR.NoAdditionalKeysOnInstanceIdLoad));
     }
     handle = this.store.CreateInstanceHandle(this.owner, (suggestedIdOrId == Guid.Empty) ? Guid.NewGuid() : suggestedIdOrId);
     return(new LoadWorkflowCommand {
         AcceptUninitializedInstance = canCreateInstance
     });
 }
Exemple #4
0
        protected override IAsyncResult BeginTryCommand(InstancePersistenceContext context, InstancePersistenceCommand command, TimeSpan timeout, AsyncCallback callback, object state)
        {
            SaveWorkflowCommand save = command as SaveWorkflowCommand;

            if (save != null)
            {
                lock (FileStore.s_thisLock)
                {
                    ProcessSaveCommand(context, save);
                }
            }

            LoadWorkflowCommand load = command as LoadWorkflowCommand;

            if (load != null)
            {
                lock (FileStore.s_thisLock)
                {
                    ProcessLoadCommand(context, load);
                }
            }

            LoadWorkflowByInstanceKeyCommand loadByKey = command as LoadWorkflowByInstanceKeyCommand;

            if (loadByKey != null)
            {
                lock (FileStore.s_thisLock)
                {
                    ProcessLoadByKeyCommand(context, loadByKey);
                }
            }

            if (save != null || load != null || loadByKey != null)
            {
                return(new CompletedAsyncResult(callback, state));
            }

            if (command is CreateWorkflowOwnerCommand createOwner)
            {
                Guid  ownerId = Guid.NewGuid();
                Owner owner   = new Owner();
                lock (s_thisLock)
                {
                    owner.Id        = ownerId;
                    owner.LockToken = Guid.NewGuid();
                    owner.Metadata  = new PropertyBag(createOwner.InstanceOwnerMetadata);
                    PersistenceItemManager.SaveToFile <Owner>(owner);
                }

                context.BindInstanceOwner(ownerId, owner.LockToken);
                context.BindEvent(HasRunnableWorkflowEvent.Value);
                return(new CompletedAsyncResult(callback, state));
            }

            if (command is DeleteWorkflowOwnerCommand deleteOwner)
            {
                Guid ownerId = context.InstanceView.InstanceOwner.InstanceOwnerId;

                lock (FileStore.s_thisLock)
                {
                    Owner owner = PersistenceItemManager.Load <Owner>(ownerId);
                    if (owner != null && owner.LockToken == context.LockToken)
                    {
                        PersistenceItemManager.Remove <Owner>(ownerId);
                    }
                }

                context.InstanceHandle.Free();
                return(new CompletedAsyncResult(callback, state));
            }

            return(base.BeginTryCommand(context, command, timeout, callback, state));
        }
Exemple #5
0
        private long ProcessLoadByKeyCommand(InstancePersistenceContext context, LoadWorkflowByInstanceKeyCommand command)
        {
            Owner owner = CheckOwner(context, command.Name);

            Key      key = PersistenceItemManager.Load <Key>(command.LookupInstanceKey);
            Instance instance;

            if (key == null)
            {
                if (context.InstanceView.IsBoundToLock && context.InstanceView.InstanceId != command.AssociateInstanceKeyToInstanceId)
                {
                    // This happens in the bind reclaimed lock case.
                    context.InstanceHandle.Free();
                    throw new InstanceLockLostException(command.Name, context.InstanceView.InstanceId);
                }
                if (command.AssociateInstanceKeyToInstanceId == Guid.Empty)
                {
                    throw new InstanceKeyNotReadyException(command.Name, new InstanceKey(command.LookupInstanceKey));
                }

                key = new Key()
                {
                    Id = command.LookupInstanceKey,
                    TargetInstanceId = command.AssociateInstanceKeyToInstanceId,
                    Metadata         = new PropertyBag()
                };

                instance = PersistenceItemManager.Load <Instance>(command.AssociateInstanceKeyToInstanceId);
                if (instance == null)
                {
                    // Checking instance.Owner is like an InstanceLockQueryResult.
                    context.QueriedInstanceStore(new InstanceLockQueryResult(command.AssociateInstanceKeyToInstanceId, Guid.Empty));

                    if (context.InstanceView.IsBoundToLock)
                    {
                        // This happens in the bind reclaimed lock case.
                        context.InstanceHandle.Free();
                        throw new InstanceLockLostException(command.Name, context.InstanceView.InstanceId);
                    }

                    context.BindInstance(command.AssociateInstanceKeyToInstanceId);

                    if (command.AcceptUninitializedInstance)
                    {
                        instance = new Instance()
                        {
                            Id       = command.AssociateInstanceKeyToInstanceId,
                            Version  = 1,
                            Metadata = new PropertyBag(),
                            Owner    = context.InstanceView.InstanceOwner.InstanceOwnerId
                        };
                        PersistenceItemManager.SaveToFile <Instance>(instance);
                    }
                    else
                    {
                        throw new Exception("Could not create new Instance");
                    }

                    context.BindAcquiredLock(1);
                }
                else
                {
                    // Checking instance.Owner is like an InstanceLockQueryResult.
                    context.QueriedInstanceStore(new InstanceLockQueryResult(command.AssociateInstanceKeyToInstanceId, instance.Owner));

                    if (context.InstanceView.IsBoundToLock)
                    {
                        if (instance.Version != context.InstanceVersion || instance.Owner != context.InstanceView.InstanceOwner.InstanceOwnerId)
                        {
                            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);
                        }
                    }

                    if (instance.Data != null)
                    {
                        // LoadByInstanceKeyCommand only allows auto-association to an uninitialized instance.
                        throw new InstanceCollisionException(command.Name, command.AssociateInstanceKeyToInstanceId);
                    }

                    if (!context.InstanceView.IsBoundToLock)
                    {
                        if (instance.Owner == Guid.Empty)
                        {
                            context.BindInstance(command.AssociateInstanceKeyToInstanceId);
                            instance.Version++;
                            instance.Owner = context.InstanceView.InstanceOwner.InstanceOwnerId;
                            PersistenceItemManager.SaveToFile <Instance>(instance);
                            context.BindAcquiredLock(instance.Version);
                        }
                        else if (instance.Owner == context.InstanceView.InstanceOwner.InstanceOwnerId)
                        {
                            // This is a pretty weird case - maybe it's a retry?
                            context.BindInstance(command.AssociateInstanceKeyToInstanceId);
                            return(instance.Version);
                        }
                        else
                        {
                            throw new InstanceLockedException(command.Name, instance.Owner);
                        }
                    }
                }

                if (command.InstanceKeysToAssociate.TryGetValue(command.LookupInstanceKey, out IDictionary <XName, InstanceValue> lookupKeyMetadata))
                {
                    key.Metadata = new PropertyBag(lookupKeyMetadata);
                }
                else
                {
                    key.Metadata = new PropertyBag();
                }
                key.Id = command.LookupInstanceKey;
                key.TargetInstanceId = command.AssociateInstanceKeyToInstanceId;
                PersistenceItemManager.SaveToFile <Key>(key);
                context.AssociatedInstanceKey(command.LookupInstanceKey);
                if (lookupKeyMetadata != null)
                {
                    foreach (KeyValuePair <XName, InstanceValue> property in lookupKeyMetadata)
                    {
                        context.WroteInstanceKeyMetadataValue(command.LookupInstanceKey, property.Key, property.Value);
                    }
                }
            }
            else
            {
                if (context.InstanceView.IsBoundToLock && (key.State == InstanceKeyState.Completed || key.TargetInstanceId != context.InstanceView.InstanceId))
                {
                    // This happens in the bind reclaimed lock case.
                    context.InstanceHandle.Free();
                    throw new InstanceLockLostException(command.Name, context.InstanceView.InstanceId);
                }
                if (key.State == InstanceKeyState.Completed)
                {
                    throw new InstanceKeyCompleteException(command.Name, new InstanceKey(command.LookupInstanceKey));
                }

                instance = PersistenceItemManager.Load <Instance>(key.TargetInstanceId);

                // Checking instance.Owner is like an InstanceLockQueryResult.
                context.QueriedInstanceStore(new InstanceLockQueryResult(key.TargetInstanceId, instance.Owner));

                if (context.InstanceView.IsBoundToLock)
                {
                    if (instance.Version != context.InstanceVersion || instance.Owner != context.InstanceView.InstanceOwner.InstanceOwnerId)
                    {
                        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);
                    }
                }

                if (instance.Data == null && !command.AcceptUninitializedInstance)
                {
                    throw new InstanceNotReadyException(command.Name, key.TargetInstanceId);
                }

                if (!context.InstanceView.IsBoundToLock)
                {
                    if (instance.Owner == Guid.Empty)
                    {
                        context.BindInstance(key.TargetInstanceId);
                        instance.Version++;
                        instance.Owner = context.InstanceView.InstanceOwner.InstanceOwnerId;
                        PersistenceItemManager.SaveToFile <Instance>(instance);
                        context.BindAcquiredLock(instance.Version);
                    }
                    else if (instance.Owner == context.InstanceView.InstanceOwner.InstanceOwnerId)
                    {
                        // 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.
                        context.BindInstance(key.TargetInstanceId);
                        return(instance.Version);
                    }
                    else
                    {
                        throw new InstanceLockedException(command.Name, instance.Owner);
                    }
                }
            }

            Key       newKey;
            Exception exception = null;

            foreach (KeyValuePair <Guid, IDictionary <XName, InstanceValue> > keyEntry in command.InstanceKeysToAssociate)
            {
                newKey = PersistenceItemManager.Load <Key>(keyEntry.Key);
                if (newKey == null)
                {
                    newKey = new Key()
                    {
                        Id = keyEntry.Key,
                        TargetInstanceId = key.TargetInstanceId,
                        Metadata         = new PropertyBag(keyEntry.Value)
                    };
                    PersistenceItemManager.AddKeyToInstance(key.TargetInstanceId, newKey);

                    context.AssociatedInstanceKey(keyEntry.Key);
                    if (keyEntry.Value != null)
                    {
                        foreach (KeyValuePair <XName, InstanceValue> property in keyEntry.Value)
                        {
                            context.WroteInstanceKeyMetadataValue(keyEntry.Key, property.Key, property.Value);
                        }
                    }
                }
                else
                {
                    if (newKey.TargetInstanceId != key.TargetInstanceId && exception == null)
                    {
                        exception = new InstanceKeyCollisionException(command.Name, key.TargetInstanceId, new InstanceKey(keyEntry.Key), newKey.TargetInstanceId);
                    }
                }
            }
            if (exception != null)
            {
                throw exception;
            }

            Dictionary <Guid, IDictionary <XName, InstanceValue> > associatedKeys = new Dictionary <Guid, IDictionary <XName, InstanceValue> >();
            Dictionary <Guid, IDictionary <XName, InstanceValue> > completedKeys  = new Dictionary <Guid, IDictionary <XName, InstanceValue> >();

            foreach (Guid keyId in instance.RelatedKeys)
            {
                key = PersistenceItemManager.Load <Key>(keyId);

                if (key.TargetInstanceId == context.InstanceView.InstanceId)
                {
                    if (key.State == InstanceKeyState.Completed)
                    {
                        completedKeys.Add(key.Id, ExcludeWriteOnlyPropertyBagItems(key.Metadata));
                    }
                    else
                    {
                        associatedKeys.Add(key.Id, ExcludeWriteOnlyPropertyBagItems(key.Metadata));
                    }
                }
            }

            instance.State = instance.Data == null ? InstanceState.Uninitialized : InstanceState.Initialized;
            PersistenceItemManager.SaveToFile <Instance>(instance);
            context.LoadedInstance(instance.State, ExcludeWriteOnlyPropertyBagItems(instance.Data),
                                   ExcludeWriteOnlyPropertyBagItems(instance.Metadata), associatedKeys, completedKeys);

            return(0);
        }