コード例 #1
0
        private void Attach(bool force)
        {
            if (force == false && _attached)
            {
                return;
            }

            Task.Factory.StartNew(async() =>
            {
                await _locker.WaitAsync();

                try
                {
                    if (force == false && _attached)
                    {
                        return;
                    }

                    var database = await _databaseLandlord.TryGetOrCreateResourceStore(_databaseName);

                    database.Changes.OnIndexChange += AddIndexIfNecessary;

                    await AddIndexesFromDatabase(database);

                    _attached = true;
                }
                finally
                {
                    _locker.Release();
                }
            });
        }
コード例 #2
0
        protected override TData GetData()
        {
            if (Landlord.IsDatabaseLoaded(DatabaseName))
            {
                return(GetData(Landlord.TryGetOrCreateResourceStore(DatabaseName).Result));
            }

            return(default(TData));
        }
コード例 #3
0
        private void GenerateNewDatabaseId(string databaseName)
        {
            Task <DocumentDatabase> databaseTask;

            if (DatabasesLandlord.TryGetOrCreateResourceStore(databaseName, out databaseTask) == false)
            {
                return;
            }

            var database = databaseTask.Result;

            database.TransactionalStorage.ChangeId();
        }
コード例 #4
0
        private void AddReplicationBundleAndDisableReplicationDestinations(string databaseName)
        {
            Task <DocumentDatabase> databaseTask;

            if (DatabasesLandlord.TryGetOrCreateResourceStore(databaseName, out databaseTask) == false)
            {
                return;
            }

            var database = databaseTask.Result;
            var replicationDocumentAsJson = database.Documents.Get(Constants.RavenReplicationDestinations, null);

            if (replicationDocumentAsJson != null)
            {
                var replicationDocument = replicationDocumentAsJson.DataAsJson.JsonDeserialization <ReplicationDocument>();
                foreach (var destination in replicationDocument.Destinations)
                {
                    destination.Disabled = true;
                }

                database
                .Documents
                .Put(Constants.RavenReplicationDestinations, null, RavenJObject.FromObject(replicationDocument), new RavenJObject(), null);
            }

            var databaseDocumentAsJson = DatabasesLandlord.SystemDatabase.Documents.Get(Constants.Database.Prefix + databaseName, null);
            var databaseDocument       = databaseDocumentAsJson.DataAsJson.JsonDeserialization <DatabaseDocument>();

            var bundles = databaseDocument.Settings[Constants.ActiveBundles].GetSemicolonSeparatedValues();

            bundles.Add("Replication");

            databaseDocument.Settings[Constants.ActiveBundles] = string.Join(";", bundles);

            DatabasesLandlord
            .SystemDatabase
            .Documents
            .Put(
                Constants.Database.Prefix + databaseName,
                null,
                RavenJObject.FromObject(databaseDocument),
                new RavenJObject
            {
                { "Raven-Temp-Allow-Bundles-Change", true }
            },
                null);
        }
コード例 #5
0
        public override bool SetupRequestToProperDatabase(RequestManager rm)
        {
            var tenantId = DatabaseName;

            if (string.IsNullOrWhiteSpace(tenantId) || tenantId == "<system>")
            {
                landlord.LastRecentlyUsed.AddOrUpdate("System", SystemTime.UtcNow, (s, time) => SystemTime.UtcNow);
                var args = new BeforeRequestWebApiEventArgs
                {
                    Controller    = this,
                    IgnoreRequest = false,
                    TenantId      = "System",
                    Database      = landlord.SystemDatabase
                };
                rm.OnBeforeRequest(args);
                if (args.IgnoreRequest)
                {
                    return(false);
                }
                return(true);
            }

            Task <DocumentDatabase> resourceStoreTask;
            bool hasDb;

            try
            {
                hasDb = landlord.TryGetOrCreateResourceStore(tenantId, out resourceStoreTask);
            }
            catch (Exception e)
            {
                var msg = "Could not open database named: " + tenantId;
                Logger.WarnException(msg, e);
                throw new HttpException(503, msg, e);
            }
            if (hasDb)
            {
                try
                {
                    if (resourceStoreTask.Wait(TimeSpan.FromSeconds(30)) == false)
                    {
                        var msg = "The database " + tenantId +
                                  " is currently being loaded, but after 30 seconds, this request has been aborted. Please try again later, database loading continues.";
                        Logger.Warn(msg);
                        throw new HttpException(503, msg);
                    }
                    var args = new BeforeRequestWebApiEventArgs()
                    {
                        Controller    = this,
                        IgnoreRequest = false,
                        TenantId      = tenantId,
                        Database      = resourceStoreTask.Result
                    };
                    rm.OnBeforeRequest(args);
                    if (args.IgnoreRequest)
                    {
                        return(false);
                    }
                }
                catch (Exception e)
                {
                    string exceptionMessage   = e.Message;
                    var    aggregateException = e as AggregateException;
                    if (aggregateException != null)
                    {
                        exceptionMessage = aggregateException.ExtractSingleInnerException().Message;
                    }
                    var msg = "Could not open database named: " + tenantId + Environment.NewLine + exceptionMessage;

                    Logger.WarnException(msg, e);
                    throw new HttpException(503, msg, e);
                }

                landlord.LastRecentlyUsed.AddOrUpdate(tenantId, SystemTime.UtcNow, (s, time) => SystemTime.UtcNow);
            }
            else
            {
                var msg = "Could not find a database named: " + tenantId;
                Logger.Warn(msg);
                throw new HttpException(503, msg);
            }
            return(true);
        }
