Example #1
0
        private void DocumentDatabaseDisposingStarted(object documentDatabase, EventArgs args)
        {
            try
            {
                var database = documentDatabase as DocumentDatabase;
                if (database == null)
                {
                    return;
                }

                ResourcesStoresCache.Set(database.Name, (dbName) =>
                {
                    var tcs = new TaskCompletionSource <DocumentDatabase>();
                    tcs.SetException(new ObjectDisposedException(database.Name, "Database named " + database.Name + " is being disposed right now and cannot be accessed.\r\n" +
                                                                 "Access will be available when the dispose process will end")
                    {
                        Data =
                        {
                            { "Raven/KeepInResourceStore", "true" }
                        }
                    });
                    // we need to observe this task exception in case no one is actually looking at it during disposal
                    GC.KeepAlive(tcs.Task.Exception);
                    return(tcs.Task);
                });
            }
            catch (Exception ex)
            {
                Logger.WarnException("Failed to substitute database task with temporary place holder. This should not happen", ex);
            }
        }
Example #2
0
        public override Task <DocumentDatabase> TryGetOrCreateResourceStore(StringSegment databaseName)
        {
            if (HasLocks != 0)
            {
                AssertLocks(databaseName);
            }
            Task <DocumentDatabase> database;

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

            return(CreateDatabase(databaseName));
        }
Example #3
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;

                // 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);
        }
Example #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 (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);
                }
            }

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

            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);
        }
Example #5
0
 public void ForAllCountersInCacheOnly(Action <CounterStorage> action)
 {
     foreach (var value in ResourcesStoresCache
              .Select(cs => cs.Value)
              .Where(value => value.Status == TaskStatus.RanToCompletion))
     {
         action(value.Result);
     }
 }
Example #6
0
 public void ForAllFileSystems(Action <RavenFileSystem> action)
 {
     foreach (var value in ResourcesStoresCache
              .Select(db => db.Value)
              .Where(value => value.Status == TaskStatus.RanToCompletion))
     {
         action(value.Result);
     }
 }
Example #7
0
 public void ForAllTimeSeries(Action <TimeSeriesStorage> action)
 {
     foreach (var value in ResourcesStoresCache
              .Select(cs => cs.Value)
              .Where(value => value.Status == TaskStatus.RanToCompletion))
     {
         action(value.Result);
     }
 }
Example #8
0
 public void ForAllDatabases(Action <DocumentDatabase> action)
 {
     action(systemDatabase);
     foreach (var value in ResourcesStoresCache
              .Select(db => db.Value)
              .Where(value => value.Status == TaskStatus.RanToCompletion))
     {
         action(value.Result);
     }
 }
Example #9
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 (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);
                }
            }

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

            var config = CreateTenantConfiguration(tenantId);

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

            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);
        }
Example #10
0
        public bool IsFileSystemLoaded(string tenantName)
        {
            Task <RavenFileSystem> dbTask;

            if (ResourcesStoresCache.TryGetValue(tenantName, out dbTask) == false)
            {
                return(false);
            }

            return(dbTask != null && dbTask.Status == TaskStatus.RanToCompletion);
        }
