public DatabaseBulkOperations(DocumentDatabase database, TransactionInformation transactionInformation, CancellationTokenSource tokenSource, CancellationTimeout timeout)
		{
			this.database = database;
			this.transactionInformation = transactionInformation;
			this.tokenSource = tokenSource;
			this.timeout = timeout;
		}
		public override void OnPut(string key, RavenJObject document, RavenJObject metadata, TransactionInformation transactionInformation)
		{
			VersioningConfiguration versioningConfiguration;

			if (metadata.ContainsKey(Constants.RavenCreateVersion))
			{
				metadata.__ExternalState[Constants.RavenCreateVersion] = metadata[Constants.RavenCreateVersion];
				metadata.Remove(Constants.RavenCreateVersion);
			}

			if (TryGetVersioningConfiguration(key, metadata, out versioningConfiguration) == false)
				return;

			var revision = GetNextRevisionNumber(key);

			using (Database.DisableAllTriggersForCurrentThread())
			{
				RemoveOldRevisions(key, revision, versioningConfiguration, transactionInformation);
			}
			metadata.__ExternalState["Next-Revision"] = revision;

			metadata.__ExternalState["Parent-Revision"] = metadata.Value<string>(VersioningUtil.RavenDocumentRevision);

			metadata[VersioningUtil.RavenDocumentRevisionStatus] = RavenJToken.FromObject("Current");
			metadata[VersioningUtil.RavenDocumentRevision] = RavenJToken.FromObject(revision);
		}
Example #3
0
		public static void AssertNotModifiedByAnotherTransaction(TableStorage storage, ITransactionStorageActions transactionStorageActions, string key, Table.ReadResult readResult, TransactionInformation transactionInformation)
		{
			if (readResult == null)
				return;
			var txIdAsBytes = readResult.Key.Value<byte[]>("txId");
			if (txIdAsBytes == null)
				return;

			var txId = new Guid(txIdAsBytes);
			if (transactionInformation != null && transactionInformation.Id == txId)
			{
				return;
			}

			var existingTx = storage.Transactions.Read(new RavenJObject { { "txId", txId.ToByteArray() } });
			if (existingTx == null)//probably a bug, ignoring this as not a real tx
				return;

			var timeout = existingTx.Key.Value<DateTime>("timeout");
			if (SystemTime.UtcNow > timeout)
			{
				transactionStorageActions.RollbackTransaction(txId);
				return;
			}

			throw new ConcurrencyException("Document '" + key + "' is locked by transacton: " + txId);
		}
Example #4
0
		public void AfterCommittingCanSeeChangesWithoutTx()
		{
			var transactionInformation = new TransactionInformation
			{
				Id = Guid.NewGuid(),
				Timeout = TimeSpan.FromDays(7)
			};

			using (var tx = NewTransactionalStorage())
			{
				tx.Batch(mutator => mutator.Transactions.AddDocumentInTransaction("Ayende", null, RavenJObject.FromObject(new { Name = "Rahien" }), new RavenJObject(),
					transactionInformation));

				tx.Batch(mutator => mutator.Transactions.CompleteTransaction(transactionInformation.Id, data =>
				{
					if (data.Delete)
					{
						RavenJObject metadata;
						mutator.Documents.DeleteDocument(data.Key, null, out metadata);
					}
					else
						mutator.Documents.AddDocument(data.Key, null, data.Data, data.Metadata);
				}));
				tx.Batch(viewer =>
					Assert.NotNull(viewer.Documents.DocumentByKey("Ayende", null)));
			}
		}
        public override ReadVetoResult AllowRead(string key, RavenJObject metadata, ReadOperation operation, TransactionInformation transactionInformation)
        {
            // This trigger is only for simple query operations
            if (key == null || operation != ReadOperation.Query)
                return ReadVetoResult.Allowed;

            // Don't do anything if temporal versioning is inactive for this document type
            if (!Database.IsTemporalVersioningEnabled(key, metadata))
                return ReadVetoResult.Allowed;

            // If an effective date was passed in, then use it.
            DateTimeOffset effective;
            var headerValue = CurrentOperationContext.Headers.Value[TemporalMetadata.RavenTemporalEffective];
            if (headerValue == null || !DateTimeOffset.TryParse(headerValue, null, DateTimeStyles.RoundtripKind, out effective))
            {
                // If no effective data passed, return as stored.
                return ReadVetoResult.Allowed;
            }

            // Return the requested effective date in the metadata.
            var temporal = metadata.GetTemporalMetadata();
            temporal.Effective = effective;

            // Return the result if it's the active revision, or skip it otherwise.
            return temporal.Status == TemporalStatus.Revision &&
                   temporal.EffectiveStart <= effective && effective < temporal.EffectiveUntil &&
                   !temporal.Deleted
                       ? ReadVetoResult.Allowed
                       : ReadVetoResult.Ignore;
        }
        public override void OnPut(string key, RavenJObject document, RavenJObject metadata, TransactionInformation transactionInformation)
        {
            if (!metadata.ContainsKey("IsRoutable") || !metadata.Value<bool>("IsRoutable")) {
                return;
            }

            RavenJToken parentIdToken;
            RavenJToken slugToken;
            if (document.TryGetValue("ParentId", out parentIdToken) && document.TryGetValue("Slug", out slugToken)) {
                var parentId = parentIdToken.Value<string>();
                var slug = slugToken.Value<string>();

                string parentPath = null;
                if (!String.IsNullOrEmpty(parentId)) {
                    var parent = Database.Get(parentId, transactionInformation);
                    parentPath = parent.DataAsJson["Path"].Value<string>();
                }

                if (String.IsNullOrEmpty(parentPath)) {
                    document["Path"] = slug;
                } else {
                    document["Path"] = parentPath + "/" + slug;
                }
            }

            base.OnPut(key, document, metadata, transactionInformation);
        }
