Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        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();
                }
            }
        }
Ejemplo n.º 3
0
        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();
                }
            }
        }
Ejemplo n.º 4
0
        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);
        }