Пример #1
0
 public void Cleanup()
 {
     Cleanups
     .AsEnumerable()
     .Reverse()
     .ToList()
     .ForEach(x => x());
 }
Пример #2
0
        public override bool TryGetOrCreateResourceStore(string resourceName, out Task <DocumentDatabase> resourceTask)
        {
            if (Locks.Contains(DisposingLock))
            {
                throw new ObjectDisposedException("DatabaseLandlord", "Server is shutting down, can't access any databases");
            }

            if (Locks.Contains(resourceName))
            {
                throw new InvalidOperationException("Database '" + resourceName + "' is currently locked and cannot be accessed.");
            }

            ManualResetEvent cleanupLock;

            if (Cleanups.TryGetValue(resourceName, out cleanupLock) && cleanupLock.WaitOne(MaxSecondsForTaskToWaitForDatabaseToLoad * 1000) == false)
            {
                throw new InvalidOperationException(string.Format("Database '{0}' is currently being restarted and cannot be accessed. We already waited {1} seconds.", resourceName, MaxSecondsForTaskToWaitForDatabaseToLoad));
            }

            if (ResourcesStoresCache.TryGetValue(resourceName, out resourceTask))
            {
                if (resourceTask.IsFaulted || resourceTask.IsCanceled)
                {
                    ResourcesStoresCache.TryRemove(resourceName, out resourceTask);
                    DateTime time;
                    LastRecentlyUsed.TryRemove(resourceName, out time);
                    // and now we will try creating it again
                }
                else
                {
                    return(true);
                }
            }

            var config = CreateTenantConfiguration(resourceName);

            if (config == null)
            {
                return(false);
            }


            if (!ResourceSemaphore.Wait(ConcurrentResourceLoadTimeout))
            {
                throw new ConcurrentLoadTimeoutException("Too much databases loading concurrently, timed out waiting for them to load.");
            }


            var didReleaseDuringWait = 0;
            var createdNewTask       = false;

            resourceTask = ResourcesStoresCache.GetOrAdd(resourceName, __ =>
            {
                createdNewTask = true;
                return(Task.Factory.StartNew(() =>
                {
                    var transportState = ResourseTransportStates.GetOrAdd(resourceName, s => new TransportState());

                    AssertLicenseParameters(config);
                    var documentDatabase = new DocumentDatabase(config, systemDatabase, 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(resourceName, SystemTime.UtcNow, (_, time) => SystemTime.UtcNow);
                    documentDatabase.RequestManager = SystemDatabase.RequestManager;
                    documentDatabase.ClusterManager = SystemDatabase.ClusterManager;
                    return documentDatabase;
                }).ContinueWith(task =>
                {
                    if (task.Status == TaskStatus.RanToCompletion)
                    {
                        OnDatabaseLoaded(resourceName);
                    }

                    if (task.Status == TaskStatus.Faulted) // this observes the task exception
                    {
                        Logger.WarnException("Failed to create database " + resourceName, task.Exception);
                    }

                    ResourceSemaphore.Release();

                    return task;
                }).Unwrap());
            });

            if (createdNewTask == false)
            {
                ResourceSemaphore.Release();
            }


            if (resourceTask.IsFaulted && resourceTask.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 (resourceTask.Exception.Data.Contains("Raven/KeepInResourceStore") == false)
                {
                    Task <DocumentDatabase> val;
                    ResourcesStoresCache.TryRemove(resourceName, out val);
                }
            }

            return(true);
        }
Пример #3
0
        public 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(MaxSecondsForTaskToWaitForDatabaseToLoad * 1000) == false)
            {
                throw new InvalidOperationException(string.Format("File system '{0}' is currently being restarted and cannot be accessed. We already waited {1} seconds.", tenantId, MaxSecondsForTaskToWaitForDatabaseToLoad));
            }

            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 filesystems 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();
                }
            }
        }
Пример #4
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) == 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);
            }

            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);
        }