Example #7
0
		public override void OnPut(string key, RavenJObject document, RavenJObject metadata, TransactionInformation transactionInformation)
		{
			if (key.StartsWith("Raven/", StringComparison.InvariantCultureIgnoreCase))
				return;

			if (metadata.Value<string>(VersioningUtil.RavenDocumentRevisionStatus) == "Historical")
				return;

			var versioningConfiguration = Database.GetDocumentVersioningConfiguration(metadata);
			if (versioningConfiguration == null || versioningConfiguration.Exclude)
				return;

			using (Database.DisableAllTriggersForCurrentThread())
			{
				var copyMetadata = new RavenJObject(metadata);
				copyMetadata[VersioningUtil.RavenDocumentRevisionStatus] = RavenJToken.FromObject("Historical");
				copyMetadata[Constants.RavenReadOnly] = true;
				copyMetadata.Remove(VersioningUtil.RavenDocumentRevision);
				var parentRevision = metadata.Value<string>(VersioningUtil.RavenDocumentRevision);
				if (parentRevision != null)
				{
					copyMetadata[VersioningUtil.RavenDocumentParentRevision] = key + "/revisions/" + parentRevision;
					metadata[VersioningUtil.RavenDocumentParentRevision] = key + "/revisions/" + parentRevision;
				}

				PutResult newDoc = Database.Put(key + "/revisions/", null, document, copyMetadata,
				                                transactionInformation);
				int revision = int.Parse(newDoc.Key.Split('/').Last());

				RemoveOldRevisions(key, revision, versioningConfiguration, transactionInformation);

				metadata[VersioningUtil.RavenDocumentRevisionStatus] = RavenJToken.FromObject("Current");
				metadata[VersioningUtil.RavenDocumentRevision] = RavenJToken.FromObject(revision);
			}
		}
        public override VetoResult AllowDelete(string key, TransactionInformation transactionInformation)
        {
            if (key == Constants.InResourceKeyVerificationDocumentName)
                return VetoResult.Deny("Cannot delete the encryption verification document.");

            return base.AllowDelete(key, transactionInformation);
        }
        public override void AfterPut(string key, RavenJObject document, RavenJObject metadata, Etag etag, TransactionInformation transactionInformation)
        {
            if (key.StartsWith("Raven/", StringComparison.InvariantCultureIgnoreCase))
            return;

              var status = document.Value<string>("Status");
              if (string.IsNullOrWhiteSpace(status) || !status.Equals("Published", StringComparison.InvariantCultureIgnoreCase))
            return;

              if (metadata.Value<string>(PublishedVersioningConstants.AtisDocumentRevisionStatus) == "Historical")
            return;

              using (Database.DisableAllTriggersForCurrentThread())
              {
            var copyMetadata = new RavenJObject(metadata);
            copyMetadata[PublishedVersioningConstants.AtisDocumentRevisionStatus] = RavenJToken.FromObject("Historical");
            copyMetadata[Constants.RavenReadOnly] = true;
            copyMetadata.Remove(PublishedVersioningConstants.AtisDocumentRevision);

            object value;
            metadata.__ExternalState.TryGetValue("Next-Revision", out value);
            var revisionKey = string.Format("{0}/PublishedRevisions/{1}", key, value);
            Database.Put(revisionKey, null, (RavenJObject)document.CreateSnapshot(), copyMetadata, transactionInformation);
            log.Debug(() => string.Format("Created published revision with key [{0}]", revisionKey));
              }
        }
Example #10
0
        /// <summary>
        /// Called when [put].
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="document">The document.</param>
        /// <param name="metadata">The metadata.</param>
        /// <param name="transactionInformation">The transaction information.</param>
        public override void OnPut(string key, RavenJObject document, RavenJObject metadata, TransactionInformation transactionInformation)
        {
            if (key.StartsWith("Raven/",true,CultureInfo.InvariantCulture)) // we don't deal with system documents
                return;

            if (TriggerContext.IsInTriggerContext)
                return;

            using (TriggerContext.Enter()) {
                var meta = document["MetaData"] as RavenJObject;
                if(meta != null) {
                    var slug = meta.Value<string>("Slug");
                    RavenJToken parent;
                    if (document.TryGetValue("Parent", out parent) && parent.Type != JTokenType.Null) {
                        var parentId = parent.Value<string>("Id");
                        var parentDocument = Database.Get(parentId, transactionInformation);
                        var parentUrl = parentDocument.DataAsJson.Value<JObject>("Metadata").Value<string>("Url");
                        if (parentUrl != null) {
                            meta["Url"] = string.Format("{0}/{1}", parentUrl, slug);
                            base.OnPut(key, document, metadata, transactionInformation);
                            return;
                        }
                    }
                    meta["Url"] = slug;
                }
            }
            base.OnPut(key, document, metadata, transactionInformation);
        }
Example #11
0
		public override void OnPut(string key, RavenJObject document, RavenJObject metadata, TransactionInformation transactionInformation)
		{
			if (key.StartsWith("Raven/")) // we don't deal with system documents
				return;
			var doc = Database.Get(key, null);
			if (doc != null)
			{
				var history = doc.Metadata.Value<RavenJArray>(ReplicationConstants.RavenReplicationHistory) ?? new RavenJArray();
				metadata[ReplicationConstants.RavenReplicationHistory] = history;

				history.Add(new RavenJObject
				{
					{ReplicationConstants.RavenReplicationVersion, doc.Metadata[ReplicationConstants.RavenReplicationVersion]},
					{ReplicationConstants.RavenReplicationSource, doc.Metadata[ReplicationConstants.RavenReplicationSource]}

				});

				if (history.Length > ReplicationConstants.ChangeHistoryLength)
				{
					history.RemoveAt(0);
				}
			}
			metadata[ReplicationConstants.RavenReplicationVersion] = RavenJToken.FromObject(hiLo.NextId());
			metadata[ReplicationConstants.RavenReplicationSource] = RavenJToken.FromObject(Database.TransactionalStorage.Id);
		}
