Пример #1
0
 private void RemoveMetadataReservedProperties(RavenJObject metadata, InvokeSource source = InvokeSource.Default)
 {
     RemoveReservedProperties(metadata);
     metadata.Remove("Raven-Last-Modified");
     if (source != InvokeSource.FromConflictAtReplication)
     {
         metadata.Remove("Last-Modified");
     }
 }
Пример #2
0
 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;
 }
Пример #3
0
 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设置异常类型
 }
Пример #4
0
 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;
 }
Пример #5
0
        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);
        }
Пример #6
0
        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
            });
        }
Пример #7
0
        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
                });
            }
        }
Пример #8
0
        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);
            }
        }