private void IdleOperations(object state) { try { try { if (DatabaseNeedToRunIdleOperations(landlord.SystemDatabase)) { landlord.SystemDatabase.RunIdleOperations(); } } catch (Exception e) { Logger.ErrorException("Error during idle operation run for system database", e); } foreach (var documentDatabase in landlord.ResourcesStoresCache) { try { if (documentDatabase.Value.Status != TaskStatus.RanToCompletion) { continue; } var database = documentDatabase.Value.Result; if (DatabaseNeedToRunIdleOperations(database)) { database.RunIdleOperations(); } } catch (Exception e) { Logger.WarnException("Error during idle operation run for " + documentDatabase.Key, e); } } var databasesToCleanup = landlord.LastRecentlyUsed .Where(x => (SystemTime.UtcNow - x.Value) > maxTimeDatabaseCanBeIdle) .Select(x => x.Key) .ToArray(); foreach (var db in databasesToCleanup) { // intentionally inside the loop, so we get better concurrency overall // since shutting down a database can take a while landlord.Cleanup(db, skipIfActiveInDuration: maxTimeDatabaseCanBeIdle, shouldSkip: database => database.Configuration.RunInMemory); } } catch (Exception e) { Logger.WarnException("Error during idle operations for the server", e); } finally { try { serverTimer.Change(frequencyToCheckForIdleDatabases, TimeSpan.FromDays(7)); } catch (ObjectDisposedException) { } } }
private void CleanupDatabases(DatabasesLandlord databaseLandlord) { var systemDatabase = databaseLandlord.SystemDatabase; int nextStart = 0; var databaseDocuments = systemDatabase .Documents .GetDocumentsWithIdStartingWith(Constants.Database.Prefix, null, null, 0, int.MaxValue, CancellationToken.None, ref nextStart); var databaseIds = databaseDocuments .Select(x => ((RavenJObject)x)["@metadata"]) .Where(x => x != null) .Select(x => x.Value<string>("@id")) .Where(x => x != null && x != Constants.SystemDatabase) .ToList(); foreach (var databaseId in databaseIds) { try { var key = databaseId; if (key.StartsWith(Constants.Database.Prefix)) key = key.Substring(Constants.Database.Prefix.Length); var shouldCleanup = false; DateTime value; if (databaseLandlord.IsDatabaseLoaded(key) == false) shouldCleanup = true; else if (databaseLandlord.LastRecentlyUsed.TryGetValue(key, out value) == false || (SystemTime.UtcNow - value) > maxTimeResourceCanBeIdle) shouldCleanup = true; if (shouldCleanup == false) continue; var configuration = databaseLandlord.CreateTenantConfiguration(key, true); databaseLandlord.Cleanup(key, maxTimeResourceCanBeIdle, database => false); var docKey = Constants.Database.Prefix + key; systemDatabase.Documents.Delete(docKey, null, null); if (configuration == null) continue; IOExtensions.DeleteDirectory(configuration.DataDirectory); if (configuration.IndexStoragePath != null) IOExtensions.DeleteDirectory(configuration.IndexStoragePath); if (configuration.Storage.Esent.JournalsStoragePath != null) IOExtensions.DeleteDirectory(configuration.Storage.Esent.JournalsStoragePath); if (configuration.Storage.Voron.JournalsStoragePath != null) IOExtensions.DeleteDirectory(configuration.Storage.Voron.JournalsStoragePath); } catch (Exception e) { log.WarnException(string.Format("Failed to cleanup '{0}' database.", databaseId), e); } } }
private void CleanupDatabases(DatabasesLandlord databaseLandlord) { var systemDatabase = databaseLandlord.SystemDatabase; int nextStart = 0; var databaseDocuments = systemDatabase .Documents .GetDocumentsWithIdStartingWith(Constants.Database.Prefix, null, null, 0, int.MaxValue, CancellationToken.None, ref nextStart); var databaseIds = databaseDocuments .Select(x => ((RavenJObject)x)["@metadata"]) .Where(x => x != null) .Select(x => x.Value <string>("@id")) .Where(x => x != null && x != Constants.SystemDatabase) .ToList(); foreach (var databaseId in databaseIds) { try { var key = databaseId; if (key.StartsWith(Constants.Database.Prefix)) { key = key.Substring(Constants.Database.Prefix.Length); } var shouldCleanup = false; DateTime value; if (databaseLandlord.IsDatabaseLoaded(key) == false) { shouldCleanup = true; } else if (databaseLandlord.LastRecentlyUsed.TryGetValue(key, out value) == false || (SystemTime.UtcNow - value) > maxTimeResourceCanBeIdle) { shouldCleanup = true; } if (shouldCleanup == false) { continue; } var configuration = databaseLandlord.CreateTenantConfiguration(key, true); databaseLandlord.Cleanup(key, maxTimeResourceCanBeIdle, database => false); var docKey = Constants.Database.Prefix + key; systemDatabase.Documents.Delete(docKey, null, null); if (configuration == null) { continue; } IOExtensions.DeleteDirectory(configuration.DataDirectory); if (configuration.IndexStoragePath != null) { IOExtensions.DeleteDirectory(configuration.IndexStoragePath); } if (configuration.Storage.Esent.JournalsStoragePath != null) { IOExtensions.DeleteDirectory(configuration.Storage.Esent.JournalsStoragePath); } if (configuration.Storage.Voron.JournalsStoragePath != null) { IOExtensions.DeleteDirectory(configuration.Storage.Voron.JournalsStoragePath); } } catch (Exception e) { log.WarnException(string.Format("Failed to cleanup '{0}' database.", databaseId), e); } } }