Example #1
0
        private static async Task UnlikelyWaitForDatabaseToLoad(RequestHandlerContext context, Task <DocumentDatabase> database,
                                                                DatabasesLandlord databasesLandlord, StringSegment databaseName)
        {
            var time = databasesLandlord.DatabaseLoadTimeout;
            await Task.WhenAny(database, Task.Delay(time));

            if (database.IsCompleted == false)
            {
                if (databasesLandlord.InitLog.TryGetValue(databaseName.Value, out var initLogQueue))
                {
                    var sb = new StringBuilder();
                    foreach (var logline in initLogQueue)
                    {
                        sb.AppendLine(logline);
                    }

                    ThrowDatabaseLoadTimeoutWithLog(databaseName, databasesLandlord.DatabaseLoadTimeout, sb.ToString());
                }
                ThrowDatabaseLoadTimeout(databaseName, databasesLandlord.DatabaseLoadTimeout);
            }
            context.Database = await database;
            if (context.Database == null)
            {
                DatabaseDoesNotExistException.Throw(databaseName.Value);
            }
        }
Example #2
0
        public Task CreateDatabase(RequestHandlerContext context)
        {
            var databaseName = context.RouteMatch.GetCapture();

            if (context.RavenServer.ServerStore.IsPassive())
            {
                throw new NodeIsPassiveException($"Can't perform actions on the database '{databaseName}' while the node is passive.");
            }

            var databasesLandlord = context.RavenServer.ServerStore.DatabasesLandlord;
            var database          = databasesLandlord.TryGetOrCreateResourceStore(databaseName);

            if (database.IsCompletedSuccessfully)
            {
                context.Database = database.Result;

                if (context.Database == null)
                {
                    DatabaseDoesNotExistException.Throw(databaseName.Value);
                }

                return(context.Database?.DatabaseShutdown.IsCancellationRequested == false
                    ? Task.CompletedTask
                    : UnlikelyWaitForDatabaseToUnload(context, context.Database, databasesLandlord, databaseName));
            }

            return(UnlikelyWaitForDatabaseToLoad(context, database, databasesLandlord, databaseName));
        }
Example #3
0
        private async Task <bool> DispatchDatabaseTcpConnection(TcpConnectionOptions tcp, TcpConnectionHeaderMessage header)
        {
            var databaseLoadingTask = ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(header.DatabaseName);

            if (databaseLoadingTask == null)
            {
                DatabaseDoesNotExistException.Throw(header.DatabaseName);
                return(true);
            }

            var databaseLoadTimeout = ServerStore.DatabasesLandlord.DatabaseLoadTimeout;

            if (databaseLoadingTask.IsCompleted == false)
            {
                var resultingTask = await Task.WhenAny(databaseLoadingTask, Task.Delay(databaseLoadTimeout));

                if (resultingTask != databaseLoadingTask)
                {
                    ThrowTimeoutOnDatabaseLoad(header);
                }
            }

            tcp.DocumentDatabase = await databaseLoadingTask;
            if (tcp.DocumentDatabase == null)
            {
                DatabaseDoesNotExistException.Throw(header.DatabaseName);
            }

            Debug.Assert(tcp.DocumentDatabase != null);

            if (tcp.DocumentDatabase.DatabaseShutdown.IsCancellationRequested)
            {
                ThrowDatabaseShutdown(tcp.DocumentDatabase);
            }

            tcp.DocumentDatabase.RunningTcpConnections.Add(tcp);
            switch (header.Operation)
            {
            case TcpConnectionHeaderMessage.OperationTypes.Subscription:
                SubscriptionConnection.SendSubscriptionDocuments(tcp);
                break;

            case TcpConnectionHeaderMessage.OperationTypes.Replication:
                var documentReplicationLoader = tcp.DocumentDatabase.ReplicationLoader;
                documentReplicationLoader.AcceptIncomingConnection(tcp);
                break;

            default:
                throw new InvalidOperationException("Unknown operation for TCP " + header.Operation);
            }

            //since the responses to TCP connections mostly continue to run
            //beyond this point, no sense to dispose the connection now, so set it to null.
            //this way the responders are responsible to dispose the connection and the context
            // ReSharper disable once RedundantAssignment
            tcp = null;
            return(false);
        }
