// 根据数据库模板的定义,刷新一个已经存在的数据库的定义 // return: // -1 // 0 keys定义没有更新 // 1 keys定义更新了 int RefreshDatabase(RmsChannel channel, string strTemplateDir, string strDatabaseName, string strIncludeFilenames, string strExcludeFilenames, out string strError) { strError = ""; int nRet = 0; strIncludeFilenames = strIncludeFilenames.ToLower(); strExcludeFilenames = strExcludeFilenames.ToLower(); bool bKeysChanged = false; DirectoryInfo di = new DirectoryInfo(strTemplateDir); FileInfo[] fis = di.GetFiles(); // 创建所有文件对象 for (int i = 0; i < fis.Length; i++) { string strName = fis[i].Name; if (strName == "." || strName == "..") continue; if (FileUtil.IsBackupFile(strName) == true) continue; /* if (strName.ToLower() == "keys" || strName.ToLower() == "browse") continue; * */ // 如果Include和exclude里面都有一个文件名,优先依exclude(排除) if (StringUtil.IsInList(strName, strExcludeFilenames) == true) continue; if (strIncludeFilenames != "*") { if (StringUtil.IsInList(strName, strIncludeFilenames) == false) continue; } string strFullPath = fis[i].FullName; nRet = ConvertGb2312TextfileToUtf8(strFullPath, out strError); if (nRet == -1) return -1; string strExistContent = ""; string strNewContent = ""; Stream new_stream = new FileStream(strFullPath, FileMode.Open); { StreamReader sr = new StreamReader(new_stream, Encoding.UTF8); strNewContent = ConvertCrLf(sr.ReadToEnd()); } new_stream.Seek(0, SeekOrigin.Begin); try { string strPath = strDatabaseName + "/cfgs/" + strName; // 获取已有的配置文件对象 byte[] timestamp = null; string strOutputPath = ""; string strMetaData = ""; string strStyle = "content,data,metadata,timestamp,outputpath"; MemoryStream exist_stream = new MemoryStream(); try { long lRet = channel.GetRes( strPath, exist_stream, null, // stop, strStyle, null, // byte [] input_timestamp, out strMetaData, out timestamp, out strOutputPath, out strError); if (lRet == -1) { // 配置文件不存在,怎么返回错误码的? if (channel.ErrorCode == ChannelErrorCode.NotFound) { timestamp = null; goto DO_CREATE; } return -1; } exist_stream.Seek(0, SeekOrigin.Begin); { StreamReader sr = new StreamReader(exist_stream, Encoding.UTF8); strExistContent = ConvertCrLf(sr.ReadToEnd()); } } finally { if (exist_stream != null) exist_stream.Close(); } // 比较本地的和服务器的有无区别,无区别就不要上载了 if (strExistContent == strNewContent) { continue; } DO_CREATE: // 在服务器端创建对象 // parameters: // strStyle 风格。当创建目录的时候,为"createdir",否则为空 // return: // -1 错误 // 1 已经存在同名对象 // 0 正常返回 nRet = NewServerSideObject( channel, strPath, "", new_stream, timestamp, out strError); if (nRet == -1) return -1; if (nRet == 1) { strError = "NewServerSideObject()发现已经存在同名对象: " + strError; return -1; } if (strName.ToLower() == "keys") bKeysChanged = true; } finally { new_stream.Close(); } } if (bKeysChanged == true) { // 对数据库及时调用刷新keys表的API long lRet = channel.DoRefreshDB( "begin", strDatabaseName, false, out strError); if (lRet == -1) { strError = "数据库 '" + strDatabaseName + "' 的定义已经被成功刷新,但在刷新内核Keys表操作时失败: " + strError; return -1; } return 1; } return 0; }
void RefreshDB(bool bClearAllKeyTables) { if (this.SelectedNode == null) { MessageBox.Show(this, "尚未选择要刷新定义的数据库节点"); return; } if (this.SelectedNode.ImageIndex != RESTYPE_DB) { MessageBox.Show(this, "所选择的节点不是数据库类型。请选择要刷新定义的数据库节点。"); return; } ResPath respath = new ResPath(this.SelectedNode); string strText = "确实要刷新位于服务器 '" + respath.Url + "' 上的数据库 '" + respath.Path + "' 的定义吗?\r\n\r\n注:刷新数据库定义,会为数据库增补在keys配置文件中新增的SQL表,不会损坏数据库中已有的数据。"; DialogResult msgResult = MessageBox.Show(this, strText, "刷新数据库定义", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2); if (msgResult != DialogResult.OK) { MessageBox.Show(this, "刷新数据库定义的操作被放弃..."); return; } this.channel = Channels.GetChannel(respath.Url); Debug.Assert(channel != null, "Channels.GetChannel() 异常"); string strError = ""; #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("正在刷新数据库定义: " + respath.FullPath); long lRet = channel.DoRefreshDB( "begin", respath.Path, bClearAllKeyTables, out strError); EndStop(stop); #if NO if (stopManager != null) { stop.EndLoop(); stop.OnStop -= new StopEventHandler(this.DoStop); stop.Initial(""); stop.Unregister(); // 和容器脱离关联 } #endif this.channel = null; if (lRet == -1) { MessageBox.Show(this, strError); } else { MessageBox.Show(this, "位于服务器'" + respath.Url + "'上的数据库 '" + respath.Path + "' 被成功刷新了定义。"); } }
// 重建检索点 // TODO: 需要改造为在不校准首位号的情况下进度条也要显示正确。可参考DoExportFile() // parameters: void DoRebuildKeys() { string strError = ""; int nRet = 0; long lRet = 0; string strInfo = ""; // 汇总信息,在完成后显示 // bClearKeysAtBegin 批处理开始的时候清除了所有的keys表 // bDeleteOldKeysPerRecord 做每条记录的时候是否要先删除属于这条记录的旧的检索点。 bool bClearKeysAtBegin = true; bool bDeleteOldKeysPerRecord = false; m_nRecordCount = -1; if (textBox_dbPath.Text == "") { MessageBox.Show(this, "尚未选择要重建检索点的数据库 ..."); return; } DialogResult result = MessageBox.Show(this, "确实要对下列数据库\r\n---\r\n" + this.textBox_dbPath.Text.Replace(";", "\r\n") + "\r\n---\r\n进行重建检索点的操作?", "dp2batch", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2); if (result == DialogResult.No) return; RebuildKeysDialog option_dlg = new RebuildKeysDialog(); MainForm.SetControlFont(option_dlg, this.DefaultFont); option_dlg.StartPosition = FormStartPosition.CenterScreen; option_dlg.ShowDialog(this); if (option_dlg.DialogResult == DialogResult.Cancel) return; if (option_dlg.WholeMode == true) { bClearKeysAtBegin = true; bDeleteOldKeysPerRecord = false; } else { bClearKeysAtBegin = false; bDeleteOldKeysPerRecord = true; } string[] dbpaths = textBox_dbPath.Text.Split(new char[] { ';' }); // 如果为单库输出 if (dbpaths.Length == 1) { // 否则移到DoExportFile()函数里面去校验 ResPath respath = new ResPath(dbpaths[0]); channel = this.Channels.GetChannel(respath.Url); string strDbName = respath.Path; // 校验起止号 if (checkBox_verifyNumber.Checked == true) { nRet = VerifyRange(channel, strDbName, out strError); if (nRet == -1) MessageBox.Show(this, strError); } else { if (this.textBox_startNo.Text == "") { strError = "尚未指定起始号"; goto ERROR1; } if (this.textBox_endNo.Text == "") { strError = "尚未指定结束号"; goto ERROR1; } } } else { Debug.Assert(dbpaths.Length > 1, ""); // 多库输出。修改界面要素,表示针对每个库都是全库处理 this.radioButton_all.Checked = true; this.textBox_startNo.Text = "1"; this.textBox_endNo.Text = "9999999999"; } stop.OnStop += new StopEventHandler(this.DoStop); stop.Initial("正在重建检索点"); stop.BeginLoop(); EnableControls(false); try { // TODO: 如果是多库输出,是否要对非“全部”的起止号范围进行警告? 因为后面是强迫按照全部来进行的 for (int f = 0; f < dbpaths.Length; f++) { string strOneDbPath = dbpaths[f]; ResPath respath = new ResPath(strOneDbPath); channel = this.Channels.GetChannel(respath.Url); string strDbName = respath.Path; if (String.IsNullOrEmpty(strInfo) == false) strInfo += "\r\n"; strInfo += "" + strDbName; // 实际处理的首尾号 string strRealStartNo = ""; string strRealEndNo = ""; /* DialogResult result; if (checkBox_export_delete.Checked == true) { result = MessageBox.Show(this, "确实要删除" + respath.Path + "内指定范围的记录?\r\n\r\n---------\r\n(是)删除 (否)放弃批处理", "dp2batch", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2); if (result != DialogResult.Yes) continue; }*/ // // 如果为多库重建 if (dbpaths.Length > 1) { // 如果为全选 if (this.radioButton_all.Checked == true || f > 0) { // 恢复为最大范围 this.textBox_startNo.Text = "1"; this.textBox_endNo.Text = "9999999999"; } // 校验起止号 if (checkBox_verifyNumber.Checked == true) { nRet = VerifyRange(channel, strDbName, out strError); if (nRet == -1) MessageBox.Show(this, strError); if (nRet == 0) { // 库中无记录 AutoCloseMessageBox.Show(this, "数据库 " + strDbName + " 中无记录。"); strInfo += "(无记录)"; /* if (bClearKeysAtBegin == true) { // 结束Refresh数据库定义 lRet = channel.DoRefreshDB( "end", strDbName, false, // 此参数此时无用 out strError); if (lRet == -1) goto ERROR1; } * */ continue; } } else { if (this.textBox_startNo.Text == "") { strError = "尚未指定起始号"; goto ERROR1; } if (this.textBox_endNo.Text == "") { strError = "尚未指定结束号"; goto ERROR1; } } } Int64 nStart; Int64 nEnd; Int64 nCur; bool bAsc = GetDirection( this.textBox_startNo.Text, this.textBox_endNo.Text, out nStart, out nEnd); // 设置进度条范围 Int64 nMax = nEnd - nStart; if (nMax < 0) nMax *= -1; nMax++; /* ProgressRatio = nMax / 10000; if (ProgressRatio < 1.0) ProgressRatio = 1.0; progressBar_main.Minimum = 0; progressBar_main.Maximum = (int)(nMax / ProgressRatio); progressBar_main.Value = 0; * */ stop.SetProgressRange(0, nMax); // Refresh数据库定义 lRet = channel.DoRefreshDB( "begin", strDbName, bClearKeysAtBegin == true ? true : false, out strError); if (lRet == -1) goto ERROR1; bool bFirst = true; // 是否为第一次取记录 string strID = this.textBox_startNo.Text; m_nRecordCount = 0; // 循环 for (; ; ) { Application.DoEvents(); // 出让界面控制权 if (stop.State != 0) { result = MessageBox.Show(this, "确实要中断当前批处理操作?", "dp2batch", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2); if (result == DialogResult.Yes) { strError = "用户中断"; goto ERROR1; } else { stop.Continue(); } } string strDirectionComment = ""; string strStyle = ""; strStyle = "timestamp,outputpath"; // 优化 if (bDeleteOldKeysPerRecord == true) strStyle += ",forcedeleteoldkeys"; if (bFirst == true) { // 注:如果不校验首号,只有强制循环的情况下,才能不需要next风格 strStyle += ""; } else { if (bAsc == true) { strStyle += ",next"; strDirectionComment = "的后一条记录"; } else { strStyle += ",prev"; strDirectionComment = "的前一条记录"; } } string strPath = strDbName + "/" + strID; string strOutputPath = ""; bool bFoundRecord = false; bool bNeedRetry = true; REDO_REBUILD: // 获得资源 // return: // -1 出错。具体出错原因在this.ErrorCode中。this.ErrorInfo中有出错信息。 // 0 成功 lRet = channel.DoRebuildResKeys(strPath, strStyle, out strOutputPath, out strError); if (lRet == -1) { if (channel.ErrorCode == ChannelErrorCode.NotFound) { if (bFirst == true) { // 如果要强制循环 if (checkBox_forceLoop.Checked == true) { AutoCloseMessageBox.Show(this, "您为数据库 " + strDbName + " 指定的首记录 " + strID + strDirectionComment + " 不存在。\r\n\r\n按 确认 继续向后找。"); bFirst = false; goto CONTINUE; } else { // 如果不要强制循环,此时也不能结束,否则会让用户以为数据库里面根本没有数据 AutoCloseMessageBox.Show(this, "您为数据库 " + strDbName + " 指定的首记录 " + strID + strDirectionComment + " 不存在。\r\n\r\n(注:为避免出现此提示,可在操作前勾选“校准首尾ID”)\r\n\r\n按 确认 继续向后找..."); bFirst = false; goto CONTINUE; } } else { Debug.Assert(bFirst == false, ""); if (bFirst == true) { strError = "记录 " + strID + strDirectionComment + " 不存在。处理结束。"; } else { if (bAsc == true) strError = "记录 " + strID + " 是最末一条记录。处理结束。"; else strError = "记录 " + strID + " 是最前一条记录。处理结束。"; } if (dbpaths.Length > 1) break; // 多库情况,继续其它库循环 else { bNeedRetry = false; // 单库情况,也没有必要出现重试对话框 MessageBox.Show(this, strError); break; } } } else if (channel.ErrorCode == ChannelErrorCode.EmptyRecord) { bFirst = false; // bFoundRecord = false; // 把id解析出来 strID = ResPath.GetRecordId(strOutputPath); goto CONTINUE; } // 允许重试 if (bNeedRetry == true) { DialogResult redo_result = MessageBox.Show(this, "重建检索点 记录 '" + strPath + "' (style='" + strStyle + "')时出现错误: " + strError + "\r\n\r\n重试,还是中断当前批处理操作?\r\n(Retry 重试;Cancel 中断批处理)", "dp2batch", MessageBoxButtons.RetryCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1); if (redo_result == DialogResult.Cancel) goto ERROR1; goto REDO_REBUILD; } else { goto ERROR1; } } // end of nRet == -1 bFirst = false; bFoundRecord = true; // 把id解析出来 strID = ResPath.GetRecordId(strOutputPath); stop.SetMessage("已重建检索点 记录 " + strOutputPath + " " + m_nRecordCount.ToString()); if (String.IsNullOrEmpty(strRealStartNo) == true) { strRealStartNo = strID; } strRealEndNo = strID; CONTINUE: // 是否超过循环范围 try { nCur = Convert.ToInt64(strID); } catch { // ??? nCur = 0; } if (bAsc == true && nCur > nEnd) break; if (bAsc == false && nCur < nEnd) break; if (bFoundRecord == true) m_nRecordCount++; // // if (bAsc == true) { // progressBar_main.Value = (int)((nCur - nStart + 1) / ProgressRatio); stop.SetProgressValue(nCur - nStart + 1); } else { // ? // progressBar_main.Value = (int)((nStart - nCur + 1) / ProgressRatio); stop.SetProgressValue(nStart - nCur + 1); } // 对已经作过的进行判断 if (bAsc == true && nCur >= nEnd) break; if (bAsc == false && nCur <= nEnd) break; } if (bClearKeysAtBegin == true) { // 结束Refresh数据库定义 lRet = channel.DoRefreshDB( "end", strDbName, false, // 此参数此时无用 out strError); if (lRet == -1) goto ERROR1; } strInfo += " : " + m_nRecordCount.ToString() + "条 (ID " + strRealStartNo + "-" + strRealEndNo + ")"; } // end of dbpaths loop } // end of try finally { EnableControls(true); stop.EndLoop(); stop.OnStop -= new StopEventHandler(this.DoStop); stop.Initial(""); } strError = "重建检索点完成。\r\n---\r\n" + strInfo; // END1: MessageBox.Show(this, strError); return; ERROR1: MessageBox.Show(this, strError); }
int ManageKeysIndex( string strDbUrl, string strAction, string strMessage, out string strError) { strError = ""; ResPath respath = null; if (strDbUrl == null) { if (this.SelectedNode == null) { strError = "尚未选择要要操作的数据库节点"; goto ERROR1; } if (this.SelectedNode.ImageIndex != RESTYPE_DB) { strError = "所选择的节点不是数据库类型。请选择要操作的数据库节点。"; goto ERROR1; } respath = new ResPath(this.SelectedNode); } else respath = new ResPath(strDbUrl); this.channel = Channels.GetChannel(respath.Url); Debug.Assert(channel != null, "Channels.GetChannel() 异常"); #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( strMessage == null ? "正在对 " + respath.FullPath + " 进行管理操作 " + strAction + " ..." : strMessage); TimeSpan old_timeout = channel.Timeout; if (strAction == "endfastappend") { // 收尾阶段可能要耗费很长的时间 channel.Timeout = new TimeSpan(3, 0, 0); } try { long lRet = channel.DoRefreshDB( strAction, respath.Path, false, out strError); if (lRet == -1) { strError = "管理数据库 '" + respath.Path + "' 时出错: " + strError; goto ERROR1; } } finally { EndStop(stop); #if NO if (stopManager != null) { stop.EndLoop(); stop.OnStop -= new StopEventHandler(this.DoStop); stop.Initial(""); stop.Unregister(); // 和容器脱离关联 } #endif if (strAction == "endfastappend") { channel.Timeout = old_timeout; } this.channel = null; } return 0; ERROR1: return -1; }