コード例 #6
0
        public async Task Run()
        {
            using var _ = _client;
            using var messageBuilder = new MessageBuilder();

            Stream stream = _client.GetStream();

            stream = await HandleInitialMessage(stream, messageBuilder);

            var reader = PipeReader.Create(stream);
            var writer = PipeWriter.Create(stream);

            if (_clientOptions == null) //TODO pfyasu maybe unused when cancel message will be implemented
            {
                return;
            }

            if (_clientOptions.TryGetValue("database", out string databaseName) == false)
            {
                await writer.WriteAsync(messageBuilder.ErrorResponse(
                                            PgSeverity.Fatal,
                                            PgErrorCodes.ConnectionFailure,
                                            "Failed to connect to database",
                                            "Missing database name in the connection string"), _token);

                return;
            }

            var database = await _databasesLandlord.TryGetOrCreateResourceStore(databaseName);

            if (database == null)
            {
                await writer.WriteAsync(messageBuilder.ErrorResponse(
                                            PgSeverity.Fatal,
                                            PgErrorCodes.ConnectionFailure,
                                            "Failed to connect to database",
                                            $"Database '{databaseName}' does not exist"), _token);

                return;
            }

            string username = null;

            try
            {
                username = _clientOptions["user"];

                using var transaction = new PgTransaction(database, new MessageReader(), username);

                if (_serverCertificate != null)
                {
                    // Authentication is required only when running in secured mode

                    await writer.WriteAsync(messageBuilder.AuthenticationCleartextPassword(), _token);

                    var authMessage = await transaction.MessageReader.GetUninitializedMessage(reader, _token);

                    await authMessage.Init(transaction.MessageReader, reader, _token);

                    await authMessage.Handle(transaction, messageBuilder, reader, writer, _token);
                }
                else
                {
                    await writer.WriteAsync(messageBuilder.AuthenticationOk(), _token);
                }

                await writer.WriteAsync(messageBuilder.ParameterStatusMessages(PgConfig.ParameterStatusList), _token);

                await writer.WriteAsync(messageBuilder.BackendKeyData(_processId, _identifier), _token);

                await writer.WriteAsync(messageBuilder.ReadyForQuery(transaction.State), _token);

                while (_token.IsCancellationRequested == false)
                {
                    var message = await transaction.MessageReader.GetUninitializedMessage(reader, _token);

                    try
                    {
                        await message.Init(transaction.MessageReader, reader, _token);

                        await message.Handle(transaction, messageBuilder, reader, writer, _token);
                    }
                    catch (PgErrorException e)
                    {
                        await message.HandleError(e, transaction, messageBuilder, writer, _token);
                    }
                }
            }
            catch (PgFatalException e)
            {
                if (Logger.IsInfoEnabled)
                {
                    Logger.Info($"{e.Message} (fatal pg error code {e.ErrorCode}). {GetSourceConnectionDetails(username)}", e);
                }

                await writer.WriteAsync(messageBuilder.ErrorResponse(
                                            PgSeverity.Fatal,
                                            e.ErrorCode,
                                            e.Message,
                                            e.ToString()), _token);
            }
            catch (PgErrorException e)
            {
                if (Logger.IsInfoEnabled)
                {
                    Logger.Info($"{e.Message} (pg error code {e.ErrorCode}). {GetSourceConnectionDetails(username)}", e);
                }

                // Shouldn't get to this point, PgErrorExceptions shouldn't be fatal
                await writer.WriteAsync(messageBuilder.ErrorResponse(
                                            PgSeverity.Error,
                                            e.ErrorCode,
                                            e.Message,
                                            e.ToString()), _token);
            }
            catch (PgTerminateReceivedException)
            {
                // Terminate silently
            }
            catch (QueryParser.ParseException e)
            {
                if (Logger.IsInfoEnabled)
                {
                    Logger.Info("Invalid RQL query", e);
                }

                try
                {
                    await writer.WriteAsync(messageBuilder.ErrorResponse(
                                                PgSeverity.Error,
                                                PgErrorCodes.InvalidSqlStatementName,
                                                e.ToString()), _token);
                }
                catch (Exception)
                {
                    // ignored
                }
            }
            catch (Exception e)
            {
                if (Logger.IsInfoEnabled)
                {
                    Logger.Info($"Unexpected internal pg error. {GetSourceConnectionDetails(username)}", e);
                }

                try
                {
                    await writer.WriteAsync(messageBuilder.ErrorResponse(
                                                PgSeverity.Fatal,
                                                PgErrorCodes.InternalError,
                                                e.ToString()), _token);
                }
                catch (Exception)
                {
                    // ignored
                }
            }
        }