public static AssertNotModifiedByAnotherTransaction ( |
||
storage | ||
transactionStorageActions | ITransactionStorageActions | |
key | string | |
readResult | Table | |
transactionInformation | Raven.Database.TransactionInformation | |
return | void |
private void AssertValidEtag(string key, Guid?etag, string op, TransactionInformation transactionInformation) { var readResult = storage.Documents.Read(new JObject { { "key", key }, }); if (readResult != null) { StorageHelper.AssertNotModifiedByAnotherTransaction(storage, transactionStorageActions, key, readResult, transactionInformation); if (etag != null) { var existingEtag = new Guid(readResult.Key.Value <byte[]>("etag")); if (existingEtag != etag) { throw new ConcurrencyException(op + " attempted on document '" + key + "' using a non current etag") { ActualETag = etag.Value, ExpectedETag = existingEtag }; } } } else { readResult = storage.DocumentsModifiedByTransactions.Read(new JObject { { "key", key } }); StorageHelper.AssertNotModifiedByAnotherTransaction(storage, transactionStorageActions, key, readResult, transactionInformation); } }
public bool DeleteDocumentInTransaction(TransactionInformation transactionInformation, string key, Guid?etag) { var nonTxResult = storage.Documents.Read(new RavenJObject { { "key", key } }); if (nonTxResult == null) { if (etag != null && etag.Value != Guid.Empty) { throw new ConcurrencyException("DELETE attempted on document '" + key + "' using a non current etag") { ActualETag = Guid.Empty, ExpectedETag = etag.Value, Key = key }; } return(false); } var readResult = storage.DocumentsModifiedByTransactions.Read(new RavenJObject { { "key", key } }); StorageHelper.AssertNotModifiedByAnotherTransaction(storage, this, key, readResult, transactionInformation); AssertValidEtag(key, nonTxResult, readResult, etag, "DELETE"); var ravenJObject = ((RavenJObject)nonTxResult.Key.CloneToken()); ravenJObject["txId"] = transactionInformation.Id.ToByteArray(); if (storage.Documents.UpdateKey(ravenJObject) == false) { throw new ConcurrencyException("DELETE attempted on document '" + key + "' that is currently being modified by another transaction") { Key = key } } ; storage.Transactions.UpdateKey(new RavenJObject { { "txId", transactionInformation.Id.ToByteArray() }, { "timeout", SystemTime.UtcNow.Add(transactionInformation.Timeout) } }); var newEtag = generator.CreateSequentialUuid(UuidType.DocumentTransactions); storage.DocumentsModifiedByTransactions.UpdateKey(new RavenJObject { { "key", key }, { "etag", newEtag.ToByteArray() }, { "modified", SystemTime.UtcNow }, { "deleted", true }, { "txId", transactionInformation.Id.ToByteArray() } }); return(true); }
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 }; } } 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 } } ; 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 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") { Key = key } } ; } 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 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); ((RavenJObject)readResult.Key)["txId"] = transactionInformation.Id.ToByteArray(); if (storage.Documents.UpdateKey(readResult.Key) == 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); var dataBytes = documentCodecs.Aggregate(data.ToBytes(), (bytes, codec) => codec.Encode(key, data, metadata, bytes)); ms.Write(dataBytes, 0, dataBytes.Length); var newEtag = generator.CreateSequentialUuid(); storage.DocumentsModifiedByTransactions.Put(new RavenJObject { { "key", key }, { "etag", newEtag.ToByteArray() }, { "modified", SystemTime.UtcNow }, { "txId", transactionInformation.Id.ToByteArray() } }, ms.ToArray()); return(newEtag); }
public bool DeleteDocumentInTransaction(TransactionInformation transactionInformation, string key, Guid?etag) { var readResult = storage.Documents.Read(new RavenJObject { { "key", key } }); if (readResult == null) { return(false); } readResult = storage.DocumentsModifiedByTransactions.Read(new RavenJObject { { "key", key } }); StorageHelper.AssertNotModifiedByAnotherTransaction(storage, this, key, readResult, transactionInformation); AssertValidEtag(key, readResult, storage.DocumentsModifiedByTransactions.Read(new RavenJObject { { "key", key } }), etag); if (readResult != null) { ((RavenJObject)readResult.Key)["txId"] = transactionInformation.Id.ToByteArray(); if (storage.Documents.UpdateKey(readResult.Key) == false) { throw new ConcurrencyException("DELETE attempted on document '" + key + "' that is currently being modified by another transaction"); } } storage.Transactions.UpdateKey(new RavenJObject { { "txId", transactionInformation.Id.ToByteArray() }, { "timeout", SystemTime.UtcNow.Add(transactionInformation.Timeout) } }); var newEtag = generator.CreateSequentialUuid(); storage.DocumentsModifiedByTransactions.UpdateKey(new RavenJObject { { "key", key }, { "etag", newEtag.ToByteArray() }, { "modified", SystemTime.UtcNow }, { "deleted", true }, { "txId", transactionInformation.Id.ToByteArray() } }); return(true); }