private Exception ProcessLoadWorkflow(
     InstancePersistenceContext context,
     LoadWorkflowCommand command)
 {
     try
     {
         if (command.AcceptUninitializedInstance)
         {
             context.LoadedInstance(InstanceState.Uninitialized,
                                    null, null, null, null);
         }
         else
         {
             SharedLoadWorkflow(context, context.InstanceView.InstanceId);
         }
         return(null);
     }
     catch (InstancePersistenceException exception)
     {
         Console.WriteLine(
             // ReSharper disable LocalizableElement
             "ProcessLoadWorkflow exception: {0}",
             // ReSharper restore LocalizableElement
             exception.Message);
         return(exception);
     }
 }
Beispiel #2
0
        private bool LoadWorkflow(InstancePersistenceContext context, LoadWorkflowCommand command)
        {
            if (command.AcceptUninitializedInstance)
            {
                return(false);
            }

            if (context.InstanceVersion == -1)
            {
                context.BindAcquiredLock(0);
            }

            Guid instanceId      = context.InstanceView.InstanceId;
            Guid instanceOwnerId = context.InstanceView.InstanceOwner.InstanceOwnerId;

            IDictionary <XName, InstanceValue> instanceData     = null;
            IDictionary <XName, InstanceValue> instanceMetadata = null;

            Dictionary <string, object> fullInstanceData = _stores.LoadWorkflowContext();

            instanceData     = this.DeserializePropertyBag((Dictionary <XName, object>)fullInstanceData["instanceData"]);
            instanceMetadata = this.DeserializePropertyBag((Dictionary <XName, object>)fullInstanceData["instanceMetadata"]);

            context.LoadedInstance(InstanceState.Initialized, instanceData, instanceMetadata, null, null);

            return(true);
        }
Beispiel #3
0
        // The persistence engine will send a variety of commands to the configured InstanceStore,
        // such as CreateWorkflowOwnerCommand, SaveWorkflowCommand, and LoadWorkflowCommand.
        // This method is where we will handle those commands.
        protected override IAsyncResult BeginTryCommand(InstancePersistenceContext context, InstancePersistenceCommand command, TimeSpan timeout, AsyncCallback callback, object state)
        {
            IDictionary <XName, InstanceValue> instanceStateData = null;

            //The CreateWorkflowOwner command instructs the instance store to create a new instance owner bound to the instanace handle
            if (command is CreateWorkflowOwnerCommand)
            {
                context.BindInstanceOwner(_storeId, Guid.NewGuid());
            }
            //The SaveWorkflow command instructs the instance store to modify the instance bound to the instance handle or an instance key
            else if (command is SaveWorkflowCommand)
            {
                SaveWorkflowCommand saveCommand = (SaveWorkflowCommand)command;
                instanceStateData = saveCommand.InstanceData;

                var instanceStateXml = DictionaryToXml(instanceStateData);
                Save(context.InstanceView.InstanceId, this._storeId, instanceStateXml);
            }
            //The LoadWorkflow command instructs the instance store to lock and load the instance bound to the identifier in the instance handle
            else if (command is LoadWorkflowCommand)
            {
                var xml = Load(context.InstanceView.InstanceId, this._storeId);
                instanceStateData = XmlToDictionary(xml);
                //load the data into the persistence Context
                context.LoadedInstance(InstanceState.Initialized, instanceStateData, null, null, null);
            }

            return(new CompletedAsyncResult <bool>(true, callback, state));
        }