Example #12
0
        private void RecursiveDelete(string key, TransactionInformation transactionInformation)
        {
            var document = Database.Documents.Get(key, transactionInformation);
            if (document == null)
                return;

            var documentsToDelete = document.Metadata.Value<RavenJArray>(MetadataKeys.DocumentsToCascadeDelete);
            if (documentsToDelete != null)
            {
                foreach (var documentToDelete in documentsToDelete)
                {
                    var documentId = documentToDelete.Value<string>();
                    if (!CascadeDeleteContext.HasAlreadyDeletedDocument(documentId))
                    {
                        CascadeDeleteContext.AddDeletedDocument(documentId);
                        RecursiveDelete(documentId, transactionInformation);
                        Database.Documents.Delete(documentId, null, transactionInformation);
                    }
                }
            }
            var attachmentsToDelete = document.Metadata.Value<RavenJArray>(MetadataKeys.AttachmentsToCascadeDelete);

            if (attachmentsToDelete != null)
                foreach (var attachmentToDelete in attachmentsToDelete)
                    Database.Attachments.DeleteStatic(attachmentToDelete.Value<string>(), null);
            return;
        }
Example #13
0
     public long GetNextIdentityValueWithoutOverwritingOnExistingDocuments(string key,
 IStorageActionsAccessor actions,
 TransactionInformation transactionInformation)
     {
         int tries;
         return GetNextIdentityValueWithoutOverwritingOnExistingDocuments(key, actions, transactionInformation, out tries);
     }
        public override VetoResult AllowPut(string key, RavenJObject document, RavenJObject metadata, TransactionInformation transactionInformation)
        {
            // always reset these
            _clearCurrent.Value = false;
            _originalDocument.Value = null;
            _now.Value = SystemTime.UtcNow;

            if (key == null)
                return VetoResult.Allowed;

            // Don't do anything if temporal versioning is inactive for this document type
            if (!Database.IsTemporalVersioningEnabled(key, metadata))
                return VetoResult.Allowed;

            // Don't allow modifications to revision documents
            if (key.Contains(TemporalConstants.TemporalKeySeparator))
                return VetoResult.Deny("Modifying an existing temporal revision directly is not allowed.");

            // If no effective date was passed in, use now.
            var temporal = metadata.GetTemporalMetadata();
            if (!temporal.Effective.HasValue)
                temporal.Effective = _now.Value;

            return VetoResult.Allowed;
        }
		public override void OnDelete(string key, TransactionInformation transactionInformation)
		{
			if (CascadeDeleteContext.IsInCascadeDeleteContext)
				return;

			var document = Database.Get(key, transactionInformation);
			if (document == null)
				return;

			using (CascadeDeleteContext.Enter())
			{
				var documentsToDelete = document.Metadata.Value<RavenJArray>(MetadataKeys.DocumentsToCascadeDelete);

				if (documentsToDelete != null)
				{
					foreach (var documentToDelete in documentsToDelete)
					{
						var documentId = documentToDelete.Value<string>();
						if (!CascadeDeleteContext.HasAlreadyDeletedDocument(documentId))
						{
							CascadeDeleteContext.AddDeletedDocument(documentId);
							Database.Delete(documentId, null, transactionInformation);
						}
					}
				}

				var attachmentsToDelete = document.Metadata.Value<RavenJArray>(MetadataKeys.AttachmentsToCascadeDelete);

				if (attachmentsToDelete != null)
					foreach (var attachmentToDelete in attachmentsToDelete)
						Database.DeleteStatic(attachmentToDelete.Value<string>(), null);
			}
		}
		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 AfterDelete(string key, TransactionInformation transactionInformation)
     {
         var versioningConfig = Database.GetDocumentVersioningConfiguration(versionInformer.Value[key]);
 
         
         using (Database.DisableAllTriggersForCurrentThread())
         {
             Database.TransactionalStorage.Batch(accessor =>
             {
                 using (DocumentCacher.SkipSetDocumentsInDocumentCache())
                 {
                     foreach (var jsonDocument in accessor.Documents.GetDocumentsWithIdStartingWith(key + "/revisions/", 0, int.MaxValue, null))
                     {
                         if (jsonDocument == null)
                             continue;
                         if (versioningConfig != null && versioningConfig.PurgeOnDelete)
                         {
                             Database.Documents.Delete(jsonDocument.Key, null, transactionInformation);
                         }
                         else
                         {
                             jsonDocument.Metadata.Remove(Constants.RavenReadOnly);
                             accessor.Documents.AddDocument(jsonDocument.Key, jsonDocument.Etag, jsonDocument.DataAsJson, jsonDocument.Metadata);
                         }
                     }
                 }
             });
         }
     }
Example #18
0
		public void CanModifyTxId()
		{
			var transactionInformation = new TransactionInformation
			{
				Id = Guid.NewGuid(),
				Timeout = TimeSpan.FromDays(7)
			};

			using (var tx = NewTransactionalStorage())
			{
				tx.Batch(mutator => mutator.Transactions.AddDocumentInTransaction("Ayende", null, RavenJObject.FromObject(new { Name = "Rahien" }), new RavenJObject(),
					transactionInformation));

				var txInfo2 = new TransactionInformation
				{
					Id = Guid.NewGuid(),
					Timeout = TimeSpan.FromDays(1)
				};

				tx.Batch(mutator => mutator.Transactions.ModifyTransactionId(transactionInformation.Id, txInfo2.Id, txInfo2.Timeout));


				tx.Batch(viewer =>
					Assert.NotNull(viewer.Documents.DocumentByKey("Ayende", txInfo2)));
			}
		}
