Example #1
0
        public override void OnPut(string key, RavenJObject document, RavenJObject metadata, TransactionInformation transactionInformation)
        {
            if (key.StartsWith("Raven/", StringComparison.OrdinalIgnoreCase) &&             // we don't deal with system documents
                key.StartsWith("Raven/Hilo/", StringComparison.OrdinalIgnoreCase) == false) // except for hilos
            {
                return;
            }
            using (Database.DisableAllTriggersForCurrentThread())
            {
                var documentMetadata = GetDocumentMetadata(key);
                if (documentMetadata != null)
                {
                    RavenJArray history = new RavenJArray(ReplicationData.GetHistory(documentMetadata));
                    metadata[Constants.RavenReplicationHistory] = history;

                    if (documentMetadata.ContainsKey(Constants.RavenReplicationVersion) &&
                        documentMetadata.ContainsKey(Constants.RavenReplicationSource))
                    {
                        history.Add(new RavenJObject
                        {
                            { Constants.RavenReplicationVersion, documentMetadata[Constants.RavenReplicationVersion] },
                            { Constants.RavenReplicationSource, documentMetadata[Constants.RavenReplicationSource] }
                        });
                    }

                    while (history.Length > Constants.ChangeHistoryLength)
                    {
                        history.RemoveAt(0);
                    }
                }

                metadata[Constants.RavenReplicationVersion] = RavenJToken.FromObject(HiLo.NextId());
                metadata[Constants.RavenReplicationSource]  = RavenJToken.FromObject(Database.TransactionalStorage.Id);
            }
        }
		public override void OnPut(string key, Stream data, RavenJObject metadata)
		{
			if (key.StartsWith("Raven/")) // we don't deal with system attachment
				return;
			using (Database.DisableAllTriggersForCurrentThread())
			{
				var attachmentMetadata = GetAttachmentMetadata(key);
				if (attachmentMetadata != null)
				{
					RavenJArray history = new RavenJArray(metadata.Value<RavenJArray>(Constants.RavenReplicationHistory));
					metadata[Constants.RavenReplicationHistory] = history;

					if (attachmentMetadata.ContainsKey(Constants.RavenReplicationVersion) &&
						attachmentMetadata.ContainsKey(Constants.RavenReplicationSource))
					{
						history.Add(new RavenJObject
						{
							{Constants.RavenReplicationVersion, attachmentMetadata[Constants.RavenReplicationVersion]},
							{Constants.RavenReplicationSource, attachmentMetadata[Constants.RavenReplicationSource]}
						});
					}

					if (history.Length > Constants.ChangeHistoryLength)
					{
						history.RemoveAt(0);
					}
				}

				metadata[Constants.RavenReplicationVersion] = RavenJToken.FromObject(HiLo.NextId());
				metadata[Constants.RavenReplicationSource] = RavenJToken.FromObject(Database.TransactionalStorage.Id);
			}
		}
		public override void OnPut(string key, RavenJObject document, RavenJObject metadata, TransactionInformation transactionInformation)
		{
			if (key.StartsWith("Raven/", StringComparison.OrdinalIgnoreCase) && // we don't deal with system documents
				key.StartsWith("Raven/Hilo/", StringComparison.OrdinalIgnoreCase) == false) // except for hilos
				return;
			using (Database.DisableAllTriggersForCurrentThread())
			{
				var documentMetadata = GetDocumentMetadata(key);
				if (documentMetadata != null)
				{
					RavenJArray history = new RavenJArray(ReplicationData.GetHistory(documentMetadata));
					metadata[Constants.RavenReplicationHistory] = history;

					if (documentMetadata.ContainsKey(Constants.RavenReplicationVersion) && 
						documentMetadata.ContainsKey(Constants.RavenReplicationSource))
					{
						history.Add(new RavenJObject
						{
							{Constants.RavenReplicationVersion, documentMetadata[Constants.RavenReplicationVersion]},
							{Constants.RavenReplicationSource, documentMetadata[Constants.RavenReplicationSource]}
						});
					}

					while (history.Length > Constants.ChangeHistoryLength)
					{
						history.RemoveAt(0);
					}
				}

				metadata[Constants.RavenReplicationVersion] = RavenJToken.FromObject(HiLo.NextId());
				metadata[Constants.RavenReplicationSource] = RavenJToken.FromObject(Database.TransactionalStorage.Id);
			}
		}
        public override void OnPut(string key, Stream data, RavenJObject metadata)
        {
            if (key.StartsWith("Raven/"))             // we don't deal with system attachment
            {
                return;
            }
            using (Database.DisableAllTriggersForCurrentThread())
            {
                var attachmentMetadata = GetAttachmentMetadata(key);
                if (attachmentMetadata != null)
                {
                    RavenJArray history = new RavenJArray(ReplicationData.GetHistory(metadata));
                    metadata[Constants.RavenReplicationHistory] = history;

                    if (attachmentMetadata.ContainsKey(Constants.RavenReplicationVersion) &&
                        attachmentMetadata.ContainsKey(Constants.RavenReplicationSource))
                    {
                        history.Add(new RavenJObject
                        {
                            { Constants.RavenReplicationVersion, attachmentMetadata[Constants.RavenReplicationVersion] },
                            { Constants.RavenReplicationSource, attachmentMetadata[Constants.RavenReplicationSource] }
                        });
                    }

                    while (history.Length > Constants.ChangeHistoryLength)
                    {
                        history.RemoveAt(0);
                    }
                }

                metadata[Constants.RavenReplicationVersion] = RavenJToken.FromObject(HiLo.NextId());
                metadata[Constants.RavenReplicationSource]  = RavenJToken.FromObject(Database.TransactionalStorage.Id);
            }
        }
