Exemplo n.º 1
0
        // Todo: Cancel or wait for any unfinished operations (queries, etc.) when reloading the database.

        internal Task LoadAsync(IDatabaseLoadMethod loadMethod,
                                CancellationToken cancellationToken = default(CancellationToken))
        {
            if (loadMethod == null)
            {
                throw new ArgumentNullException(nameof(loadMethod));
            }

            return(Task.Run(() =>
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    return;
                }

                lock (DbWriteLock)
                {
                    var databaseItems = new ConcurrentList <Entity>();
                    List <Entity> previousItems;
                    using (var e = volatileDatabaseItems.GetEnumerator(cancellationToken))
                    {
                        previousItems = e.AsEnumerable().ToList();
                    }
                    if (cancellationToken.IsCancellationRequested)
                    {
                        return;
                    }

                    volatileDatabaseItems = databaseItems;

                    try
                    {
                        Log(new DatabaseEvent(DatabaseEventType.LoadStart, message: "Database load started."));

                        if (loadMethod.Scannable)
                        {
                            Log(new DatabaseEvent(DatabaseEventType.ScanStart, message: "Scan started."));
                            loadMethod.Scan(previousItems, Logger, cancellationToken);
                            if (cancellationToken.IsCancellationRequested)
                            {
                                return;
                            }
                            foreach (var item in previousItems)
                            {
                                databaseItems.Add(item);
                            }
                            Log(new DatabaseEvent(DatabaseEventType.ScanEnd, message: "Scan ended."));

                            Log(new DatabaseEvent(DatabaseEventType.LoadProgress,
                                                  message: $"Load progress: 0 / {loadMethod.ItemCount:n0}",
                                                  progress: new Progress(0, loadMethod.ItemCount)));
                        }

                        var items = loadMethod.Load(Logger);

                        var stopwatch = new Stopwatch();
                        stopwatch.Start();
                        var i = -1;
                        foreach (var item in items)
                        {
                            i++;
                            if (cancellationToken.IsCancellationRequested)
                            {
                                break;
                            }

                            if (item != null)
                            {
                                databaseItems.Add(item);
                            }

                            if (loadMethod.Scannable)
                            {
                                if (stopwatch.ElapsedMilliseconds >= ProgressEventDelay)
                                {
                                    Log(new DatabaseEvent(DatabaseEventType.LoadProgress,
                                                          progress: new Progress(i + 1, loadMethod.ItemCount)));
                                    stopwatch.Restart();
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Log(new DatabaseEvent(
                                DatabaseEventType.Message, message: $"Database load error: {ex.Message}",
                                severity: EventSeverity.Error));
                    }
                    finally
                    {
                        databaseItems.CompleteAdding();
                        Log(new DatabaseEvent(DatabaseEventType.LoadEnd, message: "Database load ended."));
                    }
                }
            }, cancellationToken));
        }
Exemplo n.º 2
0
        /// <summary>
        /// A high-level database save/load method that handles caching automatically.
        /// </summary>
        /// <param name="connection"></param>
        /// <param name="directory"></param>
        /// <param name="cacheDirectory"></param>
        /// <param name="mode"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static Task LoadAsync(
            this IDatabaseConnection connection,
            string directory,
            string cacheDirectory,
            DatabaseLoadMode mode = DatabaseLoadMode.Auto,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            if (connection == null)
            {
                throw new ArgumentNullException(nameof(connection));
            }
            if (directory == null)
            {
                throw new ArgumentNullException(nameof(directory));
            }
            if (cacheDirectory == null)
            {
                throw new ArgumentNullException(nameof(cacheDirectory));
            }

            return(Task.Run(async() =>
            {
                var cacheFilePath = Path.Combine(cacheDirectory, IO.IOUtil.PathToHash(directory));

                IDatabaseLoadMethod loadMethod = null;
                IDatabaseSaveMethod saveMethod = null;

                try
                {
                    switch (mode)
                    {
                    case DatabaseLoadMode.Auto:
                        if (File.Exists(cacheFilePath))
                        {
                            goto case DatabaseLoadMode.LoadCache;
                        }
                        else
                        {
                            goto case DatabaseLoadMode.Rebuild;
                        }

                    case DatabaseLoadMode.LoadCache:
                        loadMethod = new SerializedDatabaseLoadMethod(cacheFilePath);
                        break;

                    case DatabaseLoadMode.Rebuild:
                        loadMethod = new CreateFromDirectoryDatabaseLoadMethod(directory, FileIOUtil.CreateOmniFileHandler());
                        saveMethod = new SerializedDatabaseSaveMethod(cacheFilePath);
                        break;

                    case DatabaseLoadMode.Refresh:
                        loadMethod = new CreateFromDirectoryDatabaseLoadMethod(directory, FileIOUtil.CreateOmniFileHandler(), update: true);
                        saveMethod = new SerializedDatabaseSaveMethod(cacheFilePath);
                        break;

                    default:
                        throw new ArgumentOutOfRangeException(nameof(mode), mode, null);
                    }

                    await connection.LoadAsync(loadMethod, cancellationToken);

                    if (saveMethod != null)
                    {
                        await connection.SaveAsync(saveMethod, cancellationToken);
                    }
                }
                catch (TaskCanceledException)
                {
                }
                finally
                {
                    loadMethod?.Dispose();
                    saveMethod?.Dispose();
                }
            }, cancellationToken));
        }