private void StartLogRecoverDlg_Load(object sender, EventArgs e) { string strError = ""; try { // 起始位置参数 ServerReplicationStart start = ServerReplicationStart.FromString(this.StartInfo.Start); this.textBox_startDate.Text = start.Date; this.textBox_startIndex.Text = start.Index.ToString(); // 通用启动参数 ServerReplicationParam param = ServerReplicationParam.FromString(this.StartInfo.Param); this.comboBox_recoverLevel.Text = param.RecoverLevel; this.checkBox_clearBefore.Checked = param.ClearFirst; this.checkBox_clearBefore.Checked = param.ContinueWhenError; } catch (Exception ex) { strError = ex.Message; goto ERROR1; } return; ERROR1: MessageBox.Show(this, strError); }
// 读出断点信息,和恢复 this.StartInfos // return: // -1 出错 // 0 没有发现断点信息 // 1 成功 int ReadBreakPoint( out ServerReplicationStart start, out ServerReplicationParam param, out string strError) { strError = ""; start = null; param = null; string strText = ""; // 从断点记忆文件中读出信息 // return: // -1 error // 0 file not found // 1 found int nRet = this.App.ReadBatchTaskBreakPointFile(this.DefaultName, out strText, out strError); if (nRet == -1) { return(-1); } if (nRet == 0) { strError = "启动失败。因当前还没有断点信息,请指定为其他方式运行"; return(0); } string strStart = ""; string strParam = ""; StringUtil.ParseTwoPart(strText, "|||", out strParam, out strStart); // 可能会抛出异常 start = ServerReplicationStart.FromString(strParam); if (string.IsNullOrEmpty(start.Date) == true || start.Date.Length != 8) { strError = "start 字符串格式不正确 '" + strParam + "'。文件名部分应为 8 字符"; return(-1); } param = ServerReplicationParam.FromString(strStart); return(1); }
// 一次操作循环 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; }