Example #5
0
        private void RemoveValue(PatchRequest patchCmd, string propName, RavenJToken token)
        {
            EnsurePreviousValueMatchCurrentValue(patchCmd, token);
            if (token == null)
            {
                token = new RavenJArray();
                document[propName] = token;
            }
            var array = GetArray(token, propName);

            array = new RavenJArray(array);
            document[propName] = array;

            var position = patchCmd.Position;
            var value    = patchCmd.Value;

            if (position == null && (value == null || value.Type == JTokenType.Null))
            {
                throw new InvalidOperationException("Cannot remove value from  '" + propName +
                                                    "' because position element does not exists or not an integer and no value was present");
            }
            if (position != null && value != null && value.Type != JTokenType.Null)
            {
                throw new InvalidOperationException("Cannot remove value from  '" + propName +
                                                    "' because both a position and a value are set");
            }
            if (position != null && (position.Value < 0 || position.Value >= array.Length))
            {
                throw new IndexOutOfRangeException("Cannot remove value from  '" + propName +
                                                   "' because position element is out of bounds");
            }

            if (value != null && value.Type != JTokenType.Null)
            {
                foreach (var ravenJToken in array.Where(x => RavenJToken.DeepEquals(x, value)).ToList())
                {
                    array.Remove(ravenJToken);
                }

                return;
            }

            if (position != null)
            {
                array.RemoveAt(position.Value);
            }
        }
		public override void OnPut(string key, RavenJObject document, RavenJObject metadata, TransactionInformation transactionInformation)
		{
			using (Database.DisableAllTriggersForCurrentThread())
			{
				if (metadata.Remove(Constants.RavenReplicationConflictSkipResolution))
				{
					if (key.IndexOf("/conflicts/", StringComparison.OrdinalIgnoreCase) == -1)
					{
						metadata["@Http-Status-Code"] = 409;
						metadata["@Http-Status-Description"] = "Conflict";
					}

					return;
				}

				metadata.Remove(Constants.RavenReplicationConflict);// you can't put conflicts

				var oldVersion = Database.Documents.Get(key, transactionInformation);
				if (oldVersion == null)
					return;
				if (oldVersion.Metadata[Constants.RavenReplicationConflict] == null)
					return;

				var history = new RavenJArray();
				metadata[Constants.RavenReplicationHistory] = history;

				// this is a conflict document, holding document keys in the 
				// values of the properties
				var conflicts = oldVersion.DataAsJson.Value<RavenJArray>("Conflicts");
				if(conflicts == null)
					return;

			    var list = new List<RavenJArray>
			    {
			        new RavenJArray(ReplicationData.GetHistory(metadata)) // first item to interleave
			    };

				foreach (var prop in conflicts)
				{
					RavenJObject deletedMetadata;
					Database.Documents.Delete(prop.Value<string>(), null, transactionInformation, out deletedMetadata);

				    if (deletedMetadata != null)
				    {
                        var conflictHistory = new RavenJArray(ReplicationData.GetHistory(deletedMetadata));
                        conflictHistory.Add(new RavenJObject
				        {
				            {Constants.RavenReplicationVersion, deletedMetadata[Constants.RavenReplicationVersion]},
				            {Constants.RavenReplicationSource, deletedMetadata[Constants.RavenReplicationSource]}
				        });
				        list.Add(conflictHistory);
				    }
				}


			    int index = 0;
                bool added = true;
                while (added) // interleave the history from all conflicts
                {
                    added = false;
                    foreach (var deletedMetadata in list)
			        {
                        // add the conflict history to the mix, so we make sure that we mark that we resolved the conflict
			            if (index < deletedMetadata.Length)
			            {
			                history.Add(deletedMetadata[index]);
			                added = true;
			            }
			        }
			        index++;
			    }

                while (history.Length > Constants.ChangeHistoryLength)
                {
                    history.RemoveAt(0);
                }
			}
		}
