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; }
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); }
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; }
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); } }
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); }
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); } } }