/// <summary> /// ファイルに対するVFS処理を定期実行します /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void OnIndexTimerElapsed(object sender, System.Timers.ElapsedEventArgs e) { if (this.IsSuspendIndex) { return; // サスペンド時はインデックス生成処理はスキップする } // インデックス生成処理中は、このメソッドを呼び出すタイマーは停止しておきます。 var timer = sender as System.Timers.Timer; timer.Enabled = false; mLogger.Info("タイマー処理の実行"); // ディレクトリ削除イベントが発生している場合、 // 削除したディレクトリに含まれていたファイルを、削除したパスから見つけ出して削除処理を行うキューに追加する lock (sameDirectoryOperation_Locker) { if (sameDirectoryOperation_Name != "") { sameDirectoryOperation_Name = ""; var relativeDirPath = mWorkspace.TrimWorekspacePath(sameDirectoryOperation_FullPath); using (AsyncScopedLifestyle.BeginScope(container)) { var fileMappingInfoRepository = container.GetInstance <IFileMappingInfoRepository> (); foreach (var prop in fileMappingInfoRepository.FindPathWithStart(relativeDirPath)) { var fileUpdateQueueItem = new FileUpdateQueueItem { Target = new FileInfo(Path.Combine(mWatcherVirtual.Path, prop.MappingFilePath + ".aclgene")) }; fileUpdateQueueItem.Recents.Add(new RecentInfo { EventType = WatcherChangeTypes.Deleted }); mUpdatesWatchFiles.AddOrUpdate(prop.MappingFilePath, fileUpdateQueueItem, (_key, _value) => fileUpdateQueueItem); } } } } // foreach (var @pair in mUpdatesWatchFiles.ToList()) { // 最後のファイル監視状態から、一定時間経過している場合のみ処理を行う。 var @diff = DateTime.Now - @pair.Value.LastUpdate; if (@diff.Seconds >= 10) // 10秒 以上経過 { FileUpdateQueueItem item; // work if (mUpdatesWatchFiles.TryRemove(@pair.Key, out item)) { var @lastItem = item.Recents.LastOrDefault(); // NOTE: UpdateVirtualSpaceFlowワークフローを呼び出す mLogger.Info("ワークフロー実行 [{1}] 対象ファイルパス={0}", item.Target.FullName, @lastItem.EventType); // ワークフロー処理中に発生するファイル更新イベントにより、更新キューに項目が追加されてしまうことを防ぐため、 // 処理中のファイルを更新キューから除外するための除外リストに、処理中のファイルを追加する。 // // ※処理中のファイルがACLファイル以外の場合、対象ファイルのACLファイル名も除外リストに追加する mIgnoreUpdateFiles.Enqueue(item.Target.FullName); if (item.Target.Extension != ".aclgene") { var localPath = mWorkspace.TrimWorekspacePath(item.Target.FullName); var vpath = Path.Combine(mWorkspace.VirtualPath, localPath); mIgnoreUpdateFiles.Enqueue(vpath + ".aclgene"); // 仮想領域に作成するACLファイルを除外リストに追加 } using (var scope = FoxpictAsyncScopedLifestyle.BeginScope(container)) { try { var workspaceRepository = container.GetInstance <IWorkspaceRepository> (); var workspace = workspaceRepository.Load(mWorkspace.Id); if (workspace == null) { workspace = mWorkspace; } // VFS機能のサービスを取得する var fileUpdateRunner = container.GetInstance <IFileUpdateRunner> (); if (workspace.ContainsImport(item.Target)) { // インポート領域のファイルの場合は、カテゴリのパース処理を実施する。 fileUpdateRunner.EnableCategoryParse = true; } // 処理対象のファイルがACLファイルか、物理ファイルかで処理を切り分けます // ■ACLファイルの場合 // リネーム更新イベントに対応します。 // ■物理ファイルの場合 // リネーム更新イベントも、UPDATEイベントとして処理します。 if (item.Target.Extension == ".aclgene") { var fileNameWithputExtension = item.Target.Name.Replace(item.Target.Extension, ""); switch (@lastItem.EventType) { case WatcherChangeTypes.Renamed: fileUpdateRunner.file_rename_acl(item.Target, workspace); break; case WatcherChangeTypes.Changed: case WatcherChangeTypes.Created: fileUpdateRunner.file_create_acl(item.Target, workspace); break; case WatcherChangeTypes.Deleted: fileUpdateRunner.file_remove_acl(item.Target, workspace); break; } } else { if (File.Exists(item.Target.FullName)) { switch (@lastItem.EventType) { case WatcherChangeTypes.Renamed: case WatcherChangeTypes.Changed: case WatcherChangeTypes.Created: fileUpdateRunner.file_create_normal(item.Target, workspace); break; case WatcherChangeTypes.Deleted: break; } } else { mLogger.Info("「{0}」は存在しない物理ファイルのため、処理をスキップします。", item.Target.FullName); } } scope.Complete(); } catch (Exception expr) { mLogger.Error(expr, "VFSの処理に失敗しました。"); mLogger.Debug(expr.StackTrace); if (expr.InnerException != null) { mLogger.Error(expr.InnerException.Message); mLogger.Error(expr.InnerException.StackTrace); } } } // 処理を終了したファイルを、除外リストから削除します string ignoreUpdateFile; mIgnoreUpdateFiles.TryDequeue(out ignoreUpdateFile); if (item.Target.Extension != ".aclgene") { mIgnoreUpdateFiles.TryDequeue(out ignoreUpdateFile); } } } // [CPU使用率に対するループ遅延を行う] // var cpuPer = _CpuCounter.NextValue(); // if (cpuPer > 90.0) // { // await Task.Delay(100); // 100msec待機 // } // else if (cpuPer > 30.0) // { // //await Task.Delay(10); // 10msec待機 // } } // [FileWatcherコンポーネントの、ファイルイベント通知漏れ対策] // 1つでもファイルイベントが発生しているフォルダは、そのフォルダに属するファイルを処理キューに「新規作成アイテム」として登録する。 // ただし、処理済みのファイルまで登録してしまうと2度処理を行うことになるため、除外リストに含まれているファイルは処理キューへの登録は行わない。 foreach (var pair in mUpdateDirectory.ToList()) { var itemDirectory = new DirectoryInfo(pair.Value.FullName); if (mWorkspace.ContainsImport(itemDirectory)) { // フォルダが、インポート領域の場合 if (!itemDirectory.Exists) { // インポート領域では、Deleteイベントは受け取らないため、 // フォルダ有無を検証し、フォルダが削除済みの場合は更新ディレクトリキューから削除する。 DirectoryInfo dummy; mUpdateDirectory.TryRemove(pair.Key, out dummy); mLogger.Info($"キューから処理対象のディレクトリ({dummy.Name})を削除"); continue; } RegisterDirectoryFiles(itemDirectory); // インポート領域内で、かつ空フォルダの場合は、フォルダを削除する if (itemDirectory.GetFiles("*", SearchOption.AllDirectories).Length == 0) { try { itemDirectory.Delete(true); } catch (Exception expr) { mLogger.Error(expr, $"フォルダの削除({itemDirectory.Name})に失敗しました。"); throw expr; } mLogger.Info($"インポート領域内のディレクトリ({itemDirectory.Name})を削除しました。"); DirectoryInfo dummy; mUpdateDirectory.TryRemove(pair.Key, out dummy); mLogger.Info($"キューから処理対象のディレクトリ({dummy.Name})を削除"); } } else { // フォルダが、仮想領域の場合 RegisterDirectoryFiles(itemDirectory); DirectoryInfo dummy; mUpdateDirectory.TryRemove(itemDirectory.FullName, out dummy); } } timer.Enabled = true; }
/// <summary> /// Configures the application. /// </summary> /// <param name="app">The application.</param> /// <param name="env">The hosting environment</param> public void Configure(IApplicationBuilder app, IHostingEnvironment env) { InitializeContainer(app); SetupApplication(); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseHttpsRedirection(); // SSL app.UseDefaultFiles(); app.UseStaticFiles(); // Enable middleware to serve generated Swagger as a JSON endpoint. app.UseSwagger(); // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.), specifying the Swagger JSON endpoint. app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); }); app.UseStaticFiles(); //app.UseSpaStaticFiles(); // services.AddSpaStaticFilesを使って、ASPに静的なファイルを組み込む場合は併用する using (var scope = FoxpictAsyncScopedLifestyle.BeginScope(mContainer)) { // カットポイント「INIT」を呼び出す var extentionManager = mContainer.GetInstance <ExtentionManager> (); try { extentionManager.Execute(ExtentionCutpointType.INIT); scope.Complete(); } catch (Exception expr) { mLogger.Error(expr, "INITカットポイントの処理に失敗しました。"); mLogger.Debug(expr.StackTrace); } } using (var scope = FoxpictAsyncScopedLifestyle.BeginScope(mContainer)) { // カットポイント「START」を呼び出す var extentionManager = mContainer.GetInstance <ExtentionManager> (); try { extentionManager.Execute(ExtentionCutpointType.START, new CutpointStartParameter { WorkspaceId = 1L }); scope.Complete(); } catch (Exception expr) { mLogger.Error(expr, "STARTカットポイントの処理に失敗しました。"); mLogger.Debug(expr.StackTrace); } } // FS監視開始 using (FoxpictAsyncScopedLifestyle.BeginScope(mContainer)) { var workspaceRepository = mContainer.GetInstance <IWorkspaceRepository> (); var vspFileUpdateWatchManager = mContainer.GetInstance <VirtualFileUpdateWatchService> (); vspFileUpdateWatchManager.StartWatch(workspaceRepository.Load(1L)); } app.UseMvc(routes => { routes.MapRoute(name: "default", template: "{controller}/{action=index}/{id}"); }); app.UseSpa(spa => { // To learn more about options for serving an Angular SPA from ASP.NET Core, // see https://go.microsoft.com/fwlink/?linkid=864501 //spa.Options.SourcePath = "wwwroot"; spa.Options.SourcePath = "ClientApp"; if (env.IsDevelopment()) { //spa.UseAngularCliServer(npmScript: "start"); spa.UseProxyToSpaDevelopmentServer("http://localhost:4200"); // 外部起動しているHTTPサーバにアクセスする } }); }