Example #7
0
        public override void OnPut(string key, RavenJObject jsonReplicationDocument, RavenJObject metadata, TransactionInformation transactionInformation)
        {
            if (key.StartsWith("Raven/", StringComparison.OrdinalIgnoreCase) &&             // we don't deal with system documents
                key.StartsWith("Raven/Hilo/", StringComparison.OrdinalIgnoreCase) == false) // except for hilos
            {
                return;
            }

            using (Database.DisableAllTriggersForCurrentThread())
            {
                var documentMetadata = GetDocumentMetadata(key);
                if (documentMetadata == null)
                {
                    var history = new RavenJArray()
                    {
                        new RavenJObject
                        {
                            { Constants.RavenReplicationVersion, metadata[Constants.RavenReplicationVersion] },
                            { Constants.RavenReplicationSource, metadata[Constants.RavenReplicationSource] }
                        }
                    };
                }
                else
                {
                    var history = new RavenJArray(ReplicationData.GetOrCreateHistory(documentMetadata));

                    if (documentMetadata.ContainsKey(Constants.RavenReplicationMergedHistory) == false)
                    {
                        if (documentMetadata.ContainsKey(Constants.RavenReplicationVersion) &&
                            documentMetadata.ContainsKey(Constants.RavenReplicationSource))
                        {
                            history.Add(new RavenJObject
                            {
                                { Constants.RavenReplicationVersion, documentMetadata[Constants.RavenReplicationVersion] },
                                { Constants.RavenReplicationSource, documentMetadata[Constants.RavenReplicationSource] }
                            });
                        }
                        else
                        {
                            history.Add(new RavenJObject
                            {
                                { Constants.RavenReplicationVersion, 0 },
                                { Constants.RavenReplicationSource, RavenJToken.FromObject(Database.TransactionalStorage.Id) }
                            });
                        }

                        var sources = new HashSet <RavenJToken>(RavenJTokenEqualityComparer.Default);
                        int pos     = history.Length - 1;
                        for (; pos >= 0; pos--)
                        {
                            var source = ((RavenJObject)history[pos])[Constants.RavenReplicationSource];
                            if (sources.Contains(source))
                            {
                                history.RemoveAt(pos);
                                continue;
                            }
                            sources.Add(source);
                        }
                        metadata[Constants.RavenReplicationMergedHistory] = true;
                        metadata[Constants.RavenReplicationHistory]       = history;
                    }
                    //If we have the flag we must have Constants.RavenReplicationVersion and Constants.RavenReplicationSource too
                    //Here we assume that the replication history is in the form of a "sorted dictionary" so we just need to remove
                    //the entry with the current source id and insert the new version at the end of the history.
                    else
                    {
                        int i = history.Length - 1;
                        for (; i >= 0; i--)
                        {
                            var currentEntry = history[i];
                            if (RavenJTokenEqualityComparer.Default.Equals(((RavenJObject)currentEntry)
                                                                           [Constants.RavenReplicationSource], documentMetadata[Constants.RavenReplicationSource]))
                            {
                                break;
                            }
                        }
                        if (i != -1)
                        {
                            history.RemoveAt(i);
                        }
                        history.Add(new RavenJObject
                        {
                            { Constants.RavenReplicationVersion, documentMetadata[Constants.RavenReplicationVersion] },
                            { Constants.RavenReplicationSource, documentMetadata[Constants.RavenReplicationSource] }
                        });
                        metadata[Constants.RavenReplicationHistory] = history;
                    }
                }

                metadata[Constants.RavenReplicationVersion] = RavenJToken.FromObject(ReplicationHiLo.NextId(Database));
                metadata[Constants.RavenReplicationSource]  = RavenJToken.FromObject(Database.TransactionalStorage.Id);
            }
        }
