Exemple #1
0
        /// <summary>
        /// Sends a deleteItem method to the clients that are sync'd to sequences that contain this item.
        /// It does not send a delete message to the adapter/assembler but instead assumes that this
        /// item is already have been deleted from the database or is being deleted in this transaction.
        /// If you rollback the transaction, this message is also rolled back.
        ///
        /// This version of the delete method causes clients to generate a conflict if they have a version
        /// of the item that does not match the version of the item specified. You can use the
        /// DeleteItemWithId method to unconditionally delete an item on the client if you do not have
        /// the original version.
        /// </summary>
        /// <param name="destination">Name of the destination containing the item to be deleted.</param>
        /// <param name="item">Version of the item to delete. Clients can detect a conflict if this version of the item does not match the version they are currently managing.</param>
        public void DeleteItem(string destination, object item)
        {
            DataMessage     dataMessage     = new DataMessage();
            DataDestination dataDestination = _dataService.GetDestination(destination) as DataDestination;

            dataMessage.operation   = DataMessage.DeleteOperation;
            dataMessage.body        = item;
            dataMessage.destination = destination;
            if (_clientId != null)
            {
                dataMessage.clientId = _clientId;
            }
            else
            {
                dataMessage.clientId = "srv:" + Guid.NewGuid().ToString("D");
            }
            dataMessage.identity  = Identity.GetIdentity(item, dataDestination);
            dataMessage.messageId = "srv:" + Guid.NewGuid().ToString("D") + ":" + _idCounter.ToString();
            System.Threading.Interlocked.Increment(ref _idCounter);

            ArrayList messages = new ArrayList(1);

            messages.Add(dataMessage);
            MessageBatch messageBatch = new MessageBatch(dataMessage, messages);

            AddProcessedMessageBatch(messageBatch);
        }