Example #4
0
        public Task CreateDatabase(RequestHandlerContext context)
        {
            var databaseName = context.RouteMatch.GetCapture();

            // todo: think if we need to pass this check to the landlord
            if (context.RavenServer.ServerStore.IsPassive())
            {
                throw new NodeIsPassiveException($"Can't perform actions on the database '{databaseName}' while the node is passive.");
            }

            if (context.RavenServer.ServerStore.IdleDatabases.TryGetValue(databaseName.Value, out var replicationsDictionary))
            {
                if (context.HttpContext.Request.Query.TryGetValue("from-outgoing", out var dbId) && context.HttpContext.Request.Query.TryGetValue("etag", out var replicationEtag))
                {
                    var hasChanges = false;
                    var etag       = Convert.ToInt64(replicationEtag);

                    if (replicationsDictionary.TryGetValue(dbId, out var storedEtag))
                    {
                        if (storedEtag < etag)
                        {
                            hasChanges = true;
                        }
                    }
                    else
                    {
                        if (etag > 0)
                        {
                            hasChanges = true;
                        }
                    }

                    if (hasChanges == false)
                    {
                        throw new DatabaseIdleException($"Replication attempt doesn't have changes to database {databaseName.Value}, which is currently idle.");
                    }
                }
            }

            var databasesLandlord = context.RavenServer.ServerStore.DatabasesLandlord;
            var database          = databasesLandlord.TryGetOrCreateResourceStore(databaseName);

            if (database.IsCompletedSuccessfully)
            {
                context.Database = database.Result;

                if (context.Database == null)
                {
                    DatabaseDoesNotExistException.Throw(databaseName.Value);
                }

                return(context.Database?.DatabaseShutdown.IsCancellationRequested == false
                    ? Task.CompletedTask
                    : UnlikelyWaitForDatabaseToUnload(context, context.Database, databasesLandlord, databaseName));
            }

            return(UnlikelyWaitForDatabaseToLoad(context, database, databasesLandlord, databaseName));
        }
Example #5
0
        public void Initialize(InitializeOptions options = InitializeOptions.None)
        {
            try
            {
                NotificationCenter.Initialize(this);

                DocumentsStorage.Initialize((options & InitializeOptions.GenerateNewDatabaseId) == InitializeOptions.GenerateNewDatabaseId);
                TxMerger.Start();
                ConfigurationStorage.Initialize();

                if ((options & InitializeOptions.SkipLoadingDatabaseRecord) == InitializeOptions.SkipLoadingDatabaseRecord)
                {
                    return;
                }

                long           index;
                DatabaseRecord record;
                using (_serverStore.ContextPool.AllocateOperationContext(out TransactionOperationContext context))
                    using (context.OpenReadTransaction())
                        record = _serverStore.Cluster.ReadDatabase(context, Name, out index);

                if (record == null)
                {
                    DatabaseDoesNotExistException.Throw(Name);
                }

                PeriodicBackupRunner = new PeriodicBackupRunner(this, _serverStore);

                _indexStoreTask = IndexStore.InitializeAsync(record);
                ReplicationLoader?.Initialize(record);
                EtlLoader.Initialize(record);

                DocumentTombstoneCleaner.Start();

                try
                {
                    _indexStoreTask.Wait(DatabaseShutdown);
                }
                finally
                {
                    _indexStoreTask = null;
                }

                SubscriptionStorage.Initialize();

                NotifyFeaturesAboutStateChange(record, index);
            }
            catch (Exception)
            {
                Dispose();
                throw;
            }
        }
Example #6
0
        private static async Task UnlikelyWaitForDatabaseToLoad(RequestHandlerContext context, Task <DocumentDatabase> database,
                                                                DatabasesLandlord databasesLandlord, StringSegment databaseName)
        {
            var time = databasesLandlord.DatabaseLoadTimeout;
            await Task.WhenAny(database, Task.Delay(time));

            if (database.IsCompleted == false)
            {
                ThrowDatabaseLoadTimeout(databaseName, databasesLandlord.DatabaseLoadTimeout);
            }
            context.Database = await database;
            if (context.Database == null)
            {
                DatabaseDoesNotExistException.Throw(databaseName);
            }
        }
Example #7
0
        public Task CreateDatabase(RequestHandlerContext context)
        {
            var databaseName      = context.RouteMatch.GetCapture();
            var databasesLandlord = context.RavenServer.ServerStore.DatabasesLandlord;
            var database          = databasesLandlord.TryGetOrCreateResourceStore(databaseName);

            if (database.IsCompletedSuccessfully)
            {
                context.Database = database.Result;

                if (context.Database == null)
                {
                    DatabaseDoesNotExistException.Throw(databaseName);
                }

                return(context.Database?.DatabaseShutdown.IsCancellationRequested == false
                    ? Task.CompletedTask
                    : UnlikelyWaitForDatabaseToUnload(context, context.Database, databasesLandlord, databaseName));
            }

            return(UnlikelyWaitForDatabaseToLoad(context, database, databasesLandlord, databaseName));
        }