Example #8
0
		private void RemoveValue(PatchRequest patchCmd, string propName, RavenJToken token)
		{
			EnsurePreviousValueMatchCurrentValue(patchCmd, token);
			if (token == null)
			{
				token = new RavenJArray();
				document[propName] = token;
			}
			var array = GetArray(token, propName);
			array = new RavenJArray(array);
			document[propName] = array;

			var position = patchCmd.Position;
			var value = patchCmd.Value;
			if (position == null && (value == null || value.Type == JTokenType.Null))
				throw new InvalidOperationException("Cannot remove value from  '" + propName +
				                                    "' because position element does not exists or not an integer and no value was present");
			if (position != null && value != null && value.Type != JTokenType.Null)
				throw new InvalidOperationException("Cannot remove value from  '" + propName +
				                                    "' because both a position and a value are set");
			if (position != null && (position.Value < 0 || position.Value >= array.Length))
				throw new IndexOutOfRangeException("Cannot remove value from  '" + propName +
				                                   "' because position element is out of bounds");

			if (value != null && value.Type != JTokenType.Null)
			{
				foreach (var ravenJToken in array.Where(x => RavenJToken.DeepEquals(x, value)).ToList())
				{
					array.Remove(ravenJToken);
				}

				return;
			}

			if (position != null)
				array.RemoveAt(position.Value);
		}
        private void ReplicateDelete(string id, RavenJObject metadata, TExternal incoming)
        {
            TInternal existingItem;
            Guid      existingEtag;
            var       existingMetadata = TryGetExisting(id, out existingItem, out existingEtag);

            if (existingMetadata == null)
            {
                log.Debug("Replicating deleted item {0} from {1} that does not exist, ignoring", id, Src);
                return;
            }
            if (existingMetadata.Value <bool>(Constants.RavenReplicationConflict))            // locally conflicted
            {
                log.Debug("Replicating deleted item {0} from {1} that is already conflicted, adding to conflicts.", id, Src);
                var savedConflictedItemId = SaveConflictedItem(id, metadata, incoming, existingEtag);
                AppendToCurrentItemConflicts(id, savedConflictedItemId, existingMetadata, existingItem);
                return;
            }
            if (existingMetadata.Value <bool>(Constants.RavenDeleteMarker))           //deleted locally as well
            {
                log.Debug("Replicating deleted item {0} from {1} that was deleted locally. Merging histories", id, Src);
                var existingHistory = new RavenJArray(existingMetadata.Value <RavenJArray>(Constants.RavenReplicationHistory));
                var newHistory      = new RavenJArray(metadata.Value <RavenJArray>(Constants.RavenReplicationHistory));

                foreach (var item in newHistory)
                {
                    existingHistory.Add(item);
                }


                if (metadata.ContainsKey(Constants.RavenReplicationVersion) &&
                    metadata.ContainsKey(Constants.RavenReplicationSource))
                {
                    existingHistory.Add(new RavenJObject
                    {
                        { Constants.RavenReplicationVersion, metadata[Constants.RavenReplicationVersion] },
                        { Constants.RavenReplicationSource, metadata[Constants.RavenReplicationSource] }
                    });
                }

                while (existingHistory.Length > Constants.ChangeHistoryLength)
                {
                    existingHistory.RemoveAt(0);
                }

                MarkAsDeleted(id, metadata);
                return;
            }
            if (Historian.IsDirectChildOfCurrent(metadata, existingMetadata))           // not modified
            {
                log.Debug("Delete of existing item {0} was replicated successfully from {1}", id, Src);
                DeleteItem(id, existingEtag);
                MarkAsDeleted(id, metadata);
                return;
            }

            Database.TransactionalStorage.ExecuteImmediatelyOrRegisterForSynchronization(() =>
                                                                                         Database.RaiseNotifications(new DocumentChangeNotification
            {
                Id   = id,
                Type = DocumentChangeTypes.ReplicationConflict
            }));
            var newConflictId = SaveConflictedItem(id, metadata, incoming, existingEtag);

            log.Debug("Existing item {0} is in conflict with replicated delete from {1}, marking item as conflicted", id, Src);

            // we have a new conflict  move the existing doc to a conflict and create a conflict document
            var existingDocumentConflictId = id + "/conflicts/" + HashReplicationIdentifier(existingEtag);

            CreateConflict(id, newConflictId, existingDocumentConflictId, existingItem, existingMetadata);
        }