Example #11
0
        protected override bool TryGetOrCreateResourceStore(string tenantId, out IResourceStore database)
        {
            if (ResourcesStoresCache.TryGetValue(tenantId, out database))
            {
                return(true);
            }

            JsonDocument jsonDocument;

            using (DefaultDatabase.DisableAllTriggersForCurrentThread())
                jsonDocument = DefaultDatabase.Get("Raven/Databases/" + tenantId, null);

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

            var document = jsonDocument.DataAsJson.JsonDeserialization <DatabaseDocument>();

            database = ResourcesStoresCache.GetOrAddAtomically(tenantId, s =>
            {
                var config = new InMemoryRavenConfiguration
                {
                    Settings = DefaultConfiguration.Settings,
                };
                foreach (var setting in document.Settings)
                {
                    config.Settings[setting.Key] = setting.Value;
                }
                var dataDir = config.Settings["Raven/DataDir"];
                if (dataDir == null)
                {
                    throw new InvalidOperationException("Could not find Raven/DataDir");
                }
                if (dataDir.StartsWith("~/") || dataDir.StartsWith(@"~\"))
                {
                    var baseDataPath = Path.GetDirectoryName(DefaultDatabase.Configuration.DataDirectory);
                    if (baseDataPath == null)
                    {
                        throw new InvalidOperationException("Could not find root data path");
                    }
                    config.Settings["Raven/DataDir"] = Path.Combine(baseDataPath, dataDir.Substring(2));
                }
                config.Settings["Raven/VirtualDir"] = config.Settings["Raven/VirtualDir"] + "/" + tenantId;

                config.DatabaseName = tenantId;

                config.Initialize();
                var documentDatabase = new DocumentDatabase(config);
                documentDatabase.SpinBackgroundWorkers();
                return(documentDatabase);
            });
            return(true);
        }
Example #12
0
        private Task <DocumentDatabase> CreateDatabase(StringSegment databaseName)
        {
            var config = CreateDatabaseConfiguration(databaseName);

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

            var hasAcquired = false;

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

                hasAcquired = true;

                var task     = new Task <DocumentDatabase>(() => CreateDocumentsStorage(databaseName, config));
                var database = ResourcesStoresCache.GetOrAdd(databaseName, task);
                if (database == task)
                {
                    task.Start();
                }

                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(databaseName, out val);
                    }
                }

                database.ContinueWith(_ => ServerStore.TrackChange("Loaded", Constants.Database.Prefix + databaseName));

                return(database);
            }
            finally
            {
                if (hasAcquired)
                {
                    ResourceSemaphore.Release();
                }
            }
        }
Example #13
0
        public bool IsDatabaseLoaded(string tenantName)
        {
            if (tenantName == Constants.SystemDatabase)
            {
                return(true);
            }

            Task <DocumentDatabase> dbTask;

            if (ResourcesStoresCache.TryGetValue(tenantName, out dbTask) == false)
            {
                return(false);
            }

            return(dbTask != null && dbTask.Status == TaskStatus.RanToCompletion);
        }
Example #14
0
        private void DocumentDatabaseDisposingEnded(object documentDatabase, EventArgs args)
        {
            try
            {
                var database = documentDatabase as DocumentDatabase;
                if (database == null)
                {
                    return;
                }

                ResourcesStoresCache.Remove(database.Name);
            }
            catch (Exception ex)
            {
                Logger.ErrorException("Failed to remove database at the end of the disposal. This should not happen", ex);
            }
        }
Example #15
0
        public Guid?GetDatabaseId(string tenantName)
        {
            if (tenantName == Constants.SystemDatabase)
            {
                return(null);
            }

            Task <DocumentDatabase> dbTask;

            if (ResourcesStoresCache.TryGetValue(tenantName, out dbTask) == false)
            {
                return(null);
            }

            if (dbTask == null || dbTask.Status != TaskStatus.RanToCompletion)
            {
                return(null);
            }

            return(dbTask.Result.Statistics.DatabaseId);
        }
Example #16
0
        public bool TryGetDatabase(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))
            {
                return(false);
            }

            if (!database.IsFaulted && !database.IsCanceled)
            {
                return(true);
            }

            ResourcesStoresCache.TryRemove(tenantId, out database);
            DateTime time;

            LastRecentlyUsed.TryRemove(tenantId, out time);
            return(false);
        }
Example #17
0
        private void DocumentDatabaseDisposingStarted(object documentDatabase, EventArgs args)
        {
            try
            {
                var database = documentDatabase as DocumentDatabase;
                if (database == null)
                {
                    return;
                }

                ResourcesStoresCache.Set(database.Name, (dbName) =>
                {
                    var tcs = new TaskCompletionSource <DocumentDatabase>();
                    tcs.SetException(new ObjectDisposedException(dbName, "Database named " + dbName + " is being disposed right now and cannot be accessed.\r\n" +
                                                                 "Access will be available when the dispose process will end"));
                    return(tcs.Task);
                });
            }
            catch (Exception ex)
            {
                Logger.WarnException("Failed to substitute database task with temporary place holder. This should not happen", ex);
            }
        }
Example #18
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);
        }
Example #19
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();
                }
            }
        }
Example #20
0
 public bool TryGetFileSystem(string tenantId, out Task <RavenFileSystem> fileSystem)
 {
     return(ResourcesStoresCache.TryGetValue(tenantId, out fileSystem));
 }
Example #21
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());

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