private void _read() { _lenRecord = m_io.ReadU4le(); _type = m_io.ReadU4le(); switch (Type) { case 1699505740: { __raw_body = m_io.ReadBytes((LenRecord - 12)); var io___raw_body = new KaitaiStream(__raw_body); _body = new RecordBody(io___raw_body, this, m_root); break; } case 286331153: { __raw_body = m_io.ReadBytes((LenRecord - 12)); var io___raw_body = new KaitaiStream(__raw_body); _body = new CursorRecordBody(io___raw_body, this, m_root); break; } default: { _body = m_io.ReadBytes((LenRecord - 12)); break; } } _lenRecord2 = m_io.ReadU4le(); }
const int _upload_batchSize = 1000; // 上传结果集每批个数 // 写入 dp2kernel 成为永久结果集 int UploadPermanentResultset(RmsChannel channel, string strResultsetName, DpResultSet resultset, out string strError) { strError = ""; // resultset.Clear(); // testing List<RecordBody> records = new List<RecordBody>(); // 结果集为空,也要在 dp2kernel 端创建一个结果集对象 if (resultset.Count == 0) { RecordBody[] results = null; long lRet = channel.DoWriteRecords(null, records.ToArray(), "createResultset,name:#" + strResultsetName + ",clear,permanent", out results, out strError); if (lRet == -1) return -1; return 0; } #if DETAIL_LOG this.WriteErrorLog("开始上传结果集到 dp2kernel"); #endif long lPos = -1; // 中间保持不透明的值 bool bFirst = true; for (long i = 0; i < resultset.Count; i++) { DpRecord dpRecord = null; long lIndex = i; if (lIndex == 0) { dpRecord = resultset.GetFirstRecord( lIndex, false, out lPos); } else { // 取元素比[]操作速度快 dpRecord = resultset.GetNextRecord( ref lPos); } if (dpRecord == null) break; RecordBody record = new RecordBody(); record.Path = dpRecord.ID; records.Add(record); if (records.Count >= _upload_batchSize || (i >= resultset.Count - 1 && records.Count > 0)) { this._app_down.Token.ThrowIfCancellationRequested(); #if DETAIL_LOG this.WriteErrorLog("一批 " + records.Count); #endif RecordBody[] results = null; long lRet = channel.DoWriteRecords(null, records.ToArray(), "createResultset,name:#~" + strResultsetName + (bFirst ? ",clear" : ""), out results, out strError); if (lRet == -1) return -1; bFirst = false; records.Clear(); } } // 最后一次执行改名、排序 { RecordBody[] results = null; long lRet = channel.DoWriteRecords(null, null, "renameResultset,oldname:#~" + strResultsetName + ",newname:#" + strResultsetName + ",permanent,sort", out results, out strError); if (lRet == -1) return -1; } #if DETAIL_LOG this.WriteErrorLog("结束上传结果集"); #endif return 0; }
public void AddBody(RecordBody body) { records.Add(body); size += body.typePtr.size; }
// 2012/11/11 // 成批写入XML记录 // 浅包装版本 // 每个元素中Xml成员内放了一条完整的XML记录。如果记录不完整,请不要使用此API。 // results中返回和inputs一样数目的元素,每个元素表示对应的inputs元素写入是否成功,返回时间戳和实际写入的路径 // 在中途出错的情况下,results中的元素数目会比inputs中的少,但从前到后顺序是固定的,可以对应 public long DoWriteRecords( DigitalPlatform.Stop stop, RecordBody[] inputs, string strStyle, out RecordBody[] results, out string strError) { strError = ""; results = null; REDO: try { IAsyncResult soapresult = this.ws.BeginWriteRecords( inputs, strStyle, null, null); for (; ; ) { DoIdle(); // 出让控制权,避免CPU资源耗费过度 bool bRet = soapresult.AsyncWaitHandle.WaitOne(100, false); if (bRet == true) break; } if (this.m_ws == null) { strError = "用户中断"; this.ErrorCode = ChannelErrorCode.RequestCanceled; return -1; } // Record[] records = null; Result result = this.ws.EndWriteRecords( out results, soapresult); if (result.Value == -1) { if (result.ErrorCode == ErrorCodeValue.NotLogin && this.Container != null) { // return: // -1 error // 0 login failed // 1 login succeed int nRet = this.UiLogin("", out strError); if (nRet == -1 || nRet == 0) { return -1; } goto REDO; } ConvertErrorCode(result); strError = result.ErrorString; return -1; } else { // 可以在这里检查返回参数 } this.ClearRedoCount(); return result.Value; // 结果集内总数 } catch (Exception ex) { int nRet = ConvertWebError(ex, out strError); if (nRet == 0) return -1; goto REDO; } }
const int _upload_batchSize = 1000; // 上传结果集每批个数 // 写入 dp2kernel 成为永久结果集 int UploadPermanentResultset(RmsChannel channel, string strResultsetName, DpResultSet resultset, out string strError) { strError = ""; // resultset.Clear(); // testing List <RecordBody> records = new List <RecordBody>(); // 结果集为空,也要在 dp2kernel 端创建一个结果集对象 if (resultset.Count == 0) { long lRet = channel.DoWriteRecords(null, records.ToArray(), "createResultset,name:#" + strResultsetName + ",clear,permanent", out RecordBody[] results, out strError); if (lRet == -1) { return(-1); } return(0); } #if DETAIL_LOG this.WriteErrorLog("开始上传结果集到 dp2kernel"); #endif long lPos = -1; // 中间保持不透明的值 bool bFirst = true; for (long i = 0; i < resultset.Count; i++) { DpRecord dpRecord = null; long lIndex = i; if (lIndex == 0) { dpRecord = resultset.GetFirstRecord( lIndex, false, out lPos); } else { // 取元素比[]操作速度快 dpRecord = resultset.GetNextRecord( ref lPos); } if (dpRecord == null) { break; } RecordBody record = new RecordBody(); record.Path = dpRecord.ID; records.Add(record); if (records.Count >= _upload_batchSize || (i >= resultset.Count - 1 && records.Count > 0)) { this._app_down.Token.ThrowIfCancellationRequested(); #if DETAIL_LOG this.WriteErrorLog("一批 " + records.Count); #endif RecordBody[] results = null; long lRet = channel.DoWriteRecords(null, records.ToArray(), "createResultset,name:#~" + strResultsetName + (bFirst ? ",clear" : ""), out results, out strError); if (lRet == -1) { return(-1); } bFirst = false; records.Clear(); } } // 最后一次执行改名、排序 { long lRet = channel.DoWriteRecords(null, null, "renameResultset,oldname:#~" + strResultsetName + ",newname:#" + strResultsetName + ",permanent,sort", out RecordBody[] results, out strError); if (lRet == -1) { return(-1); } } #if DETAIL_LOG this.WriteErrorLog("结束上传结果集"); #endif return(0); }
// 将 XML 记录成批写入数据库 // return: // -1 出错 // >=0 本次已经写入的记录个数。本函数返回时 records 集合的元素数没有变化(但元素的Path和Timestamp会有变化),如果必要调主可截取records集合中后面未处理的部分再次调用本函数 public static int WriteRecords( IWin32Window owner, Stop stop, RmsChannel channel, bool bQuickMode, bool bIfNotExist, List<UploadRecord> records, // List<RecordBody> records, ref bool bDontPromptTimestampMismatchWhenOverwrite, out string strError) { strError = ""; // int nRet = 0; int nProcessCount = 0; // TODO: 需要检查每个 Path 的服务器URL是完全一样的 // 提交 RecordBody[] inputs = new RecordBody[records.Count]; for (int i = 0; i < records.Count; i++) { UploadRecord record = records[i]; inputs[i] = record.RecordBody; Debug.Assert(record.RecordBody != null, ""); } List<string> styles = new List<string>(); if (bQuickMode) styles.Add("fastmode"); if (bIfNotExist) styles.Add("ifnotexist"); // 记录不存在才决定写入 string strStyle = StringUtil.MakePathList(styles); REDO: RecordBody[] results = null; long lRet = channel.DoWriteRecords(stop, inputs, strStyle, // bQuickMode == true ? "fastmode" : "", // strStyle, out results, out strError); if (lRet == -1) return -1; if (results == null) { strError = "results == null"; return -1; } // TODO: 如何面对 Server 的 Quota Exceed 报错? // 出错后改用只提交一个记录的策略?或者更换为传统的保存方式? Debug.Assert(results.Length <= inputs.Length); List<RecordBody> redo_write_list = new List<RecordBody>(); // 需要重做写入的元素 List<RecordBody> redo_timestamp_list = new List<RecordBody>(); // 因为时间戳不匹配,需要重做写入的元素 // 询问时间戳不匹配等报错 string strMessageError = ""; string strMessageTimestamp = ""; for (int i = 0; i < results.Length; i++) { RecordBody result = results[i]; if (result.Result != null && result.Result.ErrorCode != ErrorCodeValue.NoError) { if (bIfNotExist && result.Result.ErrorCode == ErrorCodeValue.Canceled) { // ifnotexist 情况下不要报错 nProcessCount++; continue; } if (result.Result.ErrorCode == ErrorCodeValue.TimestampMismatch) { strMessageTimestamp += "记录 " + result.Path + " 在覆盖保存过程中出错: " + result.Result.ErrorString + "\r\n"; redo_timestamp_list.Add(inputs[i]); } else { strMessageError += "记录 " + result.Path + " 保存过程中出错: " + result.Result.ErrorString + "\r\n"; redo_write_list.Add(inputs[i]); } } else { nProcessCount++; } } if (string.IsNullOrEmpty(strMessageTimestamp) == false) { if (bDontPromptTimestampMismatchWhenOverwrite == false) { DialogResult result = MessageDlg.Show(owner, strMessageTimestamp + "\r\n---\r\n\r\n是否重试以新时间戳强行覆盖保存?\r\n\r\n注:\r\n[重试] 重试强行覆盖\r\n[跳过] 忽略当前记录或资源保存,但继续后面的处理\r\n[中断] 中断整个批处理", "导入数据", MessageBoxButtons.YesNoCancel, MessageBoxDefaultButton.Button1, ref bDontPromptTimestampMismatchWhenOverwrite, new string[] { "重试", "跳过", "中断" }); if (result == DialogResult.Cancel) { strError = strMessageTimestamp; return -1; } if (result == DialogResult.No) { // 跳过 redo_timestamp_list.Clear(); if (redo_timestamp_list.Count + redo_write_list.Count == 0) return results.Length; } } } if (string.IsNullOrEmpty(strMessageError) == false) { bool bDontAsk = false; DialogResult result = MessageDlg.Show(owner, strMessageError + "\r\n---\r\n\r\n是否重试保存?\r\n\r\n注:\r\n[重试] 重试保存\r\n[跳过] 忽略当前记录或资源保存,但继续后面的处理\r\n[中断] 中断整个批处理", "导入数据", MessageBoxButtons.YesNoCancel, MessageBoxDefaultButton.Button1, ref bDontAsk, new string[] { "重试", "跳过", "中断" }); if (result == DialogResult.Cancel) { strError = strMessageError; return -1; } if (result == DialogResult.No) { // 跳过 redo_write_list.Clear(); if (redo_timestamp_list.Count + redo_write_list.Count == 0) return results.Length; } } // for (int i = 0; i < results.Length; i++) { RecordBody result = results[i]; RecordBody record = inputs[i]; record.Path = result.Path; // 实际写入的路径 record.Timestamp = result.Timestamp; // 新的时间戳 } if (redo_write_list.Count + redo_timestamp_list.Count > 0) { inputs = new RecordBody[redo_write_list.Count + redo_timestamp_list.Count]; redo_write_list.CopyTo(inputs); redo_timestamp_list.CopyTo(inputs, redo_write_list.Count); goto REDO; } return nProcessCount; }