public Task GetClusterTopology() { using (ServerStore.ContextPool.AllocateOperationContext(out TransactionOperationContext context)) using (context.OpenReadTransaction()) { var topology = ServerStore.GetClusterTopology(context); var nodeTag = ServerStore.NodeTag; if (topology.Members.Count == 0) { var tag = ServerStore.NodeTag ?? "A"; var serverUrl = ServerStore.NodeHttpServerUrl; topology = new ClusterTopology( "dummy", new Dictionary <string, string> { [tag] = serverUrl }, new Dictionary <string, string>(), new Dictionary <string, string>(), tag ); nodeTag = tag; } HttpContext.Response.StatusCode = (int)HttpStatusCode.OK; using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream())) { var loadLicenseLimits = ServerStore.LoadLicenseLimits(); var nodeLicenseDetails = loadLicenseLimits == null ? null : DynamicJsonValue.Convert(loadLicenseLimits.NodeLicenseDetails); var json = new DynamicJsonValue { ["Topology"] = topology.ToSortedJson(), ["Leader"] = ServerStore.LeaderTag, ["CurrentState"] = ServerStore.CurrentRachisState, ["NodeTag"] = nodeTag, ["CurrentTerm"] = ServerStore.Engine.CurrentTerm, ["NodeLicenseDetails"] = nodeLicenseDetails, [nameof(ServerStore.Engine.LastStateChangeReason)] = ServerStore.LastStateChangeReason() }; var clusterErrors = ServerStore.GetClusterErrors(); if (clusterErrors.Count > 0) { json["Errors"] = clusterErrors; } var nodesStatues = ServerStore.GetNodesStatuses(); json["Status"] = DynamicJsonValue.Convert(nodesStatues); context.Write(writer, json); writer.Flush(); } } return(Task.CompletedTask); }
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); } }
public Task GetClusterTopology() { using (ServerStore.ContextPool.AllocateOperationContext(out TransactionOperationContext context)) using (context.OpenReadTransaction()) { var topology = ServerStore.GetClusterTopology(context); var nodeTag = ServerStore.NodeTag; if (topology.AllNodes.Count == 0) { var tag = ServerStore.NodeTag ?? "A"; var serverUrl = ServerStore.GetNodeHttpServerUrl(HttpContext.Request.GetClientRequestedNodeUrl()); topology = new ClusterTopology( topology.TopologyId ?? "dummy", new Dictionary <string, string> { [tag] = serverUrl }, new Dictionary <string, string>(), new Dictionary <string, string>(), tag, -1L ); nodeTag = tag; } else { var isClientIndependent = GetBoolValueQueryString("clientIndependent", false) ?? false; if (isClientIndependent == false && HttpContext.Items.TryGetValue(nameof(LocalEndpointClient.DebugPackage), out var _) == false) { topology.ReplaceCurrentNodeUrlWithClientRequestedNodeUrlIfNecessary(ServerStore, HttpContext); } } HttpContext.Response.StatusCode = (int)HttpStatusCode.OK; using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream())) { var loadLicenseLimits = ServerStore.LoadLicenseLimits(); var nodeLicenseDetails = loadLicenseLimits == null ? null : DynamicJsonValue.Convert(loadLicenseLimits.NodeLicenseDetails); var json = new DynamicJsonValue { [nameof(ClusterTopologyResponse.Topology)] = topology.ToSortedJson(), [nameof(ClusterTopologyResponse.Etag)] = topology.Etag, [nameof(ClusterTopologyResponse.Leader)] = ServerStore.LeaderTag, ["LeaderShipDuration"] = ServerStore.Engine.CurrentLeader?.LeaderShipDuration, ["CurrentState"] = ServerStore.CurrentRachisState, [nameof(ClusterTopologyResponse.NodeTag)] = nodeTag, ["CurrentTerm"] = ServerStore.Engine.CurrentTerm, ["NodeLicenseDetails"] = nodeLicenseDetails, [nameof(ServerStore.Engine.LastStateChangeReason)] = ServerStore.LastStateChangeReason() }; var clusterErrors = ServerStore.GetClusterErrors(); if (clusterErrors.Count > 0) { json["Errors"] = clusterErrors; } var nodesStatues = ServerStore.GetNodesStatuses(); json["Status"] = DynamicJsonValue.Convert(nodesStatues); context.Write(writer, json); writer.Flush(); } } return(Task.CompletedTask); }