// 得到10位的记录ID // return: // -1 出错 // 0 成功 public static int CheckAndGet10RecordID(ref string strRecordID, out string strError) { strError = ""; if (strRecordID == null) { strError = "记录ID不能为null"; return(-1); } if (strRecordID == "") { strError = "记录ID不能为空字符串"; return(-1); } // 大于10不合法 if (strRecordID.Length > 10) { strError = "记录ID '" + strRecordID + "' 不合法,不能大于10位"; return(-1); } //把'?'换成'-1' 因为原来系统都认得'-1' if (strRecordID == "?") { strRecordID = "-1"; } // 不能转换成数据不合法 try { long nId = Convert.ToInt64(strRecordID); // 除-1外,负数不合法 if (nId < -1) { strError = "记录ID '" + strRecordID + "' 不合法"; return(-1); } } catch { strError = "记录ID '" + strRecordID + "' 不合法"; return(-1); } strRecordID = DbPath.GetID10(strRecordID); return(0); }
// 从结果集中提取指定范围的记录 // parameter: // strRanges 范围 // strStyle 样式,以逗号分隔,id:表示取id,cols表示取浏览格式,xml表示取xml记录体 // strLang 语言版本,用来获得记录路径 // richRecords 得到的记录数组,成员为类型为Record // result: // -1 出错 // >=0 结果集的总数 public long API_GetRichRecords( DpResultSet resultset, string strRanges, string strLang, string strStyle, out RichRecord[] richRecords, out string strError) { strError = ""; richRecords = null; int nCurCount = 0; List <RichRecord> aRichRecord = new List <RichRecord>(); string strFormat = StringUtil.GetStyleParam(strStyle, "format"); RangeList rangeList = new RangeList(strRanges); for (int i = 0; i < rangeList.Count; i++) { RangeItem rangeItem = (RangeItem)rangeList[i]; int nStart = (int)rangeItem.lStart; int nLength = (int)rangeItem.lLength; if (nLength == 0) { continue; } // long lPos = 0; // 应该用快速方式,不应用[]??? 2006/3/29 for (int j = 0; j < nLength; j++) { int nRet = 0; DpRecord dpRecord = resultset[j + nStart]; RichRecord richRecord = new RichRecord(); DbPath dbpath = new DbPath(dpRecord.ID); Database db = this.app.Dbs.GetDatabaseSafety(dbpath.Name); if (db == null) //也应放到本条的记录出错信息里 { strError = "没有找到数据库'" + dbpath.Name + "',换语言版本时出错"; richRecord.Result.Value = -1; richRecord.Result.ErrorCode = KernelApplication.Ret2ErrorCode(nRet); richRecord.Result.ErrorString = strError; } else { // 记录路径 if (StringUtil.IsInList("id", strStyle, true) == true || StringUtil.IsInList("path", strStyle, true) == true) { richRecord.Path = db.GetCaptionSafety(strLang) + "/" + dbpath.CompressedID; } // 浏览列 if (StringUtil.IsInList("cols", strStyle, true) == true) { string[] cols = null; nRet = db.GetCols( strFormat, dbpath.ID10, "", 0, out cols); // 2013/1/14 if (nRet == -1) { if (cols != null && cols.Length > 0) { strError = cols[0]; } else { strError = "GetCols() error"; } return(-1); } richRecord.Cols = cols; } bool bXml = false; bool bTimestamp = false; if (StringUtil.IsInList("xml", strStyle, true) == true) { bXml = true; } if (StringUtil.IsInList("timestamp", strStyle, true) == true) { bTimestamp = true; } if (bXml == true || bTimestamp == true) { string strGetStyle = ""; //"data,timestamp"; // ,outputpath, metadata if (bTimestamp == true) { StringUtil.SetInList(ref strGetStyle, "timestamp", true); } if (bXml == true) { StringUtil.SetInList(ref strGetStyle, "data", true); } int nStart0 = 0; int nLength0 = -1; int nMaxLength = 300 * 1024; // 每次最多获取300K int nTotalLength = 0; string strOutputID = ""; byte[] baTotal = null; byte[] baOutputTimestamp = null; int nAdditionError = 0; string strMetadata = ""; for (; ;) { byte[] baData = null; long lRet = db.GetXml(dbpath.ID, "", // strXPath, nStart0, nLength0, nMaxLength, strGetStyle, out baData, out strMetadata, out strOutputID, out baOutputTimestamp, true, out nAdditionError, out strError); if (lRet <= -1) { richRecord.Result.Value = -1; richRecord.Result.ErrorCode = KernelApplication.Ret2ErrorCode(nAdditionError); // nRet? richRecord.Result.ErrorString = strError; goto CONTINUE; } nTotalLength = (int)lRet; // 如果数据体太大 if (nTotalLength > QUOTA_SIZE) { richRecord.Result.Value = -1; richRecord.Result.ErrorCode = ErrorCodeValue.CommonError; richRecord.Result.ErrorString = "数据超过1M"; goto CONTINUE; } baTotal = ByteArray.Add(baTotal, baData); nStart0 += baData.Length; if (nStart0 >= nTotalLength) { break; } } // 记录体 // 转换成字符串 if (StringUtil.IsInList("xml", strStyle, true) == true) { richRecord.Xml = ByteArray.ToString(baTotal); } // 时间戳? if (StringUtil.IsInList("timestamp", strStyle, true) == true) { richRecord.baTimestamp = baOutputTimestamp; } // string strOutputPath = strDbName + "/" + strOutputID; } // 记录体 if (StringUtil.IsInList("xml", strStyle, true) == true) { /* * nRet = db.GetXmlDataSafety(dbpath.ID, * out richRecord.Xml, * out strError); * if (nRet <= -1) * { * richRecord.Result.Value = -1; * richRecord.Result.ErrorCode = RmswsApplication.Ret2ErrorCode(nRet); * richRecord.Result.ErrorString = strError; * } * */ } } CONTINUE: aRichRecord.Add(richRecord); Thread.Sleep(0); nCurCount++; // 如果超出最大范围,则停止 if (nCurCount >= SessionInfo.MaxRecordsCountPerApi) { break; } } } richRecords = new RichRecord[aRichRecord.Count]; for (int i = 0; i < richRecords.Length; i++) { richRecords[i] = aRichRecord[i]; } return(resultset.Count); }
// 从结果集中提取指定范围的记录 // 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 nRet = 0; if (paths == null) { strError = "API_GetBrowse() paths == null"; return(-1); } //定义一个最大数量 ,应该是用尺寸,这里暂时用数组个数计算 //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]; #if NO DbPath path = new DbPath(strPath); Database db = this.app.Dbs.GetDatabaseSafety(path.Name); if (db == null) { strError = "没有找到数据库'" + path.Name + "',换语言版本时出错"; return(-1); } #endif DatabaseCollection.PathInfo info = null; // 解析资源路径 // return: // -1 一般性错误 // -5 未找到数据库 // -7 路径不合法 // 0 成功 nRet = this.app.Dbs.ParsePath(strPath, out info, out strError); if (nRet < 0) { return(-1); } if (info == null) { strError = "ParsePath() (strPath='" + strPath + "') error, info == null"; return(-1); } if (info.IsConfigFilePath == true) { strError = "路径 '" + strPath + "' 不是记录型的路径"; return(-1); } if (bHasID == true) { record.Path = strPath; } if (bHasCols == true && info.IsObjectPath == false) { if (info.Database == null) { strError = "ParsePath() (strPath='" + strPath + "') error, info.Database == null"; return(-1); } string[] cols; nRet = info.Database.GetCols( strFormat, info.RecordID10, // 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 (info.IsObjectPath == false && (bXml == true || bTimestamp == true || bMetadata == true) ) { long lRet = GetXmlBody( info.Database, // db, info.RecordID, // path.ID, bXml, bTimestamp, bMetadata, bWithResMetadata, out strXml, out strMetadata, out baTimestamp, out strError); record.RecordBody = new RecordBody(); record.RecordBody.Xml = strXml; record.RecordBody.Metadata = strMetadata; record.RecordBody.Timestamp = baTimestamp; if (lRet <= -1) { Result result = new Result(); result.Value = -1; result.ErrorCode = KernelApplication.Ret2ErrorCode((int)lRet); result.ErrorString = strError; record.RecordBody.Result = result; // return (int)lRet; } } // 2015/11/14 if (info.IsObjectPath == true && (bTimestamp == true || bMetadata == true) ) { if (info.Database == null) { strError = "ParsePath() (strPath='" + strPath + "') error, info.Database == null"; return(-1); } byte[] buffer = new byte[10]; // return: // -1 出错 // -4 记录不存在 // >=0 资源总长度 long lRet = info.Database.GetObject(info.RecordID, info.ObjectID, 0, 0, -1, strStyle, out buffer, out strMetadata, out baTimestamp, out strError); record.RecordBody = new RecordBody(); record.RecordBody.Xml = ""; record.RecordBody.Metadata = strMetadata; record.RecordBody.Timestamp = baTimestamp; if (lRet <= -1) { Result result = new Result(); result.Value = -1; result.ErrorCode = KernelApplication.Ret2ErrorCode((int)lRet); result.ErrorString = strError; record.RecordBody.Result = result; // return (int)lRet; } } 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); }
// 从结果集中提取指定范围的记录 // parameter: // strRanges 范围 // strStyle 样式,以逗号分隔,id:表示取id,cols表示取浏览格式,xml表示取xml记录体 // strLang 语言版本,用来获得记录路径 // richRecords 得到的记录数组,成员为类型为Record // result: // -1 出错 // >=0 结果集的总数 public long API_GetRichRecords( DpResultSet resultset, string strRanges, string strLang, string strStyle, out RichRecord[] richRecords, out string strError) { strError = ""; richRecords = null; int nCurCount = 0; List<RichRecord> aRichRecord = new List<RichRecord>(); string strFormat = StringUtil.GetStyleParam(strStyle, "format"); RangeList rangeList = new RangeList(strRanges); for (int i = 0; i < rangeList.Count; i++) { RangeItem rangeItem = (RangeItem)rangeList[i]; int nStart = (int)rangeItem.lStart; int nLength = (int)rangeItem.lLength; if (nLength == 0) continue; // long lPos = 0; // 应该用快速方式,不应用[]??? 2006/3/29 for (int j = 0; j < nLength; j++) { int nRet = 0; DpRecord dpRecord = resultset[j + nStart]; RichRecord richRecord = new RichRecord(); DbPath dbpath = new DbPath(dpRecord.ID); Database db = this.app.Dbs.GetDatabaseSafety(dbpath.Name); if (db == null) //也应放到本条的记录出错信息里 { strError = "没有找到数据库'" + dbpath.Name + "',换语言版本时出错"; richRecord.Result.Value = -1; richRecord.Result.ErrorCode = KernelApplication.Ret2ErrorCode(nRet); richRecord.Result.ErrorString = strError; } else { // 记录路径 if (StringUtil.IsInList("id", strStyle, true) == true || StringUtil.IsInList("path", strStyle, true) == true) { richRecord.Path = db.GetCaptionSafety(strLang) + "/" + dbpath.CompressedID; } // 浏览列 if (StringUtil.IsInList("cols", strStyle, true) == true) { string[] cols = null; /*未完成 nRet = db.GetCols(dbpath.ID10, out cols, out strError); if (nRet <= -1) { richRecord.Result.Value = -1; richRecord.Result.ErrorCode = GlobalInfo.Ret2ErrorCode(nRet); richRecord.Result.ErrorString = strError; } */ nRet = db.GetCols( strFormat, dbpath.ID10, "", 0, out cols); // 2013/1/14 if (nRet == -1) { if (cols != null && cols.Length > 0) strError = cols[0]; else strError = "GetCols() error"; return -1; } richRecord.Cols = cols; } bool bXml = false; bool bTimestamp = false; if (StringUtil.IsInList("xml", strStyle, true) == true) bXml = true; if (StringUtil.IsInList("timestamp", strStyle, true) == true) bTimestamp = true; if (bXml == true || bTimestamp == true) { string strGetStyle = ""; //"data,timestamp"; // ,outputpath, metadata if (bTimestamp == true) StringUtil.SetInList(ref strGetStyle, "timestamp", true); if (bXml == true) StringUtil.SetInList(ref strGetStyle, "data", true); int nStart0 = 0; int nLength0 = -1; int nMaxLength = 300 * 1024; // 每次最多获取300K int nTotalLength = 0; string strOutputID = ""; byte[] baTotal = null; byte[] baOutputTimestamp = null; int nAdditionError = 0; string strMetadata = ""; for (; ; ) { byte[] baData = null; long lRet = db.GetXml(dbpath.ID, "", // strXPath, nStart0, nLength0, nMaxLength, strGetStyle, out baData, out strMetadata, out strOutputID, out baOutputTimestamp, true, out nAdditionError, out strError); if (lRet <= -1) { richRecord.Result.Value = -1; richRecord.Result.ErrorCode = KernelApplication.Ret2ErrorCode(nAdditionError); // nRet? richRecord.Result.ErrorString = strError; goto CONTINUE; } nTotalLength = (int)lRet; // 如果数据体太大 if (nTotalLength > QUOTA_SIZE) { richRecord.Result.Value = -1; richRecord.Result.ErrorCode = ErrorCodeValue.CommonError; richRecord.Result.ErrorString = "数据超过1M"; goto CONTINUE; } baTotal = ByteArray.Add(baTotal, baData); nStart0 += baData.Length; if (nStart0 >= nTotalLength) break; } // 记录体 // 转换成字符串 if (StringUtil.IsInList("xml", strStyle, true) == true) { richRecord.Xml = ByteArray.ToString(baTotal); } // 时间戳? if (StringUtil.IsInList("timestamp", strStyle, true) == true) { richRecord.baTimestamp = baOutputTimestamp; } // string strOutputPath = strDbName + "/" + strOutputID; } // 记录体 if (StringUtil.IsInList("xml", strStyle, true) == true) { /* nRet = db.GetXmlDataSafety(dbpath.ID, out richRecord.Xml, out strError); if (nRet <= -1) { richRecord.Result.Value = -1; richRecord.Result.ErrorCode = RmswsApplication.Ret2ErrorCode(nRet); richRecord.Result.ErrorString = strError; } * */ } } CONTINUE: aRichRecord.Add(richRecord); Thread.Sleep(0); nCurCount++; // 如果超出最大范围,则停止 if (nCurCount >= SessionInfo.MaxRecordsCountPerApi) break; } } richRecords = new RichRecord[aRichRecord.Count]; for (int i = 0; i < richRecords.Length; i++) { richRecords[i] = aRichRecord[i]; } return resultset.Count; }
// 从结果集中提取指定范围的记录 // 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; }
/* * // 从用户集合中清除一个用户 * // parameters: * // user 用户对象 * // strError out参数,返回出错信息 * // return: * // -1 出错 * // 0 成功 * // 线:不安全安全 * public int RemoveUser(User user, * out string strError) * { * strError = ""; * * Debug.Assert(user != null, "RemoveUser()调用错误,user参数值不能为null。"); * * int nIndex = this.IndexOf(user); * if (nIndex == -1) * { * strError = "RemoveUser(),user竟然不是集合中的成员,异常。"; * return -1; * } * * this.RemoveAt(nIndex); * * return 0; * } */ // 系统管理员修改用户密码 // parameters: // user 当前帐户 // strChangedUserName 被修改用户名 // strNewPassword 新密码 // strError out参数,返回出错信息 // return: // -1 出错 // -4 记录不存在 // -6 权限不够 // 0 成功 public int ChangePassword(User user, string strChangedUserName, string strNewPassword, out string strError) { strError = ""; User changedUser = null; // return: // -1 出错 // 0 未找到帐户 // 1 找到了 // 线:安全 int nRet = this.GetUserSafety( false, strChangedUserName, this.KernelApplication._app_down.Token, out changedUser, out strError); if (nRet == -1) { return(-1); } if (nRet == 0) { strError = "没有找到名称为'" + strChangedUserName + "'的用户"; return(-1); } Debug.Assert(changedUser != null, "此时userChanged对象不可能为null,请检查服务器的ChangePassword()函数。"); DbPath path = new DbPath(changedUser.RecPath); Database db = this.Dbs.GetDatabase(path.Name); if (db == null) { strError = "未找到帐户'" + strChangedUserName + "'从属的数据库,异常。"; return(-1); } // ???????认不认库的其它语言库名 string strDbName = db.GetCaption("zh-CN"); string strExistRights = ""; bool bHasRight = user.HasRights(strDbName, ResType.Database, "changepassword", out strExistRights); if (bHasRight == false) { strError = "您的帐户名为'" + user.Name + "',对帐户名为'" + strChangedUserName + "'所从属的数据库'" + strDbName + "'没有'修改记录密码(changepassword)'的权限,目前的权限值为'" + strExistRights + "'。"; return(-6); } // return: // -1 出错 // -4 记录不存在 // 0 成功 return(changedUser.ChangePassword(strNewPassword, out strError)); }
// 保存内存对象到数据库记录 // 和m_bChanged状态无关 // return: // -1 出错 // -4 记录不存在 // 0 成功 private int InternalSave(out string strError) { strError = ""; if (this.container == null) { throw new Exception("User对象的container成员不能为null"); } if (String.IsNullOrEmpty(this.m_strRecPath) == true) { strError = "InternalSave失败,因为m_strRecPath为空"; return(-1); } Database db = this.container.m_dbs.GetDatabaseFromRecPath(this.m_strRecPath); if (db == null) { strError = "GetDatabaseFromRecPath()没有找到记录路径'" + this.m_strRecPath + "'对应的数据库对象"; return(-1); } DbPath path = new DbPath(this.RecPath); // 将帐户记录的内容读到一个字节数组 MemoryStream fs = new MemoryStream(); this.m_dom.Save(fs); fs.Seek(0, SeekOrigin.Begin); byte[] baSource = new byte[fs.Length]; fs.Read(baSource, 0, baSource.Length); fs.Close(); string strRange = "0-" + Convert.ToString(baSource.Length - 1); byte[] baInputTimestamp = null; byte[] baOutputTimestamp = null; string strOutputID = ""; string strOutputValue = ""; string strStyle = "ignorechecktimestamp"; // return: // -1 出错 // -2 时间戳不匹配 // 因为风格中有ignorechecktimestamp,所以此次调用不可能出现-2的情况 // -4 记录不存在 // -6 权限不够 // 此次调用不可能出现权限不够的情况 // 0 成功 // 因为传了user对象为null,所以不可能出现权限不够的情况 int nRet = db.WriteXml(null, //oUser path.ID, null, strRange, baSource.Length, baSource, null, "", //metadata strStyle, baInputTimestamp, out baOutputTimestamp, out strOutputID, out strOutputValue, false, //bCheckAccount out strError); Debug.Assert(nRet != -1 && nRet != -4, "不可能的情况。"); return(nRet); }
// 根据记录路径得到数据库对象 public Database GetDatabaseFromRecPath(string strRecPath) { // 创建一个DpPsth实例 DbPath path = new DbPath(strRecPath); // 找到指定帐户数据库 return this.GetDatabaseSafety(path.Name); }
// 根据用户名从库中查找用户记录,得到用户对象 // 对象尚未进入集合, 因此无需为对象加锁 // parameters: // strBelongDb 用户从属的数据库,中文名称 // user out参数,返回帐户对象 // strError out参数,返回出错信息 // return: // -1 出错 // 0 未找到帐户 // 1 找到了 // 线:安全 internal int ShearchUser(string strUserName, out User user, out string strError) { user = null; strError = ""; int nRet = 0; DpResultSet resultSet = new DpResultSet(); //*********对帐户库集合加读锁*********** m_lock.AcquireReaderLock(m_nTimeOut); #if DEBUG_LOCK this.WriteDebugInfo("ShearchUser(),对帐户库集合加读锁。"); #endif try { // return: // -1 出错 // 0 成功 nRet = this.SearchUserInternal(strUserName, resultSet, out strError); if (nRet == -1) return -1; } finally { //*********对帐户库集合解读锁************* m_lock.ReleaseReaderLock(); #if DEBUG_LOCK this.m_dbColl.WriteDebugInfo("ShearchUser(),对帐户库集合解读锁。"); #endif } // 根据用户名没找到对应的帐户记录 long lCount = resultSet.Count; if (lCount == 0) return 0; if (lCount > 1) { strError = "用户名'" + strUserName + "'对应多条记录"; return -1; } // 按第一个帐户算 DpRecord record = (DpRecord)resultSet[0]; // 创建一个DpPsth实例 DbPath path = new DbPath(record.ID); // 找到指定帐户数据库 Database db = this.GetDatabaseSafety(path.Name); if (db == null) { strError = "未找到'" + strUserName + "'帐户对应的名为'" + path.Name + "'的数据库对象"; return -1; } // 从帐户库中找到记录 string strXml = ""; // return: // -1 出错 // -4 记录不存在 // 0 正确 nRet = db.GetXmlDataSafety(path.ID, out strXml, out strError); if (nRet <= -1) // 将-4与-1都作为-1返回 return -1; //加载到dom XmlDocument dom = new XmlDocument(); //dom.PreserveWhitespace = true; //设PreserveWhitespace为true try { dom.LoadXml(strXml); } catch (Exception ex) { strError = "加载用户 '" + strUserName + "' 的帐户记录到dom时出错,原因:" + ex.Message; return -1; } user = new User(); // return: // -1 出错 // 0 成功 nRet = user.Initial( record.ID, dom, db, this, out strError); if (nRet == -1) return -1; return 1; }
// 获取记录的时间戳 // parameters: // strRecordPath 记录路径 // baOutputTimestamp out参数,返回时间戳 // strError out参数,返回出错信息 // return: // -1 出错 // -4 未找到记录 // 0 成功 public int GetTimestampFromDb(string strRecordPath, out byte[] baOutputTimestamp, out string strError) { baOutputTimestamp = null; strError = ""; Debug.Assert(strRecordPath != null && strRecordPath != "", "GetTimestampFromDb()调用错误,strRecordPath参数值不能为null或空字符串。"); DbPath dbpath = new DbPath(strRecordPath); Database db = this.GetDatabase(dbpath.Name); if (db == null) { strError = "未找到名为'" + dbpath.Name + "'的数据库。"; return -1; } // return: // -1 出错 // -4 未找到记录 // 0 成功 int nRet = db.GetTimestampFromDb(dbpath.ID, out baOutputTimestamp, out strError); return nRet; }
// 保存内存对象到数据库记录 // 和m_bChanged状态无关 // return: // -1 出错 // -4 记录不存在 // 0 成功 private int InternalSave(out string strError) { strError = ""; if (this.container == null) throw new Exception("User对象的container成员不能为null"); if (String.IsNullOrEmpty(this.m_strRecPath) == true) { strError = "InternalSave失败,因为m_strRecPath为空"; return -1; } Database db = this.container.m_dbs.GetDatabaseFromRecPath(this.m_strRecPath); if (db == null) { strError = "GetDatabaseFromRecPath()没有找到记录路径'"+this.m_strRecPath+"'对应的数据库对象"; return -1; } DbPath path = new DbPath(this.RecPath); // 将帐户记录的内容读到一个字节数组 MemoryStream fs = new MemoryStream(); this.m_dom.Save(fs); fs.Seek(0, SeekOrigin.Begin); byte[] baSource = new byte[fs.Length]; fs.Read(baSource, 0, baSource.Length); fs.Close(); string strRange = "0-" + Convert.ToString(baSource.Length - 1); byte[] baInputTimestamp = null; byte[] baOutputTimestamp = null; string strOutputID = ""; string strOutputValue = ""; string strStyle = "ignorechecktimestamp"; // return: // -1 出错 // -2 时间戳不匹配 // 因为风格中有ignorechecktimestamp,所以此次调用不可能出现-2的情况 // -4 记录不存在 // -6 权限不够 // 此次调用不可能出现权限不够的情况 // 0 成功 // 因为传了user对象为null,所以不可能出现权限不够的情况 int nRet = db.WriteXml(null, //oUser path.ID, null, strRange, baSource.Length, baSource, null, "", //metadata strStyle, baInputTimestamp, out baOutputTimestamp, out strOutputID, out strOutputValue, false, //bCheckAccount out strError); Debug.Assert(nRet != -1 && nRet != -4, "不可能的情况。"); return nRet; }