Example #1
0
 public void WhileCreatingDocumentInTransactionTryingToWriteOutsideTransactionFail()
 {
     var transactionInformation = new TransactionInformation { Id = Guid.NewGuid(), Timeout = TimeSpan.FromMinutes(1) };
     db.Put("ayende", null, JObject.Parse("{ayende:'rahien'}"), new JObject(), transactionInformation);
     Assert.Throws<ConcurrencyException>(
         () => db.Put("ayende", null, JObject.Parse("{ayende:'oren'}"), new JObject(), null));
 }
Example #2
0
        public static void AssertNotModifiedByAnotherTransaction(TableStorage storage, ITransactionStorageActions transactionStorageActions, string key, PersistentDictionary.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 JObject { { "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 (DateTime.UtcNow > timeout)
            {
                transactionStorageActions.RollbackTransaction(txId);
                return;
            }

            throw new ConcurrencyException("Document '" + key + "' is locked by transacton: " + txId);
        }
		public override void OnDelete(string key, TransactionInformation transactionInformation)
		{
			var document = Database.Get(key, null);
			if (document == null)
				return;
            Database.Delete(document.Metadata.Value<string>("Cascade-Delete"), null, null);
		}
        public override void OnPut(string key, JObject document, JObject metadata, TransactionInformation transactionInformation)
        {
			if (VersioningContext.IsInVersioningContext)
				return;
			if (key.StartsWith("Raven/", StringComparison.InvariantCultureIgnoreCase))
				return;

			if (excludeByEntityName.Contains(metadata.Value<string>("Raven-Entity-Name")))
				return;

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

			using(VersioningContext.Enter())
			{
				var copyMetadata = new JObject(metadata);
				copyMetadata[RavenDocumentRevisionStatus] = JToken.FromObject("Historical");
				copyMetadata.Remove(RavenDocumentRevision);
				var parentRevision = metadata.Value<string>(RavenDocumentRevision);
				if(parentRevision!=null)
				{
					copyMetadata[RavenDocumentParentRevision] = key + "/revisions/" + parentRevision;
					metadata[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, transactionInformation);

				metadata[RavenDocumentRevisionStatus] = JToken.FromObject("Current");
				metadata[RavenDocumentRevision] = JToken.FromObject(revision);
			}
        }
Example #5
0
 public override void AfterDelete(string key, TransactionInformation transactionInformation)
 {
     if (ReplicationContext.IsInReplicationContext)
         return;
     Database.Put(key, null, new JObject(), new JObject(new JProperty("Raven-Delete-Marker", true)),
                  transactionInformation);
 }
Example #6
0
        public void PutNewDocInTxAndThenGetItBeforeCommitInSameTransactionReturnsNonNull()
        {
            var transactionInformation = new TransactionInformation { Id = Guid.NewGuid(), Timeout = TimeSpan.FromMinutes(1) };
            db.Put("ayende", null, JObject.Parse("{ayende:'rahien'}"), new JObject(), transactionInformation);

            Assert.NotNull(db.Get("ayende", transactionInformation));
        }
Example #7
0
 public void DeletingDocumentInTransactionInNotVisibleBeforeCommit()
 {
     db.Put("ayende", null, JObject.Parse("{ayende:'oren'}"), new JObject(), null);
     var transactionInformation = new TransactionInformation { Id = Guid.NewGuid(), Timeout = TimeSpan.FromMinutes(1) };
     db.Delete("ayende", null, transactionInformation);
     Assert.NotNull(db.Get("ayende", null));
 }
Example #8
0
		public void CanModifyTxId()
		{
			var transactionInformation = new TransactionInformation
			{
				Id = Guid.NewGuid(),
				Timeout = TimeSpan.FromDays(7)
			};

			using (var tx = new TransactionalStorage("test"))
			{
				tx.Write(mutator => mutator.Transactions.AddDocumentInTransaction("Ayende", null, JObject.FromObject(new { Name = "Rahien" }), new JObject(),
					transactionInformation));

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

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


				tx.Read(viewer =>
					Assert.NotNull(viewer.Documents.DocumentByKey("Ayende", txInfo2)));
			}
		}
Example #9
0
    	public JsonDocument ProcessReadVetoes(JsonDocument document, TransactionInformation transactionInformation, ReadOperation operation)
        {
            if (document == null)
                return document;
            foreach (var readTrigger in triggers)
            {
                var readVetoResult = readTrigger.AllowRead(document.Key, document.DataAsJson ?? document.Projection, document.Metadata, operation, transactionInformation);
                switch (readVetoResult.Veto)
                {
                    case ReadVetoResult.ReadAllow.Allow:
                        break;
                    case ReadVetoResult.ReadAllow.Deny:
                        return new JsonDocument
                        {
                            DataAsJson = new JObject(),
                            Metadata = new JObject(
                                new JProperty("Raven-Read-Veto", new JObject(new JProperty("Reason", readVetoResult.Reason),
                                                                             new JProperty("Trigger", readTrigger.ToString())
                                                                    ))
                                )
                        };
                    case ReadVetoResult.ReadAllow.Ignore:
                        return null;
                    default:
                        throw new ArgumentOutOfRangeException(readVetoResult.Veto.ToString());
                }
            }

            return document;
        }
Example #10
0
		public void AfterCommittingCanSeeChangesWithoutTx()
		{
			var transactionInformation = new TransactionInformation
			{
				Id = Guid.NewGuid(),
				Timeout = TimeSpan.FromDays(7)
			};

			using (var tx = new TransactionalStorage("test"))
			{
				tx.Write(mutator => mutator.Transactions.AddDocumentInTransaction("Ayende", null, JObject.FromObject(new { Name = "Rahien" }), new JObject(),
					transactionInformation));

				tx.Write(mutator => mutator.Transactions.CompleteTransaction(transactionInformation.Id, data =>
				{
					if (data.Delete)
					{
						JObject metadata;
						mutator.Documents.DeleteDocument(data.Key, null, out metadata);
					}
					else
						mutator.Documents.AddDocument(data.Key, null, data.Data, data.Metadata);
				}));
				tx.Read(viewer =>
					Assert.NotNull(viewer.Documents.DocumentByKey("Ayende", null)));
			}
		}
Example #11
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);
        }
Example #12
0
 public void WhileDocumentIsBeingUpdatedInTransactionCannotUpdateOutsideTransaction()
 {
     db.Put("ayende", null, JObject.Parse("{ayende:'oren'}"), new JObject(), null);
     var transactionInformation = new TransactionInformation { Id = Guid.NewGuid(), Timeout = TimeSpan.FromMinutes(1) };
     db.Put("ayende", null, JObject.Parse("{ayende:'rahien'}"), new JObject(), transactionInformation);
     Assert.Throws<ConcurrencyException>(
         () => db.Put("ayende", null, JObject.Parse("{ayende:'oren'}"), new JObject(), null));
 }
        public override VetoResult AllowPut(string key, JObject document, JObject metadata, TransactionInformation transactionInformation)
		{
			var name = document["name"];
			if(name != null && name.Value<string>().Any(char.IsUpper))
			{
				return VetoResult.Deny("Can't use upper case characters in the 'name' property");
			}
			return VetoResult.Allowed;
		}
Example #14
0
        public override VetoResult AllowPut(string key, JObject document, JObject metadata, TransactionInformation transactionInformation)
        {
            if (metadata.Value<string>(RavenDocumentRevisionStatus) != "Historical")
                return VetoResult.Allowed;
            if (Database.Get(key, transactionInformation) == null)
                return VetoResult.Allowed;

            return VetoResult.Deny("Modifying a historical revision is not allowed");
        }
Example #15
0
        public override VetoResult AllowPut(string key, JObject document, JObject metadata, TransactionInformation transactionInformation)
        {
			if (VersioningContext.IsInVersioningContext)
				return VetoResult.Allowed;
			
			if (metadata.Value<string>(RavenDocumentRevisionStatus) == "Historical")
				return VetoResult.Deny("Modifying a historical revision is not allowed");
			return VetoResult.Allowed;
        }
Example #16
0
        public void PutNewDocInTxCommitAndThenGetIt()
        {
            var transactionInformation = new TransactionInformation{Id = Guid.NewGuid(),Timeout = TimeSpan.FromMinutes(1)};
            db.Put("ayende", null, JObject.Parse("{ayende:'rahien'}"), new JObject(), transactionInformation);

            db.Commit(transactionInformation.Id);

            Assert.NotNull(db.Get("ayende", null));
        }
Example #17
0
        public void UpdateDocInTxAndThenGetItBeforeCommitInSameTx()
        {
            db.Put("ayende", null, JObject.Parse("{ayende:'oren'}"), new JObject(), null);
            var transactionInformation = new TransactionInformation { Id = Guid.NewGuid(), Timeout = TimeSpan.FromMinutes(1) };
            db.Put("ayende", null, JObject.Parse("{ayende:'rahien'}"), new JObject(), transactionInformation);

            Assert.NotNull(db.Get("ayende", transactionInformation));
            Assert.Equal("rahien", db.Get("ayende", transactionInformation).ToJson()["ayende"].Value<string>());
        }
Example #18
0
 public void WhenUsingTransactionWillFailIfDocumentEtagDoesNotMatch()
 {
     db.Put("ayende", null, JObject.Parse("{ayende:'oren'}"), new JObject(), null);
     var transactionInformation = new TransactionInformation { Id = Guid.NewGuid(), Timeout = TimeSpan.FromMinutes(1) };
     Assert.Throws<ConcurrencyException>(
         () =>
         db.Put("ayende", Guid.NewGuid(), JObject.Parse("{ayende:'rahien'}"), new JObject(),
                transactionInformation));
 }
 public override ReadVetoResult AllowRead(string key, JObject document, JObject metadata, ReadOperation operation,
     TransactionInformation transactionInformation)
 {
     if (ReplicationContext.IsInReplicationContext)
         return ReadVetoResult.Allowed;
     JToken value;
     if (metadata.TryGetValue("Raven-Delete-Marker", out value))
         return ReadVetoResult.Ignore;
     return ReadVetoResult.Allowed;
 }
Example #20
0
        public void WhenUsingTransactionWillWorkIfDocumentEtagMatch()
        {
            db.Put("ayende", null, JObject.Parse("{ayende:'oren'}"), new JObject(), null);
            var doc = db.Get("ayende", null);
            var transactionInformation = new TransactionInformation { Id = Guid.NewGuid(), Timeout = TimeSpan.FromMinutes(1) };
            db.Put("ayende", doc.Etag, JObject.Parse("{ayende:'rahien'}"), new JObject(), transactionInformation);
            db.Commit(transactionInformation.Id);

            Assert.Equal("rahien", db.Get("ayende", null).ToJson()["ayende"].Value<string>());
        }
Example #21
0
        public void DeletingDocumentAndThenAddingDocumentInSameTransactionCanWork()
        {
            db.Put("ayende", null, JObject.Parse("{ayende:'oren'}"), new JObject(), null);
            var transactionInformation = new TransactionInformation { Id = Guid.NewGuid(), Timeout = TimeSpan.FromMinutes(1) };
            db.Delete("ayende", null, transactionInformation);
            db.Put("ayende", null, JObject.Parse("{ayende:'rahien'}"), new JObject(), transactionInformation);
            db.Commit(transactionInformation.Id);

            Assert.Equal("rahien", db.Get("ayende", null).ToJson()["ayende"].Value<string>());
        }
Example #22
0
        public void AfterPuttingDocInTxWillChangeEtag()
        {
            db.Put("ayende", null, JObject.Parse("{ayende:'oren'}"), new JObject(), null);
            var doc = db.Get("ayende", null);
            var transactionInformation = new TransactionInformation { Id = Guid.NewGuid(), Timeout = TimeSpan.FromMinutes(1) };
            db.Put("ayende", doc.Etag, JObject.Parse("{ayende:'rahien'}"), new JObject(), transactionInformation);
            var docInTx = db.Get("ayende", transactionInformation);
            db.Put("ayende", docInTx.Etag, JObject.Parse("{ayende:'rahien'}"), new JObject(), transactionInformation);

            Assert.NotEqual(doc.Etag, docInTx.Etag);
        }
        private void RemoveOldRevisions(string key, int revision, TransactionInformation transactionInformation)
        {
            if (maxRevisions == null)
                return;

            int latestValidRevision = revision - maxRevisions.Value;
            if (latestValidRevision <= 1)
                return;

        	Database.Delete(key + "/revisions/" + (latestValidRevision - 1), null, transactionInformation);
        }
        public override void OnDelete(string key, TransactionInformation transactionInformation)
        {
            if (ReplicationContext.IsInReplicationContext)
                return;

            var document = Database.Get(key, transactionInformation);
            if (document == null)
                return;
            deletedSource.Value = document.Metadata[ReplicationConstants.RavenReplicationSource];
            deletedVersion.Value = document.Metadata[ReplicationConstants.RavenReplicationVersion];
        }
Example #25
0
        private JsonDocument ExecuteReadTriggersOnRead(JsonDocument resultingDocument, TransactionInformation transactionInformation, ReadOperation operation)
        {
            if (resultingDocument == null)
                return null;

            foreach (var readTrigger in triggers)
            {
                readTrigger.OnRead(resultingDocument.Key, resultingDocument.DataAsJson, resultingDocument.Metadata, operation, transactionInformation);
            }
            return resultingDocument;
        }
Example #26
0
		public void CommittingWillOnlyCommitSingleTransaction()
		{
			var transactionInformation = new TransactionInformation { Id = Guid.NewGuid(), Timeout = TimeSpan.FromMinutes(1) };
			db.Put("ayende1", null, JObject.Parse("{ayende:'rahien'}"), new JObject(), transactionInformation);
			db.Put("ayende2", null, JObject.Parse("{ayende:'rahien'}"), new JObject(), new TransactionInformation { Id = Guid.NewGuid(), Timeout = TimeSpan.FromMinutes(1) });

			db.Commit(transactionInformation.Id);

			Assert.NotNull(db.Get("ayende1", null));
			Assert.Null(db.Get("ayende2", null));
		}
 public override VetoResult AllowDelete(string key, TransactionInformation transactionInformation)
 {
     if(allowDeletiongOfHistoricalDocuments)
         return VetoResult.Allowed;
     JsonDocument document = Database.Get(key, transactionInformation);
     if (document == null)
         return VetoResult.Allowed;
     if (document.Metadata.Value<string>(VersioningPutTrigger.RavenDocumentRevisionStatus) != "Historical")
         return VetoResult.Allowed;
     return VetoResult.Deny("Deleting a historical revision is not allowed");
 }
Example #28
0
		public void PutTwoDocumentsAndThenCommitReversedOrder()
		{
			var transactionInformation = new TransactionInformation { Id = Guid.NewGuid(), Timeout = TimeSpan.FromMinutes(1) };
			db.Put("ayende2", null, JObject.Parse("{ayende:'rahien'}"), new JObject(), transactionInformation);
			db.Put("ayende1", null, JObject.Parse("{ayende:'rahien'}"), new JObject(), transactionInformation);

			db.Commit(transactionInformation.Id);

			Assert.NotNull(db.Get("ayende1", null));
			Assert.NotNull(db.Get("ayende2", null));
		}
Example #29
0
		private void EnsureTransactionExists(TransactionInformation transactionInformation)
		{
			Api.JetSetCurrentIndex(session, Transactions, "by_tx_id");
			Api.MakeKey(session, Transactions, transactionInformation.Id.ToByteArray(), MakeKeyGrbit.NewKey);
			var isUpdate = Api.TrySeek(session, Transactions, SeekGrbit.SeekEQ);
			using (var update = new Update(session, Transactions, isUpdate ? JET_prep.Replace : JET_prep.Insert))
			{
				Api.SetColumn(session, Transactions, tableColumnsCache.TransactionsColumns["tx_id"], transactionInformation.Id.ToByteArray());
				Api.SetColumn(session, Transactions, tableColumnsCache.TransactionsColumns["timeout"],
							  DateTime.UtcNow + transactionInformation.Timeout);
				update.Save();
			}
		}
 public override ReadVetoResult AllowRead(string key, JObject document, JObject metadata, ReadOperation operation,
                                          TransactionInformation transactionInformation)
 {
     if(metadata == null)
         return ReadVetoResult.Allowed;
     var property = metadata.Property(RavenExpirationDate);
     if (property == null)
         return ReadVetoResult.Allowed;
     var dateTime = property.Value.Value<DateTime>();
     if(dateTime > GetCurrentUtcDate())
         return ReadVetoResult.Allowed;
     return ReadVetoResult.Ignore;
 }
Example #31
0
        private JsonDocument ExecuteReadTriggersOnRead(JsonDocument resultingDocument, TransactionInformation transactionInformation, ReadOperation operation)
        {
            if (resultingDocument == null)
            {
                return(null);
            }

            foreach (var readTrigger in ReadTriggers)
            {
                readTrigger.OnRead(resultingDocument.Key, resultingDocument.DataAsJson, resultingDocument.Metadata, operation, transactionInformation);
            }
            return(resultingDocument);
        }
Example #32
0
        private void AssertPutOperationNotVetoed(string key, JObject metadata, JObject 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 #33
0
        public PatchResult ApplyPatch(string docId, Guid?etag, PatchRequest[] patchDoc, TransactionInformation transactionInformation)
        {
            var result = PatchResult.Patched;

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

                workContext.ShouldNotifyAboutWork();
            });

            return(result);
        }
