예제 #1
0
        private static void SetNodeStatus(
            DatabaseTopology topology,
            string nodeTag,
            NodesTopology nodesTopology,
            Dictionary <string, NodeStatus> nodeStatuses)
        {
            var nodeStatus = new DatabaseGroupNodeStatus
            {
                LastStatus = DatabasePromotionStatus.Ok
            };

            if (topology.PromotablesStatus.TryGetValue(nodeTag, out var status))
            {
                nodeStatus.LastStatus = status;
            }
            if (topology.DemotionReasons.TryGetValue(nodeTag, out var reason))
            {
                nodeStatus.LastError = reason;
            }

            if (nodeStatus.LastStatus == DatabasePromotionStatus.Ok &&
                nodeStatuses.TryGetValue(nodeTag, out var serverNodeStatus) &&
                serverNodeStatus.Connected == false)
            {
                nodeStatus.LastError  = serverNodeStatus.ErrorDetails;
                nodeStatus.LastStatus = DatabasePromotionStatus.NotResponding;
            }

            nodesTopology.Status[nodeTag] = nodeStatus;
        }
예제 #2
0
        private void WriteFaultedDatabaseInfo(string databaseName,
                                              NodesTopology nodesTopology,
                                              Exception exception,
                                              JsonOperationContext context,
                                              AbstractBlittableJsonTextWriter writer)
        {
            var doc = new DynamicJsonValue
            {
                [nameof(DatabaseInfo.Name)]          = databaseName,
                [nameof(DatabaseInfo.NodesTopology)] = nodesTopology,
                [nameof(DatabaseInfo.LoadError)]     = exception.Message
            };

            context.Write(writer, doc);
        }
예제 #3
0
        private static void SetNodeStatus(DatabaseTopology topology, string nodeTag, NodesTopology nodesTopology)
        {
            var nodeStatus = new DbGroupNodeStatus
            {
                LastStatus = DatabasePromotionStatus.Ok
            };

            if (topology.PromotablesStatus.TryGetValue(nodeTag, out var status))
            {
                nodeStatus.LastStatus = status;
            }
            if (topology.DemotionReasons.TryGetValue(nodeTag, out var reason))
            {
                nodeStatus.LastError = reason;
            }
            nodesTopology.Status[nodeTag] = nodeStatus;
        }
예제 #4
0
        private void WriteDatabaseInfo(string databaseName, BlittableJsonReaderObject dbRecordBlittable,
                                       TransactionOperationContext context, AbstractBlittableJsonTextWriter writer)
        {
            try
            {
                var online = ServerStore.DatabasesLandlord.DatabasesCache.TryGetValue(databaseName, out Task <DocumentDatabase> dbTask) &&
                             dbTask != null &&
                             dbTask.IsCompleted;

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

                var dbRecord = JsonDeserializationCluster.DatabaseRecord(dbRecordBlittable);
                var db       = online ? dbTask.Result : null;

                var indexingStatus = db?.IndexStore?.Status ?? IndexRunningStatus.Running;
                // 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 topology        = dbRecord.Topology;
                var clusterTopology = ServerStore.GetClusterTopology(context);
                clusterTopology.ReplaceCurrentNodeUrlWithClientRequestedNodeUrlIfNecessary(ServerStore, HttpContext);

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

                var nodesTopology = new NodesTopology();

                var statuses = ServerStore.GetNodesStatuses();
                if (topology != null)
                {
                    foreach (var member in topology.Members)
                    {
                        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)
                    {
                        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)
                    {
                        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);
                    }
                }

                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.ToString(),
                            [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),

                    Alerts         = db?.NotificationCenter.GetAlertCount() ?? 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 != null,
                    IndexesCount   = db?.IndexStore?.GetIndexes()?.Count() ?? 0,
                    IndexingStatus = indexingStatus,
                    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, e, context, writer);
            }
        }