Beispiel #4
0
        // The persistence engine will send a variety of commands to the configured InstanceStore,
        // such as CreateWorkflowOwnerCommand, SaveWorkflowCommand, and LoadWorkflowCommand.
        // This method is where we will handle those commands.
        protected override IAsyncResult BeginTryCommand(InstancePersistenceContext context, InstancePersistenceCommand command, TimeSpan timeout, AsyncCallback callback, object state)
        {
            IDictionary <XName, InstanceValue> instanceStateData = null;
            WorkflowInstance instance   = null;
            Guid             InstanceId = Guid.Empty;

            if (context != null && context.InstanceView != null)
            {
                InstanceId = context.InstanceView.InstanceId;
                instance   = WorkflowInstance.Instances.Where(x => x.InstanceId == InstanceId.ToString()).FirstOrDefault();
            }

            //The CreateWorkflowOwner command instructs the instance store to create a new instance owner bound to the instanace handle
            if (command is CreateWorkflowOwnerCommand)
            {
                context.BindInstanceOwner(_storeId, Guid.NewGuid());
            }
            //The SaveWorkflow command instructs the instance store to modify the instance bound to the instance handle or an instance key
            else if (command is SaveWorkflowCommand)
            {
                if (instance != null && instance.Workflow != null && instance.Workflow.Serializable == true)
                {
                    SaveWorkflowCommand saveCommand = (SaveWorkflowCommand)command;
                    try
                    {
                        instanceStateData = saveCommand.InstanceData;
                        var instanceStateXml = DictionaryToXml(instanceStateData);
                        Save(context.InstanceView.InstanceId, this._storeId, instanceStateXml);
                    }
                    catch (Exception)
                    {
                        instance.Workflow.Serializable = false;
                    }
                }
            }
            //The LoadWorkflow command instructs the instance store to lock and load the instance bound to the identifier in the instance handle
            else if (command is LoadWorkflowCommand)
            {
                var xml = Load(InstanceId, _storeId);
                // if (xml == null) throw new ArgumentNullException("Failed locating instance data for " + context.InstanceView.InstanceId.ToString());
                // if (xml == null) return new CompletedAsyncResult<bool>(false, callback, state);
                if (xml == null)
                {
                    return(new CompletedAsyncResult <bool>(true, callback, state));
                }
                instanceStateData = XmlToDictionary(xml);
                //load the data into the persistence Context
                context.LoadedInstance(InstanceState.Initialized, instanceStateData, null, null, null);
            }
            return(new CompletedAsyncResult <bool>(true, callback, state));
        }
Beispiel #5
0
        private bool LoadWorkflow(InstancePersistenceContext context, LoadWorkflowCommand command)
        {
            if (command.AcceptUninitializedInstance)
            {
                return(false);
            }

            if (context.InstanceVersion == -1)
            {
                context.BindAcquiredLock(0);
            }

            IDictionary <XName, InstanceValue> instanceData     = null;
            IDictionary <XName, InstanceValue> instanceMetadata = null;

            FileStream instanceDataStream;
            FileStream instanceMetadataStream;

            GetFileStreams(context.InstanceView.InstanceId, out instanceDataStream, out instanceMetadataStream, FileMode.Open);

            DataContractSerializer instanceDataSerializer;
            DataContractSerializer instanceMetadataSerializer;

            GetDataContractSerializers(out instanceDataSerializer, out instanceMetadataSerializer);

            Dictionary <string, InstanceValue> serializableInstanceData;
            Dictionary <string, InstanceValue> serializableInstanceMetadata;

            try
            {
                serializableInstanceData     = (Dictionary <string, InstanceValue>)instanceDataSerializer.ReadObject(instanceDataStream);
                serializableInstanceMetadata = (Dictionary <string, InstanceValue>)instanceMetadataSerializer.ReadObject(instanceMetadataStream);
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                instanceDataStream.Dispose();
                instanceMetadataStream.Dispose();
            }

            instanceData     = this.DeserializePropertyBagConvertXNameInstanceValue(serializableInstanceData);
            instanceMetadata = this.DeserializePropertyBagConvertXNameInstanceValue(serializableInstanceMetadata);

            context.LoadedInstance(InstanceState.Initialized, instanceData, instanceMetadata, null, null);

            return(true);
        }
Beispiel #6
0
        private bool LoadWorkflow(InstancePersistenceContext context, LoadWorkflowCommand command)
        {
            if (command.AcceptUninitializedInstance)
            {
                return(false);
            }

            if (context.InstanceVersion == -1)
            {
                context.BindAcquiredLock(0);
            }

            IDictionary <XName, InstanceValue> instanceData     = null;
            IDictionary <XName, InstanceValue> instanceMetadata = null;

            Dictionary <string, InstanceValue> serializableInstanceData     = null;
            Dictionary <string, InstanceValue> serializableInstanceMetadata = null;

            try
            {
                if (ToLoad != null)
                {
                    Serialized serialized = ToLoad();

                    serializableInstanceData     = WorkflowSerialization.DeSerialize <Dictionary <string, InstanceValue> >(serialized.SerializedInstanceData);
                    serializableInstanceMetadata = WorkflowSerialization.DeSerialize <Dictionary <string, InstanceValue> >(serialized.SerializedInstanceMetadata);
                }
            }
            catch (Exception exc)
            {
                throw;
            }

            if (serializableInstanceData != null)
            {
                instanceData = this.DeserializePropertyBagConvertXNameInstanceValue(serializableInstanceData);
            }

            if (serializableInstanceMetadata != null)
            {
                instanceMetadata = this.DeserializePropertyBagConvertXNameInstanceValue(serializableInstanceMetadata);
            }

            context.LoadedInstance(InstanceState.Initialized, instanceData, instanceMetadata, null, null);

            return(true);
        }
