public DbNameMap Clone() { /* * DbNameMap result = new DbNameMap(); * * foreach( DictionaryEntry entry in this) * { * // int i =0; * * * DbNameMapItem olditem = (DbNameMapItem)this[entry.Key]; * * DbNameMapItem newitem = new DbNameMapItem(); * * newitem.strOrigin = olditem.strOrigin; * newitem.strStyle = olditem.strStyle; * newitem.strTarget = olditem.strTarget; * * result.Add(entry.Key, newitem); * } */ DbNameMap result = new DbNameMap(); for (int i = 0; i < this.m_list.Count; i++) { DbNameMapItem olditem = (DbNameMapItem)this.m_list[i]; string strError = ""; if (result.NewItem(olditem.Origin, olditem.Target, olditem.Style, out strError) == null) { throw new Exception(strError); } } return(result); }
// 询问无法匹配的源路径如何处理 // return: // -1 出错 // 0 cancel全部处理 // 1 已经选择处理办法 public static int AskNotMatchOriginBox( IWin32Window owner, ApplicationInfo ap, ServerCollection Servers, RmsChannelCollection Channels, string strComment, string strSelectedLongPath, string strOrigin, DbNameMap map) { DbNameMapItemDlg dlg = new DbNameMapItemDlg(); dlg.Font = GuiUtil.GetDefaultFont(); dlg.Servers = Servers; dlg.Channels = Channels; dlg.Comment = strComment; dlg.AskMode = AskMode.AskNotMatchOrigin; dlg.Origin = strOrigin; dlg.Target = strSelectedLongPath; dlg.WriteMode = "append"; dlg.Text = "请指定映射关系"; if (ap != null) { ap.LinkFormState(dlg, "AskNotMatchOriginBox_state"); } dlg.ShowDialog(owner); if (ap != null) { ap.UnlinkFormState(dlg); } if (dlg.DialogResult != DialogResult.OK) { return(0); // cancel } string strError = ""; if (map.NewItem(dlg.Origin, dlg.Target, dlg.WriteMode, 0, // 插入最前面 out strError) == null) { MessageBox.Show(owner, strError); return(-1); } return(1); }
// 构造map对象。 // parameters: // strDbPaths 分号间隔的路径。将创建为Origin和Target相同的overwrite事项。 // 格式为 dbpathorigin-dbpathtarget|style;... // 可以省略为dbpath1;dbpath2;... 每个path既当origin也当target用 public static DbNameMap Build(string strDbPaths, out string strError) { strError = ""; DbNameMap map = new DbNameMap(); string[] aPath = strDbPaths.Split(new char[] { ';' }); for (int i = 0; i < aPath.Length; i++) { string strLine = aPath[i].Trim(); if (strLine == "") { continue; } string strOrigin = ""; string strTarget = ""; string strStyle = ""; int nRet = strLine.IndexOf("|"); if (nRet == -1) { strStyle = "overwrite"; } else { strStyle = strLine.Substring(nRet + 1).Trim().ToLower(); strLine = strLine.Substring(0, nRet).Trim(); } nRet = strLine.IndexOf("-"); if (nRet == -1) { strOrigin = strLine; strTarget = strLine; } else { strOrigin = strLine.Substring(0, nRet).Trim(); strTarget = strLine.Substring(nRet + 1).Trim(); } if (map.NewItem(strOrigin, strTarget, strStyle, out strError) == null) { return(null); } } return(map); }
private void button_OK_Click(object sender, System.EventArgs e) { string strTarget = ""; string strStyle = ""; if (radioButton_skip.Checked == true) { strStyle = "skip"; } if (radioButton_append.Checked == true) { if (this.textBox_appendDbName.Text == "") { MessageBox.Show(this, "在选择了追加方式的情况下,必须选择目标库..."); return; } strTarget = this.textBox_appendDbName.Text; strStyle = "append"; } if (radioButton_overwrite.Checked == true) { if (this.textBox_overwriteDbName.Text == "") { MessageBox.Show(this, "在选择了覆盖方式的情况下,必须选择目标库..."); return; } strTarget = this.textBox_overwriteDbName.Text; strStyle = "overwrite"; } // 如果要仅仅当次起作用,需要深复制Map,以便对话框调主使用后自动丢弃 if (checkBox_notAskWhenSameOrigin.Checked == false) { this.Map = this.Map.Clone(); } string strError = ""; if (Map.NewItem(Origin, strTarget, strStyle, out strError) == null) { MessageBox.Show(this, strError); return; } this.DialogResult = DialogResult.OK; this.Close(); }
// 构造map对象。 // parameters: // strDbPaths 分号间隔的路径。将创建为Origin和Target相同的overwrite事项。 // 格式为 dbpathorigin-dbpathtarget|style;... // 可以省略为dbpath1;dbpath2;... 每个path既当origin也当target用 public static DbNameMap Build(string strDbPaths, out string strError) { strError = ""; DbNameMap map = new DbNameMap(); string[] aPath = strDbPaths.Split(new char[] { ';' }); for (int i = 0; i < aPath.Length; i++) { string strLine = aPath[i].Trim(); if (strLine == "") continue; string strOrigin = ""; string strTarget = ""; string strStyle = ""; int nRet = strLine.IndexOf("|"); if (nRet == -1) strStyle = "overwrite"; else { strStyle = strLine.Substring(nRet + 1).Trim().ToLower(); strLine = strLine.Substring(0, nRet).Trim(); } nRet = strLine.IndexOf("-"); if (nRet == -1) { strOrigin = strLine; strTarget = strLine; } else { strOrigin = strLine.Substring(0, nRet).Trim(); strTarget = strLine.Substring(nRet + 1).Trim(); } if (map.NewItem(strOrigin, strTarget, strStyle, out strError) == null) return null; } return map; }
public DbNameMap Clone() { /* DbNameMap result = new DbNameMap(); foreach( DictionaryEntry entry in this) { // int i =0; DbNameMapItem olditem = (DbNameMapItem)this[entry.Key]; DbNameMapItem newitem = new DbNameMapItem(); newitem.strOrigin = olditem.strOrigin; newitem.strStyle = olditem.strStyle; newitem.strTarget = olditem.strTarget; result.Add(entry.Key, newitem); } */ DbNameMap result = new DbNameMap(); for (int i = 0; i < this.m_list.Count; i++) { DbNameMapItem olditem = (DbNameMapItem)this.m_list[i]; string strError = ""; if (result.NewItem(olditem.Origin, olditem.Target, olditem.Style, out strError) == null) throw new Exception(strError); } return result; }
// 上载一个res // parameter: // inputfile: 源流 // bIsFirstRes: 是否是第一个资源(xml) // strError: error info // return: // -2 片断中发现时间戳不匹配。本函数调主可重上载整个资源 // -1 error // 0 successed public int DoResUpload( ref RmsChannel channel, ref string strRecordPath, Stream inputfile, ref DbNameMap map, bool bIsFirstRes, string strCount, out string strError) { strError = ""; int nRet; long lBodyStart = 0; long lBodyLength = 0; // 1. 从输入流中得到strMetadata,与body(body放到一个临时文件里) string strMetaDataXml = ""; nRet = GetResInfo(inputfile, bIsFirstRes, out strMetaDataXml, out lBodyStart, out lBodyLength, out strError); if (nRet == -1) goto ERROR1; if (lBodyLength == 0) return 0; // 空包不需上载 // 2.为上载做准备 XmlDocument metadataDom = new XmlDocument(); try { metadataDom.LoadXml(strMetaDataXml); } catch (Exception ex) { strError = "加载元数据到dom出错!\r\n" + ex.Message; goto ERROR1; } XmlNode node = metadataDom.DocumentElement; string strResPath = DomUtil.GetAttr(node, "path"); string strTargetPath = ""; if (bIsFirstRes == true) // 第一个资源 { // 从map中查询覆盖还是追加? ResPath respath = new ResPath(strResPath); respath.MakeDbName(); REDO: DbNameMapItem mapItem = (DbNameMapItem)map["*"]; if (mapItem != null) { } else { mapItem = (DbNameMapItem)map[respath.FullPath.ToUpper()]; } if (mapItem == null) { OriginNotFoundDlg dlg = new OriginNotFoundDlg(); MainForm.SetControlFont(dlg, this.DefaultFont); dlg.Message = "数据中声明的数据库路径 '" + respath.FullPath + "' 在覆盖关系对照表中没有找到, 请选择覆盖方式: "; dlg.Origin = respath.FullPath.ToUpper(); dlg.Servers = this.Servers; dlg.Channels = this.Channels; dlg.Map = map; dlg.StartPosition = FormStartPosition.CenterScreen; dlg.ShowDialog(this); if (dlg.DialogResult != DialogResult.OK) { strError = "用户中断..."; goto ERROR1; } map = dlg.Map; goto REDO; } if (mapItem.Style == "skip") return 0; // 构造目标路径 // 1)从源路径中提取id。源路径来自备份文件数据 respath = new ResPath(strResPath); string strID = respath.GetRecordId(); if (strID == null || strID == "" || (mapItem.Style == "append") ) { strID = "?"; // 将来加一个对话框 } // 2)用目标库路径构造完整的记录路径 string strTargetFullPath = ""; if (mapItem.Target == "*") { respath = new ResPath(strResPath); respath.MakeDbName(); strTargetFullPath = respath.FullPath; } else { strTargetFullPath = mapItem.Target; } respath = new ResPath(strTargetFullPath); strTargetPath = respath.Path + "/" + strID; strRecordPath = strTargetPath; channel = this.Channels.GetChannel(respath.Url); } else // 第二个以后的资源 { if (channel == null) { strError = "当bIsFirstRes==false时,参数channel不应为null..."; goto ERROR1; } ResPath respath = new ResPath(strResPath); string strObjectId = respath.GetObjectId(); if (strObjectId == null || strObjectId == "") { strError = "object id为空..."; goto ERROR1; } strTargetPath = strRecordPath + "/object/" + strObjectId; if (strRecordPath == "") { strError = "strRecordPath参数值为空..."; goto ERROR1; } } // string strLocalPath = DomUtil.GetAttr(node,"localpath"); // string strMimeType = DomUtil.GetAttr(node,"mimetype"); string strTimeStamp = DomUtil.GetAttr(node, "timestamp"); // 注意,strLocalPath并不是要上载的body文件,它只用来作元数据\ // body文件为strBodyTempFileName // 3.将body文件拆分成片断进行上载 string[] ranges = null; if (lBodyLength == 0) { // 空文件 ranges = new string[1]; ranges[0] = ""; } else { string strRange = ""; strRange = "0-" + Convert.ToString(lBodyLength - 1); // 按照100K作为一个chunk ranges = RangeList.ChunkRange(strRange, 100 * 1024 ); } byte[] timestamp = ByteArray.GetTimeStampByteArray(strTimeStamp); byte[] output_timestamp = null; REDOWHOLESAVE: string strOutputPath = ""; string strWarning = ""; for (int j = 0; j < ranges.Length; j++) { REDOSINGLESAVE: Application.DoEvents(); // 出让界面控制权 if (stop.State != 0) { DialogResult result = MessageBox.Show(this, "确实要中断当前批处理操作?", "dp2batch", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2); if (result == DialogResult.Yes) { strError = "用户中断"; goto ERROR1; } else { stop.Continue(); } } string strWaiting = ""; if (j == ranges.Length - 1) strWaiting = " 请耐心等待..."; string strPercent = ""; RangeList rl = new RangeList(ranges[j]); if (rl.Count >= 1) { double ratio = (double)((RangeItem)rl[0]).lStart / (double)lBodyLength; strPercent = String.Format("{0,3:N}", ratio * (double)100) + "%"; } if (stop != null) stop.SetMessage("正在上载 " + ranges[j] + "/" + Convert.ToString(lBodyLength) + " " + strPercent + " " + strTargetPath + strWarning + strWaiting + " " + strCount); inputfile.Seek(lBodyStart, SeekOrigin.Begin); long lRet = channel.DoSaveResObject(strTargetPath, inputfile, lBodyLength, "", // style strMetaDataXml, ranges[j], j == ranges.Length - 1 ? true : false, // 最尾一次操作,提醒底层注意设置特殊的WebService API超时时间 timestamp, out output_timestamp, out strOutputPath, out strError); // progressBar_main.Value = (int)((inputfile.Position)/ProgressRatio); stop.SetProgressValue(inputfile.Position); strWarning = ""; if (lRet == -1) { if (channel.ErrorCode == ChannelErrorCode.TimestampMismatch) { string strDisplayRecPath = strOutputPath; if (string.IsNullOrEmpty(strDisplayRecPath) == true) strDisplayRecPath = strTargetPath; if (this.bNotAskTimestampMismatchWhenOverwrite == true) { timestamp = new byte[output_timestamp.Length]; Array.Copy(output_timestamp, 0, timestamp, 0, output_timestamp.Length); strWarning = " (时间戳不匹配, 自动重试)"; if (ranges.Length == 1 || j == 0) goto REDOSINGLESAVE; goto REDOWHOLESAVE; } DialogResult result = MessageDlg.Show(this, "上载 '" + strDisplayRecPath + "' (片断:" + ranges[j] + "/总尺寸:" + Convert.ToString(lBodyLength) + ") 时发现时间戳不匹配。详细情况如下:\r\n---\r\n" + strError + "\r\n---\r\n\r\n是否以新时间戳强行上载?\r\n注:(是)强行上载 (否)忽略当前记录或资源上载,但继续后面的处理 (取消)中断整个批处理", "dp2batch", MessageBoxButtons.YesNoCancel, MessageBoxDefaultButton.Button1, ref this.bNotAskTimestampMismatchWhenOverwrite); if (result == DialogResult.Yes) { if (output_timestamp != null) { timestamp = new byte[output_timestamp.Length]; Array.Copy(output_timestamp, 0, timestamp, 0, output_timestamp.Length); } else { timestamp = output_timestamp; } strWarning = " (时间戳不匹配, 应用户要求重试)"; if (ranges.Length == 1 || j == 0) goto REDOSINGLESAVE; goto REDOWHOLESAVE; } if (result == DialogResult.No) { return 0; // 继续作后面的资源 } if (result == DialogResult.Cancel) { strError = "用户中断"; goto ERROR1; // 中断整个处理 } } goto ERROR1; } timestamp = output_timestamp; } // 考虑到保存第一个资源的时候,id可能为“?”,因此需要得到实际的id值 if (bIsFirstRes) strRecordPath = strOutputPath; return 0; ERROR1: return -1; }
// 上载一个item // parameter: // file: 源数据文件流 // strError: error info // return: // -1: error // 0: successed public int DoBackupItemUpload(Stream file, ref DbNameMap map, // 2007/6/5 bool bSkip, string strCount, out string strError) { strError = ""; long lStart = file.Position; byte[] data = new byte[8]; int nRet = file.Read(data, 0, 8); if (nRet == 0) return 1; // 已经结束 if (nRet < 8) { strError = "read file error..."; return -1; } // 毛长度 long lLength = BitConverter.ToInt64(data, 0); // +8可能是一个bug!!! if (bSkip == true) { file.Seek(lLength, SeekOrigin.Current); return 0; } this.channel = null; string strRecordPath = ""; for (int i = 0; ; i++) { Application.DoEvents(); // 出让界面控制权 if (stop.State != 0) { DialogResult result = MessageBox.Show(this, "确实要中断当前批处理操作?", "dp2batch", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2); if (result == DialogResult.Yes) { strError = "用户中断"; return -1; } else { stop.Continue(); } } // progressBar_main.Value = (int)((file.Position)/ProgressRatio); stop.SetProgressValue(file.Position); if (file.Position - lStart >= lLength + 8) // 2006/8/29 changed break; // 上载对象资源 nRet = this.DoResUpload( ref this.channel, ref strRecordPath, file, ref map, // 2007/6/5 ref i == 0 ? true : false, strCount, out strError); if (nRet == -1) return -1; } return 0; }
// 上载一个item // parameter: // strError: error info // return: // -1 出错 // 0 正常 // 1 结束 public int DoXmlItemUpload( bool bFastMode, string strXml, DbNameMap map, bool bSkip, string strCount, out string strError) { strError = ""; int nRet = 0; // bool bRet = false; // MessageBox.Show(this, strXml); if (bSkip == true) return 0; XmlDocument dataDom = new XmlDocument(); try { dataDom.LoadXml(strXml); } catch (Exception ex) { strError = "加载数据到dom出错!\r\n" + ex.Message; goto ERROR1; } XmlNode node = dataDom.DocumentElement; string strResPath = DomUtil.GetAttr(DpNs.dprms, node, "path"); string strTargetPath = ""; string strSourceDbPath = ""; if (strResPath != "") { // 从map中查询覆盖还是追加? ResPath respath0 = new ResPath(strResPath); respath0.MakeDbName(); strSourceDbPath = respath0.FullPath; } REDO: DbNameMapItem mapItem = null; mapItem = map.MatchItem(strSourceDbPath/*strResPath*/); if (mapItem != null) goto MAPITEMOK; if (mapItem == null) { if (strSourceDbPath/*strResPath*/ == "") { string strText = "源数据文件中记录 " + Convert.ToString(this.m_nRecordCount) + " 没有来源数据库,对所有这样的数据,将作如何处理?"; WriteLog("打开对话框 '" + strText.Replace("\r\n", "\\n") + "'"); nRet = DbNameMapItemDlg.AskNullOriginBox( this, this.AppInfo, strText, this.SearchPanel, map); WriteLog("关闭对话框 '" + strText.Replace("\r\n", "\\n") + "'"); if (nRet == 0) { strError = "用户中断"; goto ERROR1; // 中断整个处理 } goto REDO; } else { string strText = "源数据文件中记录 " + Convert.ToString(this.m_nRecordCount) + " 的来源数据库 '" + strSourceDbPath/*strResPath*/ + "' 没有找到对应的目标库, 对所有这样的数据,将作如何处理?"; WriteLog("打开对话框 '" + strText.Replace("\r\n", "\\n") + "'"); nRet = DbNameMapItemDlg.AskNotMatchOriginBox( this, this.AppInfo, strText, this.SearchPanel, strSourceDbPath/*strResPath*/, map); WriteLog("关闭对话框 '" + strText.Replace("\r\n", "\\n") + "'"); if (nRet == 0) { strError = "用户中断"; goto ERROR1; // 中断整个处理 } goto REDO; } } MAPITEMOK: if (mapItem.Style == "skip") return 0; // 构造目标路径 // 1)从源路径中提取id。源路径来自备份文件数据 ResPath respath = new ResPath(strResPath); string strID = respath.GetRecordId(); if (strID == null || strID == "" || (mapItem.Style == "append") ) { strID = "?"; // 将来加一个对话框 } // 2)用目标库路径构造完整的记录路径 string strTargetFullPath = ""; if (mapItem.Target == "*") { // 此时target为*, 需要从strResPath中获得库名 if (strResPath == "") { Debug.Assert(false, "不可能出现的情况"); } respath = new ResPath(strResPath); respath.MakeDbName(); strTargetFullPath = respath.FullPath; } else { strTargetFullPath = mapItem.Target; } respath = new ResPath(strTargetFullPath); // 需要检查目标库所允许的MARC格式 if (CheckTargetDb != null) { CheckTargetDbEventArgs e = new CheckTargetDbEventArgs(); e.DbFullPath = strTargetFullPath; e.CurrentMarcSyntax = this.CurMarcSyntax; this.CheckTargetDb(this, e); if (e.Cancel == true) { if (e.ErrorInfo == "") strError = "CheckTargetDb 事件导致中断"; else strError = e.ErrorInfo; return -1; } } strTargetPath = respath.Path + "/" + strID; // strRecordPath = strTargetPath; channel = this.Channels.GetChannel(respath.Url); string strTimeStamp = DomUtil.GetAttr(DpNs.dprms, node, "timestamp"); byte[] timestamp = ByteArray.GetTimeStampByteArray(strTimeStamp); // 2012/5/29 string strOutMarcSyntax = ""; string strMARC = ""; // 将MARCXML格式的xml记录转换为marc机内格式字符串 // parameters: // bWarning ==true, 警告后继续转换,不严格对待错误; = false, 非常严格对待错误,遇到错误后不继续转换 // strMarcSyntax 指示marc语法,如果=="",则自动识别 // strOutMarcSyntax out参数,返回marc,如果strMarcSyntax == "",返回找到marc语法,否则返回与输入参数strMarcSyntax相同的值 nRet = MarcUtil.Xml2Marc(strXml, false, "", out strOutMarcSyntax, out strMARC, out strError); /* if (nRet == -1) return -1; * */ // 2012/5/30 if (batchObj != null) { batchObj.MarcSyntax = strOutMarcSyntax; batchObj.MarcRecord = strMARC; batchObj.MarcRecordChanged = false; // 为本轮Script运行准备初始状态 } if (this.MarcFilter != null) { // 触发filter中的Record相关动作 nRet = MarcFilter.DoRecord( null, batchObj.MarcRecord, m_nRecordCount, out strError); if (nRet == -1) goto ERROR1; } // C#脚本 -- Inputing if (this.AssemblyMain != null) { // 这些变量要先初始化,因为filter代码可能用到这些Batch成员. batchObj.SkipInput = false; batchObj.XmlRecord = strXml; //batchObj.MarcSyntax = this.CurMarcSyntax; //batchObj.MarcRecord = strMarc; // MARC记录体 //batchObj.MarcRecordChanged = false; // 为本轮Script运行准备初始状态 batchObj.SearchPanel.ServerUrl = channel.Url; batchObj.ServerUrl = channel.Url; batchObj.RecPath = strTargetPath; // 记录路径 batchObj.RecIndex = m_nRecordCount; // 当前记录在一批中的序号 batchObj.TimeStamp = timestamp; BatchEventArgs args = new BatchEventArgs(); batchObj.Inputing(this, args); if (args.Continue == ContinueType.SkipAll) { strError = "脚本中断SkipAll"; goto END2; } if (batchObj.SkipInput == true) return 0; // 继续处理后面的 } string strWarning = ""; byte[] output_timestamp = null; string strOutputPath = ""; REDOSAVE: if (stop != null) { if (strTargetPath.IndexOf("?") == -1) { stop.SetMessage("正在上载 " + strTargetPath + strWarning + " " + strCount); } } // 保存Xml记录 long lRet = channel.DoSaveTextRes(strTargetPath, strXml, false, // bIncludePreamble bFastMode == true ? "fastmode" : "",//strStyle, timestamp, out output_timestamp, out strOutputPath, out strError); if (lRet == -1) { if (stop != null) stop.Continue(); if (channel.ErrorCode == ChannelErrorCode.TimestampMismatch) { string strDisplayRecPath = strOutputPath; if (string.IsNullOrEmpty(strDisplayRecPath) == true) strDisplayRecPath = strTargetPath; if (this.bNotAskTimestampMismatchWhenOverwrite == true) { timestamp = new byte[output_timestamp.Length]; Array.Copy(output_timestamp, 0, timestamp, 0, output_timestamp.Length); strWarning = " (时间戳不匹配, 自动重试)"; goto REDOSAVE; } string strText = "上载 '" + strDisplayRecPath + " 时发现时间戳不匹配。详细情况如下:\r\n---\r\n" + strError + "\r\n---\r\n\r\n是否以新时间戳强行上载?\r\n注:(是)强行上载 (否)忽略当前记录或资源上载,但继续后面的处理 (取消)中断整个批处理"; WriteLog("打开对话框 '" + strText.Replace("\r\n", "\\n") + "'"); DialogResult result = MessageDlg.Show(this, strText, "dp2batch", MessageBoxButtons.YesNoCancel, MessageBoxDefaultButton.Button1, ref this.bNotAskTimestampMismatchWhenOverwrite); WriteLog("关闭对话框 '" + strText.Replace("\r\n", "\\n") + "'"); if (result == DialogResult.Yes) { timestamp = new byte[output_timestamp.Length]; Array.Copy(output_timestamp, 0, timestamp, 0, output_timestamp.Length); strWarning = " (时间戳不匹配, 应用户要求重试)"; goto REDOSAVE; } if (result == DialogResult.No) { return 0; // 继续作后面的资源 } if (result == DialogResult.Cancel) { strError = "用户中断"; goto ERROR1; // 中断整个处理 } } // 询问是否重试 { string strText = "上载 '" + strTargetPath + " 时发生错误。详细情况如下:\r\n---\r\n" + strError + "\r\n---\r\n\r\n是否重试?\r\n注:(是)重试 (否)不重试,但继续后面的处理 (取消)中断整个批处理"; WriteLog("打开对话框 '" + strText.Replace("\r\n", "\\n") + "'"); DialogResult result1 = MessageBox.Show(this, strText, "dp2batch", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1); WriteLog("关闭对话框 '" + strText.Replace("\r\n", "\\n") + "'"); if (result1 == DialogResult.Yes) goto REDOSAVE; if (result1 == DialogResult.No) return 0; // 继续作后面的资源 } goto ERROR1; } // C#脚本 -- Inputed() if (this.AssemblyMain != null) { // 大部分变量保留刚才Inputing()时的原样,只修改部分 batchObj.RecPath = strOutputPath; // 记录路径 batchObj.TimeStamp = output_timestamp; BatchEventArgs args = new BatchEventArgs(); batchObj.Inputed(this, args); /* if (args.Continue == ContinueType.SkipMiddle) { strError = "脚本中断SkipMiddle"; goto END1; } if (args.Continue == ContinueType.SkipBeginMiddle) { strError = "脚本中断SkipBeginMiddle"; goto END1; } */ if (args.Continue == ContinueType.SkipAll) { strError = "脚本中断SkipAll"; goto END1; } } this.m_nRecordCount++; if (stop != null) { stop.SetMessage("已上载成功 '" + strOutputPath + "' " + strCount); } // strRecordPath = strOutputPath; return 0; END1: END2: ERROR1: return -1; }
// 上载一个item // parameter: // strError: error info // return: // -1 出错 // 0 正常 // 1 结束 public int DoXmlItemUpload( bool bFastMode, XmlTextReader reader, DbNameMap map, bool bSkip, string strCount, out string strError) { strError = ""; bool bRet = false; while (true) { if (reader.NodeType == XmlNodeType.Element) break; bRet = reader.Read(); if (bRet == false) return 1; } /* if (bRet == false) return 1; // 结束 * */ string strXml = reader.ReadOuterXml(); return DoXmlItemUpload( bFastMode, strXml, map, bSkip, strCount, out strError); }
// 导入数据 int ImportData(bool bFastMode = false) { string strError = ""; string strTimeMessage = ""; int CHUNK_SIZE = 150 * 1024; // 70 if (this.SelectedNode == null) { strError = "尚未选择要要导入数据的数据库节点"; goto ERROR0; } if (this.SelectedNode.ImageIndex != RESTYPE_DB) { strError = "所选择的节点不是数据库类型。请选择要导入数据的数据库节点。"; goto ERROR0; } if (bFastMode == true) { DialogResult result = MessageBox.Show(this, "警告:\r\n在快速导入期间,相关数据库会进入一种锁定状态,对数据库的其他检索和修改操作暂时会被禁止,直到处理完成。\r\n\r\n请问确实要进行快速导入么?", "导入数据", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2); if (result == DialogResult.No) return 0; } OpenFileDialog dlg = new OpenFileDialog(); dlg.Title = "请指定要导入的数据文件"; dlg.FileName = ""; dlg.Filter = "备份文件 (*.dp2bak)|*.dp2bak|XML文件 (*.xml)|*.xml|ISO2709文件 (*.iso;*.mrc)|*.iso;*.mrc|All files (*.*)|*.*"; dlg.RestoreDirectory = true; if (dlg.ShowDialog() != DialogResult.OK) { return 0; } long lTotalCount = 0; ImportUtil import_util = new ImportUtil(); int nRet = import_util.Begin(this, this.AppInfo, dlg.FileName, out strError); if (nRet == -1 || nRet == 1) goto ERROR0; #if NO ResPath respath = new ResPath(this.SelectedNode); this.channel = Channels.GetChannel(respath.Url); Debug.Assert(channel != null, "Channels.GetChannel() 异常"); #endif // 缺省的目标数据库路径 ResPath default_target_respath = new ResPath(this.SelectedNode); RmsChannel cur_channel = Channels.CreateTempChannel(default_target_respath.Url); Debug.Assert(cur_channel != null, "Channels.GetChannel() 异常"); List<string> target_dburls = new List<string>(); #if NO DigitalPlatform.Stop stop = null; if (stopManager != null) { stop = new DigitalPlatform.Stop(); stop.Register(this.stopManager, true); // 和容器关联 stop.OnStop += new StopEventHandler(this.DoStop); stop.Initial("正在导入数据 " + respath.FullPath); stop.BeginLoop(); } #endif DigitalPlatform.Stop stop = PrepareStop("正在导入数据 ..."); // + default_target_respath.FullPath); stop.OnStop -= new StopEventHandler(this.DoStop); // 去掉缺省的回调函数 stop.OnStop += (sender1, e1) => { if (cur_channel != null) cur_channel.Abort(); }; stop.Style = StopStyle.EnableHalfStop; // API的间隙才让中断。避免获取结果集的中途,因为中断而导致 Session 失效,结果集丢失,进而无法 Retry 获取 ProgressEstimate estimate = new ProgressEstimate(); try // open import util { bool bDontPromptTimestampMismatchWhenOverwrite = false; DbNameMap map = new DbNameMap(); long lSaveOffs = -1; estimate.SetRange(0, import_util.Stream.Length); estimate.StartEstimate(); stop.SetProgressRange(0, import_util.Stream.Length); List<UploadRecord> records = new List<UploadRecord>(); int nBatchSize = 0; for (int index = 0; ; index++) { Application.DoEvents(); // 出让界面控制权 if (stop.State != 0) { DialogResult result = MessageBox.Show(this, "确实要中断当前批处理操作?", "导入数据", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2); if (result == DialogResult.Yes) { strError = "用户中断"; goto ERROR1; } else { stop.Continue(); } } //string strXml = ""; //string strResPath = ""; //string strTimeStamp = ""; UploadRecord record = null; if (import_util.FileType == ExportFileType.BackupFile) { if (lSaveOffs != -1) import_util.Stream.Seek(lSaveOffs, SeekOrigin.Begin); } nRet = import_util.ReadOneRecord(out record, out strError); if (nRet == -1) goto ERROR1; if (nRet == 1) break; if (import_util.FileType == ExportFileType.BackupFile) { // 保存每次读取后的文件指针位置 lSaveOffs = import_util.Stream.Position; } Debug.Assert(record != null, ""); #if NO XmlDocument dom = new XmlDocument(); try { dom.LoadXml(strXml); } catch (Exception ex) { strError = "XML装入DOM时出错: " + ex.Message; goto ERROR1; } string strResPath = DomUtil.GetAttr(DpNs.dprms, dom.DocumentElement, "path"); string strTimeStamp = DomUtil.GetAttr(DpNs.dprms, dom.DocumentElement, "timestamp"); #endif // 准备目标路径 { string strLongPath = record.Url + "?" + record.RecordBody.Path; #if NO // 根据原始路径准备即将写入的路径 // return: // -1 出错 // 0 用户放弃 // 1 成功 nRet = ImportUtil.PrepareOverwritePath( this.Servers, this.Channels, this, ref map, ref strLongPath, out strError); if (nRet == 0 || nRet == -1) goto ERROR1; #endif // 根据原始路径准备即将写入的路径 // return: // -1 出错 // 0 用户放弃 // 1 成功 // 2 要跳过本条 nRet = ImportUtil.PrepareOverwritePath( this, this.Servers, this.Channels, this.AppInfo, index, default_target_respath.FullPath, ref map, ref strLongPath, out strError); if (nRet == 0 || nRet == -1) goto ERROR1; if (nRet == 2) continue; ResPath respath = new ResPath(strLongPath); record.Url = respath.Url; record.RecordBody.Path = respath.Path; // 记载每个数据库的 URL string strDbUrl = GetDbUrl(strLongPath); if (target_dburls.IndexOf(strDbUrl) == -1) { // 每个数据库要进行一次快速模式的准备操作 if (bFastMode == true) { nRet = ManageKeysIndex(strDbUrl, "beginfastappend", "正在对数据库 "+strDbUrl+" 进行快速导入模式的准备工作 ...", out strError); if (nRet == -1) goto ERROR1; } target_dburls.Add(strDbUrl); } } bool bNeedPush = false; // 是否要把积累的记录推送出去进行写入? // 要进行以下检查: // 1) 当前记录和前一条记录之间,更换了服务器 // 2) 累积的记录尺寸超过要求 // 3) 当前记录是一条超大的记录 (这是因为要保持从文件中读出的顺序来写入(例如追加时候的号码增量顺序),就必须在单条写入本条前,先写入积累的那些记录) if (records.Count > 0) { if (record.TooLarge() == true) bNeedPush = true; else if (nBatchSize + record.RecordBody.Xml.Length > CHUNK_SIZE) bNeedPush = true; else { if (LastUrl(records) != record.Url) bNeedPush = true; } } if (bNeedPush == true) { // 准备 Channel Debug.Assert(records.Count > 0, ""); cur_channel = ImportUtil.GetChannel(this.Channels, stop, LastUrl(records), cur_channel); List<UploadRecord> save_records = new List<UploadRecord>(); save_records.AddRange(records); while (records.Count > 0) { // 将 XML 记录成批写入数据库 // return: // -1 出错 // >=0 本次已经写入的记录个数。本函数返回时 records 集合的元素数没有变化(但元素的Path和Timestamp会有变化),如果必要调主可截取records集合中后面未处理的部分再次调用本函数 nRet = ImportUtil.WriteRecords( this, stop, cur_channel, bFastMode, records, ref bDontPromptTimestampMismatchWhenOverwrite, out strError); if (nRet == -1) goto ERROR1; if (nRet == 0) { // TODO: 或可以改为单条写入 strError = "WriteRecords() error :" + strError; goto ERROR1; } Debug.Assert(nRet <= records.Count, ""); records.RemoveRange(0, nRet); lTotalCount += nRet; } // 上载对象 // return: // -1 出错 // 0 成功 nRet = import_util.UploadObjects( stop, cur_channel, save_records, ref bDontPromptTimestampMismatchWhenOverwrite, out strError); if (nRet == -1) goto ERROR1; nBatchSize = 0; stop.SetProgressValue(import_util.Stream.Position); stop.SetMessage("已经写入记录 " + lTotalCount.ToString() + " 条。" + "剩余时间 " + ProgressEstimate.Format(estimate.Estimate(import_util.Stream.Position)) + " 已经过时间 " + ProgressEstimate.Format(estimate.delta_passed)); } // 如果 记录的 XML 尺寸太大不便于成批上载,需要在单独直接上载 if (record.TooLarge() == true) { // 准备 Channel // ResPath respath = new ResPath(record.RecordBody.Path); cur_channel = ImportUtil.GetChannel(this.Channels, stop, record.Url, cur_channel); // 写入一条 XML 记录 // return: // -1 出错 // 0 邀请中断整个处理 // 1 成功 // 2 跳过本条,继续处理后面的 nRet = ImportUtil.WriteOneXmlRecord( this, stop, cur_channel, record, ref bDontPromptTimestampMismatchWhenOverwrite, out strError); if (nRet == -1) goto ERROR1; if (nRet == 0) goto ERROR1; List<UploadRecord> temp = new List<UploadRecord>(); temp.Add(record); // 上载对象 // return: // -1 出错 // 0 成功 nRet = import_util.UploadObjects( stop, cur_channel, temp, ref bDontPromptTimestampMismatchWhenOverwrite, out strError); if (nRet == -1) goto ERROR1; lTotalCount += 1; continue; } records.Add(record); if (record.RecordBody != null && record.RecordBody.Xml != null) nBatchSize += record.RecordBody.Xml.Length; } // 最后提交一次 if (records.Count > 0) { // 准备 Channel Debug.Assert(records.Count > 0, ""); cur_channel = ImportUtil.GetChannel(this.Channels, stop, LastUrl(records), cur_channel); List<UploadRecord> save_records = new List<UploadRecord>(); save_records.AddRange(records); while (records.Count > 0) { // 将 XML 记录成批写入数据库 // return: // -1 出错 // >=0 本次已经写入的记录个数。本函数返回时 records 集合的元素数没有变化(但元素的Path和Timestamp会有变化),如果必要调主可截取records集合中后面未处理的部分再次调用本函数 nRet = ImportUtil.WriteRecords( this, stop, cur_channel, bFastMode, records, ref bDontPromptTimestampMismatchWhenOverwrite, out strError); if (nRet == -1) goto ERROR1; if (nRet == 0) { strError = "WriteRecords() error :" + strError; goto ERROR1; } Debug.Assert(nRet <= records.Count, ""); records.RemoveRange(0, nRet); lTotalCount += nRet; } // 上载对象 // return: // -1 出错 // 0 成功 nRet = import_util.UploadObjects( stop, cur_channel, save_records, ref bDontPromptTimestampMismatchWhenOverwrite, out strError); if (nRet == -1) goto ERROR1; nBatchSize = 0; stop.SetProgressValue(import_util.Stream.Position); stop.SetMessage("已经写入记录 " + lTotalCount.ToString() + " 条。" + "剩余时间 " + ProgressEstimate.Format(estimate.Estimate(import_util.Stream.Position)) + " 已经过时间 " + ProgressEstimate.Format(estimate.delta_passed)); records.Clear(); nBatchSize = 0; } }// close import util finally { if (bFastMode == true) { foreach (string url in target_dburls) { string strQuickModeError = ""; nRet = ManageKeysIndex(url, "endfastappend", "正在对数据库 " + url + " 进行快速导入模式的收尾工作,请耐心等待 ...", out strQuickModeError); if (nRet == -1) MessageBox.Show(this, strQuickModeError); } } EndStop(stop); #if NO if (stopManager != null) { stop.EndLoop(); stop.OnStop -= new StopEventHandler(this.DoStop); stop.Initial(""); stop.Unregister(); // 和容器脱离关联 } #endif cur_channel.Close(); cur_channel = null; import_util.End(); } strTimeMessage = "总共耗费时间: " + estimate.GetTotalTime().ToString(); MessageBox.Show(this, "文件 " + dlg.FileName + " 内的数据已经成功导入下列数据库:\r\n\r\n" + StringUtil.MakePathList(target_dburls, "\r\n") + "\r\n\r\n共导入记录 " + lTotalCount.ToString() + " 条。\r\n\r\n" + strTimeMessage); return 0; ERROR0: MessageBox.Show(this, strError); return -1; ERROR1: MessageBox.Show(this, strError); // 使用了 lTotalCount 和 estimate 以后的报错 if (lTotalCount > 0) { strTimeMessage = "总共耗费时间: " + estimate.GetTotalTime().ToString(); MessageBox.Show(this, "文件 " + dlg.FileName + " 内的部分数据已经成功导入下列数据库:\r\n\r\n" + StringUtil.MakePathList(target_dburls, "\r\n") + "\r\n\r\n共导入记录 " + lTotalCount.ToString() + " 条。\r\n\r\n" + strTimeMessage); } return -1; }
// 询问无法匹配的源路径如何处理 // return: // -1 出错 // 0 cancel全部处理 // 1 已经选择处理办法 public static int AskNotMatchOriginBox( IWin32Window owner, ApplicationInfo ap, ServerCollection Servers, RmsChannelCollection Channels, string strComment, string strSelectedLongPath, string strOrigin, DbNameMap map) { DbNameMapItemDlg dlg = new DbNameMapItemDlg(); dlg.Font = GuiUtil.GetDefaultFont(); dlg.Servers = Servers; dlg.Channels = Channels; dlg.Comment = strComment; dlg.AskMode = AskMode.AskNotMatchOrigin; dlg.Origin = strOrigin; dlg.Target = strSelectedLongPath; dlg.WriteMode = "append"; dlg.Text = "请指定映射关系"; if (ap != null) ap.LinkFormState(dlg, "AskNotMatchOriginBox_state"); dlg.ShowDialog(owner); if (ap != null) ap.UnlinkFormState(dlg); if (dlg.DialogResult != DialogResult.OK) return 0; // cancel string strError = ""; if (map.NewItem(dlg.Origin, dlg.Target, dlg.WriteMode, 0, // 插入最前面 out strError) == null) { MessageBox.Show(owner, strError); return -1; } return 1; }
// 询问空源路径如何处理 // return: // -1 出错 // 0 cancel全部处理 // 1 已经选择处理办法 public static int AskNullOriginBox( IWin32Window owner, ApplicationInfo ap, string strComment, SearchPanel searchpanel, DbNameMap map) { DbNameMapItemDlg dlg = new DbNameMapItemDlg(); dlg.Font = GuiUtil.GetDefaultFont(); dlg.Comment = strComment; dlg.AskMode = AskMode.AskNullOrigin; dlg.SearchPanel = searchpanel; dlg.Origin = "{null}"; dlg.Target = ""; dlg.WriteMode = "append"; dlg.Text = "请指定映射关系"; if (ap != null) ap.LinkFormState(dlg, "AskNotMatchOriginBox_state"); dlg.ShowDialog(owner); if (ap != null) ap.UnlinkFormState(dlg); if (dlg.DialogResult != DialogResult.OK) return 0; // cancel string strError = ""; if (map.NewItem(dlg.Origin, dlg.Target, dlg.WriteMode, 0,// 插入最前面 out strError) == null) { MessageBox.Show(owner, strError); return -1; } return 1; }
// 根据原始路径准备即将写入的路径 // return: // -1 出错 // 0 用户放弃 // 1 成功 public static int PrepareOverwritePath( ServerCollection Servers, RmsChannelCollection Channels, IWin32Window owner, ref DbNameMap map, ref string strLongPath, out string strError) { strError = ""; // 从map中查询覆盖还是追加? ResPath respath = new ResPath(strLongPath); respath.MakeDbName(); REDO: DbNameMapItem mapItem = (DbNameMapItem)map["*"]; if (mapItem != null) { } else { mapItem = (DbNameMapItem)map[respath.FullPath.ToUpper()]; } if (mapItem == null) { OriginNotFoundDlg dlg = new OriginNotFoundDlg(); Font font = GuiUtil.GetDefaultFont(); if (font != null) dlg.Font = font; dlg.Message = "数据中声明的数据库路径 '" +respath.FullPath+ "' 在覆盖关系对照表中没有找到, 请选择覆盖方式: " ; dlg.Origin = respath.FullPath.ToUpper(); dlg.Servers = Servers; dlg.Channels = Channels; dlg.Map = map; dlg.StartPosition = FormStartPosition.CenterScreen; dlg.ShowDialog(owner); if (dlg.DialogResult != DialogResult.OK) { strError = "用户中断..."; return 0; } map = dlg.Map; goto REDO; } if (mapItem.Style == "skip") return 0; // 构造目标路径 // 1)从源路径中提取id。源路径来自备份文件数据 respath = new ResPath(strLongPath); string strID = respath.GetRecordId(); if (string.IsNullOrEmpty(strID) == true || mapItem.Style == "append") { strID = "?"; // 将来加一个对话框 } // 2)用目标库路径构造完整的记录路径 string strTargetFullPath = ""; if (mapItem.Target == "*") { respath = new ResPath(strLongPath); respath.MakeDbName(); strTargetFullPath = respath.FullPath; } else { strTargetFullPath = mapItem.Target; } respath = new ResPath(strTargetFullPath); respath.Path = respath.Path + "/" + strID; strLongPath = respath.FullPath; return 1; }
// 根据原始路径准备即将写入的路径 // parameters: // strSelectedLongPath 用户选定的默认的目标库长路径。将优先出现在询问对话框的目标中 // return: // -1 出错 // 0 用户放弃 // 1 成功 // 2 要跳过本条 public static int PrepareOverwritePath( IWin32Window owner, ServerCollection Servers, RmsChannelCollection Channels, ApplicationInfo AppInfo, long lIndex, string strSelectedLongPath, ref DbNameMap map, ref string strLongPath, out string strError) { strError = ""; int nRet = 0; ResPath respath = new ResPath(strLongPath); respath.MakeDbName(); string strSourceDbPath = respath.FullPath; REDO: DbNameMapItem mapItem = null; mapItem = map.MatchItem(strSourceDbPath); if (mapItem != null) goto MAPITEMOK; if (mapItem == null) { if (string.IsNullOrEmpty(strSourceDbPath) == true) { string strText = "源数据文件中记录 " + lIndex.ToString() + " 没有来源数据库。\r\n请问对所有这样的数据,将作如何处理?"; // WriteLog("打开对话框 '" + strText.Replace("\r\n", "\\n") + "'"); nRet = DbNameMapItemDlg.AskNullOriginBox( owner, AppInfo, Servers, Channels, strText, strSelectedLongPath, map); // WriteLog("关闭对话框 '" + strText.Replace("\r\n", "\\n") + "'"); if (nRet == 0) { strError = "用户中断"; return 0; // 中断整个处理 } goto REDO; } else { string strText = "源数据文件中记录 " + lIndex.ToString() + " 的来源数据库 '" + strSourceDbPath + "' 没有明确的对应规则。\r\n请问对所有这样的数据,将作如何处理?"; // 没有找到对应的目标库 // WriteLog("打开对话框 '" + strText.Replace("\r\n", "\\n") + "'"); nRet = DbNameMapItemDlg.AskNotMatchOriginBox( owner, AppInfo, Servers, Channels, strText, strSelectedLongPath, strSourceDbPath/*strResPath*/, map); // WriteLog("关闭对话框 '" + strText.Replace("\r\n", "\\n") + "'"); if (nRet == 0) { strError = "用户中断"; return 0; // 中断整个处理 } goto REDO; } } MAPITEMOK: if (mapItem.Style == "skip") return 2; // 构造目标路径 // 1)从源路径中提取id。源路径来自备份文件数据 respath = new ResPath(strLongPath); string strID = respath.GetRecordId(); if (string.IsNullOrEmpty(strID) == true || mapItem.Style == "append") { strID = "?"; // 将来加一个对话框 } // 2)用目标库路径构造完整的记录路径 string strTargetFullPath = ""; if (mapItem.Target == "*") { respath = new ResPath(strLongPath); respath.MakeDbName(); strTargetFullPath = respath.FullPath; } else { strTargetFullPath = mapItem.Target; } respath = new ResPath(strTargetFullPath); respath.Path = respath.Path + "/" + strID; strLongPath = respath.FullPath; return 1; }