Beispiel #1
0
        public override HttpRequestMessage CreateRequest(JsonOperationContext ctx, ServerNode node, out string url)
        {
            var request = new HttpRequestMessage
            {
                Method  = HttpMethod.Post,
                Content = new BlittableJsonContent(stream =>
                {
                    using (var writer = new BlittableJsonTextWriter(ctx, stream))
                    {
                        writer.WriteStartObject();
                        writer.WriteArray("Commands", _commands);
                        if (_mode == TransactionMode.ClusterWide)
                        {
                            writer.WriteComma();
                            writer.WritePropertyName(nameof(TransactionMode));
                            writer.WriteString(nameof(TransactionMode.ClusterWide));
                        }
                        writer.WriteEndObject();
                    }
                })
            };

            if (_attachmentStreams != null && _attachmentStreams.Count > 0)
            {
                var multipartContent = new MultipartContent {
                    request.Content
                };
                foreach (var stream in _attachmentStreams)
                {
                    PutAttachmentCommandHelper.PrepareStream(stream);
                    var streamContent = new AttachmentStreamContent(stream, CancellationToken);
                    streamContent.Headers.TryAddWithoutValidation("Command-Type", "AttachmentStream");
                    multipartContent.Add(streamContent);
                }
                request.Content = multipartContent;
            }

            var sb = new StringBuilder($"{node.Url}/databases/{node.Database}/bulk_docs");

            AppendOptions(sb);

            url = sb.ToString();

            return(request);
        }
        private void WriteOperationHeaderToRemote(BlittableJsonTextWriter writer, bool drop = false)
        {
            var operation = drop ? TcpConnectionHeaderMessage.OperationTypes.Drop : TcpConnectionHeaderMessage.OperationTypes.Heartbeats;

            writer.WriteStartObject();
            {
                writer.WritePropertyName(nameof(TcpConnectionHeaderMessage.Operation));
                writer.WriteString(operation.ToString());
                writer.WriteComma();
                writer.WritePropertyName(nameof(TcpConnectionHeaderMessage.OperationVersion));
                writer.WriteInteger(TcpConnectionHeaderMessage.HeartbeatsTcpVersion);
                writer.WriteComma();
                writer.WritePropertyName(nameof(TcpConnectionHeaderMessage.DatabaseName));
                writer.WriteNull();
            }
            writer.WriteEndObject();
            writer.Flush();
        }
Beispiel #3
0
            public override HttpRequestMessage CreateRequest(JsonOperationContext ctx, ServerNode node, out string url)
            {
                url = $"{node.Url}/databases/{node.Database}/admin/sql-migration/import";

                var request = new HttpRequestMessage
                {
                    Method = HttpMethods.Post,

                    Content = new BlittableJsonContent(stream =>
                    {
                        using (var writer = new BlittableJsonTextWriter(ctx, stream))
                        {
                            writer.WriteStartObject();

                            writer.WritePropertyName(nameof(ConnectionStringName));
                            writer.WriteString(ConnectionStringName);
                            writer.WriteComma();

                            writer.WritePropertyName(nameof(BinaryToAttachment));
                            writer.WriteBool(BinaryToAttachment);
                            writer.WriteComma();

                            writer.WritePropertyName(nameof(TrimStrings));
                            writer.WriteBool(TrimStrings);
                            writer.WriteComma();

                            writer.WritePropertyName(nameof(SkipUnsupportedTypes));
                            writer.WriteBool(SkipUnsupportedTypes);
                            writer.WriteComma();

                            writer.WritePropertyName(nameof(BatchSize));
                            writer.WriteInteger(BatchSize);
                            writer.WriteComma();

                            WriteTablesArray(nameof(Tables), Tables, writer);

                            writer.WriteEndObject();
                        }
                    })
                };

                return(request);
            }