예제 #5
0
        private void WriteDatabaseInfo(string databaseName, BlittableJsonReaderObject dbRecordBlittable,
                                       TransactionOperationContext context, BlittableJsonTextWriter writer)
        {
            var online = ServerStore.DatabasesLandlord.DatabasesCache.TryGetValue(databaseName, out Task <DocumentDatabase> dbTask) &&
                         dbTask != null &&
                         dbTask.IsCompleted;

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

            var dbRecord = JsonDeserializationCluster.DatabaseRecord(dbRecordBlittable);
            var db       = online ? dbTask.Result : null;

            var indexingStatus = db?.IndexStore.Status ?? IndexRunningStatus.Running;

            // 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) && val == "true")
            {
                indexingStatus = IndexRunningStatus.Disabled;
            }
            var disabled        = dbRecord.Disabled;
            var topology        = dbRecord.Topology;
            var clusterTopology = ServerStore.GetClusterTopology(context);

            var nodesTopology = new NodesTopology();

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

                foreach (var promotable in topology.Promotables)
                {
                    var node   = GetNode(databaseName, clusterTopology, promotable, out var promotableTask);
                    var mentor = topology.WhoseTaskIsIt(promotableTask, ServerStore.IsPassive());
                    nodesTopology.Promotables.Add(GetNodeId(node, mentor));
                    SetNodeStatus(topology, promotable, nodesTopology);
                }

                foreach (var rehab in topology.Rehabs)
                {
                    var node   = GetNode(databaseName, clusterTopology, rehab, out var promotableTask);
                    var mentor = topology.WhoseTaskIsIt(promotableTask, ServerStore.IsPassive());
                    nodesTopology.Rehabs.Add(GetNodeId(node, mentor));
                    SetNodeStatus(topology, rehab, nodesTopology);
                }
            }

            if (online == false)
            {
                // If state of database is found in the cache we can continue
                if (ServerStore.DatabaseInfoCache.TryWriteOfflineDatabaseStatusToRequest(
                        context, writer, databaseName, disabled, indexingStatus, nodesTopology))
                {
                    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 = new Size(GetTotalSize(db));

            var databaseInfo = new DatabaseInfo
            {
                Name      = databaseName,
                Disabled  = disabled,
                TotalSize = size,

                IsAdmin     = true, //TODO: implement me!
                IsEncrypted = dbRecord.Encrypted,
                UpTime      = online ? (TimeSpan?)GetUptime(db) : null,
                BackupInfo  = GetBackupInfo(db),

                Alerts         = db?.NotificationCenter.GetAlertCount() ?? 0,
                RejectClients  = false, //TODO: implement me!
                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 != null,
                IndexesCount   = db?.IndexStore.GetIndexes().Count() ?? 0,
                IndexingStatus = indexingStatus,

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

            var doc = databaseInfo.ToJson();

            context.Write(writer, doc);
        }
예제 #6
0
        public unsafe bool TryWriteOfflineDatabaseStatusToRequest(TransactionOperationContext ctx, BlittableJsonTextWriter writer, string databaseName, bool disabled, IndexRunningStatus indexingStatus, NodesTopology topology)
        {
            using (_contextPool.AllocateOperationContext(out TransactionOperationContext context))
                using (var tx = context.OpenReadTransaction())
                {
                    var table = tx.InnerTransaction.OpenTable(_databaseInfoSchema, DatabaseInfoSchema.DatabaseInfoTree);

                    TableValueReader infoTvr;
                    using (Slice.From(tx.InnerTransaction.Allocator, databaseName.ToLowerInvariant(), out Slice databaseNameAsSlice))
                    {
                        if (table.ReadByKey(databaseNameAsSlice, out infoTvr) == false)
                        {
                            return(false);
                        }
                    }
                    //It seems like the database was shutdown rudely and never wrote it stats onto the disk
                    if (infoTvr.Pointer == null)
                    {
                        return(false);
                    }

                    using (var databaseInfoJson = Read(context, ref infoTvr))
                    {
                        databaseInfoJson.Modifications = new DynamicJsonValue(databaseInfoJson)
                        {
                            [nameof(DatabaseInfo.Disabled)]       = disabled,
                            [nameof(DatabaseInfo.IndexingStatus)] = indexingStatus.ToString(),
                            [nameof(DatabaseInfo.NodesTopology)]  = topology.ToJson()
                        };

                        ctx.Write(writer, databaseInfoJson);
                        return(true);
                    }
                }
        }