public bool TryGetOrCreateResourceStore(string tenantId, out Task <DocumentDatabase> database) { if (Locks.Contains(DisposingLock)) { throw new ObjectDisposedException("DatabaseLandlord", "Server is shutting down, can't access any databases"); } if (Locks.Contains(tenantId)) { throw new InvalidOperationException("Database '" + tenantId + "' is currently locked and cannot be accessed."); } ManualResetEvent cleanupLock; if (Cleanups.TryGetValue(tenantId, out cleanupLock) && cleanupLock.WaitOne(MaxSecondsForTaskToWaitForDatabaseToLoad) == false) { throw new InvalidOperationException(string.Format("Database '{0}' is currently being restarted and cannot be accessed. We already waited {1} seconds.", tenantId, MaxSecondsForTaskToWaitForDatabaseToLoad)); } if (ResourcesStoresCache.TryGetValue(tenantId, out database)) { if (database.IsFaulted || database.IsCanceled) { ResourcesStoresCache.TryRemove(tenantId, out database); DateTime time; LastRecentlyUsed.TryRemove(tenantId, out time); // and now we will try creating it again } else { return(true); } } var config = CreateTenantConfiguration(tenantId); if (config == null) { return(false); } database = ResourcesStoresCache.GetOrAdd(tenantId, __ => Task.Factory.StartNew(() => { var transportState = ResourseTransportStates.GetOrAdd(tenantId, s => new TransportState()); AssertLicenseParameters(config); var documentDatabase = new DocumentDatabase(config, transportState); documentDatabase.SpinBackgroundWorkers(false); documentDatabase.Disposing += DocumentDatabaseDisposingStarted; documentDatabase.DisposingEnded += DocumentDatabaseDisposingEnded; documentDatabase.StorageInaccessible += UnloadDatabaseOnStorageInaccessible; // register only DB that has incremental backup set. documentDatabase.OnBackupComplete += OnDatabaseBackupCompleted; // if we have a very long init process, make sure that we reset the last idle time for this db. LastRecentlyUsed.AddOrUpdate(tenantId, SystemTime.UtcNow, (_, time) => SystemTime.UtcNow); return(documentDatabase); }).ContinueWith(task => { if (task.Status == TaskStatus.Faulted) // this observes the task exception { Logger.WarnException("Failed to create database " + tenantId, task.Exception); } return(task); }).Unwrap()); if (database.IsFaulted && database.Exception != null) { // if we are here, there is an error, and if there is an error, we need to clear it from the // resource store cache so we can try to reload it. // Note that we return the faulted task anyway, because we need the user to look at the error if (database.Exception.Data.Contains("Raven/KeepInResourceStore") == false) { Task <DocumentDatabase> val; ResourcesStoresCache.TryRemove(tenantId, out val); } } return(true); }
public bool TryGetOrCreateResourceStore(string tenantId, out Task <CounterStorage> counter) { if (Locks.Contains(DisposingLock)) { throw new ObjectDisposedException("CountersLandlord", "Server is shutting down, can't access any counters"); } if (Enabled == false) { throw new InvalidOperationException("Counters are an experimental feature that is not enabled"); } if (Locks.Contains(tenantId)) { throw new InvalidOperationException("Counters '" + tenantId + "' is currently locked and cannot be accessed"); } ManualResetEvent cleanupLock; if (Cleanups.TryGetValue(tenantId, out cleanupLock) && cleanupLock.WaitOne(MaxSecondsForTaskToWaitForDatabaseToLoad * 1000) == false) { throw new InvalidOperationException(string.Format("Counters '{0}' are currently being restarted and cannot be accessed. We already waited {1} seconds.", tenantId, MaxSecondsForTaskToWaitForDatabaseToLoad)); } if (ResourcesStoresCache.TryGetValue(tenantId, out counter)) { if (counter.IsFaulted || counter.IsCanceled) { ResourcesStoresCache.TryRemove(tenantId, out counter); DateTime time; LastRecentlyUsed.TryRemove(tenantId, out time); // and now we will try creating it again } else { return(true); } } var config = CreateTenantConfiguration(tenantId); if (config == null) { return(false); } var hasAcquired = false; try { if (!ResourceSemaphore.Wait(ConcurrentResourceLoadTimeout)) { throw new ConcurrentLoadTimeoutException("Too much counters loading concurrently, timed out waiting for them to load."); } hasAcquired = true; counter = ResourcesStoresCache.GetOrAdd(tenantId, __ => Task.Factory.StartNew(() => { var transportState = ResourseTransportStates.GetOrAdd(tenantId, s => new TransportState()); var cs = new CounterStorage(systemDatabase.ServerUrl, tenantId, config, transportState); AssertLicenseParameters(); // if we have a very long init process, make sure that we reset the last idle time for this db. LastRecentlyUsed.AddOrUpdate(tenantId, SystemTime.UtcNow, (_, time) => SystemTime.UtcNow); return(cs); }).ContinueWith(task => { if (task.Status == TaskStatus.Faulted) // this observes the task exception { Logger.WarnException("Failed to create counters " + tenantId, task.Exception); } return(task); }).Unwrap()); return(true); } finally { if (hasAcquired) { ResourceSemaphore.Release(); } } }
public override bool TryGetOrCreateResourceStore(string tenantId, out Task <RavenFileSystem> fileSystem) { if (Locks.Contains(DisposingLock)) { throw new ObjectDisposedException("FileSystem", "Server is shutting down, can't access any file systems"); } if (Locks.Contains(tenantId)) { throw new InvalidOperationException("FileSystem '" + tenantId + "' is currently locked and cannot be accessed"); } ManualResetEvent cleanupLock; if (Cleanups.TryGetValue(tenantId, out cleanupLock) && cleanupLock.WaitOne(MaxTimeForTaskToWaitForDatabaseToLoad) == false) { throw new InvalidOperationException($"File system '{tenantId}' is currently being restarted and cannot be accessed. We already waited {MaxTimeForTaskToWaitForDatabaseToLoad.TotalSeconds} seconds."); } if (ResourcesStoresCache.TryGetValue(tenantId, out fileSystem)) { if (fileSystem.IsFaulted || fileSystem.IsCanceled) { ResourcesStoresCache.TryRemove(tenantId, out fileSystem); DateTime time; LastRecentlyUsed.TryRemove(tenantId, out time); // and now we will try creating it again } else { return(true); } } var config = CreateTenantConfiguration(tenantId); if (config == null) { return(false); } var hasAcquired = false; try { if (!ResourceSemaphore.Wait(ConcurrentResourceLoadTimeout)) { throw new ConcurrentLoadTimeoutException("Too much counters loading concurrently, timed out waiting for them to load."); } hasAcquired = true; fileSystem = ResourcesStoresCache.GetOrAdd(tenantId, __ => Task.Factory.StartNew(() => { var transportState = ResourseTransportStates.GetOrAdd(tenantId, s => new TransportState()); AssertLicenseParameters(config); var fs = new RavenFileSystem(config, tenantId, transportState); fs.Initialize(); // if we have a very long init process, make sure that we reset the last idle time for this db. LastRecentlyUsed.AddOrUpdate(tenantId, SystemTime.UtcNow, (_, time) => SystemTime.UtcNow); return(fs); }).ContinueWith(task => { if (task.Status == TaskStatus.Faulted) // this observes the task exception { Logger.WarnException("Failed to create filesystem " + tenantId, task.Exception); } return(task); }).Unwrap()); return(true); } finally { if (hasAcquired) { ResourceSemaphore.Release(); } } }
public bool TryGetOrCreateResourceStore(string tenantId, out Task <DocumentDatabase> database) { if (Locks.Contains(DisposingLock)) { throw new ObjectDisposedException("DatabaseLandlord", "Server is shutting down, can't access any databases"); } if (ResourcesStoresCache.TryGetValue(tenantId, out database)) { if (database.IsFaulted || database.IsCanceled) { ResourcesStoresCache.TryRemove(tenantId, out database); DateTime time; LastRecentlyUsed.TryRemove(tenantId, out time); // and now we will try creating it again } else { return(true); } } if (Locks.Contains(tenantId)) { throw new InvalidOperationException("Database '" + tenantId + "' is currently locked and cannot be accessed."); } var config = CreateTenantConfiguration(tenantId); if (config == null) { return(false); } database = ResourcesStoresCache.GetOrAdd(tenantId, __ => Task.Factory.StartNew(() => { var transportState = ResourseTransportStates.GetOrAdd(tenantId, s => new TransportState()); AssertLicenseParameters(config); var documentDatabase = new DocumentDatabase(config, transportState); documentDatabase.SpinBackgroundWorkers(); documentDatabase.Disposing += DocumentDatabaseDisposingStarted; documentDatabase.DisposingEnded += DocumentDatabaseDisposingEnded; documentDatabase.StorageInaccessible += UnloadDatabaseOnStorageInaccessible; // register only DB that has incremental backup set. documentDatabase.OnBackupComplete += OnDatabaseBackupCompleted; // if we have a very long init process, make sure that we reset the last idle time for this db. LastRecentlyUsed.AddOrUpdate(tenantId, SystemTime.UtcNow, (_, time) => SystemTime.UtcNow); return(documentDatabase); }).ContinueWith(task => { if (task.Status == TaskStatus.Faulted) // this observes the task exception { Logger.WarnException("Failed to create database " + tenantId, task.Exception); } return(task); }).Unwrap()); return(true); }