Example #19
0
        public void Delete(string key, Guid?etag, TransactionInformation transactionInformation)
        {
            log.DebugFormat("Delete a document with key: {0} and etag {1}", key, etag);
            TransactionalStorage.Batch(actions =>
            {
                if (transactionInformation == null)
                {
                    AssertDeleteOperationNotVetoed(key, transactionInformation);

                    DeleteTriggers.Apply(trigger => trigger.OnDelete(key, transactionInformation));

                    RavenJObject metadata;
                    if (actions.Documents.DeleteDocument(key, etag, out metadata))
                    {
                        AddIndexingTask(actions, metadata, () => new RemoveFromIndexTask {
                            Keys = new[] { key }
                        });
                        DeleteTriggers.Apply(trigger => trigger.AfterDelete(key, transactionInformation));
                    }
                }
                else
                {
                    actions.Transactions.DeleteDocumentInTransaction(transactionInformation, key, etag);
                }
                workContext.ShouldNotifyAboutWork();
            });
            TransactionalStorage
            .ExecuteImmediatelyOrRegisterForSyncronization(() => DeleteTriggers.Apply(trigger => trigger.AfterCommit(key)));
        }
Example #20
0
        public override VetoResult AllowPut(string key, Raven.Json.Linq.RavenJObject document, Raven.Json.Linq.RavenJObject metadata, TransactionInformation transactionInformation)
        {
            if (key == "Raven/Authorization/WindowsSettings" && Authentication.IsEnabled == false)
                return VetoResult.Deny("Cannot setup Windows Authentication without a valid commercial license.");

            return VetoResult.Allowed;
        }
        public bool RecoverTransaction(string id, IEnumerable <DocumentInTransactionData> changes)
        {
            var txInfo = new TransactionInformation
            {
                Id      = id,
                Timeout = TimeSpan.FromMinutes(5)
            };

            if (changes == null)
            {
                log.Warn("Failed to prepare transaction " + id + " because changes were null, maybe this is a partially committed transaction? Transaction will be rolled back");

                return(false);
            }
            foreach (var changedDoc in changes)
            {
                if (changedDoc == null)
                {
                    log.Warn("Failed preparing a document change in transaction " + id + " with a null change, maybe this is partiall committed transaction? Transaction will be rolled back");
                    return(false);
                }

                changedDoc.Metadata.EnsureCannotBeChangeAndEnableSnapshotting();
                changedDoc.Data.EnsureCannotBeChangeAndEnableSnapshotting();

                //we explicitly pass a null for the etag here, because we might have calls for TouchDocument()
                //that happened during the transaction, which changed the committed etag. That is fine when we are just running
                //the transaction, since we can just report the error and abort. But it isn't fine when we recover
                //var etag = changedDoc.CommittedEtag;
                Etag etag = null;
                AddToTransactionState(changedDoc.Key, null, txInfo, etag, changedDoc);
            }
            return(true);
        }
Example #22
0
		private void HandleConflictedDocument(JsonDocument document, TransactionInformation transactionInformation)
		{
			var conflicts = document.DataAsJson.Value<RavenJArray>("Conflicts");
			var currentSource = Database.TransactionalStorage.Id.ToString();

			foreach (var c in conflicts)
			{
				var conflict = Database.Get(c.Value<string>(), transactionInformation);
				var conflictSource = conflict.Metadata.Value<RavenJValue>(Constants.RavenReplicationSource).Value<string>();

				if (conflictSource != currentSource)
					continue;

				this.deletedHistory.Value = new RavenJArray
				{
					new RavenJObject
					{
						{ Constants.RavenReplicationVersion, conflict.Metadata[Constants.RavenReplicationVersion] },
						{ Constants.RavenReplicationSource, conflict.Metadata[Constants.RavenReplicationSource] }
					}
				};

				return;
			}
		}
        private bool TryGetInternal <T>(string key, TransactionInformation transactionInformation, Func <string, DocumentInTransactionData, T> createDoc, out T document)
            where T : class
        {
            TransactionState state;

            if (transactionStates.TryGetValue(transactionInformation.Id, out state) == false)
            {
                document = null;
                return(false);
            }
            var change = state.changes.LastOrDefault(x => string.Equals(x.Key, key, StringComparison.InvariantCultureIgnoreCase));

            if (change == null)
            {
                document = null;
                return(false);
            }
            if (change.Delete)
            {
                document = null;
                return(true);
            }
            document = createDoc(key, change);
            return(true);
        }
        public override VetoResult AllowDelete(string key, TransactionInformation transactionInformation)
        {
            var document = Database.Documents.Get(key, transactionInformation);
            if (document == null)
                return VetoResult.Allowed;

            versionInformer.Value[key] = document.Metadata;
            if (document.Metadata.Value<string>(VersioningUtil.RavenDocumentRevisionStatus) != "Historical")
                return VetoResult.Allowed;

            if (Database.ChangesToRevisionsAllowed() == false &&
                Database.IsVersioningActive(document.Metadata))
            {
                var revisionPos = key.LastIndexOf("/revisions/", StringComparison.OrdinalIgnoreCase);
                if (revisionPos != -1)
                {
                    var parentKey = key.Remove(revisionPos);
                    var parentDoc = Database.Documents.Get(parentKey, transactionInformation);
                    if (parentDoc == null)
                        return VetoResult.Allowed;
                }

                return VetoResult.Deny("Deleting a historical revision is not allowed");
            }

            return VetoResult.Allowed;
        }
        private void HandleConflictedDocument(JsonDocument document, TransactionInformation transactionInformation)
        {
            var conflicts = document.DataAsJson.Value<RavenJArray>("Conflicts");
            var currentSource = Database.TransactionalStorage.Id.ToString();
            var historySet = false;

            foreach (var c in conflicts)
            {
                RavenJObject conflict;
                if (Database.Documents.Delete(c.Value<string>(), null, transactionInformation, out conflict) == false)
                    continue;

                if (historySet)
                    continue;

                var conflictSource = conflict.Value<RavenJValue>(Constants.RavenReplicationSource).Value<string>();

                if (conflictSource != currentSource)
                    continue;

                deletedHistory.Value = new RavenJArray
                {
                    new RavenJObject
                    {
                        { Constants.RavenReplicationVersion, conflict[Constants.RavenReplicationVersion] },
                        { Constants.RavenReplicationSource, conflict[Constants.RavenReplicationSource] }
                    }
                };

                historySet = true;
            }
        }
