Ejemplo n.º 1
0
        private void WriteDatabaseInfo(string databaseName, BlittableJsonReaderObject dbRecordBlittable,
                                       TransactionOperationContext context, AbstractBlittableJsonTextWriter writer)
        {
            var nodesTopology = new NodesTopology();

            try
            {
                var online = ServerStore.DatabasesLandlord.DatabasesCache.TryGetValue(databaseName, out Task <DocumentDatabase> dbTask) &&
                             dbTask != null &&
                             dbTask.IsCompleted;

                var dbRecord = JsonDeserializationCluster.DatabaseRecord(dbRecordBlittable);
                var topology = dbRecord.Topology;

                var statuses = ServerStore.GetNodesStatuses();
                if (topology != null)
                {
                    nodesTopology.PriorityOrder = topology.PriorityOrder;

                    var clusterTopology = ServerStore.GetClusterTopology(context);
                    clusterTopology.ReplaceCurrentNodeUrlWithClientRequestedNodeUrlIfNecessary(ServerStore, HttpContext);

                    foreach (var member in topology.Members)
                    {
                        if (dbRecord.DeletionInProgress != null && dbRecord.DeletionInProgress.ContainsKey(member))
                        {
                            continue;
                        }

                        var url  = clusterTopology.GetUrlFromTag(member);
                        var node = new InternalReplication
                        {
                            Database = databaseName,
                            NodeTag  = member,
                            Url      = url
                        };
                        nodesTopology.Members.Add(GetNodeId(node));
                        SetNodeStatus(topology, member, nodesTopology, statuses);
                    }

                    foreach (var promotable in topology.Promotables)
                    {
                        if (dbRecord.DeletionInProgress != null && dbRecord.DeletionInProgress.ContainsKey(promotable))
                        {
                            continue;
                        }

                        topology.PredefinedMentors.TryGetValue(promotable, out var mentorCandidate);
                        var node   = GetNode(databaseName, clusterTopology, promotable, mentorCandidate, out var promotableTask);
                        var mentor = topology.WhoseTaskIsIt(ServerStore.Engine.CurrentState, promotableTask, null);
                        nodesTopology.Promotables.Add(GetNodeId(node, mentor));
                        SetNodeStatus(topology, promotable, nodesTopology, statuses);
                    }

                    foreach (var rehab in topology.Rehabs)
                    {
                        if (dbRecord.DeletionInProgress != null && dbRecord.DeletionInProgress.ContainsKey(rehab))
                        {
                            continue;
                        }

                        var node   = GetNode(databaseName, clusterTopology, rehab, null, out var promotableTask);
                        var mentor = topology.WhoseTaskIsIt(ServerStore.Engine.CurrentState, promotableTask, null);
                        nodesTopology.Rehabs.Add(GetNodeId(node, mentor));
                        SetNodeStatus(topology, rehab, nodesTopology, statuses);
                    }
                }

                // Check for exceptions
                if (dbTask != null && dbTask.IsFaulted)
                {
                    var exception = dbTask.Exception.ExtractSingleInnerException();
                    WriteFaultedDatabaseInfo(databaseName, nodesTopology, exception, context, writer);
                    return;
                }

                var db = online ? dbTask.Result : null;

                var indexingStatus = db?.IndexStore?.Status;
                if (indexingStatus == null)
                {
                    // Looking for disabled indexing flag inside the database settings for offline database status
                    if (dbRecord.Settings.TryGetValue(RavenConfiguration.GetKey(x => x.Indexing.Disabled), out var val) &&
                        bool.TryParse(val, out var indexingDisabled) && indexingDisabled)
                    {
                        indexingStatus = IndexRunningStatus.Disabled;
                    }
                }

                var disabled = dbRecord.Disabled;

                var studioEnvironment = StudioConfiguration.StudioEnvironment.None;
                if (dbRecord.Studio != null && !dbRecord.Studio.Disabled)
                {
                    studioEnvironment = dbRecord.Studio.Environment;
                }

                if (online == false)
                {
                    // if state of database is found in the cache we can continue
                    if (ServerStore.DatabaseInfoCache.TryGet(databaseName, databaseInfoJson =>
                    {
                        databaseInfoJson.Modifications = new DynamicJsonValue(databaseInfoJson)
                        {
                            [nameof(DatabaseInfo.Disabled)] = disabled,
                            [nameof(DatabaseInfo.IndexingStatus)] = indexingStatus,
                            [nameof(DatabaseInfo.NodesTopology)] = nodesTopology.ToJson(),
                            [nameof(DatabaseInfo.DeletionInProgress)] = DynamicJsonValue.Convert(dbRecord.DeletionInProgress),
                            [nameof(DatabaseInfo.Environment)] = studioEnvironment
                        };

                        context.Write(writer, databaseInfoJson);
                    }))
                    {
                        return;
                    }

                    // we won't find it if it is a new database or after a dirty shutdown,
                    // so just report empty values then
                }

                var size = db?.GetSizeOnDisk() ?? (new Size(0), new Size(0));

                var databaseInfo = new DatabaseInfo
                {
                    Name            = databaseName,
                    Disabled        = disabled,
                    TotalSize       = size.Data,
                    TempBuffersSize = size.TempBuffers,

                    IsAdmin     = true,
                    IsEncrypted = dbRecord.Encrypted,
                    UpTime      = online ? (TimeSpan?)GetUptime(db) : null,
                    BackupInfo  = GetBackupInfo(db, context),

                    Alerts           = db?.NotificationCenter.GetAlertCount() ?? 0,
                    PerformanceHints = db?.NotificationCenter.GetPerformanceHintCount() ?? 0,
                    RejectClients    = false,
                    LoadError        = null,
                    IndexingErrors   = db?.IndexStore?.GetIndexes()?.Sum(index => index.GetErrorCount()) ?? 0,

                    DocumentsCount             = db?.DocumentsStorage.GetNumberOfDocuments() ?? 0,
                    HasRevisionsConfiguration  = db?.DocumentsStorage.RevisionsStorage.Configuration != null,
                    HasExpirationConfiguration = (db?.ExpiredDocumentsCleaner?.ExpirationConfiguration?.Disabled ?? true) == false,
                    HasRefreshConfiguration    = (db?.ExpiredDocumentsCleaner?.RefreshConfiguration?.Disabled ?? true) == false,
                    IndexesCount   = db?.IndexStore?.GetIndexes()?.Count() ?? 0,
                    IndexingStatus = indexingStatus ?? IndexRunningStatus.Running,
                    Environment    = studioEnvironment,

                    NodesTopology            = nodesTopology,
                    ReplicationFactor        = topology?.ReplicationFactor ?? -1,
                    DynamicNodesDistribution = topology?.DynamicNodesDistribution ?? false,
                    DeletionInProgress       = dbRecord.DeletionInProgress
                };

                var doc = databaseInfo.ToJson();
                context.Write(writer, doc);
            }
            catch (Exception e)
            {
                if (Logger.IsInfoEnabled)
                {
                    Logger.Info($"Failed to get database info for: {databaseName}", e);
                }

                WriteFaultedDatabaseInfo(databaseName, nodesTopology, e, context, writer);
            }
        }