// ==================================================================== // protected 関数 // ==================================================================== // -------------------------------------------------------------------- // ネビュラコア(統計データ作成)のメインルーチン // -------------------------------------------------------------------- protected override async Task CoreMainAsync() { // 急ぎではないのでプライオリティーを下げる Thread.CurrentThread.Priority = ThreadPriority.Lowest; while (true) { MainEvent.WaitOne(); Int32 startTick = Environment.TickCount; try { YlModel.Instance.EnvModel.AppCancellationTokenSource.Token.ThrowIfCancellationRequested(); if (YlModel.Instance.EnvModel.YukaListerWholeStatus == YukaListerStatus.Error) { continue; } if (!YlModel.Instance.EnvModel.YlSettings.IsYukariRequestDatabaseValid()) { continue; } YlModel.Instance.EnvModel.LogWriter.LogMessage(Common.TRACE_EVENT_TYPE_STATUS, GetType().Name + " アクティブ化。"); // データベースアクセス準備 using YukariStatisticsContext yukariStatisticsContext = new(); using YukariRequestContext yukariRequestContext = new(); yukariRequestContext.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; using ListContextInDisk listContextInDisk = new(); listContextInDisk.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; UpdateLastYukariRequestClearTimeIfNeeded(yukariRequestContext.YukariRequests); // request.db にある予約の統計更新 await AnalyzeYukariRequests(yukariStatisticsContext.YukariStatistics, yukariRequestContext.YukariRequests, listContextInDisk.Founds); #if DEBUG Boolean hasChangesBak = yukariStatisticsContext.ChangeTracker.HasChanges(); Double lastWriteTimeBak = yukariStatisticsContext.LastWriteMjd(); #endif if (yukariStatisticsContext.ChangeTracker.HasChanges()) { yukariStatisticsContext.BackupDatabase(); } yukariStatisticsContext.SaveChanges(); #if DEBUG Debug.WriteLine("Yurelin.CoreMain() 更新フラグ " + hasChangesBak.ToString()); Debug.WriteLine("Yurelin.CoreMain() 実際のファイル更新 " + (lastWriteTimeBak == yukariStatisticsContext.LastWriteMjd() ? "なし" : "有り")); Debug.Assert(hasChangesBak == (lastWriteTimeBak != yukariStatisticsContext.LastWriteMjd()), "Yurelin.CoreMain() フラグが実際と異なった Bak: " + JulianDay.ModifiedJulianDateToDateTime(lastWriteTimeBak).ToString(YlConstants.TIME_FORMAT) + ", 現在: " + JulianDay.ModifiedJulianDateToDateTime(yukariStatisticsContext.LastWriteMjd()).ToString(YlConstants.TIME_FORMAT)); #endif if (UpdatePastYukariStatisticsKind != UpdatePastYukariStatisticsKind.None) { // 過去の統計(request.db にないものを含む)更新 UpdatePast(); } } catch (OperationCanceledException) { return; } catch (Exception ex) { YlModel.Instance.EnvModel.NebulaCoreErrors.Enqueue(GetType().Name + " ループ稼働時エラー:\n" + ex.Message); YlModel.Instance.EnvModel.LogWriter.LogMessage(Common.TRACE_EVENT_TYPE_STATUS, " スタックトレース:\n" + ex.StackTrace); } TimeSpan timeSpan = new(YlCommon.MiliToHNano(Environment.TickCount - startTick)); YlModel.Instance.EnvModel.LogWriter.LogMessage(Common.TRACE_EVENT_TYPE_STATUS, GetType().Name + " スリープ化:アクティブ時間:" + timeSpan.ToString(@"hh\:mm\:ss")); } }
// ==================================================================== // protected 関数 // ==================================================================== // -------------------------------------------------------------------- // ネビュラコア(検索データ作成)のメインルーチン // -------------------------------------------------------------------- protected override Task CoreMainAsync() { while (true) { MainEvent.WaitOne(); Int32 startTick = Environment.TickCount; try { YlModel.Instance.EnvModel.AppCancellationTokenSource.Token.ThrowIfCancellationRequested(); if (YlModel.Instance.ProjModel.UndoneTargetFolderInfo() == null) { continue; } YlModel.Instance.EnvModel.YukaListerPartsStatus[(Int32)YukaListerPartsStatusIndex.Sifolin] = YukaListerStatus.Running; YlModel.Instance.EnvModel.LogWriter.LogMessage(Common.TRACE_EVENT_TYPE_STATUS, GetType().Name + " アクティブ化。"); if (YlModel.Instance.EnvModel.YlSettings.ApplyMusicInfoIntelligently) { YlModel.Instance.EnvModel.LogWriter.LogMessage(Common.TRACE_EVENT_TYPE_STATUS, "楽曲情報データベースが不十分な場合の誤適用を軽減する設定。"); } MusicInfoDatabaseToMemory(); _prevFolderTaskDetail = FolderTaskDetail.Done; while (true) { TargetFolderInfo?targetFolderInfo; // 削除 targetFolderInfo = YlModel.Instance.ProjModel.FindTargetFolderInfo(FolderTaskDetail.Remove); if (targetFolderInfo != null) { Remove(targetFolderInfo); continue; } // キャッシュ活用(全体の動作状況がエラーではない場合のみ) if (YlModel.Instance.EnvModel.YukaListerWholeStatus != YukaListerStatus.Error) { targetFolderInfo = YlModel.Instance.ProjModel.FindTargetFolderInfo(FolderTaskDetail.CacheToDisk); if (targetFolderInfo != null) { CacheToDisk(targetFolderInfo); continue; } } // すべてのフォルダーのキャッシュ活用が終わったら Yurelin をアクティブ化する // 起動直後に前回のゆかり予約を解析することを想定している if (_prevFolderTaskDetail == FolderTaskDetail.CacheToDisk) { Debug.WriteLine("Sifolin.CoreMain() キャッシュ活用後の Yurelin アクティブ化"); YlCommon.ActivateYurelinIfNeeded(); } // 更新削除 targetFolderInfo = YlModel.Instance.ProjModel.FindTargetFolderInfo(FolderTaskDetail.UpdateRemove); if (targetFolderInfo != null) { UpdateRemove(targetFolderInfo); continue; } // 更新サブフォルダー検索 targetFolderInfo = YlModel.Instance.ProjModel.FindTargetFolderInfo(FolderTaskDetail.UpdateFindSubFolders); if (targetFolderInfo != null) { UpdateFindSubFolders(targetFolderInfo); continue; } // サブフォルダー検索 targetFolderInfo = YlModel.Instance.ProjModel.FindTargetFolderInfo(FolderTaskDetail.FindSubFolders); if (targetFolderInfo != null) { FindSubFolders(targetFolderInfo); continue; } // ファイル名追加 targetFolderInfo = YlModel.Instance.ProjModel.FindTargetFolderInfo(FolderTaskDetail.AddFileNames); if (targetFolderInfo != null) { AddFileNames(targetFolderInfo); continue; } // ファイル情報追加 targetFolderInfo = YlModel.Instance.ProjModel.FindTargetFolderInfo(FolderTaskDetail.AddInfos); if (targetFolderInfo != null) { AddInfos(targetFolderInfo); continue; } // メモリー DB → ディスク DB(全体の動作状況がエラーではない場合のみ) if (_needsMemoryDbToDiskDb && YlModel.Instance.EnvModel.YukaListerWholeStatus != YukaListerStatus.Error) { MemoryToDisk(); _needsMemoryDbToDiskDb = false; continue; } // メモリー DB → キャッシュ DB if (_needsMemoryDbToCacheDb) { MemoryToCache(); _needsMemoryDbToCacheDb = false; continue; } // Kamlin アクティブ化 YlCommon.ActivateKamlinIfNeeded(); // Yurelin アクティブ化 YlCommon.ActivateYurelinIfNeeded(); // やることが無くなったのでループを抜けて待機へ向かう break; } } catch (OperationCanceledException) { return(Task.CompletedTask); } catch (Exception ex) { YlModel.Instance.EnvModel.NebulaCoreErrors.Enqueue(GetType().Name + " ループ稼働時エラー:\n" + ex.Message); YlModel.Instance.EnvModel.LogWriter.LogMessage(Common.TRACE_EVENT_TYPE_STATUS, " スタックトレース:\n" + ex.StackTrace); } // 念のため最後に表示を更新 YlModel.Instance.EnvModel.YukaListerPartsStatus[(Int32)YukaListerPartsStatusIndex.Sifolin] = YukaListerStatus.Ready; YlModel.Instance.EnvModel.IsMainWindowDataGridCountChanged = true; TimeSpan timeSpan = new(YlCommon.MiliToHNano(Environment.TickCount - startTick)); YlModel.Instance.EnvModel.LogWriter.LogMessage(Common.TRACE_EVENT_TYPE_STATUS, GetType().Name + " スリープ化:アクティブ時間:" + timeSpan.ToString(@"hh\:mm\:ss")); } }
// ==================================================================== // protected 関数 // ==================================================================== // -------------------------------------------------------------------- // ネビュラコア(同期)のメインルーチン // -------------------------------------------------------------------- protected override async Task CoreMainAsync() { #if DEBUGz Debug.WriteLine("priority before: " + Thread.CurrentThread.Priority.ToString()); Thread.CurrentThread.Priority = ThreadPriority.Lowest; Debug.WriteLine("priority after: " + Thread.CurrentThread.Priority.ToString()); #endif YlCommon.SetLogWriterSyncDetail(_logWriterSyncDetail); while (true) { MainEvent.WaitOne(); Debug.Assert(MainWindowViewModel != null, "Syclin.CoreMain() MainWindowViewModel is null"); Int32 startTick = Environment.TickCount; try { YlModel.Instance.EnvModel.AppCancellationTokenSource.Token.ThrowIfCancellationRequested(); if (YlModel.Instance.EnvModel.YukaListerWholeStatus == YukaListerStatus.Error) { continue; } if (!YlModel.Instance.EnvModel.YlSettings.SyncMusicInfoDb) { continue; } IsActive = true; YlModel.Instance.EnvModel.LogWriter.LogMessage(Common.TRACE_EVENT_TYPE_STATUS, GetType().Name + " アクティブ化。"); // ログイン MainWindowViewModel.SetStatusBarMessageWithInvoke(Common.TRACE_EVENT_TYPE_STATUS, "同期準備中..."); await LoginToSyncServerAsync(); // データベースをバックアップ using MusicInfoContextDefault musicInfoContextDefault = new(); musicInfoContextDefault.BackupDatabase(); using YukariStatisticsContext yukariStatisticsContext = new(); yukariStatisticsContext.BackupDatabase(); // 再取得の場合は楽曲情報データベース初期化 CreateDatabaseIfNeeded(musicInfoContextDefault, yukariStatisticsContext); // ダウンロード (Int32 numTotalDownloads, Int32 numTotalImports) = await DownloadSyncDataAsync(); // アップロード Int32 numTotalUploads = await UploadSyncDataAsync(); if (numTotalUploads > 0) { // アップロードを行った場合は、自身がアップロードしたデータの更新日・Dirty を更新するために再ダウンロードが必要 (numTotalDownloads, numTotalImports) = await DownloadSyncDataAsync(); } // 完了表示 MainWindowViewModel.SetStatusBarMessageWithInvoke(Common.TRACE_EVENT_TYPE_STATUS, "データベース同期完了(ダウンロード" + (numTotalDownloads == 0 ? "無" : " " + numTotalDownloads.ToString("#,0") + " 件、うち " + numTotalImports.ToString("#,0") + " 件インポート") + "、アップロード" + (numTotalUploads == 0 ? "無" : " " + numTotalUploads.ToString("#,0") + " 件") + ")"); // 起動直後は Syclin と Yurelin が両方起動され、Syclin による属性未確認データのアップロード&ダウンロードと、Yurelin による属性確認が競合し、属性未確認の状態に戻ることがある // Syclin スリープ化直前に Yurelin を起動し、再度属性確認が行われるようにする YlCommon.ActivateYurelinIfNeeded(); } catch (OperationCanceledException) { return; } catch (Exception excep) { DbCommon.LogDatabaseExceptionIfCan(excep); // メッセージボックスではなくステータスバーにエラー表示 MainWindowViewModel.SetStatusBarMessageWithInvoke(TraceEventType.Error, excep.Message); YlModel.Instance.EnvModel.LogWriter.LogMessage(Common.TRACE_EVENT_TYPE_STATUS, " スタックトレース:\n" + excep.StackTrace); } IsActive = false; TimeSpan timeSpan = new(YlCommon.MiliToHNano(Environment.TickCount - startTick)); YlModel.Instance.EnvModel.LogWriter.LogMessage(Common.TRACE_EVENT_TYPE_STATUS, GetType().Name + " スリープ化:アクティブ時間:" + timeSpan.ToString(@"hh\:mm\:ss")); } }
// ==================================================================== // protected 関数 // ==================================================================== // -------------------------------------------------------------------- // ネビュラコア(動画リスト作成)のメインルーチン // -------------------------------------------------------------------- protected override async Task CoreMainAsync() { // リスト出力時の処理が重いことによるトラブルの可能性がゼロではないため、プライオリティーを下げる(チケット #97) Thread.CurrentThread.Priority = ThreadPriority.Lowest; while (true) { MainEvent.WaitOne(); Debug.Assert(MainWindowViewModel != null, "Kamlin.CoreMain() MainWindowViewModel is null"); Int32 startTick = Environment.TickCount; try { YlModel.Instance.EnvModel.AppCancellationTokenSource.Token.ThrowIfCancellationRequested(); // 全体の動作状況がエラーの場合はリスト作成しない if (YlModel.Instance.EnvModel.YukaListerWholeStatus == YukaListerStatus.Error) { continue; } // リストデータベースのレコード数が 0 ならリスト作成不要 using ListContextInDisk listContextInDisk = new(); if (!listContextInDisk.Founds.Any()) { continue; } YlModel.Instance.EnvModel.YukaListerPartsStatus[(Int32)YukaListerPartsStatusIndex.Kamlin] = YukaListerStatus.Running; YlModel.Instance.EnvModel.LogWriter.LogMessage(Common.TRACE_EVENT_TYPE_STATUS, GetType().Name + " アクティブ化。"); // 問題報告用に ID 接頭辞が必要 try { await YlCommon.InputIdPrefixIfNeededWithInvoke(MainWindowViewModel); } catch (Exception) { // OperationCanceledException を通常の例外に変換 throw new Exception("ID 接頭辞が設定されていません。"); } // リスト出力 YukariOutputWriter yukariOutputWriter = new(); yukariOutputWriter.Output(); YlModel.Instance.EnvModel.LogWriter.LogMessage(TraceEventType.Information, "リスト出力が完了しました。"); } catch (OperationCanceledException) { return; } catch (Exception ex) { YlModel.Instance.EnvModel.NebulaCoreErrors.Enqueue(GetType().Name + " ループ稼働時エラー:\n" + ex.Message); YlModel.Instance.EnvModel.LogWriter.LogMessage(Common.TRACE_EVENT_TYPE_STATUS, " スタックトレース:\n" + ex.StackTrace); } YlModel.Instance.EnvModel.YukaListerPartsStatus[(Int32)YukaListerPartsStatusIndex.Kamlin] = YukaListerStatus.Ready; TimeSpan timeSpan = new(YlCommon.MiliToHNano(Environment.TickCount - startTick)); YlModel.Instance.EnvModel.LogWriter.LogMessage(Common.TRACE_EVENT_TYPE_STATUS, GetType().Name + " スリープ化:アクティブ時間:" + timeSpan.ToString(@"hh\:mm\:ss")); } }