Example #10
0
        public override void OnPut(string key, RavenJObject document, RavenJObject metadata, TransactionInformation transactionInformation)
        {
            using (Database.DisableAllTriggersForCurrentThread())
            {
                metadata.Remove(Constants.RavenReplicationConflict);                // you can't put conflicts

                var oldVersion = Database.Get(key, transactionInformation);
                if (oldVersion == null)
                {
                    return;
                }
                if (oldVersion.Metadata[Constants.RavenReplicationConflict] == null)
                {
                    return;
                }

                var history = new RavenJArray();
                metadata[Constants.RavenReplicationHistory] = history;

                var ravenJTokenEqualityComparer = new RavenJTokenEqualityComparer();
                // this is a conflict document, holding document keys in the
                // values of the properties
                var conflicts = oldVersion.DataAsJson.Value <RavenJArray>("Conflicts");
                if (conflicts == null)
                {
                    return;
                }

                var list = new List <RavenJArray>
                {
                    new RavenJArray(ReplicationData.GetHistory(metadata))             // first item to interleave
                };
                foreach (var prop in conflicts)
                {
                    RavenJObject deletedMetadata;
                    Database.Delete(prop.Value <string>(), null, transactionInformation, out deletedMetadata);

                    if (deletedMetadata != null)
                    {
                        var conflictHistory = new RavenJArray(ReplicationData.GetHistory(deletedMetadata));
                        conflictHistory.Add(new RavenJObject
                        {
                            { Constants.RavenReplicationVersion, deletedMetadata[Constants.RavenReplicationVersion] },
                            { Constants.RavenReplicationSource, deletedMetadata[Constants.RavenReplicationSource] }
                        });
                        list.Add(conflictHistory);
                    }
                }


                int  index = 0;
                bool added = true;
                while (added) // interleave the history from all conflicts
                {
                    added = false;
                    foreach (var deletedMetadata in list)
                    {
                        // add the conflict history to the mix, so we make sure that we mark that we resolved the conflict
                        if (index < deletedMetadata.Length)
                        {
                            history.Add(deletedMetadata[index]);
                            added = true;
                        }
                    }
                    index++;
                }

                while (history.Length > Constants.ChangeHistoryLength)
                {
                    history.RemoveAt(0);
                }
            }
        }
        public override void OnPut(string key, RavenJObject jsonReplicationDocument, RavenJObject metadata)
        {
            using (Database.DisableAllTriggersForCurrentThread())
            {
                if (metadata.Remove(Constants.RavenReplicationConflictSkipResolution))
                {
                    if (key.IndexOf("/conflicts/", StringComparison.OrdinalIgnoreCase) == -1)
                    {
                        metadata["@Http-Status-Code"]        = 409;
                        metadata["@Http-Status-Description"] = "Conflict";
                    }

                    return;
                }

                metadata.Remove(Constants.RavenReplicationConflict);// you can't put conflicts

                var oldVersion = Database.Documents.Get(key);
                if (oldVersion == null)
                {
                    return;
                }
                if (oldVersion.Metadata[Constants.RavenReplicationConflict] == null)
                {
                    return;
                }

                var history = new RavenJArray();
                metadata[Constants.RavenReplicationHistory] = history;

                // this is a conflict document, holding document keys in the
                // values of the properties
                var conflicts = oldVersion.DataAsJson.Value <RavenJArray>("Conflicts");
                if (conflicts == null)
                {
                    return;
                }

                var list = new List <RavenJArray>
                {
                    new RavenJArray(ReplicationData.GetHistory(metadata)) // first item to interleave
                };

                foreach (var prop in conflicts)
                {
                    RavenJObject deletedMetadata;
                    Database.Documents.Delete(prop.Value <string>(), null, out deletedMetadata);

                    if (deletedMetadata != null)
                    {
                        var conflictHistory = new RavenJArray(ReplicationData.GetHistory(deletedMetadata));
                        conflictHistory.Add(new RavenJObject
                        {
                            { Constants.RavenReplicationVersion, deletedMetadata[Constants.RavenReplicationVersion] },
                            { Constants.RavenReplicationSource, deletedMetadata[Constants.RavenReplicationSource] }
                        });
                        list.Add(conflictHistory);
                    }
                }


                int  index = 0;
                bool added = true;
                while (added) // interleave the history from all conflicts
                {
                    added = false;
                    foreach (var deletedMetadata in list)
                    {
                        // add the conflict history to the mix, so we make sure that we mark that we resolved the conflict
                        if (index < deletedMetadata.Length)
                        {
                            history.Add(deletedMetadata[index]);
                            added = true;
                        }
                    }
                    index++;
                }

                while (history.Length > Constants.ChangeHistoryLength)
                {
                    history.RemoveAt(0);
                }
            }
        }