Example #8
0
        public void Initialize(InitializeOptions options = InitializeOptions.None)
        {
            try
            {
                _addToInitLog("Initializing NotificationCenter");
                NotificationCenter.Initialize(this);

                _addToInitLog("Initializing DocumentStorage");
                DocumentsStorage.Initialize((options & InitializeOptions.GenerateNewDatabaseId) == InitializeOptions.GenerateNewDatabaseId);
                _addToInitLog("Starting Transaction Merger");
                TxMerger.Start();
                _addToInitLog("Initializing ConfigurationStorage");
                ConfigurationStorage.Initialize();

                if ((options & InitializeOptions.SkipLoadingDatabaseRecord) == InitializeOptions.SkipLoadingDatabaseRecord)
                {
                    return;
                }

                _addToInitLog("Loading Database");
                long           index;
                DatabaseRecord record;
                using (_serverStore.ContextPool.AllocateOperationContext(out TransactionOperationContext context))
                    using (context.OpenReadTransaction())
                        record = _serverStore.Cluster.ReadDatabase(context, Name, out index);

                if (record == null)
                {
                    DatabaseDoesNotExistException.Throw(Name);
                }

                PeriodicBackupRunner = new PeriodicBackupRunner(this, _serverStore);

                _addToInitLog("Initializing IndexStore (async)");
                _indexStoreTask = IndexStore.InitializeAsync(record);
                _addToInitLog("Initializing Replication");
                ReplicationLoader?.Initialize(record);
                _addToInitLog("Initializing ETL");
                EtlLoader.Initialize(record);

                DocumentTombstoneCleaner.Start();

                try
                {
                    _indexStoreTask.Wait(DatabaseShutdown);
                }
                finally
                {
                    _addToInitLog("Initializing IndexStore completed");
                    _indexStoreTask = null;
                }

                SubscriptionStorage.Initialize();
                _addToInitLog("Initializing SubscriptionStorage completed");

                TaskExecutor.Execute((state) =>
                {
                    try
                    {
                        NotifyFeaturesAboutStateChange(record, index);
                    }
                    catch
                    {
                        // We ignore the exception since it was caught in the function itself
                    }
                }, null);
            }
            catch (Exception)
            {
                Dispose();
                throw;
            }
        }
Example #9
0
        public Task CreateDatabase(RequestHandlerContext context)
        {
            var databaseName = context.RouteMatch.GetCapture();

            // todo: think if we need to pass this check to the landlord
            if (context.RavenServer.ServerStore.IsPassive())
            {
                throw new NodeIsPassiveException($"Can't perform actions on the database '{databaseName}' while the node is passive.");
            }

            if (context.RavenServer.ServerStore.IdleDatabases.TryGetValue(databaseName.Value, out var replicationsDictionary))
            {
                if (context.HttpContext.Request.Query.TryGetValue("from-outgoing", out var dbId) && context.HttpContext.Request.Query.TryGetValue("etag", out var replicationEtag))
                {
                    var hasChanges = false;
                    var etag       = Convert.ToInt64(replicationEtag);

                    if (replicationsDictionary.TryGetValue(dbId, out var storedEtag))
                    {
                        if (storedEtag < etag)
                        {
                            hasChanges = true;
                        }
                    }
                    else
                    {
                        if (etag > 0)
                        {
                            hasChanges = true;
                        }
                    }

                    if (hasChanges == false)
                    {
                        throw new DatabaseIdleException($"Replication attempt doesn't have changes to database {databaseName.Value}, which is currently idle.");
                    }
                }
            }

            var databasesLandlord = context.RavenServer.ServerStore.DatabasesLandlord;
            var database          = databasesLandlord.TryGetOrCreateResourceStore(databaseName);

            if (database.IsCompletedSuccessfully)
            {
                context.Database = database.Result;

                if (context.Database == null)
                {
                    DatabaseDoesNotExistException.Throw(databaseName.Value);
                }

                // ReSharper disable once PossibleNullReferenceException
                if (context.Database.DatabaseShutdownCompleted.IsSet)
                {
                    using (context.RavenServer.ServerStore.ContextPool.AllocateOperationContext(out TransactionOperationContext ctx))
                        using (ctx.OpenReadTransaction())
                        {
                            if (context.RavenServer.ServerStore.Cluster.DatabaseExists(ctx, databaseName.Value))
                            {
                                // db got disabled during loading
                                throw new DatabaseDisabledException($"Cannot complete the request, because {databaseName.Value} has been disabled.");
                            }
                        }

                    // db got deleted during loading
                    DatabaseDoesNotExistException.ThrowWithMessage(databaseName.Value, "Cannot complete the request.");
                }

                return(context.Database.DatabaseShutdown.IsCancellationRequested == false
                    ? Task.CompletedTask
                    : UnlikelyWaitForDatabaseToUnload(context, context.Database, databasesLandlord, databaseName));
            }

            return(UnlikelyWaitForDatabaseToLoad(context, database, databasesLandlord, databaseName));
        }