Beispiel #4
0
        public async Task PostIndexType()
        {
            using (ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
            {
                using (var json = await context.ReadForMemoryAsync(RequestBodyStream(), "map"))
                {
                    var indexDefinition = JsonDeserializationServer.IndexDefinition(json);

                    var indexType = indexDefinition.DetectStaticIndexType();

                    using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                    {
                        writer.WriteStartObject();
                        writer.WritePropertyName("IndexType");
                        writer.WriteString(indexType.ToString());
                        writer.WriteEndObject();;
                    }
                }
            }
        }
Beispiel #5
0
        public Task GetNextOperationId()
        {
            var nextId = Database.Operations.GetNextOperationId();

            using (ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
            {
                using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                {
                    writer.WriteStartObject();
                    writer.WritePropertyName("Id");
                    writer.WriteInteger(nextId);
                    writer.WriteComma();
                    writer.WritePropertyName(nameof(GetNextOperationIdCommand.NodeTag));
                    writer.WriteString(Server.ServerStore.NodeTag);
                    writer.WriteEndObject();
                }
            }

            return(Task.CompletedTask);
        }
Beispiel #6
0
                public override HttpRequestMessage CreateRequest(JsonOperationContext ctx, ServerNode node, out string url)
                {
                    url = $"{node.Url}/studio-tasks/format";

                    return(new HttpRequestMessage
                    {
                        Method = HttpMethod.Post,
                        Content = new BlittableJsonContent(stream =>
                        {
                            using (var writer = new BlittableJsonTextWriter(_context, stream))
                            {
                                writer.WriteStartObject();
                                writer.WritePropertyName(nameof(FormatOperation.Result.Expression));
                                writer.WriteString(_expression);

                                writer.WriteEndObject();
                            }
                        })
                    });
                }
Beispiel #7
0
        public Task GetDocumentsAttachmentMetadataWithCounts()
        {
            var id = GetStringQueryString("id", false);

            using (ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
                using (context.OpenReadTransaction())
                {
                    var array = Database.DocumentsStorage.AttachmentsStorage.GetAttachmentsMetadataForDocumenWithCounts(context, id.ToLowerInvariant());
                    using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                    {
                        writer.WriteStartObject();
                        writer.WritePropertyName("Id");
                        writer.WriteString(id);
                        writer.WriteComma();
                        writer.WriteArray("Attachments", array, context);
                        writer.WriteEndObject();
                    }
                }
            return(Task.CompletedTask);
        }
        private void WriteSchemaResponse(DocumentsOperationContext context, SqlSchemaResultTable[] Tables = null, string Error = null)
        {
            using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
            {
                writer.WriteStartObject();

                WriteTablesArray(nameof(Tables), Tables, writer);
                writer.WriteComma();

                writer.WritePropertyName(nameof(Error));
                writer.WriteString(Error);
                writer.WriteComma();

                var Success = Error == null;
                writer.WritePropertyName(nameof(Success));
                writer.WriteBool(Success);

                writer.WriteEndObject();
            }
        }
Beispiel #9
0
        public async Task SetupAgreement()
        {
            AssertOnlyInSetupMode();

            var email = GetQueryStringValueAndAssertIfSingleAndNotEmpty("email");

            using (ServerStore.ContextPool.AllocateOperationContext(out JsonOperationContext context))
            {
                var baseUri = new Uri("https://letsencrypt.org/");
                var uri     = new Uri(baseUri, await SetupManager.LetsEncryptAgreement(email, ServerStore));

                using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                {
                    writer.WriteStartObject();
                    writer.WritePropertyName("Uri");
                    writer.WriteString(uri.AbsoluteUri);
                    writer.WriteEndObject();
                }
            }
        }
Beispiel #10
0
        public Task FullDataDirectory()
        {
            var path = GetStringQueryString("path", required: false);
            var name = GetStringQueryString("name", required: false);

            var baseDataDirectory = ServerStore.Configuration.Core.DataDirectory.FullPath;

            // 1. Used as default when both Name & Path are Not defined
            var result = baseDataDirectory;

            // 2. Path defined, Path overrides any given Name
            if (string.IsNullOrEmpty(path) == false)
            {
                result = PathUtil.ToFullPath(path, baseDataDirectory);
            }

            // 3. Name defined, No path
            else if (string.IsNullOrEmpty(name) == false)
            {
                // 'Databases' prefix is added...
                result = RavenConfiguration.GetDataDirectoryPath(ServerStore.Configuration.Core, name, ResourceType.Database);
            }

            if (ServerStore.Configuration.Core.EnforceDataDirectoryPath)
            {
                if (PathUtil.IsSubDirectory(result, ServerStore.Configuration.Core.DataDirectory.FullPath) == false)
                {
                    result = $"The administrator has restricted databases to be created only under the {RavenConfiguration.GetKey(x => x.Core.DataDirectory)} directory: '{ServerStore.Configuration.Core.DataDirectory.FullPath}'.";
                }
            }
            using (ServerStore.ContextPool.AllocateOperationContext(out JsonOperationContext context))
                using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                {
                    writer.WriteStartObject();
                    writer.WritePropertyName("FullPath");
                    writer.WriteString(result);
                    writer.WriteEndObject();
                }

            return(Task.CompletedTask);
        }
Beispiel #11
0
            public override HttpRequestMessage CreateRequest(JsonOperationContext ctx, ServerNode node, out string url)
            {
                url = $"{node.Url}/admin/certificates/replace-cluster-cert?replaceImmediately={_replaceImmediately}";

                var request = new HttpRequestMessage
                {
                    Method  = HttpMethod.Post,
                    Content = new BlittableJsonContent(stream =>
                    {
                        using (var writer = new BlittableJsonTextWriter(ctx, stream))
                        {
                            writer.WriteStartObject();
                            writer.WritePropertyName(nameof(CertificateDefinition.Certificate));
                            writer.WriteString(Convert.ToBase64String(_certBytes)); // keep the private key -> this is a server cert
                            writer.WriteEndObject();
                        }
                    })
                };

                return(request);
            }
        private void WriteHeaders(BlittableJsonTextWriter writer, HttpContext httpContext, LazyStringValue headersProperty)
        {
            writer.WritePropertyName(headersProperty);
            writer.WriteStartObject();
            bool headerStart = true;

            foreach (var header in httpContext.Response.Headers)
            {
                foreach (var value in header.Value)
                {
                    if (headerStart == false)
                    {
                        writer.WriteComma();
                    }
                    headerStart = false;
                    writer.WritePropertyName(header.Key);
                    writer.WriteString(value);
                }
            }
            writer.WriteEndObject();
        }
        public async Task Allocations()
        {
            var delay = GetIntValueQueryString("delay", required: false) ?? 5;

            IReadOnlyCollection <AllocationInfo> allocations;

            using (var listener = new Expensive_GcEventListener())
            {
                await Task.Delay(TimeSpan.FromSeconds(delay));

                allocations = listener.Allocations;
            }

            using (ServerStore.ContextPool.AllocateOperationContext(out TransactionOperationContext context))
                using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                {
                    writer.WriteStartObject();

                    var first = true;
                    foreach (var alloc in allocations.OrderByDescending(x => x.Allocations))
                    {
                        if (first == false)
                        {
                            writer.WriteComma();
                        }

                        first = false;
                        writer.WritePropertyName(alloc.Type);
                        writer.WriteStartObject();
                        writer.WritePropertyName("Memory");
                        writer.WriteString(new Size((long)alloc.Allocations, SizeUnit.Bytes).ToString());
                        writer.WriteComma();
                        writer.WritePropertyName("Allocations");
                        writer.WriteInteger(alloc.NumberOfAllocations);
                        writer.WriteEndObject();
                    }

                    writer.WriteEndObject();
                }
        }
Beispiel #14
0
        public Task Exists()
        {
            var hash = GetStringQueryString("hash");

            using (ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
                using (context.OpenReadTransaction())
                    using (Slice.From(context.Allocator, hash, out var hashSlice))
                    {
                        var count = AttachmentsStorage.GetCountOfAttachmentsForHash(context, hashSlice);
                        using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                        {
                            writer.WriteStartObject();
                            writer.WritePropertyName("Hash");
                            writer.WriteString(hash);
                            writer.WriteComma();
                            writer.WritePropertyName("Count");
                            writer.WriteInteger(count);
                            writer.WriteEndObject();
                        }
                    }
            return(Task.CompletedTask);
        }
        protected void PersistMapFields(JsonOperationContext context, BlittableJsonTextWriter writer)
        {
            writer.WritePropertyName((nameof(MapFields)));
            writer.WriteStartArray();
            var first = true;

            foreach (var field in MapFields.Values)
            {
                if (first == false)
                {
                    writer.WriteComma();
                }

                writer.WriteStartObject();

                writer.WritePropertyName((nameof(field.Name)));
                writer.WriteString((field.Name));
                writer.WriteComma();

                writer.WritePropertyName((nameof(field.Highlighted)));
                writer.WriteBool(field.Highlighted);
                writer.WriteComma();

                writer.WritePropertyName((nameof(field.SortOption)));
                writer.WriteInteger((int)(field.SortOption ?? SortOptions.None));
                writer.WriteComma();

                writer.WritePropertyName((nameof(field.MapReduceOperation)));
                writer.WriteInteger((int)(field.MapReduceOperation));

                writer.WriteEndObject();

                first = false;
            }
            writer.WriteEndArray();
        }
Beispiel #16
0
        public static string ConvertResultToString(ScriptRunnerResult result)
        {
            var ms = new MemoryStream();

            using (var ctx = JsonOperationContext.ShortTermSingleUse())
                using (var writer = new BlittableJsonTextWriter(ctx, ms))
                {
                    writer.WriteStartObject();

                    writer.WritePropertyName("Result");

                    if (result.IsNull)
                    {
                        writer.WriteNull();
                    }
                    else if (result.RawJsValue.IsBoolean())
                    {
                        writer.WriteBool(result.RawJsValue.AsBoolean());
                    }
                    else if (result.RawJsValue.IsString())
                    {
                        writer.WriteString(result.RawJsValue.AsString());
                    }
                    else
                    {
                        writer.WriteObject(result.TranslateToObject(ctx));
                    }

                    writer.WriteEndObject();
                    writer.Flush();
                }

            var str = Encoding.UTF8.GetString(ms.ToArray());

            return(str);
        }
Beispiel #17
0
        public void WriteTo(BlittableJsonTextWriter writer)
        {
            writer.WriteStartObject();

            writer.WritePropertyName(nameof(UpTime));
            writer.WriteString(UpTime.ToString("c"));
            writer.WriteComma();

            writer.WritePropertyName(nameof(StartUpTime));
            writer.WriteDateTime(StartUpTime, isUtc: true);
            writer.WriteComma();

            writer.WritePropertyName(nameof(LastRequestTime));
            if (LastRequestTime.HasValue)
            {
                writer.WriteDateTime(LastRequestTime.Value, isUtc: true);
            }
            else
            {
                writer.WriteNull();
            }

            writer.WriteEndObject();
        }
Beispiel #18
0
        public void CompareLazyCompressedStringValue()
        {
            using (var context = JsonOperationContext.ShortTermSingleUse())
                using (var ms = new MemoryStream())
                    using (var writer = new BlittableJsonTextWriter(context, ms))
                    {
                        writer.WriteStartObject();
                        writer.WritePropertyName("Test");
                        writer.WriteString(new string('c', 1024 * 1024));
                        writer.WriteEndObject();
                        writer.Flush();
                        ms.Flush();

                        ms.Position = 0;
                        var json = context.Read(ms, "test");

                        ms.Position = 0;
                        var json2 = context.Read(ms, "test");

                        Assert.IsType <LazyCompressedStringValue>(json["Test"]);
                        Assert.IsType <LazyCompressedStringValue>(json2["Test"]);
                        Assert.Equal(json["Test"], json2["Test"]);
                    }
        }
Beispiel #19
0
        public async Task Put()
        {
            using (ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
            {
                var id          = GetQueryStringValueAndAssertIfSingleAndNotEmpty("id");
                var name        = GetQueryStringValueAndAssertIfSingleAndNotEmpty("name");
                var contentType = GetStringQueryString("contentType", false) ?? "";

                AttachmentDetails result;
                using (var streamsTempFile = Database.DocumentsStorage.AttachmentsStorage.GetTempFile("put"))
                    using (var stream = streamsTempFile.StartNewStream())
                    {
                        Stream requestBodyStream = RequestBodyStream();
                        string hash;
                        try
                        {
                            hash = await AttachmentsStorageHelper.CopyStreamToFileAndCalculateHash(context, requestBodyStream, stream, Database.DatabaseShutdown);
                        }
                        catch (Exception)
                        {
                            try
                            {
                                // if we failed to read the entire request body stream, we might leave
                                // data in the pipe still, this will cause us to read and discard the
                                // rest of the attachment stream and return the actual error to the caller
                                requestBodyStream.CopyTo(Stream.Null);
                            }
                            catch (Exception)
                            {
                                // we tried, but we can't clean the request, so let's just kill
                                // the connection
                                HttpContext.Abort();
                            }
                            throw;
                        }

                        var changeVector = context.GetLazyString(GetStringFromHeaders("If-Match"));

                        var cmd = new MergedPutAttachmentCommand
                        {
                            Database             = Database,
                            ExpectedChangeVector = changeVector,
                            DocumentId           = id,
                            Name        = name,
                            Stream      = stream,
                            Hash        = hash,
                            ContentType = contentType
                        };
                        stream.Flush();
                        await Database.TxMerger.Enqueue(cmd);

                        cmd.ExceptionDispatchInfo?.Throw();
                        result = cmd.Result;
                    }

                HttpContext.Response.StatusCode = (int)HttpStatusCode.Created;

                using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                {
                    writer.WriteStartObject();

                    writer.WritePropertyName(nameof(AttachmentDetails.ChangeVector));
                    writer.WriteString(result.ChangeVector);
                    writer.WriteComma();

                    writer.WritePropertyName(nameof(AttachmentDetails.Name));
                    writer.WriteString(result.Name);
                    writer.WriteComma();

                    writer.WritePropertyName(nameof(AttachmentDetails.DocumentId));
                    writer.WriteString(result.DocumentId);
                    writer.WriteComma();

                    writer.WritePropertyName(nameof(AttachmentDetails.ContentType));
                    writer.WriteString(result.ContentType);
                    writer.WriteComma();

                    writer.WritePropertyName(nameof(AttachmentDetails.Hash));
                    writer.WriteString(result.Hash);
                    writer.WriteComma();

                    writer.WritePropertyName(nameof(AttachmentDetails.Size));
                    writer.WriteInteger(result.Size);

                    writer.WriteEndObject();
                }
            }
        }
Beispiel #20
0
        public Task GetCertificates()
        {
            var thumbprint    = GetStringQueryString("thumbprint", required: false);
            var showSecondary = GetBoolValueQueryString("secondary", required: false) ?? false;

            var start    = GetStart();
            var pageSize = GetPageSize();

            using (ServerStore.ContextPool.AllocateOperationContext(out TransactionOperationContext context))
            {
                var certificates = new List <(string ItemName, BlittableJsonReaderObject Value)>();
                try
                {
                    if (string.IsNullOrEmpty(thumbprint))
                    {
                        if (ServerStore.CurrentRachisState == RachisState.Passive)
                        {
                            List <string> localCertKeys;
                            using (context.OpenReadTransaction())
                                localCertKeys = ServerStore.Cluster.GetCertificateKeysFromLocalState(context).ToList();

                            var serverCertKey = Constants.Certificates.Prefix + Server.Certificate.Certificate?.Thumbprint;
                            if (Server.Certificate.Certificate != null && localCertKeys.Contains(serverCertKey) == false)
                            {
                                // Since we didn't go through EnsureNotPassive(), the server certificate is not registered yet so we'll add it to the local state.
                                var serverCertDef = new CertificateDefinition
                                {
                                    Name              = "Server Certificate",
                                    Certificate       = Convert.ToBase64String(Server.Certificate.Certificate.Export(X509ContentType.Cert)),
                                    Permissions       = new Dictionary <string, DatabaseAccess>(),
                                    SecurityClearance = SecurityClearance.ClusterNode,
                                    Thumbprint        = Server.Certificate.Certificate.Thumbprint,
                                    NotAfter          = Server.Certificate.Certificate.NotAfter
                                };

                                var serverCert = context.ReadObject(serverCertDef.ToJson(), "Server/Certificate/Definition");
                                using (var tx = context.OpenWriteTransaction())
                                {
                                    ServerStore.Cluster.PutLocalState(context, Constants.Certificates.Prefix + Server.Certificate.Certificate.Thumbprint, serverCert);
                                    tx.Commit();
                                }
                                certificates.Add((serverCertKey, serverCert));
                            }

                            foreach (var localCertKey in localCertKeys)
                            {
                                BlittableJsonReaderObject localCertificate;
                                using (context.OpenReadTransaction())
                                    localCertificate = ServerStore.Cluster.GetLocalState(context, localCertKey);

                                if (localCertificate == null)
                                {
                                    continue;
                                }

                                var def = JsonDeserializationServer.CertificateDefinition(localCertificate);

                                if (showSecondary || string.IsNullOrEmpty(def.CollectionPrimaryKey))
                                {
                                    certificates.Add((localCertKey, localCertificate));
                                }
                                else
                                {
                                    localCertificate.Dispose();
                                }
                            }
                        }
                        else
                        {
                            using (context.OpenReadTransaction())
                            {
                                foreach (var item in ServerStore.Cluster.ItemsStartingWith(context, Constants.Certificates.Prefix, start, pageSize))
                                {
                                    var def = JsonDeserializationServer.CertificateDefinition(item.Value);

                                    if (showSecondary || string.IsNullOrEmpty(def.CollectionPrimaryKey))
                                    {
                                        certificates.Add(item);
                                    }
                                    else
                                    {
                                        item.Value.Dispose();
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        using (context.OpenReadTransaction())
                        {
                            var key = Constants.Certificates.Prefix + thumbprint;

                            var certificate = ServerStore.CurrentRachisState == RachisState.Passive
                                ? ServerStore.Cluster.GetLocalState(context, key)
                                : ServerStore.Cluster.Read(context, key);

                            if (certificate == null)
                            {
                                HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
                                return(Task.CompletedTask);
                            }

                            var definition = JsonDeserializationServer.CertificateDefinition(certificate);
                            if (string.IsNullOrEmpty(definition.CollectionPrimaryKey) == false)
                            {
                                certificate = ServerStore.Cluster.Read(context, definition.CollectionPrimaryKey);
                                if (certificate == null)
                                {
                                    HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
                                    return(Task.CompletedTask);
                                }
                            }

                            certificates.Add((key, certificate));
                        }
                    }

                    using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                    {
                        writer.WriteStartObject();
                        writer.WriteArray(context, "Results", certificates.ToArray(), (w, c, cert) =>
                        {
                            c.Write(w, cert.Value);
                        });
                        writer.WriteComma();
                        writer.WritePropertyName("LoadedServerCert");
                        writer.WriteString(Server.Certificate.Certificate?.Thumbprint);
                        writer.WriteEndObject();
                    }
                }
                finally
                {
                    foreach (var cert in certificates)
                    {
                        cert.Value?.Dispose();
                    }
                }
            }

            return(Task.CompletedTask);
        }
Beispiel #21
0
        public Task Performance()
        {
            var from  = 0;
            var froms = HttpContext.Request.Query["from"];

            if (froms.Count > 1)
            {
                throw new ArgumentException($"Query string value 'from' must appear exactly once");
            }
            if (froms.Count > 0 && int.TryParse(froms[0], out from) == false)
            {
                throw new ArgumentException($"Query string value 'from' must be a number");
            }

            var stats = GetIndexesToReportOn()
                        .Select(x => new IndexPerformanceStats
            {
                IndexName   = x.Name,
                IndexId     = x.IndexId,
                Performance = x.GetIndexingPerformance(from)
            })
                        .ToArray();

            JsonOperationContext context;

            using (Database.DocumentsStorage.ContextPool.AllocateOperationContext(out context))
                using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                {
                    writer.WriteStartArray();

                    var isFirst = true;
                    foreach (var stat in stats)
                    {
                        if (isFirst == false)
                        {
                            writer.WriteComma();
                        }

                        isFirst = false;

                        writer.WriteStartObject();

                        writer.WritePropertyName(nameof(stat.IndexName));
                        writer.WriteString((stat.IndexName));
                        writer.WriteComma();

                        writer.WritePropertyName(nameof(stat.IndexId));
                        writer.WriteInteger(stat.IndexId);
                        writer.WriteComma();

                        writer.WritePropertyName(nameof(stat.Performance));
                        writer.WriteStartArray();
                        var isFirstInternal = true;
                        foreach (var performance in stat.Performance)
                        {
                            if (isFirstInternal == false)
                            {
                                writer.WriteComma();
                            }

                            isFirstInternal = false;

                            writer.WriteIndexingPerformanceStats(context, performance);
                        }
                        writer.WriteEndArray();

                        writer.WriteEndObject();
                    }

                    writer.WriteEndArray();
                }

            return(Task.CompletedTask);
        }
Beispiel #22
0
        public Task GetErrors()
        {
            var names = HttpContext.Request.Query["name"];

            List <Index> indexes;

            if (names.Count == 0)
            {
                indexes = Database.IndexStore.GetIndexes().ToList();
            }
            else
            {
                indexes = new List <Index>();
                foreach (var name in names)
                {
                    var index = Database.IndexStore.GetIndex(name);
                    if (index == null)
                    {
                        throw new InvalidOperationException("There is not index with name: " + name);
                    }

                    indexes.Add(index);
                }
            }

            DocumentsOperationContext context;

            using (ContextPool.AllocateOperationContext(out context))
                using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                {
                    writer.WriteStartArray();

                    var first = true;
                    foreach (var index in indexes)
                    {
                        if (first == false)
                        {
                            writer.WriteComma();
                        }

                        first = false;

                        writer.WriteStartObject();

                        writer.WritePropertyName(("Name"));
                        writer.WriteString((index.Name));
                        writer.WriteComma();

                        writer.WritePropertyName(("Errors"));
                        writer.WriteStartArray();
                        var firstError = true;
                        foreach (var error in index.GetErrors())
                        {
                            if (firstError == false)
                            {
                                writer.WriteComma();
                            }

                            firstError = false;

                            writer.WriteStartObject();

                            writer.WritePropertyName((nameof(error.Timestamp)));
                            writer.WriteString((error.Timestamp.GetDefaultRavenFormat()));
                            writer.WriteComma();

                            writer.WritePropertyName((nameof(error.Document)));
                            if (string.IsNullOrWhiteSpace(error.Document) == false)
                            {
                                writer.WriteString((error.Document));
                            }
                            else
                            {
                                writer.WriteNull();
                            }
                            writer.WriteComma();

                            writer.WritePropertyName((nameof(error.Action)));
                            if (string.IsNullOrWhiteSpace(error.Action) == false)
                            {
                                writer.WriteString((error.Action));
                            }
                            else
                            {
                                writer.WriteNull();
                            }
                            writer.WriteComma();

                            writer.WritePropertyName((nameof(error.Error)));
                            if (string.IsNullOrWhiteSpace(error.Error) == false)
                            {
                                writer.WriteString((error.Error));
                            }
                            else
                            {
                                writer.WriteNull();
                            }

                            writer.WriteEndObject();
                        }

                        writer.WriteEndArray();

                        writer.WriteEndObject();
                    }

                    writer.WriteEndArray();
                }

            return(Task.CompletedTask);
        }
Beispiel #23
0
        public Task GetAll()
        {
            var name = GetStringQueryString("name", required: false);

            var start     = GetStart();
            var pageSize  = GetPageSize();
            var namesOnly = GetBoolValueQueryString("namesOnly", required: false) ?? false;

            DocumentsOperationContext context;

            using (ContextPool.AllocateOperationContext(out context))
                using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                {
                    IndexDefinition[] indexDefinitions;
                    if (string.IsNullOrEmpty(name))
                    {
                        indexDefinitions = Database.IndexStore
                                           .GetIndexes()
                                           .OrderBy(x => x.Name)
                                           .Skip(start)
                                           .Take(pageSize)
                                           .Select(x => x.GetIndexDefinition())
                                           .ToArray();
                    }
                    else
                    {
                        var index = Database.IndexStore.GetIndex(name);
                        if (index == null)
                        {
                            HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
                            return(Task.CompletedTask);
                        }

                        indexDefinitions = new[] { index.GetIndexDefinition() };
                    }

                    writer.WriteStartArray();

                    var isFirst = true;
                    foreach (var indexDefinition in indexDefinitions)
                    {
                        if (isFirst == false)
                        {
                            writer.WriteComma();
                        }

                        isFirst = false;

                        if (namesOnly)
                        {
                            writer.WriteString((indexDefinition.Name));
                            continue;
                        }

                        writer.WriteIndexDefinition(context, indexDefinition);
                    }

                    writer.WriteEndArray();
                }

            return(Task.CompletedTask);
        }
Beispiel #24
0
        public Task Debug()
        {
            var name = GetQueryStringValueAndAssertIfSingleAndNotEmpty("name");

            var index = Database.IndexStore.GetIndex(name);

            if (index == null)
            {
                HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
                return(Task.CompletedTask);
            }

            var operation = GetStringQueryString("op");

            JsonOperationContext context;

            using (ContextPool.AllocateOperationContext(out context))
                using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                {
                    if (string.Equals(operation, "map-reduce-tree", StringComparison.OrdinalIgnoreCase))
                    {
                        if (index.Type.IsMapReduce() == false)
                        {
                            HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;

                            context.Write(writer, new DynamicJsonValue
                            {
                                ["Error"] = $"{index.Name} is not map-reduce index",
                            });

                            return(Task.CompletedTask);
                        }

                        var docId = GetStringQueryString("docId", required: false);

                        IEnumerable <ReduceTree> trees;
                        using (index.GetReduceTree(docId, out trees))
                        {
                            writer.WriteReduceTrees(trees);
                        }

                        return(Task.CompletedTask);
                    }

                    if (string.Equals(operation, "source-doc-ids", StringComparison.OrdinalIgnoreCase))
                    {
                        IEnumerable <string> ids;
                        using (index.GetIdentifiersOfMappedDocuments(GetStringQueryString("startsWith", required: false), GetStart(), GetPageSize(), out ids))
                        {
                            writer.WriteArrayOfResultsAndCount(ids);
                        }

                        return(Task.CompletedTask);
                    }

                    if (string.Equals(operation, "entries-fields", StringComparison.OrdinalIgnoreCase))
                    {
                        var fields = index.GetEntriesFields();

                        var first = true;
                        writer.WriteStartArray();

                        foreach (var field in fields)
                        {
                            if (first == false)
                            {
                                writer.WriteComma();
                            }

                            first = false;

                            writer.WriteString(field);
                        }

                        writer.WriteEndArray();

                        return(Task.CompletedTask);
                    }

                    throw new NotSupportedException($"{operation} is not supported");
                }
        }
        private static void WriteIndexFieldOptions(this BlittableJsonTextWriter writer, JsonOperationContext context, IndexFieldOptions options, bool removeAnalyzers)
        {
            writer.WriteStartObject();

            writer.WritePropertyName(nameof(options.Analyzer));
            if (string.IsNullOrWhiteSpace(options.Analyzer) == false && !removeAnalyzers)
            {
                writer.WriteString(options.Analyzer);
            }
            else
            {
                writer.WriteNull();
            }
            writer.WriteComma();

            writer.WritePropertyName(nameof(options.Indexing));
            if (options.Indexing.HasValue)
            {
                writer.WriteString(options.Indexing.ToString());
            }
            else
            {
                writer.WriteNull();
            }
            writer.WriteComma();

            writer.WritePropertyName(nameof(options.Storage));
            if (options.Storage.HasValue)
            {
                writer.WriteString(options.Storage.ToString());
            }
            else
            {
                writer.WriteNull();
            }
            writer.WriteComma();

            writer.WritePropertyName(nameof(options.Suggestions));
            if (options.Suggestions.HasValue)
            {
                writer.WriteBool(options.Suggestions.Value);
            }
            else
            {
                writer.WriteNull();
            }
            writer.WriteComma();

            writer.WritePropertyName(nameof(options.TermVector));
            if (options.TermVector.HasValue)
            {
                writer.WriteString(options.TermVector.ToString());
            }
            else
            {
                writer.WriteNull();
            }
            writer.WriteComma();

            writer.WritePropertyName(nameof(options.Spatial));
            if (options.Spatial != null)
            {
                writer.WriteStartObject();

                writer.WritePropertyName(nameof(options.Spatial.Type));
                writer.WriteString(options.Spatial.Type.ToString());
                writer.WriteComma();

                writer.WritePropertyName(nameof(options.Spatial.MaxTreeLevel));
                writer.WriteInteger(options.Spatial.MaxTreeLevel);
                writer.WriteComma();

                writer.WritePropertyName(nameof(options.Spatial.MaxX));
                LazyStringValue lazyStringValue;
                using (lazyStringValue = context.GetLazyString(CharExtensions.ToInvariantString(options.Spatial.MaxX)))
                    writer.WriteDouble(new LazyNumberValue(lazyStringValue));
                writer.WriteComma();

                writer.WritePropertyName(nameof(options.Spatial.MaxY));
                using (lazyStringValue = context.GetLazyString(CharExtensions.ToInvariantString(options.Spatial.MaxY)))
                    writer.WriteDouble(new LazyNumberValue(lazyStringValue));
                writer.WriteComma();

                writer.WritePropertyName(nameof(options.Spatial.MinX));
                using (lazyStringValue = context.GetLazyString(CharExtensions.ToInvariantString(options.Spatial.MinX)))
                    writer.WriteDouble(new LazyNumberValue(lazyStringValue));
                writer.WriteComma();

                writer.WritePropertyName(nameof(options.Spatial.MinY));
                using (lazyStringValue = context.GetLazyString(CharExtensions.ToInvariantString(options.Spatial.MinY)))
                    writer.WriteDouble(new LazyNumberValue(lazyStringValue));
                writer.WriteComma();

                writer.WritePropertyName(nameof(options.Spatial.Strategy));
                writer.WriteString(options.Spatial.Strategy.ToString());
                writer.WriteComma();

                writer.WritePropertyName(nameof(options.Spatial.Units));
                writer.WriteString(options.Spatial.Units.ToString());

                writer.WriteEndObject();
            }
            else
            {
                writer.WriteNull();
            }

            writer.WriteEndObject();
        }
Beispiel #26
0
        public async Task Patch()
        {
            var id = GetQueryStringValueAndAssertIfSingleAndNotEmpty("id");

            var isTest    = GetBoolValueQueryString("test", required: false) ?? false;
            var debugMode = GetBoolValueQueryString("debug", required: false) ?? isTest;
            var skipPatchIfChangeVectorMismatch = GetBoolValueQueryString("skipPatchIfChangeVectorMismatch", required: false) ?? false;

            using (ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
            {
                var request = context.Read(RequestBodyStream(), "ScriptedPatchRequest");
                if (request.TryGet("Patch", out BlittableJsonReaderObject patchCmd) == false || patchCmd == null)
                {
                    throw new ArgumentException("The 'Patch' field in the body request is mandatory");
                }

                var patch = PatchRequest.Parse(patchCmd, out var patchArgs);

                PatchRequest patchIfMissing = null;
                BlittableJsonReaderObject patchIfMissingArgs = null;
                if (request.TryGet("PatchIfMissing", out BlittableJsonReaderObject patchIfMissingCmd) && patchIfMissingCmd != null)
                {
                    patchIfMissing = PatchRequest.Parse(patchIfMissingCmd, out patchIfMissingArgs);
                }

                var changeVector = context.GetLazyString(GetStringFromHeaders("If-Match"));

                var command = new PatchDocumentCommand(context,
                                                       id,
                                                       changeVector,
                                                       skipPatchIfChangeVectorMismatch,
                                                       (patch, patchArgs),
                                                       (patchIfMissing, patchIfMissingArgs),
                                                       Database,
                                                       isTest,
                                                       debugMode,
                                                       true,
                                                       returnDocument: false
                                                       );


                if (isTest == false)
                {
                    await Database.TxMerger.Enqueue(command);
                }
                else
                {
                    // PutDocument requires the write access to the docs storage
                    // testing patching is rare enough not to optimize it
                    using (context.OpenWriteTransaction())
                    {
                        command.Execute(context, null);
                    }
                }

                switch (command.PatchResult.Status)
                {
                case PatchStatus.DocumentDoesNotExist:
                    HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
                    return;

                case PatchStatus.Created:
                    HttpContext.Response.StatusCode = (int)HttpStatusCode.Created;
                    break;

                case PatchStatus.Skipped:
                    HttpContext.Response.StatusCode = (int)HttpStatusCode.NotModified;
                    return;

                case PatchStatus.Patched:
                case PatchStatus.NotModified:
                    HttpContext.Response.StatusCode = (int)HttpStatusCode.OK;
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                {
                    writer.WriteStartObject();

                    writer.WritePropertyName(nameof(command.PatchResult.Status));
                    writer.WriteString(command.PatchResult.Status.ToString());
                    writer.WriteComma();

                    writer.WritePropertyName(nameof(command.PatchResult.ModifiedDocument));
                    writer.WriteObject(command.PatchResult.ModifiedDocument);

                    if (debugMode)
                    {
                        writer.WriteComma();
                        writer.WritePropertyName(nameof(command.PatchResult.OriginalDocument));
                        if (isTest)
                        {
                            writer.WriteObject(command.PatchResult.OriginalDocument);
                        }
                        else
                        {
                            writer.WriteNull();
                        }

                        writer.WriteComma();

                        writer.WritePropertyName(nameof(command.PatchResult.Debug));

                        context.Write(writer, new DynamicJsonValue
                        {
                            ["Info"]    = new DynamicJsonArray(command.DebugOutput),
                            ["Actions"] = command.DebugActions
                        });
                    }

                    switch (command.PatchResult.Status)
                    {
                    case PatchStatus.Created:
                    case PatchStatus.Patched:

                        writer.WriteComma();

                        writer.WritePropertyName(nameof(command.PatchResult.LastModified));
                        writer.WriteString(command.PatchResult.LastModified.GetDefaultRavenFormat(isUtc: command.PatchResult.LastModified.Kind == DateTimeKind.Utc));
                        writer.WriteComma();

                        writer.WritePropertyName(nameof(command.PatchResult.ChangeVector));
                        writer.WriteString(command.PatchResult.ChangeVector);
                        writer.WriteComma();

                        writer.WritePropertyName(nameof(command.PatchResult.Collection));
                        writer.WriteString(command.PatchResult.Collection);
                        break;
                    }

                    writer.WriteEndObject();
                }
            }
        }
        public static void WriteDatabaseStatistics(this BlittableJsonTextWriter writer, JsonOperationContext context, DatabaseStatistics statistics)
        {
            writer.WriteStartObject();

            writer.WritePropertyName(nameof(statistics.CountOfIndexes));
            writer.WriteInteger(statistics.CountOfIndexes);
            writer.WriteComma();

            writer.WritePropertyName(nameof(statistics.CountOfDocuments));
            writer.WriteInteger(statistics.CountOfDocuments);
            writer.WriteComma();

            if (statistics.CountOfRevisionDocuments > 0)
            {
                writer.WritePropertyName(nameof(statistics.CountOfRevisionDocuments));
                writer.WriteInteger(statistics.CountOfRevisionDocuments);
                writer.WriteComma();
            }

            writer.WritePropertyName(nameof(statistics.CountOfAttachments));
            writer.WriteInteger(statistics.CountOfAttachments);
            writer.WriteComma();

            writer.WritePropertyName(nameof(statistics.CountOfUniqueAttachments));
            writer.WriteInteger(statistics.CountOfUniqueAttachments);
            writer.WriteComma();

            writer.WritePropertyName(nameof(statistics.DatabaseChangeVector));
            writer.WriteString(statistics.DatabaseChangeVector);
            writer.WriteComma();

            writer.WritePropertyName(nameof(statistics.DatabaseId));
            writer.WriteString(statistics.DatabaseId);
            writer.WriteComma();

            writer.WritePropertyName(nameof(statistics.Is64Bit));
            writer.WriteBool(statistics.Is64Bit);
            writer.WriteComma();

            writer.WritePropertyName(nameof(statistics.Pager));
            writer.WriteString(statistics.Pager);
            writer.WriteComma();

            writer.WritePropertyName(nameof(statistics.LastDocEtag));
            if (statistics.LastDocEtag.HasValue)
            {
                writer.WriteInteger(statistics.LastDocEtag.Value);
            }
            else
            {
                writer.WriteNull();
            }
            writer.WriteComma();

            writer.WritePropertyName((nameof(statistics.DatabaseChangeVector)));
            writer.WriteString(statistics.DatabaseChangeVector);
            writer.WriteComma();

            writer.WritePropertyName(nameof(statistics.LastIndexingTime));
            if (statistics.LastIndexingTime.HasValue)
            {
                writer.WriteDateTime(statistics.LastIndexingTime.Value, isUtc: true);
            }
            else
            {
                writer.WriteNull();
            }
            writer.WriteComma();

            writer.WritePropertyName(nameof(statistics.Indexes));
            writer.WriteStartArray();
            var isFirstInternal = true;

            foreach (var index in statistics.Indexes)
            {
                if (isFirstInternal == false)
                {
                    writer.WriteComma();
                }

                isFirstInternal = false;

                writer.WriteStartObject();

                writer.WritePropertyName(nameof(index.IsStale));
                writer.WriteBool(index.IsStale);
                writer.WriteComma();

                writer.WritePropertyName(nameof(index.Name));
                writer.WriteString(index.Name);
                writer.WriteComma();

                writer.WritePropertyName(nameof(index.Etag));
                writer.WriteInteger(index.Etag);
                writer.WriteComma();

                writer.WritePropertyName(nameof(index.LockMode));
                writer.WriteString(index.LockMode.ToString());
                writer.WriteComma();

                writer.WritePropertyName(nameof(index.Priority));
                writer.WriteString(index.Priority.ToString());
                writer.WriteComma();

                writer.WritePropertyName(nameof(index.State));
                writer.WriteString(index.State.ToString());
                writer.WriteComma();

                writer.WritePropertyName(nameof(index.Type));
                writer.WriteString(index.Type.ToString());
                writer.WriteComma();

                writer.WritePropertyName(nameof(index.LastIndexingTime));
                if (index.LastIndexingTime.HasValue)
                {
                    writer.WriteDateTime(index.LastIndexingTime.Value, isUtc: true);
                }
                else
                {
                    writer.WriteNull();
                }

                writer.WriteEndObject();
            }
            writer.WriteEndArray();

            writer.WriteEndObject();
        }
        public static void WriteIndexProgress(this BlittableJsonTextWriter writer, JsonOperationContext context, IndexProgress progress)
        {
            writer.WriteStartObject();

            writer.WritePropertyName(nameof(progress.IsStale));
            writer.WriteBool(progress.IsStale);
            writer.WriteComma();

            writer.WritePropertyName(nameof(progress.Collections));
            if (progress.Collections != null)
            {
                writer.WriteStartObject();
                var isFirst = true;
                foreach (var kvp in progress.Collections)
                {
                    if (isFirst == false)
                    {
                        writer.WriteComma();
                    }

                    isFirst = false;

                    writer.WritePropertyName(kvp.Key);

                    writer.WriteStartObject();

                    writer.WritePropertyName(nameof(kvp.Value.LastProcessedDocumentEtag));
                    writer.WriteInteger(kvp.Value.LastProcessedDocumentEtag);
                    writer.WriteComma();

                    writer.WritePropertyName(nameof(kvp.Value.LastProcessedTombstoneEtag));
                    writer.WriteInteger(kvp.Value.LastProcessedTombstoneEtag);
                    writer.WriteComma();

                    writer.WritePropertyName(nameof(kvp.Value.NumberOfDocumentsToProcess));
                    writer.WriteInteger(kvp.Value.NumberOfDocumentsToProcess);
                    writer.WriteComma();

                    writer.WritePropertyName(nameof(kvp.Value.NumberOfTombstonesToProcess));
                    writer.WriteInteger(kvp.Value.NumberOfTombstonesToProcess);
                    writer.WriteComma();

                    writer.WritePropertyName(nameof(kvp.Value.TotalNumberOfDocuments));
                    writer.WriteInteger(kvp.Value.TotalNumberOfDocuments);
                    writer.WriteComma();

                    writer.WritePropertyName(nameof(kvp.Value.TotalNumberOfTombstones));
                    writer.WriteInteger(kvp.Value.TotalNumberOfTombstones);

                    writer.WriteEndObject();
                }
                writer.WriteEndObject();
            }
            else
            {
                writer.WriteNull();
            }
            writer.WriteComma();

            writer.WritePropertyName(nameof(progress.Name));
            writer.WriteString(progress.Name);
            writer.WriteComma();

            writer.WritePropertyName(nameof(progress.Type));
            writer.WriteString(progress.Type.ToString());
            writer.WriteComma();

            writer.WritePropertyName(nameof(progress.Etag));
            writer.WriteInteger(progress.Etag);

            writer.WriteEndObject();
        }
Beispiel #29
0
        public static void WriteIndexQuery(this BlittableJsonTextWriter writer, DocumentConventions conventions, JsonOperationContext context, IndexQuery query)
        {
            writer.WriteStartObject();

            writer.WritePropertyName(nameof(query.Query));
            writer.WriteString(query.Query);
            writer.WriteComma();

            if (query.PageSizeSet && query.PageSize >= 0)
            {
                writer.WritePropertyName(nameof(query.PageSize));
                writer.WriteInteger(query.PageSize);
                writer.WriteComma();
            }

            if (query.WaitForNonStaleResults)
            {
                writer.WritePropertyName(nameof(query.WaitForNonStaleResults));
                writer.WriteBool(query.WaitForNonStaleResults);
                writer.WriteComma();
            }

            if (query.Start > 0)
            {
                writer.WritePropertyName(nameof(query.Start));
                writer.WriteInteger(query.Start);
                writer.WriteComma();
            }

            if (query.WaitForNonStaleResultsTimeout.HasValue)
            {
                writer.WritePropertyName(nameof(query.WaitForNonStaleResultsTimeout));
                writer.WriteString(query.WaitForNonStaleResultsTimeout.Value.ToInvariantString());
                writer.WriteComma();
            }

            if (query.DisableCaching)
            {
                writer.WritePropertyName(nameof(query.DisableCaching));
                writer.WriteBool(query.DisableCaching);
                writer.WriteComma();
            }

#if FEATURE_EXPLAIN_SCORES
            if (query.ExplainScores)
            {
                writer.WritePropertyName(nameof(query.ExplainScores));
                writer.WriteBool(query.ExplainScores);
                writer.WriteComma();
            }
#endif

#if FEATURE_SHOW_TIMINGS
            if (query.ShowTimings)
            {
                writer.WritePropertyName(nameof(query.ShowTimings));
                writer.WriteBool(query.ShowTimings);
                writer.WriteComma();
            }
#endif

            if (query.SkipDuplicateChecking)
            {
                writer.WritePropertyName(nameof(query.SkipDuplicateChecking));
                writer.WriteBool(query.SkipDuplicateChecking);
                writer.WriteComma();
            }

            writer.WritePropertyName(nameof(query.QueryParameters));
            if (query.QueryParameters != null)
            {
                writer.WriteObject(EntityToBlittable.ConvertCommandToBlittable(query.QueryParameters, context));
            }
            else
            {
                writer.WriteNull();
            }

            writer.WriteEndObject();
        }
        public static void WriteIndexDefinition(this BlittableJsonTextWriter writer, JsonOperationContext context, IndexDefinition indexDefinition, bool removeAnalyzers = false)
        {
            writer.WriteStartObject();

            writer.WritePropertyName(nameof(indexDefinition.Name));
            writer.WriteString(indexDefinition.Name);
            writer.WriteComma();

            writer.WritePropertyName(nameof(indexDefinition.Etag));
            writer.WriteInteger(indexDefinition.Etag);
            writer.WriteComma();

            writer.WritePropertyName(nameof(indexDefinition.Type));
            writer.WriteString(indexDefinition.Type.ToString());
            writer.WriteComma();

            writer.WritePropertyName(nameof(indexDefinition.LockMode));
            if (indexDefinition.LockMode.HasValue)
            {
                writer.WriteString(indexDefinition.LockMode.ToString());
            }
            else
            {
                writer.WriteNull();
            }
            writer.WriteComma();

            writer.WritePropertyName(nameof(indexDefinition.Priority));
            if (indexDefinition.Priority.HasValue)
            {
                writer.WriteString(indexDefinition.Priority.ToString());
            }
            else
            {
                writer.WriteNull();
            }
            writer.WriteComma();

            writer.WritePropertyName(nameof(indexDefinition.OutputReduceToCollection));
            writer.WriteString(indexDefinition.OutputReduceToCollection);
            writer.WriteComma();

            writer.WritePropertyName(nameof(indexDefinition.Configuration));
            writer.WriteStartObject();
            var isFirstInternal = true;

            foreach (var kvp in indexDefinition.Configuration)
            {
                if (isFirstInternal == false)
                {
                    writer.WriteComma();
                }

                isFirstInternal = false;

                writer.WritePropertyName(kvp.Key);
                writer.WriteString(kvp.Value);
            }
            writer.WriteEndObject();
            writer.WriteComma();

            writer.WritePropertyName(nameof(indexDefinition.AdditionalSources));
            writer.WriteStartObject();
            isFirstInternal = true;
            foreach (var kvp in indexDefinition.AdditionalSources)
            {
                if (isFirstInternal == false)
                {
                    writer.WriteComma();
                }

                isFirstInternal = false;

                writer.WritePropertyName(kvp.Key);
                writer.WriteString(kvp.Value);
            }
            writer.WriteEndObject();
            writer.WriteComma();

            writer.WritePropertyName(nameof(indexDefinition.IsTestIndex));
            writer.WriteBool(indexDefinition.IsTestIndex);
            writer.WriteComma();

            writer.WritePropertyName(nameof(indexDefinition.Reduce));
            if (string.IsNullOrWhiteSpace(indexDefinition.Reduce) == false)
            {
                writer.WriteString(indexDefinition.Reduce);
            }
            else
            {
                writer.WriteNull();
            }
            writer.WriteComma();

            writer.WritePropertyName(nameof(indexDefinition.Maps));
            writer.WriteStartArray();
            isFirstInternal = true;
            foreach (var map in indexDefinition.Maps)
            {
                if (isFirstInternal == false)
                {
                    writer.WriteComma();
                }

                isFirstInternal = false;
                writer.WriteString(map);
            }
            writer.WriteEndArray();
            writer.WriteComma();

            writer.WritePropertyName(nameof(indexDefinition.Fields));
            writer.WriteStartObject();
            isFirstInternal = true;
            foreach (var kvp in indexDefinition.Fields)
            {
                if (isFirstInternal == false)
                {
                    writer.WriteComma();
                }

                isFirstInternal = false;
                writer.WritePropertyName(kvp.Key);
                if (kvp.Value != null)
                {
                    writer.WriteIndexFieldOptions(context, kvp.Value, removeAnalyzers);
                }
                else
                {
                    writer.WriteNull();
                }
            }
            writer.WriteEndObject();

            writer.WriteEndObject();
        }