public RavenDBOptions(InMemoryRavenConfiguration configuration, DocumentDatabase db = null) { if (configuration == null) throw new ArgumentNullException("configuration"); try { HttpEndpointRegistration.RegisterHttpEndpointTarget(); HttpEndpointRegistration.RegisterAdminLogsTarget(); if (db == null) { configuration.UpdateDataDirForLegacySystemDb(); systemDatabase = new DocumentDatabase(configuration); systemDatabase.SpinBackgroundWorkers(); } else { systemDatabase = db; } fileSystemLandlord = new FileSystemsLandlord(systemDatabase); databasesLandlord = new DatabasesLandlord(systemDatabase); countersLandlord = new CountersLandlord(systemDatabase); requestManager = new RequestManager(databasesLandlord); mixedModeRequestAuthorizer = new MixedModeRequestAuthorizer(); mixedModeRequestAuthorizer.Initialize(systemDatabase, new RavenServer(databasesLandlord.SystemDatabase, configuration)); } catch { if (systemDatabase != null) systemDatabase.Dispose(); throw; } }
public RavenDBOptions(InMemoryRavenConfiguration configuration, DocumentDatabase db = null) { if (configuration == null) throw new ArgumentNullException("configuration"); try { HttpEndpointRegistration.RegisterHttpEndpointTarget(); HttpEndpointRegistration.RegisterAdminLogsTarget(); ThreadPool.SetMinThreads(configuration.MinThreadPoolWorkerThreads, configuration.MinThreadPoolCompletionThreads); if (db == null) { configuration.UpdateDataDirForLegacySystemDb(); systemDatabase = new DocumentDatabase(configuration); systemDatabase.SpinBackgroundWorkers(false); } else { systemDatabase = db; } WebSocketBufferPool.Initialize(configuration.WebSockets.InitialBufferPoolSize); fileSystemLandlord = new FileSystemsLandlord(systemDatabase); databasesLandlord = new DatabasesLandlord(systemDatabase); countersLandlord = new CountersLandlord(systemDatabase); requestManager = new RequestManager(databasesLandlord); mixedModeRequestAuthorizer = new MixedModeRequestAuthorizer(); mixedModeRequestAuthorizer.Initialize(systemDatabase, new RavenServer(databasesLandlord.SystemDatabase, configuration)); serverStartupTasks = configuration.Container.GetExportedValues<IServerStartupTask>(); foreach (var task in serverStartupTasks) { toDispose.Add(task); task.Execute(this); } } catch { if (systemDatabase != null) systemDatabase.Dispose(); throw; } }
private static HttpConfiguration CreateHttpCfg( DatabasesLandlord databasesLandlord, FileSystemsLandlord fileSystemsLandlord, MixedModeRequestAuthorizer mixedModeRequestAuthorizer, RequestManager requestManager) { var cfg = new HttpConfiguration(); cfg.Properties[typeof(DatabasesLandlord)] = databasesLandlord; cfg.Properties[typeof(FileSystemsLandlord)] = fileSystemsLandlord; cfg.Properties[typeof(MixedModeRequestAuthorizer)] = mixedModeRequestAuthorizer; cfg.Properties[typeof(RequestManager)] = requestManager; cfg.Formatters.Remove(cfg.Formatters.XmlFormatter); cfg.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new NaveValueCollectionJsonConverterOnlyForConfigFormatters()); cfg.Services.Replace(typeof(IAssembliesResolver), new MyAssemblyResolver()); cfg.Filters.Add(new RavenExceptionFilterAttribute()); cfg.MapHttpAttributeRoutes(); cfg.Routes.MapHttpRoute( "RavenFs", "ravenfs/{controller}/{action}", new {id = RouteParameter.Optional}); cfg.Routes.MapHttpRoute( "API Default", "{controller}/{action}", new { id = RouteParameter.Optional }); cfg.Routes.MapHttpRoute( "Database Route", "databases/{databaseName}/{controller}/{action}", new { id = RouteParameter.Optional }); cfg.MessageHandlers.Add(new GZipToJsonAndCompressHandler()); cfg.Services.Replace(typeof(IHostBufferPolicySelector), new SelectiveBufferPolicySelector()); cfg.EnsureInitialized(); return cfg; }
public override bool SetupRequestToProperDatabase(RequestManager rm) { var tenantId = CountersName; if (string.IsNullOrWhiteSpace(tenantId)) { throw new HttpException(503, "Could not find a counter with no name"); } Task<CounterStorage> resourceStoreTask; bool hasDb; try { hasDb = landlord.TryGetOrCreateResourceStore(tenantId, out resourceStoreTask); } catch (Exception e) { var msg = "Could open counter 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 counter " + tenantId + " is currently being loaded, but after 30 seconds, this request has been aborted. Please try again later, file system loading continues."; Logger.Warn(msg); throw new HttpException(503, msg); } var args = new BeforeRequestWebApiEventArgs { Controller = this, IgnoreRequest = false, TenantId = tenantId, Counters = resourceStoreTask.Result }; rm.OnBeforeRequest(args); if (args.IgnoreRequest) return false; } catch (Exception e) { var msg = "Could open counters named: " + tenantId; 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 counter named: " + tenantId; Logger.Warn(msg); throw new HttpException(503, msg); } return true; }
protected override void InnerInitialization(HttpControllerContext controllerContext) { base.InnerInitialization(controllerContext); landlord = (CountersLandlord)controllerContext.Configuration.Properties[typeof(CountersLandlord)]; requestManager = (RequestManager)controllerContext.Configuration.Properties[typeof(RequestManager)]; var values = controllerContext.Request.GetRouteData().Values; if (values.ContainsKey("MS_SubRoutes")) { var routeDatas = (IHttpRouteData[])controllerContext.Request.GetRouteData().Values["MS_SubRoutes"]; var selectedData = routeDatas.FirstOrDefault(data => data.Values.ContainsKey("counterName")); if (selectedData != null) CountersName = selectedData.Values["counterName"] as string; } else { if (values.ContainsKey("cou")) CountersName = values["counterName"] as string; } if (CountersName == null) throw new InvalidOperationException("Could not find counter name for this request"); }
public static void CreateInfoPackageForDatabase(ZipArchive package, DocumentDatabase database, RequestManager requestManager, string zipEntryPrefix = null) { zipEntryPrefix = zipEntryPrefix ?? string.Empty; var databaseName = database.Name; if (string.IsNullOrWhiteSpace(databaseName)) databaseName = Constants.SystemDatabase; var jsonSerializer = JsonExtensions.CreateDefaultJsonSerializer(); jsonSerializer.Formatting=Formatting.Indented; if (database.StartupTasks.OfType<ReplicationTask>().Any()) { var replication = package.CreateEntry(zipEntryPrefix + "replication.json", compressionLevel); using (var statsStream = replication.Open()) using (var streamWriter = new StreamWriter(statsStream)) { jsonSerializer.Serialize(streamWriter, ReplicationUtils.GetReplicationInformation(database)); streamWriter.Flush(); } } var sqlReplicationTask = database.StartupTasks.OfType<SqlReplicationTask>().FirstOrDefault(); if (sqlReplicationTask != null) { var replication = package.CreateEntry(zipEntryPrefix + "sql_replication.json", compressionLevel); using (var statsStream = replication.Open()) using (var streamWriter = new StreamWriter(statsStream)) { jsonSerializer.Serialize(streamWriter, sqlReplicationTask.Statistics); streamWriter.Flush(); } } var stats = package.CreateEntry(zipEntryPrefix + "stats.json", compressionLevel); using (var statsStream = stats.Open()) using (var streamWriter = new StreamWriter(statsStream)) { jsonSerializer.Serialize(streamWriter, database.Statistics); streamWriter.Flush(); } var metrics = package.CreateEntry(zipEntryPrefix + "metrics.json", compressionLevel); using (var metricsStream = metrics.Open()) using (var streamWriter = new StreamWriter(metricsStream)) { jsonSerializer.Serialize(streamWriter, database.CreateMetrics()); streamWriter.Flush(); } var logs = package.CreateEntry(zipEntryPrefix + "logs.csv", compressionLevel); using (var logsStream = logs.Open()) using (var streamWriter = new StreamWriter(logsStream)) { var target = LogManager.GetTarget<DatabaseMemoryTarget>(); if (target == null) streamWriter.WriteLine("DatabaseMemoryTarget was not registered in the log manager, logs are not available"); else { var boundedMemoryTarget = target[databaseName]; var log = boundedMemoryTarget.GeneralLog; streamWriter.WriteLine("time,logger,level,message,exception"); foreach (var logEvent in log) { streamWriter.WriteLine("{0:O},{1},{2},{3},{4}", logEvent.TimeStamp, logEvent.LoggerName, logEvent.Level, logEvent.FormattedMessage, logEvent.Exception); } } streamWriter.Flush(); } var config = package.CreateEntry(zipEntryPrefix + "config.json", compressionLevel); using (var configStream = config.Open()) using (var streamWriter = new StreamWriter(configStream)) using (var jsonWriter = new JsonTextWriter(streamWriter) { Formatting = Formatting.Indented }) { GetConfigForDebug(database).WriteTo(jsonWriter, new EtagJsonConverter()); jsonWriter.Flush(); } var indexes = package.CreateEntry(zipEntryPrefix + "indexes.json", compressionLevel); using (var indexesStream = indexes.Open()) using (var streamWriter = new StreamWriter(indexesStream)) { jsonSerializer.Serialize(streamWriter, database.IndexDefinitionStorage.IndexDefinitions.ToDictionary(x => x.Key, x => x.Value)); streamWriter.Flush(); } var currentlyIndexing = package.CreateEntry(zipEntryPrefix + "currently-indexing.json", compressionLevel); using (var currentlyIndexingStream = currentlyIndexing.Open()) using (var streamWriter = new StreamWriter(currentlyIndexingStream)) { jsonSerializer.Serialize(streamWriter, GetCurrentlyIndexingForDebug(database)); streamWriter.Flush(); } var queries = package.CreateEntry(zipEntryPrefix + "queries.json", compressionLevel); using (var queriesStream = queries.Open()) using (var streamWriter = new StreamWriter(queriesStream)) { jsonSerializer.Serialize(streamWriter, database.WorkContext.CurrentlyRunningQueries); streamWriter.Flush(); } var version = package.CreateEntry(zipEntryPrefix + "version.json", compressionLevel); using (var versionStream = version.Open()) using (var streamWriter = new StreamWriter(versionStream)) { jsonSerializer.Serialize(streamWriter, new { DocumentDatabase.ProductVersion, DocumentDatabase.BuildVersion }); streamWriter.Flush(); } var prefetchStatus = package.CreateEntry(zipEntryPrefix + "prefetch-status.json", compressionLevel); using (var prefetchStatusStream = prefetchStatus.Open()) using (var streamWriter = new StreamWriter(prefetchStatusStream)) { jsonSerializer.Serialize(streamWriter, GetPrefetchingQueueStatusForDebug(database)); streamWriter.Flush(); } var requestTracking = package.CreateEntry(zipEntryPrefix + "request-tracking.json", compressionLevel); using (var requestTrackingStream = requestTracking.Open()) using (var streamWriter = new StreamWriter(requestTrackingStream)) { jsonSerializer.Serialize(streamWriter, GetRequestTrackingForDebug(requestManager, databaseName)); streamWriter.Flush(); } var tasks = package.CreateEntry(zipEntryPrefix + "tasks.json", compressionLevel); using (var tasksStream = tasks.Open()) using (var streamWriter = new StreamWriter(tasksStream)) { jsonSerializer.Serialize(streamWriter, GetTasksForDebug(database)); streamWriter.Flush(); } var systemUtilization = package.CreateEntry(zipEntryPrefix + "system-utilization.json", compressionLevel); using (var systemUtilizationStream = systemUtilization.Open()) using (var streamWriter = new StreamWriter(systemUtilizationStream)) { long totalPhysicalMemory = -1; long availableMemory = -1; object cpuTimes = null; try { totalPhysicalMemory = MemoryStatistics.TotalPhysicalMemory; availableMemory = MemoryStatistics.AvailableMemoryInMb; using (var searcher = new ManagementObjectSearcher("select * from Win32_PerfFormattedData_PerfOS_Processor")) { cpuTimes = searcher.Get() .Cast<ManagementObject>() .Select(mo => new { Name = mo["Name"], Usage = string.Format("{0} %", mo["PercentProcessorTime"]) }).ToArray(); } } catch (Exception e) { cpuTimes = "Could not get CPU times" + Environment.NewLine + e; } jsonSerializer.Serialize(streamWriter, new { TotalPhysicalMemory = string.Format("{0:#,#.##;;0} MB", totalPhysicalMemory), AvailableMemory = string.Format("{0:#,#.##;;0} MB", availableMemory), CurrentCpuUsage = cpuTimes }); streamWriter.Flush(); } }
internal static object GetRequestTrackingForDebug(RequestManager requestManager, string databaseName) { return requestManager.GetRecentRequests(databaseName).Select(x => { var dic = new Dictionary<String, String>(); foreach (var httpHeader in x.Headers.Value) { dic[httpHeader.Key] = httpHeader.Value.First(); } dic.Remove("Authorization"); dic.Remove("Proxy-Authorization"); dic.Remove("WWW-Authenticate"); dic.Remove("Proxy-Authenticate"); return new { Uri = x.RequestUri, Method = x.HttpMethod, StatusCode = x.ResponseStatusCode, RequestHeaders = dic.Select(z=>new{Name = z.Key, Values= new[]{z.Value}}), ExecutionTime = string.Format("{0} ms", x.Stopwatch.ElapsedMilliseconds), AdditionalInfo = x.CustomInfo ?? string.Empty }; }); }
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 TimeoutException(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; }
public override bool SetupRequestToProperDatabase(RequestManager rm) { var tenantId = this.DatabaseName; var landlord = this.DatabasesLandlord; 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 + " " + e.Message; Logger.WarnException(msg, e); throw new HttpException(503, msg, e); } if (hasDb) { try { int TimeToWaitForDatabaseToLoad = MaxSecondsForTaskToWaitForDatabaseToLoad; if (resourceStoreTask.IsCompleted == false && resourceStoreTask.IsFaulted == false) { if (MaxNumberOfThreadsForDatabaseToLoad.Wait(0) == false) { var msg = string.Format("The database {0} is currently being loaded, but there are too many requests waiting for database load. Please try again later, database loading continues.", tenantId); Logger.Warn(msg); throw new TimeoutException(msg); } try { if (resourceStoreTask.Wait(TimeSpan.FromSeconds(TimeToWaitForDatabaseToLoad)) == false) { var msg = string.Format("The database {0} is currently being loaded, but after {1} seconds, this request has been aborted. Please try again later, database loading continues.", tenantId, TimeToWaitForDatabaseToLoad); Logger.Warn(msg); throw new TimeoutException(msg); } } finally { MaxNumberOfThreadsForDatabaseToLoad.Release(); } } var args = new BeforeRequestWebApiEventArgs() { Controller = this, IgnoreRequest = false, TenantId = tenantId, Database = resourceStoreTask.Result }; rm.OnBeforeRequest(args); if (args.IgnoreRequest) return false; } catch (Exception e) { var msg = "Could not open database named: " + tenantId + Environment.NewLine + e; 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; }
internal static object GetRequestTrackingForDebug(RequestManager requestManager, string databaseName) { return requestManager.GetRecentRequests(databaseName).Select(x => new { Uri = x.RequestUri, Method = x.HttpMethod, StatusCode = x.ResponseStatusCode, RequestHeaders = x.Headers.AllKeys.Select(k => new { Name = k, Values = x.Headers.GetValues(k) }), ExecutionTime = string.Format("{0} ms", x.Stopwatch.ElapsedMilliseconds), AdditionalInfo = x.CustomInfo ?? string.Empty }); }