Example #1
0
        public async Task Put()
        {
            using (ServerStore.ContextPool.AllocateOperationContext(out TransactionOperationContext context))
            {
                var input = await context.ReadForMemoryAsync(RequestBodyStream(), "Analyzers");

                if (input.TryGet("Analyzers", out BlittableJsonReaderArray analyzers) == false)
                {
                    ThrowRequiredPropertyNameInRequest("Analyzers");
                }

                var commands = new List <PutServerWideAnalyzerCommand>();
                foreach (var analyzerToAdd in analyzers)
                {
                    var analyzerDefinition = JsonDeserializationServer.AnalyzerDefinition((BlittableJsonReaderObject)analyzerToAdd);
                    analyzerDefinition.Name = analyzerDefinition.Name?.Trim();

                    if (LoggingSource.AuditLog.IsInfoEnabled)
                    {
                        var clientCert = GetCurrentCertificate();

                        var auditLog = LoggingSource.AuditLog.GetLogger("Server", "Audit");
                        auditLog.Info($"Analyzer {analyzerDefinition.Name} PUT by {clientCert?.Subject} {clientCert?.Thumbprint} with definition: {analyzerToAdd}");
                    }

                    analyzerDefinition.Validate();

                    // check if analyzer is compilable
                    AnalyzerCompiler.Compile(analyzerDefinition.Name, analyzerDefinition.Code);

                    var command = new PutServerWideAnalyzerCommand(analyzerDefinition, GetRaftRequestIdFromQuery());

                    commands.Add(command);
                }

                var index = 0L;
                foreach (var command in commands)
                {
                    index = (await ServerStore.SendToLeaderAsync(command)).Index;
                }

                await ServerStore.WaitForCommitIndexChange(RachisConsensus.CommitIndexModification.GreaterOrEqual, index);

                NoContentStatus(HttpStatusCode.Created);
            }
        }
Example #2
0
        public void CanUseCustomAnalyzer_Restart_Faulty()
        {
            var serverPath   = NewDataPath();
            var databasePath = NewDataPath();

            IOExtensions.DeleteDirectory(serverPath);
            IOExtensions.DeleteDirectory(databasePath);

            var analyzerName = GetDatabaseName();

            using (var server = GetNewServer(new ServerCreationOptions
            {
                DataDirectory = serverPath,
                RunInMemory = false
            }))
                using (var store = GetDocumentStore(new Options
                {
                    ModifyDatabaseName = _ => analyzerName,
                    Path = databasePath,
                    RunInMemory = false,
                    Server = server,
                    DeleteDatabaseOnDispose = false
                }))
                {
                    var e = Assert.Throws <IndexCompilationException>(() => store.ExecuteIndex(new MyIndex(analyzerName)));
                    Assert.Contains($"Cannot find analyzer type '{analyzerName}' for field: Name", e.Message);

                    var analyzerCode = GetAnalyzer("RavenDB_14939.MyAnalyzer.cs", "MyAnalyzer", analyzerName);

                    store.Maintenance.Server.Send(new PutServerWideAnalyzersOperation(new AnalyzerDefinition
                    {
                        Name = analyzerName,
                        Code = analyzerCode
                    }));

                    store.ExecuteIndex(new MyIndex(analyzerName));

                    Fill(store);

                    Indexes.WaitForIndexing(store);

                    AssertCount <MyIndex>(store);

                    server.ServerStore.DatabasesLandlord.UnloadDirectly(store.Database);

                    // skipping compilation on purpose
                    using (server.ServerStore.Engine.ContextPool.AllocateOperationContext(out ClusterOperationContext context))
                        using (var tx = context.OpenWriteTransaction())
                        {
                            var command = new PutServerWideAnalyzerCommand(
                                new AnalyzerDefinition {
                                Name = analyzerName, Code = analyzerCode.Replace(analyzerName, "MyAnalyzer")
                            },
                                RaftIdGenerator.NewId());

                            using (var json = context.ReadObject(command.ValueToJson(), command.Name))
                            {
                                ClusterStateMachine.PutValueDirectly(context, command.Name, json, 1);
                            }

                            tx.Commit();
                        }
                }

            AnalyzerCompilationCache.Instance.RemoveServerWideItem(analyzerName);

            using (var server = GetNewServer(new ServerCreationOptions
            {
                DataDirectory = serverPath,
                RunInMemory = false,
                DeletePrevious = false
            }))
                using (var store = GetDocumentStore(new Options
                {
                    ModifyDatabaseName = _ => analyzerName,
                    Path = databasePath,
                    RunInMemory = false,
                    Server = server,
                    CreateDatabase = false
                }))
                {
                    store.Maintenance.Send(new ResetIndexOperation(new MyIndex(analyzerName).IndexName));

                    AssertErrors(store);

                    // can override with database analyzer
                    store.Maintenance.Send(new PutAnalyzersOperation(new AnalyzerDefinition
                    {
                        Name = analyzerName,
                        Code = GetAnalyzer("RavenDB_14939.MyAnalyzer.cs", "MyAnalyzer", analyzerName)
                    }));

                    store.Maintenance.Send(new ResetIndexOperation(new MyIndex(analyzerName).IndexName));

                    Indexes.WaitForIndexing(store);

                    AssertCount <MyIndex>(store);

                    // can go back to server analyzer
                    store.Maintenance.Send(new DeleteAnalyzerOperation(analyzerName));

                    store.Maintenance.Send(new ResetIndexOperation(new MyIndex(analyzerName).IndexName));

                    AssertErrors(store);

                    // can fix server analyzer
                    store.Maintenance.Server.Send(new PutServerWideAnalyzersOperation(new AnalyzerDefinition
                    {
                        Name = analyzerName,
                        Code = GetAnalyzer("RavenDB_14939.MyAnalyzer.cs", "MyAnalyzer", analyzerName)
                    }));

                    store.Maintenance.Send(new ResetIndexOperation(new MyIndex(analyzerName).IndexName));

                    Indexes.WaitForIndexing(store);

                    AssertCount <MyIndex>(store);
                }

            void AssertErrors(IDocumentStore store)
            {
                var errors = Indexes.WaitForIndexingErrors(store);

                Assert.Equal(1, errors.Length);
                Assert.Equal(1, errors[0].Errors.Length);
                Assert.Contains("is an implementation of a faulty analyzer", errors[0].Errors[0].Error);
                Assert.Contains("Could not find type", errors[0].Errors[0].Error);
            }
        }