private void RemoveMetadataReservedProperties(RavenJObject metadata, InvokeSource source = InvokeSource.Default) { RemoveReservedProperties(metadata); metadata.Remove("Raven-Last-Modified"); if (source != InvokeSource.FromConflictAtReplication) { metadata.Remove("Last-Modified"); } }
public InvokeResponse(InvokeSource source, InvokeProtocol protocol, IntPtr waitHandle, int srcMsgId, AnyValue result) { Source = source; Protocol = protocol; WaitHandle = waitHandle; SourceMsgId = srcMsgId; Error = InvokeResponseError.None; Result = result; }
public InvokeResponse(InvokeSource source, InvokeProtocol contentType, IntPtr waitHandle, int srcMsgId, InvokeResponseError error, string errorMsg) { Source = source; Protocol = contentType; WaitHandle = waitHandle; SourceMsgId = srcMsgId; Error = error; Result = AnyValue.From(errorMsg); //TODO:考虑AnyValue设置异常类型 }
public InvokeRequire(InvokeSource source, InvokeProtocol contentType, IntPtr waitHandle, string service, InvokeArgs args, int sourceMsgId, ISessionInfo session = null) { Source = source; ContentType = contentType; WaitHandle = waitHandle; SourceMsgId = sourceMsgId; Service = service; Args = args; WaitHandle = waitHandle; Session = session; }
private bool WriteDocumentData(string key, string normalizedKey, Etag etag, RavenJObject data, RavenJObject metadata, InvokeSource source, out Etag newEtag, out Etag existingEtag, out DateTime savedAt) { var normalizedKeySlice = (Slice)normalizedKey; var keyByEtagDocumentIndex = tableStorage.Documents.GetIndex(Tables.Documents.Indices.KeyByEtag); ushort?existingVersion; var isUpdate = tableStorage.Documents.Contains(Snapshot, normalizedKeySlice, writeBatch.Value, out existingVersion); existingEtag = null; if (isUpdate) { existingEtag = EnsureDocumentEtagMatch(normalizedKey, etag, "PUT"); keyByEtagDocumentIndex.Delete(writeBatch.Value, existingEtag); } else if (etag != null && etag != Etag.Empty) { throw new ConcurrencyException("PUT attempted on document '" + key + "' using a non current etag (document deleted)") { ExpectedETag = etag }; } var dataStream = CreateStream(); using (var finalDataStream = documentCodecs.Aggregate((Stream) new UndisposableStream(dataStream), (current, codec) => codec.Encode(normalizedKey, data, metadata, current))) { data.WriteTo(finalDataStream); finalDataStream.Flush(); } dataStream.Position = 0; tableStorage.Documents.Add(writeBatch.Value, normalizedKeySlice, dataStream, existingVersion ?? 0); newEtag = uuidGenerator.CreateSequentialUuid(UuidType.Documents); var keepLastModified = source == InvokeSource.FromConflictAtReplication && metadata.ContainsKey(Constants.LastModified); savedAt = keepLastModified ? metadata.Value <DateTime>(Constants.LastModified) : SystemTime.UtcNow; var isUpdated = PutDocumentMetadataInternal(key, normalizedKeySlice, metadata, newEtag, savedAt); keyByEtagDocumentIndex.Add(writeBatch.Value, newEtag, normalizedKey); return(isUpdated); }
public AddDocumentResult AddDocument(string key, Etag etag, RavenJObject data, RavenJObject metadata, InvokeSource source = InvokeSource.Default) { if (string.IsNullOrEmpty(key)) { throw new ArgumentNullException("key"); } Etag existingEtag; Etag newEtag; DateTime savedAt; var normalizedKey = CreateKey(key); var isUpdate = WriteDocumentData(key, normalizedKey, etag, data, metadata, source, out newEtag, out existingEtag, out savedAt); if (logger.IsDebugEnabled) { logger.Debug("AddDocument() - {0} document with key = '{1}'", isUpdate ? "Updated" : "Added", key); } if (existingEtag != null) { documentCacher.RemoveCachedDocument(normalizedKey, existingEtag); } return(new AddDocumentResult { Etag = newEtag, PrevEtag = existingEtag, SavedAt = savedAt, Updated = isUpdate }); }
public PutResult Put(string key, Etag etag, RavenJObject document, RavenJObject metadata, TransactionInformation transactionInformation, IEnumerable <string> participatingIds = null, InvokeSource source = InvokeSource.Default) { WorkContext.MetricsCounters.DocsPerSecond.Mark(); key = string.IsNullOrWhiteSpace(key) ? Guid.NewGuid().ToString() : key.Trim(); RemoveReservedProperties(document); RemoveMetadataReservedProperties(metadata, source); var newEtag = Etag.Empty; using (Database.DocumentLock.Lock()) { TransactionalStorage.Batch(actions => { if (key.EndsWith("/")) { key += GetNextIdentityValueWithoutOverwritingOnExistingDocuments(key, actions); } AssertPutOperationNotVetoed(key, metadata, document, transactionInformation); if (transactionInformation == null) { if (Database.InFlightTransactionalState.IsModified(key)) { throw new ConcurrencyException("PUT attempted on : " + key + " while it is being locked by another transaction"); } Database.PutTriggers.Apply(trigger => trigger.OnPut(key, document, metadata, null)); var addDocumentResult = actions.Documents.AddDocument(key, etag, document, metadata, source); newEtag = addDocumentResult.Etag; Database.Indexes.CheckReferenceBecauseOfDocumentUpdate(key, actions, participatingIds); metadata[Constants.LastModified] = addDocumentResult.SavedAt; metadata.EnsureSnapshot( "Metadata was written to the database, cannot modify the document after it was written (changes won't show up in the db). Did you forget to call CreateSnapshot() to get a clean copy?"); document.EnsureSnapshot( "Document was written to the database, cannot modify the document after it was written (changes won't show up in the db). Did you forget to call CreateSnapshot() to get a clean copy?"); actions.AfterStorageCommitBeforeWorkNotifications(new JsonDocument { Metadata = metadata, Key = key, DataAsJson = document, Etag = newEtag, LastModified = addDocumentResult.SavedAt, SkipDeleteFromIndex = addDocumentResult.Updated == false }, documents => { if (Database.IndexDefinitionStorage.IndexesCount == 0 || Database.WorkContext.RunIndexing == false) { return; } Database.Prefetcher.AfterStorageCommitBeforeWorkNotifications(PrefetchingUser.Indexer, documents); }); Database.PutTriggers.Apply(trigger => trigger.AfterPut(key, document, metadata, newEtag, null)); TransactionalStorage .ExecuteImmediatelyOrRegisterForSynchronization(() => { Database.PutTriggers.Apply(trigger => trigger.AfterCommit(key, document, metadata, newEtag)); var newDocumentChangeNotification = new DocumentChangeNotification { Id = key, Type = DocumentChangeTypes.Put, TypeName = metadata.Value <string>(Constants.RavenClrType), CollectionName = metadata.Value <string>(Constants.RavenEntityName), Etag = newEtag }; Database.Notifications.RaiseNotifications(newDocumentChangeNotification, metadata); }); WorkContext.ShouldNotifyAboutWork(() => "PUT " + key); } else { var doc = actions.Documents.DocumentMetadataByKey(key); newEtag = Database.InFlightTransactionalState.AddDocumentInTransaction(key, etag, document, metadata, transactionInformation, doc == null ? Etag.Empty : doc.Etag, UuidGenerator); } }); if (Log.IsDebugEnabled) { Log.Debug("Put document {0} with etag {1}", key, newEtag); } return(new PutResult { Key = key, ETag = newEtag }); } }
public AddDocumentResult AddDocument(string key, Etag etag, RavenJObject data, RavenJObject metadata, InvokeSource source = InvokeSource.Default) { if (key == null) { throw new ArgumentNullException("key"); } var byteCount = Encoding.Unicode.GetByteCount(key); if (byteCount >= 2048) { throw new ArgumentException(string.Format("The key must be a maximum of 2,048 bytes in Unicode, 1,024 characters, key is: '{0}'", key), "key"); } try { Api.JetSetCurrentIndex(session, Documents, "by_key"); Api.MakeKey(session, Documents, key, Encoding.Unicode, MakeKeyGrbit.NewKey); var isUpdate = Api.TrySeek(session, Documents, SeekGrbit.SeekEQ); Etag existingEtag = null; if (isUpdate) { existingEtag = EnsureDocumentEtagMatch(key, etag, "PUT"); } else { 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 } } ; if (Api.TryMoveFirst(session, Details)) { Api.EscrowUpdate(session, Details, tableColumnsCache.DetailsColumns["document_count"], 1); } } Etag newEtag = uuidGenerator.CreateSequentialUuid(UuidType.Documents); DateTime savedAt; try { using (var update = new Update(session, Documents, isUpdate ? JET_prep.Replace : JET_prep.Insert)) { Api.SetColumn(session, Documents, tableColumnsCache.DocumentsColumns["key"], key, Encoding.Unicode); using (var columnStream = new ColumnStream(session, Documents, tableColumnsCache.DocumentsColumns["data"])) { if (isUpdate) { columnStream.SetLength(0); // empty the existing value, since we are going to overwrite the entire thing } using (Stream stream = new BufferedStream(columnStream)) using ( var finalStream = documentCodecs.Aggregate(stream, (current, codec) => codec.Encode(key, data, metadata, current)) ) { data.WriteTo(finalStream); finalStream.Flush(); } } Api.SetColumn(session, Documents, tableColumnsCache.DocumentsColumns["etag"], newEtag.TransformToValueForEsentSorting()); var keepLastModified = source == InvokeSource.FromConflictAtReplication && metadata.ContainsKey(Constants.LastModified); savedAt = keepLastModified ? metadata.Value <DateTime>(Constants.LastModified) : SystemTime.UtcNow; Api.SetColumn(session, Documents, tableColumnsCache.DocumentsColumns["last_modified"], savedAt.ToBinary()); using (var columnStream = new ColumnStream(session, Documents, tableColumnsCache.DocumentsColumns["metadata"])) { if (isUpdate) { columnStream.SetLength(0); } using (Stream stream = new BufferedStream(columnStream)) { metadata.WriteTo(stream); stream.Flush(); } } update.Save(); } } catch (EsentErrorException e) { if (e.Error == JET_err.KeyDuplicate || e.Error == JET_err.WriteConflict) { throw new ConcurrencyException("PUT attempted on document '" + key + "' concurrently", e); } throw; } if (logger.IsDebugEnabled) { logger.Debug("Inserted a new document with key '{0}', update: {1}, ", key, isUpdate); } if (existingEtag != null) { cacher.RemoveCachedDocument(key, existingEtag); } return(new AddDocumentResult { Etag = newEtag, PrevEtag = existingEtag, SavedAt = savedAt, Updated = isUpdate }); } catch (EsentKeyDuplicateException e) { throw new ConcurrencyException("Illegal duplicate key " + key, e); } }