Beispiel #7
0
        //The persistence engine will send a variety of commands to the configured InstanceStore,
        //such as CreateWorkflowOwnerCommand, SaveWorkflowCommand, and LoadWorkflowCommand.
        //This method is where we will handle those commands
        protected override IAsyncResult BeginTryCommand(InstancePersistenceContext context, InstancePersistenceCommand command, TimeSpan timeout, AsyncCallback callback, object state)
        {
            IDictionary <XName, InstanceValue> data = null;

            //The CreateWorkflowOwner command instructs the instance store to create a new instance owner bound to the instanace handle
            if (command is CreateWorkflowOwnerCommand || command is CreateWorkflowOwnerWithIdentityCommand) //Arghya test
            {
                context.BindInstanceOwner(ownerInstanceID, Guid.NewGuid());                                 //TODO??
            }
            //The SaveWorkflow command instructs the instance store to modify the instance bound to the instance handle or an instance key
            else if (command is SaveWorkflowCommand)
            {
                SaveWorkflowCommand saveCommand = (SaveWorkflowCommand)command;
                data = saveCommand.InstanceData;

                Save(data, context.InstanceView.InstanceId.ToString()); //arghya
            }
            //The LoadWorkflow command instructs the instance store to lock and load the instance bound to the identifier in the instance handle
            else if (command is LoadWorkflowCommand)
            {
                //string fileName = Path.Combine(Directory.GetCurrentDirectory(), string.Format(CultureInfo.InvariantCulture, InstanceFormatString, this.ownerInstanceID));
                string fileName = Path.Combine(
                    Directory.GetCurrentDirectory(),
                    string.Format(CultureInfo.InvariantCulture,
                                  InstanceFormatString,
                                  context.InstanceView.InstanceId.ToString())); //this.ownerInstanceID //arghya

                try
                {
                    using (FileStream inputStream = new FileStream(fileName, FileMode.Open))
                    {
                        data = LoadInstanceDataFromFile(inputStream);
                        //load the data into the persistence Context
                        context.LoadedInstance(InstanceState.Initialized, data, null, null, null);
                    }
                }
                catch (Exception exception)
                {
                    throw new FileLoadException(exception.Message); //PersistenceException //using System.ServiceModel.Persistence;
                }
            }

            return(new CompletedAsyncResult <bool>(true, callback, state));
        }
Beispiel #8
0
        private bool LoadWorkflow(InstancePersistenceContext context, LoadWorkflowCommand command)
        {
            if (command.AcceptUninitializedInstance)
            {
                return(false);
            }

            if (context.InstanceVersion == -1)
            {
                context.BindAcquiredLock(0);
            }

            var package  = _repository.Load(context.InstanceView.InstanceId);
            var data     = Deserialize(package.Data);
            var metadata = Deserialize(package.Metadata);

            context.LoadedInstance(InstanceState.Initialized, data, metadata, null, null);
            return(true);
        }
Beispiel #9
0
        private bool LoadWorkflow(InstancePersistenceContext context, LoadWorkflowCommand command)
        {
            if (command.AcceptUninitializedInstance)
            {
                return(false);
            }

            if (context.InstanceVersion == -1)
            {
                context.BindAcquiredLock(0);
            }

            IDictionary <XName, InstanceValue> instanceData     = null;
            IDictionary <XName, InstanceValue> instanceMetadata = null;

            Dictionary <string, InstanceValue> serializableInstanceData;
            Dictionary <string, InstanceValue> serializableInstanceMetadata;

            try
            {
                ////var serializedInstanceData = File.ReadAllText(_storeDirectoryPath + "\\" + context.InstanceView.InstanceId + "-InstanceData");
                //var serializedInstanceData = File.ReadAllText(_storePathInstanceData);
                //serializableInstanceData = JsonConvert.DeserializeObject<Dictionary<string, InstanceValue>>(serializedInstanceData, _jsonSerializerSettings);

                ////var serializedInstanceMetadata = File.ReadAllText(_storeDirectoryPath + "\\" + context.InstanceView.InstanceId + "-InstanceMetadata");
                //var serializedInstanceMetadata = File.ReadAllText(_storePathInstanceMetadata);
                //serializableInstanceMetadata = JsonConvert.DeserializeObject<Dictionary<string, InstanceValue>>(serializedInstanceMetadata, _jsonSerializerSettings);

                deserialize_dc(out serializableInstanceData, out serializableInstanceMetadata);
            }
            catch (Exception exc)
            {
                throw;
            }

            instanceData     = this.DeserializePropertyBagConvertXNameInstanceValue(serializableInstanceData);
            instanceMetadata = this.DeserializePropertyBagConvertXNameInstanceValue(serializableInstanceMetadata);

            context.LoadedInstance(InstanceState.Initialized, instanceData, instanceMetadata, null, null);

            return(true);
        }