Example #26
0
		public override void OnPut(string key, RavenJObject document, RavenJObject metadata, TransactionInformation transactionInformation)
		{
			if (key.StartsWith("Raven/", StringComparison.InvariantCultureIgnoreCase) && // we don't deal with system documents
				key.StartsWith("Raven/Hilo/", StringComparison.InvariantCultureIgnoreCase) == false) // except for hilos
				return;
			using (Database.DisableAllTriggersForCurrentThread())
			{
				var doc = Database.Get(key, null);
				if (doc != null)
				{
					var history = doc.Metadata.Value<RavenJArray>(ReplicationConstants.RavenReplicationHistory) ?? new RavenJArray();
					metadata[ReplicationConstants.RavenReplicationHistory] = history;

					if (doc.Metadata.ContainsKey(ReplicationConstants.RavenReplicationVersion) && 
						doc.Metadata.ContainsKey(ReplicationConstants.RavenReplicationSource))
					{
						history.Add(new RavenJObject
						{
							{ReplicationConstants.RavenReplicationVersion, doc.Metadata[ReplicationConstants.RavenReplicationVersion]},
							{ReplicationConstants.RavenReplicationSource, doc.Metadata[ReplicationConstants.RavenReplicationSource]}
						});
					}

					if (history.Length > ReplicationConstants.ChangeHistoryLength)
					{
						history.RemoveAt(0);
					}
				}
				metadata[ReplicationConstants.RavenReplicationVersion] = RavenJToken.FromObject(HiLo.NextId());
				metadata[ReplicationConstants.RavenReplicationSource] = RavenJToken.FromObject(Database.TransactionalStorage.Id);
			}
		}
Example #27
0
        /// <summary>
        /// Called when [delete].
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="transactionInformation">The transaction information.</param>
        public override void OnDelete(string key, TransactionInformation transactionInformation)
        {
            if (key.StartsWith("Raven/")) // we don't deal with system documents
                return;

            var childrenQuery = new IndexQuery
            {
                Query = "Id:" + key
            };

            var queryResult = Database.Query("Documents/ByParent", childrenQuery);

            if (queryResult.Results.Count > 0) {
                foreach (var result in queryResult.Results) {

                    var metadataJObject = result.Value<RavenJObject>("@metadata");

                    if (metadataJObject != null)
                    {
                        var childId = metadataJObject.Value<string>("@id");

                        var childEtag = metadataJObject.Value<string>("@etag");
                        Database.Delete(childId, Guid.Parse(childEtag), transactionInformation);
                    }
                }
            }

            base.OnDelete(key, transactionInformation);
        }
Example #28
0
File: Put.cs Project: sainiuc/docs
 public override void OnPut(string key, RavenJObject document, RavenJObject metadata, TransactionInformation transactionInformation)
 {
     if (metadata["Document-Owner"] == null) // user didn't explicitly set it
     {
         // modify the metadata to the current user
         metadata["Document-Owner"] = RavenJObject.FromObject(Thread.CurrentPrincipal.Identity.Name);
     }
 }
		public override ReadVetoResult AllowRead(string key, RavenJObject metadata, ReadOperation operation, TransactionInformation transactionInformation)
		{
			if (operation != ReadOperation.Index)
				return ReadVetoResult.Allowed;
			if (metadata.ContainsKey("Deleted") == false)
				return ReadVetoResult.Allowed;
			return ReadVetoResult.Ignore;
		}
Example #30
0
 public override void OnRead(string key, RavenJObject document, RavenJObject metadata, ReadOperation operation, TransactionInformation transactionInformation)
 {
     var name = document["name"];
     if (name != null)
     {
         document["name"] = new RavenJValue(name.Value<string>().ToUpper());
     }
 }
Example #31
0
		private void RemoveOldRevisions(string key, int revision, VersioningConfiguration versioningConfiguration, TransactionInformation transactionInformation)
		{
			int latestValidRevision = revision - versioningConfiguration.MaxRevisions;
			if (latestValidRevision <= 0)
				return;

			Database.Delete(string.Format("{0}/revisions/{1}", key, latestValidRevision), null, transactionInformation);
		}