Exemple #2
0
        /// <summary>
        /// Send an update event to clients subscribed to this message. Note that this method does not send
        /// the change to the adapter/assembler - it assumes that the changes have already been applied
        /// or are being applied. It only updates the clients with the new version of this data.
        ///
        /// You must supply a destination parameter and a new version of the object. If you supply a
        /// non-null previous version, this object is used to detect conflicts on the client in case
        /// the client's version of the data does not match the previous version. You may also supply
        /// a list of property names that have changed as a hint to the client to indicate which properties
        /// should be checked for conflicts and updated. If you supply null for the changes, all
        /// properties on the client are updated. These property names do not accept any kind of dot
        /// notation to specify that a property of a property has changed. Only top level property
        /// names are allowed.
        /// </summary>
        /// <param name="destination">Name of the Data Management Services destination that is managing the item you want to update.</param>
        /// <param name="newVersion">New version of the item to update. The identity of the item is used to determine which item to update.</param>
        /// <param name="previousVersion">If not null, this contains a version of the item you intend to update. The client can detect a conflict if its version does not match the previousVersion. If you specify the value as null, a conflict is only detected if the client has pending changes for the item being updated.</param>
        /// <param name="changes">Array of property names which are to be updated. You can provide a null value to indicate that all property values may have changed.</param>
        public void UpdateItem(string destination, object newVersion, object previousVersion, string[] changes)
        {
            DataMessage     dataMessage     = new DataMessage();
            DataDestination dataDestination = _dataService.GetDestination(destination) as DataDestination;

            object[] body = new object[3];
            body[0] = changes;
            body[2] = newVersion;
            body[1] = previousVersion;
            dataMessage.operation   = DataMessage.UpdateOperation;
            dataMessage.body        = body;
            dataMessage.destination = destination;
            if (_clientId != null)
            {
                dataMessage.clientId = _clientId;
            }
            else
            {
                dataMessage.clientId = "srv:" + Guid.NewGuid().ToString("D");
            }
            dataMessage.identity  = Identity.GetIdentity(newVersion, dataDestination);
            dataMessage.messageId = "srv:" + Guid.NewGuid().ToString("D") + ":" + _idCounter.ToString();
            System.Threading.Interlocked.Increment(ref _idCounter);
            ArrayList messages = new ArrayList(1);

            messages.Add(dataMessage);
            MessageBatch messageBatch = new MessageBatch(dataMessage, messages);

            _processedMessageBatches.Add(messageBatch);
        }
        void SyncSequenceChanges(DataMessage dataMessage, DataServiceTransaction dataServiceTransaction)
        {
            lock (_objLock) {
                ArrayList sequenceList = new ArrayList(_sequenceIdToSequenceHash.Values.Count);
                sequenceList.AddRange(_sequenceIdToSequenceHash.Values);                //Hashtable may be changed here
                foreach (Sequence sequence in sequenceList)
                {
                    switch (dataMessage.operation)
                    {
                    case DataMessage.CreateOperation:
                    case DataMessage.CreateAndSequenceOperation:
                        RefreshSequence(sequence, dataMessage, dataMessage.body, dataServiceTransaction);
                        break;

                    case DataMessage.DeleteOperation: {
                        //RefreshSequence(sequence, dataMessage, dataMessage.body, dataServiceTransaction);
                        Identity identity = Identity.GetIdentity(dataMessage.body, _dataDestination);
                        int      index    = sequence.IndexOf(identity);
                        if (index != -1)
                        {
                            RemoveIdentityFromSequence(sequence, identity, dataServiceTransaction);
                        }
                    }
                    break;

                    case DataMessage.UpdateOperation:
                        RefreshSequence(sequence, dataMessage, (dataMessage.body as IList)[2], dataServiceTransaction);
                        break;
                    }
                }
            }
        }
        public Sequence RefreshSequence(Sequence sequence, DataMessage dataMessage, object item, DataServiceTransaction dataServiceTransaction)
        {
            if (sequence.Parameters == null)
            {
                return(sequence);
            }
            DotNetAdapter dotNetAdapter = _dataDestination.ServiceAdapter as DotNetAdapter;

            if (dotNetAdapter != null)
            {
                bool isCreate = (dataMessage.operation == DataMessage.CreateOperation || dataMessage.operation == DataMessage.CreateAndSequenceOperation);
                int  fill     = dotNetAdapter.RefreshFill(sequence.Parameters, item, isCreate);
                switch (fill)
                {
                case Assembler.ExecuteFill: {
                    IList parameters = sequence.Parameters;
                    //if (parameters == null)
                    //    parameters = new object[0];
                    DataMessage fillDataMessage = new DataMessage();
                    fillDataMessage.clientId  = dataMessage.clientId;
                    fillDataMessage.operation = DataMessage.FillOperation;
                    fillDataMessage.body      = parameters != null ? parameters : new object[0];
                    IList result = _dataDestination.ServiceAdapter.Invoke(fillDataMessage) as IList;
                    return(CreateSequence(dataMessage.clientId as string, result, parameters, dataServiceTransaction));
                }

                case Assembler.AppendToFill: {
                    Identity identity = Identity.GetIdentity(item, _dataDestination);
                    if (!sequence.Contains(identity))
                    {
                        AddIdentityToSequence(sequence, identity, dataServiceTransaction);
                    }
                    _itemIdToItemHash[identity] = new ItemWrapper(item);
                }
                break;

                case Assembler.RemoveFromFill: {
                    Identity identity = Identity.GetIdentity(item, _dataDestination);
                    if (sequence.Contains(identity))
                    {
                        RemoveIdentityFromSequence(sequence, identity, dataServiceTransaction);
                    }
                }
                break;

                case Assembler.DoNotExecuteFill:
                    break;
                }
            }
            return(sequence);
        }
        public Sequence CreateSequence(string clientId, IList result, IList parameters, DataServiceTransaction dataServiceTransaction)
        {
            Sequence sequence = null;

            Identity[] identities = new Identity[result.Count];

            lock (_objLock) {
                for (int i = 0; i < identities.Length; i++)
                {
                    if (result[i] != null)
                    {
                        Identity identity = Identity.GetIdentity(result[i], _dataDestination);
                        identities[i] = identity;
                        if (!_itemIdToItemHash.ContainsKey(identity))
                        {
                            _itemIdToItemHash.Add(identity, new ItemWrapper(result[i]));
                        }
                        else
                        {
                            ItemWrapper itemWrapper = _itemIdToItemHash[identity] as ItemWrapper;
                            itemWrapper.Instance = result[i];
                        }
                    }
                }
                //Lookup existing sequence
                if (parameters != null)
                {
                    if (_parametersToSequenceIdHash.Contains(parameters))
                    {
                        sequence = _parametersToSequenceIdHash[parameters] as Sequence;
                    }
                }
                else
                {
                    IDictionary sequenceIdMap = _itemIdToSequenceIdMapHash[identities[0]] as IDictionary;
                    if (sequenceIdMap != null)
                    {
                        foreach (Sequence sequenceTmp in sequenceIdMap.Values)
                        {
                            if (sequenceTmp.Parameters == null)
                            {
                                sequence = sequenceTmp;
                                break;
                            }
                        }
                    }
                }
                //if (parameters == null)
                //    parameters = new ArrayList();

                if (sequence == null)
                {
                    sequence    = new Sequence();
                    sequence.Id = sequence.GetHashCode();

                    object[] parametersArray = null;
                    if (parameters != null)
                    {
                        parametersArray = new object[parameters.Count];
                        parameters.CopyTo(parametersArray, 0);
                        sequence.Parameters = parametersArray;
                        _parametersToSequenceIdHash[parameters] = sequence;
                    }

                    for (int i = 0; i < identities.Length; i++)
                    {
                        Identity identity = identities[i];
                        AddIdentityToSequence(sequence, identity, dataServiceTransaction);
                    }

                    _sequenceIdToSequenceHash[sequence.Id] = sequence;

                    if (log.IsDebugEnabled)
                    {
                        log.Debug(__Res.GetString(__Res.SequenceManager_CreateSeq, sequence.Id, clientId));
                    }
                }
                else
                {
                    for (int i = 0; i < identities.Length; i++)
                    {
                        Identity identity         = identities[i];
                        Identity existingIdentity = null;
                        if (i < sequence.Count)
                        {
                            existingIdentity = sequence[i];
                        }
                        if (!identity.Equals(existingIdentity))
                        {
                            //Identity not found in sequence
                            if (!sequence.Contains(identity))
                            {
                                int position = AddIdentityToSequence(sequence, identity, dataServiceTransaction);
                            }
                        }
                    }
                }
                sequence.AddSubscriber(clientId);
                ArrayList sequences;
                if (_clientIdToSequenceHash.Contains(clientId))
                {
                    sequences = _clientIdToSequenceHash[clientId] as ArrayList;
                }
                else
                {
                    sequences = new ArrayList();
                    _clientIdToSequenceHash[clientId] = sequences;
                }
                if (!sequences.Contains(sequence))
                {
                    sequences.Add(sequence);
                }
            }
            return(sequence);
        }