Beispiel #10
0
        protected override IAsyncResult BeginTryCommand(InstancePersistenceContext context, InstancePersistenceCommand command, TimeSpan timeout, AsyncCallback callback, object state)
        {
            if (command is CreateWorkflowOwnerCommand)
            {
                context.BindInstanceOwner(OwnerInstanceId, Guid.NewGuid());
            }
            else if (command is SaveWorkflowCommand)
            {
                var saveCommand = (SaveWorkflowCommand)command;
                Save(context.InstanceView.InstanceId, saveCommand.InstanceData);
            }
            else if (command is LoadWorkflowCommand)
            {
                context.LoadedInstance(InstanceState.Initialized, Load(context.InstanceView.InstanceId), null, null, null);
            }
            else if (command is DeleteWorkflowOwnerCommand)
            {
            }

            return(new CompletedAsyncResult <bool>(true, callback, state));
        }
        /// <summary>
        /// The begin try command.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="command">The command.</param>
        /// <param name="timeout">The timeout.</param>
        /// <param name="callback">The callback.</param>
        /// <param name="state">The state.</param>
        /// <returns>The <see cref="IAsyncResult" />.</returns>
        /// <exception cref="SystemFailureException">Error processing message.</exception>
        protected override IAsyncResult BeginTryCommand(
            InstancePersistenceContext context,
            InstancePersistenceCommand command,
            TimeSpan timeout,
            AsyncCallback callback,
            object state)
        {
            lock (LocalLock)
            {
                if (command is CreateWorkflowOwnerCommand)
                {
                    context.BindInstanceOwner(this.ownerInstanceId, Guid.NewGuid());
                }
                else
                {
                    var saveWorkflowCommand = command as SaveWorkflowCommand;
                    if (saveWorkflowCommand != null)
                    {
                        this.SaveInstanceData(saveWorkflowCommand.InstanceData);
                    }
                    else if (command is LoadWorkflowCommand)
                    {
                        try
                        {
                            var instanceData = this.unstructuredStorageRepository.GetById(
                                "WorkflowInstanceStoreData",
                                this.ownerInstanceId.ToString());
                            var deserializedData = DeserializeData(instanceData.Payload.Combine());
                            context.LoadedInstance(InstanceState.Initialized, deserializedData, null, null, null);
                        }
                        catch (Exception exception)
                        {
                            throw;
                        }
                    }
                }

                return(new CompletedAsyncResult <bool>(true, callback, state));
            }
        }