Example #32
0
        private void RemoveOldRevisions(string key, int revision, VersioningConfiguration versioningConfiguration, TransactionInformation transactionInformation)
        {
            int latestValidRevision = revision - versioningConfiguration.MaxRevisions;
            if (latestValidRevision <= 1)
                return;

        	Database.Delete(key + "/revisions/" + (latestValidRevision - 1), null, transactionInformation);
        }
        private Etag AddToTransactionState(string key,
                                           Etag etag,
                                           TransactionInformation transactionInformation,
                                           Etag committedEtag,
                                           DocumentInTransactionData item)
        {
            try
            {
                var state = transactionStates.GetOrAdd(transactionInformation.Id, id => new TransactionState());
                lock (state)
                {
                    state.LastSeen = new Reference <DateTime>
                    {
                        Value = SystemTime.UtcNow
                    };
                    state.Timeout = transactionInformation.Timeout;

                    var currentTxVal = state.Changes.LastOrDefault(x => string.Equals(x.Key, key, StringComparison.InvariantCultureIgnoreCase));
                    if (currentTxVal != null)
                    {
                        EnsureValidEtag(key, etag, committedEtag, currentTxVal);
                        state.Changes.Remove(currentTxVal);
                    }
                    var result = changedInTransaction.AddOrUpdate(key, s =>
                    {
                        EnsureValidEtag(key, etag, committedEtag, currentTxVal);

                        return(new ChangedDoc
                        {
                            transactionId = transactionInformation.Id,
                            committedEtag = committedEtag,
                            currentEtag = item.Etag
                        });
                    }, (_, existing) =>
                    {
                        if (existing.transactionId == transactionInformation.Id)
                        {
                            EnsureValidEtag(key, etag, committedEtag, currentTxVal);
                            existing.currentEtag = item.Etag;
                            return(existing);
                        }

                        throw new ConcurrencyException("Document " + key + " is being modified by another transaction: " + existing);
                    });

                    state.Changes.Add(item);

                    return(result.currentEtag);
                }
            }
            catch (Exception)
            {
                Rollback(transactionInformation.Id);
                throw;
            }
        }
Example #34
0
        private void AssertDeleteOperationNotVetoed(string key, TransactionInformation transactionInformation)
        {
            var vetoResult = DeleteTriggers
                             .Select(trigger => new { Trigger = trigger, VetoResult = trigger.AllowDelete(key, transactionInformation) })
                             .FirstOrDefault(x => x.VetoResult.IsAllowed == false);

            if (vetoResult != null)
            {
                throw new OperationVetoedException("DELETE vetoed by " + vetoResult.Trigger + " because: " + vetoResult.VetoResult.Reason);
            }
        }
 public bool TryGet(string key, TransactionInformation transactionInformation, out JsonDocumentMetadata document)
 {
     return(TryGetInternal(key, transactionInformation, (theKey, change) => new JsonDocumentMetadata
     {
         Metadata = (RavenJObject)change.Metadata.CreateSnapshot(),
         Key = theKey,
         Etag = change.Etag,
         NonAuthoritativeInformation = false,
         LastModified = change.LastModified
     }, out document));
 }
Example #36
0
        public JsonDocumentMetadata GetDocumentMetadata(string key, TransactionInformation transactionInformation)
        {
            JsonDocumentMetadata document = null;

            TransactionalStorage.Batch(actions =>
            {
                document = actions.Documents.DocumentMetadataByKey(key, transactionInformation);
            });

            DocumentRetriever.EnsureIdInMetadata(document);
            return(new DocumentRetriever(null, ReadTriggers)
                   .ProcessReadVetoes(document, transactionInformation, ReadOperation.Load));
        }
 public void DeleteDocumentInTransaction(
     TransactionInformation transactionInformation,
     string key,
     Etag etag,
     Etag committedEtag,
     SequentialUuidGenerator uuidGenerator)
 {
     AddToTransactionState(key, etag, transactionInformation, committedEtag, new DocumentInTransactionData
     {
         Delete       = true,
         Key          = key,
         LastModified = SystemTime.UtcNow
     });
 }
Example #38
0
 public void CanGetErrorOnOptimisticDeleteInTransaction()
 {
     using (var store = NewDocumentStore())
     {
         using (var session = store.OpenSession())
         {
             session.Store(new Item());
             session.SaveChanges();
         }
         var tx = new TransactionInformation
         {
             Id = Guid.NewGuid().ToString()
         };
         Assert.Throws <ConcurrencyException>(() =>
                                              store.DocumentDatabase.Delete("items/1", Etag.InvalidEtag, tx));
     }
 }
Example #39
0
 public void CanGetErrorOnOptimisticDeleteInTransactionWhenModifiedInTransaction()
 {
     using (var store = NewDocumentStore())
     {
         using (var session = store.OpenSession())
         {
             session.Store(new Item());
             session.SaveChanges();
         }
         var tx = new TransactionInformation
         {
             Id = Guid.NewGuid()
         };
         store.DocumentDatabase.Put("items/1", null, new RavenJObject(), new RavenJObject(), tx);
         Assert.Throws <ConcurrencyException>(() =>
                                              store.DocumentDatabase.Delete("items/1", Guid.NewGuid(), tx));
     }
 }
Example #40
0
 public void CanGetErrorOnOptimisticDeleteInTransactionWhenDeletedInTransaction()
 {
     using (var store = NewDocumentStore(requestedStorage: "esent"))
     {
         EnsureDtcIsSupported(store);
         using (var session = store.OpenSession())
         {
             session.Store(new Item());
             session.SaveChanges();
         }
         var tx = new TransactionInformation
         {
             Id = Guid.NewGuid().ToString()
         };
         store.SystemDatabase.Documents.Delete("items/1", null, tx);
         Assert.Throws <ConcurrencyException>(() =>
                                              store.SystemDatabase.Documents.Delete("items/1", Etag.InvalidEtag, tx));
     }
 }
        public void RecoverTransaction(string id, IEnumerable <DocumentInTransactionData> changes)
        {
            var txInfo = new TransactionInformation
            {
                Id      = id,
                Timeout = TimeSpan.FromMinutes(5)
            };

            foreach (var changedDoc in changes)
            {
                changedDoc.Metadata.EnsureCannotBeChangeAndEnableSnapshotting();
                changedDoc.Data.EnsureCannotBeChangeAndEnableSnapshotting();

                //we explicitly pass a null for the etag here, because we might have calls for TouchDocument()
                //that happened during the transaction, which changed the committed etag. That is fine when we are just running
                //the transaction, since we can just report the error and abort. But it isn't fine when we recover
                //var etag = changedDoc.CommittedEtag;
                Etag etag = null;
                AddToTransactionState(changedDoc.Key, null, txInfo, etag, changedDoc);
            }
        }
