Ejemplo n.º 1
0
        /// <summary>
        /// ファイル監視で変更通知が行われた、ファイルの更新キューを更新する。
        /// </summary>
        /// <remarks>
        /// 対象パスがキューに登録済みの場合は、登録情報の更新を行います。
        /// 未登録の場合は、情報を新規登録します。
        /// </remarks>
        /// <param name="watchTarget">変更通知が発生した、ファイル情報</param>
        /// <param name="watcherChangeType">変更内容区分</param>
        /// <param name="beforeRenamedName">変更内容区分がリネームの場合、リネーム前のファイル名を入力してください</param>
        FileUpdateQueueItem UpdateOrInsertUpdatedFileQueueItem(FileInfo watchTarget, WatcherChangeTypes watcherChangeType, string beforeRenamedName)
        {
            FileUpdateQueueItem fileUpdateQueueItem;
            string key;

            lock (this)
            {
                // 更新イベントの対象ファイルが、ACLファイルか物理ファイルか更新キューに使用するキーが異なる。
                // ACLファイルでは、ACLハッシュをキーに使用します。
                // 物理ファイルでは、ファイルパスをキーに使用します。
                if (watchTarget.Extension == ".aclgene")
                {
                    // ACLファイルの場合、更新イベントを追わなくてもACLハッシュで常にどのファイルが更新キュー内のどこにあるかがわかる
                    // ※ただし、ファイル削除を除く

                    if (watcherChangeType == WatcherChangeTypes.Deleted)
                    {
                        var deletedFileRelativePath = this._Workspace.TrimWorekspacePath(watchTarget.FullName, false);
                        var r = from u in _UpdatesWatchFiles
                                where u.Value.OldRenameNamePath == deletedFileRelativePath
                                select u;
                        var prop = r.FirstOrDefault();
                        if (prop.Key != null)
                        {
                            _UpdatesWatchFiles.TryGetValue(prop.Key, out fileUpdateQueueItem);
                        }
                        else
                        {
                            fileUpdateQueueItem = new FileUpdateQueueItem {
                                Target = watchTarget
                            };

                            _UpdatesWatchFiles.AddOrUpdate(deletedFileRelativePath,
                                                           fileUpdateQueueItem, (_key, _value) => fileUpdateQueueItem
                                                           );

                            // 発生はありえないが、発生した場合は処理せず終了
                            // →発生はありうる。
                            //LOG.Warn("更新キューに登録されていないACLファイルの削除イベント");
                            //return null;
                        }
                    }
                    else
                    {
                        // ACLファイルからACLデータを取得
                        AclFileStructure aclFileData;
                        using (var file = File.OpenRead(watchTarget.FullName))
                        {
                            aclFileData = Serializer.Deserialize <AclFileStructure>(file);
                        }

                        var aclhash = aclFileData.FindKeyValue("ACLHASH");

                        if (!_UpdatesWatchFiles.ContainsKey(aclhash))
                        {
                            fileUpdateQueueItem = new FileUpdateQueueItem {
                                Target = watchTarget
                            };

                            _UpdatesWatchFiles.AddOrUpdate(aclhash, fileUpdateQueueItem, (_key, _value) => fileUpdateQueueItem);
                        }
                        else
                        {
                            // キューから情報を取得
                            _UpdatesWatchFiles.TryGetValue(aclhash, out fileUpdateQueueItem);
                            fileUpdateQueueItem.Target = watchTarget;                             // 登録している物理ファイル情報を最新のオブジェクトにする
                        }

                        // 最後に更新イベントが発生した時のファイルパスを格納しておく(Deleteイベント用)
                        fileUpdateQueueItem.OldRenameNamePath = this._Workspace.TrimWorekspacePath(watchTarget.FullName, false);
                    }
                }
                else
                {
                    if (watcherChangeType == WatcherChangeTypes.Renamed && !string.IsNullOrEmpty(beforeRenamedName))
                    {
                        // 変更内容がリネームの場合、名前変更前のファイルパスで登録済みの項目を取得し、
                        // 名前変更前の項目はキューから削除します。
                        // 名前変更後の項目として、新たにキューに再登録を行います。
                        var renamedFullName = watchTarget.FullName.Replace(watchTarget.FullName, beforeRenamedName);

                        var oldkey = this._Workspace.TrimWorekspacePath(renamedFullName, false);
                        key = this._Workspace.TrimWorekspacePath(watchTarget.FullName, false);

                        if (_UpdatesWatchFiles.ContainsKey(oldkey))
                        {
                            // 古いキーの項目をキューから削除します。
                            // 新しいキーで、キューに情報を再登録します。
                            _UpdatesWatchFiles.TryRemove(oldkey, out fileUpdateQueueItem);
                            _UpdatesWatchFiles.AddOrUpdate(key, fileUpdateQueueItem, (_key, _value) => fileUpdateQueueItem);
                        }
                    }
                    else if (watcherChangeType == WatcherChangeTypes.Created)
                    {
                        key = this._Workspace.TrimWorekspacePath(watchTarget.FullName, false);
                    }
                    else
                    {
                        key = this._Workspace.TrimWorekspacePath(watchTarget.FullName, false);
                    }

                    // 更新通知があったファイルが処理キューに未登録の場合、キューに更新通知情報を新規登録します
                    if (!_UpdatesWatchFiles.ContainsKey(key))
                    {
                        fileUpdateQueueItem = new FileUpdateQueueItem {
                            Target = watchTarget
                        };

                        _UpdatesWatchFiles.AddOrUpdate(key, fileUpdateQueueItem, (_key, _value) => fileUpdateQueueItem);
                    }
                    else
                    {
                        // キューから情報を取得
                        _UpdatesWatchFiles.TryGetValue(key, out fileUpdateQueueItem);
                        fileUpdateQueueItem.Target = watchTarget;                         // 登録している物理ファイル情報を最新のオブジェクトにする
                    }

                    // 更新通知のイベント区分が『リネーム』の場合、元のファイル名も保存しておく。
                    // イベント処理前は物理ディレクトリ空間のファイルパスはリネーム前のパスのままなので、
                    // リネーム前のファイル名のみを保存します。
                    if (watcherChangeType == WatcherChangeTypes.Renamed &&
                        string.IsNullOrEmpty(fileUpdateQueueItem.OldRenameNamePath))
                    {
                        fileUpdateQueueItem.OldRenameNamePath = beforeRenamedName;
                    }
                }



                // 情報に、履歴を追加
                var now = DateTime.Now;
                fileUpdateQueueItem.LastUpdate = now;
                var rec = new RecentInfo
                {
                    EventType  = watcherChangeType,
                    RecentDate = now
                };
                fileUpdateQueueItem.Recents.Add(rec);

                return(fileUpdateQueueItem);
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// インデックス作成処理を一定間隔で行います
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        async void OnIndexTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (this.IsSuspendIndex)
            {
                return;                                  // サスペンド時はインデックス生成処理はスキップする
            }
            // インデックス生成処理中は、このメソッドを呼び出すタイマーは停止しておきます。
            var timer = sender as System.Timers.Timer;

            timer.Enabled = false;

            LOG.Info("タイマー処理の実行");

            // ディレクトリ削除イベントが発生している場合、
            // 削除したディレクトリに含まれていたファイルを、削除したパスから見つけ出して削除処理を行うキューに追加する
            lock (sameDirectoryOperation_Locker)
            {
                if (sameDirectoryOperation_Name != "")
                {
                    sameDirectoryOperation_Name = "";
                    var relativeDirPath = _Workspace.TrimWorekspacePath(sameDirectoryOperation_FullPath, false);
                    using (var dbc = new AppDbContext())
                    {
                        var repo = new FileMappingInfoRepository(dbc);
                        foreach (var prop in repo.FindBy(p => p.MappingFilePath.StartsWith(relativeDirPath)))
                        {
                            var fileUpdateQueueItem = new FileUpdateQueueItem {
                                Target = new FileInfo(Path.Combine(_Workspace.WorkspacePath, prop.MappingFilePath + ".aclgene"))
                            };
                            fileUpdateQueueItem.Recents.Add(new RecentInfo {
                                EventType = WatcherChangeTypes.Deleted
                            });
                            _UpdatesWatchFiles.AddOrUpdate(prop.MappingFilePath, fileUpdateQueueItem, (_key, _value) => fileUpdateQueueItem);
                        }
                    }
                }
            }

            //
            foreach (var @pair in _UpdatesWatchFiles.ToList())
            {
                // 最後のファイル監視状態から、一定時間経過している場合のみ処理を行う。
                var @diff = DateTime.Now - @pair.Value.LastUpdate;

                if (@diff.Seconds >= 10)                 // 10秒 以上経過
                {
                    FileUpdateQueueItem item;            // work
                    if (_UpdatesWatchFiles.TryRemove(@pair.Key, out item))
                    {
                        var @lastItem = item.Recents.LastOrDefault();

                        // NOTE: UpdateVirtualSpaceFlowワークフローを呼び出す
                        LOG.InfoFormat("ワークフロー実行 [{1}] 対象ファイルパス={0}", item.Target.FullName, @lastItem.EventType);

                        // ワークフロー処理中に発生するファイル更新イベントにより、更新キューに項目が追加されてしまうことを防ぐため、
                        // 処理中のファイルを更新キューから除外するための除外リストに、処理中のファイルを追加する。
                        //
                        // ※処理中のファイルがACLファイル以外の場合、対象ファイルのACLファイル名も除外リストに追加する
                        _IgnoreUpdateFiles.Enqueue(item.Target.FullName);
                        if (item.Target.Extension != ".aclgene")
                        {
                            _IgnoreUpdateFiles.Enqueue(item.Target.FullName + ".aclgene");
                        }

                        try
                        {
                            using (var dbc = new AppDbContext())
                            {
                                var workspace = WorkspaceRepository.Load(dbc, _Workspace.Id);
                                var workflow  = new WorkflowInvoker(new UpdateVirtualSpaceAppFlow());
                                workflow.Extensions.Add(new WorkflowExtention(dbc));
                                var pstack = new ParameterStack();

                                // 処理対象のファイルがACLファイルか、物理ファイルかで処理を切り分けます
                                // ■ACLファイルの場合
                                //    リネーム更新イベントに対応します。
                                // ■物理ファイルの場合
                                //    リネーム更新イベントも、UPDATEイベントとして処理します。
                                if (item.Target.Extension == ".aclgene")
                                {
                                    var fileNameWithputExtension = item.Target.Name.Replace(item.Target.Extension, "");
                                    switch (@lastItem.EventType)
                                    {
                                    case WatcherChangeTypes.Renamed:
                                        pstack.SetValue("Event", Mogami.Core.Constructions.UpdateVirtualStatusEventType.RENAME);
                                        pstack.SetValue(ActivityParameterStack.WORKSPACE_FILEINFO, item.Target);
                                        pstack.SetValue(ActivityParameterStack.WORKSPACE_FILEPATH, item.Target.Name);                                                 // リネーム後のファイル名
                                        pstack.SetValue(ActivityParameterStack.WORKSPACE, workspace);

                                        var results_renamed = workflow.Invoke(new Dictionary <string, object>
                                        {
                                            { "ParameterStack", pstack },
                                            //{"EventType", UpdateVirtualStatusEventType.RENAME},
                                            //{"Target", item.Target},
                                            //{"BeforeRenameName",item.OldRenameNamePath},
                                            //{"Workspace", workspace}
                                        });
                                        break;

                                    case WatcherChangeTypes.Changed:
                                    case WatcherChangeTypes.Created:
                                        var aclfileLocalPath = workspace.TrimWorekspacePath(item.Target.FullName, false);
                                        pstack.SetValue("Event", Mogami.Core.Constructions.UpdateVirtualStatusEventType.UPDATE);
                                        pstack.SetValue(ActivityParameterStack.WORKSPACE_FILEINFO, item.Target);
                                        pstack.SetValue(ActivityParameterStack.WORKSPACE_FILEPATH, aclfileLocalPath);                                                 // 移動後のファイルパス
                                        pstack.SetValue(ActivityParameterStack.WORKSPACE, workspace);
                                        var results_changed = workflow.Invoke(new Dictionary <string, object>
                                        {
                                            { "ParameterStack", pstack },
                                            //{"EventType", UpdateVirtualStatusEventType.UPDATE},
                                            //{"Target", item.Target},
                                            //{"Workspace", workspace}
                                        });
                                        break;

                                    case WatcherChangeTypes.Deleted:
                                        var aclfileLocalPath_Delete = workspace.TrimWorekspacePath(item.Target.FullName, false);
                                        pstack.SetValue("Event", Mogami.Core.Constructions.UpdateVirtualStatusEventType.DELETE);
                                        pstack.SetValue(ActivityParameterStack.WORKSPACE_FILEINFO, item.Target);
                                        pstack.SetValue(ActivityParameterStack.WORKSPACE_FILEPATH, aclfileLocalPath_Delete);                                                 // 削除したファイル
                                        pstack.SetValue(ActivityParameterStack.WORKSPACE, workspace);
                                        pstack.SetValue("WF_DeleteAclMappingFilePath", fileNameWithputExtension);

                                        var results_deleted = workflow.Invoke(new Dictionary <string, object>
                                        {
                                            { "ParameterStack", pstack },
                                            //{"EventType", UpdateVirtualStatusEventType.DELETE},
                                            //{"Target", item.Target},
                                            //{"DeleteAclHash", @pair.Key},
                                            //{"Workspace", workspace}
                                        });
                                        break;
                                    }
                                }
                                else
                                {
                                    if (File.Exists(item.Target.FullName))
                                    {
                                        switch (@lastItem.EventType)
                                        {
                                        case WatcherChangeTypes.Renamed:
                                        case WatcherChangeTypes.Changed:
                                        case WatcherChangeTypes.Created:
                                            var aclfileLocalPath_Update = workspace.TrimWorekspacePath(item.Target.FullName, false);
                                            pstack.SetValue("Event", Mogami.Core.Constructions.UpdateVirtualStatusEventType.UPDATE);
                                            pstack.SetValue(ActivityParameterStack.WORKSPACE_FILEINFO, item.Target);
                                            pstack.SetValue(ActivityParameterStack.WORKSPACE_FILEPATH, aclfileLocalPath_Update);                                                     // 削除したファイル
                                            pstack.SetValue(ActivityParameterStack.WORKSPACE, workspace);

                                            var results_changed = workflow.Invoke(new Dictionary <string, object>
                                            {
                                                { "ParameterStack", pstack },
                                                //{"EventType", UpdateVirtualStatusEventType.UPDATE},
                                                //{"Target", item.Target},
                                                //{"Workspace", workspace}
                                            });
                                            break;

                                        case WatcherChangeTypes.Deleted:
                                            var aclfileLocalPath_Delete = workspace.TrimWorekspacePath(item.Target.FullName, false);
                                            pstack.SetValue("Event", Mogami.Core.Constructions.UpdateVirtualStatusEventType.DELETE);
                                            pstack.SetValue(ActivityParameterStack.WORKSPACE_FILEINFO, item.Target);
                                            pstack.SetValue(ActivityParameterStack.WORKSPACE_FILEPATH, aclfileLocalPath_Delete);                                                     // 削除したファイル
                                            pstack.SetValue(ActivityParameterStack.WORKSPACE, workspace);

                                            var results_deleted = workflow.Invoke(new Dictionary <string, object>
                                            {
                                                { "ParameterStack", pstack },
                                                //{"EventType", UpdateVirtualStatusEventType.DELETE},
                                                //{"Target", item.Target},
                                                //{"Workspace", workspace}
                                            });
                                            break;
                                        }
                                    }
                                    else
                                    {
                                        LOG.InfoFormat("「{0}」は存在しない物理ファイルのため、処理をスキップします。", item.Target.FullName);
                                    }
                                }

                                dbc.SaveChanges();
                            }
                        }
                        catch (Exception expr)
                        {
                            LOG.ErrorFormat("タイマー処理時エラー = {0}", expr.Message);
                        }

                        // 処理を終了したファイルを、除外リストから削除します
                        string ignoreUpdateFile;
                        _IgnoreUpdateFiles.TryDequeue(out ignoreUpdateFile);
                        if (item.Target.Extension != ".aclgene")
                        {
                            _IgnoreUpdateFiles.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待機
                }
            }

            timer.Enabled = true;
        }