Beispiel #12
0
        //The persistence engine will send a variety of commands to the configured InstanceStore,
        //such as CreateWorkflowOwnerCommand, SaveWorkflowCommand, and LoadWorkflowCommand.
        //This method is where we will handle those commands
        protected override IAsyncResult BeginTryCommand(InstancePersistenceContext context, InstancePersistenceCommand command, TimeSpan timeout, AsyncCallback callback, object state)
        {
            IDictionary <XName, InstanceValue> data = null;

            //The CreateWorkflowOwner command instructs the instance store to create a new instance owner bound to the instanace handle
            if (command is CreateWorkflowOwnerCommand)
            {
                context.BindInstanceOwner(ownerInstanceID, ownerInstanceID);
            }
            //The SaveWorkflow command instructs the instance store to modify the instance bound to the instance handle or an instance key
            else if (command is SaveWorkflowCommand)
            {
                SaveWorkflowCommand saveCommand = (SaveWorkflowCommand)command;
                data = saveCommand.InstanceData;


                Save(data);
                //_saveWaitHandler.WaitOne(new TimeSpan(0, 0, 1));
            }
            //The LoadWorkflow command instructs the instance store to lock and load the instance bound to the identifier in the instance handle
            else if (command is LoadWorkflowCommand)
            {
                string fileName = GetFileName(this.ownerInstanceID);

                data = LoadInstanceDataFromFile(fileName);
                var nonWriteOnly = data.Where(kvp => (kvp.Value.Options & InstanceValueOptions.WriteOnly) != InstanceValueOptions.WriteOnly).ToDictionary(k => k.Key, v => v.Value);


                //load the data into the persistence Context
                context.LoadedInstance(InstanceState.Initialized, nonWriteOnly, null, null, null);
            }
            else if (command.Name.LocalName == "CreateWorkflowOwner")
            {
                //do nothing
            }
            var result = new CompletedAsyncResult <bool>(true, callback, state);

            return(result);
        }
        //The persistence engine will send a variety of commands to the configured InstanceStore,
        //such as CreateWorkflowOwnerCommand, SaveWorkflowCommand, and LoadWorkflowCommand.
        //This method is where we will handle those commands
        protected override IAsyncResult BeginTryCommand(InstancePersistenceContext context, InstancePersistenceCommand command, TimeSpan timeout, AsyncCallback callback, object state)
        {
            IDictionary <XName, InstanceValue> data = null;

            //The CreateWorkflowOwner command instructs the instance store to create a new instance owner bound to the instanace handle
            if (command is CreateWorkflowOwnerCommand)
            {
                context.BindInstanceOwner(ownerInstanceID, Guid.NewGuid());
            }
            //The SaveWorkflow command instructs the instance store to modify the instance bound to the instance handle or an instance key
            else if (command is SaveWorkflowCommand)
            {
                SaveWorkflowCommand saveCommand = (SaveWorkflowCommand)command;
                data = saveCommand.InstanceData;

                Save(data);
            }
            //The LoadWorkflow command instructs the instance store to lock and load the instance bound to the identifier in the instance handle
            else if (command is LoadWorkflowCommand)
            {
                string fileName = this.ownerInstanceID.ToString();

                try
                {
                    using (FileStream inputStream = new FileStream(fileName, FileMode.Open))
                    {
                        data = LoadInstanceDataFromFile(inputStream);
                        //load the data into the persistence Context
                        context.LoadedInstance(InstanceState.Initialized, data, null, null, null);
                    }
                }
                catch (Exception exception)
                {
                    throw new Exception(exception.Message);
                }
            }

            return(new CompletedAsyncResult <bool>(true, callback, state));
        }
 private void SharedLoadWorkflow(InstancePersistenceContext context,
                                 Guid instanceId)
 {
     if (instanceId != Guid.Empty)
     {
         IDictionary <XName, InstanceValue> instanceData;
         IDictionary <XName, InstanceValue> instanceMetadata;
         _dataStore.LoadInstance(instanceId,
                                 out instanceData, out instanceMetadata);
         if (context.InstanceView.InstanceId == Guid.Empty)
         {
             context.BindInstance(instanceId);
         }
         context.LoadedInstance(InstanceState.Initialized,
                                instanceData, instanceMetadata, null, null);
     }
     else
     {
         throw new InstanceNotReadyException(
                   String.Format(ErrorResource.UnableToLoadInstance, instanceId));
     }
 }
Beispiel #15
0
        /// <summary>
        /// Handles a <see cref="LoadWorkflowCommand"/>.
        /// </summary>
        /// <param name="context"></param>
        /// <param name="command"></param>
        Task <bool> LoadWorkflowCommand(InstancePersistenceContext context, LoadWorkflowCommand command)
        {
            if (state.InstanceId != context.InstanceView.InstanceId)
            {
                throw new InvalidOperationException("Loading InstanceId does not match state InstanceId.");
            }

            if (state.InstanceState != InstanceState.Completed)
            {
                context.LoadedInstance(
                    InstanceState.Initialized,
                    LoadInstanceData(context.InstanceView.InstanceId),
                    LoadInstanceMetadata(context.InstanceView.InstanceId),
                    null,
                    null);

                return(Task.FromResult(true));
            }
            else
            {
                return(Task.FromResult(false));
            }
        }
Beispiel #16
0
        private long ProcessLoadCommand(InstancePersistenceContext context, LoadWorkflowCommand 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);
                }
                if (!command.AcceptUninitializedInstance)
                {
                    throw new InstanceNotReadyException(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 (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.State == InstanceState.Completed)
                {
                    throw new InstanceCompleteException(command.Name, context.InstanceView.InstanceId);
                }
                if ((instance.Data == null || instance.Data.Count < 1) && !command.AcceptUninitializedInstance)
                {
                    throw new InstanceNotReadyException(command.Name, context.InstanceView.InstanceId);
                }

                if (!context.InstanceView.IsBoundToLock)
                {
                    if (instance.Owner == Guid.Empty)
                    {
                        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.
                        return(instance.Version);
                    }
                    else
                    {
                        throw new InstanceLockedException(command.Name, instance.Owner);
                    }
                }
            }

            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 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);
        }
Beispiel #17
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);
        }