Example #42
0
        public void ConcurrentDtcTransactions()
        {
            using (var store = NewDocumentStore(requestedStorage: "esent"))
            {
                var documentDatabase = store.SystemDatabase;

                var tx1 = new TransactionInformation
                {
                    Id      = "tx1",
                    Timeout = TimeSpan.FromHours(1)
                };
                var tx2 = new TransactionInformation
                {
                    Id      = "tx2",
                    Timeout = TimeSpan.FromHours(1)
                };

                documentDatabase.Documents.Put("test/1", null, new RavenJObject(), new RavenJObject(), tx1);
                documentDatabase.Documents.Put("test/2", null, new RavenJObject(), new RavenJObject(), tx1);

                documentDatabase.Documents.Put("test/3", null, new RavenJObject(), new RavenJObject(), tx2);
                documentDatabase.Documents.Put("test/4", null, new RavenJObject(), new RavenJObject(), tx2);

                documentDatabase.PrepareTransaction("tx1");
                documentDatabase.PrepareTransaction("tx2");

                documentDatabase.Commit("tx2");

                WaitForIndexing(documentDatabase);

                documentDatabase.Commit("tx1");

                WaitForIndexing(documentDatabase);

                var queryResult = store.DatabaseCommands.Query("Raven/DocumentsByEntityName", new IndexQuery(), null);

                Assert.Equal(4, queryResult.TotalResults);
            }
        }
 public Etag AddDocumentInTransaction(
     string key,
     Etag etag,
     RavenJObject data,
     RavenJObject metadata,
     TransactionInformation transactionInformation,
     Etag committedEtag,
     SequentialUuidGenerator uuidGenerator)
 {
     metadata.EnsureCannotBeChangeAndEnableSnapshotting();
     data.EnsureCannotBeChangeAndEnableSnapshotting();
     return(AddToTransactionState(key, etag,
                                  transactionInformation,
                                  committedEtag,
                                  new DocumentInTransactionData
     {
         Metadata = metadata,
         Data = data,
         Delete = false,
         Key = key,
         LastModified = SystemTime.UtcNow,
         Etag = uuidGenerator.CreateSequentialUuid(UuidType.DocumentTransactions)
     }));
 }
        public Func <TDocument, TDocument> GetNonAuthoritativeInformationBehavior <TDocument>(TransactionInformation tx, string key) where TDocument : class, IJsonDocumentMetadata, new()
        {
            ChangedDoc existing;

            if (changedInTransaction.TryGetValue(key, out existing) == false || (tx != null && tx.Id == existing.transactionId))
            {
                return(null);
            }

            return(document =>
            {
                if (document == null)
                {
                    return new TDocument
                    {
                        Key = key,
                        Metadata = new RavenJObject {
                            { Constants.RavenDocumentDoesNotExists, true }
                        },
                        LastModified = DateTime.MinValue,
                        NonAuthoritativeInformation = true,
                        Etag = Etag.Empty
                    };
                }

                document.NonAuthoritativeInformation = true;
                return document;
            });
        }
Example #45
0
 public override void AfterPut(string key, Raven.Json.Linq.RavenJObject document, Raven.Json.Linq.RavenJObject metadata, Etag etag, Raven.Abstractions.Data.TransactionInformation transactionInformation)
 {
     if (key == "Raven/Authorization/WindowsSettings")
     {
         WindowsRequestAuthorizer.InvokeWindowsSettingsChanged();
     }
     base.AfterPut(key, document, metadata, etag, transactionInformation);
 }
        private Etag AddToTransactionState(string key,
                                           Etag etag,
                                           TransactionInformation transactionInformation,
                                           Etag committedEtag,
                                           DocumentInTransactionData item)
        {
            try
            {
                TransactionState state;

                if (transactionStates.TryGetValue(transactionInformation.Id, out state) == false)
                {
                    lock (modifyTransactionStates)
                    {
                        if (transactionStates.TryGetValue(transactionInformation.Id, out state) == false) // check it once again, after we retrieved the lock - could be added while we waited for the lock
                        {
                            state             = new TransactionState();
                            transactionStates = transactionStates.Add(transactionInformation.Id, state);
                        }
                    }
                }

                lock (state)
                {
                    state.LastSeen = new Reference <DateTime>
                    {
                        Value = SystemTime.UtcNow
                    };
                    state.Timeout = transactionInformation.Timeout;

                    var currentTxVal = state.Changes.LastOrDefault(x => string.Equals(x.Key, key, StringComparison.InvariantCultureIgnoreCase));
                    if (currentTxVal != null)
                    {
                        EnsureValidEtag(key, etag, committedEtag, currentTxVal);
                        state.Changes.Remove(currentTxVal);
                    }

                    ChangedDoc result;

                    lock (modifyChangedInTransaction)
                    {
                        if (changedInTransaction.TryGetValue(key, out result))
                        {
                            if (result.transactionId != transactionInformation.Id)
                            {
                                throw new ConcurrencyException("Document " + key + " is being modified by another transaction: " + result);
                            }

                            EnsureValidEtag(key, etag, committedEtag, currentTxVal);
                            result.currentEtag = item.Etag;
                        }
                        else
                        {
                            EnsureValidEtag(key, etag, committedEtag, currentTxVal);

                            result = new ChangedDoc
                            {
                                transactionId = transactionInformation.Id,
                                committedEtag = committedEtag,
                                currentEtag   = item.Etag
                            };

                            changedInTransaction = changedInTransaction.Add(key, result);
                        }
                    }

                    state.Changes.Add(item);

                    return(result.currentEtag);
                }
            }
            catch (Exception)
            {
                Rollback(transactionInformation.Id);
                throw;
            }
        }
