Exemplo n.º 1
0
        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;
        }
Exemplo n.º 2
0
        // 按照命令启动一个批处理任务(不是自动启动)
        // return:
        //      -1  出错
        //      0   启动成功
        //      1   调用前任务已经处于执行状态,本次调用激活了这个任务
        public int StartBatchTask(string strName,
            BatchTaskInfo param,
            out BatchTaskInfo info,
            out string strError)
        {
            strError = "";
            info = null;

            if (strName == "!continue")
            {
                this.PauseBatchTask = false;

                // 2013/11/23
                foreach (BatchTask current_task in this.BatchTasks)
                {
                    current_task.Activate();
                }

                info = GetTaskInfo("全部批处理任务已经解除暂停");
                return 1;
            }

            // 2007/12/18
            if (this.HangupReason == HangupReason.LogRecover)
            {
                strError = "当前系统正处在LogRecover挂起状态,无法启动新的批处理任务";
                return -1;
            }

            // 2012/2/4
            if (this.PauseBatchTask == true)
            {
                strError = "当前所有批处理任务均处在暂停状态,无法启动新的批处理任务";
                return -1;
            }

            BatchTask task = this.BatchTasks.GetBatchTask(strName);

            // 创建新的任务
            if (task == null)
            {
                if (strName == "预约到书管理")
                    task = new ArriveMonitor(this, strName);
                else if (strName == "日志恢复")
                    task = new OperLogRecover(this, strName);
                else if (strName == "dp2Library 同步")
                    task = new LibraryReplication(this, strName);
                else if (strName == "重建检索点")
                    task = new RebuildKeys(this, strName);
                /*
            else if (strName == "跟踪DTLP数据库")
                task = new TraceDTLP(this, strName);
                 * */
                else if (strName == "正元一卡通读者信息同步")
                    task = new ZhengyuanReplication(this, strName);
                else if (strName == "迪科远望一卡通读者信息同步")
                    task = new DkywReplication(this, strName);
                else if (strName == "读者信息同步")
                    task = new PatronReplication(this, strName);
                else if (strName == "超期通知")
                    task = new ReadersMonitor(this, strName);
                else if (strName == "消息监控")
                    task = new MessageMonitor(this, strName);
                else
                {
                    strError = "系统不能识别任务名 '" + strName + "'";
                    return -1;
                }

                try
                {
                    this.BatchTasks.Add(task);
                }
                catch (Exception ex)
                {
                    strError = ex.Message;
                    return -1;
                }
            }
            else
            {
                bool bOldStoppedValue = task.Stopped;


                if (bOldStoppedValue == false)
                {
                    if (strName == "重建检索点")
                    {
                        task.StartInfos.Add(param.StartInfo);

                        task.AppendResultText("新任务已加入等待队列:\r\n---\r\n" + RebuildKeys.GetSummary(param.StartInfo) + "\r\n---\r\n\r\n");
                    }

                    else
                    {
                        // 尽量采用前端发来的参数进行运行
                        task.StartInfo = param.StartInfo;
                    }

                    // 激活 2007/10/10
                    task.eventActive.Set();
                    task.ManualStart = true;    // 表示为命令启动

                    strError = "任务 " + task.Name + " 已经在运行中,不能重复启动。本次操作激活了这个任务。";
                    return 1;
                }
            }

            // 执行日志恢复任务前,需要先中断正在执行的其他任何任务
            // TODO: 日志恢复 任务结束后,原先中断的那些任务并不会自动去启动。需要系统管理员手动重新启动一次Application
            if (strName == "日志恢复")
            {
                StopAllBatchTasks();
            }

            task.ManualStart = true;    // 表示为命令启动
            task.StartInfo = param.StartInfo;
            task.ClearProgressFile();   // 清除进度文件内容
            task.StartWorkerThread();

            /*
            // 激活 2007/10/10
            task.eventActive.Set();
             * */

            info = task.GetCurrentInfo(param.ResultOffset,
                param.MaxResultBytes);

            return 0;
        }