// 探测一个结果集在 dp2kernel 一侧是否已经存在 bool LocationResultsetExists(string strLocation) { string strError = ""; // 临时的SessionInfo对象 SessionInfo session = new SessionInfo(this); try { this._app_down.Token.ThrowIfCancellationRequested(); RmsChannel channel = session.Channels.GetChannel(this.WsUrl); if (channel == null) { return(false); } #if DETAIL_LOG this.WriteErrorLog("开始探测结果集 " + strLocation); #endif Record[] searchresults = null; // 获得检索结果的浏览格式 // 浅包装版本 long lHitCount = channel.DoGetSearchResult( "#" + strLocation, 0, 0, "id", "zh", null, out searchresults, out strError); if (lHitCount == -1) { if (channel.ErrorCode == ChannelErrorCode.NotFound) { return(false); } return(false); } return(true); } finally { session.CloseSession(); session = null; } }
protected void Session_End(Object sender, EventArgs e) { SessionInfo sessioninfo = (SessionInfo)Session["sessioninfo"]; Session["sessioninfo"] = null; if (sessioninfo != null) { sessioninfo.CloseSession(); // 减去计数 // string strClientIP = HttpContext.Current.Request.UserHostAddress.ToString(); OpacApplication app = (OpacApplication)Application["app"]; if (app != null) { app.IpTable.IncIpCount(sessioninfo.ClientIP, -1); } } }
protected void Page_Load(object sender, EventArgs e) { if (WebUtil.PrepareEnvironment(this, ref app, ref sessioninfo) == false) { return; } // 是否登录? if (sessioninfo.UserID == "") { sessioninfo.UserID = "public"; sessioninfo.IsReader = false; } string strError = ""; int nRet = 0; #if NO SessionInfo temp_sessioninfo = new SessionInfo(app); temp_sessioninfo.UserID = app.ManagerUserName; temp_sessioninfo.Password = app.ManagerPassword; temp_sessioninfo.IsReader = false; #endif LibraryChannel channel = app.GetChannel(); try { bool bHintDisplayName = false; // []暗示为显示名 string strDisplayName = this.Request["displayName"]; string strBarcode = this.Request["barcode"]; string strEncyptBarcode = Request.QueryString["encrypt_barcode"]; string strText = ""; // 如果为加密的条码形态 if (String.IsNullOrEmpty(strEncyptBarcode) == false) { strBarcode = OpacApplication.DecryptPassword(strEncyptBarcode); if (strBarcode == null) { strError = "encrypt_barcode参数值格式错误"; goto ERROR1; } bHintDisplayName = true; goto SEARCH_COMMENT; } { if (String.IsNullOrEmpty(strDisplayName) == false) { if (strDisplayName.IndexOfAny(new char[] { '[', ']' }) != -1) { bHintDisplayName = true; } strDisplayName = strDisplayName.Replace("[", "").Trim(); strDisplayName = strDisplayName.Replace("]", "").Trim(); } nRet = 0; string strReaderXml = ""; string strOutputReaderPath = ""; if (String.IsNullOrEmpty(strDisplayName) == false) { byte[] timestamp = null; string[] results = null; long lRet = // temp_sessioninfo.Channel. channel.GetReaderInfo( null, "@displayName:" + strDisplayName, "xml", out results, out strOutputReaderPath, out timestamp, out strError); if (lRet == -1) { goto ERROR1; } if (lRet == 0 && bHintDisplayName == true) { strBarcode = ""; goto SEARCH_COMMENT; } strReaderXml = results[0]; // CONTINUE1: if (nRet == 0) { strBarcode = strDisplayName; } } // SEARCH_BARCODE: if (nRet == 0 && String.IsNullOrEmpty(strBarcode) == false) { strReaderXml = ""; byte[] timestamp = null; string[] results = null; long lRet = // temp_sessioninfo.Channel. channel.GetReaderInfo( null, strBarcode, "xml", out results, out strOutputReaderPath, out timestamp, out strError); if (lRet == -1) { goto ERROR1; } if (lRet == 0) { goto SEARCH_COMMENT; } strReaderXml = results[0]; } if (nRet == 0) { /* * strError = "读者显示名或者证条码号 '" + strDisplayName + "' 不存在"; * goto ERROR1; * */ if (String.IsNullOrEmpty(strBarcode) == true) { strBarcode = strDisplayName; } goto SEARCH_COMMENT; } XmlDocument readerdom = null; nRet = OpacApplication.LoadToDom(strReaderXml, out readerdom, out strError); if (nRet == -1) { strError = "装载读者记录 '" + strOutputReaderPath + "' 进入XML DOM时发生错误: " + strError; goto ERROR1; } strDisplayName = DomUtil.GetElementText(readerdom.DocumentElement, "displayName"); strBarcode = DomUtil.GetElementInnerXml(readerdom.DocumentElement, "barcode"); } SEARCH_COMMENT: strText = strDisplayName; if (String.IsNullOrEmpty(strText) == true) { strText = strBarcode; } this.Label_name.Text = strText; string strRecipient = ""; /* * if (String.IsNullOrEmpty(strDisplayName) == false) * { * if (strDisplayName.IndexOf("[") == -1) * strRecipient = "[" + strDisplayName + "]"; * else * strRecipient = strDisplayName; * if (String.IsNullOrEmpty(strEncyptBarcode) == false) * strRecipient += " encrypt_barcode:" + strEncyptBarcode; * } * else * strRecipient = strBarcode; * */ strRecipient = BoxesInfo.BuildOneAddress(strDisplayName, strBarcode); string strSendMessageUrl = "./message.aspx?recipient=" + HttpUtility.UrlEncode(strRecipient); this.Button_sendMessage.OnClientClick = "window.open('" + strSendMessageUrl + "','_blank'); return cancelClick();"; LoginState loginstate = GlobalUtil.GetLoginState(this.Page); if (loginstate == LoginState.NotLogin || loginstate == LoginState.Public) { this.Button_sendMessage.Enabled = false; } this.BrowseSearchResultControl1.Title = strText + " 所发表的书评"; if (String.IsNullOrEmpty(strEncyptBarcode) == false) { this.Image_photo.ImageUrl = "./getphoto.aspx?encrypt_barcode=" + HttpUtility.UrlEncode(strEncyptBarcode) + "&displayName=" + HttpUtility.UrlEncode(strDisplayName); } else { this.Image_photo.ImageUrl = "./getphoto.aspx?barcode=" + HttpUtility.UrlEncode(strBarcode); } this.Image_photo.Width = 128; this.Image_photo.Height = 128; if (this.IsPostBack == false) { string strXml = ""; if (String.IsNullOrEmpty(strDisplayName) == false && String.IsNullOrEmpty(strBarcode) == false) { // 创建评注记录XML检索式 // 用作者和作者显示名共同限定检索 nRet = ItemSearchControl.BuildCommentQueryXml( app, strDisplayName, strBarcode, "<全部>", 15000, // app.SearchMaxResultCount true, out strXml, out strError); if (nRet == -1) { goto ERROR1; } } else if (String.IsNullOrEmpty(strBarcode) == false) { // 创建XML检索式 nRet = ItemSearchControl.BuildQueryXml( this.app, "comment", strBarcode, "<全部>", "作者", "exact", 15000, // app.SearchMaxResultCount true, out strXml, out strError); if (nRet == -1) { goto ERROR1; } } else if (String.IsNullOrEmpty(strDisplayName) == false) { // 创建XML检索式 nRet = ItemSearchControl.BuildQueryXml( this.app, "comment", strDisplayName, "<全部>", "作者显示名", "exact", 15000, // app.SearchMaxResultCount true, out strXml, out strError); if (nRet == -1) { goto ERROR1; } } else { strError = "strBarcode和strDisplayName均为空,无法进行检索"; goto ERROR1; } string strResultSetName = "opac_userinfo"; // sessioninfo.Channel. channel.Idle += new IdleEventHandler(channel_Idle); try { long lRet = //sessioninfo.Channel. channel.Search( null, strXml, strResultSetName, "", // strOutputStyle out strError); if (lRet == -1) { goto ERROR1; } // not found if (lRet == 0) { this.BrowseSearchResultControl1.Title = strText + " 没有发表过任何书评"; } else { this.BrowseSearchResultControl1.ResultSetName = strResultSetName; this.BrowseSearchResultControl1.ResultCount = (int)lRet; this.BrowseSearchResultControl1.StartIndex = 0; } return; } finally { //sessioninfo.Channel. channel.Idle -= new IdleEventHandler(channel_Idle); } } return; ERROR1: Response.Write(HttpUtility.HtmlEncode(strError)); Response.End(); } finally { #if NO temp_sessioninfo.CloseSession(); #endif app.ReturnChannel(channel); } }
// 创建一个馆藏地的限定结果集 void CreateOneLocationResultset(string strLocation) { string strError = ""; // 临时的SessionInfo对象 SessionInfo session = new SessionInfo(this); try { string strQueryXml = ""; // 构造检索实体库的 XML 检索式 // return: // -1 出错 // 0 没有发现任何实体库定义 // 1 成功 int nRet = this.BuildSearchItemQuery( "<全部>", strLocation + "/", -1, "馆藏地点", "left", "zh", "", // strSearchStyle, out strQueryXml, out strError); if (nRet == -1) goto ERROR1; if (nRet == 0) return; this._app_down.Token.ThrowIfCancellationRequested(); RmsChannel channel = session.Channels.GetChannel(this.WsUrl); if (channel == null) { strError = "get channel error"; goto ERROR1; } #if DETAIL_LOG this.WriteErrorLog("开始检索"); #endif long lHitCount = channel.DoSearch(strQueryXml, "default", "", // strOutputStyle, out strError); if (lHitCount == -1) goto ERROR1; if (lHitCount == 0) { // 没有命中任何记录,也要继续后面的处理 } this._app_down.Token.ThrowIfCancellationRequested(); DpResultSet resultset = new DpResultSet(true); try { if (lHitCount > 0) { nRet = GetResultset(channel, "default", resultset, out strError); if (nRet == -1) goto ERROR1; } // 写入 dp2kernel 成为永久结果集 nRet = UploadPermanentResultset(channel, strLocation, resultset, out strError); if (nRet == -1) goto ERROR1; } finally { resultset.Close(); } return; } finally { session.CloseSession(); session = null; } ERROR1: this.WriteErrorLog("馆藏地结果集创建出错: " + strError); return; }
// 探测一个结果集在 dp2kernel 一侧是否已经存在 bool LocationResultsetExists(string strLocation) { string strError = ""; // 临时的SessionInfo对象 SessionInfo session = new SessionInfo(this); try { this._app_down.Token.ThrowIfCancellationRequested(); RmsChannel channel = session.Channels.GetChannel(this.WsUrl); if (channel == null) return false; #if DETAIL_LOG this.WriteErrorLog("开始探测结果集 " + strLocation); #endif Record[] searchresults = null; // 获得检索结果的浏览格式 // 浅包装版本 long lHitCount = channel.DoGetSearchResult( "#" + strLocation, 0, 0, "id", "zh", null, out searchresults, out strError); if (lHitCount == -1) { if (channel.ErrorCode == ChannelErrorCode.NotFound) return false; return false; } return true; } finally { session.CloseSession(); session = null; } }
// 获得图书摘要信息 // 调用时不需要SessionInfo public int GetBiblioSummary(string strItemBarcode, string strConfirmItemRecPath, string strBiblioRecPathExclude, int nMaxLength, out string strBiblioRecPath, out string strSummary, out string strError) { strError = ""; strSummary = ""; strBiblioRecPath = ""; // 临时的SessionInfo对象 SessionInfo sessioninfo = new SessionInfo(this); // 模拟一个账户 Account account = new Account(); account.LoginName = "内部调用"; account.Password = ""; account.Rights = "getbibliosummary"; account.Type = ""; account.Barcode = ""; account.Name = "内部调用"; account.UserID = "内部调用"; account.RmsUserName = this.ManagerUserName; account.RmsPassword = this.ManagerPassword; sessioninfo.Account = account; try { RmsChannel channel = sessioninfo.Channels.GetChannel(this.WsUrl); if (channel == null) { strError = "get channel error"; return -1; } LibraryServerResult result = this.GetBiblioSummary( sessioninfo, channel, strItemBarcode, strConfirmItemRecPath, strBiblioRecPathExclude, out strBiblioRecPath, out strSummary); if (result.Value == -1) { strError = result.ErrorInfo; return -1; } else { if (nMaxLength != -1) { // 截断 if (strSummary.Length > nMaxLength) strSummary = strSummary.Substring(0, nMaxLength) + "..."; } } } finally { sessioninfo.CloseSession(); sessioninfo = null; } return 0; }
void submit_button_Click(object sender, EventArgs e) { string strError = ""; OpacApplication app = (OpacApplication)this.Page.Application["app"]; SessionInfo sessioninfo = (SessionInfo)this.Page.Session["sessioninfo"]; string strCreator = sessioninfo.UserID; // 先创建一条书目记录 TextBox biblio_title = (TextBox)this.FindControl("edit_biblio_title"); TextBox biblio_author = (TextBox)this.FindControl("edit_biblio_author"); TextBox biblio_publisher = (TextBox)this.FindControl("edit_biblio_publisher"); TextBox biblio_isbn = (TextBox)this.FindControl("edit_biblio_isbn"); TextBox biblio_price = (TextBox)this.FindControl("edit_biblio_price"); TextBox biblio_summary = (TextBox)this.FindControl("edit_biblio_summary"); // 检查必备字段 if (String.IsNullOrEmpty(biblio_title.Text) == true) { strError = "尚未输入书名/刊名"; goto ERROR1; } DropDownList store_dbname = (DropDownList)this.FindControl("store_dbname"); string strBiblioDbName = store_dbname.SelectedValue; if (String.IsNullOrEmpty(strBiblioDbName) == true) { strError = "尚未选定目标库"; goto ERROR1; } string strBiblioRecPath = ""; string strMarcSyntax = ""; string strMARC = ""; // 得到目标书目库的MARC格式 ItemDbCfg cfg = app.GetBiblioDbCfg(strBiblioDbName); if (cfg == null) { strError = "目标库 '" + strBiblioDbName + "' 不是系统定义的的书目库"; goto ERROR1; } strMarcSyntax = cfg.BiblioDbSyntax; int nRet = BuildBiblioRecord( strMarcSyntax, biblio_title.Text, biblio_author.Text, biblio_publisher.Text, biblio_isbn.Text, biblio_price.Text, biblio_summary.Text, strCreator, out strMARC, out strError); if (nRet == -1) { goto ERROR1; } // 保存 // 将MARC格式转换为XML格式 nRet = MarcUtil.Marc2Xml( strMARC, strMarcSyntax, out string strXml, out strError); if (nRet == -1) { goto ERROR1; } #if NO SessionInfo temp_sessioninfo = new SessionInfo(app); temp_sessioninfo.UserID = app.ManagerUserName; temp_sessioninfo.Password = app.ManagerPassword; temp_sessioninfo.IsReader = false; #endif string strOutputBiblioRecPath = ""; LibraryChannel channel = sessioninfo.GetChannel(true); try { strBiblioRecPath = strBiblioDbName + "/?"; long lRet = // temp_sessioninfo.Channel. channel.SetBiblioInfo( null, "new", strBiblioRecPath, "xml", strXml, null, "", out strOutputBiblioRecPath, out byte[] baOutputTimestamp, out strError); if (lRet == -1) { strError = "创建书目记录发生错误: " + strError; goto ERROR1; } } finally { #if NO temp_sessioninfo.CloseSession(); temp_sessioninfo = null; #endif sessioninfo.ReturnChannel(channel); } // 清除每个输入域的内容 biblio_title.Text = ""; biblio_author.Text = ""; biblio_publisher.Text = ""; biblio_isbn.Text = ""; biblio_summary.Text = ""; biblio_price.Text = ""; strBiblioRecPath = strOutputBiblioRecPath; CommentControl commentcontrol = (CommentControl)this.FindControl("commentcontrol"); // 创建评注记录 if (String.IsNullOrEmpty(commentcontrol.EditTitle) == false || String.IsNullOrEmpty(commentcontrol.EditContent) == false) { string strWarning = ""; commentcontrol.BiblioRecPath = strBiblioRecPath; nRet = commentcontrol.DoSubmit( out strWarning, out strError); if (nRet == -1) { goto ERROR1; } if (String.IsNullOrEmpty(strWarning) == false) { this.SetDebugInfo("warninginfo", strWarning); } } string strUrl = "./book.aspx?bibliorecpath=" + HttpUtility.UrlEncode(strBiblioRecPath); string strText = "新的荐购书目记录创建成功。点击此处可查看:<a href='" + strUrl + "' target='_blank'>" + strUrl + "</a>"; SetInfo(strText); this.SetDebugInfo("succeedinfo", strText); return; ERROR1: SetDebugInfo("errorinfo", strError); }
// 创建书目过滤结果集 // 书目过滤结果集的特点是,直接针对书目库进行检索,在 dp2kernel 一端就成为永久结果集 void CreateBiblioFilterResultset(string strQueryXml, string strResultsetName) { string strError = ""; // TODO: 要设法把临时的 Session 对象管理起来。在 Application down 的时候,主动对这些 session 的 Channels 执行 stop // 临时的 SessionInfo 对象 SessionInfo session = new SessionInfo(this); try { this._app_down.Token.ThrowIfCancellationRequested(); // RmsChannel channel = session.Channels.GetChannel(this.WsUrl); RmsChannel channel = _slowChannelList.GetChannel(session.Channels, this.WsUrl); if (channel == null) { strError = "get channel null error"; goto ERROR1; } try { #if DETAIL_LOG this.WriteErrorLog("开始检索"); #endif long lHitCount = channel.DoSearch(strQueryXml, "#~" + strResultsetName, "", // strOutputStyle, out strError); if (lHitCount == -1) { goto ERROR1; } if (lHitCount == 0) { // 没有命中任何记录,也要继续后面的处理 // 结果集为空,也要在 dp2kernel 端创建一个结果集对象 long lRet = channel.DoWriteRecords(null, new RecordBody[0], "createResultset,name:#" + strResultsetName + ",clear,permanent", out RecordBody[] results, out strError); if (lRet == -1) { goto ERROR1; } return; } this._app_down.Token.ThrowIfCancellationRequested(); // 最后一次执行改名、排序 { long lRet = channel.DoWriteRecords(null, null, "renameResultset,oldname:#~" + strResultsetName + ",newname:#" + strResultsetName + ",permanent,sort", out RecordBody[] results, out strError); if (lRet == -1) { goto ERROR1; } } return; } finally { _slowChannelList.ReturnChannel(session.Channels, channel); } } finally { session.CloseSession(); session = null; } ERROR1: this.WriteErrorLog("书目 '" + strResultsetName + "' 结果集创建出错: " + strError); }
// 创建一个馆藏地的限定结果集 void CreateOneLocationResultset(string strLocation) { string strError = ""; // TODO: 要设法把临时的 Session 对象管理起来。在 Application down 的时候,主动对这些 session 的 Channels 执行 stop // 临时的 SessionInfo 对象 SessionInfo session = new SessionInfo(this); try { // 构造检索实体库的 XML 检索式 // return: // -1 出错 // 0 没有发现任何实体库定义 // 1 成功 int nRet = this.BuildSearchItemQuery( "<全部>", strLocation + "/", -1, "馆藏地点", "left", "zh", "", // strSearchStyle, out string strQueryXml, out strError); if (nRet == -1) { goto ERROR1; } if (nRet == 0) { return; } this._app_down.Token.ThrowIfCancellationRequested(); // RmsChannel channel = session.Channels.GetChannel(this.WsUrl); RmsChannel channel = _slowChannelList.GetChannel(session.Channels, this.WsUrl); if (channel == null) { strError = "get channel null error"; goto ERROR1; } try { #if DETAIL_LOG this.WriteErrorLog("开始检索"); #endif long lHitCount = channel.DoSearch(strQueryXml, "default", "", // strOutputStyle, out strError); if (lHitCount == -1) { goto ERROR1; } if (lHitCount == 0) { // 没有命中任何记录,也要继续后面的处理 } this._app_down.Token.ThrowIfCancellationRequested(); DpResultSet resultset = new DpResultSet(true); try { if (lHitCount > 0) { nRet = GetResultset(channel, "default", resultset, out strError); if (nRet == -1) { goto ERROR1; } } // 写入 dp2kernel 成为永久结果集 nRet = UploadPermanentResultset(channel, strLocation, resultset, out strError); if (nRet == -1) { goto ERROR1; } } finally { resultset.Close(); } } finally { _slowChannelList.ReturnChannel(session.Channels, channel); } return; } finally { session.CloseSession(); session = null; } ERROR1: this.WriteErrorLog("馆藏地 '" + strLocation + "' 结果集创建出错: " + strError); return; }
// 重设密码 // parameters: // strParameters 参数字符串。如果 queryword 使用 NB: 形态,注意要这样使用 NB:姓名|,因为这是采用前方一致检索的,如果没有竖线部分,可能会匹配上不该命中的较长的名字 // strMessageTempate 消息文字模板。其中可以使用 %name% %barcode% %temppassword% %expiretime% %period% 等宏 // strMessage 返回拟发送给读者的消息文字 // return: // -2 读者的图书馆账户尚未注册手机号 // -1 出错 // 0 因为条件不具备功能没有成功执行 // 1 功能成功执行 public int ResetPassword( // string strLibraryCodeList, string strParameters, string strMessageTemplate, out string strMessage, out string strError) { strError = ""; strMessage = ""; MessageInterface external_interface = this.GetMessageInterface("sms"); Hashtable parameters = StringUtil.ParseParameters(strParameters, ',', '='); string strQueryWord = (string)parameters["queryword"]; string strPatronBarcodeParam = (string)parameters["barcode"]; string strNameParam = (string)parameters["name"]; string strTelParam = (string)parameters["tel"]; string strLibraryCodeList = (string)parameters["librarycode"]; // 控制检索读者记录的范围 int nMaxHitCount = 10; bool bReturnMessage = false; string strStyle = (string)parameters["style"]; if (StringUtil.IsInList("returnMessage", strStyle) == true) { // 直接给调用者返回拟发送到手机短信的内容。要求调用者具有特殊权限才行,要求在调用本函数前判断好。 bReturnMessage = true; } else { if (external_interface == null) { strError = "当前系统尚未配置短消息 (sms) 接口,无法进行重设密码的操作"; return -1; } } if (string.IsNullOrEmpty(strQueryWord) == true) { strError = "缺乏 queryword 参数"; return -1; } if (bReturnMessage == false && string.IsNullOrEmpty(strNameParam) == true) { strError = "缺乏 name 参数"; return -1; } if (string.IsNullOrEmpty(strTelParam) == true) { strError = "缺乏 tel 参数"; return -1; } // 判断电话号码是否为手机号码 if (strTelParam.Length != 11) { strError = "所提供的电话号码应该是 11 位的手机号码"; return 0; } // 临时的SessionInfo对象 SessionInfo sessioninfo = new SessionInfo(this); try { RmsChannel channel = sessioninfo.Channels.GetChannel(this.WsUrl); if (channel == null) { strError = "get channel error"; return -1; } List<KernelRecord> records = null; // 获得读者记录 // return: // -2 当前没有配置任何读者库,或者可以操作的读者库 // -1 error // 0 not found // 1 命中1条 // >1 命中多于1条 int nRet = this.GetReaderRecXmlForLogin( channel, strLibraryCodeList, strQueryWord, nMaxHitCount, "id,xml,timestamp", out records, out strError); if (nRet == -1 || nRet == -2) { strError = "以登录名 '" + strQueryWord + "' 检索读者记录出错: " + strError; return -1; } if (nRet == 0) { strError = "读者帐户 '" + strQueryWord + "' 不存在"; return 0; } #if NO if (nRet > 1) { strError = "登录名 '" + strLoginName + "' 所匹配的帐户多于一个"; return 0; } #endif List<KernelRecord> results = null; // 筛选读者记录 // return: // -2 尚未注册手机号 // -1 出错 // 0 完成筛选 nRet = FilterPatron(records, strNameParam, strPatronBarcodeParam, strTelParam, out results, out strError); if (nRet == -1) return -1; if (results.Count == 0) { if (nRet == -2) { strError = "读者帐户 '" + strQueryWord + "' " + strError; return -2; } strError = "符合条件的读者帐户 '" + strQueryWord + "' 不存在"; return 0; } XmlDocument output_dom = new XmlDocument(); output_dom.LoadXml("<root />"); foreach (KernelRecord record in results) { string strLibraryCode = ""; // 获得读者库的馆代码 // return: // -1 出错 // 0 成功 nRet = GetLibraryCode( record.RecPath, out strLibraryCode, out strError); if (nRet == -1) return -1; XmlDocument readerdom = null; nRet = LibraryApplication.LoadToDom(record.Xml, out readerdom, out strError); if (nRet == -1) { strError = "装载读者记录进入XML DOM时发生错误: " + strError; return -1; } // 观察 password 元素的 lastResetTime 属性,需在规定的时间长度以外才能再次进行重设 DateTime end; // 观察在 password 元素 tempPasswordExpire 属性中残留的失效期,必须在这个时间以后才能进行本次操作 // parameters: // now 当前时间。本地时间 // return: // -1 出错 // 0 已经过了失效期 // 1 还在失效期以内 nRet = CheckOldExpireTime(readerdom, this.Clock.Now, out end, out strError); if (nRet == -1) return -1; if (nRet == 1) { strError = "本次重设密码的操作距离上次操作间隔不足一小时,操作被拒绝。请在 " + end.ToShortTimeString() + " 以后再进行操作"; return 0; } string strBarcode = DomUtil.GetElementText(readerdom.DocumentElement, "barcode"); string strRefID = DomUtil.GetElementText(readerdom.DocumentElement, "refID"); string strName = DomUtil.GetElementText(readerdom.DocumentElement, "name"); // 重新设定一个密码 Random rnd = new Random(); string strReaderTempPassword = rnd.Next(1, 999999).ToString(); DateTime expire = this.Clock.Now + new TimeSpan(1, 0, 0); // 本地时间 string strExpireTime = DateTimeUtil.Rfc1123DateTimeStringEx(expire); if (bReturnMessage == true) { XmlElement node = output_dom.CreateElement("patron"); output_dom.DocumentElement.AppendChild(node); // 直接给调用者返回消息内容。消息内容中有临时密码,属于敏感信息,要求调用者具有特殊权限才行。 DomUtil.SetElementText(node, "tel", strTelParam); DomUtil.SetElementText(node, "barcode", strBarcode); DomUtil.SetElementText(node, "name", strName); DomUtil.SetElementText(node, "tempPassword", strReaderTempPassword); DomUtil.SetElementText(node, "expireTime", expire.ToLongTimeString()); DomUtil.SetElementText(node, "period", "一小时"); DomUtil.SetElementText(node, "refID", strRefID); // 在所提供的姓名或者电话号码命中不止一条读者记录的情形,调用者后面使用读者记录的 refID 来绑定特别重要。 } else { if (string.IsNullOrEmpty(strMessageTemplate) == true) strMessageTemplate = "%name% 您好!\n您的读者帐户(证条码号为 %barcode%)已设临时密码 %temppassword%,在 %period% 内登录会成为正式密码"; string strBody = strMessageTemplate.Replace("%barcode%", strBarcode) .Replace("%name%", strName) .Replace("%temppassword%", strReaderTempPassword) .Replace("%expiretime%", expire.ToLongTimeString()) .Replace("%period%", "一小时"); // string strBody = "读者(证条码号) " + strBarcode + " 的帐户密码已经被重设为 " + strReaderNewPassword + ""; // 向手机号码发送短信 { // 发送消息 try { // 发送一条消息 // parameters: // strPatronBarcode 读者证条码号 // strPatronXml 读者记录XML字符串。如果需要除证条码号以外的某些字段来确定消息发送地址,可以从XML记录中取 // strMessageText 消息文字 // strError [out]返回错误字符串 // return: // -1 发送失败 // 0 没有必要发送 // >=1 发送成功,返回实际发送的消息条数 nRet = external_interface.HostObj.SendMessage( strBarcode, readerdom.DocumentElement.OuterXml, strBody, strLibraryCode, out strError); } catch (Exception ex) { strError = external_interface.Type + " 类型的外部消息接口Assembly中SendMessage()函数抛出异常: " + ex.Message; nRet = -1; } if (nRet == -1) { strError = "向读者 '" + strBarcode + "' 发送" + external_interface.Type + " message时出错: " + strError; if (this.Statis != null) this.Statis.IncreaseEntryValue( strLibraryCode, "重设密码通知", external_interface.Type + " message 重设密码通知消息发送错误数", 1); this.WriteErrorLog(strError); return -1; } else { if (this.Statis != null) this.Statis.IncreaseEntryValue( strLibraryCode, "重设密码通知", external_interface.Type + " message 重设密码通知消息发送数", nRet); // 短信条数可能多于次数 if (this.Statis != null) this.Statis.IncreaseEntryValue(strLibraryCode, "重设密码通知", external_interface.Type + " message 重设密码通知人数", 1); } } } byte[] output_timestamp = null; nRet = ChangeReaderTempPassword( sessioninfo, record.RecPath, readerdom, strReaderTempPassword, strExpireTime, record.Timestamp, out output_timestamp, out strError); if (nRet == -1) return -1; // 此时短信已经发出,但临时密码并未修改成功 } if (StringUtil.IsInList("returnMessage", strStyle) == true) strMessage = output_dom.DocumentElement.OuterXml; } finally { sessioninfo.CloseSession(); sessioninfo = null; } if (bReturnMessage == false) strError = "临时密码已通过短信方式发送到手机 " + strTelParam + "。请按照手机短信提示进行操作"; return 1; }
public int LoadCfg( bool bReload, string strDataDir, string strHostDir, // 为了脚本编译时候获得dll目录 out string strError) { strError = ""; int nRet = 0; LibraryApplication app = this; // new CirculationApplication(); // this.m_lock.AcquireWriterLock(m_nLockTimeout); this.LockForWrite(); // 2016/10/16 try { // 装载配置文件的过程,只能消除以前的 StartError 挂起状态,其他状态是无法消除的 // 本函数过程也约定好,只进行 StartError 挂起,不做其他挂起 #if NO if (app.HangupReason == LibraryServer.HangupReason.StartingError) app.HangupReason = LibraryServer.HangupReason.None; #endif if (app.HangupList.Count > 0) { ClearHangup("StartingError"); } try { DateTime start = DateTime.Now; this.DataDir = strDataDir; this.HostDir = strHostDir; string strFileName = PathUtil.MergePath(strDataDir, "library.xml"); string strBinDir = strHostDir; // PathUtil.MergePath(strHostDir, "bin"); string strCfgDir = PathUtil.MergePath(strDataDir, "cfgs"); string strCfgMapDir = PathUtil.MergePath(strDataDir, "cfgsmap"); string strLogDir = PathUtil.MergePath(strDataDir, "log"); string strOperLogDir = PathUtil.MergePath(strDataDir, "operlog"); string strZhengyuanDir = PathUtil.MergePath(strDataDir, "zhengyuan"); string strDkywDir = PathUtil.MergePath(strDataDir, "dkyw"); string strPatronReplicationDir = PathUtil.MergePath(strDataDir, "patronreplication"); string strStatisDir = PathUtil.MergePath(strDataDir, "statis"); string strSessionDir = PathUtil.MergePath(strDataDir, "session"); string strColumnDir = PathUtil.MergePath(strDataDir, "column"); string strTempDir = PathUtil.MergePath(strDataDir, "temp"); app.m_strFileName = strFileName; app.CfgDir = strCfgDir; app.CfgMapDir = strCfgMapDir; PathUtil.CreateDirIfNeed(app.CfgMapDir); // 确保目录创建 // log app.LogDir = strLogDir; // 日志存储目录 PathUtil.CreateDirIfNeed(app.LogDir); // 确保目录创建 // zhengyuan 一卡通 app.ZhengyuanDir = strZhengyuanDir; PathUtil.CreateDirIfNeed(app.ZhengyuanDir); // 确保目录创建 // dkyw 一卡通 app.DkywDir = strDkywDir; PathUtil.CreateDirIfNeed(app.DkywDir); // 确保目录创建 // patron replication app.PatronReplicationDir = strPatronReplicationDir; PathUtil.CreateDirIfNeed(app.PatronReplicationDir); // 确保目录创建 // statis 统计文件 app.StatisDir = strStatisDir; PathUtil.CreateDirIfNeed(app.StatisDir); // 确保目录创建 // session临时文件 app.SessionDir = strSessionDir; PathUtil.CreateDirIfNeed(app.SessionDir); // 确保目录创建 if (bReload == false) CleanSessionDir(this.SessionDir); // 各种临时文件 app.TempDir = strTempDir; PathUtil.CreateDirIfNeed(app.TempDir); // 确保目录创建 if (bReload == false) { #if NO try { string strTempFileName = Path.GetTempFileName(); File.Delete(strTempFileName); string strTempDir1 = Path.GetDirectoryName(strTempFileName); long count = 0; long size = PathUtil.GetAllFileSize(strTempDir1, ref count); app.WriteErrorLog("系统临时文件目录 " + Path.GetTempPath() + " 内的全部临时文件尺寸为 " + size.ToString() + ", 文件个数为 " + count.ToString()); } catch { } #endif #if NO if (PathUtil.TryClearDir(app.TempDir) == false) app.WriteErrorLog("清除临时文件目录 " + app.TempDir + " 时出错"); #endif try { PathUtil.ClearDir(app.TempDir); } catch (Exception ex) { app.WriteErrorLog("清除临时文件目录 " + app.TempDir + " 时出现异常: " + ExceptionUtil.GetDebugText(ex)); } } this.InitialLoginCache(); this.InitialBiblioSummaryCache(); if (bReload == false) { if (app.HasAppBeenKilled() == true) { app.WriteErrorLog("*** 发现library application先前曾被意外终止 ***"); } } this.WriteErrorLog("*********"); if (bReload == true) app.WriteErrorLog("library (" + Version + ") application 开始重新装载 " + this.m_strFileName); else app.WriteErrorLog("library (" + Version + ") application 开始初始化。"); // #if NO if (bReload == false) { app.m_strWebuiFileName = PathUtil.MergePath(strDataDir, "webui.xml"); // string strWebUiFileName = PathUtil.MergePath(strDataDir, "webui.xml"); nRet = LoadWebuiCfgDom(out strError); if (nRet == -1) { // strError = "装载配置文件-- '" + strWebUiFileName + "'时发生错误,原因:" + ex.Message; app.WriteErrorLog(strError); goto ERROR1; } } #endif #if LOG_INFO app.WriteErrorLog("INFO: 开始装载 " + strFileName + " 到 XMLDOM"); #endif // XmlDocument dom = new XmlDocument(); try { dom.Load(strFileName); } catch (FileNotFoundException) { strError = "file '" + strFileName + "' not found ..."; goto ERROR1; } catch (Exception ex) { strError = "装载配置文件-- '" + strFileName + "' 时发生错误,错误类型:" + ex.GetType().ToString() + ",原因:" + ex.Message; app.WriteErrorLog(strError); // throw ex; goto ERROR1; } app.LibraryCfgDom = dom; #if LOG_INFO app.WriteErrorLog("INFO: 初始化内存参数"); #endif // *** 进入内存的参数开始 // 注意修改了这些参数的结构后,必须相应修改Save()函数的相关片断 // 2011/1/7 bool bValue = false; DomUtil.GetBooleanParam(app.LibraryCfgDom.DocumentElement, "debugMode", false, out bValue, out strError); this.DebugMode = bValue; WriteErrorLog("是否为调试态: " + this.DebugMode); // 2013/4/10 // uid this.UID = app.LibraryCfgDom.DocumentElement.GetAttribute("uid"); if (string.IsNullOrEmpty(this.UID) == true) { this.UID = Guid.NewGuid().ToString(); this.Changed = true; WriteErrorLog("自动为 library.xml 添加 uid '" + this.UID + "'"); } // 内核参数 // 元素<rmsserver> // 属性url/username/password XmlElement node = dom.DocumentElement.SelectSingleNode("rmsserver") as XmlElement; if (node != null) { app.WsUrl = DomUtil.GetAttr(node, "url"); if (app.WsUrl.IndexOf(".asmx") != -1) { strError = "装载配置文件 '" + strFileName + "' 过程中发生错误: <rmsserver>元素url属性中的 dp2内核 服务器URL '" + app.WsUrl + "' 不正确,应当为非.asmx形态的地址..."; app.WriteErrorLog(strError); goto ERROR1; } app.ManagerUserName = DomUtil.GetAttr(node, "username"); try { app.ManagerPassword = Cryptography.Decrypt( DomUtil.GetAttr(node, "password"), EncryptKey); } catch { strError = "<rmsserver>元素password属性中的密码设置不正确"; // throw new Exception(); goto ERROR1; } CfgsMap = new CfgsMap(this.CfgMapDir/*, this.WsUrl*/); CfgsMap.Clear(); } else { app.WsUrl = ""; app.ManagerUserName = ""; app.ManagerPassword = ""; } // 元素 <mongoDB> // 属性 connectionString / instancePrefix node = dom.DocumentElement.SelectSingleNode("mongoDB") as XmlElement; if (node != null) { this.MongoDbConnStr = DomUtil.GetAttr(node, "connectionString"); this.MongoDbInstancePrefix = node.GetAttribute("instancePrefix"); } else { this.MongoDbConnStr = ""; this.MongoDbInstancePrefix = ""; this.AccessLogDatabase = new AccessLogDatabase(); this.HitCountDatabase = new HitCountDatabase(); this.ChargingOperDatabase = new ChargingOperDatabase(); } // 预约到书 // 元素<arrived> // 属性dbname/reserveTimeSpan/outofReservationThreshold/canReserveOnshelf/notifyTypes node = dom.DocumentElement.SelectSingleNode("arrived") as XmlElement; if (node != null) { app.ArrivedDbName = DomUtil.GetAttr(node, "dbname"); app.ArrivedReserveTimeSpan = DomUtil.GetAttr(node, "reserveTimeSpan"); int nValue = 0; nRet = DomUtil.GetIntegerParam(node, "outofReservationThreshold", 10, out nValue, out strError); if (nRet == -1) { app.WriteErrorLog("元素<arrived>属性outofReservationThreshold读入时发生错误: " + strError); goto ERROR1; } app.OutofReservationThreshold = nValue; bValue = false; nRet = DomUtil.GetBooleanParam(node, "canReserveOnshelf", true, out bValue, out strError); if (nRet == -1) { app.WriteErrorLog("元素<arrived>属性canReserveOnshelf读入时发生错误: " + strError); goto ERROR1; } app.CanReserveOnshelf = bValue; // 没有这个属性的时候,默认 "dpmail,email",否则依其值,哪怕为 "" if (node.GetAttributeNode("notifyTypes") == null) app.ArrivedNotifyTypes = "dpmail,email"; else app.ArrivedNotifyTypes = node.GetAttribute("notifyTypes"); } else { app.ArrivedDbName = ""; app.ArrivedReserveTimeSpan = ""; app.OutofReservationThreshold = 10; app.CanReserveOnshelf = true; app.ArrivedNotifyTypes = "dpmail,email"; } // 2013/9/24 // 借期提醒通知定义 // 元素 <monitors/readersMonitor> // 属性 notifyDef node = dom.DocumentElement.SelectSingleNode("monitors/readersMonitor") as XmlElement; if (node != null) { // 提醒通知的定义 app.NotifyDef = DomUtil.GetAttr(node, "notifyDef"); } else { app.NotifyDef = ""; } // <login> node = dom.DocumentElement.SelectSingleNode("login") as XmlElement; if (node != null) { this.CheckClientVersion = DomUtil.GetBooleanParam(node, "checkClientVersion", false); } else { this.CheckClientVersion = false; } // <circulation> node = dom.DocumentElement.SelectSingleNode("circulation") as XmlElement; if (node != null) { { string strList = DomUtil.GetAttr(node, "patronAdditionalFroms"); if (string.IsNullOrEmpty(strList) == false) this.PatronAdditionalFroms = StringUtil.SplitList(strList); else this.PatronAdditionalFroms = new List<string>(); } { string strList = DomUtil.GetAttr(node, "patronAdditionalFields"); if (string.IsNullOrEmpty(strList) == false) this.PatronAdditionalFields = StringUtil.SplitList(strList); else this.PatronAdditionalFields = new List<string>(); } { string strList = DomUtil.GetAttr(node, "patronReplicationFields"); if (string.IsNullOrEmpty(strList) == false) this.PatronReplicationFields = StringUtil.SplitList(strList); else this.PatronReplicationFields = StringUtil.SplitList(strList); } int v = 0; nRet = DomUtil.GetIntegerParam(node, "maxPatronHistoryItems", 10, // 100, out v, out strError); if (nRet == -1) app.WriteErrorLog(strError); this.MaxPatronHistoryItems = v; nRet = DomUtil.GetIntegerParam(node, "maxItemHistoryItems", 10, // 100, out v, out strError); if (nRet == -1) app.WriteErrorLog(strError); this.MaxItemHistoryItems = v; this.VerifyBarcode = DomUtil.GetBooleanParam(node, "verifyBarcode", false); this.AcceptBlankItemBarcode = DomUtil.GetBooleanParam(node, "acceptBlankItemBarcode", true); this.AcceptBlankReaderBarcode = DomUtil.GetBooleanParam(node, "acceptBlankReaderBarcode", true); this.VerifyBookType = DomUtil.GetBooleanParam(node, "verifyBookType", false); this.VerifyReaderType = DomUtil.GetBooleanParam(node, "verifyReaderType", false); this.BorrowCheckOverdue = DomUtil.GetBooleanParam(node, "borrowCheckOverdue", true); this.CirculationNotifyTypes = node.GetAttribute("notifyTypes"); } else { this.PatronAdditionalFroms = new List<string>(); this.PatronAdditionalFields = new List<string>(); this.MaxPatronHistoryItems = DEFAULT_MAXPATRONHITSTORYITEMS; this.MaxItemHistoryItems = DEFAULT_MAXITEMHISTORYITEMS; this.VerifyBarcode = false; this.AcceptBlankItemBarcode = true; this.AcceptBlankReaderBarcode = true; this.VerifyBookType = false; this.VerifyReaderType = false; this.BorrowCheckOverdue = true; this.CirculationNotifyTypes = ""; } // <channel> node = dom.DocumentElement.SelectSingleNode("channel") as XmlElement; if (node != null) { int v = 0; nRet = DomUtil.GetIntegerParam(node, "maxChannelsPerIP", 50, out v, out strError); if (nRet == -1) app.WriteErrorLog(strError); if (this.SessionTable != null) this.SessionTable.MaxSessionsPerIp = v; nRet = DomUtil.GetIntegerParam(node, "maxChannelsLocalhost", 150, out v, out strError); if (nRet == -1) app.WriteErrorLog(strError); if (this.SessionTable != null) this.SessionTable.MaxSessionsLocalHost = v; } else { if (this.SessionTable != null) { this.SessionTable.MaxSessionsPerIp = 50; this.SessionTable.MaxSessionsLocalHost = 150; } } // <cataloging> node = dom.DocumentElement.SelectSingleNode("cataloging") as XmlElement; if (node != null) { // 是否允许删除带有下级记录的书目记录 bValue = true; nRet = DomUtil.GetBooleanParam(node, "deleteBiblioSubRecords", true, out bValue, out strError); if (nRet == -1) app.WriteErrorLog(strError); this.DeleteBiblioSubRecords = bValue; } else { this.DeleteBiblioSubRecords = true; } // 入馆登记 // 元素<passgate> // 属性writeOperLog node = dom.DocumentElement.SelectSingleNode("passgate") as XmlElement; if (node != null) { string strWriteOperLog = DomUtil.GetAttr(node, "writeOperLog"); this.PassgateWriteToOperLog = ToBoolean(strWriteOperLog, true); } else { this.PassgateWriteToOperLog = true; } // 对象管理 // 元素<object> // 属性 writeOperLog node = dom.DocumentElement.SelectSingleNode("object") as XmlElement; if (node != null) { string strWriteOperLog = DomUtil.GetAttr(node, "writeGetResOperLog"); this.GetObjectWriteToOperLog = ToBoolean(strWriteOperLog, false); } else { this.GetObjectWriteToOperLog = false; } // 2015/11/26 // 日志特性 // 元素<log> node = dom.DocumentElement.SelectSingleNode("log") as XmlElement; if (node != null) { int nValue = 0; DomUtil.GetIntegerParam(node, "accessLogMaxCountPerDay", 10000, out nValue, out strError); this.AccessLogMaxCountPerDay = nValue; } else { this.AccessLogMaxCountPerDay = 10000; } // 消息 // 元素<message> // 属性dbname/reserveTimeSpan/defaultQueue node = dom.DocumentElement.SelectSingleNode("message") as XmlElement; if (node != null) { this.MessageDbName = DomUtil.GetAttr(node, "dbname"); this.MessageReserveTimeSpan = DomUtil.GetAttr(node, "reserveTimeSpan"); // 2016/4/10 this.OutgoingQueue = DomUtil.GetAttr(node, "defaultQueue"); // 2010/12/31 add if (String.IsNullOrEmpty(this.MessageReserveTimeSpan) == true) this.MessageReserveTimeSpan = "365day"; } else { this.MessageDbName = ""; this.MessageReserveTimeSpan = "365day"; this.OutgoingQueue = ""; } // OPAC服务器 // 元素<opacServer> // 属性url node = dom.DocumentElement.SelectSingleNode("opacServer") as XmlElement; if (node != null) { app.OpacServerUrl = DomUtil.GetAttr(node, "url"); } else { app.OpacServerUrl = ""; } // 违约金 // 元素<amerce> // 属性dbname/overdueStyle node = dom.DocumentElement.SelectSingleNode("amerce") as XmlElement; if (node != null) { app.AmerceDbName = DomUtil.GetAttr(node, "dbname"); app.OverdueStyle = DomUtil.GetAttr(node, "overdueStyle"); } else { app.AmerceDbName = ""; app.OverdueStyle = ""; } // 发票 // 元素<invoice> // 属性dbname node = dom.DocumentElement.SelectSingleNode("invoice") as XmlElement; if (node != null) { app.InvoiceDbName = DomUtil.GetAttr(node, "dbname"); } else { app.InvoiceDbName = ""; } // *** 进入内存的参数结束 // bin dir app.BinDir = strBinDir; nRet = 0; { #if LOG_INFO app.WriteErrorLog("INFO: LoadReaderDbGroupParam"); #endif // <readerdbgroup> app.LoadReaderDbGroupParam(dom); #if LOG_INFO app.WriteErrorLog("INFO: LoadItemDbGroupParam"); #endif // <itemdbgroup> nRet = app.LoadItemDbGroupParam(dom, out strError); if (nRet == -1) { app.WriteErrorLog(strError); goto ERROR1; } // 临时的SessionInfo对象 SessionInfo session = new SessionInfo(this); try { #if LOG_INFO app.WriteErrorLog("INFO: InitialKdbs"); #endif // 初始化kdbs nRet = InitialKdbs(session.Channels, out strError); if (nRet == -1) { app.WriteErrorLog("ERR001 首次初始化kdbs失败: " + strError); // DefaultThread可以重试初始化 // session.Close(); // goto ERROR1; } else { #if LOG_INFO app.WriteErrorLog("INFO: CheckKernelVersion"); #endif // 检查 dpKernel 版本号 nRet = CheckKernelVersion(session.Channels, out strError); if (nRet == -1) goto ERROR1; } #if LOG_INFO app.WriteErrorLog("INFO: InitialVdbs"); #endif // 2008/6/6 重新初始化虚拟库定义 // 这样,其他地方调用的InitialVdbs()就可以去除了 // TODO: 为了提高运行速度,可以优化为,只有当<virtualDatabases>元素下的内容有改变时,才重新进行这个初始化 this.vdbs = null; nRet = app.InitialVdbs(session.Channels, out strError); if (nRet == -1) { app.WriteErrorLog("ERR002 首次初始化vdbs失败: " + strError); } } finally { session.CloseSession(); session = null; #if LOG_INFO app.WriteErrorLog("INFO: 临时 session 使用完毕"); #endif } } // 时钟 string strClock = DomUtil.GetElementText(dom.DocumentElement, "clock"); try { this.Clock.Delta = Convert.ToInt64(strClock); } catch { // TODO: 写入错误日志 } // *** 初始化操作日志环境 if (bReload == false) // 2014/4/2 { // this.OperLogDir = strOperLogDir; // 2006/12/7 #if LOG_INFO app.WriteErrorLog("INFO: OperLog.Initial"); #endif // oper log nRet = this.OperLog.Initial(this, strOperLogDir, out strError); if (nRet == -1) { app.WriteErrorLog(strError); goto ERROR1; } } // *** 初始化统计对象 // if (bReload == false) // 2014/4/2 { #if LOG_INFO app.WriteErrorLog("INFO: Statis.Initial"); #endif this.Statis = new Statis(); nRet = this.Statis.Initial(this, out strError); if (nRet == -1) { app.WriteErrorLog(strError); goto ERROR1; } } #if LOG_INFO app.WriteErrorLog("INFO: InitialLibraryHostAssembly"); #endif // 初始化LibraryHostAssembly对象 // 必须在ReadersMonitor以前启动。否则其中用到脚本代码时会出错。2007/10/10 changed // return: // -1 出错 // 0 成功 nRet = this.InitialLibraryHostAssembly(out strError); if (nRet == -1) { app.WriteErrorLog(strError); goto ERROR1; } #if LOG_INFO app.WriteErrorLog("INFO: InitialExternalMessageInterfaces"); #endif // 初始化扩展消息接口 nRet = app.InitialExternalMessageInterfaces( out strError); if (nRet == -1) { strError = "初始化扩展的消息接口时出错: " + strError; app.WriteErrorLog(strError); // goto ERROR1; } // 创建 MSMQ 消息队列 #if LOG_INFO app.WriteErrorLog("INFO: Message Queue"); #endif /// app.InitialMsmq(); // 初始化 mongodb 相关对象 nRet = InitialMongoDatabases(out strError); if (nRet == -1) { // app.HangupReason = LibraryServer.HangupReason.StartingError; app.AddHangup("ERR002"); app.WriteErrorLog("ERR002 首次初始化 mongodb database 失败: " + strError); } #if LOG_INFO app.WriteErrorLog("INFO: 准备下属数据库对象"); #endif // this.IssueItemDatabase = new IssueItemDatabase(this); this.OrderItemDatabase = new OrderItemDatabase(this); this.CommentItemDatabase = new CommentItemDatabase(this); #if LOG_INFO app.WriteErrorLog("INFO: MessageCenter"); #endif // this.MessageCenter = new MessageCenter(); this.MessageCenter.ServerUrl = this.WsUrl; this.MessageCenter.MessageDbName = this.MessageDbName; this.MessageCenter.VerifyAccount -= new VerifyAccountEventHandler(MessageCenter_VerifyAccount); // 2008/6/6 this.MessageCenter.VerifyAccount += new VerifyAccountEventHandler(MessageCenter_VerifyAccount); if (this.BatchTasks == null) this.BatchTasks = new BatchTaskCollection(); // Close() 的时候会设置为 null。因此这里要准备重新 new // 启动批处理任务 // TODO: 这一段考虑分离到一个函数中 if (bReload == false) { string strBreakPoint = ""; #if LOG_INFO app.WriteErrorLog("INFO: DefaultThread"); #endif // 启动DefaultThread try { DefaultThread defaultThread = new DefaultThread(this, null); this.BatchTasks.Add(defaultThread); defaultThread.StartWorkerThread(); this.defaultManagerThread = defaultThread; } catch (Exception ex) { app.WriteErrorLog("启动后台任务 DefaultThread 时出错:" + ex.Message); goto ERROR1; } #if LOG_INFO app.WriteErrorLog("INFO: OperLogThread"); #endif // 启动 OperLogThread try { OperLogThread thread = new OperLogThread(this, null); this.BatchTasks.Add(thread); thread.StartWorkerThread(); this.operLogThread = thread; } catch (Exception ex) { app.WriteErrorLog("启动后台任务 OperLogThread 时出错:" + ex.Message); goto ERROR1; } #if LOG_INFO app.WriteErrorLog("INFO: ArriveMonitor"); #endif // 启动ArriveMonitor try { ArriveMonitor arriveMonitor = new ArriveMonitor(this, null); this.BatchTasks.Add(arriveMonitor); arriveMonitor.StartWorkerThread(); } catch (Exception ex) { app.WriteErrorLog("启动批处理任务ArriveMonitor时出错:" + ex.Message); goto ERROR1; } #if LOG_INFO app.WriteErrorLog("INFO: ReadersMonitor"); #endif // 启动ReadersMonitor try { ReadersMonitor readersMonitor = new ReadersMonitor(this, null); this.BatchTasks.Add(readersMonitor); readersMonitor.StartWorkerThread(); } catch (Exception ex) { app.WriteErrorLog("启动批处理任务ReadersMonitor时出错:" + ex.Message); goto ERROR1; } #if LOG_INFO app.WriteErrorLog("INFO: MessageMonitor"); #endif // 启动MessageMonitor try { MessageMonitor messageMonitor = new MessageMonitor(this, null); this.BatchTasks.Add(messageMonitor); // 从断点记忆文件中读出信息 // return: // -1 error // 0 file not found // 1 found nRet = ReadBatchTaskBreakPointFile(messageMonitor.DefaultName, out strBreakPoint, out strError); if (nRet == -1) { app.WriteErrorLog("ReadBatchTaskBreakPointFile时出错:" + strError); } if (messageMonitor.StartInfo == null) messageMonitor.StartInfo = new BatchTaskStartInfo(); // 按照缺省值来 // 如果需要从断点启动 if (nRet == 1) messageMonitor.StartInfo.Start = "!breakpoint"; //strBreakPoint; messageMonitor.ClearProgressFile(); // 清除进度文件内容 messageMonitor.StartWorkerThread(); } catch (Exception ex) { app.WriteErrorLog("启动批处理任务MessageMonitor时出错:" + ex.Message); goto ERROR1; } // 启动DkywReplication // <dkyw> node = this.LibraryCfgDom.DocumentElement.SelectSingleNode("dkyw") as XmlElement; if (node != null) { #if LOG_INFO app.WriteErrorLog("INFO: DkywReplication"); #endif try { DkywReplication dkyw = new DkywReplication(this, null); this.BatchTasks.Add(dkyw); /* // 从断点记忆文件中读出信息 // return: // -1 error // 0 file not found // 1 found nRet = ReadBatchTaskBreakPointFile(dkyw.DefaultName, out strBreakPoint, out strError); if (nRet == -1) { app.WriteErrorLog("ReadBatchTaskBreakPointFile时出错:" + strError); } * */ bool bLoop = false; string strLastNumber = ""; // return: // -1 出错 // 0 没有找到断点信息 // 1 找到了断点信息 nRet = dkyw.ReadLastNumber( out bLoop, out strLastNumber, out strError); if (nRet == -1) { app.WriteErrorLog("ReadLastNumber时出错:" + strError); } if (dkyw.StartInfo == null) dkyw.StartInfo = new BatchTaskStartInfo(); // 按照缺省值来 if (bLoop == true) { // 需要从断点启动 if (nRet == 1) dkyw.StartInfo.Start = "!breakpoint"; //strBreakPoint; dkyw.ClearProgressFile(); // 清除进度文件内容 dkyw.StartWorkerThread(); } } catch (Exception ex) { app.WriteErrorLog("启动批处理任务DkywReplication时出错:" + ex.Message); goto ERROR1; } } // 启动PatronReplication // <patronReplication> // 读者库数据同步 批处理任务 // 从卡中心同步读者数据 node = this.LibraryCfgDom.DocumentElement.SelectSingleNode("patronReplication") as XmlElement; if (node != null) { #if LOG_INFO app.WriteErrorLog("INFO: PatronReplication"); #endif try { PatronReplication patron_rep = new PatronReplication(this, null); this.BatchTasks.Add(patron_rep); patron_rep.StartWorkerThread(); } catch (Exception ex) { app.WriteErrorLog("启动批处理任务PatronReplication时出错:" + ex.Message); goto ERROR1; } } // 启动 LibraryReplication #if LOG_INFO app.WriteErrorLog("INFO: LibraryReplication ReadBatchTaskBreakPointFile"); #endif // 从断点记忆文件中读出信息 // return: // -1 error // 0 file not found // 1 found nRet = ReadBatchTaskBreakPointFile("dp2Library 同步", out strBreakPoint, out strError); if (nRet == -1) { app.WriteErrorLog("ReadBatchTaskBreakPointFile() 时出错:" + strError); } // 如果nRet == 0,表示没有断点文件存在,也就不必自动启动这个任务 // strBreakPoint 并未被使用。而是断点文件是否存在,这一信息有价值。 if (nRet == 1) { #if LOG_INFO app.WriteErrorLog("INFO: LibraryReplication"); #endif try { // 从断点文件中取出断点字符串 // 断点字符串格式:序号.偏移量@日志文件名 // 或者:序号@日志文件名 // 获得断点信息的整个过程的代码,是否适宜归入TraceDTLP类? // 如果成熟,可以归纳作为BatchTask基类的一个特性。 LibraryReplication replication = new LibraryReplication(this, null); this.BatchTasks.Add(replication); if (replication.StartInfo == null) replication.StartInfo = new BatchTaskStartInfo(); // 按照缺省值来 replication.StartInfo.Start = "date=continue"; // 从断点开始做 replication.ClearProgressFile(); // 清除进度文件内容 replication.StartWorkerThread(); } catch (Exception ex) { app.WriteErrorLog("启动批处理任务时出错:" + ex.Message); goto ERROR1; } } // 启动 RebuildKeys #if LOG_INFO app.WriteErrorLog("INFO: RebuildKeys ReadBatchTaskBreakPointFile"); #endif // 从断点记忆文件中读出信息 // return: // -1 error // 0 file not found // 1 found nRet = ReadBatchTaskBreakPointFile("重建检索点", out strBreakPoint, out strError); if (nRet == -1) { app.WriteErrorLog("ReadBatchTaskBreakPointFile() 时出错:" + strError); } // 如果nRet == 0,表示没有断点文件存在,也就不必自动启动这个任务 // strBreakPoint 并未被使用。而是断点文件是否存在,这一信息有价值。 if (nRet == 1) { #if LOG_INFO app.WriteErrorLog("INFO: RebuildKeys"); #endif try { // 从断点文件中取出断点字符串 RebuildKeys replication = new RebuildKeys(this, null); this.BatchTasks.Add(replication); if (replication.StartInfo == null) replication.StartInfo = new BatchTaskStartInfo(); // 按照缺省值来 replication.StartInfo.Start = "dbnamelist=continue"; // 从断点开始做 replication.ClearProgressFile(); // 清除进度文件内容 replication.StartWorkerThread(); } catch (Exception ex) { app.WriteErrorLog("启动批处理任务时出错:" + ex.Message); goto ERROR1; } } } // 公共查询最大命中数 { XmlNode nodeTemp = this.LibraryCfgDom.DocumentElement.SelectSingleNode("//virtualDatabases"); if (nodeTemp != null) { try { string strMaxCount = DomUtil.GetAttr(nodeTemp, "searchMaxResultCount"); if (String.IsNullOrEmpty(strMaxCount) == false) this.SearchMaxResultCount = Convert.ToInt32(strMaxCount); } catch { } } } #if NO if (bReload == false) { PathUtil.CreateDirIfNeed(strColumnDir); // 确保目录创建 nRet = LoadCommentColumn( PathUtil.MergePath(strColumnDir, "comment"), out strError); if (nRet == -1) { app.WriteErrorLog("装载栏目存储时出错: " + strError); } } #endif // 升级library.xml文件版本 if (bReload == false) { #if LOG_INFO app.WriteErrorLog("INFO: UpgradeLibraryXml"); #endif nRet = this.UpgradeLibraryXml(out strError); if (nRet == -1) { app.WriteErrorLog("升级library.xml时出错:" + strError); } } if (bReload == true) app.WriteErrorLog("library application结束重新装载 " + this.m_strFileName); else { TimeSpan delta = DateTime.Now - start; app.WriteErrorLog("library application成功初始化。初始化操作耗费时间 " + delta.TotalSeconds.ToString() + " 秒"); // 写入down机检测文件 app.WriteAppDownDetectFile("library application成功初始化。"); if (this.watcher == null) { #if LOG_INFO app.WriteErrorLog("INFO: BeginWatcher"); #endif BeginWatcher(); #if LOG_INFO app.WriteErrorLog("INFO: End BeginWatcher"); #endif } #if NO if (this.virtual_watcher == null) BeginVirtualDirWatcher(); #endif } if (this.MaxClients != 255) // 255 通道情况下不再检查版本失效日期 2016/11/3 { DateTime expire = new DateTime(2017, 3, 1); // 上一个版本是 2016/11/1 if (DateTime.Now > expire) { if (this.MaxClients == 255) { this.WriteErrorLog("*** 当前 dp2library 版本已于 " + expire.ToLongDateString() + " 失效。请系统管理员注意主动升级 dp2library"); } else { // 通知系统挂起 // this.HangupReason = HangupReason.Expire; app.AddHangup("Expire"); this.WriteErrorLog("*** 当前 dp2library 版本因为长期没有升级,已经失效。系统被挂起。请立即升级 dp2library 到最新版本"); } } } else this.WriteErrorLog("*** 特殊版本不检查失效日期。请系统管理员注意每隔半年主动升级一次 dp2library"); // 2013/4/10 if (this.Changed == true) this.ActivateManagerThread(); } catch (Exception ex) { strError = "LoadCfg() 抛出异常: " + ExceptionUtil.GetDebugText(ex); goto ERROR1; } return 0; } finally { // this.m_lock.ReleaseWriterLock(); this.UnlockForWrite(); } // 2008/10/13 ERROR1: if (bReload == false) { if (this.watcher == null) { #if LOG_INFO app.WriteErrorLog("INFO: BeginWatcher"); #endif BeginWatcher(); #if LOG_INFO app.WriteErrorLog("INFO: End BeginWatcher"); #endif } #if NO if (this.virtual_watcher == null) BeginVirtualDirWatcher(); #endif } if (bReload == true) app.WriteErrorLog("library application重新装载 " + this.m_strFileName + " 的过程发生严重错误 [" + strError + "],服务处于残缺状态,请及时排除故障后重新启动"); else { // app.HangupReason = LibraryServer.HangupReason.StartingError; app.AddHangup("StartingError"); app.WriteErrorLog("library application初始化过程发生严重错误 [" + strError + "],当前此服务处于残缺状态,请及时排除故障后重新启动"); } return -1; }