public override void AfterPut(string key, RavenJObject document, RavenJObject metadata, System.Guid etag, TransactionInformation transactionInformation) { if (key.StartsWith("Raven/")) { return; } var entityName = metadata.Value<string>(Constants.RavenEntityName) + "/"; var properties = metadata.Value<RavenJArray>(Constants.EnsureUniqueConstraints); if (properties == null || properties.Length <= 0) return; var constraintMetaObject = new RavenJObject { { Constants.IsConstraintDocument, true } }; constraintMetaObject.EnsureSnapshot(); foreach (var property in properties) { var propName = ((RavenJValue)property).Value.ToString(); var uniqueValue = document.Value<string>(propName); if(uniqueValue == null) continue; string documentName = "UniqueConstraints/" + entityName + propName + "/" +Util.EscapeUniqueValue(uniqueValue); Database.Put( documentName, null, RavenJObject.FromObject(new { RelatedId = key }), (RavenJObject)constraintMetaObject.CreateSnapshot(), transactionInformation); } }
public void WhileCreatingDocumentInTransactionTryingToWriteOutsideTransactionFail() { var transactionInformation = new TransactionInformation { Id = Guid.NewGuid(), Timeout = TimeSpan.FromMinutes(1) }; db.Put("ayende", null, RavenJObject.Parse("{ayende:'rahien'}"), new RavenJObject(), transactionInformation); Assert.Throws<ConcurrencyException>( () => db.Put("ayende", null, RavenJObject.Parse("{ayende:'oren'}"), new RavenJObject(), null)); }
public void DeletingDocumentInTransactionInNotVisibleBeforeCommit() { db.Put("ayende", null, RavenJObject.Parse("{ayende:'oren'}"), new RavenJObject(), null); var transactionInformation = new TransactionInformation { Id = Guid.NewGuid(), Timeout = TimeSpan.FromMinutes(1) }; db.Delete("ayende", null, transactionInformation); Assert.NotNull(db.Get("ayende", null)); }
public void Should_save_put_to_tenant_database_if_tenant_database_is_reloaded_in_the_middle_of_the_put_transaction() { using (var server = GetNewServer(runInMemory: false)) using (var store = new DocumentStore { Url = "http://*****:*****@"~\Databases\Mine" } }, }); var tx1 = new TransactionInformation { Id = Guid.NewGuid().ToString() }; var tx2 = new TransactionInformation { Id = Guid.NewGuid().ToString() }; var tenantDatabaseDocument = store.DatabaseCommands.Get("Raven/Databases/" + TenantName); server.Database.Put("Raven/Databases/mydb", null, tenantDatabaseDocument.DataAsJson, tenantDatabaseDocument.Metadata, tx1); var tenantDb = GetDocumentDatabaseForTenant(server, TenantName); tenantDb.Put("Foo/1", null, new RavenJObject { { "Test", "123" } }, new RavenJObject(), tx2); server.Database.PrepareTransaction(tx1.Id); server.Database.Commit(tx1.Id); tenantDb = GetDocumentDatabaseForTenant(server, TenantName); tenantDb.PrepareTransaction(tx2.Id); tenantDb.Commit(tx2.Id); var fooDoc = tenantDb.Get("Foo/1", new TransactionInformation { Id = Guid.NewGuid().ToString() }); Assert.NotNull(fooDoc); } }
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 void PutNewDocInTxAndThenGetItBeforeCommitReturnsNull() { var transactionInformation = new TransactionInformation { Id = Guid.NewGuid(), Timeout = TimeSpan.FromMinutes(1) }; db.Put("ayende", null, RavenJObject.Parse("{ayende:'rahien'}"), new RavenJObject(), transactionInformation); Assert.True(db.Get("ayende", null).Metadata.Value<bool>(Constants.RavenDocumentDoesNotExists)); }
public void PutNewDocInTxAndThenGetItBeforeCommitInSameTransactionReturnsNonNull() { var transactionInformation = new TransactionInformation { Id = Guid.NewGuid(), Timeout = TimeSpan.FromMinutes(1) }; db.Put("ayende", null, RavenJObject.Parse("{ayende:'rahien'}"), new RavenJObject(), transactionInformation); Assert.NotNull(db.Get("ayende", transactionInformation)); }
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); }
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 void OnDelete(string key, TransactionInformation transactionInformation) { if (key.StartsWith("Raven")) return; var doc = Database.Get(key, transactionInformation); if (doc == null) return; var metadata = doc.Metadata; var entityName = metadata.Value<string>(Constants.RavenEntityName) + "/"; var uniqueConstraits = metadata.Value<RavenJArray>(Constants.EnsureUniqueConstraints); if (uniqueConstraits == null) return; foreach (var property in uniqueConstraits) { var checkKey = "UniqueConstraints/" + entityName + property + "/" + doc.DataAsJson.Value<string>(property.Value<string>()); Database.Delete(checkKey, null, transactionInformation); } }
private void SetupReplication() { if (RoleEnvironment.CurrentRoleInstance.Role.Instances.Count < 2) { var tr = new TransactionInformation(); _database.Put("Debug", null, JObject.Parse(@"{""Url"":""" + GetEndPointAddress(MyInstanceEndpoint.IPEndpoint) + @"""}"), new JObject(), tr); _database.Commit(tr.Id); } else { var json = BuildDestinationsString(); Trace.WriteLine(json); var tr = new TransactionInformation(); _database.Delete("Raven/Replication/Destinations", null, tr); _database.Put("Raven/Replication/Destinations", null, JObject.Parse(json), new JObject(), tr); _database.Commit(tr.Id); } }
public override VetoResult AllowPut(string key, RavenJObject document, RavenJObject metadata, TransactionInformation transactionInformation) { return VetoResult.Allowed; }
public override void OnDelete(string key, TransactionInformation transactionInformation) { if (key.StartsWith("Raven")) return; var doc = Database.Get(key, transactionInformation); if (doc == null) return; var metadata = doc.Metadata; var entityName = metadata.Value<string>(Constants.RavenEntityName) + "/"; var uniqueConstraits = metadata.Value<RavenJArray>(Constants.EnsureUniqueConstraints); if (uniqueConstraits == null) return; foreach (var property in uniqueConstraits) { var constraint = Util.GetConstraint(property); var prefix = "UniqueConstraints/" + entityName + constraint.PropName+ "/"; // UniqueConstraints/EntityNamePropertyName/ var prop = doc.DataAsJson[constraint.PropName]; if (prop == null || prop.Type == JTokenType.Null) continue; var array = prop as RavenJArray; var checkKeys = array != null ? array.Select(p => p.Value<string>()) : new[] {prop.Value<string>()}; foreach (var checkKey in checkKeys) { Database.Delete(prefix + Util.EscapeUniqueValue(checkKey, constraint.CaseInsensitive), null, transactionInformation); } } }
private TransactionInformation(TransactionInformation other) { this.local_id = other.local_id; this.dtcId = other.dtcId; this.creation_time = other.creation_time; this.status = other.status; }
private TransactionInformation (TransactionInformation other) { local_id = other.local_id; dtcId = other.dtcId; creation_time = other.creation_time; status = other.status; }
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 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 OnPut(string key, RavenJObject document, RavenJObject metadata, TransactionInformation transactionInformation) { if (key.StartsWith("Raven/")) { return; } var entityName = metadata.Value<string>(Constants.RavenEntityName) +"/"; var properties = metadata.Value<RavenJArray>(Constants.EnsureUniqueConstraints); if (properties == null || properties.Length <= 0) return; var oldDoc = Database.Get(key, transactionInformation); if (oldDoc == null) { return; } var oldJson = oldDoc.DataAsJson; foreach (var property in metadata.Value<RavenJArray>(Constants.EnsureUniqueConstraints)) { var propName = ((RavenJValue)property).Value.ToString(); // Handle Updates in the Constraint if (!oldJson.Value<string>(propName).Equals(document.Value<string>(propName))) { Database.Delete("UniqueConstraints/" + entityName + propName + "/" + oldJson.Value<string>(propName), null, transactionInformation); } } }
public override void AfterPut(string key, RavenJObject document, RavenJObject metadata, System.Guid etag, TransactionInformation transactionInformation) { if (key.StartsWith("Raven/")) { return; } var entityName = metadata.Value<string>(Constants.RavenEntityName) + "/"; var properties = metadata.Value<RavenJArray>(Constants.EnsureUniqueConstraints); if (properties == null || properties.Count() <= 0) return; var constraintMetaObject = new RavenJObject { { Constants.IsConstraintDocument, true } }; foreach (var property in properties) { var propName = ((RavenJValue)property).Value.ToString(); Database.Put( "UniqueConstraints/" + entityName + propName + "/" + document.Value<string>(propName), null, RavenJObject.FromObject(new { RelatedId = key }), constraintMetaObject, transactionInformation); } }
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<JArray>(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<JArray>(MetadataKeys.AttachmentsToCascadeDelete); if (attachmentsToDelete != null) foreach (var attachmentToDelete in attachmentsToDelete) Database.DeleteStatic(attachmentToDelete.Value<string>(), null); } }
public virtual void OnPut( string key, RavenJObject document, RavenJObject metadata, TransactionInformation transactionInformation) { }
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))); } }
public override void OnDelete(string key, TransactionInformation transactionInformation) { if (key.StartsWith("Raven")) return; var doc = Database.Get(key, transactionInformation); if (doc == null) return; var metadata = doc.Metadata; var entityName = metadata.Value<string>(Constants.RavenEntityName) + "/"; var uniqueConstraits = metadata.Value<RavenJArray>(Constants.EnsureUniqueConstraints); if (uniqueConstraits == null) return; foreach (var property in uniqueConstraits) { var constraint = Util.GetConstraint(property); var prefix = "UniqueConstraints/" + entityName + constraint.PropName+ "/"; // UniqueConstraints/EntityNamePropertyName/ var prop = doc.DataAsJson[constraint.PropName]; string[] uniqueValues; if (!Util.TryGetUniqueValues(prop, out uniqueValues)) continue; foreach (var uniqueValue in uniqueValues) { Database.Delete(prefix + Util.EscapeUniqueValue(uniqueValue, constraint.CaseInsensitive), null, transactionInformation); } } }
public JsonDocument DocumentByKey(string key, TransactionInformation transactionInformation) { byte[] data; JObject metadata; if (transactionInformation != null) { Api.JetSetCurrentIndex(session, DocumentsModifiedByTransactions, "by_key"); Api.MakeKey(session, DocumentsModifiedByTransactions, key, Encoding.Unicode, MakeKeyGrbit.NewKey); if (Api.TrySeek(session, DocumentsModifiedByTransactions, SeekGrbit.SeekEQ)) { var txId = Api.RetrieveColumn(session, DocumentsModifiedByTransactions, tableColumnsCache.DocumentsModifiedByTransactionsColumns["locked_by_transaction"]); if (new Guid(txId) == transactionInformation.Id) { if (Api.RetrieveColumnAsBoolean(session, DocumentsModifiedByTransactions, tableColumnsCache.DocumentsModifiedByTransactionsColumns["delete_document"]) == true) { logger.DebugFormat("Document with key '{0}' was deleted in transaction: {1}", key, transactionInformation.Id); return null; } data = Api.RetrieveColumn(session, DocumentsModifiedByTransactions, tableColumnsCache.DocumentsModifiedByTransactionsColumns["data"]); metadata = Api.RetrieveColumn(session, DocumentsModifiedByTransactions, tableColumnsCache.DocumentsModifiedByTransactionsColumns["metadata"]).ToJObject(); data = documentCodecs.Aggregate(data, (bytes, codec) => codec.Decode(key, metadata, bytes)); logger.DebugFormat("Document with key '{0}' was found in transaction: {1}", key, transactionInformation.Id); var etag = new Guid(Api.RetrieveColumn(session, DocumentsModifiedByTransactions, tableColumnsCache.DocumentsModifiedByTransactionsColumns["etag"])); return new JsonDocument { DataAsJson = data.ToJObject(), Etag = etag, Key = Api.RetrieveColumnAsString(session, DocumentsModifiedByTransactions, tableColumnsCache.DocumentsModifiedByTransactionsColumns["key"], Encoding.Unicode), Metadata = metadata }; } } } Api.JetSetCurrentIndex(session, Documents, "by_key"); Api.MakeKey(session, Documents, key, Encoding.Unicode, MakeKeyGrbit.NewKey); if (Api.TrySeek(session, Documents, SeekGrbit.SeekEQ) == false) { logger.DebugFormat("Document with key '{0}' was not found", key); return null; } data = Api.RetrieveColumn(session, Documents, tableColumnsCache.DocumentsColumns["data"]); metadata = Api.RetrieveColumn(session, Documents, tableColumnsCache.DocumentsColumns["metadata"]).ToJObject(); data = documentCodecs.Aggregate(data, (bytes, codec) => codec.Decode(key, metadata, bytes)); logger.DebugFormat("Document with key '{0}' was found", key); var existingEtag = new Guid(Api.RetrieveColumn(session, Documents, tableColumnsCache.DocumentsColumns["etag"])); return new JsonDocument { DataAsJson = data.ToJObject(), Etag = existingEtag, Key = Api.RetrieveColumnAsString(session, Documents, tableColumnsCache.DocumentsColumns["key"], Encoding.Unicode), Metadata = metadata }; }
public override ReadVetoResult AllowRead(string key, JObject document, JObject metadata, ReadOperation operation, TransactionInformation transactionInformation) { if(key == null) return ReadVetoResult.Allowed; if (key.StartsWith("Raven/") && operation == ReadOperation.Query) return ReadVetoResult.Ignore; // hide Raven's documentation from queries return ReadVetoResult.Allowed; }
public override void OnDelete(string key, TransactionInformation transactionInformation) { var document = Database.Get(key, transactionInformation); if (document == null) return; deletedSource.Value = document.Metadata[ReplicationConstants.RavenReplicationSource]; deletedVersion.Value = document.Metadata[ReplicationConstants.RavenReplicationVersion]; }
public void WhileDocumentIsBeingUpdatedInTransactionCannotUpdateOutsideTransaction() { db.Put("ayende", null, RavenJObject.Parse("{ayende:'oren'}"), new RavenJObject(), null); var transactionInformation = new TransactionInformation { Id = Guid.NewGuid(), Timeout = TimeSpan.FromMinutes(1) }; db.Put("ayende", null, RavenJObject.Parse("{ayende:'rahien'}"), new RavenJObject(), transactionInformation); Assert.Throws<ConcurrencyException>( () => db.Put("ayende", null, RavenJObject.Parse("{ayende:'oren'}"), new RavenJObject(), null)); }
public void UpdateDocInTxAndThenGetItBeforeCommit() { db.Put("ayende", null, RavenJObject.Parse("{ayende:'oren'}"), new RavenJObject(), null); var transactionInformation = new TransactionInformation { Id = Guid.NewGuid(), Timeout = TimeSpan.FromMinutes(1) }; db.Put("ayende", null, RavenJObject.Parse("{ayende:'rahien'}"), new RavenJObject(), transactionInformation); Assert.NotNull(db.Get("ayende", null)); Assert.Equal("oren", db.Get("ayende", null).ToJson()["ayende"].Value<string>()); }
public void DeletingDocumentInTransactionInNotFoundInSameTransactionBeforeCommit() { EnsureDtcIsSupported(db); db.Documents.Put("ayende", null, RavenJObject.Parse("{ayende:'oren'}"), new RavenJObject(), null); var transactionInformation = new TransactionInformation { Id = Guid.NewGuid().ToString(), Timeout = TimeSpan.FromMinutes(1) }; db.Documents.Delete("ayende", null, transactionInformation); Assert.Null(db.Documents.Get("ayende", transactionInformation)); }
public override VetoResult AllowPut(string key, RavenJObject document, RavenJObject 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; }
public void WhenUsingTransactionWillFailIfDocumentEtagDoesNotMatch() { db.Put("ayende", null, RavenJObject.Parse("{ayende:'oren'}"), new RavenJObject(), null); var transactionInformation = new TransactionInformation { Id = Guid.NewGuid(), Timeout = TimeSpan.FromMinutes(1) }; Assert.Throws<ConcurrencyException>( () => db.Put("ayende", Guid.NewGuid(), RavenJObject.Parse("{ayende:'rahien'}"), new RavenJObject(), transactionInformation)); }
public bool Delete(string key, Etag etag, TransactionInformation transactionInformation, out RavenJObject metadata, IEnumerable <string> participatingIds = null) { if (key == null) { throw new ArgumentNullException("key"); } key = key.Trim(); var deleted = false; if (Log.IsDebugEnabled) { Log.Debug("Delete a document with key: {0} and etag {1}", key, etag); } RavenJObject metadataVar = null; using (Database.DocumentLock.Lock()) { TransactionalStorage.Batch(actions => { AssertDeleteOperationNotVetoed(key, transactionInformation); if (transactionInformation == null) { Database.DeleteTriggers.Apply(trigger => trigger.OnDelete(key, null)); string collection = null; Etag deletedETag; if (actions.Documents.DeleteDocument(key, etag, out metadataVar, out deletedETag)) { deleted = true; actions.Indexing.RemoveAllDocumentReferencesFrom(key); WorkContext.MarkDeleted(key); Database.Indexes.CheckReferenceBecauseOfDocumentUpdate(key, actions, participatingIds); collection = metadataVar.Value <string>(Constants.RavenEntityName); DeleteDocumentFromIndexesForCollection(key, collection, actions); if (deletedETag != null) { Database.Prefetcher.AfterDelete(key, deletedETag); } Database.DeleteTriggers.Apply(trigger => trigger.AfterDelete(key, null, metadataVar)); } TransactionalStorage .ExecuteImmediatelyOrRegisterForSynchronization(() => { Database.DeleteTriggers.Apply(trigger => trigger.AfterCommit(key)); if (string.IsNullOrEmpty(collection) == false) { Database.LastCollectionEtags.Update(collection); } Database.Notifications.RaiseNotifications(new DocumentChangeNotification { Id = key, Type = DocumentChangeTypes.Delete, TypeName = (metadataVar != null) ? metadataVar.Value <string>(Constants.RavenClrType) : null, CollectionName = (metadataVar != null) ? metadataVar.Value <string>(Constants.RavenEntityName) : null }, metadataVar); }); } else { var doc = actions.Documents.DocumentMetadataByKey(key); Database.InFlightTransactionalState.DeleteDocumentInTransaction(transactionInformation, key, etag, doc == null ? Etag.Empty : doc.Etag, UuidGenerator); deleted = doc != null; } WorkContext.ShouldNotifyAboutWork(() => "DEL " + key); }); metadata = metadataVar; return(deleted); } }
public override ReadVetoResult AllowRead(string key, JObject metadata, ReadOperation operation, TransactionInformation transactionInformation) { if (operation == ReadOperation.Index) { return(ReadVetoResult.Allowed); } var name = metadata["hidden"]; if (name != null && name.Value <bool>()) { return(ReadVetoResult.Ignore); } return(ReadVetoResult.Allowed); }
public Guid AddDocumentInTransaction(string key, Guid?etag, JObject data, JObject metadata, TransactionInformation transactionInformation) { Api.JetSetCurrentIndex(session, Documents, "by_key"); Api.MakeKey(session, Documents, key, Encoding.Unicode, MakeKeyGrbit.NewKey); var isUpdate = Api.TrySeek(session, Documents, SeekGrbit.SeekEQ); if (isUpdate) { EnsureNotLockedByTransaction(key, transactionInformation.Id); EnsureDocumentEtagMatchInTransaction(key, etag); using (var update = new Update(session, Documents, JET_prep.Replace)) { Api.SetColumn(session, Documents, tableColumnsCache.DocumentsColumns["locked_by_transaction"], transactionInformation.Id.ToByteArray()); update.Save(); } } else { EnsureDocumentIsNotCreatedInAnotherTransaction(key, transactionInformation.Id); } EnsureTransactionExists(transactionInformation); Guid newEtag = DocumentDatabase.CreateSequentialUuid(); Api.JetSetCurrentIndex(session, DocumentsModifiedByTransactions, "by_key"); Api.MakeKey(session, DocumentsModifiedByTransactions, key, Encoding.Unicode, MakeKeyGrbit.NewKey); var isUpdateInTransaction = Api.TrySeek(session, DocumentsModifiedByTransactions, SeekGrbit.SeekEQ); var bytes = documentCodecs.Aggregate(Encoding.UTF8.GetBytes(data.ToString()), (current, codec) => codec.Encode(key, data, metadata, current)); using (var update = new Update(session, DocumentsModifiedByTransactions, isUpdateInTransaction ? JET_prep.Replace : JET_prep.Insert)) { Api.SetColumn(session, DocumentsModifiedByTransactions, tableColumnsCache.DocumentsModifiedByTransactionsColumns["key"], key, Encoding.Unicode); Api.SetColumn(session, DocumentsModifiedByTransactions, tableColumnsCache.DocumentsModifiedByTransactionsColumns["data"], bytes); Api.SetColumn(session, DocumentsModifiedByTransactions, tableColumnsCache.DocumentsModifiedByTransactionsColumns["etag"], newEtag.ToByteArray()); Api.SetColumn(session, DocumentsModifiedByTransactions, tableColumnsCache.DocumentsModifiedByTransactionsColumns["metadata"], Encoding.UTF8.GetBytes(metadata.ToString())); Api.SetColumn(session, DocumentsModifiedByTransactions, tableColumnsCache.DocumentsModifiedByTransactionsColumns["delete_document"], false); Api.SetColumn(session, DocumentsModifiedByTransactions, tableColumnsCache.DocumentsModifiedByTransactionsColumns["locked_by_transaction"], transactionInformation.Id.ToByteArray()); update.Save(); } logger.DebugFormat("Inserted a new document with key '{0}', update: {1}, in transaction: {2}", key, isUpdate, transactionInformation.Id); return(newEtag); }
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); }
public override VetoResult AllowPut(string key, RavenJObject document, RavenJObject metadata, TransactionInformation transactionInformation) { if (Database.Name != null && Database.Name != Constants.SystemDatabase) { return(VetoResult.Allowed); } if (key.StartsWith(RavenDatabasesPrefix, StringComparison.InvariantCultureIgnoreCase) == false) { return(VetoResult.Allowed); } var tempPermission = metadata[Constants.AllowBundlesChange]; if (tempPermission != null) { metadata.Remove(Constants.AllowBundlesChange); // this is a temp marker so do not persist this medatada } var bundlesChangesAllowed = tempPermission != null && tempPermission.Value <string>() .Equals("true", StringComparison.InvariantCultureIgnoreCase); if (bundlesChangesAllowed) { return(VetoResult.Allowed); } var existingDbDoc = Database.Documents.Get(key, transactionInformation); if (existingDbDoc == null) { return(VetoResult.Allowed); } var currentDbDocument = existingDbDoc.DataAsJson.JsonDeserialization <DatabaseDocument>(); var currentBundles = new List <string>(); string value; if (currentDbDocument.Settings.TryGetValue(Constants.ActiveBundles, out value)) { currentBundles = value.GetSemicolonSeparatedValues(); } var newDbDocument = document.JsonDeserialization <DatabaseDocument>(); var newBundles = new List <string>(); if (newDbDocument.Settings.TryGetValue(Constants.ActiveBundles, out value)) { newBundles = value.GetSemicolonSeparatedValues(); } if (currentBundles.Count == newBundles.Count) { return(VetoResult.Allowed); } if (currentBundles.Count == 0) { return(VetoResult.Allowed); } if (currentBundles.TrueForAll(x => newBundles.Contains(x))) { return(VetoResult.Allowed); } return(VetoResult.Deny( "You should not change 'Raven/ActiveBundles' setting for a database. This setting should be set only once when a database is created. " + "If you really need to override it you have to specify {\"" + Constants.AllowBundlesChange + "\": true} in metadata of a database document every time when you send it." + Environment.NewLine + "Current: " + string.Join("; ", currentBundles) + Environment.NewLine + "New: " + string.Join("; '", newBundles))); }
private T DocumentByKeyInternal <T>(string key, TransactionInformation transactionInformation, Func <Tuple <MemoryStream, RavenJObject, int>, JsonDocumentMetadata, T> createResult) where T : class { RavenJObject metadata; var resultInTx = storage.DocumentsModifiedByTransactions.Read(new RavenJObject { { "key", key } }); if (transactionInformation != null && resultInTx != null) { if (resultInTx.Key.Value <string>("txId") == transactionInformation.Id) { if (resultInTx.Key.Value <bool>("deleted")) { return(null); } var txEtag = Etag.Parse(resultInTx.Key.Value <byte[]>("etag")); var resultTx = ReadMetadata(key, txEtag, resultInTx.Data, out metadata); return(createResult(resultTx, new JsonDocumentMetadata { Key = resultInTx.Key.Value <string>("key"), Etag = txEtag, Metadata = metadata, LastModified = resultInTx.Key.Value <DateTime>("modified"), })); } } var readResult = storage.Documents.Read(new RavenJObject { { "key", key } }); if (readResult == null) { if (resultInTx != null) { return(createResult(Tuple.Create <MemoryStream, RavenJObject, int>(null, new RavenJObject(), 0), new JsonDocumentMetadata { Key = resultInTx.Key.Value <string>("key"), Etag = Etag.Empty, Metadata = new RavenJObject { { Constants.RavenDocumentDoesNotExists, true } }, NonAuthoritativeInformation = true, LastModified = DateTime.MinValue })); } return(null); } var etag = Etag.Parse(readResult.Key.Value <byte[]>("etag")); var result = ReadMetadata(key, etag, readResult.Data, out metadata); return(createResult(result, new JsonDocumentMetadata { Key = readResult.Key.Value <string>("key"), Etag = etag, Metadata = metadata, LastModified = readResult.Key.Value <DateTime>("modified") })); }
public Guid AddDocumentInTransaction(string key, Guid?etag, RavenJObject data, RavenJObject metadata, TransactionInformation transactionInformation) { var readResult = storage.Documents.Read(new RavenJObject { { "key", key } }); if (readResult != null) // update { StorageHelper.AssertNotModifiedByAnotherTransaction(storage, this, key, readResult, transactionInformation); AssertValidEtag(key, readResult, storage.DocumentsModifiedByTransactions.Read(new RavenJObject { { "key", key } }), etag, "DELETE"); var ravenJObject = ((RavenJObject)readResult.Key.CloneToken()); ravenJObject["txId"] = transactionInformation.Id.ToByteArray(); if (storage.Documents.UpdateKey(ravenJObject) == false) { throw new ConcurrencyException("PUT attempted on document '" + key + "' that is currently being modified by another transaction"); } } else { readResult = storage.DocumentsModifiedByTransactions.Read(new RavenJObject { { "key", key } }); StorageHelper.AssertNotModifiedByAnotherTransaction(storage, this, key, readResult, transactionInformation); } storage.Transactions.UpdateKey(new RavenJObject { { "txId", transactionInformation.Id.ToByteArray() }, { "timeout", SystemTime.UtcNow.Add(transactionInformation.Timeout) } }); var ms = new MemoryStream(); metadata.WriteTo(ms); using (var stream = documentCodecs.Aggregate <Lazy <AbstractDocumentCodec>, Stream>(ms, (memoryStream, codec) => codec.Value.Encode(key, data, metadata, memoryStream))) { data.WriteTo(stream); stream.Flush(); } var newEtag = generator.CreateSequentialUuid(UuidType.DocumentTransactions); storage.DocumentsModifiedByTransactions.Put(new RavenJObject { { "key", key }, { "etag", newEtag.ToByteArray() }, { "modified", SystemTime.UtcNow }, { "txId", transactionInformation.Id.ToByteArray() } }, ms.ToArray()); return(newEtag); }
public override void OnPut(string key, RavenJObject document, RavenJObject metadata, TransactionInformation transactionInformation) { if (string.IsNullOrEmpty(Database.Name) == false && Database.Name != Constants.SystemDatabase) { return; } if (key.StartsWith(Constants.Database.Prefix, StringComparison.OrdinalIgnoreCase) == false) { return; } RavenJObject settings; RavenJToken value; if (document.TryGetValue("Settings", out value) == false) { document["Settings"] = settings = new RavenJObject(); } else { settings = (RavenJObject)value; } EnsureQuotasBundleActivated(settings); EnsureVoronIsSetAsStorageEngineAndIsRunningInMemory(settings); }
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.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); } } }
public async Task <IActionResult> GetTransactions( string cryptoCode, [ModelBinder(BinderType = typeof(DerivationStrategyModelBinder))] DerivationStrategyBase derivationScheme, [ModelBinder(BinderType = typeof(BitcoinAddressModelBinder))] BitcoinAddress address, [ModelBinder(BinderType = typeof(UInt256ModelBinding))] uint256 txId = null, bool includeTransaction = true) { var trackedSource = GetTrackedSource(derivationScheme, address); if (trackedSource == null) { throw new ArgumentNullException(nameof(trackedSource)); } TransactionInformation fetchedTransactionInfo = null; var network = GetNetwork(cryptoCode, false); var chain = ChainProvider.GetChain(network); var repo = RepositoryProvider.GetRepository(network); var response = new GetTransactionsResponse(); int currentHeight = chain.Height; response.Height = currentHeight; var txs = await GetAnnotatedTransactions(repo, chain, trackedSource, txId); foreach (var item in new[] { new { TxSet = response.ConfirmedTransactions, AnnotatedTx = txs.ConfirmedTransactions }, new { TxSet = response.UnconfirmedTransactions, AnnotatedTx = txs.UnconfirmedTransactions }, new { TxSet = response.ReplacedTransactions, AnnotatedTx = txs.ReplacedTransactions }, }) { foreach (var tx in item.AnnotatedTx) { var txInfo = new TransactionInformation() { BlockHash = tx.Height.HasValue ? tx.Record.BlockHash : null, Height = tx.Height, TransactionId = tx.Record.TransactionHash, Transaction = includeTransaction ? tx.Record.Transaction : null, Confirmations = tx.Height.HasValue ? currentHeight - tx.Height.Value + 1 : 0, Timestamp = tx.Record.FirstSeen, Inputs = tx.Record.SpentOutpoints.Select(o => txs.GetUTXO(o)).Where(o => o != null).ToList(), Outputs = tx.Record.GetReceivedOutputs().ToList() }; if (txId == null || txId == txInfo.TransactionId) { item.TxSet.Transactions.Add(txInfo); } if (txId != null && txId == txInfo.TransactionId) { fetchedTransactionInfo = txInfo; } txInfo.BalanceChange = txInfo.Outputs.Select(o => o.Value).Sum() - txInfo.Inputs.Select(o => o.Value).Sum(); } item.TxSet.Transactions.Reverse(); // So the youngest transaction is generally first } if (txId == null) { return(Json(response)); } else if (fetchedTransactionInfo == null) { return(NotFound()); } else { return(Json(fetchedTransactionInfo)); } }
public JsonDocument DocumentByKey(string key, TransactionInformation transactionInformation) { byte[] data; JObject metadata; if (transactionInformation != null) { Api.JetSetCurrentIndex(session, DocumentsModifiedByTransactions, "by_key"); Api.MakeKey(session, DocumentsModifiedByTransactions, key, Encoding.Unicode, MakeKeyGrbit.NewKey); if (Api.TrySeek(session, DocumentsModifiedByTransactions, SeekGrbit.SeekEQ)) { var txId = Api.RetrieveColumn(session, DocumentsModifiedByTransactions, tableColumnsCache.DocumentsModifiedByTransactionsColumns["locked_by_transaction"]); if (new Guid(txId) == transactionInformation.Id) { if (Api.RetrieveColumnAsBoolean(session, DocumentsModifiedByTransactions, tableColumnsCache.DocumentsModifiedByTransactionsColumns["delete_document"]) == true) { logger.DebugFormat("Document with key '{0}' was deleted in transaction: {1}", key, transactionInformation.Id); return(null); } data = Api.RetrieveColumn(session, DocumentsModifiedByTransactions, tableColumnsCache.DocumentsModifiedByTransactionsColumns["data"]); metadata = Api.RetrieveColumn(session, DocumentsModifiedByTransactions, tableColumnsCache.DocumentsModifiedByTransactionsColumns["metadata"]).ToJObject(); data = documentCodecs.Aggregate(data, (bytes, codec) => codec.Decode(key, metadata, bytes)); logger.DebugFormat("Document with key '{0}' was found in transaction: {1}", key, transactionInformation.Id); var etag = new Guid(Api.RetrieveColumn(session, DocumentsModifiedByTransactions, tableColumnsCache.DocumentsModifiedByTransactionsColumns["etag"])); return(new JsonDocument { DataAsJson = data.ToJObject(), Etag = etag, Key = Api.RetrieveColumnAsString(session, DocumentsModifiedByTransactions, tableColumnsCache.DocumentsModifiedByTransactionsColumns["key"], Encoding.Unicode), Metadata = metadata }); } } } Api.JetSetCurrentIndex(session, Documents, "by_key"); Api.MakeKey(session, Documents, key, Encoding.Unicode, MakeKeyGrbit.NewKey); if (Api.TrySeek(session, Documents, SeekGrbit.SeekEQ) == false) { logger.DebugFormat("Document with key '{0}' was not found", key); return(null); } data = Api.RetrieveColumn(session, Documents, tableColumnsCache.DocumentsColumns["data"]); metadata = Api.RetrieveColumn(session, Documents, tableColumnsCache.DocumentsColumns["metadata"]).ToJObject(); data = documentCodecs.Aggregate(data, (bytes, codec) => codec.Decode(key, metadata, bytes)); logger.DebugFormat("Document with key '{0}' was found", key); var existingEtag = new Guid(Api.RetrieveColumn(session, Documents, tableColumnsCache.DocumentsColumns["etag"])); return(new JsonDocument { DataAsJson = data.ToJObject(), Etag = existingEtag, Key = Api.RetrieveColumnAsString(session, Documents, tableColumnsCache.DocumentsColumns["key"], Encoding.Unicode), Metadata = metadata }); }
public JsonDocumentMetadata DocumentMetadataByKey(string key, TransactionInformation transactionInformation) { return(DocumentByKeyInternal(key, transactionInformation, (stream, metadata) => metadata)); }
/// <summary> /// Initializes a new instance of the <see cref="RavenClientEnlistment"/> class. /// </summary> public RavenClientEnlistment(ITransactionalDocumentSession session, Action onTxComplete) { transaction = Transaction.Current.TransactionInformation; this.session = session; this.onTxComplete = onTxComplete; }
private PatchResultData ApplyPatchInternal(string docId, Etag etag, TransactionInformation transactionInformation, Func <JsonDocument, RavenJObject> patcher, Func <RavenJObject> patcherIfMissing, Func <IList <JsonDocument> > getDocsCreatedInPatch, Func <RavenJObject> getDebugActions, bool debugMode) { if (docId == null) { throw new ArgumentNullException("docId"); } docId = docId.Trim(); var result = new PatchResultData { PatchResult = PatchResult.Patched }; bool shouldRetry = false; int retries = 128; Random rand = null; do { var doc = Database.Documents.Get(docId, transactionInformation); Log.Debug(() => string.Format("Preparing to apply patch on ({0}). Document found?: {1}.", docId, doc != null)); if (etag != null && doc != null && doc.Etag != etag) { Debug.Assert(doc.Etag != null); Log.Debug(() => string.Format("Got concurrent exception while tried to patch the following document ID: {0}", docId)); throw new ConcurrencyException("Could not patch document '" + docId + "' because non current etag was used") { ActualETag = doc.Etag, ExpectedETag = etag, }; } var documentBeforePatching = doc != null?doc.ToJson().CloneToken() : null; var jsonDoc = (doc != null ? patcher(doc) : patcherIfMissing()); if (jsonDoc == null) { Log.Debug(() => string.Format("Preparing to apply patch on ({0}). DocumentDoesNotExists.", docId)); result.PatchResult = PatchResult.DocumentDoesNotExists; } else { if (debugMode) { result.Document = jsonDoc; result.PatchResult = PatchResult.Tested; result.DebugActions = getDebugActions(); } else { try { var notModified = false; if (doc == null) { Database.Documents.Put(docId, null, jsonDoc, jsonDoc.Value <RavenJObject>(Constants.Metadata), transactionInformation); } else { if (IsNotModified(jsonDoc.CloneToken(), documentBeforePatching)) { notModified = true; } else { Database.Documents.Put(doc.Key, (doc.Etag), jsonDoc, jsonDoc.Value <RavenJObject>(Constants.Metadata), transactionInformation); } } var docsCreatedInPatch = getDocsCreatedInPatch(); if (docsCreatedInPatch != null && docsCreatedInPatch.Count > 0) { foreach (var docFromPatch in docsCreatedInPatch) { Database.Documents.Put(docFromPatch.Key, docFromPatch.Etag, docFromPatch.DataAsJson, docFromPatch.Metadata, transactionInformation); } } shouldRetry = false; result.PatchResult = notModified ? PatchResult.NotModified : PatchResult.Patched; } catch (ConcurrencyException) { if (TransactionalStorage.IsAlreadyInBatch) { throw; } if (retries-- > 0) { shouldRetry = true; if (rand == null) { rand = new Random(); } Thread.Sleep(rand.Next(5, Math.Max(retries * 2, 10))); continue; } throw; } } } if (shouldRetry == false) { WorkContext.ShouldNotifyAboutWork(() => "PATCH " + docId); } } while (shouldRetry); return(result); }
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; } object value; metadata.__ExternalState.TryGetValue("Next-Revision", out value); Database.Documents.Put(key + "/revisions/" + value, null, (RavenJObject)document.CreateSnapshot(), copyMetadata, transactionInformation); } }
public override void OnPut(string key, RavenJObject document, RavenJObject metadata, TransactionInformation transactionInformation) { document["created_at"] = new RavenJValue(new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc)); }
public override VetoResult AllowPut(string key, RavenJObject document, RavenJObject metadata, TransactionInformation transactionInformation) { var jsonDocument = Database.Documents.Get(key, transactionInformation); if (jsonDocument == null) { return(VetoResult.Allowed); } if (Database.ChangesToRevisionsAllowed() == false && jsonDocument.Metadata.Value <string>(VersioningUtil.RavenDocumentRevisionStatus) == "Historical" && Database.IsVersioningActive(metadata)) { return(VetoResult.Deny("Modifying a historical revision is not allowed")); } return(VetoResult.Allowed); }
public override void OnRead(string key, JObject document, JObject metadata, ReadOperation operation, TransactionInformation transactionInformation) { var name = document.Property("name"); if (name != null) { name.Value = new JValue(name.Value.Value <string>().ToUpper()); } }
public override VetoResult AllowPut(string key, RavenJObject document, RavenJObject metadata, TransactionInformation transactionInformation) { return(VetoResult.Allowed); }
private Etag AssertValidEtag(string key, Etag etag, string op, TransactionInformation transactionInformation) { var readResult = storage.Documents.Read(new RavenJObject { { "key", key } }); if (readResult != null) { var existingEtag = Etag.Parse(readResult.Key.Value <byte[]>("etag")); if (etag != null) { Etag next; while (etagTouches.TryGetValue(etag, out next)) { etag = next; } if (existingEtag != etag) { if (etag == Etag.Empty) { RavenJObject metadata; ReadMetadata(key, existingEtag, readResult.Data, out metadata); if (metadata.ContainsKey(Constants.RavenDeleteMarker) && metadata.Value <bool>(Constants.RavenDeleteMarker)) { return(existingEtag); } } throw new ConcurrencyException(op + " attempted on document '" + key + "' using a non current etag") { ActualETag = existingEtag, ExpectedETag = etag }; } } return(existingEtag); } if (etag != null && etag != Etag.Empty) // expected something to be there. { throw new ConcurrencyException("PUT attempted on document '" + key + "' using a non current etag (document deleted)") { ExpectedETag = etag } } ; readResult = storage.DocumentsModifiedByTransactions.Read(new RavenJObject { { "key", key } }); if (readResult == null) { return(null); } return(Etag.Parse(readResult.Key.Value <byte[]>("etag"))); } }
private void RemoveOldRevisions(string key, long revision, VersioningConfiguration versioningConfiguration, TransactionInformation transactionInformation) { long latestValidRevision = revision - versioningConfiguration.MaxRevisions; if (latestValidRevision <= 0) { return; } Database.Documents.Delete(string.Format("{0}/revisions/{1}", key, latestValidRevision), null, transactionInformation); }
public async Task <GetTransactionsResponse> GetTransactions( string cryptoCode, [ModelBinder(BinderType = typeof(DestinationModelBinder))] DerivationStrategyBase extPubKey, [ModelBinder(BinderType = typeof(BookmarksModelBinding))] HashSet <Bookmark> unconfirmedBookmarks = null, [ModelBinder(BinderType = typeof(BookmarksModelBinding))] HashSet <Bookmark> confirmedBookmarks = null, [ModelBinder(BinderType = typeof(BookmarksModelBinding))] HashSet <Bookmark> replacedBookmarks = null, bool includeTransaction = true, bool longPolling = false) { if (extPubKey == null) { throw new ArgumentNullException(nameof(extPubKey)); } GetTransactionsResponse response = null; using (CancellationTokenSource cts = new CancellationTokenSource()) { if (longPolling) { cts.CancelAfter(LongPollTimeout); } var network = GetNetwork(cryptoCode, false); var chain = ChainProvider.GetChain(network); var repo = RepositoryProvider.GetRepository(network); while (true) { response = new GetTransactionsResponse(); int currentHeight = chain.Height; response.Height = currentHeight; var txs = GetAnnotatedTransactions(repo, chain, extPubKey); foreach (var item in new[] { new { TxSet = response.ConfirmedTransactions, KnownBookmarks = confirmedBookmarks ?? new HashSet <Bookmark>(), AnnotatedTx = txs.ConfirmedTransactions }, new { TxSet = response.UnconfirmedTransactions, KnownBookmarks = unconfirmedBookmarks ?? new HashSet <Bookmark>(), AnnotatedTx = txs.UnconfirmedTransactions }, new { TxSet = response.ReplacedTransactions, KnownBookmarks = replacedBookmarks ?? new HashSet <Bookmark>(), AnnotatedTx = txs.ReplacedTransactions }, }) { item.TxSet.Bookmark = Bookmark.Start; item.TxSet.KnownBookmark = item.KnownBookmarks.Contains(Bookmark.Start) ? Bookmark.Start : null; BookmarkProcessor processor = new BookmarkProcessor(32 + 32 + 25); foreach (var tx in item.AnnotatedTx.Values) { processor.PushNew(); processor.AddData(tx.Record.Transaction.GetHash()); processor.AddData(tx.Record.BlockHash ?? uint256.Zero); processor.UpdateBookmark(); var txInfo = new TransactionInformation() { BlockHash = tx.Record.BlockHash, Height = tx.Record.BlockHash == null ? null : tx.Height, TransactionId = tx.Record.Transaction.GetHash(), Transaction = includeTransaction ? tx.Record.Transaction : null, Confirmations = tx.Record.BlockHash == null ? 0 : currentHeight - tx.Height.Value + 1, Timestamp = txs.GetByTxId(tx.Record.Transaction.GetHash()).Select(t => t.Record.FirstSeen).First(), Inputs = ToMatch(txs, tx.Record.Transaction.Inputs.Select(o => txs.GetUTXO(o.PrevOut)).ToList(), extPubKey, tx.Record.TransactionMatch.Inputs), Outputs = ToMatch(txs, tx.Record.Transaction.Outputs, extPubKey, tx.Record.TransactionMatch.Outputs) }; item.TxSet.Transactions.Add(txInfo); txInfo.BalanceChange = txInfo.Outputs.Select(o => o.Value).Sum() - txInfo.Inputs.Select(o => o.Value).Sum(); item.TxSet.Bookmark = processor.CurrentBookmark; if (item.KnownBookmarks.Contains(processor.CurrentBookmark)) { item.TxSet.KnownBookmark = processor.CurrentBookmark; item.TxSet.Transactions.Clear(); } } } if (!longPolling || response.HasChanges()) { break; } if (!await WaitingTransaction(extPubKey, cts.Token)) { break; } } } return(response); }
public override ReadVetoResult AllowRead(string key, JObject metadata, ReadOperation operation, TransactionInformation transactionInformation) { if (operation == ReadOperation.Index) { return(ReadVetoResult.Allowed); } var name = metadata["name"]; if (name != null && name.Value <string>().Any(char.IsUpper)) { return(ReadVetoResult.Deny("Upper case characters in the 'name' property means the document is a secret!")); } return(ReadVetoResult.Allowed); }
public override VetoResult AllowPut(string key, RavenJObject document, RavenJObject metadata, TransactionInformation transactionInformation) { return(SizeQuotaConfiguration.GetConfiguration(Database).AllowPut()); }
private Guid?AssertValidEtag(string key, Guid?etag, string op, TransactionInformation transactionInformation) { var readResult = storage.Documents.Read(new RavenJObject { { "key", key } }); if (readResult != null) { StorageHelper.AssertNotModifiedByAnotherTransaction(storage, transactionStorageActions, key, readResult, transactionInformation); var existingEtag = new Guid(readResult.Key.Value <byte[]>("etag")); if (etag != null) { if (existingEtag != etag) { if (etag.Value == Guid.Empty) { RavenJObject metadata; ReadMetadata(key, existingEtag, readResult.Data, out metadata); if (metadata.ContainsKey(Constants.RavenDeleteMarker) && metadata.Value <bool>(Constants.RavenDeleteMarker)) { return(existingEtag); } } throw new ConcurrencyException(op + " attempted on document '" + key + "' using a non current etag") { ActualETag = etag.Value, ExpectedETag = existingEtag, Key = key }; } } return(existingEtag); } if (etag != null && etag != Guid.Empty) // expected something to be there. { throw new ConcurrencyException("PUT attempted on document '" + key + "' using a non current etag (document deleted)") { ExpectedETag = etag.Value, Key = key } } ; readResult = storage.DocumentsModifiedByTransactions.Read(new RavenJObject { { "key", key } }); StorageHelper.AssertNotModifiedByAnotherTransaction(storage, transactionStorageActions, key, readResult, transactionInformation); if (readResult == null) { return(null); } return(new Guid(readResult.Key.Value <byte[]>("etag"))); } }
public override void OnPut(string key, RavenJObject jsonReplicationDocument, RavenJObject metadata, TransactionInformation transactionInformation) { if (AuditContext.IsInAuditContext) { return; } using (AuditContext.Enter()) { if (metadata.Value <string>("Raven-Entity-Name") == "People") { if (metadata["CreatedByPersonId"] == null) { metadata["CreatedByPersonId"] = CurrentOperationContext.Headers.Value.Value["CurrentUserPersonId"]; metadata["CreatedDate"] = CreatedAtDateTime; } else { metadata["LastUpdatedPersonId"] = CurrentOperationContext.Headers.Value.Value["CurrentUserPersonId"]; metadata["LastUpdatedDate"] = CreatedAtDateTime; } } } }
private JsonDocument ExecuteReadTriggersOnRead(JsonDocument resultingDocument, TransactionInformation transactionInformation, ReadOperation operation) { if (resultingDocument == null) { return(null); } triggers.Apply( trigger => trigger.OnRead(resultingDocument.Key, resultingDocument.DataAsJson, resultingDocument.Metadata, operation, transactionInformation)); return(resultingDocument); }
public JsonDocument ExecuteReadTriggers(JsonDocument document, TransactionInformation transactionInformation, ReadOperation operation) { return(ExecuteReadTriggersOnRead(ProcessReadVetoes(document, transactionInformation, operation), transactionInformation, operation)); }
public override void OnPut(string key, RavenJObject jsonReplicationDocument, RavenJObject metadata, TransactionInformation transactionInformation) { Hello = CurrentOperationContext.Headers.Value.Value["Hello"]; base.OnPut(key, jsonReplicationDocument, metadata, transactionInformation); }
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); } }