void ClearFilterTask() { // string strTempDir = this.GetTempDir(); string strTempDir = this.TempDir; List <FilterTask> delete_items = new List <FilterTask>(); _filterTaskLock.EnterWriteLock(); try { foreach (string key in this.FilterTasks.Keys) { FilterTask task = (FilterTask)this.FilterTasks[key]; if (task != null) { delete_items.Add(task); } } this.FilterTasks.Clear(); } finally { _filterTaskLock.ExitWriteLock(); } foreach (FilterTask task in delete_items) { task.DeleteTempFiles(strTempDir); } }
public FilterTask FindFilterTask(string strName) { _filterTaskLock.EnterReadLock(); try { FilterTask task = (FilterTask)this.FilterTasks[strName]; if (task != null) { task.Touch(); } return(task); } finally { _filterTaskLock.ExitReadLock(); } }
// parameters: // task 要设置的 FilterTask 对象。如果为 null,表示要删除名字为 strName 的对象 public void SetFilterTask(string strName, FilterTask task) { _filterTaskLock.EnterWriteLock(); try { FilterTask old_task = (FilterTask)this.FilterTasks[strName]; if (old_task == task) { if (old_task != null) { old_task.Touch(); } return; } // 删除任务所创建的结果集文件 if (old_task != null) { old_task.DeleteTempFiles( // this.GetTempDir() this.TempDir ); } // TODO: 是否要定义一个极限值,不让元素数超过这个数目 if (task == null) { this.FilterTasks.Remove(strName); } else { task.Touch(); this.FilterTasks[strName] = task; } } finally { _filterTaskLock.ExitWriteLock(); } }
// 根据记录数量的多少,少的时候可以立即返回结果,多的时候用线程后台处理,然后可以随时查询状态 // 线程用线程池,避免过多耗用线程数目 // 根据结果集名,提取全部书目XML记录,然后批处理经过MarcFilter过滤,创建若干个子结果集 // 最基本的功能是返回子结果集的显示名,文件名,包含记录数量,供前端显示在界面上 // 较为深入的功能是,将子结果集按照key排序归并,而显示出二级条目和数量。二级结果集是子结果集的子结果集 // TODO: 如何及时清理Task对象,避免内存过度膨胀? 是否仅保存最新10个Task对象? void GetFilterInfo( string strResultsetName, string strSelected, string strLang) { string strError = ""; GetFilterInfo result_info = new GetFilterInfo(); if (string.IsNullOrEmpty(strResultsetName) == true) { strError = "结果集名不应为空"; goto ERROR1; } #if NO Hashtable result_table = null; string strFilterFileName = PathUtil.MergePath(app.DataDir, "cfgs/facet.fltx"); int nRet = ResultsetFilter.DoFilter( app, sessioninfo.Channel, strResultsetName, strFilterFileName, 1000, ref result_table, out strError); if (nRet == -1) goto ERROR1; #endif FilterTask t = sessioninfo.FindFilterTask(strResultsetName); // Task对象是利用Session内结果集名来进行管理的 if (t == null) { // 如果一个结果集还没有被后台任务处理,就立即启动一个后台任务 t = new FilterTask(); sessioninfo.SetFilterTask(strResultsetName, t); string strGlobalResultSetName = ""; bool bShare = false; if (strResultsetName[0] == '#') strGlobalResultSetName = strResultsetName.Substring(1); else { // 构造全局结果集名 strGlobalResultSetName = sessioninfo.GetHashCode() + "_" + strResultsetName; // 先把结果集共享 // 管理结果集 // parameters: // strAction share/remove 分别表示共享为全局结果集对象/删除全局结果集对象 long lRet = sessioninfo.Channel.ManageSearchResult( null, "share", strResultsetName, strGlobalResultSetName, out strError); if (lRet == -1) goto ERROR1; bShare = true; } FilterTaskInput i = new FilterTaskInput(); i.App = app; i.FilterFileName = PathUtil.MergePath(app.DataDir, "cfgs/facet.fltx"); i.ResultSetName = strGlobalResultSetName; i.ShareResultSet = bShare; i.SessionInfo = sessioninfo; i.TaskName = strResultsetName; // Task对象是利用Session内结果集名来进行管理的 i.MaxCount = 1000; // i.aggregation_names = new List<string>() {"author"}; XmlDocument def_dom = GetFacetDefDom(out strError); if (def_dom == null) goto ERROR1; i.DefDom = def_dom; ThreadPool.QueueUserWorkItem(t.ThreadPoolCallBack, i); strError = "#pending"; // 表示正在处理,希望前端稍后重新访问 goto ERROR1; } else { if (t.TaskState == TaskState.Processing) { if (t.ProgressRange != 0) result_info.ProgressValue = (int)(((double)t.ProgressValue / (double)t.ProgressRange) * 100); strError = "#pending"; // 表示正在处理,希望前端稍后重新访问 goto ERROR1; } if (string.IsNullOrEmpty(t.ErrorInfo) == false) { strError = t.ErrorInfo; goto ERROR1; } #if NO string[] names = new string[t.ResultTable.Keys.Count]; t.ResultTable.Keys.CopyTo(names, 0); Array.Sort(names); List<FilterInfo> infos = new List<FilterInfo>(); foreach (string strName in names) { KeyValueCollection items = (KeyValueCollection)t.ResultTable[strName]; FilterInfo info = new FilterInfo(); info.Name = strName; if (items != null) info.Count = items.Count.ToString(); else info.Count = "0"; infos.Add(info); } result_info.Items = new FilterInfo[infos.Count]; infos.CopyTo(result_info.Items); #endif #if NO Hashtable keyname_table = null; // 获得名称对照表 // parameters: // keyname_table keyname --> 当前语言的名称 int nRet = ResultsetFilter.GetKeyNameTable( app, PathUtil.MergePath(app.DataDir, "cfgs/facet.fltx"), t.ResultItems, string.IsNullOrEmpty(strLang) == true ? Thread.CurrentThread.CurrentUICulture.Name : strLang, out keyname_table, out strError); if (nRet == -1) goto ERROR1; #endif long lHitCount = MyWebPage.GetServerResultCount(sessioninfo, strResultsetName); XmlDocument def_dom = GetFacetDefDom(out strError); if (def_dom == null) goto ERROR1; this.m_facetDom = def_dom; this.m_strLang = strLang; try { // 创建FilterInfo数组 result_info.Items = ResultsetFilter.BuildFilterInfos( strResultsetName, lHitCount, strSelected, GetKeyNameCaption, t.ResultItems, sessioninfo.GetTempDir(), 10); } catch (Exception ex) { strError = ex.Message; goto ERROR1; } if (t.HitCount > 1000) { result_info.Comment = "分面导航只提取了当前结果集的前 1000 条记录"; } } // 返回一级节点的名字和包含记录数量 this.Response.Write(MyWebPage.GetResultString(result_info)); this.Response.End(); return; ERROR1: result_info.ErrorString = strError; this.Response.Write(MyWebPage.GetResultString(result_info)); this.Response.End(); }
// 清除最近没有使用过的 FilterTask 对象 // parameters: // delta 最近一次用过的时刻距离现在的时间长度。长于这个的对象才会被清除 public void CleanFilterTask(TimeSpan delta) { List <string> remove_keys = new List <string>(); // 第一步,找出过期的 key // 读锁定并不阻碍一般性访问 _filterTaskLock.EnterReadLock(); try { foreach (string key in this.FilterTasks.Keys) { FilterTask task = (FilterTask)this.FilterTasks[key]; if (task == null || (DateTime.Now - task.LastUsedTime) >= delta) { remove_keys.Add(key); // 这里暂时无法删除,因为 foreach 还要用枚举器 } } } finally { _filterTaskLock.ExitReadLock(); } if (remove_keys.Count == 0) { return; } // 第二步,清除 hashtable 中的对象 // 因为要删除某些元素,所以用写锁定 List <FilterTask> delete_items = new List <FilterTask>(); _filterTaskLock.EnterWriteLock(); try { foreach (string key in remove_keys) { FilterTask task = (FilterTask)this.FilterTasks[key]; if (task == null) { continue; } // 和 hashtable 脱离关系 this.FilterTasks.Remove(key); delete_items.Add(task); } } finally { _filterTaskLock.ExitWriteLock(); } // 第三步,删除临时文件 string strTempDir = this.TempDir; foreach (FilterTask task in delete_items) { task.DeleteTempFiles(strTempDir); } }
public void SetFilterTask(string strName, FilterTask task) { lock (this.FilterTasks) { FilterTask old_task = (FilterTask)this.FilterTasks[strName]; if (old_task == task) return; // 删除任务所创建的结果集文件 if (old_task != null) old_task.DeleteTempFiles(this.GetTempDir()); if (task == null) this.FilterTasks.Remove(strName); else this.FilterTasks[strName] = task; } }
// 根据记录数量的多少,少的时候可以立即返回结果,多的时候用线程后台处理,然后可以随时查询状态 // 线程用线程池,避免过多耗用线程数目 // 根据结果集名,提取全部书目 XML 记录,然后批处理经过 MarcFilter 过滤,创建若干个子结果集 // 最基本的功能是返回子结果集的显示名,文件名,包含记录数量,供前端显示在界面上 // 较为深入的功能是,将子结果集按照 key 排序归并,而显示出二级条目和数量。二级结果集是子结果集的子结果集 // TODO: 如何及时清理Task对象,避免内存过度膨胀? 是否仅保存最新10个Task对象? void GetFilterInfo( string strResultsetName, string strSelected, string strLang) { string strError = ""; GetFilterInfo result_info = new GetFilterInfo(); if (string.IsNullOrEmpty(strResultsetName) == true) { strError = "结果集名不应为空"; goto ERROR1; } FilterTask t = app.FindFilterTask(strResultsetName); // Task对象是利用 Session 内结果集名来进行管理的 if (t == null) { // 如果一个结果集还没有被后台任务处理,就立即启动一个后台任务 t = new FilterTask(); app.SetFilterTask(strResultsetName, t); string strGlobalResultSetName = ""; bool bShare = false; if (strResultsetName[0] == '#') strGlobalResultSetName = strResultsetName.Substring(1); else { // 构造全局结果集名 strGlobalResultSetName = sessioninfo.GetHashCode() + "_" + strResultsetName; LibraryChannel channel = sessioninfo.GetChannel(true); try { // 先把结果集共享 // 管理结果集 // parameters: // strAction share/remove 分别表示共享为全局结果集对象/删除全局结果集对象 long lRet = // sessioninfo.Channel. channel.ManageSearchResult( null, "share", strResultsetName, strGlobalResultSetName, out strError); if (lRet == -1) goto ERROR1; bShare = true; } finally { sessioninfo.ReturnChannel(channel); } } FilterTaskInput i = new FilterTaskInput(); i.App = app; i.FilterFileName = Path.Combine(app.DataDir, "cfgs/facet.fltx"); i.ResultSetName = strGlobalResultSetName; i.ShareResultSet = bShare; // i.SessionInfo = sessioninfo; i.TempDir = app.TempDir; i.TaskName = strResultsetName; // Task对象是利用Session内结果集名来进行管理的 i.MaxCount = 1000; // i.aggregation_names = new List<string>() {"author"}; XmlDocument def_dom = GetFacetDefDom(out strError); if (def_dom == null) goto ERROR1; i.DefDom = def_dom; ThreadPool.QueueUserWorkItem(t.ThreadPoolCallBack, i); strError = "#pending"; // 表示正在处理,希望前端稍后重新访问 goto ERROR1; } else { if (t.TaskState == TaskState.Processing) { if (t.ProgressRange != 0) result_info.ProgressValue = (int)(((double)t.ProgressValue / (double)t.ProgressRange) * 100); strError = "#pending"; // 表示正在处理,希望前端稍后重新访问 goto ERROR1; } if (string.IsNullOrEmpty(t.ErrorInfo) == false) { strError = t.ErrorInfo; goto ERROR1; } GC.Collect(); // 试着释放 Hashtable 等 long lHitCount = MyWebPage.GetServerResultCount(sessioninfo, strResultsetName); XmlDocument def_dom = GetFacetDefDom(out strError); if (def_dom == null) goto ERROR1; this.m_facetDom = def_dom; this.m_strLang = strLang; try { // 创建FilterInfo数组 result_info.Items = ResultsetFilter.BuildFilterInfos( strResultsetName, lHitCount, strSelected, GetKeyNameCaption, t.ResultItems, app.TempDir, // sessioninfo.GetTempDir(), 10); // GC.Collect(); // 担心 DpResultSet 未能回收 } catch (Exception ex) { strError = ExceptionUtil.GetAutoText(ex); goto ERROR1; } if (t.HitCount > 1000) { result_info.Comment = "分面导航只提取了当前结果集的前 1000 条记录"; } } // 返回一级节点的名字和包含记录数量 this.Response.Write(MyWebPage.GetResultString(result_info)); this.Response.End(); return; ERROR1: result_info.ErrorString = strError; this.Response.Write(MyWebPage.GetResultString(result_info)); this.Response.End(); }
// parameters: // task 要设置的 FilterTask 对象。如果为 null,表示要删除名字为 strName 的对象 public void SetFilterTask(string strName, FilterTask task) { _filterTaskLock.EnterWriteLock(); try { FilterTask old_task = (FilterTask)this.FilterTasks[strName]; if (old_task == task) { if (old_task != null) old_task.Touch(); return; } // 删除任务所创建的结果集文件 if (old_task != null) old_task.DeleteTempFiles( // this.GetTempDir() this.TempDir ); // TODO: 是否要定义一个极限值,不让元素数超过这个数目 if (task == null) this.FilterTasks.Remove(strName); else { task.Touch(); this.FilterTasks[strName] = task; } } finally { _filterTaskLock.ExitWriteLock(); } }