// 保存断点信息,并保存 this.StartInfos void SaveBreakPoint(BreakPointCollcation infos, bool bClearStartInfos) { // 写入断点文件 this.App.WriteBatchTaskBreakPointFile(this.Name, infos.ToString() + "|||" + ToString(this.StartInfos)); if (bClearStartInfos) { this.StartInfos = new List <BatchTaskStartInfo>(); // 避免残余信息对后一轮运行发生影响 } }
// 通过字符串构造 public static BreakPointCollcation Build(string strText) { BreakPointCollcation infos = new BreakPointCollcation(); string[] segments = strText.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); foreach (string segment in segments) { infos.Add(BreakPointInfo.Build(segment)); } return(infos); }
// 通过数据库名列表字符串构造 public static BreakPointCollcation BuildFromDbNameList(string strText) { BreakPointCollcation infos = new BreakPointCollcation(); string[] dbnames = strText.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); foreach (string dbname in dbnames) { BreakPointInfo info = new BreakPointInfo(); info.DbName = dbname; infos.Add(info); } return(infos); }
// 读出断点信息,和恢复 this.StartInfos // return: // -1 出错 // 0 没有发现断点信息 // 1 成功 int ReadBreakPoint(out BreakPointCollcation breakpoints, out string strError) { strError = ""; breakpoints = null; List <BatchTaskStartInfo> start_infos = 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 strStartInfos = ""; string strBreakPoint = ""; StringUtil.ParseTwoPart(strText, "|||", out strBreakPoint, out strStartInfos); // 可能会抛出异常 breakpoints = BreakPointCollcation.Build(strBreakPoint); start_infos = FromString(strStartInfos); if (start_infos != null) { this.StartInfos = start_infos; } return(1); }
// 一次操作循环 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 }