static int GetLength(Record record) { int nLength = 0; if (record == null) return 0; if (record.Path != null) { nLength += record.Path.Length; nLength += PACKAGE_UNIT_SIZE; // 估计 20 个 bytes 的额外消耗 } if (record.Keys != null) { nLength += GetLength(record.Keys); nLength += PACKAGE_UNIT_SIZE; // 估计 20 个 bytes 的额外消耗 } if (record.Cols != null) nLength += GetLength(record.Cols); if (record.RecordBody != null) nLength += GetLength(record.RecordBody); nLength += PACKAGE_UNIT_SIZE; // 估计 20 个 bytes 的额外消耗 return nLength; }
// 从结果集中提取指定范围的记录 // parameter: // lStart 开始序号 // lLength 长度. -1表示从lStart到末尾 // strLang 语言 // strStyle 样式,以逗号分隔,id:表示取id,cols表示取浏览格式 // 如果包含 format:cfgs/browse 这样的子串,表示指定浏览格式 // aRecord 得到的记录数组,成员为类型为Record // strError out参数,返回出错信息 // result: // -1 出错 // >=0 结果集的总数 public long API_GetRecords( DpResultSet resultSet, long lStart, long lLength, string strLang, string strStyle, out Record[] records, out string strError) { records = null; strError = ""; // DpResultSet resultSet = this.DefaultResultSet; if (resultSet == null) { strError = "GetRecords()出错, resultSet 为 null"; return -1; } long lTotalPackageLength = 0; // 累计计算要输出的XML记录占据的空间 long lOutputLength; // 检查lStart lLength和resultset.Count之间的关系, // 和每批返回最大元素数限制, 综合得出一个合适的尺寸 // return: // -1 出错 // 0 成功 int nRet = ConvertUtil.GetRealLength((int)lStart, (int)lLength, (int)resultSet.Count, SessionInfo.MaxRecordsCountPerApi,//nMaxCount, out lOutputLength, out strError); if (nRet == -1) return -1; bool bKeyCount = StringUtil.IsInList("keycount", strStyle, true); bool bKeyID = StringUtil.IsInList("keyid", strStyle, true); bool bHasID = StringUtil.IsInList("id", strStyle, true); bool bHasCols = StringUtil.IsInList("cols", strStyle, true); bool bHasKey = StringUtil.IsInList("key", strStyle, true); if (bKeyID == true && bHasID == false && bHasCols == false && bHasKey == false) { strError = "strStyle包含了keyid但是没有包含id/key/cols中任何一个,导致API不返回任何内容,操作无意义"; return -1; } bool bXml = StringUtil.IsInList("xml", strStyle, true); bool bWithResMetadata = StringUtil.IsInList("withresmetadata", strStyle, true); bool bTimestamp = StringUtil.IsInList("timestamp", strStyle, true); bool bMetadata = StringUtil.IsInList("metadata", strStyle, true); string strFormat = StringUtil.GetStyleParam(strStyle, "format"); List<Record> results = new List<Record>(100); long lPos = -1; // 中间保持不透明的值 for (long i = 0; i < lOutputLength; i++) { DpRecord dpRecord = null; long lIndex = lStart + i; if (lIndex == lStart) { dpRecord = resultSet.GetFirstRecord( lIndex, false, out lPos); } else { // 取元素比[]操作速度快 dpRecord = resultSet.GetNextRecord( ref lPos); } if (dpRecord == null) break; Record record = new Record(); if (bKeyCount == true) { record.Path = dpRecord.ID; record.Cols = new string[1]; record.Cols[0] = dpRecord.Index.ToString(); #if NO lTotalPackageLength += record.Path.Length; lTotalPackageLength += record.Cols[0].Length; if (lTotalPackageLength > QUOTA_SIZE && i > 0) { // 响应包的尺寸已经超过 1M,并且已经至少包含了一条记录 break; } #endif goto CONTINUE; } DbPath path = new DbPath(dpRecord.ID); Database db = this.app.Dbs.GetDatabaseSafety(path.Name); if (db == null) { strError = "GetDatabaseSafety()从库id '" + path.Name + "' 找数据库对象失败"; return -1; } // 如果有必要获得记录体 string strXml = ""; string strMetadata = ""; byte[] baTimestamp = null; if (bXml == true || bTimestamp == true || bMetadata == true) { // 获得一条记录的 XML 字符串 // return: // -1 出错 // -4 未找到记录 // -10 记录局部未找到 // 0 成功 long lRet = GetXmlBody( db, path.ID, bXml, bTimestamp, bMetadata, bWithResMetadata, out strXml, out strMetadata, out baTimestamp, out strError); if (lRet <= -1) { record.RecordBody = new RecordBody(); record.RecordBody.Xml = strXml; record.RecordBody.Metadata = strMetadata; record.RecordBody.Timestamp = baTimestamp; Result result = new Result(); result.Value = -1; result.ErrorCode = KernelApplication.Ret2ErrorCode((int)lRet); result.ErrorString = strError; record.RecordBody.Result = result; goto CONTINUE; // return lRet; } #if NO lTotalPackageLength += strXml.Length; if (string.IsNullOrEmpty(strMetadata) == false) lTotalPackageLength += strMetadata.Length; if (baTimestamp != null) lTotalPackageLength += baTimestamp.Length * 2; if (lTotalPackageLength > QUOTA_SIZE && i > 0) { // 响应包的尺寸已经超过 1M,并且已经至少包含了一条记录 break; } #endif record.RecordBody = new RecordBody(); record.RecordBody.Xml = strXml; record.RecordBody.Metadata = strMetadata; record.RecordBody.Timestamp = baTimestamp; } if (bKeyID == true) { // string strID = ""; string strKey = ""; // strID = dpRecord.ID; strKey = dpRecord.BrowseText; /* string strText = dpRecord.ID; nRet = strText.LastIndexOf(","); if (nRet != -1) { strKey = strText.Substring(0, nRet); strID = strText.Substring(nRet + 1); } else strID = strText; * */ if (bHasID == true) { // GetCaptionSafety()函数先找到指定语言的库名; // 如果没有找到,就找截短形态的语言的库名; // 再找不到,就用第一种语言的库名。 // 如果连一种语言也没有,则返回库id record.Path = db.GetCaptionSafety(strLang) + "/" + path.CompressedID; // lTotalPackageLength += record.Path.Length; } if (bHasKey == true) { record.Keys = BuildKeyFromArray(strKey); // lTotalPackageLength += GetLength(record.Keys); } if (bHasCols == true) { string[] cols; nRet = db.GetCols( strFormat, path.ID10, strXml, 0, out cols); // 2013/1/14 if (nRet == -1) { if (cols != null && cols.Length > 0) strError = cols[0]; else strError = "GetCols() error"; return -1; } record.Cols = cols; // lTotalPackageLength += nRet; } goto CONTINUE; } { if (bHasID == true) { // GetCaptionSafety()函数先找到指定语言的库名; // 如果没有找到,就找截短形态的语言的库名; // 再找不到,就用第一种语言的库名。 // 如果连一种语言也没有,则返回库id record.Path = db.GetCaptionSafety(strLang) + "/" + path.CompressedID; // lTotalPackageLength += record.Path.Length; } // 在不是keyid的风格下(例如keycount,空),cols全部是浏览列 if (bHasCols == true) { string[] cols; nRet = db.GetCols( strFormat, path.ID10, strXml, 0, out cols); // 2013/1/14 if (nRet == -1) { if (cols != null && cols.Length > 0) strError = cols[0]; else strError = "GetCols() error"; return -1; } record.Cols = cols; // lTotalPackageLength += nRet; } } CONTINUE: lTotalPackageLength += GetLength(record); if (lTotalPackageLength > QUOTA_SIZE && i > 0) { // 响应包的尺寸已经超过 1M,并且已经至少包含了一条记录 break; } // records[i] = record; results.Add(record); Thread.Sleep(0); // 降低CPU耗用? } records = new Record[results.Count]; results.CopyTo(records); return resultSet.Count; }
// 获得一批记录的浏览格式 // 目前情况是:除了数据库名出错以外,其他小错不会终止循环。浏览的第一列放了表示错误的字符串。 // parameter: // paths 记录路径数组 // strStyle 风格 // aRecord 得到的记录数组,成员为类型为Record // result: // -1 出错 // 0 成功 public int API_GetBrowse(string[] paths, string strStyle, out Record[] records, out string strError) { records = null; strError = ""; //定义一个最大数量 ,应该是用尺寸,这里暂时用数组个数计算 //int nMaxCount = 100; bool bHasID = StringUtil.IsInList("id", strStyle); bool bHasCols = StringUtil.IsInList("cols", strStyle); bool bXml = StringUtil.IsInList("xml", strStyle, true); bool bWithResMetadata = StringUtil.IsInList("withresmetadata", strStyle, true); bool bTimestamp = StringUtil.IsInList("timestamp", strStyle, true); bool bMetadata = StringUtil.IsInList("metadata", strStyle, true); string strFormat = StringUtil.GetStyleParam(strStyle, "format"); long lTotalPackageLength = 0; // 累计计算要输出的XML记录占据的空间 List<Record> results = new List<Record>(100); for (long i = 0; i < paths.Length; i++) { Record record = new Record(); string strPath = paths[i]; DbPath path = new DbPath(strPath); Database db = this.app.Dbs.GetDatabaseSafety(path.Name); if (db == null) { strError = "没有找到数据库'" + path.Name + "',换语言版本时出错"; return -1; } if (bHasID == true) { record.Path = strPath; } if (bHasCols == true) { string[] cols; int nRet = db.GetCols( strFormat, path.ID10, "", 0, out cols); if (nRet == -1) { if (cols != null && cols.Length > 0) strError = cols[0]; else strError = "GetCols() error"; return -1; } record.Cols = cols; } // 如果有必要获得记录体 string strXml = ""; string strMetadata = ""; byte[] baTimestamp = null; if (bXml == true || bTimestamp == true || bMetadata == true) { long lRet = GetXmlBody( db, path.ID, bXml, bTimestamp, bMetadata, bWithResMetadata, out strXml, out strMetadata, out baTimestamp, out strError); if (lRet <= -1) return (int)lRet; #if NO lTotalPackageLength += strXml.Length; if (lTotalPackageLength > QUOTA_SIZE && i > 0) { // 响应包的尺寸已经超过 1M,并且已经至少包含了一条记录 break; } #endif record.RecordBody = new RecordBody(); record.RecordBody.Xml = strXml; record.RecordBody.Metadata = strMetadata; record.RecordBody.Timestamp = baTimestamp; } lTotalPackageLength += GetLength(record); if (lTotalPackageLength > QUOTA_SIZE && i > 0) { // 响应包的尺寸已经超过 1M,并且已经至少包含了一条记录 break; } results.Add(record); Thread.Sleep(0); // 降低CPU耗用? } /* if (paths.Length <= SessionInfo.MaxRecordsCountPerApi) records = new Record[paths.Length]; else records = new Record[SessionInfo.MaxRecordsCountPerApi]; * */ records = new Record[results.Count]; results.CopyTo(records); return 0; }