Example #47
0
        public PatchResult ApplyPatch(string docId, Guid?etag, PatchRequest[] patchDoc, TransactionInformation transactionInformation)
        {
            var result = PatchResult.Patched;

            TransactionalStorage.Batch(actions =>
            {
                var doc = actions.Documents.DocumentByKey(docId, transactionInformation);
                if (doc == null)
                {
                    result = PatchResult.DocumentDoesNotExists;
                }
                else if (etag != null && doc.Etag != etag.Value)
                {
                    Debug.Assert(doc.Etag != null);
                    throw new ConcurrencyException("Could not patch document '" + docId + "' because non current etag was used")
                    {
                        ActualETag   = doc.Etag.Value,
                        ExpectedETag = etag.Value,
                    };
                }
                else
                {
                    var jsonDoc = doc.ToJson();
                    new JsonPatcher(jsonDoc).Apply(patchDoc);
                    Put(doc.Key, doc.Etag, jsonDoc, jsonDoc.Value <RavenJObject>("@metadata"), transactionInformation);
                    result = PatchResult.Patched;
                }

                workContext.ShouldNotifyAboutWork();
            });

            return(result);
        }
Example #48
0
        private void AssertPutOperationNotVetoed(string key, RavenJObject metadata, RavenJObject document, TransactionInformation transactionInformation)
        {
            var vetoResult = PutTriggers
                             .Select(trigger => new { Trigger = trigger, VetoResult = trigger.AllowPut(key, document, metadata, transactionInformation) })
                             .FirstOrDefault(x => x.VetoResult.IsAllowed == false);

            if (vetoResult != null)
            {
                throw new OperationVetoedException("PUT vetoed by " + vetoResult.Trigger + " because: " + vetoResult.VetoResult.Reason);
            }
        }
Example #49
0
        public PutResult Put(string key, Guid?etag, RavenJObject document, RavenJObject metadata, TransactionInformation transactionInformation)
        {
            if (key != null && Encoding.Unicode.GetByteCount(key) >= 255)
            {
                throw new ArgumentException("The key must be a maximum of 255 bytes in unicode, 127 characters", "key");
            }

            log.DebugFormat("Putting a document with key: {0} and etag {1}", key, etag);

            if (string.IsNullOrEmpty(key))
            {
                // we no longer sort by the key, so it doesn't matter
                // that the key is no longer sequential
                key = Guid.NewGuid().ToString();
            }
            RemoveReservedProperties(document);
            RemoveReservedProperties(metadata);
            Guid newEtag = Guid.Empty;

            lock (this)
            {
                TransactionalStorage.Batch(actions =>
                {
                    if (key.EndsWith("/"))
                    {
                        key += actions.General.GetNextIdentityValue(key);
                    }
                    if (transactionInformation == null)
                    {
                        AssertPutOperationNotVetoed(key, metadata, document, transactionInformation);
                        PutTriggers.Apply(trigger => trigger.OnPut(key, document, metadata, transactionInformation));

                        newEtag = actions.Documents.AddDocument(key, etag, document, metadata);
                        // We detect this by using the etags
                        // AddIndexingTask(actions, metadata, () => new IndexDocumentsTask { Keys = new[] { key } });
                        PutTriggers.Apply(trigger => trigger.AfterPut(key, document, metadata, newEtag, transactionInformation));
                    }
                    else
                    {
                        newEtag = actions.Transactions.AddDocumentInTransaction(key, etag,
                                                                                document, metadata, transactionInformation);
                    }
                    workContext.ShouldNotifyAboutWork();
                });
            }
            TransactionalStorage
            .ExecuteImmediatelyOrRegisterForSyncronization(() => PutTriggers.Apply(trigger => trigger.AfterCommit(key, document, metadata, newEtag)));

            return(new PutResult
            {
                Key = key,
                ETag = newEtag
            });
        }
Example #50
-1
		public override void AfterPut(string key, RavenJObject document, RavenJObject metadata, Etag etag, TransactionInformation transactionInformation)
		{
			VersioningConfiguration versioningConfiguration;
			if (TryGetVersioningConfiguration(key, metadata, out versioningConfiguration) == false)
				return;

			using (Database.DisableAllTriggersForCurrentThread())
			{
				var copyMetadata = new RavenJObject(metadata);
				copyMetadata[VersioningUtil.RavenDocumentRevisionStatus] = RavenJToken.FromObject("Historical");
				copyMetadata[Constants.RavenReadOnly] = true;
				copyMetadata.Remove(VersioningUtil.RavenDocumentRevision);
				object parentRevision;
				metadata.__ExternalState.TryGetValue("Parent-Revision", out parentRevision);
				if (parentRevision != null)
				{
					copyMetadata[VersioningUtil.RavenDocumentParentRevision] = key + "/revisions/" + parentRevision;
					copyMetadata[VersioningUtil.RavenDocumentParentRevision] = key + "/revisions/" + parentRevision;
				}

				object value;
				metadata.__ExternalState.TryGetValue("Next-Revision", out value);
				Database.Put(key + "/revisions/" + value, null, (RavenJObject)document.CreateSnapshot(), copyMetadata,
							 transactionInformation);
			}
		}