Example #34
0
        public PutResult Put(string key, Guid?etag, JObject document, JObject metadata, TransactionInformation transactionInformation)
        {
            if (string.IsNullOrEmpty(key))
            {
                Guid value;
                UuidCreateSequential(out value);
                key = value.ToString();
            }
            RemoveReservedProperties(document);
            RemoveReservedProperties(metadata);
            TransactionalStorage.Batch(actions =>
            {
                metadata["Last-Modified"] = JToken.FromObject(DateTime.UtcNow.ToString("r"));
                if (key.EndsWith("/"))
                {
                    key += actions.GetNextIdentityValue(key);
                }
                metadata.Add("@id", new JValue(key));
                if (transactionInformation == null)
                {
                    AssertPutOperationNotVetoed(key, metadata, document, transactionInformation);
                    PutTriggers.Apply(trigger => trigger.OnPut(key, document, metadata, transactionInformation));

                    etag = actions.AddDocument(key, etag, document, metadata);
                    AddIndexingTask(actions, metadata, () => new IndexDocumentsTask {
                        Keys = new[] { key }
                    });
                    PutTriggers.Apply(trigger => trigger.AfterPut(key, document, metadata, transactionInformation));
                }
                else
                {
                    etag = actions.AddDocumentInTransaction(key, etag,
                                                            document, metadata, transactionInformation);
                }
                workContext.ShouldNotifyAboutWork();
            });

            TransactionalStorage
            .ExecuteImmediatelyOrRegisterForSyncronization(() => PutTriggers.Apply(trigger => trigger.AfterCommit(key, document, metadata)));

            return(new PutResult
            {
                Key = key,
                ETag = (Guid)etag
            });
        }