public static BatchTaskStartInfo FromString(string strText) { BatchTaskStartInfo info = new BatchTaskStartInfo(); Hashtable table = StringUtil.ParseParameters(strText, ',', ':'); info.Param = (string)table["Param"]; info.BreakPoint = (string)table["BreakPoint"]; info.Start = (string)table["Start"]; info.Count = (string)table["Count"]; return(info); }
BatchTaskStartInfo GetContinueStartInfo(bool bContinueWhenError) { XmlDocument dom = new XmlDocument(); dom.LoadXml("<root continueWhenError=\"" + (bContinueWhenError ? "true" : "false") + "\" />"); BatchTaskStartInfo info = new BatchTaskStartInfo(); info.Param = dom.DocumentElement.OuterXml; return(info); }
static List <BatchTaskStartInfo> FromString(string strText) { List <BatchTaskStartInfo> results = new List <BatchTaskStartInfo>(); string[] segments = strText.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); foreach (string segment in segments) { BatchTaskStartInfo info = BatchTaskStartInfo.FromString(segment); results.Add(info); } return(results); }
public static BatchTaskStartInfo FromString(string strText) { BatchTaskStartInfo info = new BatchTaskStartInfo(); Hashtable table = StringUtil.ParseParameters(strText, ',', ':'); info.Param = (string)table["Param"]; info.BreakPoint = (string)table["BreakPoint"]; info.Start = (string)table["Start"]; info.Count = (string)table["Count"]; info.WaitForBegin = DomUtil.IsBooleanTrue((string)table["WaitForBegin"]); info.OutputParam = (string)table["OutputParam"]; return(info); }
BatchTaskStartInfo BuildStartInfo(ServerReplicationStart start, ServerReplicationParam param) { BatchTaskStartInfo info = new BatchTaskStartInfo(); if (start != null) { info.Start = start.ToString(); } if (param != null) { info.Param = param.ToString(); } return(info); }
// 一次操作循环 public override void Worker() { // 系统挂起的时候,不运行本线程 //if (this.App.HangupReason == HangupReason.LogRecover) // return; if (this.App.ContainsHangup("LogRecover") == true) { return; } if (this.App.PauseBatchTask == true) { return; } string strError = ""; BatchTaskStartInfo startinfo = this.StartInfo; if (startinfo == null) { startinfo = new BatchTaskStartInfo(); // 按照缺省值来 } long lStartIndex = 0; // 开始位置 string strStartFileName = ""; // 开始文件名 int nRet = ParseLogRecoverStart(startinfo.Start, out lStartIndex, out strStartFileName, out strError); if (nRet == -1) { this.AppendResultText("启动失败: " + strError + "\r\n"); return; } // bool bClearFirst = false; bool bContinueWhenError = false; nRet = ParseLogRecoverParam(startinfo.Param, out bClearFirst, out bContinueWhenError, out strError); if (nRet == -1) { this.AppendResultText("启动失败: " + strError + "\r\n"); return; } // 开始处理时的日期 string strEndDate = DateTimeUtil.DateTimeToString8(DateTime.Now); // 记忆当前最后一条操作日志记录的位置 // return: // -1 出错 // 0 日志文件不存在,或者记录数为 0 // >0 记录数 long lRecCount = GetOperLogCount(strEndDate, out strError); if (lRecCount == -1) { this.AppendResultText("启动失败: " + strError + "\r\n"); return; } this.App.WriteErrorLog(this.Name + " 任务启动。"); if (bClearFirst == true) { nRet = this.App.ChargingOperDatabase.Clear(out strError); if (nRet == -1) { this.AppendResultText("清除 ChargingOperDatabase 中全部记录时发生错误: " + strError + "\r\n"); return; } } bool bStart = false; if (String.IsNullOrEmpty(strStartFileName) == true) { // 做所有文件 bStart = true; } // 列出所有日志文件 DirectoryInfo di = new DirectoryInfo(this.App.OperLog.Directory); FileInfo[] fis = di.GetFiles("*.log"); Array.Sort(fis, (x, y) => { return((new CaseInsensitiveComparer()).Compare(((FileInfo)x).Name, ((FileInfo)y).Name)); }); foreach (FileInfo info in fis) { if (this.Stopped == true) { break; } string strFileName = info.Name; this.AppendResultText("检查文件 " + strFileName + "\r\n"); if (bStart == false) { // 从特定文件开始做 if (string.CompareOrdinal(strStartFileName, strFileName) <= 0) // 2015/9/12 从等号修改为 Compare { bStart = true; if (lStartIndex < 0) { lStartIndex = 0; } // lStartIndex = Convert.ToInt64(startinfo.Param); } } if (bStart == true) { long lMax = -1; if (strEndDate + ".log" == strFileName) { lMax = lRecCount; } nRet = DoOneLogFile(strFileName, lStartIndex, lMax, bContinueWhenError, out strError); if (nRet == -1) { goto ERROR1; } lStartIndex = 0; // 第一个文件以后的文件就全做了 } } this.AppendResultText("循环结束\r\n"); this.App.WriteErrorLog(this.Name + "恢复 任务结束。"); return; ERROR1: return; }
public override void Worker() { // 系统挂起的时候,不运行本线程 // 2007/12/18 //if (this.App.HangupReason == HangupReason.LogRecover) // return; if (this.App.ContainsHangup("LogRecover") == true) return; // 2012/2/4 if (this.App.PauseBatchTask == true) return; string strError = ""; BatchTaskStartInfo startinfo = this.StartInfo; if (startinfo == null) startinfo = new BatchTaskStartInfo(); // 按照缺省值来 // 通用启动参数 bool bLoop = true; int nRet = ParseDkywReplicationParam(startinfo.Param, out bLoop, out strError); if (nRet == -1) { this.AppendResultText("启动失败: " + strError + "\r\n"); return; } this.Loop = bLoop; string strID = ""; nRet = ParseDkywReplicationStart(startinfo.Start, out strID, out strError); if (nRet == -1) { this.AppendResultText("启动失败: " + strError + "\r\n"); this.Loop = false; return; } if (strID == "!breakpoint") { string strLastNumber = ""; bool bTempLoop = false; nRet = ReadLastNumber( out bTempLoop, out strLastNumber, out strError); if (nRet == -1) { string strErrorText = "从断点文件中获取最大号码时发生错误: " + strError; this.AppendResultText(strErrorText + "\r\n"); this.App.WriteErrorLog(strErrorText); return; } strID = strLastNumber; } try { // 把数据文件写入有映射关系的读者库 this.AppendResultText("同步读者数据开始\r\n"); string strMaxNumber = ""; // 返回操作末尾的最大号 try { // return: // -1 error // 0 succeed // 1 中断 nRet = WriteToReaderDb(strID, out strMaxNumber, out strError); } finally { // 写入文件,记忆已经做过的最大号码 // 要用bLoop,这是来自启动面板的值;不能用this.Loop 因为中断时其值已经被改变 if (String.IsNullOrEmpty(strMaxNumber) == true) { // 如果运行出错或者根本没有新源记录,连一条也没有成功作过,就保持原来的断点记录号 // 如果写入的断点记录号是空,下次运行的时候,将从'1'开始。这一般是不能接受的 WriteLastNumber(bLoop, strID); } else WriteLastNumber(bLoop, strMaxNumber); } if (nRet == -1) { string strErrorText = "写入读者库: " + strError; this.AppendResultText(strErrorText + "\r\n"); this.App.WriteErrorLog(strErrorText); return; } else if (nRet == 1) { this.AppendResultText("同步读者数据被中断\r\n"); return; } else { this.AppendResultText("同步读者数据完成\r\n"); Debug.Assert(this.App != null, ""); } this.AppendResultText("兑现黑名单开始\r\n"); // 将黑名单中的卡挂失入读者库 // parameters: // return: // -1 error // 0 succeed // 1 中断 nRet = DoBlackList(out strError); if (nRet == -1) { string strErrorText = "兑现黑名单: " + strError; this.AppendResultText(strErrorText + "\r\n"); this.App.WriteErrorLog(strErrorText); return; } else if (nRet == 1) { this.AppendResultText("兑现黑名单被中断\r\n"); return; } else { this.AppendResultText("兑现黑名单完成\r\n"); Debug.Assert(this.App != null, ""); } } finally { this.StartInfo.Start = "!breakpoint"; // 自动循环的时候,没有号码,要从断点文件中取得 } }
// 一次操作循环 public override void Worker() { // 系统挂起的时候,不运行本线程 if (this.App.ContainsHangup("LogRecover") == true) { return; } if (this.App.PauseBatchTask == true) { return; } this.Loop = true; // 2017/10/16 BatchTaskStartInfo startinfo = this.StartInfo; if (startinfo == null) { startinfo = new BatchTaskStartInfo(); // 按照缺省值来 } string strError = ""; int nRet = 0; ServerReplicationStart start = ServerReplicationStart.FromString(startinfo.Start); ServerReplicationParam param = ServerReplicationParam.FromString(startinfo.Param); #if NO long lStartIndex = 0; // 开始位置 string strStartFileName = ""; // 开始文件名 nRet = ParseReplicationStart(startinfo.Start, out lStartIndex, out strStartFileName, out strError); if (nRet == -1) { this.AppendResultText("启动失败: " + strError + "\r\n"); return; } // string strRecoverLevel = ""; bool bClearFirst = false; bool bContinueWhenError = false; nRet = ParseReplicationParam(startinfo.Param, out strRecoverLevel, out bClearFirst, out bContinueWhenError, out strError); if (nRet == -1) { this.AppendResultText("启动失败: " + strError + "\r\n"); return; } #endif this.App.WriteErrorLog(this.Name + " 任务启动。"); // 获得源 dp2library 服务器配置信息 { nRet = GetSourceServerCfg(out strError); if (nRet == -1) { goto ERROR1; } nRet = CheckUID(out strError); if (nRet == -1) { goto ERROR1; } } #if NO // 当为容错恢复级别时,检查当前全部读者库的检索点是否符合要求 if (this.RecoverLevel == LibraryServer.RecoverLevel.Robust) { // 检查全部读者库的检索途径,看是否满足都有“所借册条码号”这个检索途径的这个条件 // return: // -1 出错 // 0 不满足 // 1 满足 nRet = this.App.DetectReaderDbFroms(out strError); if (nRet == -1) { this.AppendResultText("检查读者库检索点时发生错误: " + strError + "\r\n"); return; } if (nRet == 0) { this.AppendResultText("在容错恢复级别下,当前读者库中有部分或全部读者库缺乏“所借册条码号”检索点,无法进行日志恢复。请按照日志恢复要求,刷新所有读者库的检索点配置,然后再进行日志恢复\r\n"); return; } } #endif // TODO: 检查当前是否有 重建检索点 的后台任务正在运行,或者还有没有运行完的部分。 // 要求重建检索点的任务运行完以后才能执行日志恢复任务 #if NO if (bClearFirst == true) { nRet = this.App.ClearAllDbs(this.RmsChannels, out strError); if (nRet == -1) { this.AppendResultText("清除全部数据库记录时发生错误: " + strError + "\r\n"); return; } } #endif // 进行处理 // BreakPointInfo breakpoint = null; #if NO if (string.IsNullOrEmpty(start.StartFileName) == false && start.StartFileName != "continue") { breakpoint = new BreakPointInfo(start.StartFileName.Substring(0, 8), start.StartIndex); } #endif this.AppendResultText("*********\r\n"); if (start.Date == "continue" || string.IsNullOrEmpty(start.Date)) { // 按照断点信息处理 this.AppendResultText("从上次断点位置继续\r\n"); // return: // -1 出错 // 0 没有发现断点信息 // 1 成功 nRet = ReadBreakPoint(out start, out param, out strError); if (nRet == -1) { goto ERROR1; } if (nRet == 0) { // return; goto ERROR1; } // 此后返回前可以用 start 写入断点文件了 } else { // 先从远端复制整个数据库,然后从开始复制时的日志末尾进行同步 this.AppendResultText("指定的数据库\r\n"); // 采纳先前创建好的复制并继续的断点信息 } Debug.Assert(start != null, ""); this.AppendResultText("计划进行的处理:\r\n---\r\n" + start.GetSummary() + "\r\n---\r\n\r\n"); // TODO: 处理中途可以定期保存断点文件,这样可以在掉电等情况下也能尽量保证后续从断点位置附近开始处理 // return: // -1 出错 // 0 中断 // 1 完成 nRet = ProcessOperLogs(start, param.ContinueWhenError, (s) => { SaveBreakPoint(s, param); }, param == null ? "" : param.Style, out strError); if (nRet == -1 || nRet == 0) { // 保存断点文件 // 迫使后面循环处理的时候,从断点位置继续 goto ERROR2; } #if NO bool bStart = false; if (String.IsNullOrEmpty(strStartFileName) == true) { // 做所有文件 bStart = true; } // 列出所有日志文件 DirectoryInfo di = new DirectoryInfo(this.App.OperLog.Directory); FileInfo[] fis = di.GetFiles("*.log"); // BUG!!! 以前缺乏排序。2008/2/1 Array.Sort(fis, new FileInfoCompare()); for (int i = 0; i < fis.Length; i++) { if (this.Stopped == true) { break; } string strFileName = fis[i].Name; this.AppendResultText("检查文件 " + strFileName + "\r\n"); if (bStart == false) { // 从特定文件开始做 if (string.CompareOrdinal(strStartFileName, strFileName) <= 0) // 2015/9/12 从等号修改为 Compare { bStart = true; if (lStartIndex < 0) { lStartIndex = 0; } // lStartIndex = Convert.ToInt64(startinfo.Param); } } if (bStart == true) { nRet = DoOneLogFile(strFileName, lStartIndex, bContinueWhenError, out strError); if (nRet == -1) { goto ERROR1; } lStartIndex = 0; // 第一个文件以后的文件就全做了 } } #endif this.AppendResultText("循环结束\r\n"); this.App.WriteErrorLog("日志恢复 任务结束。"); // 保存断点文件 SaveBreakPoint(start, param); this.StartInfo = BuildStartInfo(null, param); // 迫使后面循环处理的时候,从断点位置继续 return; ERROR1: this.AppendResultText(strError + "\r\n任务因出错而中断。\r\n"); return; ERROR2: // 保存断点文件 SaveBreakPoint(start, param); this.StartInfo = BuildStartInfo(null, param); // 迫使后面循环处理的时候,从断点位置继续 this.AppendResultText(strError + "\r\n任务因出错而中断。\r\n"); return; }
public static BatchTaskStartInfo FromString(string strText) { BatchTaskStartInfo info = new BatchTaskStartInfo(); Hashtable table = StringUtil.ParseParameters(strText, ',', ':'); info.Param = (string)table["Param"] ; info.BreakPoint = (string)table["BreakPoint"]; info.Start = (string)table["Start"]; info.Count = (string)table["Count"]; return info; }
// 一次操作循环 public override void Worker() { // 把系统挂起 // this.App.HangupReason = HangupReason.LogRecover; this.App.HangupList.Add("LogRecover"); try { string strError = ""; BatchTaskStartInfo startinfo = this.StartInfo; if (startinfo == null) { startinfo = new BatchTaskStartInfo(); // 按照缺省值来 } long lStartIndex = 0; // 开始位置 string strStartFileName = ""; // 开始文件名 int nRet = ParseLogRecorverStart(startinfo.Start, out lStartIndex, out strStartFileName, out strError); if (nRet == -1) { this.AppendResultText("启动失败: " + strError + "\r\n"); return; } // string strRecoverLevel = ""; bool bClearFirst = false; bool bContinueWhenError = false; nRet = ParseLogRecoverParam(startinfo.Param, out strRecoverLevel, out bClearFirst, out bContinueWhenError, out strError); if (nRet == -1) { this.AppendResultText("启动失败: " + strError + "\r\n"); return; } if (String.IsNullOrEmpty(strRecoverLevel) == true) { strRecoverLevel = "Snapshot"; } try { this.RecoverLevel = (RecoverLevel)Enum.Parse(typeof(RecoverLevel), strRecoverLevel, true); } catch (Exception ex) { this.AppendResultText("启动失败: 启动参数Param中的recoverLevel枚举值 '" + strRecoverLevel + "' 错误: " + ex.Message + "\r\n"); return; } this.App.WriteErrorLog("日志恢复 任务启动。"); // 当为容错恢复级别时,检查当前全部读者库的检索点是否符合要求 if (this.RecoverLevel == LibraryServer.RecoverLevel.Robust) { // 检查全部读者库的检索途径,看是否满足都有“所借册条码号”这个检索途径的这个条件 // return: // -1 出错 // 0 不满足 // 1 满足 nRet = this.App.DetectReaderDbFroms(out strError); if (nRet == -1) { this.AppendResultText("检查读者库检索点时发生错误: " + strError + "\r\n"); return; } if (nRet == 0) { this.AppendResultText("在容错恢复级别下,当前读者库中有部分或全部读者库缺乏“所借册条码号”检索点,无法进行日志恢复。请按照日志恢复要求,刷新所有读者库的检索点配置,然后再进行日志恢复\r\n"); return; } } // TODO: 检查当前是否有 重建检索点 的后台任务正在运行,或者还有没有运行完的部分。 // 要求重建检索点的任务运行完以后才能执行日志恢复任务 if (bClearFirst == true) { nRet = this.App.ClearAllDbs(this.RmsChannels, out strError); if (nRet == -1) { this.AppendResultText("清除全部数据库记录时发生错误: " + strError + "\r\n"); return; } } bool bStart = false; if (String.IsNullOrEmpty(strStartFileName) == true) { // 做所有文件 bStart = true; } // 列出所有日志文件 DirectoryInfo di = new DirectoryInfo(this.App.OperLog.Directory); FileInfo[] fis = di.GetFiles("*.log"); // BUG!!! 以前缺乏排序。2008/2/1 Array.Sort(fis, new FileInfoCompare()); for (int i = 0; i < fis.Length; i++) { if (this.Stopped == true) { break; } string strFileName = fis[i].Name; this.AppendResultText("检查文件 " + strFileName + "\r\n"); if (bStart == false) { // 从特定文件开始做 if (string.CompareOrdinal(strStartFileName, strFileName) <= 0) // 2015/9/12 从等号修改为 Compare { bStart = true; if (lStartIndex < 0) { lStartIndex = 0; } // lStartIndex = Convert.ToInt64(startinfo.Param); } } if (bStart == true) { nRet = DoOneLogFile(strFileName, lStartIndex, bContinueWhenError, out strError); if (nRet == -1) { goto ERROR1; } lStartIndex = 0; // 第一个文件以后的文件就全做了 } } this.AppendResultText("循环结束\r\n"); this.App.WriteErrorLog("日志恢复 任务结束。"); return; ERROR1: return; } finally { // this.App.HangupReason = HangupReason.None; this.App.ClearHangup("LogRecover"); } }
// TODO: 如果当前任务正在运行, 需要把新的任务追加到末尾继续运行 int StartRebuildKeysTask(string strDbNameList, out string strError) { strError = ""; BatchTaskInfo info = null; // 参数原始存储的时候,为了避免在参数字符串中发生混淆,数据库名之间用 | 间隔 if (string.IsNullOrEmpty(strDbNameList) == false) strDbNameList = strDbNameList.Replace(",", "|"); BatchTaskStartInfo start_info = new BatchTaskStartInfo(); start_info.Start = "dbnamelist=" + strDbNameList; BatchTaskInfo param = new BatchTaskInfo(); param.StartInfo = start_info; int nRet = StartBatchTask("重建检索点", param, out info, out strError); if (nRet == -1) return -1; return 0; }
internal static string GetSummary(BatchTaskStartInfo info) { return(info.Start); }
// 一次操作循环 public override void Worker() { // 系统挂起的时候,不运行本线程 if (this.App.ContainsHangup("LogRecover") == true) { return; } if (this.App.PauseBatchTask == true) { return; } // REDO_TASK: try { string strError = ""; int nRet = 0; if (this.App.LibraryCfgDom == null || this.App.LibraryCfgDom.DocumentElement == null) { return; } BatchTaskStartInfo startinfo = this.StartInfo; if (startinfo == null) { startinfo = new BatchTaskStartInfo(); // 按照缺省值来 } BackupTaskStart param = BackupTaskStart.FromString(startinfo.Start); string strDbNameList = param.DbNameList; #if NO string strDbNameList = ""; int nRet = ParseStart(startinfo.Start, out strDbNameList, out strError); if (nRet == -1) { this.AppendResultText("启动失败: " + strError + "\r\n"); return; } #endif // 下一次 loop 进入的时候自动就是 continue (从断点继续) startinfo.Start = ""; #if NO // string strFunction = ""; nRet = ParseTaskParam(startinfo.Param, out strFunction, out strError); if (nRet == -1) { this.AppendResultText("启动失败: " + strError + "\r\n"); return; } #endif // if (String.IsNullOrEmpty(strDbNameList) == true) if (strDbNameList == "continue") { // 从断点继续循环 strDbNameList = "continue"; } string strRecPathFileName = Path.Combine(this.App.BackupDir, "recpath.txt"); string strBackupFileName = ""; if (string.IsNullOrEmpty(param.BackupFileName) == true) { strBackupFileName = Path.Combine(this.App.BackupDir, this.App.LibraryName + "_" + BackupTaskStart.GetDefaultBackupFileName()); } else { strBackupFileName = Path.Combine(this.App.BackupDir, CanonializeBackupFileName(param.BackupFileName)); } // 构造用于复制然后同步的断点信息 // BreakPointCollection all_breakpoints = BreakPointCollection.BuildFromDbNameList(strDbNameList, strFunction); // 进行处理 BreakPointInfo breakpoint = null; this.AppendResultText("*********\r\n"); RmsChannel channel = this.RmsChannels.GetChannel(this.App.WsUrl); if (strDbNameList == "continue") { // 按照断点信息处理 this.AppendResultText("从上次断点位置继续\r\n"); // return: // -1 出错 // 0 没有发现断点信息 // 1 成功 nRet = ReadBreakPoint(out breakpoint, out strError); if (nRet == -1) { goto ERROR1; } if (nRet == 0) { // return; // TODO: 此时如何让等待结束?并且返回启动出错信息 goto ERROR1; } strBackupFileName = breakpoint.BackupFileName; if (string.IsNullOrEmpty(strBackupFileName)) { strError = "从上次断点开始运行时,发现 BackupFileName 为空,只好放弃运行"; goto ERROR1; } // WriteStateFile(strBackupFileName, "creating"); // 表示文件正在创建中 PrepareBackupFileName(strBackupFileName, true); this.AppendResultText("(从断点继续)本次大备份文件为 " + strBackupFileName + "\r\n"); } else { { BreakPointInfo temp_breakpoint = null; // 删除上次的大备份文件 // return: // -1 出错 // 0 没有发现断点信息 // 1 成功 nRet = ReadBreakPoint(out temp_breakpoint, out strError); if (nRet == -1) { goto ERROR1; } if (nRet == 1) { string strLastBackupFileName = temp_breakpoint.BackupFileName; if (string.IsNullOrEmpty(strLastBackupFileName) == false) { DeleteDataFiles(strLastBackupFileName); this.AppendResultText("自动删除上次创建的大备份文件 " + strLastBackupFileName + "\r\n"); } } temp_breakpoint = null; } // 先从远端复制整个数据库,然后从开始复制时的日志末尾进行同步 this.AppendResultText("指定的数据库\r\n"); DeleteDataFiles(strBackupFileName); PrepareBackupFileName(strBackupFileName, false); this.AppendResultText("本次大备份文件为 " + strBackupFileName + "\r\n"); // 采纳先前创建好的复制并继续的断点信息 // breakpoints = all_breakpoints; // 建立数据库定义文件 { string strDefFileName = GetDatabaseDefFileName(strBackupFileName); nRet = CreateDatabaseDefFile(channel, strDbNameList, strDefFileName, out strError); if (nRet == -1) { this.AppendResultText("创建数据库定义文件失败: " + strError + "\r\n"); WriteStateFile(strDefFileName, null); // 表示文件创建出错 return; } } // 建立要获取的记录路径文件 nRet = CreateRecPathFile(channel, strDbNameList, strRecPathFileName, out strError); if (nRet == -1) { this.AppendResultText("创建记录路径文件失败: " + strError + "\r\n"); WriteStateFile(strBackupFileName, null); // 表示文件创建出错 return; } } // Debug.Assert(breakpoints != null, ""); this.AppendResultText("计划进行的处理:\r\n---\r\n" + (breakpoint == null ? "备份全部数据库" : breakpoint.GetSummary()) + "\r\n---\r\n\r\n"); m_nRecordCount = 0; BreakPointInfo output_breakpoint = null; // for (int i = 0; i < breakpoints.Count; i++) { // BreakPointInfo info = breakpoints[i]; // return: // -1 出错 // 0 处理被中断 // 1 成功 nRet = BackupDatabase( channel, strRecPathFileName, breakpoint, strBackupFileName, out output_breakpoint, out strError); if (nRet == -1 || nRet == 0) { // 保存断点文件 SaveBreakPoint(output_breakpoint, true); goto ERROR1; } // breakpoints.Remove(info); // i--; // 保存断点文件 SaveBreakPoint(output_breakpoint, false); try { File.Delete(strRecPathFileName); } catch { } } // TODO: 如果集合为空,需要删除断点信息文件 // 正常结束,复位断点 if (this.StartInfos.Count == 0) { // this.App.RemoveBatchTaskBreakPointFile(this.Name); this.ClearTask(); } this.StartInfo.Start = ""; // AppendResultText("针对消息库 " + strMessageDbName + " 的循环结束。共处理 " + nRecCount.ToString() + " 条记录。\r\n"); // TODO: 在断点文件中记载 StartInfos 内容 this.AppendResultText("大备份结束。结果在文件 " + strBackupFileName + " 中\r\n"); #if NO { // return: // -1 出错 // 0 没有发现断点信息 // 1 成功 nRet = ReadBreakPoint(out breakpoints, out strError); if (nRet == -1) { goto ERROR1; } // 如果有累积的任务,还需要继续执行 if (nRet == 1 && this.StartInfos.Count > 0) { this.StartInfo = this.StartInfos[0]; this.StartInfos.RemoveAt(0); goto REDO_TASK; } } #endif DoPendingCommands(strBackupFileName); return; ERROR1: this.ErrorInfo = strError; this.AppendResultText(strError + "\r\n"); this.SetProgressText(strError); DoPendingCommands(strBackupFileName); return; } finally { } }
// 一次操作循环 public override void Worker() { // 把系统挂起 this.App.HangupReason = HangupReason.LogRecover; try { string strError = ""; BatchTaskStartInfo startinfo = this.StartInfo; if (startinfo == null) startinfo = new BatchTaskStartInfo(); // 按照缺省值来 long lStartIndex = 0;// 开始位置 string strStartFileName = "";// 开始文件名 int nRet = ParseLogRecorverStart(startinfo.Start, out lStartIndex, out strStartFileName, out strError); if (nRet == -1) { this.AppendResultText("启动失败: " + strError + "\r\n"); return; } // string strRecoverLevel = ""; bool bClearFirst = false; nRet = ParseLogRecoverParam(startinfo.Param, out strRecoverLevel, out bClearFirst, out strError); if (nRet == -1) { this.AppendResultText("启动失败: " + strError + "\r\n"); return; } if (String.IsNullOrEmpty(strRecoverLevel) == true) strRecoverLevel = "Snapshot"; try { this.RecoverLevel = (RecoverLevel)Enum.Parse(typeof(RecoverLevel), strRecoverLevel, true); } catch (Exception ex) { this.AppendResultText("启动失败: 启动参数Param中的recoverLevel枚举值 '" + strRecoverLevel + "' 错误: " + ex.Message + "\r\n"); return; } this.App.WriteErrorLog("日志恢复 任务启动。"); if (bClearFirst == true) { nRet = this.App.ClearAllDbs(this.RmsChannels, out strError); if (nRet == -1) { this.AppendResultText("清除全部数据库记录时发生错误: " + strError + "\r\n"); return; } } bool bStart = false; if (String.IsNullOrEmpty(strStartFileName) == true) { // 做所有文件 bStart = true; } // 列出所有日志文件 DirectoryInfo di = new DirectoryInfo(this.App.OperLog.Directory); FileInfo[] fis = di.GetFiles("*.log"); // BUG!!! 以前缺乏排序。2008/2/1 Array.Sort(fis, new FileInfoCompare()); for (int i = 0; i < fis.Length; i++) { if (this.Stopped == true) break; string strFileName = fis[i].Name; this.AppendResultText("检查文件 " + strFileName + "\r\n"); if (bStart == false) { // 从特定文件开始做 if (string.CompareOrdinal(strStartFileName, strFileName) <= 0) // 2015/9/12 从等号修改为 Compare { bStart = true; if (lStartIndex < 0) lStartIndex = 0; // lStartIndex = Convert.ToInt64(startinfo.Param); } } if (bStart == true) { nRet = DoOneLogFile(strFileName, lStartIndex, out strError); if (nRet == -1) goto ERROR1; lStartIndex = 0; // 第一个文件以后的文件就全做了 } } this.AppendResultText("循环结束\r\n"); this.App.WriteErrorLog("日志恢复 任务结束。"); return; ERROR1: return; } finally { this.App.HangupReason = HangupReason.None; } }
// 一次操作循环 public override void Worker() { // 系统挂起的时候,不运行本线程 // 2007/12/18 if (this.App.HangupReason == HangupReason.LogRecover) return; // 2012/2/4 if (this.App.PauseBatchTask == true) return; bool bFirst = true; string strError = ""; int nRet = 0; BatchTaskStartInfo startinfo = this.StartInfo; if (startinfo == null) startinfo = new BatchTaskStartInfo(); // 按照缺省值来 // 通用启动参数 bool bLoop = true; nRet = ParseMessageMonitorParam(startinfo.Param, out bLoop, out strError); if (nRet == -1) { this.AppendResultText("启动失败: " + strError + "\r\n"); return; } this.Loop = bLoop; string strID = ""; nRet = ParseMessageMonitorStart(startinfo.Start, out strID, out strError); if (nRet == -1) { this.AppendResultText("启动失败: " + strError + "\r\n"); this.Loop = false; return; } // bool bPerDayStart = false; // 是否为每日一次启动模式 string strMonitorName = "messageMonitor"; { string strLastTime = ""; nRet = ReadLastTime( strMonitorName, out strLastTime, out strError); if (nRet == -1) { string strErrorText = "从文件中获取 " + strMonitorName + " 每日启动时间时发生错误: " + strError; this.AppendResultText(strErrorText + "\r\n"); this.App.WriteErrorLog(strErrorText); return; } string strStartTimeDef = ""; // bRet 是否到了每日启动时间 bool bRet = false; string strOldLastTime = strLastTime; // return: // -1 error // 0 没有找到startTime配置参数 // 1 找到了startTime配置参数 nRet = IsNowAfterPerDayStart( strMonitorName, ref strLastTime, out bRet, out strStartTimeDef, out strError); if (nRet == -1) { string strErrorText = "获取 " + strMonitorName + " 每日启动时间时发生错误: " + strError; this.AppendResultText(strErrorText + "\r\n"); this.App.WriteErrorLog(strErrorText); return; } // 如果nRet == 0,表示没有配置相关参数,则兼容原来的习惯,每次都作 if (nRet == 0) { } else if (nRet == 1) { if (bRet == false) { if (this.ManualStart == true) this.AppendResultText("已试探启动任务 '" + this.Name + "',但因没有到每日启动时间 " + strStartTimeDef + " 而未能启动。(上次任务处理结束时间为 " + DateTimeUtil.LocalTime(strLastTime) + ")\r\n"); // 2014/3/31 if (string.IsNullOrEmpty(strOldLastTime) == true && string.IsNullOrEmpty(strLastTime) == false) { this.AppendResultText("史上首次启动此任务。已把当前时间当作上次任务处理结束时间 " + DateTimeUtil.LocalTime(strLastTime) + " 写入了断点记忆文件\r\n"); WriteLastTime(strMonitorName, strLastTime); } return; // 还没有到每日时间 } bPerDayStart = true; } this.App.WriteErrorLog((bPerDayStart == true ? "(定时)" : "(不定时)") + strMonitorName + " 启动。"); } AppendResultText("开始新一轮循环"); RmsChannel channel = this.RmsChannels.GetChannel(this.App.WsUrl); string strMessageDbName = this.App.MessageDbName; if (String.IsNullOrEmpty(strMessageDbName) == true) { AppendResultText("尚未配置消息库名(<message dbname='...' />)"); this.Loop = false; return; } if (String.IsNullOrEmpty(this.App.MessageReserveTimeSpan) == true) { AppendResultText("尚未配置消息保留期限(<message reserveTimeSpan='...' />"); this.Loop = false; return; } // 解析期限值 string strPeriodUnit = ""; long lPeriodValue = 0; nRet = LibraryApplication.ParsePeriodUnit( this.App.MessageReserveTimeSpan, out lPeriodValue, out strPeriodUnit, out strError); if (nRet == -1) { strError = "消息保留期限 值 '" + this.App.MessageReserveTimeSpan + "' 格式错误: " + strError; AppendResultText(strError); this.Loop = false; return; } AppendResultText("开始处理消息库 " + strMessageDbName + " 的循环"); // string strID = "1"; int nRecCount = 0; for (; ; nRecCount++) { // 系统挂起的时候,不运行本线程 // 2008/2/4 if (this.App.HangupReason == HangupReason.LogRecover) break; // 2012/2/4 if (this.App.PauseBatchTask == true) break; if (this.Stopped == true) break; string strStyle = ""; strStyle = "data,content,timestamp,outputpath"; if (bFirst == true) strStyle += ""; else { strStyle += ",next"; } string strPath = strMessageDbName + "/" + strID; string strXmlBody = ""; string strMetaData = ""; string strOutputPath = ""; byte[] baOutputTimeStamp = null; // SetProgressText((nRecCount + 1).ToString() + " " + strPath); // 获得资源 // return: // -1 出错。具体出错原因在this.ErrorCode中。this.ErrorInfo中有出错信息。 // 0 成功 long lRet = channel.GetRes(strPath, strStyle, out strXmlBody, out strMetaData, out baOutputTimeStamp, out strOutputPath, out strError); if (lRet == -1) { if (channel.ErrorCode == ChannelErrorCode.NotFound) { if (bFirst == true) { // 第一条没有找到, 但是要强制循环进行 bFirst = false; goto CONTINUE; } else { if (bFirst == true) { strError = "数据库 " + strMessageDbName + " 记录 " + strID + " 不存在。处理结束。"; } else { strError = "数据库 " + strMessageDbName + " 记录 " + strID + " 是最末一条记录。处理结束。"; } break; } } else if (channel.ErrorCode == ChannelErrorCode.EmptyRecord) { bFirst = false; // 把id解析出来 strID = ResPath.GetRecordId(strOutputPath); goto CONTINUE; } goto ERROR1; } bFirst = false; // 把id解析出来 strID = ResPath.GetRecordId(strOutputPath); try { // 处理 nRet = DoOneRecord( lPeriodValue, strPeriodUnit, strOutputPath, strXmlBody, baOutputTimeStamp, out strError); } catch (Exception ex) { strError = "DoOneRecord exception: " + ExceptionUtil.GetDebugText(ex); this.AppendResultText(strError + "\r\n"); this.SetProgressText(strError); nRet = -1; } if (nRet == -1) { AppendResultText("DoOneRecord() error : " + strError + "。\r\n"); } CONTINUE: continue; } // end of for // 正常结束,复位断点 this.App.RemoveBatchTaskBreakPointFile(this.Name); this.StartInfo.Start = ""; AppendResultText("针对消息库 " + strMessageDbName + " 的循环结束。共处理 " + nRecCount.ToString() + " 条记录。\r\n"); { Debug.Assert(this.App != null, ""); // 写入文件,记忆已经做过的当日时间 string strLastTime = DateTimeUtil.Rfc1123DateTimeStringEx(this.App.Clock.UtcNow.ToLocalTime()); // 2007/12/17 changed // DateTime.UtcNow // 2012/5/27 WriteLastTime(strMonitorName, strLastTime); string strErrorText = (bPerDayStart == true ? "(定时)" : "(不定时)") + strMonitorName + "结束。共处理记录 " + nRecCount.ToString() + " 个。"; this.App.WriteErrorLog(strErrorText); } return; ERROR1: // 记忆断点 this.StartInfo.Start = MemoBreakPoint( strID //strRecordID, ); this.Loop = true; // 便于稍后继续重新循环? startinfo.Param = MakeMessageMonitorParam( bLoop); AppendResultText("MessageMonitor thread error : " + strError + "\r\n"); this.App.WriteErrorLog("MessageMonitor thread error : " + strError + "\r\n"); return; }
// 一次操作循环 public override void Worker() { // 系统挂起的时候,不运行本线程 //if (this.App.HangupReason == HangupReason.LogRecover) // return; if (this.App.ContainsHangup("LogRecover") == true) return; if (this.App.PauseBatchTask == true) return; string strError = ""; BatchTaskStartInfo startinfo = this.StartInfo; if (startinfo == null) startinfo = new BatchTaskStartInfo(); // 按照缺省值来 long lStartIndex = 0;// 开始位置 string strStartFileName = "";// 开始文件名 int nRet = ParseLogRecorverStart(startinfo.Start, out lStartIndex, out strStartFileName, out strError); if (nRet == -1) { this.AppendResultText("启动失败: " + strError + "\r\n"); return; } // bool bClearFirst = false; bool bContinueWhenError = false; nRet = ParseLogRecoverParam(startinfo.Param, out bClearFirst, out bContinueWhenError, out strError); if (nRet == -1) { this.AppendResultText("启动失败: " + strError + "\r\n"); return; } // 开始处理时的日期 string strEndDate = DateTimeUtil.DateTimeToString8(DateTime.Now); // 记忆当前最后一条操作日志记录的位置 // return: // -1 出错 // 0 日志文件不存在,或者记录数为 0 // >0 记录数 long lRecCount = GetOperLogCount(strEndDate, out strError); if (lRecCount == -1) { this.AppendResultText("启动失败: " + strError + "\r\n"); return; } this.App.WriteErrorLog(this.Name + " 任务启动。"); if (bClearFirst == true) { nRet = this.App.ChargingOperDatabase.Clear(out strError); if (nRet == -1) { this.AppendResultText("清除 ChargingOperDatabase 中全部记录时发生错误: " + strError + "\r\n"); return; } } bool bStart = false; if (String.IsNullOrEmpty(strStartFileName) == true) { // 做所有文件 bStart = true; } // 列出所有日志文件 DirectoryInfo di = new DirectoryInfo(this.App.OperLog.Directory); FileInfo[] fis = di.GetFiles("*.log"); Array.Sort(fis, (x, y) => { return ((new CaseInsensitiveComparer()).Compare(((FileInfo)x).Name, ((FileInfo)y).Name)); }); foreach (FileInfo info in fis) { if (this.Stopped == true) break; string strFileName = info.Name; this.AppendResultText("检查文件 " + strFileName + "\r\n"); if (bStart == false) { // 从特定文件开始做 if (string.CompareOrdinal(strStartFileName, strFileName) <= 0) // 2015/9/12 从等号修改为 Compare { bStart = true; if (lStartIndex < 0) lStartIndex = 0; // lStartIndex = Convert.ToInt64(startinfo.Param); } } if (bStart == true) { long lMax = -1; if (strEndDate + ".log" == strFileName) lMax = lRecCount; nRet = DoOneLogFile(strFileName, lStartIndex, lMax, bContinueWhenError, out strError); if (nRet == -1) goto ERROR1; lStartIndex = 0; // 第一个文件以后的文件就全做了 } } this.AppendResultText("循环结束\r\n"); this.App.WriteErrorLog(this.Name + "恢复 任务结束。"); return; ERROR1: return; }
public override void Worker() { // 系统挂起的时候,不运行本线程 // 2007/12/18 if (this.App.ContainsHangup("LogRecover") == true) { return; } // 2012/2/4 if (this.App.PauseBatchTask == true) { return; } string strError = ""; BatchTaskStartInfo startinfo = this.StartInfo; if (startinfo == null) { startinfo = new BatchTaskStartInfo(); // 按照缺省值来 } int nRet = ParseZhengyuanReplicationStart(startinfo.Start, out strError); if (nRet == -1) { this.AppendResultText("启动失败: " + strError + "\r\n"); return; } // 通用启动参数 bool bForceDumpAll = false; bool bForceDumpDay = false; bool bAutoDumpDay = false; bool bClearFirst = false; bool bLoop = true; nRet = ParseZhengyuanReplicationParam(startinfo.Param, out bForceDumpAll, out bForceDumpDay, out bAutoDumpDay, out bClearFirst, out bLoop, out strError); if (nRet == -1) { this.AppendResultText("启动失败: " + strError + "\r\n"); return; } this.Loop = bLoop; if (bClearFirst == true) { // 删除读者库中所有没有借阅信息的读者信息? } if (bForceDumpAll == true) { // 更新卡户信息完整表(AccountsCompleteInfo_yyyymmdd.xml) string strDataFileName = "AccountsCompleteInfo_" + GetCurrentDate() + ".xml"; string strLocalFilePath = PathUtil.MergePath(this.App.ZhengyuanDir, strDataFileName); try { // return: // -1 出错 // 0 正常结束 // 1 被用户中断 nRet = DownloadDataFile(strDataFileName, strLocalFilePath, out strError); if (nRet == -1) { string strErrorText = "下载数据文件" + strDataFileName + "失败: " + strError; this.AppendResultText(strErrorText + "\r\n"); this.App.WriteErrorLog(strErrorText); return; } if (nRet == 1) { this.AppendResultText("下载数据文件" + strDataFileName + "被中断\r\n"); this.Loop = false; return; } // 把数据文件写入有映射关系的读者库 this.AppendResultText("同步数据文件 " + strDataFileName + " 开始\r\n"); // return: // -1 error // 0 succeed // 1 中断 nRet = WriteToReaderDb(strLocalFilePath, out strError); if (nRet == -1) { string strErrorText = "文件 " + strDataFileName + " 写入读者库: " + strError; this.AppendResultText(strErrorText + "\r\n"); this.App.WriteErrorLog(strErrorText); return; } else if (nRet == 1) { this.AppendResultText("同步数据文件 " + strDataFileName + "被中断\r\n"); return; } else { this.AppendResultText("同步数据文件 " + strDataFileName + "完成\r\n"); bForceDumpAll = false; startinfo.Param = MakeZhengyuanReplicationParam( bForceDumpAll, bForceDumpDay, bAutoDumpDay, bClearFirst, bLoop); } } finally { // 删除用过的数据文件? 还是保留用作调试观察? File.Delete(strLocalFilePath); } } string strMonitorName = "zhengyuanReplication"; if (bAutoDumpDay == true || bForceDumpDay == true) { string strLastTime = ""; if (bForceDumpDay == false) { Debug.Assert(bAutoDumpDay == true, ""); // 二者必有一个==true nRet = ReadLastTime( strMonitorName, out strLastTime, out strError); if (nRet == -1) { string strErrorText = "从文件中获取每日启动时间时发生错误: " + strError; this.AppendResultText(strErrorText + "\r\n"); this.App.WriteErrorLog(strErrorText); return; } string strStartTimeDef = ""; bool bRet = false; // return: // -2 strLastTime 格式错误 // -1 一般错误 // 0 没有找到startTime配置参数 // 1 找到了startTime配置参数 nRet = IsNowAfterPerDayStart( strMonitorName, ref strLastTime, out bRet, out strStartTimeDef, out strError); if (nRet == -1 || nRet == -2) { string strErrorText = "获取每日启动时间时发生错误: " + strError; this.AppendResultText(strErrorText + "\r\n"); this.App.WriteErrorLog(strErrorText); if (nRet == -2) { WriteLastTime(strMonitorName, ""); } return; } if (bRet == false) { return; // 还没有到每日时间 } } // 更新卡户信息基本(每日)表(AccountsCompleteInfo_yyyymmdd.xml) string strDataFileName = "AccountsBasicInfo_" + GetCurrentDate() + ".xml"; string strLocalFilePath = PathUtil.MergePath(this.App.ZhengyuanDir, strDataFileName); try { // return: // -1 出错 // 0 正常结束 // 1 被用户中断 nRet = DownloadDataFile(strDataFileName, strLocalFilePath, out strError); if (nRet == -1) { string strErrorText = "下载数据文件" + strDataFileName + "失败: " + strError; this.AppendResultText(strErrorText + "\r\n"); this.App.WriteErrorLog(strErrorText); return; } if (nRet == 1) { this.AppendResultText("下载数据文件" + strDataFileName + "被中断\r\n"); this.Loop = false; return; } // 把数据文件写入有映射关系的读者库 this.AppendResultText("同步数据文件 " + strDataFileName + " 开始\r\n"); // return: // -1 error // 0 succeed // 1 中断 nRet = WriteToReaderDb(strLocalFilePath, out strError); if (nRet == -1) { string strErrorText = "文件 " + strDataFileName + " 写入读者库: " + strError; this.AppendResultText(strErrorText + "\r\n"); this.App.WriteErrorLog(strErrorText); return; } else if (nRet == 1) { this.AppendResultText("同步数据文件 " + strDataFileName + "被中断\r\n"); return; } else { this.AppendResultText("同步数据文件 " + strDataFileName + "完成\r\n"); Debug.Assert(this.App != null, ""); // 写入文件,记忆已经做过的当日时间 strLastTime = DateTimeUtil.Rfc1123DateTimeStringEx(this.App.Clock.UtcNow.ToLocalTime()); // 2007/12/17 changed // DateTime.UtcNow WriteLastTime(strMonitorName, strLastTime); if (bForceDumpDay == true) { bForceDumpDay = false; startinfo.Param = MakeZhengyuanReplicationParam( bForceDumpAll, bForceDumpDay, bAutoDumpDay, bClearFirst, bLoop); } } } finally { // 删除用过的数据文件? 还是保留用作调试观察? File.Delete(strLocalFilePath); } } }
// 一次操作循环 public override void Worker() { // 系统挂起的时候,不运行本线程 // 2007/12/18 if (this.App.ContainsHangup("LogRecover") == true) return; // 2012/2/4 if (this.App.PauseBatchTask == true) return; bool bFirst = true; string strError = ""; int nRet = 0; BatchTaskStartInfo startinfo = this.StartInfo; if (startinfo == null) startinfo = new BatchTaskStartInfo(); // 按照缺省值来 // 通用启动参数 bool bLoop = true; nRet = ParseArriveMonitorParam(startinfo.Param, out bLoop, out strError); if (nRet == -1) { this.AppendResultText("启动失败: " + strError + "\r\n"); return; } this.Loop = bLoop; string strID = ""; nRet = ParseArriveMonitorStart(startinfo.Start, out strID, out strError); if (nRet == -1) { this.AppendResultText("启动失败: " + strError + "\r\n"); this.Loop = false; return; } //// // bool bPerDayStart = false; // 是否为每日一次启动模式 string strMonitorName = "arriveMonitor"; { string strLastTime = ""; nRet = ReadLastTime( strMonitorName, out strLastTime, out strError); if (nRet == -1) { string strErrorText = "从文件中获取 " + strMonitorName + " 每日启动时间时发生错误: " + strError; this.AppendResultText(strErrorText + "\r\n"); this.App.WriteErrorLog(strErrorText); return; } string strStartTimeDef = ""; // bRet 是否到了每日启动时间 bool bRet = false; string strOldLastTime = strLastTime; // return: // -2 strLastTime 格式错误 // -1 一般错误 // 0 没有找到startTime配置参数 // 1 找到了startTime配置参数 nRet = IsNowAfterPerDayStart( strMonitorName, ref strLastTime, out bRet, out strStartTimeDef, out strError); if (nRet == -1 || nRet == -2) { string strErrorText = "获取 " + strMonitorName + " 每日启动时间时发生错误: " + strError; this.AppendResultText(strErrorText + "\r\n"); this.App.WriteErrorLog(strErrorText); if (nRet == -2) { WriteLastTime(strMonitorName, ""); } return; } // 如果nRet == 0,表示没有配置相关参数,则兼容原来的习惯,每次都作 if (nRet == 0) { } else if (nRet == 1) { if (bRet == false) { if (this.ManualStart == true) this.AppendResultText("已试探启动任务 '" + this.Name + "',但因没有到每日启动时间 " + strStartTimeDef + " 而未能启动。(上次任务处理结束时间为 " + DateTimeUtil.LocalTime(strLastTime) + ")\r\n"); // 2014/3/31 if (string.IsNullOrEmpty(strOldLastTime) == true && string.IsNullOrEmpty(strLastTime) == false) { this.AppendResultText("史上首次启动此任务。已把当前时间当作上次任务处理结束时间 " + DateTimeUtil.LocalTime(strLastTime) + " 写入了断点记忆文件\r\n"); WriteLastTime(strMonitorName, strLastTime); } return; // 还没有到每日时间 } bPerDayStart = true; } this.App.WriteErrorLog((bPerDayStart == true ? "(定时)" : "(不定时)") + strMonitorName + " 启动。"); } this.AppendResultText("开始新一轮循环\r\n"); RmsChannel channel = this.RmsChannels.GetChannel(this.App.WsUrl); this._calendarTable.Clear(); int nRecCount = 0; for (; ; nRecCount++) { #if NO // 系统挂起的时候,不运行本线程 // 2008/2/4 if (this.App.HangupReason == HangupReason.LogRecover) break; #endif if (this.Stopped == true) break; string strStyle = ""; strStyle = "data,content,timestamp,outputpath"; if (bFirst == true) strStyle += ""; else { strStyle += ",next"; } string strPath = this.App.ArrivedDbName + "/" + strID; string strXmlBody = ""; string strMetaData = ""; string strOutputPath = ""; byte[] baOutputTimeStamp = null; // this.SetProgressText((nRecCount + 1).ToString() + " " + strPath); this.AppendResultText("正在处理 " + (nRecCount + 1).ToString() + " " + strPath + "\r\n"); // 获得资源 // return: // -1 出错。具体出错原因在this.ErrorCode中。this.ErrorInfo中有出错信息。 // 0 成功 long lRet = channel.GetRes(strPath, strStyle, out strXmlBody, out strMetaData, out baOutputTimeStamp, out strOutputPath, out strError); if (lRet == -1) { if (channel.ErrorCode == ChannelErrorCode.NotFound) { if (bFirst == true) { // 第一条没有找到, 但是要强制循环进行 bFirst = false; goto CONTINUE; } else { if (bFirst == true) { strError = "记录 " + strID + " 不存在。处理结束。"; } else { strError = "记录 " + strID + " 是最末一条记录。处理结束。"; } break; } } else if (channel.ErrorCode == ChannelErrorCode.EmptyRecord) { bFirst = false; // 把id解析出来 strID = ResPath.GetRecordId(strOutputPath); goto CONTINUE; } goto ERROR1; } #if NO string strLibraryCode = ""; nRet = this.App.GetLibraryCode(strOutputPath, // ???? BUG out strLibraryCode, out strError); if (nRet == -1) goto ERROR1; #endif bFirst = false; // 把id解析出来 strID = ResPath.GetRecordId(strOutputPath); // 处理 nRet = DoOneRecord( // calendar, strOutputPath, strXmlBody, baOutputTimeStamp, out strError); if (nRet == -1) goto ERROR1; CONTINUE: continue; } // end of for this.AppendResultText("循环结束。共处理 " + nRecCount.ToString() + " 条记录。\r\n"); { Debug.Assert(this.App != null); // 写入文件,记忆已经做过的当日时间 string strLastTime = DateTimeUtil.Rfc1123DateTimeStringEx(this.App.Clock.UtcNow.ToLocalTime()); // 2007/12/17 changed // DateTime.UtcNow // 2012/5/27 WriteLastTime(strMonitorName, strLastTime); string strErrorText = (bPerDayStart == true ? "(定时)" : "(不定时)") + strMonitorName + "结束。共处理记录 " + nRecCount.ToString() + " 个。"; this.App.WriteErrorLog(strErrorText); } return; ERROR1: this.AppendResultText("arrivethread error : " + strError + "\r\n"); this.App.WriteErrorLog("arrivethread error : " + strError); return; }
// 一次操作循环 public override void Worker() { // 系统挂起的时候,不运行本线程 if (this.App.ContainsHangup("LogRecover") == true) { return; } if (this.App.PauseBatchTask == true) { return; } REDO_TASK: try { string strError = ""; if (this.App.LibraryCfgDom == null || this.App.LibraryCfgDom.DocumentElement == null) { return; } BatchTaskStartInfo startinfo = this.StartInfo; if (startinfo == null) { startinfo = new BatchTaskStartInfo(); // 按照缺省值来 } string strDbNameList = ""; int nRet = ParseStart(startinfo.Start, out strDbNameList, out strError); if (nRet == -1) { this.AppendResultText("启动失败: " + strError + "\r\n"); return; } // 下一次 loop 进入的时候自动就是 continue (从断点继续) startinfo.Start = ""; // string strRecoverLevel = ""; bool bClearFirst = false; nRet = ParseTaskParam(startinfo.Param, out strRecoverLevel, out bClearFirst, out strError); if (nRet == -1) { this.AppendResultText("启动失败: " + strError + "\r\n"); return; } // 下一次 loop 进入的时候什么动作有没有,避免重复前一次的清除数据库动作 startinfo.Param = ""; if (bClearFirst == true) { // 清除全部同步的本地库 } if (String.IsNullOrEmpty(strDbNameList) == true) { // 从断点继续循环 strDbNameList = "continue"; } // 构造用于复制然后同步的断点信息 BreakPointCollcation all_breakpoints = BreakPointCollcation.BuildFromDbNameList(strDbNameList); // 进行处理 BreakPointCollcation breakpoints = null; this.AppendResultText("*********\r\n"); if (strDbNameList == "continue") { // 按照断点信息处理 this.AppendResultText("从上次断点位置继续\r\n"); // return: // -1 出错 // 0 没有发现断点信息 // 1 成功 nRet = ReadBreakPoint(out breakpoints, out strError); if (nRet == -1) { goto ERROR1; } if (nRet == 0) { return; } } else { // 先从远端复制整个数据库,然后从开始复制时的日志末尾进行同步 this.AppendResultText("指定的数据库\r\n"); // 采纳先前创建好的复制并继续的断点信息 breakpoints = all_breakpoints; } Debug.Assert(breakpoints != null, ""); this.AppendResultText("计划进行的处理:\r\n---\r\n" + breakpoints.GetSummary() + "\r\n---\r\n\r\n"); if (this.StartInfos.Count > 0) { this.AppendResultText("等待队列:\r\n---\r\n" + GetSummary(this.StartInfos) + "\r\n---\r\n\r\n"); } m_nRecordCount = 0; for (int i = 0; i < breakpoints.Count; i++) { BreakPointInfo info = breakpoints[i]; nRet = RebuildDatabase(info, out strError); if (nRet == -1) { // 保存断点文件 SaveBreakPoint(breakpoints, true); goto ERROR1; } breakpoints.Remove(info); i--; // 保存断点文件 SaveBreakPoint(breakpoints, false); } // TODO: 如果集合为空,需要删除断点信息文件 // 正常结束,复位断点 if (this.StartInfos.Count == 0) { this.App.RemoveBatchTaskBreakPointFile(this.Name); } this.StartInfo.Start = ""; // AppendResultText("针对消息库 " + strMessageDbName + " 的循环结束。共处理 " + nRecCount.ToString() + " 条记录。\r\n"); // TODO: 在断点文件中记载 StartInfos 内容 #if NO // 按照断点信息进行处理 foreach (XmlNode server in server_nodes) { string strServerName = DomUtil.GetAttr(server, "name"); // 找到断点信息 BreakPointInfo info = breakpoints.GetBreakPoint(strServerName); if (info == null) { continue; } if (string.IsNullOrEmpty(info.BiblioDbName) == false) { // 从数据库复制 // 列出中心服务器的全部可用数据库,然后进行复制 // 断点书目库名表示从这个库开始向后复制 // 从远端复制一个数据库 // 函数返回后, info 信息可能会被改变,需要及时保存到断点文件中,便于以后重新启动批处理 // return: // -1 出错 // 0 中断 // 1 完成 nRet = CopyDatabase(server, ref info, out strError); // 保存断点文件 SaveBreakPoint(breakpoints); if (nRet == -1) { goto ERROR1; } if (nRet == 0) { goto STOP; } // 表示复制已经成功结束 info.BiblioDbName = ""; info.RecID = ""; // 保存断点文件 SaveBreakPoint(breakpoints); } if (string.IsNullOrEmpty(info.Date) == false) { string strLastDate = ""; long last_index = -1; nRet = ProcessServer(server, info.Date, strEndDate, info.Index, out strLastDate, out last_index, out strError); // 记忆 if (string.IsNullOrEmpty(strLastDate) == false) { Debug.Assert(last_index != -1, ""); info.Date = strLastDate; info.Index = last_index; // 注:从同步的角度来说,同步永远不会结束,所以不会清除 Date 和 Index } // 保存断点文件 SaveBreakPoint(breakpoints); if (nRet == -1) { this.AppendResultText("发生错误:" + strError + "\r\n"); } if (nRet == 0) { goto STOP; } SetProgressText("完成"); } } #endif this.AppendResultText("本轮处理结束\r\n"); { // return: // -1 出错 // 0 没有发现断点信息 // 1 成功 nRet = ReadBreakPoint(out breakpoints, out strError); if (nRet == -1) { goto ERROR1; } // 如果有累积的任务,还需要继续执行 if (nRet == 1 && this.StartInfos.Count > 0) { this.StartInfo = this.StartInfos[0]; this.StartInfos.RemoveAt(0); goto REDO_TASK; } } return; ERROR1: this.AppendResultText(strError + "\r\n"); return; } finally { } #if NO STOP: if (this.App.PauseBatchTask == true) { this.Loop = true; // 如果因为暂停而中断,既的后面还要重新开始 SetProgressText("暂时中断"); this.AppendResultText("暂时中断\r\n"); } else { this.Loop = false; SetProgressText("中断"); this.AppendResultText("中断\r\n"); } #endif }
// 一次操作循环 public override void Worker() { // 系统挂起的时候,不运行本线程 // 2007/12/18 //if (this.App.HangupReason == HangupReason.LogRecover) // return; if (this.App.ContainsHangup("LogRecover") == true) { return; } // 2012/2/4 if (this.App.PauseBatchTask == true) { return; } bool bFirst = true; string strError = ""; int nRet = 0; BatchTaskStartInfo startinfo = this.StartInfo; if (startinfo == null) { startinfo = new BatchTaskStartInfo(); // 按照缺省值来 } // 通用启动参数 bool bLoop = true; nRet = ParseMessageMonitorParam(startinfo.Param, out bLoop, out strError); if (nRet == -1) { this.AppendResultText("启动失败: " + strError + "\r\n"); return; } this.Loop = bLoop; string strID = ""; nRet = ParseMessageMonitorStart(startinfo.Start, out strID, out strError); if (nRet == -1) { this.AppendResultText("启动失败: " + strError + "\r\n"); this.Loop = false; return; } // bool bPerDayStart = false; // 是否为每日一次启动模式 string strMonitorName = "messageMonitor"; { string strLastTime = ""; nRet = ReadLastTime( strMonitorName, out strLastTime, out strError); if (nRet == -1) { string strErrorText = "从文件中获取 " + strMonitorName + " 每日启动时间时发生错误: " + strError; this.AppendResultText(strErrorText + "\r\n"); this.App.WriteErrorLog(strErrorText); return; } string strStartTimeDef = ""; // bRet 是否到了每日启动时间 bool bRet = false; string strOldLastTime = strLastTime; // return: // -2 strLastTime 格式错误 // -1 一般错误 // 0 没有找到startTime配置参数 // 1 找到了startTime配置参数 nRet = IsNowAfterPerDayStart( strMonitorName, ref strLastTime, out bRet, out strStartTimeDef, out strError); if (nRet == -1 || nRet == -2) { string strErrorText = "获取 " + strMonitorName + " 每日启动时间时发生错误: " + strError; this.AppendResultText(strErrorText + "\r\n"); this.App.WriteErrorLog(strErrorText); if (nRet == -2) { // 删除断点文件,避免下次继续报错 WriteLastTime(strMonitorName, ""); } return; } // 如果nRet == 0,表示没有配置相关参数,则兼容原来的习惯,每次都作 if (nRet == 0) { } else if (nRet == 1) { if (bRet == false) { if (this.ManualStart == true) { this.AppendResultText("已试探启动任务 '" + this.Name + "',但因没有到每日启动时间 " + strStartTimeDef + " 而未能启动。(上次任务处理结束时间为 " + DateTimeUtil.LocalTime(strLastTime) + ")\r\n"); } // 2014/3/31 if (string.IsNullOrEmpty(strOldLastTime) == true && string.IsNullOrEmpty(strLastTime) == false) { this.AppendResultText("史上首次启动此任务。已把当前时间当作上次任务处理结束时间 " + DateTimeUtil.LocalTime(strLastTime) + " 写入了断点记忆文件\r\n"); WriteLastTime(strMonitorName, strLastTime); } return; // 还没有到每日时间 } bPerDayStart = true; } this.App.WriteErrorLog((bPerDayStart == true ? "(定时)" : "(不定时)") + strMonitorName + " 启动。"); } AppendResultText("开始新一轮循环"); RmsChannel channel = this.RmsChannels.GetChannel(this.App.WsUrl); string strMessageDbName = this.App.MessageDbName; if (String.IsNullOrEmpty(strMessageDbName) == true) { AppendResultText("尚未配置消息库名(<message dbname='...' />)"); this.Loop = false; return; } if (String.IsNullOrEmpty(this.App.MessageReserveTimeSpan) == true) { AppendResultText("尚未配置消息保留期限(<message reserveTimeSpan='...' />"); this.Loop = false; return; } // 解析期限值 string strPeriodUnit = ""; long lPeriodValue = 0; nRet = LibraryApplication.ParsePeriodUnit( this.App.MessageReserveTimeSpan, out lPeriodValue, out strPeriodUnit, out strError); if (nRet == -1) { strError = "消息保留期限 值 '" + this.App.MessageReserveTimeSpan + "' 格式错误: " + strError; AppendResultText(strError); this.Loop = false; return; } AppendResultText("开始处理消息库 " + strMessageDbName + " 的循环"); // string strID = "1"; int nRecCount = 0; for (; ; nRecCount++) { // 系统挂起的时候,不运行本线程 // 2008/2/4 if (this.App.ContainsHangup("LogRecover") == true) { break; } // 2012/2/4 if (this.App.PauseBatchTask == true) { break; } if (this.Stopped == true) { break; } string strStyle = ""; strStyle = "data,content,timestamp,outputpath"; if (bFirst == true) { strStyle += ""; } else { strStyle += ",next"; } string strPath = strMessageDbName + "/" + strID; string strXmlBody = ""; string strMetaData = ""; string strOutputPath = ""; byte[] baOutputTimeStamp = null; // SetProgressText((nRecCount + 1).ToString() + " " + strPath); // 获得资源 // return: // -1 出错。具体出错原因在this.ErrorCode中。this.ErrorInfo中有出错信息。 // 0 成功 long lRet = channel.GetRes(strPath, strStyle, out strXmlBody, out strMetaData, out baOutputTimeStamp, out strOutputPath, out strError); if (lRet == -1) { if (channel.ErrorCode == ChannelErrorCode.NotFound) { if (bFirst == true) { // 第一条没有找到, 但是要强制循环进行 bFirst = false; goto CONTINUE; } else { if (bFirst == true) { strError = "数据库 " + strMessageDbName + " 记录 " + strID + " 不存在。处理结束。"; } else { strError = "数据库 " + strMessageDbName + " 记录 " + strID + " 是最末一条记录。处理结束。"; } break; } } else if (channel.ErrorCode == ChannelErrorCode.EmptyRecord) { bFirst = false; // 把id解析出来 strID = ResPath.GetRecordId(strOutputPath); goto CONTINUE; } goto ERROR1; } bFirst = false; // 把id解析出来 strID = ResPath.GetRecordId(strOutputPath); try { // 处理 nRet = DoOneRecord( lPeriodValue, strPeriodUnit, strOutputPath, strXmlBody, baOutputTimeStamp, out strError); } catch (Exception ex) { strError = "DoOneRecord exception: " + ExceptionUtil.GetDebugText(ex); this.AppendResultText(strError + "\r\n"); this.SetProgressText(strError); nRet = -1; } if (nRet == -1) { AppendResultText("DoOneRecord() error : " + strError + "。\r\n"); } CONTINUE: continue; } // end of for // 正常结束,复位断点 this.App.RemoveBatchTaskBreakPointFile(this.Name); this.StartInfo.Start = ""; AppendResultText("针对消息库 " + strMessageDbName + " 的循环结束。共处理 " + nRecCount.ToString() + " 条记录。\r\n"); { Debug.Assert(this.App != null, ""); // 写入文件,记忆已经做过的当日时间 string strLastTime = DateTimeUtil.Rfc1123DateTimeStringEx(this.App.Clock.UtcNow.ToLocalTime()); // 2007/12/17 changed // DateTime.UtcNow // 2012/5/27 WriteLastTime(strMonitorName, strLastTime); string strErrorText = (bPerDayStart == true ? "(定时)" : "(不定时)") + strMonitorName + "结束。共处理记录 " + nRecCount.ToString() + " 个。"; this.App.WriteErrorLog(strErrorText); } return; ERROR1: // 记忆断点 this.StartInfo.Start = MemoBreakPoint( strID //strRecordID, ); this.Loop = true; // 便于稍后继续重新循环? startinfo.Param = MakeMessageMonitorParam( bLoop); AppendResultText("MessageMonitor thread error : " + strError + "\r\n"); this.App.WriteErrorLog("MessageMonitor thread error : " + strError + "\r\n"); return; }
// 一次操作循环 public override void Worker() { // 系统挂起的时候,不运行本线程 // 2007/12/18 if (this.App.ContainsHangup("LogRecover") == true) return; // 2012/2/4 if (this.App.PauseBatchTask == true) return; if (string.IsNullOrEmpty(this.App.ArrivedDbName)) { this.AppendResultText("启动失败: 当前 library.xml 中没有配置预约到书库参数\r\n"); return; } bool bFirst = true; string strError = ""; int nRet = 0; BatchTaskStartInfo startinfo = this.StartInfo; if (startinfo == null) startinfo = new BatchTaskStartInfo(); // 按照缺省值来 // 通用启动参数 bool bLoop = true; nRet = ParseArriveMonitorParam(startinfo.Param, out bLoop, out strError); if (nRet == -1) { this.AppendResultText("启动失败: " + strError + "\r\n"); return; } this.Loop = bLoop; string strID = ""; nRet = ParseArriveMonitorStart(startinfo.Start, out strID, out strError); if (nRet == -1) { this.AppendResultText("启动失败: " + strError + "\r\n"); this.Loop = false; return; } //// // bool bPerDayStart = false; // 是否为每日一次启动模式 string strMonitorName = "arriveMonitor"; { string strLastTime = ""; nRet = ReadLastTime( strMonitorName, out strLastTime, out strError); if (nRet == -1) { string strErrorText = "从文件中获取 " + strMonitorName + " 每日启动时间时发生错误: " + strError; this.AppendResultText(strErrorText + "\r\n"); this.App.WriteErrorLog(strErrorText); return; } string strStartTimeDef = ""; // bRet 是否到了每日启动时间 bool bRet = false; string strOldLastTime = strLastTime; // return: // -2 strLastTime 格式错误 // -1 一般错误 // 0 没有找到startTime配置参数 // 1 找到了startTime配置参数 nRet = IsNowAfterPerDayStart( strMonitorName, ref strLastTime, out bRet, out strStartTimeDef, out strError); if (nRet == -1 || nRet == -2) { string strErrorText = "获取 " + strMonitorName + " 每日启动时间时发生错误: " + strError; this.AppendResultText(strErrorText + "\r\n"); this.App.WriteErrorLog(strErrorText); if (nRet == -2) { WriteLastTime(strMonitorName, ""); } return; } // 如果nRet == 0,表示没有配置相关参数,则兼容原来的习惯,每次都作 if (nRet == 0) { } else if (nRet == 1) { if (bRet == false) { if (this.ManualStart == true) this.AppendResultText("已试探启动任务 '" + this.Name + "',但因没有到每日启动时间 " + strStartTimeDef + " 而未能启动。(上次任务处理结束时间为 " + DateTimeUtil.LocalTime(strLastTime) + ")\r\n"); // 2014/3/31 if (string.IsNullOrEmpty(strOldLastTime) == true && string.IsNullOrEmpty(strLastTime) == false) { this.AppendResultText("史上首次启动此任务。已把当前时间当作上次任务处理结束时间 " + DateTimeUtil.LocalTime(strLastTime) + " 写入了断点记忆文件\r\n"); WriteLastTime(strMonitorName, strLastTime); } return; // 还没有到每日时间 } bPerDayStart = true; } this.App.WriteErrorLog((bPerDayStart == true ? "(定时)" : "(不定时)") + strMonitorName + " 启动。"); } this.AppendResultText("开始新一轮循环\r\n"); RmsChannel channel = this.RmsChannels.GetChannel(this.App.WsUrl); this._calendarTable.Clear(); int nRecCount = 0; for (; ; nRecCount++) { #if NO // 系统挂起的时候,不运行本线程 // 2008/2/4 if (this.App.HangupReason == HangupReason.LogRecover) break; #endif if (this.Stopped == true) break; string strStyle = ""; strStyle = "data,content,timestamp,outputpath"; if (bFirst == true) strStyle += ""; else { strStyle += ",next"; } string strPath = this.App.ArrivedDbName + "/" + strID; string strXmlBody = ""; string strMetaData = ""; string strOutputPath = ""; byte[] baOutputTimeStamp = null; // this.SetProgressText((nRecCount + 1).ToString() + " " + strPath); this.AppendResultText("正在处理 " + (nRecCount + 1).ToString() + " " + strPath + "\r\n"); // 获得资源 // return: // -1 出错。具体出错原因在this.ErrorCode中。this.ErrorInfo中有出错信息。 // 0 成功 long lRet = channel.GetRes(strPath, strStyle, out strXmlBody, out strMetaData, out baOutputTimeStamp, out strOutputPath, out strError); if (lRet == -1) { if (channel.ErrorCode == ChannelErrorCode.NotFound) { if (bFirst == true) { // 第一条没有找到, 但是要强制循环进行 bFirst = false; goto CONTINUE; } else { if (bFirst == true) { strError = "记录 " + strID + " 不存在。处理结束。"; } else { strError = "记录 " + strID + " 是最末一条记录。处理结束。"; } break; } } else if (channel.ErrorCode == ChannelErrorCode.EmptyRecord) { bFirst = false; // 把id解析出来 strID = ResPath.GetRecordId(strOutputPath); goto CONTINUE; } goto ERROR1; } #if NO string strLibraryCode = ""; nRet = this.App.GetLibraryCode(strOutputPath, // ???? BUG out strLibraryCode, out strError); if (nRet == -1) goto ERROR1; #endif bFirst = false; // 把id解析出来 strID = ResPath.GetRecordId(strOutputPath); // 处理 nRet = DoOneRecord( // calendar, strOutputPath, strXmlBody, baOutputTimeStamp, out strError); if (nRet == -1) goto ERROR1; CONTINUE: continue; } // end of for this.AppendResultText("循环结束。共处理 " + nRecCount.ToString() + " 条记录。\r\n"); { Debug.Assert(this.App != null); // 写入文件,记忆已经做过的当日时间 string strLastTime = DateTimeUtil.Rfc1123DateTimeStringEx(this.App.Clock.UtcNow.ToLocalTime()); // 2007/12/17 changed // DateTime.UtcNow // 2012/5/27 WriteLastTime(strMonitorName, strLastTime); string strErrorText = (bPerDayStart == true ? "(定时)" : "(不定时)") + strMonitorName + "结束。共处理记录 " + nRecCount.ToString() + " 个。"; this.App.WriteErrorLog(strErrorText); } return; ERROR1: this.AppendResultText("预约到书管理 后台任务出错: " + strError + "\r\n"); this.App.WriteErrorLog("预约到书管理 后台任务出错: " + strError); return; }
public override void Worker() { // 系统挂起的时候,不运行本线程 // 2007/12/18 if (this.App.HangupReason == HangupReason.LogRecover) return; // 2012/2/4 if (this.App.PauseBatchTask == true) return; string strError = ""; BatchTaskStartInfo startinfo = this.StartInfo; if (startinfo == null) startinfo = new BatchTaskStartInfo(); // 按照缺省值来 int nRet = ParseZhengyuanReplicationStart(startinfo.Start, out strError); if (nRet == -1) { this.AppendResultText("启动失败: " + strError + "\r\n"); return; } // 通用启动参数 bool bForceDumpAll = false; bool bForceDumpDay = false; bool bAutoDumpDay = false; bool bClearFirst = false; bool bLoop = true; nRet = ParseZhengyuanReplicationParam(startinfo.Param, out bForceDumpAll, out bForceDumpDay, out bAutoDumpDay, out bClearFirst, out bLoop, out strError); if (nRet == -1) { this.AppendResultText("启动失败: " + strError + "\r\n"); return; } this.Loop = bLoop; if (bClearFirst == true) { // 删除读者库中所有没有借阅信息的读者信息? } if (bForceDumpAll == true) { // 更新卡户信息完整表(AccountsCompleteInfo_yyyymmdd.xml) string strDataFileName = "AccountsCompleteInfo_" + GetCurrentDate() + ".xml"; string strLocalFilePath = PathUtil.MergePath(this.App.ZhengyuanDir, strDataFileName); try { // return: // -1 出错 // 0 正常结束 // 1 被用户中断 nRet = DownloadDataFile(strDataFileName, strLocalFilePath, out strError); if (nRet == -1) { string strErrorText = "下载数据文件" + strDataFileName + "失败: " + strError; this.AppendResultText(strErrorText + "\r\n"); this.App.WriteErrorLog(strErrorText); return; } if (nRet == 1) { this.AppendResultText("下载数据文件"+strDataFileName+"被中断\r\n"); this.Loop = false; return; } // 把数据文件写入有映射关系的读者库 this.AppendResultText("同步数据文件 " + strDataFileName + " 开始\r\n"); // return: // -1 error // 0 succeed // 1 中断 nRet = WriteToReaderDb(strLocalFilePath, out strError); if (nRet == -1) { string strErrorText = "文件 " + strDataFileName + " 写入读者库: " + strError; this.AppendResultText(strErrorText + "\r\n"); this.App.WriteErrorLog(strErrorText); return; } else if (nRet == 1) { this.AppendResultText("同步数据文件 " + strDataFileName + "被中断\r\n"); return; } else { this.AppendResultText("同步数据文件 " + strDataFileName + "完成\r\n"); bForceDumpAll = false; startinfo.Param = MakeZhengyuanReplicationParam( bForceDumpAll, bForceDumpDay, bAutoDumpDay, bClearFirst, bLoop); } } finally { // 删除用过的数据文件? 还是保留用作调试观察? File.Delete(strLocalFilePath); } } if (bAutoDumpDay == true || bForceDumpDay == true) { string strLastTime = ""; if (bForceDumpDay == false) { Debug.Assert(bAutoDumpDay == true, ""); // 二者必有一个==true nRet = ReadLastTime(out strLastTime, out strError); if (nRet == -1) { string strErrorText = "从文件中获取每日启动时间时发生错误: " + strError; this.AppendResultText(strErrorText + "\r\n"); this.App.WriteErrorLog(strErrorText); return; } bool bRet = false; nRet = IsNowAfterPerDayStart( strLastTime, out bRet, out strError); if (nRet == -1) { string strErrorText = "获取每日启动时间时发生错误: " + strError; this.AppendResultText(strErrorText + "\r\n"); this.App.WriteErrorLog(strErrorText); return; } if (bRet == false) return; // 还没有到每日时间 } // 更新卡户信息基本(每日)表(AccountsCompleteInfo_yyyymmdd.xml) string strDataFileName = "AccountsBasicInfo_" + GetCurrentDate() + ".xml"; string strLocalFilePath = PathUtil.MergePath(this.App.ZhengyuanDir, strDataFileName); try { // return: // -1 出错 // 0 正常结束 // 1 被用户中断 nRet = DownloadDataFile(strDataFileName, strLocalFilePath, out strError); if (nRet == -1) { string strErrorText = "下载数据文件" + strDataFileName + "失败: " + strError; this.AppendResultText(strErrorText + "\r\n"); this.App.WriteErrorLog(strErrorText); return; } if (nRet == 1) { this.AppendResultText("下载数据文件" + strDataFileName + "被中断\r\n"); this.Loop = false; return; } // 把数据文件写入有映射关系的读者库 this.AppendResultText("同步数据文件 " + strDataFileName + " 开始\r\n"); // return: // -1 error // 0 succeed // 1 中断 nRet = WriteToReaderDb(strLocalFilePath, out strError); if (nRet == -1) { string strErrorText = "文件 " + strDataFileName + " 写入读者库: " + strError; this.AppendResultText(strErrorText + "\r\n"); this.App.WriteErrorLog(strErrorText); return; } else if (nRet == 1) { this.AppendResultText("同步数据文件 " + strDataFileName + "被中断\r\n"); return; } else { this.AppendResultText("同步数据文件 " + strDataFileName + "完成\r\n"); Debug.Assert(this.App != null, ""); // 写入文件,记忆已经做过的当日时间 strLastTime = DateTimeUtil.Rfc1123DateTimeStringEx(this.App.Clock.UtcNow.ToLocalTime()); // 2007/12/17 changed // DateTime.UtcNow WriteLastTime(strLastTime); if (bForceDumpDay == true) { bForceDumpDay = false; startinfo.Param = MakeZhengyuanReplicationParam( bForceDumpAll, bForceDumpDay, bAutoDumpDay, bClearFirst, bLoop); } } } finally { // 删除用过的数据文件? 还是保留用作调试观察? File.Delete(strLocalFilePath); } } }
// 一次操作循环 public override void Worker() { // 把系统挂起 // this.App.HangupReason = HangupReason.LogRecover; this.App.AddHangup("LogRecover"); try { string strError = ""; BatchTaskStartInfo startinfo = this.StartInfo; if (startinfo == null) startinfo = new BatchTaskStartInfo(); // 按照缺省值来 long lStartIndex = 0;// 开始位置 string strStartFileName = "";// 开始文件名 int nRet = ParseLogRecorverStart(startinfo.Start, out lStartIndex, out strStartFileName, out strError); if (nRet == -1) { this.AppendResultText("启动失败: " + strError + "\r\n"); return; } // string strRecoverLevel = ""; bool bClearFirst = false; bool bContinueWhenError = false; nRet = ParseLogRecoverParam(startinfo.Param, out strRecoverLevel, out bClearFirst, out bContinueWhenError, out strError); if (nRet == -1) { this.AppendResultText("启动失败: " + strError + "\r\n"); return; } if (String.IsNullOrEmpty(strRecoverLevel) == true) strRecoverLevel = "Snapshot"; try { this.RecoverLevel = (RecoverLevel)Enum.Parse(typeof(RecoverLevel), strRecoverLevel, true); } catch (Exception ex) { this.AppendResultText("启动失败: 启动参数Param中的recoverLevel枚举值 '" + strRecoverLevel + "' 错误: " + ex.Message + "\r\n"); return; } this.App.WriteErrorLog("日志恢复 任务启动。"); // 当为容错恢复级别时,检查当前全部读者库的检索点是否符合要求 if (this.RecoverLevel == LibraryServer.RecoverLevel.Robust) { // 检查全部读者库的检索途径,看是否满足都有“所借册条码号”这个检索途径的这个条件 // return: // -1 出错 // 0 不满足 // 1 满足 nRet = this.App.DetectReaderDbFroms(out strError); if (nRet == -1) { this.AppendResultText("检查读者库检索点时发生错误: " + strError + "\r\n"); return; } if (nRet == 0) { this.AppendResultText("在容错恢复级别下,当前读者库中有部分或全部读者库缺乏“所借册条码号”检索点,无法进行日志恢复。请按照日志恢复要求,刷新所有读者库的检索点配置,然后再进行日志恢复\r\n"); return; } } // TODO: 检查当前是否有 重建检索点 的后台任务正在运行,或者还有没有运行完的部分。 // 要求重建检索点的任务运行完以后才能执行日志恢复任务 if (bClearFirst == true) { nRet = this.App.ClearAllDbs(this.RmsChannels, out strError); if (nRet == -1) { this.AppendResultText("清除全部数据库记录时发生错误: " + strError + "\r\n"); return; } } bool bStart = false; if (String.IsNullOrEmpty(strStartFileName) == true) { // 做所有文件 bStart = true; } // 列出所有日志文件 DirectoryInfo di = new DirectoryInfo(this.App.OperLog.Directory); FileInfo[] fis = di.GetFiles("*.log"); // BUG!!! 以前缺乏排序。2008/2/1 Array.Sort(fis, new FileInfoCompare()); for (int i = 0; i < fis.Length; i++) { if (this.Stopped == true) break; string strFileName = fis[i].Name; this.AppendResultText("检查文件 " + strFileName + "\r\n"); if (bStart == false) { // 从特定文件开始做 if (string.CompareOrdinal(strStartFileName, strFileName) <= 0) // 2015/9/12 从等号修改为 Compare { bStart = true; if (lStartIndex < 0) lStartIndex = 0; // lStartIndex = Convert.ToInt64(startinfo.Param); } } if (bStart == true) { nRet = DoOneLogFile(strFileName, lStartIndex, bContinueWhenError, out strError); if (nRet == -1) goto ERROR1; lStartIndex = 0; // 第一个文件以后的文件就全做了 } } this.AppendResultText("循环结束\r\n"); this.App.WriteErrorLog("日志恢复 任务结束。"); return; ERROR1: return; } finally { // this.App.HangupReason = HangupReason.None; this.App.ClearHangup("LogRecover"); } }
public override void Worker() { // 系统挂起的时候,不运行本线程 if (this.App.HangupReason == HangupReason.LogRecover) return; // 2012/2/4 if (this.App.PauseBatchTask == true) return; string strError = ""; int nRet = 0; BatchTaskStartInfo startinfo = this.StartInfo; if (startinfo == null) startinfo = new BatchTaskStartInfo(); // 按照缺省值来 // 获取配置参数 // return: // -1 出错 // 0 尚未配置<patronReplication>参数 // 1 成功 nRet = GetConfigParameters(out strError); if (nRet == -1) { string strErrorText = "获取配置参数时出错: " + strError; this.AppendResultText(strErrorText + "\r\n"); this.App.WriteErrorLog(strErrorText); return; } if (nRet == 0) { this.AppendResultText("library.xml中尚未配置<patronReplication>参数,读者信息同步任务没有被执行\r\n"); return; } #if NO BatchTaskStartInfo startinfo = this.StartInfo; if (startinfo == null) startinfo = new BatchTaskStartInfo(); // 按照缺省值来 // 通用启动参数 bool bLoop = true; int nRet = ParsePatronReplicationParam(startinfo.Param, out bLoop, out strError); if (nRet == -1) { this.AppendResultText("启动失败: " + strError + "\r\n"); return; } this.Loop = bLoop; string strID = ""; nRet = ParsePatronReplicationStart(startinfo.Start, out strID, out strError); if (nRet == -1) { this.AppendResultText("启动失败: " + strError + "\r\n"); this.Loop = false; return; } if (strID == "!breakpoint") { string strLastNumber = ""; bool bTempLoop = false; nRet = ReadLastNumber( out bTempLoop, out strLastNumber, out strError); if (nRet == -1) { string strErrorText = "从断点文件中获取最大号码时发生错误: " + strError; this.AppendResultText(strErrorText + "\r\n"); this.App.WriteErrorLog(strErrorText); return; } strID = strLastNumber; if (string.IsNullOrEmpty(strLastNumber) == false) { this.AppendResultText("从断点 "+strLastNumber+" 开始处理\r\n"); } } #endif bool bPerDayStart = false; // 是否为每日一次启动模式 string strMonitorName = "patronReplication"; { string strLastTime = ""; nRet = ReadLastTime( strMonitorName, out strLastTime, out strError); if (nRet == -1) { string strErrorText = "从文件中获取 " + strMonitorName + " 每日启动时间时发生错误: " + strError; this.AppendResultText(strErrorText + "\r\n"); this.App.WriteErrorLog(strErrorText); return; } string strStartTimeDef = ""; // bRet 是否到了每日启动时间 bool bRet = false; string strOldLastTime = strLastTime; // return: // -1 error // 0 没有找到startTime配置参数 // 1 找到了startTime配置参数 nRet = IsNowAfterPerDayStart( strMonitorName, ref strLastTime, out bRet, out strStartTimeDef, out strError); if (nRet == -1) { string strErrorText = "获取 " + strMonitorName + " 每日启动时间时发生错误: " + strError; this.AppendResultText(strErrorText + "\r\n"); this.App.WriteErrorLog(strErrorText); return; } // 如果nRet == 0,表示没有配置相关参数,则兼容原来的习惯,每次都作 if (nRet == 0 ) { } else if (nRet == 1 && startinfo.Start == "activate") { // 2015/8/4 // 虽然 library.xml 中定义了每日定时启动,但被前端要求立即启动 this.AppendResultText("任务 '" + this.Name + "' 被立即启动\r\n"); } else if (nRet == 1) { bPerDayStart = true; if (bRet == false) { if (this.ManualStart == true) this.AppendResultText("已试探启动任务 '" + this.Name + "',但因没有到每日启动时间 " + strStartTimeDef + " 而未能启动。(上次任务处理结束时间为 " + DateTimeUtil.LocalTime(strLastTime) + ")\r\n"); // 2014/3/31 if (string.IsNullOrEmpty(strOldLastTime) == true && string.IsNullOrEmpty(strLastTime) == false) { this.AppendResultText("史上首次启动此任务。已把当前时间当作上次任务处理结束时间 " + DateTimeUtil.LocalTime(strLastTime) + " 写入了断点记忆文件\r\n"); WriteLastTime(strMonitorName, strLastTime); } return; // 还没有到每日时间 } } this.App.WriteErrorLog((bPerDayStart == true ? "(定时)" : "(不定时)") + this.Name + " 启动。"); } this.AppendResultText("开始新一轮循环\r\n"); int nTotalRecCount = 0; try { // 把数据文件写入有映射关系的读者库 this.AppendResultText("*** 同步读者数据任务开始\r\n"); string strXmlFilename = PathUtil.MergePath(this.App.PatronReplicationDir, "data.xml"); // 从卡中心获取全部记录,写入一个XML文件 nRet = GetAllRecordsFromCardCenter( strXmlFilename, out strError); if (nRet == -1) { string strErrorText = "从卡中心获取数据时出错: " + strError; this.AppendResultText(strErrorText + "\r\n"); this.App.WriteErrorLog(strErrorText); return; } this.AppendResultText("检索读者库中现有的记录集合\r\n"); List<string> current_ids = null; // 检索出读者库中全部ids // 通过特定检索途径获得读者记录 // return: // -1 error // >=0 命中个数 nRet = SearchAllIds( this.RmsChannels, this.PatronDbName, this.From, out current_ids, out strError); if (nRet == -1) { string strErrorText = "检索数据库 " + this.PatronDbName + " 中所有 " + this.From + " 的keys时出错: " + strError; this.AppendResultText(strErrorText + "\r\n"); this.App.WriteErrorLog(strErrorText); return; } this.AppendResultText("刷新读者数据开始\r\n"); List<string> ids = null; string strMaxNumber = ""; // 返回操作末尾的最大号 bool bComplete = false; try { // return: // -1 error // 0 succeed // 1 中断 nRet = WriteToReaderDb( strXmlFilename, "", // strID, out strMaxNumber, out ids, out strError); if (nRet == 0) bComplete = true; } finally { if (bComplete == false) { #if NO // 写入文件,记忆已经做过的最大号码 // 要用bLoop,这是来自启动面板的值;不能用this.Loop 因为中断时其值已经被改变 if (String.IsNullOrEmpty(strMaxNumber) == true) { // 如果运行出错或者根本没有新源记录,连一条也没有成功作过,就保持原来的断点记录号 // 如果写入的断点记录号是空,下次运行的时候,将从'1'开始。这一般是不能接受的 WriteLastNumber(bLoop, strID); } else WriteLastNumber(bLoop, strMaxNumber); #endif } else { #if NO WriteLastNumber(bLoop, ""); // 本次已经完成,下次从头开始 #endif File.Delete(strXmlFilename); } } if (nRet == -1) { string strErrorText = "写入读者库时出错: " + strError; this.AppendResultText(strErrorText + "\r\n"); this.App.WriteErrorLog(strErrorText); return; } else if (nRet == 1) { this.AppendResultText("刷新读者数据被中断\r\n"); return; } else { this.AppendResultText("刷新读者数据完成,共处理读者记录 "+ids.Count.ToString()+" 条\r\n"); Debug.Assert(this.App != null, ""); } nTotalRecCount += ids.Count; // current_ids 和 ids 进行交叉运算 this.AppendResultText("排序归并ID\r\n"); current_ids.Sort(); StringUtil.RemoveDup(ref current_ids); ids.Sort(); StringUtil.RemoveDup(ref ids); List<string> targetLeft = new List<string>(); List<string> targetMiddle = null; List<string> targetRight = null; string strDebugInfo = ""; this.AppendResultText("逻辑运算ID\r\n"); // 对两个已经排序的List进行逻辑运算 // 注:sourceLeft和sourceRight在调用前应当已经排序,从小到大的方向 // parameters: // strLogicOper 运算风格 OR , AND , SUB // sourceLeft 源左边结果集 // sourceRight 源右边结果集 // targetLeft 目标左边结果集 // targetMiddle 目标中间结果集 // targetRight 目标右边结果集 // bOutputDebugInfo 是否输出处理信息 // strDebugInfo 处理信息 // return // -1 出错 // 0 成功 nRet = StringUtil.LogicOper("SUB", current_ids, ids, ref targetLeft, ref targetMiddle, ref targetRight, false, out strDebugInfo, out strError); if (nRet == -1) { string strErrorText = "逻辑运算集合时出错: " + strError; this.AppendResultText(strErrorText + "\r\n"); this.App.WriteErrorLog(strErrorText); return; } this.AppendResultText("开始标记删除读者记录\r\n"); // 从current_ids中去掉和ids重复的部分,剩下的需要作标记删除处理 nRet = MaskDeleteRecords( targetLeft, out strError); if (nRet == -1) { string strErrorText = "标记删除读者记录时出错: " + strError; this.AppendResultText(strErrorText + "\r\n"); this.App.WriteErrorLog(strErrorText); return; } else if (nRet == 1) { this.AppendResultText("标记删除读者记录被中断\r\n"); return; } else { this.AppendResultText("标记删除读者记录完成,共处理记录 " + targetLeft.Count.ToString()+ " 条\r\n"); this.AppendResultText("*** 同步读者数据任务完成\r\n"); nTotalRecCount += targetLeft.Count; Debug.Assert(this.App != null, ""); } } finally { #if NO this.StartInfo.Start = "!breakpoint"; // 自动循环的时候,没有号码,要从断点文件中取得 #endif } AppendResultText("循环结束。共处理 " + nTotalRecCount.ToString() + " 条记录。\r\n"); { Debug.Assert(this.App != null, ""); // 写入文件,记忆已经做过的当日时间 string strLastTime = DateTimeUtil.Rfc1123DateTimeStringEx(this.App.Clock.UtcNow.ToLocalTime()); WriteLastTime(strMonitorName, strLastTime); string strErrorText = (bPerDayStart == true ? "(定时)" : "(不定时)") + strMonitorName + "结束。共处理记录 " + nTotalRecCount.ToString() + " 个。"; this.App.WriteErrorLog(strErrorText); } return; ERROR1: AppendResultText("PatronReplication thread error : " + strError + "\r\n"); this.App.WriteErrorLog("PatronReplication thread error : " + strError + "\r\n"); return; }
// 一次操作循环 // TODO: 是否需要对读者记录加锁? public override void Worker() { // 系统挂起的时候,不运行本线程 // 2007/12/18 if (this.App.ContainsHangup("LogRecover") == true) return; // 2012/2/4 if (this.App.PauseBatchTask == true) return; string strError = ""; int nRet = 0; BatchTaskStartInfo startinfo = this.StartInfo; if (startinfo == null) startinfo = new BatchTaskStartInfo(); // 按照缺省值来 bool bPerDayStart = false; // 是否为每日一次启动模式 string strMonitorName = "readersMonitor"; { string strLastTime = ""; nRet = ReadLastTime( strMonitorName, out strLastTime, out strError); if (nRet == -1) { string strErrorText = "从文件中获取 " + strMonitorName + " 每日启动时间时发生错误: " + strError; this.AppendResultText(strErrorText + "\r\n"); this.App.WriteErrorLog(strErrorText); return; } string strStartTimeDef = ""; // bRet 是否到了每日启动时间 bool bRet = false; string strOldLastTime = strLastTime; // return: // -2 strLastTime 格式错误 // -1 一般错误 // 0 没有找到startTime配置参数 // 1 找到了startTime配置参数 nRet = IsNowAfterPerDayStart( strMonitorName, ref strLastTime, out bRet, out strStartTimeDef, out strError); if (nRet == -1 || nRet == -2) { string strErrorText = "获取 " + strMonitorName + " 每日启动时间时发生错误: " + strError; this.AppendResultText(strErrorText + "\r\n"); this.App.WriteErrorLog(strErrorText); if (nRet == -2) { WriteLastTime(strMonitorName, ""); } return; } // 如果nRet == 0,表示没有配置相关参数,则兼容原来的习惯,每次都作 if (nRet == 0) { } else if (nRet == 1 && startinfo.Start == "activate") { // 2015/10/3 // 虽然 library.xml 中定义了每日定时启动,但被前端要求立即启动 this.AppendResultText("任务 '" + this.Name + "' 被立即启动\r\n"); } else if (nRet == 1) { bPerDayStart = true; if (bRet == false) { if (this.ManualStart == true) this.AppendResultText("已试探启动任务 '" + this.Name + "',但因没有到每日启动时间 " + strStartTimeDef + " 而未能启动。(上次任务处理结束时间为 " + DateTimeUtil.LocalTime(strLastTime) + ")\r\n"); // 2014/3/31 if (string.IsNullOrEmpty(strOldLastTime) == true && string.IsNullOrEmpty(strLastTime) == false) { this.AppendResultText("史上首次启动此任务。已把当前时间当作上次任务处理结束时间 " + DateTimeUtil.LocalTime(strLastTime) + " 写入了断点记忆文件\r\n"); WriteLastTime(strMonitorName, strLastTime); } return; // 还没有到每日时间 } } this.App.WriteErrorLog((bPerDayStart == true ? "(定时)" : "(不定时)") + strMonitorName + " 启动。"); } this.AppendResultText("开始新一轮循环\r\n"); recpath_table.Clear(); if (string.IsNullOrEmpty(this.App.OutgoingQueue) == false) { try { _queue = new MessageQueue(this.App.OutgoingQueue); } catch (Exception ex) { strError = "创建路径为 '" + this.App.OutgoingQueue + "' 的 MessageQueue 对象失败: " + ex.Message; goto ERROR1; } } else this._queue = null; List<string> bodytypes = new List<string>(); string strBodyTypesDef = GetBodyTypesDef(); if (string.IsNullOrEmpty(strBodyTypesDef) == true) { strBodyTypesDef = "dpmail,email"; // 空表示只使用两种保守的类型 bodytypes = StringUtil.SplitList(strBodyTypesDef); } else if (strBodyTypesDef == "[all]") { // 全部类型。包括 mq 和外部接口 bodytypes.Add("dpmail"); bodytypes.Add("email"); if (string.IsNullOrEmpty(this.App.OutgoingQueue) == false) bodytypes.Add("mq"); // MSMQ 消息队列 if (this.App.m_externalMessageInterfaces != null) { foreach (MessageInterface message_interface in this.App.m_externalMessageInterfaces) { bodytypes.Add(message_interface.Type); } } } else bodytypes = StringUtil.SplitList(strBodyTypesDef); RmsChannel channel = this.RmsChannels.GetChannel(this.App.WsUrl); int nTotalRecCount = 0; foreach (DigitalPlatform.LibraryServer.LibraryApplication.ReaderDbCfg cfg in this.App.ReaderDbs) { #if NO // 系统挂起的时候,不运行本线程 // 2008/5/27 if (this.App.HangupReason == HangupReason.LogRecover) break; // 2012/2/4 if (this.App.PauseBatchTask == true) break; #endif if (this.Stopped == true) break; string strReaderDbName = cfg.DbName; string strLibraryCode = cfg.LibraryCode; AppendResultText("开始处理读者库 " + strReaderDbName + " 的循环\r\n"); bool bFirst = true; // 2008/5/27 moved string strID = "1"; int nOnePassRecCount = 0; for (; ; nOnePassRecCount++, nTotalRecCount++) { #if NO // 系统挂起的时候,不运行本线程 // 2008/2/4 if (this.App.HangupReason == HangupReason.LogRecover) break; // 2012/2/4 if (this.App.PauseBatchTask == true) break; #endif if (this.Stopped == true) break; string strStyle = ""; strStyle = "data,content,timestamp,outputpath"; if (bFirst == true) strStyle += ""; else { strStyle += ",next"; } string strPath = strReaderDbName + "/" + strID; string strXmlBody = ""; string strMetaData = ""; string strOutputPath = ""; byte[] baOutputTimeStamp = null; // SetProgressText((nOnePassRecCount + 1).ToString() + " " + strPath); // 获得资源 // return: // -1 出错。具体出错原因在this.ErrorCode中。this.ErrorInfo中有出错信息。 // 0 成功 long lRet = channel.GetRes(strPath, strStyle, out strXmlBody, out strMetaData, out baOutputTimeStamp, out strOutputPath, out strError); if (lRet == -1) { if (channel.ErrorCode == ChannelErrorCode.NotFound) { if (bFirst == true) { // 第一条没有找到, 但是要强制循环进行 bFirst = false; goto CONTINUE; } else { if (bFirst == true) { strError = "数据库 " + strReaderDbName + " 记录 " + strID + " 不存在。处理结束。"; } else { strError = "数据库 " + strReaderDbName + " 记录 " + strID + " 是最末一条记录。处理结束。"; } break; } } else if (channel.ErrorCode == ChannelErrorCode.EmptyRecord) { bFirst = false; // 把id解析出来 strID = ResPath.GetRecordId(strOutputPath); goto CONTINUE; } goto ERROR1; } #if NO string strLibraryCode = ""; nRet = this.App.GetLibraryCode(strOutputPath, out strLibraryCode, out strError); if (nRet == -1) goto ERROR1; #endif bFirst = false; this.AppendResultText("正在处理" + (nOnePassRecCount + 1).ToString() + " " + strOutputPath + "\r\n"); // 把id解析出来 strID = ResPath.GetRecordId(strOutputPath); // 处理 nRet = DoOneRecord( bodytypes, strOutputPath, strLibraryCode, strXmlBody, baOutputTimeStamp, out strError); if (nRet == -1) { AppendResultText("DoOneRecord() error : " + strError + "。\r\n"); // 循环并不停止 } CONTINUE: continue; } // end of for AppendResultText("针对读者库 " + strReaderDbName + " 的循环结束。共处理 " + nOnePassRecCount.ToString() + " 条记录。\r\n"); } recpath_table.Clear(); AppendResultText("循环结束。共处理 " + nTotalRecCount.ToString() + " 条记录。\r\n"); SetProgressText("循环结束。共处理 " + nTotalRecCount.ToString() + " 条记录。"); // 2015/10/3 // 让前端激活的任务,只执行一次。如果配置了每日激活时间,后面要再执行,除非是每日激活时间已到 if (startinfo.Start == "activate") startinfo.Start = ""; { Debug.Assert(this.App != null, ""); // 写入文件,记忆已经做过的当日时间 string strLastTime = DateTimeUtil.Rfc1123DateTimeStringEx(this.App.Clock.UtcNow.ToLocalTime()); // 2007/12/17 changed // DateTime.UtcNow WriteLastTime(strMonitorName, strLastTime); string strErrorText = (bPerDayStart == true ? "(定时)" : "(不定时)") + strMonitorName + "结束。共处理记录 " + nTotalRecCount.ToString() + " 个。"; this.App.WriteErrorLog(strErrorText); } return; ERROR1: AppendResultText("ReadersMonitor thread error : " + strError + "\r\n"); this.App.WriteErrorLog("ReadersMonitor thread error : " + strError + "\r\n"); return; }